CleanupSite

Материал из Викиреальностя
Перейти к: навигация, поиск

CleanupSite — расширение для MediaWiki. Авторы — Oversighted494 и Edward Chernenko.

Содержание

[править] Описание

Позволяет выполнять следующие действия:

  • скрывать (отмечая как правки бота) и раскрывать правки из свежих правок, а также удалять их;
  • удалять отдельные блокировки;
  • удалять записи из журналов.

Технически удаление реализуется через изменение записей базы данных или их перенос в другие таблицы. Все эти удаления могут быть отменены системным администратором.

Протестировано на MediaWiki 1.16.5 и 1.18.

ВНИМАНИЕ: корректность работы достоверно не проверена.

[править] Установка

Для установки расширения выполните файл cleanupsite.sql, чтобы добавить необходимые таблицы базы данных.

Затем скопируйте в папку $IP/extensions/CleanupSite файлы расширения:

Добавьте в файл LocalSettings.php строчку require_once( "$IP/extensions/CleanupSite/CleanupSite.php" ); и определите при помощи $wgGroupPermissions права доступа cleanupsite (позволяет использовать все функции расширения) и cleanupsite-log (позволяет просматривать журнал совершенных при помощи расширения действий).

[править] Исходный код

[править] CleanupSite.php

<?php
 
if ( !defined( 'MEDIAWIKI' ) ) {
        echo "Not a executable file";
        exit( 1 );
}
 
$wgExtensionCredits['specialpage'][] = array (
        'name' => 'CleanupSite',
        'descriptionmsg' => 'cleanupsite-desc',
        'url' => 'http://wikireality.ru/wiki/CleanupSite',
        'author' => array ('Anonymous', 'Edward Chernenko'),
        'version' => '1.1'
);
 
$wgAvailableRights[] = 'cleanupsite';
$wgAvailableRights[] = 'cleanupsite-log';
 
$wgSpecialPages['CleanupSite'] = 'CleanupSite';
$wgSpecialPageGroups['CleanupSite'] = 'wiki';
$wgAutoloadClasses['CleanupSite'] = dirname( __FILE__ ) . '/CleanupSite_body.php';
$wgExtensionMessagesFiles['CleanupSite'] = dirname( __FILE__ ) . '/CleanupSite.i18n.php';
 
$wgLogTypes[] = 'cleanupsite';
$wgLogNames['cleanupsite'] = 'cleanupsite_logpagename';
$wgLogRestrictions['cleanupsite'] = 'cleanupsite-log';
$wgLogHeaders['cleanupsite'] = 'cleanupsite_logpagetext';
$wgLogActions['cleanupsite/cleanupsite'] = 'cleanupsite_logentry';
$wgLogActions['cleanupsite/rc_hide'] = 'cleanupsite_log_rc_hide';
$wgLogActions['cleanupsite/rc_unhide'] = 'cleanupsite_log_rc_unhide';
$wgLogActions['cleanupsite/rc_delete'] = 'cleanupsite_log_rc_delete';
$wgLogActions['cleanupsite/ipblocks'] = 'cleanupsite_log_ipblocks';
$wgLogActions['cleanupsite/logs'] = 'cleanupsite_log_logs';
 
$wgCleanupSiteRCLimit = 250;
$wgCleanupSiteIpbLimit = 100;
$wgCleanupSiteLogsLimit = 100;

[править] CleanupSite_body.php

<?php
 
class CleanupSite extends SpecialPage {
        function __construct()
        {
                SpecialPage::SpecialPage( 'CleanupSite', 'cleanupsite' );
        }
 
        public function execute( $subpage ) {
                global $wgOut, $wgUser, $wgArticlePath;
                wfLoadExtensionMessages('CleanupSite');
 
                $view = 'CleanupSiteViewHome';
 
                if ( !$wgUser->isAllowed( 'cleanupsite' ) ) {
                        $this->displayRestrictionError();
                        return;
                }
 
                $params = explode( '/', $subpage );
                $params = array_values( $params );
 
                if ( $subpage == 'recentchanges' ) {
                        $view = 'CleanupRecentChanges';
                }
 
                if ( $subpage == 'ipblocks' ) {
                        $view = 'CleanupIPBlocks';
                }
 
                if ( $subpage == 'logs' ) {
                        $view = 'CleanupLogs';
                }
 
                $v = new $view( $this, $params );
                $v->subpage = $subpage;
                $v->show();
        }
}
 
abstract class CleanupSiteView {
        var $subpage;
 
        function __construct( $page, $params ) {
                $this->mPage = $page;
                $this->mParams = $params;
        }
 
        function getTitle( $subpage = '' ) {
                return $this->mPage->getTitle( $subpage );
        }
 
        abstract function show();
}
 
class CleanupSiteViewHome extends CleanupSiteView {
        function show() {
                global $wgOut, $wgArticlePath, $wgUser;
                $wgOut->setPagetitle( wfMsg( 'cleanupsite' ) );
 
                $subpages = array( 'recentchanges', 'ipblocks', 'logs' );
                $path = str_replace('$1', '', $wgArticlePath);
 
                $wgOut->addWikiMsg( 'cleanupsite-about' );
 
                $wgOut->addHTML('<ul>');
 
                foreach ($subpages as $page) {
                        $wgOut->addHTML('<li><a href="' . $path . 'Special:CleanupSite/' . $page . '">' . wfMsg( 'cleanupsite-sub-' . $page ) . '</a></li>' );
                }
 
                $wgOut->addHTML('</ul>');
        }
}
 
