ЧТМ:Расширения/BatchTools/1.45/0.3: различия между версиями

Нет описания правки
Нет описания правки
Строка 1: Строка 1:
<span class="plainlinks">'''{{Size|130|[{{SERVER}}/index.php/Файл:Batch_Tools_0.3.zip СКАЧАТЬ ZIP]}}'''</span>
<span class="plainlinks">'''{{Size|130|[{{SERVER}}/index.php/Файл:Batch_Tools_0.3.zip СКАЧАТЬ ZIP]}}'''</span>


<markdown>
<syntaxhighlight lang="markdown">
## [0.3.0] — 2026-05-24
## [0.3.0] — 2026-05-24


Строка 10: Строка 10:
- Логика массового восстановления вынесена в самостоятельный класс `MassUndeleteHandler`.
- Логика массового восстановления вынесена в самостоятельный класс `MassUndeleteHandler`.
- Код `SpecialBatchTools` существенно сокращён и переведён на декларативный роутинг вкладок. Это упростит добавление новых пакетных инструментов в будущем.
- Код `SpecialBatchTools` существенно сокращён и переведён на декларативный роутинг вкладок. Это упростит добавление новых пакетных инструментов в будущем.
</markdown>
</syntaxhighlight>
 
<pre>
BatchTools/
├── extension.json
├── i18n/
│  ├── BatchTools.alias.php
│  ├── en.json
│  └── ru.json
└── includes/
    ├── SpecialBatchTools.php
    └── Handlers/
        ├── BatchToolHandler.php
        ├── MassDeleteHandler.php
        └── MassUndeleteHandler.php
</pre>
 


== ROOT ==
== ROOT ==
Строка 19: Строка 35:
"name": "BatchTools",
"name": "BatchTools",
"version": "0.3",
"version": "0.3",
"author": "Diman Russkov",
"author": "Name",
"descriptionmsg": "batchtools-desc",
"descriptionmsg": "batchtools-desc",
"type": "specialpage",
"type": "specialpage",
Строка 46: Строка 62:
}
}
</syntaxhighlight>
</syntaxhighlight>


== i18n ==
== i18n ==
=== BatchTools.alias.php ===
<syntaxhighlight lang="php">
<?php
/**
* Aliases for special pages of the BatchTools extension
*/
$specialPageAliases = [];
/** English (English) */
$specialPageAliases['en'] = [
'BatchTools' => [ 'BatchTools' ],
];
/** Russian (Русский) */
$specialPageAliases['ru'] = [
'BatchTools' => [ 'BatchTools', 'Пакетные_инструменты' ],
];
</syntaxhighlight>


=== en.json ===
=== en.json ===
Строка 116: Строка 153:
}
}
</syntaxhighlight>
</syntaxhighlight>


== includes ==
== includes ==


=== BatchTools.alias.php ===
=== SpecialBatchTools.php ===
<syntaxhighlight lang="php">
<syntaxhighlight lang="php">
<?php
<?php
/**
* Aliases for special pages of the BatchTools extension
*/


$specialPageAliases = [];
namespace MediaWiki\Extension\BatchTools;
 
use MediaWiki\SpecialPage\SpecialPage;
use MediaWiki\Html\Html;
use MediaWiki\Exception\PermissionsError;
use MediaWiki\Extension\BatchTools\Handlers\MassDeleteHandler;
use MediaWiki\Extension\BatchTools\Handlers\MassUndeleteHandler;
 
class SpecialBatchTools extends SpecialPage {
 
    public function __construct() {
        parent::__construct( 'BatchTools' );
    }
 
    public function isListed() {
        $authority = $this->getAuthority();
        // Пока что оставляем эти права, потом добавим новые (масс-блок, переименование и т.д.)
        return $authority->isAllowed( 'deletebatch' ) || $authority->isAllowed( 'undeletebatch' );
    }
 
    public function execute( $par ) {
        $authority = $this->getAuthority();
 
        $this->setHeaders();
        $this->checkReadOnly();
 
        $out = $this->getOutput();
        $out->setPageTitle( $this->msg( 'batchtools' )->text() );
 
        $out->enableOOUI();
        $out->addModules( [
            'oojs-ui-core',
            'oojs-ui-widgets',
            'mediawiki.widgets'
        ] );
 
        // 1. ДИНАМИЧЕСКИЙ СПИСОК ДОСТУПНЫХ ВКЛАДОК (Хэндлеров)
        $handlers = [];
        if ( $authority->isAllowed( 'deletebatch' ) ) {
            $handlers['delete'] = [
                'class' => MassDeleteHandler::class,
                'label' => $this->msg( 'batchtools-tab-delete' )->text()
            ];
        }
        if ( $authority->isAllowed( 'undeletebatch' ) ) {
            $handlers['undelete'] = [
                'class' => MassUndeleteHandler::class,
                'label' => $this->msg( 'batchtools-tab-undelete' )->text()
            ];
        }
 
        if ( empty( $handlers ) ) {
            throw new PermissionsError( 'deletebatch' );
        }
 
        // 2. ОПРЕДЕЛЯЕМ АКТИВНУЮ ВКЛАДКУ
        $request = $this->getRequest();
        $view = $request->getVal( 'view' );
 
        // Если вкладка не указана или у участника нет на неё прав — кидаем на первую доступную
        if ( $view === null || !array_key_exists( $view, $handlers ) ) {
            $view = array_key_first( $handlers );
        }
 
        // 3. ОТРИСОВКА МЕНЮ
        $navHtml = '<div style="margin-bottom: 25px; font-size: 1.1em; border-bottom: 2px solid #a2a9b1; padding-bottom: 10px; display: flex; flex-wrap: wrap; gap: 10px;">';
        $tabLinks = [];
        foreach ( $handlers as $tabKey => $tabData ) {
            if ( $view === $tabKey ) {
                $tabLinks[] = '<b style="color: #202122; background: #eaecf0; padding: 5px 10px; border-radius: 2px;">' . htmlspecialchars( $tabData['label'] ) . '</b>';
            } else {
                $url = $this->getPageTitle()->getLocalURL( [ 'view' => $tabKey ] );
                $tabLinks[] = Html::element( 'a', [ 'href' => $url, 'style' => 'padding: 5px 10px;' ], $tabData['label'] );
            }
        }
        $navHtml .= implode( '<span style="color:#a2a9b1;">|</span>', $tabLinks ) . '</div>';
        $out->addHTML( $navHtml );
 
        // Вывод общих уведомлений об успехе/ошибках
        $this->printSessionResult();
 
        // 4. ЗАПУСК НУЖНОГО ХЭНДЛЕРА
        $handlerClass = $handlers[$view]['class'];
        /** @var Handlers\BatchToolHandler $handlerObj */
        $handlerObj = new $handlerClass( $this );
        $handlerObj->execute();
    }
 
    /**
    * Выводит результаты выполнения массовых операций из сессии
    */
    private function printSessionResult() {
        $session = $this->getRequest()->getSession();
        $result = $session->get( 'batchtools_result' );
 
        if ( $result ) {
            $session->remove( 'batchtools_result' );
            $html = '';
 
            $action = $result['action'] ?? 'delete';
            $msgSuccess = $action === 'delete' ? 'batchtools-massdelete-success' : 'batchtools-massrestore-success';
            $msgErrors = $action === 'delete' ? 'batchtools-massdelete-errors' : 'batchtools-massrestore-errors';
 
            if ( !empty( $result['success_count'] ) ) {
                $html .= Html::successBox( $this->msg( $msgSuccess, $result['success_count'] )->text() );
            }


/** English (English) */
            if ( !empty( $result['errors'] ) ) {
$specialPageAliases['en'] = [
                $errHtml = '<b>' . $this->msg( $msgErrors )->text() . '</b><ul style="margin-top: 5px; margin-bottom: 0;">';
'BatchTools' => [ 'BatchTools' ],
                foreach ( $result['errors'] as $err ) {
];
                    $errHtml .= '<li>' . htmlspecialchars( $err ) . '</li>';
                }
                $errHtml .= '</ul>';
                $html .= Html::errorBox( $errHtml );
            }


/** Russian (Русский) */
            if ( $html !== '' ) {
$specialPageAliases['ru'] = [
                $this->getOutput()->addHTML( '<div style="margin-bottom: 20px;">' . $html . '</div>' );
'BatchTools' => [ 'BatchTools', 'Пакетные_инструменты' ],
            }
];
        }
    }
}
</syntaxhighlight>
</syntaxhighlight>


=== handlers ===
 
=== Handlers ===