class CleanupRecentChanges extends CleanupSiteView {
        function show() {
                global $wgOut, $wgUser, $wgRequest;
 
                $action = $wgRequest->getVal( 'action', $this->subpage );
                if ( $action == 'recentchanges' ) {
                        $wgOut->setPagetitle( wfMsg( 'cleanupsite-sub-recentchanges' ) );
                        $wgOut->addWikiMsg( 'cleanupsite-recentchanges-about' );
 
                        $topmessage = wfMsg('cleanupsite-recentchanges-topmessage');
                        $rccount = wfMsg('cleanupsite-recentchanges-rccount');
                        $button = wfMsg('htmlform-submit');
 
                        $wgOut->addHTML(
                                Xml::fieldset( $topmessage ) . Xml::openElement( 'form', array( 'id' => 'mw-cleanupsite-rc', 'method' => 'post' ) ) .
                                Xml::openElement( 'table', array( 'id' => "mw-cleanupsite-rc-table" ) ) .
                                '<tr><td class="mw-label">' . Xml::label( $rccount, 'mw-cleanupsite-rccount' ) . '</td>' .
                                '<td class="mw-input">' .  Xml::input( 'wpRCCount', 20, '', array( 'tabindex' => '1', 'id' => 'mw-cleanupsite-rccount', 'maxlength' => '3' ) ) . '</td></tr>' .
                                '<tr><td></td><td class="mw-submit">' . Xml::submitButton( $button, array( 'id' => 'mw-cleanupsite-rc-submit' ) ) . '</td></tr>' .
                                '<input type=hidden name="action" value="submit" />' .
                                Xml::closeElement( 'table' ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'fieldset' )
                        );
                }
 
                $id = $wgRequest->getVal( 'id' );
                $idmessage = wfMsg('cleanupsite-recentchanges-idmessage');
                $revisionmessage = wfMsg('cleanupsite-recentchanges-revisionmessage');
                $reasonmessage = wfMsg('cleanupsite-recentchanges-reasonmessage');
                if ( $action == 'hide' ) {
                        $wgOut->setPagetitle( wfMsg( 'cleanupsite-recentchanges-hide', array( "$id" ) ) );
 
                        $topmessage = wfMsg('cleanupsite-recentchanges-hide-topmessage');
                        $button = wfMsg('cleanupsite-submit-hide');
 
                        $id = intval($id);
 
                        $dbr = wfGetDB( DB_MASTER );
                        $res = $dbr->query("SELECT * FROM recentchanges WHERE rc_id = " . $id . " LIMIT 1");
                        $row = $dbr->fetchObject( $res );
 
                        if (!$row) {
                                $wgOut->addWikiMsg('cleanupsite-error-falseid');
                                return;
                        }
 
                        $bot = $row->rc_bot;
                        if ( $bot == 1 ) {
                                $wgOut->addWikiMsg('cleanupsite-error-hidden');
                                return;
                        }
 
                        $timestamp = $row->rc_timestamp;
                        $user = htmlspecialchars( $row->rc_user_text );
                        $namespace = $row->rc_namespace;
                        $title = htmlspecialchars( $row->rc_title );
                        $comment = htmlspecialchars( $row->rc_comment );
                        $log_type = $row->rc_log_type;
                        $log_action = $row->rc_log_action;
                        if ( $log_action ) {
                                $logging = "$log_type/$log_action";
                        } else {
                                $logging = "$namespace";
                        }
 
                        $wgOut->addHTML(
                                Xml::fieldset( $topmessage ) . Xml::openElement( 'form', array( 'id' => 'mw-cleanupsite-rc-hide', 'method' => 'post' ) ) .
                                Xml::openElement( 'table', array( 'id' => "mw-cleanupsite-rc-table" ) ) .
                                '<tr><td class="mw-label">' . Xml::label( $idmessage, 'mw-cleanupsite-id' ) . '</td>' .
                                '<td><code>' . $id . '</code></td></tr>' .
                                '<tr><td class="mw-label">' . Xml::label( $revisionmessage, 'mw-cleanupsite-revision' ) . '</td>' .
                                '<td><i>' . $timestamp . ' ' . $user . ' ' . $logging . ' ' . $title . ' ' . $comment . '</i></td>' .
                                '<tr><td class="mw-label">' . Xml::label( $reasonmessage, 'mw-cleanupsite-reason' ) . '</td>' .
                                '<td class="mw-input">' .  Xml::input( 'wpCleanupSiteReason', 60, '', array( 'tabindex' => '1', 'id' => 'mw-cleanupsite-reason', 'maxlength' => '200' ) ) . '</td></tr>' .
                                '<tr><td></td><td class="mw-submit">' . Xml::submitButton( $button, array( 'id' => 'mw-cleanupsite-rc-hide-submit' ) ) . '</td></tr>' .
                                '<input type=hidden name="id" value="' . $id . '" />' .
                                '<input type=hidden name="action" value="submithide" />' .
                                Xml::closeElement( 'table' ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'fieldset' )
                        );              
                }
 
                if ( $action == 'unhide' ) {
                        $wgOut->setPagetitle( wfMsg( 'cleanupsite-recentchanges-unhide', array( "$id" ) ) );
 
                        $topmessage = wfMsg('cleanupsite-recentchanges-unhide-topmessage');
                        $button = wfMsg('cleanupsite-submit-unhide');
 
                        $id = intval($id);
 
                        $dbr = wfGetDB( DB_MASTER );
                        $res = $dbr->query("SELECT * FROM recentchanges WHERE rc_id = " . $id . " LIMIT 1");
                        $row = $dbr->fetchObject( $res );
 
                        if (!$row) {
                                $wgOut->addWikiMsg('cleanupsite-error-falseid');
                                return;
                        }
 
                        $bot = $row->rc_bot;
                        if ( $bot == 0 ) {
                                $wgOut->addWikiMsg('cleanupsite-error-unhidden');
                                return;
                        }
 
                        $timestamp = $row->rc_timestamp;
                        $user = htmlspecialchars( $row->rc_user_text );
                        $namespace = $row->rc_namespace;
                        $title = htmlspecialchars( $row->rc_title );
                        $comment = htmlspecialchars( $row->rc_comment );
                        $log_type = $row->rc_log_type;
                        $log_action = $row->rc_log_action;
                        if ( $log_action ) {
                                $logging = "$log_type/$log_action";
                        } else {
                                $logging = "$namespace";
                        }
 
                        $wgOut->addHTML(
                                Xml::fieldset( $topmessage ) . Xml::openElement( 'form', array( 'id' => 'mw-cleanupsite-rc-unhide', 'method' => 'post' ) ) .
                                Xml::openElement( 'table', array( 'id' => "mw-cleanupsite-rc-table" ) ) .
                                '<tr><td class="mw-label">' . Xml::label( $idmessage, 'mw-cleanupsite-id' ) . '</td>' .
                                '<td><code>' . $id . '</code></td></tr>' .
                                '<tr><td class="mw-label">' . Xml::label( $revisionmessage, 'mw-cleanupsite-revision' ) . '</td>' .
                                '<td><i>' . $timestamp . ' ' . $user . ' ' . $logging . ' ' . $title . ' ' . $comment . '</i></td>' .
                                '<tr><td class="mw-label">' . Xml::label( $reasonmessage, 'mw-cleanupsite-reason' ) . '</td>' .
                                '<td class="mw-input">' .  Xml::input( 'wpCleanupSiteReason', 60, '', array( 'tabindex' => '1', 'id' => 'mw-cleanupsite-reason', 'maxlength' => '200' ) ) . '</td></tr>' .                              
                                '<tr><td></td><td class="mw-submit">' . Xml::submitButton( $button, array( 'id' => 'mw-cleanupsite-rc-unhide-submit' ) ) . '</td></tr>' .
                                '<input type=hidden name="id" value="' . $id . '" />' .
                                '<input type=hidden name="action" value="submitunhide" />' .
                                Xml::closeElement( 'table' ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'fieldset' )
                        );                      
                }
 
                if ( $action == 'delete' ) {
                        $wgOut->setPagetitle( wfMsg( 'cleanupsite-recentchanges-delete', array( "$id" ) ) );
 
                        $topmessage = wfMsg('cleanupsite-recentchanges-delete-topmessage');
                        $button = wfMsg('cleanupsite-submit-delete');
 
                        $dbr = wfGetDB( DB_MASTER );
                        $res = $dbr->query("SELECT * FROM recentchanges WHERE rc_id = " . $id . " LIMIT 1");
                        $row = $dbr->fetchObject( $res );
 
                        if (!$row) {
                                $wgOut->addWikiMsg('cleanupsite-error-falseid');
                                return;
                        }
 
                        $timestamp = $row->rc_timestamp;
                        $user = htmlspecialchars( $row->rc_user_text );
                        $namespace = $row->rc_namespace;
                        $title = htmlspecialchars( $row->rc_title );
                        $comment = htmlspecialchars( $row->rc_comment );
                        $log_type = $row->rc_log_type;
                        $log_action = $row->rc_log_action;
                        if ( $log_action ) {
                                $logging = "$log_type/$log_action";
                        } else {
                                $logging = "$namespace";
                        }
 
                        $wgOut->addHTML(
                                Xml::fieldset( $topmessage ) . Xml::openElement( 'form', array( 'id' => 'mw-cleanupsite-rc-delete', 'method' => 'post' ) ) .
                                Xml::openElement( 'table', array( 'id' => "mw-cleanupsite-rc-table" ) ) .
                                '<tr><td class="mw-label">' . Xml::label( $idmessage, 'mw-cleanupsite-id' ) . '</td>' .
                                '<td><code>' . $id . '</code></td></tr>' .
                                '<tr><td class="mw-label">' . Xml::label( $revisionmessage, 'mw-cleanupsite-revision' ) . '</td>' .
                                '<td><i>' . $timestamp . ' ' . $user . ' ' . $logging . ' ' . $title . ' ' . $comment . '</i></td>' .
                                '<tr><td class="mw-label">' . Xml::label( $reasonmessage, 'mw-cleanupsite-reason' ) . '</td>' .
                                '<td class="mw-input">' .  Xml::input( 'wpCleanupSiteReason', 60, '', array( 'tabindex' => '1', 'id' => 'mw-cleanupsite-reason', 'maxlength' => '200' ) ) . '</td></tr>' .                              
                                '<tr><td></td><td class="mw-submit">' . Xml::submitButton( $button, array( 'id' => 'mw-cleanupsite-rc-delete-submit' ) ) . '</td></tr>' .
                                '<input type=hidden name="id" value="' . $id . '" />' .
                                '<input type=hidden name="action" value="submitdelete" />' .
                                Xml::closeElement( 'table' ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'fieldset' )
                        );      
                }
 
                if ( $action == 'submit' ) {
                        $this->getRCList();
                }
 
                if ( $action == 'submithide' ) {
                        $this->doHideRC();
                }
 
                if ( $action == 'submitunhide' ) {
                        $this->doUnhideRC();
                }
 
                if ( $action == 'submitdelete' ) {
                        $this->doDeleteRC();
                }
        }
 
        function getRCList() {
                global $wgRequest, $wgOut, $wgCleanupSiteRCLimit, $wgUser, $wgArticlePath;
                $rccount = $wgRequest->getVal( 'wpRCCount' );
 
                $wgOut->setPagetitle( wfMsg( 'cleanupsite-sub-recentchanges' ) );
                $wgOut->addWikiMsg( 'cleanupsite-recentchanges-about' );
 
                $rccount = intval($rccount);
                if( $rccount > $wgCleanupSiteRCLimit ) { $rccount = $wgCleanupSiteRCLimit; }
                if(!$rccount) $rccount = 10;
 
                $dbr = wfGetDB( DB_MASTER );
                $res = $dbr->query("SELECT * FROM recentchanges ORDER BY rc_timestamp DESC LIMIT " . $rccount);
 
                $idmessage = wfMsg('cleanupsite-recentchanges-idmessage');
                $timestampmessage = wfMsg('cleanupsite-recentchanges-timestampmessage');
                $usermessage = wfMsg('cleanupsite-recentchanges-usermessage');
                $typemessage = wfMsg('cleanupsite-recentchanges-typemessage');
                $titlemessage = wfMsg('cleanupsite-recentchanges-titlemessage');
                $commentmessage = wfMsg('cleanupsite-recentchanges-commentmessage');
                $actionsmessage = wfMsg('cleanupsite-recentchanges-actionsmessage');
 
                $path = str_replace('$1', '', $wgArticlePath);
 
                $out = "<table class='mw-recentchanges wikitable'>
                <tr id='mw-recentchanges-header'><th>$idmessage</th> <th>$timestampmessage</th> <th>$usermessage</th> <th>$typemessage</th> <th>$titlemessage</th> <th>$commentmessage</th> <th>$actionsmessage</th></tr>";
 
                while( $s = $res->fetchObject() ) {
                        $id = $s->rc_id;
                        $timestamp = $s->rc_timestamp;
                        $user = htmlspecialchars( $s->rc_user_text );
                        $namespace = $s->rc_namespace;
                        $title = htmlspecialchars( $s->rc_title );
                        $comment = htmlspecialchars( $s->rc_comment );
                        $log_type = $s->rc_log_type;
                        $log_action = $s->rc_log_action;
                        $hidden = $s->rc_bot;
                        if ( $hidden == 1 )     {
                                $hidelink = wfMsg('cleanupsite-recentchanges-unhidelink');
                                $hideaction = "unhide";
                        } else {
                                $hidelink = wfMsg('cleanupsite-recentchanges-hidelink');
                                $hideaction = "hide";
                        }
                        $deletelink = wfMsg('cleanupsite-recentchanges-deletelink');
 
                        $out .= "<tr><td>$id</td><td>$timestamp</td><td>$user</td>";
                        if ( $log_action ) {
                                $out .= "<td>$log_type/$log_action</td>";
                        } else {
                                $out .= "<td>$namespace</td>";
                        }
                        $out .= "<td>$title</td><td>$comment</td><td>";
                        $out .= "<a href=\"" . $path . 'Special:CleanupSite/recentchanges?action=' . $hideaction . '&id=' . $id . "\">" . $hidelink . '</a>';
                        $out .= wfMsg( 'comma-separator' );
                        $out .= "<a href=\"" . $path . 'Special:CleanupSite/recentchanges?action=delete&id=' . $id . "\">" . $deletelink . '</a>';
                        $out .= "</td></tr>";
                }
 
                $res->free();
                $out .= '</table><br />';
                $wgOut->addHTML( $out );
        }
 