==== BatchToolHandler.php ====
==== BatchToolHandler.php ====
Строка 421: Строка 568:


         $out->addHTML( $html );
         $out->addHTML( $html );
    }
}
</syntaxhighlight>
=== SpecialBatchTools.php ===
<syntaxhighlight lang="php">
<?php
namespace MediaWiki\Extension\BatchTools;
use MediaWiki\SpecialPage\SpecialPage;
use MediaWiki\Html\Html;
use MediaWiki\Exception\PermissionsError;
use MediaWiki\Extension\BatchTools\Handlers\MassDeleteHandler;
use MediaWiki\Extension\BatchTools\Handlers\MassUndeleteHandler;
class SpecialBatchTools extends SpecialPage {
    public function __construct() {
        parent::__construct( 'BatchTools' );
    }
    public function isListed() {
        $authority = $this->getAuthority();
        // Пока что оставляем эти права, потом добавим новые (масс-блок, переименование и т.д.)
        return $authority->isAllowed( 'deletebatch' ) || $authority->isAllowed( 'undeletebatch' );
    }
    public function execute( $par ) {
        $authority = $this->getAuthority();
        $this->setHeaders();
        $this->checkReadOnly();
        $out = $this->getOutput();
        $out->setPageTitle( $this->msg( 'batchtools' )->text() );
        $out->enableOOUI();
        $out->addModules( [
            'oojs-ui-core',
            'oojs-ui-widgets',
            'mediawiki.widgets'
        ] );
        // 1. ДИНАМИЧЕСКИЙ СПИСОК ДОСТУПНЫХ ВКЛАДОК (Хэндлеров)
        $handlers = [];
        if ( $authority->isAllowed( 'deletebatch' ) ) {
            $handlers['delete'] = [
                'class' => MassDeleteHandler::class,
                'label' => $this->msg( 'batchtools-tab-delete' )->text()
            ];
        }
        if ( $authority->isAllowed( 'undeletebatch' ) ) {
            $handlers['undelete'] = [
                'class' => MassUndeleteHandler::class,
                'label' => $this->msg( 'batchtools-tab-undelete' )->text()
            ];
        }
        if ( empty( $handlers ) ) {
            throw new PermissionsError( 'deletebatch' );
        }
        // 2. ОПРЕДЕЛЯЕМ АКТИВНУЮ ВКЛАДКУ
        $request = $this->getRequest();
        $view = $request->getVal( 'view' );
        // Если вкладка не указана или у участника нет на неё прав — кидаем на первую доступную
        if ( $view === null || !array_key_exists( $view, $handlers ) ) {
            $view = array_key_first( $handlers );
        }
        // 3. ОТРИСОВКА МЕНЮ
        $navHtml = '<div style="margin-bottom: 25px; font-size: 1.1em; border-bottom: 2px solid #a2a9b1; padding-bottom: 10px; display: flex; flex-wrap: wrap; gap: 10px;">';
        $tabLinks = [];
        foreach ( $handlers as $tabKey => $tabData ) {
            if ( $view === $tabKey ) {
                $tabLinks[] = '<b style="color: #202122; background: #eaecf0; padding: 5px 10px; border-radius: 2px;">' . htmlspecialchars( $tabData['label'] ) . '</b>';
            } else {
                $url = $this->getPageTitle()->getLocalURL( [ 'view' => $tabKey ] );
                $tabLinks[] = Html::element( 'a', [ 'href' => $url, 'style' => 'padding: 5px 10px;' ], $tabData['label'] );
            }
        }
        $navHtml .= implode( '<span style="color:#a2a9b1;">|</span>', $tabLinks ) . '</div>';
        $out->addHTML( $navHtml );
        // Вывод общих уведомлений об успехе/ошибках
        $this->printSessionResult();
        // 4. ЗАПУСК НУЖНОГО ХЭНДЛЕРА
        $handlerClass = $handlers[$view]['class'];
        /** @var Handlers\BatchToolHandler $handlerObj */
        $handlerObj = new $handlerClass( $this );
        $handlerObj->execute();
    }
    /**
    * Выводит результаты выполнения массовых операций из сессии
    */
    private function printSessionResult() {
        $session = $this->getRequest()->getSession();
        $result = $session->get( 'batchtools_result' );
        if ( $result ) {
            $session->remove( 'batchtools_result' );
            $html = '';
            $action = $result['action'] ?? 'delete';
            $msgSuccess = $action === 'delete' ? 'batchtools-massdelete-success' : 'batchtools-massrestore-success';
            $msgErrors = $action === 'delete' ? 'batchtools-massdelete-errors' : 'batchtools-massrestore-errors';
            if ( !empty( $result['success_count'] ) ) {
                $html .= Html::successBox( $this->msg( $msgSuccess, $result['success_count'] )->text() );
            }
            if ( !empty( $result['errors'] ) ) {
                $errHtml = '<b>' . $this->msg( $msgErrors )->text() . '</b><ul style="margin-top: 5px; margin-bottom: 0;">';
                foreach ( $result['errors'] as $err ) {
                    $errHtml .= '<li>' . htmlspecialchars( $err ) . '</li>';
                }
                $errHtml .= '</ul>';
                $html .= Html::errorBox( $errHtml );
            }
            if ( $html !== '' ) {
                $this->getOutput()->addHTML( '<div style="margin-bottom: 20px;">' . $html . '</div>' );
            }
        }
     }
     }
}
}