        function doHideRC() {
                global $wgRequest, $wgOut;
                $id = $wgRequest->getVal( 'id' );
                $reason = $wgRequest->getText( 'wpCleanupSiteReason' );
 
                $id = intval($id);
 
                $dbr = wfGetDB( DB_MASTER );
                $dbr->query("UPDATE recentchanges SET rc_bot=1 WHERE rc_id = " . $id);
 
                $selfTitle = $this->getTitle();
                $log = new LogPage( 'cleanupsite' );
                $log->addEntry( 'rc_hide', $selfTitle, $reason, array( $id ) );
 
                $wgOut->setPagetitle( wfMsg( 'cleanupsite-success' ) );
 
                $wgOut->addWikiMsg('cleanupsite-recentchanges-success-hide', "$id" );
        }
 
        function doUnhideRC() {
                global $wgRequest, $wgOut;
                $id = $wgRequest->getVal( 'id' );
                $reason = $wgRequest->getText( 'wpCleanupSiteReason' );
 
                $id = intval($id);
 
                $dbr = wfGetDB( DB_MASTER );
                $dbr->query("UPDATE recentchanges SET rc_bot=0 WHERE rc_id = " . $id);
 
                $selfTitle = $this->getTitle();
                $log = new LogPage( 'cleanupsite' );
                $log->addEntry( 'rc_unhide', $selfTitle, $reason, array( $id ) );
 
                $wgOut->setPagetitle( wfMsg( 'cleanupsite-success' ) );
 
                $wgOut->addWikiMsg('cleanupsite-recentchanges-success-unhide', "$id" );
        }
 
        function doDeleteRC() {
                global $wgRequest, $wgOut;
                $id = $wgRequest->getVal( 'id' );
                $reason = $wgRequest->getText( 'wpCleanupSiteReason' );
 
                $id = intval($id);
 
                $dbr = wfGetDB( DB_MASTER );
                $dbr->query("INSERT INTO rc_deleted () SELECT * FROM recentchanges WHERE rc_id=" . $id);
                $dbr->query("DELETE FROM recentchanges WHERE rc_id =" . $id . " LIMIT 1");
 
                $selfTitle = $this->getTitle();
                $log = new LogPage( 'cleanupsite' );
                $log->addEntry( 'rc_delete', $selfTitle, $reason, array( $id ) );
 
                $wgOut->setPagetitle( wfMsg( 'cleanupsite-success' ) );
 
                $wgOut->addWikiMsg('cleanupsite-recentchanges-success-delete', "$id" );
        }
}
 
class CleanupIPBlocks extends CleanupSiteView {
        function show() {
                global $wgOut, $wgUser, $wgRequest;
 
                $action = $wgRequest->getVal( 'action', $this->subpage );
                if ( $action == 'ipblocks' ) {
                        $wgOut->setPagetitle( wfMsg( 'cleanupsite-sub-ipblocks' ) );
                        $wgOut->addWikiMsg( 'cleanupsite-ipblocks-about' );
 
                        $topmessage = wfMsg('cleanupsite-ipblocks-topmessage');
                        $ipbcount = wfMsg('cleanupsite-ipblocks-count');
                        $button = wfMsg('htmlform-submit');
 
                        $wgOut->addHTML(
                                Xml::fieldset( $topmessage ) . Xml::openElement( 'form', array( 'id' => 'mw-cleanupsite-ipb', 'method' => 'post' ) ) .
                                Xml::openElement( 'table', array( 'id' => "mw-cleanupsite-ipb-table" ) ) .
                                '<tr><td class="mw-label">' . Xml::label( $ipbcount, 'mw-cleanupsite-ipbcount' ) . '</td>' .
                                '<td class="mw-input">' .  Xml::input( 'wpIpbCount', 20, '', array( 'tabindex' => '1', 'id' => 'mw-cleanupsite-ipbcount', 'maxlength' => '3' ) ) . '</td></tr>' .
                                '<tr><td></td><td class="mw-submit">' . Xml::submitButton( $button, array( 'id' => 'mw-cleanupsite-ipb-submit' ) ) . '</td></tr>' .
                                '<input type=hidden name="action" value="submit" />' .
                                Xml::closeElement( 'table' ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'fieldset' )
                        );                      
                }
 
                if ( $action == 'delete' ) {
                        $id = $wgRequest->getVal( 'id' );
 
                        $wgOut->setPagetitle( wfMsg( 'cleanupsite-ipblocks-delete', array( "$id" ) ) );
 
                        $topmessage = wfMsg('cleanupsite-ipblocks-delete-topmessage');
                        $button = wfMsg('cleanupsite-submit-delete');
                        $idmessage = wfMsg('cleanupsite-ipblocks-idmessage');
                        $ipbmessage = wfMsg('cleanupsite-ipblocks-ipbmessage');
                        $reasonmessage = wfMsg('cleanupsite-ipblocks-reasonmessage');
                        $usermessage = wfMsg('cleanupsite-ipblocks-usermessage');
                        $bymessage = wfMsg('cleanupsite-ipblocks-bymessage');
                        $expirymessage = wfMsg('cleanupsite-ipblocks-expirymessage');
                        $commentmessage = wfMsg('cleanupsite-ipblocks-commentmessage');
 
                        $dbr = wfGetDB( DB_MASTER );
                        $res = $dbr->query("SELECT * FROM ipblocks WHERE ipb_id = " . $id . " LIMIT 1");
                        $row = $dbr->fetchObject( $res );
 
                        if (!$row) {
                                $wgOut->addWikiMsg('cleanupsite-error-falseid');
                                return;
                        }
 
                        $id = $row->ipb_id;
                        $timestamp = $row->ipb_timestamp;
                        $user = htmlspecialchars( $row->ipb_address );
                        $byuser = htmlspecialchars( $row->ipb_by_text );
                        $expiry = $row->ipb_expiry;
                        $comment = htmlspecialchars( $row->ipb_reason );
 
                        $wgOut->addHTML(
                                Xml::fieldset( $topmessage ) . Xml::openElement( 'form', array( 'id' => 'mw-cleanupsite-ipb-delete', 'method' => 'post' ) ) .
                                Xml::openElement( 'table', array( 'id' => "mw-cleanupsite-ipb-table" ) ) .
                                '<tr><td class="mw-label">' . Xml::label( $idmessage, 'mw-cleanupsite-id' ) . '</td>' .
                                '<td><code>' . $id . '</code></td></tr>' .
                                '<tr><td class="mw-label">' . Xml::label( $ipbmessage, 'mw-cleanupsite-ipb' ) . '</td>' .
                                '<td><i>' . $timestamp . " " . $user . ", $bymessage " . $byuser . ", $expirymessage " . $expiry . ", $commentmessage «" . $comment . '»</i></td>' .
                                '<tr><td class="mw-label">' . Xml::label( $reasonmessage, 'mw-cleanupsite-reason' ) . '</td>' .
                                '<td class="mw-input">' .  Xml::input( 'wpCleanupSiteReason', 60, '', array( 'tabindex' => '1', 'id' => 'mw-cleanupsite-reason', 'maxlength' => '200' ) ) . '</td></tr>' .
                                '<tr><td></td><td class="mw-submit">' . Xml::submitButton( $button, array( 'id' => 'mw-cleanupsite-ipb-delete-submit' ) ) . '</td></tr>' .
                                '<input type=hidden name="id" value="' . $id . '" />' .
                                '<input type=hidden name="user" value="' . $user . '" />' .
                                '<input type=hidden name="action" value="submitdelete" />' .
                                Xml::closeElement( 'table' ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'fieldset' )
                        );      
                }
 
                if ( $action == 'submit' ) {
                        $this->getIPBlocksList();
                }
 
                if ( $action == 'submitdelete' ) {
                        $this->doDeleteBlock();
                }
        }
 
        function getIPBlocksList() {
                global $wgRequest, $wgOut, $wgCleanupSiteIpbLimit, $wgUser, $wgArticlePath;
                $ipbcount = $wgRequest->getVal( 'wpIpbCount' );
 
                $ipbcount = intval($ipbcount);
 
                if( $ipbcount > $wgCleanupSiteIpbLimit ) { $ipbcount = $wgCleanupSiteIpbLimit; }
                if(!$ipbcount) $ipbcount = 10;
 
                $wgOut->setPagetitle( wfMsg( 'cleanupsite-sub-ipblocks' ) );
                $wgOut->addWikiMsg( 'cleanupsite-ipblocks-about' );
 
                $dbr = wfGetDB( DB_MASTER );
                $res = $dbr->query("SELECT * FROM ipblocks ORDER BY ipb_id DESC LIMIT " . $ipbcount);
 
                $idmessage = wfMsg('cleanupsite-ipblocks-idmessage');
                $timestampmessage = wfMsg('cleanupsite-ipblocks-timestampmessage');
                $usermessage = wfMsg('cleanupsite-ipblocks-usermessage');
                $byusermessage = wfMsg('cleanupsite-ipblocks-byusermessage');
                $expirymessage = wfMsg('cleanupsite-ipblocks-expirymessage-table');
                $commentmessage = wfMsg('cleanupsite-ipblocks-commentmessage-table');
                $actionsmessage = wfMsg('cleanupsite-ipblocks-actionsmessage');
 
                $path = str_replace('$1', '', $wgArticlePath);
 
                $out = "<table class='mw-recentchanges wikitable'>
                <tr id='mw-recentchanges-header'><th>$idmessage</th> <th>$timestampmessage</th> <th>$usermessage</th> <th>$byusermessage</th> <th>$expirymessage</th> <th>$commentmessage</th> <th>$actionsmessage</th></tr>";
 
                while( $s = $res->fetchObject() ) {
                        $id = $s->ipb_id;
                        $timestamp = $s->ipb_timestamp;
                        $user = htmlspecialchars( $s->ipb_address );
                        $byuser = htmlspecialchars( $s->ipb_by_text );
                        $expiry = $s->ipb_expiry;
                        $comment = htmlspecialchars( $s->ipb_reason );
                        $action = "delete";
                        $actionlink = wfMsg('cleanupsite-ipblocks-deletelink');
 
                        $out .= "<tr><td>$id</td><td>$timestamp</td><td>$user</td><td>$byuser</td><td>$expiry</td><td>$comment</td><td><a href=\"" . $path . 'Special:CleanupSite/ipblocks?action=delete&id=' . $id . "\">" . $actionlink . "</a></td></tr>";
                }
 
                $res->free();
                $out .= '</table><br />';
                $wgOut->addHTML( $out );
        }
 
        function doDeleteBlock() {
                global $wgRequest, $wgOut;
                $id = $wgRequest->getVal( 'id' );
                $user = $wgRequest->getVal( 'user' );
                $reason = $wgRequest->getText( 'wpCleanupSiteReason' );
 
                $id = intval($id);
 
                $dbr = wfGetDB( DB_MASTER );
                $dbr->query("INSERT INTO ipb_deleted () SELECT * FROM ipblocks WHERE ipb_id=" . $id);
                $dbr->query("DELETE FROM ipblocks WHERE ipb_id =" . $id . " LIMIT 1");
 
                $selfTitle = $this->getTitle();
                $log = new LogPage( 'cleanupsite' );
                $log->addEntry( 'ipblocks', $selfTitle, $reason, array( $id, $user ) );
 
                $wgOut->setPagetitle( wfMsg( 'cleanupsite-success' ) );
 
                $wgOut->addWikiMsg('cleanupsite-ipblocks-success-delete', "$id" );
        }
}
 
class CleanupLogs extends CleanupSiteView {
        function show() {
                global $wgOut, $wgUser, $wgRequest;
 
                $action = $wgRequest->getVal( 'action', $this->subpage );
                if ( $action == 'logs' ) {
                        $wgOut->setPagetitle( wfMsg( 'cleanupsite-sub-logs' ) );
                        $wgOut->addWikiMsg( 'cleanupsite-logs-about' );
 
                        $topmessage = wfMsg('cleanupsite-logs-topmessage');
                        $logscount = wfMsg('cleanupsite-logs-count');
                        $logtype = wfMsg('cleanupsite-logs-logtype');
                        $button = wfMsg('htmlform-submit');
 
                        $wgOut->addHTML(
                                Xml::fieldset( $topmessage ) . Xml::openElement( 'form', array( 'id' => 'mw-cleanupsite-logs', 'method' => 'post' ) ) .
                                Xml::openElement( 'table', array( 'id' => "mw-cleanupsite-logs-table" ) ) .
                                '<tr><td class="mw-label">' . Xml::label( $logscount, 'mw-cleanupsite-logscount' ) . '</td>' .
                                '<td class="mw-input">' .  Xml::input( 'wpLogsCount', 30, '', array( 'tabindex' => '1', 'id' => 'mw-cleanupsite-logscount', 'maxlength' => '3' ) ) . '</td></tr>' .
                                '<tr><td class="mw-label">' . Xml::label( $logtype, 'mw-cleanupsite-logtype' ) . '</td>' .
                                '<td class="mw-input">' .  Xml::input( 'wpLogType', 30, '', array( 'tabindex' => '1', 'id' => 'mw-cleanupsite-logstype', 'maxlength' => '30' ) ) . '</td></tr>' .
                                '<tr><td></td><td class="mw-submit">' . Xml::submitButton( $button, array( 'id' => 'mw-cleanupsite-logs-submit' ) ) . '</td></tr>' .
                                '<input type=hidden name="action" value="submit" />' .
                                Xml::closeElement( 'table' ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'fieldset' )
                        );                      
                }
 
                if ( $action == 'delete' ) {
                        $id = $wgRequest->getVal( 'id' );
 
                        $wgOut->setPagetitle( wfMsg( 'cleanupsite-logs-delete', array( "$id" ) ) );
 
                        $topmessage = wfMsg('cleanupsite-logs-delete-topmessage');
                        $button = wfMsg('cleanupsite-submit-delete');
                        $idmessage = wfMsg('cleanupsite-logs-idmessage');
                        $logsmessage = wfMsg('cleanupsite-logs-logsmessage');
                        $reasonmessage = wfMsg('cleanupsite-logs-reasonmessage');
                        $typemessage = wfMsg('cleanupsite-logs-typemessage');
                        $usermessage = wfMsg('cleanupsite-logs-usermessage');
                        $titlemessage = wfMsg('cleanupsite-logs-titlemessage');
                        $commentmessage = wfMsg('cleanupsite-logs-commentmessage');
 
                        $dbr = wfGetDB( DB_MASTER );
                        $res = $dbr->query("SELECT * FROM logging WHERE log_id = " . $id . " LIMIT 1");
                        $row = $dbr->fetchObject( $res );
 
                        if (!$row) {
                                $wgOut->addWikiMsg('cleanupsite-error-falseid');
                                return;
                        }
 
                        $loguser = $row->log_user;
                        if ( $loguser == 0 ) {
                                $wgOut->addWikiMsg('cleanupsite-error-log-hidden');
                                return;
                        }
 
                        $id = $row->log_id;
                        $timestamp = $row->log_timestamp;
                        $logtype = $row->log_type;
                        $type = $logtype . "/" . $row->log_action;
                        $user = htmlspecialchars( $row->log_user_text );
                        $title = htmlspecialchars( $row->log_title );
                        $comment = htmlspecialchars( $row->log_comment );
 
                        $wgOut->addHTML(
                                Xml::fieldset( $topmessage ) . Xml::openElement( 'form', array( 'id' => 'mw-cleanupsite-logs-delete', 'method' => 'post' ) ) .
                                Xml::openElement( 'table', array( 'id' => "mw-cleanupsite-logs-table" ) ) .
                                '<tr><td class="mw-label">' . Xml::label( $idmessage, 'mw-cleanupsite-id' ) . '</td>' .
                                '<td><code>' . $id . '</code></td></tr>' .
                                '<tr><td class="mw-label">' . Xml::label( $logsmessage, 'mw-cleanupsite-logs' ) . '</td>' .
                                '<td><i>' . $timestamp . ", $typemessage " . $type . ", $targetusermessage " . $user . ", $titlemessage " . $title . ", $commentmessage " . $comment . '</i></td>' .
                                '<tr><td class="mw-label">' . Xml::label( $reasonmessage, 'mw-cleanupsite-reason' ) . '</td>' .
                                '<td class="mw-input">' .  Xml::input( 'wpCleanupSiteReason', 60, '', array( 'tabindex' => '1', 'id' => 'mw-cleanupsite-reason', 'maxlength' => '200' ) ) . '</td></tr>' .
                                '<tr><td></td><td class="mw-submit">' . Xml::submitButton( $button, array( 'id' => 'mw-cleanupsite-logs-delete-submit' ) ) . '</td></tr>' .
                                '<input type=hidden name="id" value="' . $id . '" />' .
                                '<input type=hidden name="logtype" value="' . $logtype . '" />' .
                                '<input type=hidden name="action" value="submitdelete" />' .
                                Xml::closeElement( 'table' ) . Xml::closeElement( 'form' ) . Xml::closeElement( 'fieldset' )
                        );      
                }
 
                if ( $action == 'submit' ) {
                        $this->getLogsEntry();
                }
 
                if ( $action == 'submitdelete' ) {
                        $this->doDeleteLogEntry();
                }
        }
 
        function getLogsEntry() {
                global $wgRequest, $wgOut, $wgCleanupSiteLogsLimit, $wgUser, $wgArticlePath;
                $logscount = $wgRequest->getVal( 'wpLogsCount' );
                $logtype = $wgRequest->getVal( 'wpLogType' );
 
                $logscount = intval($logscount);
                $logtype = preg_replace('[^a-zA-Z]', '', $logtype);
 
                if( $logscount > $wgCleanupSiteLogsLimit ) { $logscount = $wgCleanupSiteLogsLimit; }
                if(!$logscount) $logscount = 10;
                if(!$logtype) {
                        $logtype_req = "";
                } else {
                        $logtype_req = " WHERE log_type = '$logtype'";
                }
 
                $wgOut->setPagetitle( wfMsg( 'cleanupsite-sub-logs' ) );
                $wgOut->addWikiMsg( 'cleanupsite-logs-about' );
 
                $dbr = wfGetDB( DB_MASTER );
                $res = $dbr->query("SELECT * FROM logging$logtype_req ORDER BY log_id DESC LIMIT " . $logscount);
 
                $idmessage = wfMsg('cleanupsite-logs-idmessage');
                $timestampmessage = wfMsg('cleanupsite-logs-timestampmessage');
                $typemessage = wfMsg('cleanupsite-logs-typemessage');
                $usermessage = wfMsg('cleanupsite-logs-usermessage');
                $titlemessage = wfMsg('cleanupsite-logs-titlemessage');
                $commentmessage = wfMsg('cleanupsite-logs-commentmessage');
                $actionsmessage = wfMsg('cleanupsite-logs-actionsmessage');
 
                $path = str_replace('$1', '', $wgArticlePath);
 
                $out = "<table class='mw-recentchanges wikitable'>
                <tr id='mw-recentchanges-header'><th>$idmessage</th> <th>$timestampmessage</th> <th>$typemessage</th> <th>$usermessage</th> <th>$titlemessage</th> <th>$commentmessage</th> <th>$actionsmessage</th></tr>";
 
                while( $s = $res->fetchObject() ) {
                        $id = $s->log_id;
                        $timestamp = $s->log_timestamp;
                        $type = $s->log_type . "/" . $s->log_action;
                        $user = htmlspecialchars( $s->log_user_text );
                        $title = htmlspecialchars( $s->log_title );
                        $comment = htmlspecialchars( $s->log_comment );
                        $action = "delete";
                        $actionlink = wfMsg('cleanupsite-logs-deletelink');
                        $inactive = wfMsg('cleanupsite-logs-inactivelink');
                        $user_id = $s->log_user;
 
                        $out .= "<tr><td>$id</td><td>$timestamp</td><td>$type</td><td>$user</td><td>$title</td><td>$comment</td>";
                        if ( $user_id == 0 ) {
                                $out .= "<td>$inactive</td>";
                        } else {
                                $out .= "<td><a href=\"" . $path . 'Special:CleanupSite/logs?action=delete&id=' . $id . "\">" . $actionlink . "</a></td>";
                        }
 
                        $out .= "</tr>";
                }
 
                $res->free();
                $out .= '</table><br />';
                $wgOut->addHTML( $out );
        }
 
        function doDeleteLogEntry() {
                global $wgRequest, $wgOut;
                $id = $wgRequest->getVal( 'id' );
                $logtype = $wgRequest->getVal( 'logtype' );
                $reason = $wgRequest->getText( 'wpCleanupSiteReason' );
 
                $id = intval($id);
                $dbr = wfGetDB( DB_MASTER );
                $dbr->query("UPDATE logging SET log_user=0 WHERE log_id = " . $id);
 
                $selfTitle = $this->getTitle();
                $log = new LogPage( 'cleanupsite' );
                $log->addEntry( 'logs', $selfTitle, $reason, array( $id, $logtype ) );
 
                $wgOut->setPagetitle( wfMsg( 'cleanupsite-success' ) );
 
                $wgOut->addWikiMsg('cleanupsite-logs-success-delete', "$id" );
        }
}

[править] CleanupSite.i18n.php

<?php
 
$messages = array();
 
$messages['en'] = array(
        'cleanupsite' => 'Чистка сайта',
        'cleanupsite-desc' => 'Позволяет удалять с сайта следы нежелательной активности',
        'cleanupsite-about' => 'При помощи этой служебной страницы вы можете удалить отдельные следы нежелательной активности с сайта.',
        'cleanupsite-sub-recentchanges' => 'Чистка свежих правок',
        'cleanupsite-sub-ipblocks' => 'Чистка списка заблокированных пользователей',
        'cleanupsite-sub-logs' => 'Чистка записей в журналах',
        'cleanupsite_logpagename' => 'Журнал очистки сайта',
        'cleanupsite_logpagetext' => 'Журнал, записывающий действия администраторов по очистке сайта от следов нежелательной активности',
        'cleanupsite_logentry' => '',
        'cleanupsite_log_rc_hide' => 'скрыл запись $2 из свежих правок',
        'cleanupsite_log_rc_unhide' => 'раскрыл запись $2 из свежих правок',
        'cleanupsite_log_rc_delete' => 'удалил запись $2 из свежих правок',
        'cleanupsite_log_ipblocks' => 'удалил блокировку с ID $2 участника $3',
        'cleanupsite_log_logs' => 'удалил запись $2 из журнала «$3»',
        'cleanupsite-recentchanges-about' => 'При помощи этой служебной страницы вы можете скрывать (показываются при использовании <code>hidebots=0</code>) и удалять отдельные элементы свежих правок.',
        'cleanupsite-recentchanges-topmessage' => 'Инициализация',
        'cleanupsittd>e-recentchanges-rccount' => 'Число свежих правок',
        'cleanupsite-recentchanges-idmessage' => 'ID',
        'cleanupsite-recentchanges-timestampmessage' => 'Время изменения',
        'cleanupsite-recentchanges-usermessage' => 'Участник',
        'cleanupsite-recentchanges-typemessage' => 'ПИ или тип журнала',
        'cleanupsite-recentchanges-titlemessage' => 'Название страницы',
        'cleanupsite-recentchanges-commentmessage' => 'Комментарий к изменению',
        'cleanupsite-recentchanges-actionsmessage' => 'Действия',
        'cleanupsite-recentchanges-reasonmessage' => 'Причина',
        'cleanupsite-recentchanges-unhidelink' => 'Раскрыть',
        'cleanupsite-recentchanges-hidelink' => 'Скрыть',
        'cleanupsite-recentchanges-deletelink' => 'Удалить',
        'cleanupsite-recentchanges-hide' => 'Скрытие правки $1',
        'cleanupsite-recentchanges-hide-topmessage' => 'Скрытие правки из свежих правок',
        'cleanupsite-recentchanges-revisionmessage' => 'Данные правки',
        'cleanupsite-recentchanges-success-hide' => 'Правка $1 успешно скрыта из списка свежих правок.',
        'cleanupsite-recentchanges-unhide' => 'Раскрытие правки $1',
        'cleanupsite-recentchanges-unhide-topmessage' => 'Раскрытие правки в свежих правках',
        'cleanupsite-recentchanges-success-unhide' => 'Правка $1 успешно раскрыта в списке свежих правок.',
        'cleanupsite-recentchanges-delete' => 'Удаление правки $1',
        'cleanupsite-recentchanges-delete-topmessage' => 'Удаление правки из свежих правок',
        'cleanupsite-recentchanges-success-delete' => 'Правка $1 успешно удалена из списка свежих правок.',
        'cleanupsite-submit-delete' => 'Удалить',
        'cleanupsite-ipblocks-about' => 'При помощи этой служебной страницы вы можете удалять отдельные блокировки участников и IP-адресов. Это равносильно разблокировке.',
        'cleanupsite-ipblocks-topmessage' => 'Инициализация',
        'cleanupsite-ipblocks-count' => 'Число блокировок',
        'cleanupsite-ipblocks-idmessage' => 'ID',
        'cleanupsite-ipblocks-timestampmessage' => 'Время блокировки',
        'cleanupsite-ipblocks-usermessage' => 'Цель блокировки',
        'cleanupsite-ipblocks-byusermessage' => 'Администратор',
        'cleanupsite-ipblocks-expirymessage-table' => 'Дата окончания блокировки',
        'cleanupsite-ipblocks-commentmessage-table' => 'Комментарий',
        'cleanupsite-ipblocks-actionsmessage' => 'Действия',
        'cleanupsite-ipblocks-reasonmessage' => 'Причина',
        'cleanupsite-ipblocks-deletelink' => 'Удалить',
        'cleanupsite-ipblocks-delete' => 'Удаление блокировки $1',
        'cleanupsite-ipblocks-delete-topmessage' => 'Удаление блокировки',
        'cleanupsite-ipblocks-ipbmessage' => 'Данные о блокировке',
        'cleanupsite-ipblocks-targetusermessage' => 'заблокирован',
        'cleanupsite-ipblocks-bymessage' => 'заблокирован администратором',
        'cleanupsite-ipblocks-expirymessage' => 'истекает',
        'cleanupsite-ipblocks-commentmessage' => 'с пометкой',
        'cleanupsite-ipblocks-success-delete' => 'Блокировка $1 успешно удалена из списка блокировок.',
        'cleanupsite-logs-about' => 'При помощи этой служебной страницы вы можете скрывать отдельные записи в журналах.',
        'cleanupsite-logs-topmessage' => 'Инициализация',
        'cleanupsite-logs-count' => 'Число записей',
        'cleanupsite-logs-logtype' => 'Тип журнала',
        'cleanupsite-logs-idmessage' => 'ID',
        'cleanupsite-logs-timestampmessage' => 'Время действия',
        'cleanupsite-logs-typemessage' => 'Тип действия',
        'cleanupsite-logs-usermessage' => 'Участник',
        'cleanupsite-logs-titlemessage' => 'Цель',
        'cleanupsite-logs-commentmessage' => 'Комментарий',
        'cleanupsite-logs-actionsmessage' => 'Действия',
        'cleanupsite-logs-deletelink' => 'Удалить',
        'cleanupsite-logs-inactivelink' => 'Удалено',
        'cleanupsite-logs-delete' => 'Удаление записи журнала $1',
        'cleanupsite-logs-delete-topmessage' => 'Удаление записи журнала',
        'cleanupsite-logs-idmessage' => 'ID',
        'cleanupsite-logs-logsmessage' => 'Данные записи',
        'cleanupsite-logs-reasonmessage' => 'Причина',
        'cleanupsite-logs-typemessage' => 'тип',
        'cleanupsite-logs-usermessage' => 'участник',
        'cleanupsite-logs-titlemessage' => 'страница',
        'cleanupsite-logs-commentmessage' => 'комментарий',
        'cleanupsite-logs-success-delete' => 'Запись журнала $1 успешно удалена.',
        'cleanupsite-success' => 'Действие выполнено',
        'cleanupsite-submit-hide' => 'Скрыть',
        'cleanupsite-submit-unhide' => 'Раскрыть',
        'cleanupsite-error-falseid' => 'Ошибка. Записи с таким ID не существует в базе данных.',
        'cleanupsite-error-hidden' => 'Ошибка. Эта запись уже скрыта из свежих правок.',
        'cleanupsite-error-unhidden' => 'Ошибка. Эта запись уже раскрыта в свежих правках.',
        'cleanupsite-error-log-hidden' => 'Ошибка. Эта запись уже удалена из журналов.',
        'right-cleanupsite' => 'чистка служебных страниц',
        'right-cleanupsite-log' => 'просмотр журнала очистки служебных страниц',
        'right-cleanupsite-revert' => 'восстановление элементов служебных страниц',
        'right-cleanupsite-truncate' => 'очистка таблиц базы данных, содержащих удалённые элементы служебных страниц',
);

[править] cleanupsite.sql

CREATE TABLE rc_deleted LIKE recentchanges;
CREATE TABLE ipb_deleted LIKE ipblocks;
CleanupSite относится к теме «MediaWiki»   ±