https://www.mediawiki.org/wiki/Special:Code/MediaWiki/102139
Revision: 102139
Author: cryptocoryne
Date: 2011-11-06 01:17:04 +0000 (Sun, 06 Nov 2011)
Log Message:
-----------
Added experimental version of new extension
Added Paths:
-----------
trunk/extensions/Premoderation/
trunk/extensions/Premoderation/Premoderation.class.php
trunk/extensions/Premoderation/Premoderation.i18n.php
trunk/extensions/Premoderation/Premoderation.php
trunk/extensions/Premoderation/SpecialPremoderation.php
trunk/extensions/Premoderation/SpecialPremoderationWhiteList.php
trunk/extensions/Premoderation/db_tables.sql
trunk/extensions/Premoderation/install.php
Added: trunk/extensions/Premoderation/Premoderation.class.php
===================================================================
--- trunk/extensions/Premoderation/Premoderation.class.php
(rev 0)
+++ trunk/extensions/Premoderation/Premoderation.class.php 2011-11-06
01:17:04 UTC (rev 102139)
@@ -0,0 +1,173 @@
+<?php
+class Premoderation {
+ public static function initialize() {
+ global $wgPremoderationType, $wgPremoderationLockPages;
+ global $wgHooks, $wgAbuseFilterCustomActionsHandlers;
+
+ switch( $wgPremoderationType ) {
+ case 'all':
+ $wgHooks['ArticleSave'][] =
'Premoderation::processEditRequest';
+ break;
+
+ case 'abusefilter':
+ if( !class_exists( 'AbuseFilter' ) ) {
+ exit( 'You must install AbuseFilter
extension before using option $wgPremoderationType = \'abusefilter\'.' );
+ }
+ $wgAbuseFilterAvailableActions[] = 'moderation';
+
$wgAbuseFilterCustomActionsHandlers['moderation'] =
'Premoderation::handleAFAction';
+ break;
+ }
+
+ if( $wgPremoderationLockPages ) {
+ $wgHooks['getUserPermissionsErrorsExpensive'][] =
'Premoderation::checkQueue';
+ }
+
+ $wgHooks['ArticleEditUpdatesDeleteFromRecentchanges'][] =
'Premoderation::deleteOldQueueEntries';
+
+ return true;
+ }
+
+ public static function processEditRequest( &$article, &$user, &$text,
&$summary, $minor, $watchthis,
+ $sectionanchor, &$flags, &$status )
+ {
+ $userIP = wfGetIP();
+ if( $user->isAllowed( 'skipmoderation' ) ||
self::checkWhitelist( $userIP ) ) {
+ return true;
+ }
+
+ $title = $article->mTitle;
+
+ $dbw = wfGetDB( DB_MASTER );
+ $dbQuery = array(
+ 'pmq_id' => '',
+ 'pmq_page_last_id' => $title->getLatestRevID(),
+ 'pmq_page_ns' => $title->getNamespace(),
+ 'pmq_page_title' => $title->getDBkey(),
+ 'pmq_user' => $user->getID(),
+ 'pmq_user_text' => $user->getName(),
+ 'pmq_timestamp' => $dbw->timestamp( wfTimestampNow() ),
+ 'pmq_minor' => $minor,
+ 'pmq_summary' => $summary,
+ 'pmq_len' => $title->getLength(),
+ 'pmq_text' => $text,
+ 'pmq_flags' => $flags,
+ 'pmq_ip' => $userIP,
+ 'pmq_status' => 'new'
+ );
+ $dbw->insert( 'pm_queue', $dbQuery, __METHOD__ );
+ $dbw->commit();
+
+ throw new ErrorPageError( 'premoderation-success',
'premoderation-added-success-text' );
+ return true;
+ }
+
+ public static function handleAFAction( $action, $parameters, $title,
$vars, $rule_desc ) {
+ global $wgUser;
+
+ $dbw = wfGetDB( DB_MASTER );
+ $dbQuery = array(
+ 'pmq_id' => '',
+ 'pmq_page_last_id' => $title->getLatestRevID(),
+ 'pmq_page_ns' => $title->getNamespace(),
+ 'pmq_page_title' => $title->getDBkey(),
+ 'pmq_user' => $wgUser->getID(),
+ 'pmq_user_text' => $wgUser->getName(),
+ 'pmq_timestamp' => $dbw->timestamp( wfTimestampNow() ),
+ 'pmq_minor' => $vars->getVar( 'minor_edit' )->toInt(),
+ 'pmq_summary' => $vars->getVar( 'summary' )->toString(),
+ 'pmq_len' => $title->getLength(),
+ 'pmq_text' => $vars->getVar( 'new_wikitext'
)->toString(),
+ 'pmq_flags' => false,
+ 'pmq_ip' => wfGetIP(),
+ 'pmq_status' => 'new'
+ );
+ $dbw->insert( 'pm_queue', $dbQuery, __METHOD__ );
+ $dbw->commit();
+
+ return true;
+ }
+
+ public static function loadWhitelist() {
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select( 'pm_whitelist', '*', '', array( 'LIMIT' =>
500 ) );
+
+ $test = $dbr->fetchRow( $res );
+ if( !$test ) {
+ return true;
+ }
+
+ $returnArray = array( $test['pmw_ip'] );
+ while( $row = $dbr->fetchRow( $res ) ) {
+ $returnArray[] = $row['pmw_ip'];
+ }
+
+ return $returnArray;
+ }
+
+ public static function checkWhitelist( $ip ) {
+ $whitelist = self::loadWhitelist();
+
+ $memcKey = wfMemcKey( 'whitelisted', $ip );
+ $data = $wgMemc->get( $memcKey );
+
+ if( $data != '' ) {
+ return ( $data === 'ok' ) ? true : false;
+ }
+
+ if( is_array( $whitelist ) ) {
+ foreach( $whitelist as $entry ) {
+ if( IP::isInRange( $ip, $entry ) ) {
+ $wgMemc->set( $memcKey, 'ok', 86400 );
+ return true;
+ }
+ }
+ }
+
+ $wgMemc->set( $memcKey, 'not', 86400 );
+ return false;
+ }
+
+ public static function formatParams( $params ) {
+ $result = array();
+ while( count( $params ) > 1 ) {
+ $key = array_shift( &$params );
+ $value = array_shift( &$params );
+ $result[$key] = $value;
+ }
+
+ return $result;
+ }
+
+ public static function checkQueue( $title, $user, $action, &$result ) {
+ if( $action == 'edit' ) {
+ $dbr = wfGetDB( DB_SLAVE );
+
+ $conds = 'pmq_page_ns = ' . $dbr->addQuotes(
$title->getNamespace() ) . ' AND pmq_page_title = ' .
+ $dbr->addQuotes( $title->getDBkey() ) . ' AND
pmq_status != "approved"';
+ $res = $dbr->select( 'pm_queue', '*', $conds,
__METHOD__ );
+
+ $test = $dbr->fetchRow( $res );
+
+ if( $test ) {
+ $result[] = array(
'premoderation-edit-conflict' );
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static function deleteOldQueueEntries() {
+ global $wgPremoderationDeclinedPurge, $wgPremoderationNewPurge;
+
+ if( mt_rand( 0, 49 ) == 0 ) {
+ $dbw = wfGetDB( DB_MASTER );
+
+ $conds = '( pmq_status = \'new\' AND pmq_timestamp <
\'' . intval( $dbw->timestamp( time() -
+ $wgPremoderationNewPurge ) ) . '\' ) OR (
pmq_status = \'declined\' AND pmq_timestamp < \'' .
+ intval( $dbw->timestamp( time() -
$wgPremoderationDeclinedPurge ) ) . '\' ) OR ' .
+ 'pmq_status = \'approved\'';
+ $dbw->delete( 'pm_queue', array( $conds ), __METHOD__ );
+ }
+ return true;
+ }
+}
\ No newline at end of file
Property changes on: trunk/extensions/Premoderation/Premoderation.class.php
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/extensions/Premoderation/Premoderation.i18n.php
===================================================================
--- trunk/extensions/Premoderation/Premoderation.i18n.php
(rev 0)
+++ trunk/extensions/Premoderation/Premoderation.i18n.php 2011-11-06
01:17:04 UTC (rev 102139)
@@ -0,0 +1,150 @@
+<?php
+/**
+ * @file
+ * @ingroup Extensions
+ */
+$messages = array();
+
+/** English
+ * @author Cryptocoryne
+ * @author Kalan
+ */
+$messages['en'] = array(
+ 'premoderation' => 'Premoderation',
+ 'premoderation-desc' => 'Allows to premoderate untrusted changes',
+ 'prem-public-logname' => 'Moderation log',
+ 'prem-public-logtext' => 'Log of revisions approving by moderators.',
+ 'prem-private-logname' => 'Private moderation log.',
+ 'prem-private-logtext' => 'Log of private actions (declining, returning
to new queue) on revisions in moderation queue.',
+ 'prem-whitelist-logname' => 'Log of moderation whitelist',
+ 'prem-whitelist-logtext' => 'Log of changes in the moderation
whitelist.',
+ 'prem-log-approve-create' => 'approved creation of page "[[$2]]"',
+ 'prem-log-approve-update' => 'approved revision $3 in page "[[$2]]"',
+ 'prem-log-approve-updateold' => 'approved old revision $3 in page
"[[$2]]"',
+ 'prem-log-status' => 'changed status of revision $2 in moderation queue
to "$3"',
+ 'prem-log-whitelist-add' => 'added IP address "$2" into list',
+ 'prem-log-whitelist-delete' => 'deleted IP address "$2" from list',
+ 'premoderation-diff-h2' => 'Difference between revisions',
+ 'premoderation-internal-conflicts-h2' => 'Conflicts with revisions in
moderation queue',
+ 'premoderation-external-conflicts-h2' => 'Conflicts with published
revisions',
+ 'premoderation-list-new-h2' => 'New revisions',
+ 'premoderation-list-declined-h2' => 'Declined revisions',
+ 'premoderation-manager-mainpage' => 'Moderation queue',
+ 'premoderation-manager-invalidaction' => 'Invalid action',
+ 'premoderation-manager-status' => 'Manage revision status',
+ 'premoderation-added-success-text' => 'Your revision has been
succesfully added to the moderation queue. It will be published or declined by
moderator',
+ 'premoderation-error-externals' => 'Cannot publish this revision: newer
revisions of this page have already been published.',
+ 'premoderation-external-edits' => '\'\'\'Warning!\'\'\' This page has
published revisions newer than this one. You can probably publish it, but not
as current revision, and you must merge it with current revision manually.',
+ 'premoderation-invalidaction' => 'You are trying to perform an invalid
action.',
+ 'premoderation-list-intro' => 'This special page lists new and declined
revisions in the moderation queue. You can review each revision, approve and
publish or decline it. Declined revisions will be completely removed from
database after 3 days of last status change.',
+ 'premoderation-notexists-id' => 'This revision could not be found in
the moderation queue. Probably it has already been published or declined and
deleted from database',
+ 'premoderation-private-ip' => 'IP address:',
+ 'premoderation-success-changed-text' => 'Revision status in moderation
queue has been succesfully changed',
+ 'premoderation-table-list-status' => 'Changing status',
+ 'premoderation-table-list-title' => 'Title and parameters',
+ 'premoderation-table-list-time' => 'Date and time',
+ 'premoderation-table-list-summary' => 'Summary',
+ 'premoderation-table-list-user' => 'User',
+ 'premoderation-table-list-ip' => 'IP address',
+ 'premoderation-table-list-delete' => 'Delete',
+ 'premoderation-status-fieldset' => 'Change status',
+ 'premoderation-status-approved' => 'Approve revision',
+ 'premoderation-status-declined' => 'Decline revision',
+ 'premoderation-status-new' => 'Return to the main moderation queue',
+ 'premoderation-status-approved-changed' => 'approved by moderator $1',
+ 'premoderation-status-declined-changed' => 'declined by moderator $1',
+ 'premoderation-status-new-added' => 'new revision',
+ 'premoderation-status-new-changed' => 'returned to the queue by
moderator $1',
+ 'premoderation-success' => 'Success',
+ 'premoderation-success-approved' => 'Revision has been successfully
approved and published in the wiki',
+ 'premoderation-status-info' => 'Revision info',
+ 'premoderation-status-intro' => 'On this page, you can review revisions
in the moderation queue and manage them if you have sufficient rights',
+ 'remoderationwhitelist' => 'Moderation whitelist',
+ 'premoderation-whitelist-empty' => 'The whitelist is empty',
+ 'premoderation-whitelist-intro' => 'This page lists IP addresses and
subnets that can publish revisions without moderation',
+ 'premoderation-wl-addip-fieldset' => 'Add IP address into list',
+ 'prem-whitelist-added' => 'IP address has been successfully added to
the whitelist.',
+ 'prem-whitelist-deleted' => 'IP address has been successfully deleted
from the whitelist.',
+ 'prem-whitelist-invalid-ip' => 'You\'ve enter invalid IP address.',
+ 'premoderation-edit-conflict' => 'You can\'t edit this page due to the
revision in this page is already in the moderation queue.',
+ 'right-premoderation' => 'revision moderation',
+ 'right-premoderation-log' => 'view private moderation log',
+ 'right-premoderation-viewip' => 'view IP addresses in moderation queue',
+ 'right-premoderation-wlist' => 'view and edit the moderation whitelist',
+ 'right-skipmoderation' => 'bypass moderation',
+ 'abusefilter-action-moderation' => 'Moderation',
+ 'abusefilter-edit-action-moderation' => 'Premoderate this revision',
+ 'abusefilter-moderation' => 'Your revision has been succesfully added
to the moderation queue. It will be published or declined by moderator',
+);
+
+/** Russian (Русский)
+ * @author Cryptocoryne
+ * @author Kalan
+ */
+$messages['ru'] = array(
+ 'premoderation' => 'Премодерация',
+ 'premoderation-desc' => 'Позволяет осуществлять премодерацию
непроверенных правок',
+ 'prem-public-logname' => 'Журнал модерации',
+ 'prem-public-logtext' => 'Журнал подтверждения правок модераторами.',
+ 'prem-private-logname' => 'Закрытый журнал модерации.',
+ 'prem-private-logtext' => 'Журнал закрытых действий (отклонение,
перемещение между очередями), совершаемых с правками в очереди модерации.',
+ 'prem-whitelist-logname' => 'Журнал изменений белого списка',
+ 'prem-whitelist-logtext' => 'Журнал изменений белого списка модерации.',
+ 'prem-log-approve-create' => 'подтвердил создание страницы «[[$2]]»',
+ 'prem-log-approve-update' => 'подтвердил правку $3 на странице
«[[$2]]»',
+ 'prem-log-approve-updateold' => 'подтвердил старую правку $3 на
странице «$2»',
+ 'prem-log-status' => 'изменил статус для правки $2 в очереди модерации
на «$3»',
+ 'prem-log-whitelist-add' => 'добавил IP-адрес «$2» в список',
+ 'prem-log-whitelist-delete' => 'удалил IP-адрес «$2» из списка',
+ 'premoderation-diff-h2' => 'Разность версий',
+ 'premoderation-internal-conflicts-h2' => 'Конфликты с правками в
очереди модерации',
+ 'premoderation-external-conflicts-h2' => 'Конфликты с опубликованными
правками',
+ 'premoderation-list-new-h2' => 'Новые правки',
+ 'premoderation-list-declined-h2' => 'Отклонённые правки',
+ 'premoderation-manager-mainpage' => 'Очередь модерации',
+ 'premoderation-manager-invalidaction' => 'Ошибочное действие',
+ 'premoderation-manager-status' => 'Управление статусом правки',
+ 'premoderation-added-success-text' => 'Ваша правка успешно добавлена в
очередь модерации. После проверки модератором правка попадёт на сайт или будет
отклонена.',
+ 'premoderation-error-externals' => 'В статье были сделаны новые правки,
опубликовать эту правку невозможно.',
+ 'premoderation-external-edits' => '\'\'\'Внимание!\'\'\' В статье есть
опубликованные правки, внесённые после отправки этой правки на модерацию. Вы
можете подтвердить её, однако она будет включена между существующими ревизиями
и потребуется вручную объединить её с последней версией.',
+ 'premoderation-invalidaction' => 'Вы пытаетесь осуществить некорректное
действие.',
+ 'premoderation-list-intro' => 'На этой странице перечислены правки,
ожидающие подтверждения модератора. Вы можете просмотреть детали каждой правки,
подтвердить её (после чего она станет доступна на сайте) или отклонить (после
этого вы всё равно сможете подтвердить её или вернуть в очередь в течение 3
дней).',
+ 'premoderation-notexists-id' => 'Запись в очереди модерации не
существует. Возможно, она уже была обработана и удалена из таблицы модерации.',
+ 'premoderation-private-ip' => 'IP-адрес:',
+ 'premoderation-success-changed-text' => 'Статус правки в очереди
премодерации успешно изменён.',
+ 'premoderation-table-list-status' => 'Изменение статуса',
+ 'premoderation-table-list-title' => 'Название и параметры',
+ 'premoderation-table-list-time' => 'Дата и время',
+ 'premoderation-table-list-summary' => 'Краткое описание правки',
+ 'premoderation-table-list-user' => 'Участник',
+ 'premoderation-table-list-ip' => 'IP-адрес',
+ 'premoderation-table-list-delete' => 'Удалить',
+ 'premoderation-status-fieldset' => 'Изменить статус',
+ 'premoderation-status-approved' => 'Подтвердить правку',
+ 'premoderation-status-declined' => 'Отклонить правку',
+ 'premoderation-status-new' => 'Вернуть в основную очередь модерации',
+ 'premoderation-status-approved-changed' => 'подтверждена модератором
$1',
+ 'premoderation-status-declined-changed' => 'отклонена модератором $1',
+ 'premoderation-status-new-added' => 'новая правка',
+ 'premoderation-status-new-changed' => 'возвращена в очередь модератором
$1',
+ 'premoderation-success' => 'Действие выполнено',
+ 'premoderation-success-approved' => 'Правка успешно подтверждена и
опубликована в вики',
+ 'premoderation-status-info' => 'Информация о правке',
+ 'premoderation-status-intro' => 'При помощи этой страницы вы можете
просмотреть информацию о правке в очереди модерации, а также при наличии
возможности совершить с ней действия.',
+ 'premoderation-whitelist' => 'Белый список премодерации',
+ 'premoderation-whitelist-empty' => 'В настоящее время белый список
пуст.',
+ 'premoderation-whitelist-intro' => 'В этом списке перечислены IP-адреса
и подсети, правки которых публикуются на сайте без прохождения премодерации.',
+ 'premoderation-wl-addip-fieldset' => 'Добавить IP-адрес в список',
+ 'prem-whitelist-added' => 'IP-адрес был успешно добавлен в белый
список.',
+ 'prem-whitelist-deleted' => 'IP-адрес был успешно удалён из белого
списка.',
+ 'prem-whitelist-invalid-ip' => 'Вы ввели некорректный IP-адрес.',
+ 'premoderation-edit-conflict' => 'Вы не можете редактировать эту
страницу, так как связанная с ней правка уже есть в очереди модерации.',
+ 'right-premoderation' => 'модерация правок',
+ 'right-premoderation-log' => 'просмотр закрытого журнала модерации',
+ 'right-premoderation-viewip' => 'просмотр IP-адресов в очереди
модерации',
+ 'right-premoderation-wlist' => 'просмотр и изменение белого списка
модерации',
+ 'right-skipmoderation' => 'внесение правок без премодерации',
+ 'abusefilter-action-moderation' => 'Модерация',
+ 'abusefilter-edit-action-moderation' => 'Отправить правку на
премодерацию',
+ 'abusefilter-moderation' => 'Ваша правка успешно добавлена в очередь
модерации. После проверки модератором правка попадёт на сайт или будет
отклонена.',
+);
\ No newline at end of file
Property changes on: trunk/extensions/Premoderation/Premoderation.i18n.php
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/extensions/Premoderation/Premoderation.php
===================================================================
--- trunk/extensions/Premoderation/Premoderation.php
(rev 0)
+++ trunk/extensions/Premoderation/Premoderation.php 2011-11-06 01:17:04 UTC
(rev 102139)
@@ -0,0 +1,57 @@
+<?php
+if ( !defined( 'MEDIAWIKI' ) ) {
+ die();
+}
+
+$wgExtensionCredits['antispam'][] = array(
+ 'path' => __FILE__,
+ 'name' => 'Premoderation',
+ 'author' => array( 'Cryptocoryne' ),
+ 'descriptionmsg' => 'premoderation-desc',
+ 'version' => '1.0beta',
+ 'url' => 'http://www.mediawiki.org/wiki/Extension:Premoderation',
+);
+
+$dir = dirname( __FILE__ );
+$wgExtensionMessagesFiles['Premoderation'] = "$dir/Premoderation.i18n.php";
+$wgAutoloadClasses['Premoderation'] = "$dir/Premoderation.class.php";
+$wgAutoloadClasses['SpecialPremoderation'] = "$dir/SpecialPremoderation.php";
+$wgAutoloadClasses['SpecialPremoderationWhiteList'] =
"$dir/SpecialPremoderationWhiteList.php";
+
+$wgSpecialPages['Premoderation'] = 'SpecialPremoderation';
+$wgSpecialPages['PremoderationWhiteList'] = 'SpecialPremoderationWhiteList';
+$wgSpecialPageGroups['Premoderation'] = 'wiki';
+$wgSpecialPageGroups['PremoderationWhiteList'] = 'wiki';
+
+$wgAvailableRights[] = 'premoderation';
+$wgAvailableRights[] = 'premoderation-log';
+$wgAvailableRights[] = 'premoderation-viewip';
+$wgAvailableRights[] = 'premoderation-wlist';
+$wgAvailableRights[] = 'skipmoderation';
+
+$wgLogTypes[] = 'prem-public';
+$wgLogTypes[] = 'prem-private';
+$wgLogTypes[] = 'prem-whitelist';
+$wgLogNames['prem-public'] = 'prem-public-logname';
+$wgLogNames['prem-private'] = 'prem-private-logname';
+$wgLogNames['prem-whitelist'] = 'prem-whitelist-logname';
+$wgLogHeaders['prem-public'] = 'prem-public-logtext';
+$wgLogHeaders['prem-private'] = 'prem-private-logtext';
+$wgLogHeaders['prem-whitelist'] = 'prem-whitelist-logtext';
+$wgLogActions['prem-public/create'] = 'prem-log-approve-create';
+$wgLogActions['prem-public/update'] = 'prem-log-approve-update';
+$wgLogActions['prem-public/updateold'] = 'prem-log-approve-updateold';
+$wgLogActions['prem-private/status'] = 'prem-log-status';
+$wgLogActions['prem-whitelist/add'] = 'prem-log-whitelist-add';
+$wgLogActions['prem-whitelist/delete'] = 'prem-log-whitelist-delete';
+$wgLogRestrictions['prem-private'] = 'premoderation-log';
+$wgLogRestrictions['prem-whitelist'] = 'premoderation-wlist';
+
+// 'all' or 'abusefilter'
+$wgPremoderationType = 'all';
+$wgPremoderationStrict = false;
+$wgPremoderationLockPages = false;
+$wgPremoderationDeclinedPurge = 86400 * 3;
+$wgPremoderationNewPurge = 86400 * 14;
+
+$wgExtensionFunctions[] = 'Premoderation::initialize';
\ No newline at end of file
Property changes on: trunk/extensions/Premoderation/Premoderation.php
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/extensions/Premoderation/SpecialPremoderation.php
===================================================================
--- trunk/extensions/Premoderation/SpecialPremoderation.php
(rev 0)
+++ trunk/extensions/Premoderation/SpecialPremoderation.php 2011-11-06
01:17:04 UTC (rev 102139)
@@ -0,0 +1,376 @@
+<?php
+class SpecialPremoderation extends SpecialPage {
+ protected $mParams = false;
+ protected $mPosted = false;
+ protected $mRequest = array();
+ protected $mSummary = '';
+ public $mAllowedStatus = array( 'new', 'approved', 'declined' );
+
+ function __construct() {
+ global $wgRequest;
+ parent::__construct( 'Premoderation', 'premoderation' );
+
+ if( $wgRequest->wasPosted() ) {
+ $this->mPosted = true;
+ $this->mRequest = $wgRequest->getValues();
+ }
+ }
+
+ public function execute( $subpage ) {
+ global $wgUser, $wgOut;
+
+ if( !$wgUser->isAllowed( 'premoderation' ) ) {
+ $this->displayRestrictionError();
+ return;
+ }
+
+ $allowedActions = array( '', 'list', 'status' );
+
+ $params = array_values( explode( '/', $subpage ) );
+ $action = array_shift( &$params );
+
+ if( !in_array( $action, $allowedActions ) ) {
+ $wgOut->setPageTitle( wfMsg(
'premoderation-manager-invalidaction' ) );
+ $wgOut->addWikiMsg( 'premoderation-invalidaction' );
+ return;
+ }
+
+ if( $action == '' ) {
+ $action = 'list';
+ } elseif( isset( $params ) ) {
+ $this->mParams = Premoderation::formatParams( $params );
+ }
+
+ switch( $action ) {
+ case 'list':
+ $this->showList();
+ break;
+
+ case 'status':
+ ( $this->mPosted ) ? $this->performChanges() :
$this->statusInterface();
+ break;
+ }
+ }
+
+ protected function showList() {
+ global $wgOut;
+
+ $wgOut->setPageTitle( wfMsg( 'premoderation-manager-mainpage' )
);
+ $wgOut->addWikiMsg( 'premoderation-list-intro' );
+
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select(
+ 'pm_queue',
+ array( 'pmq_id', 'pmq_page_ns', 'pmq_page_title',
'pmq_user', 'pmq_user_text', 'pmq_timestamp',
+ 'pmq_minor', 'pmq_summary', 'pmq_len',
'pmq_status', 'pmq_updated', 'pmq_updated_user_text' ),
+ '', __METHOD__,
+ array( 'ORDER BY' => 'pmq_timestamp DESC', 'LIMIT' =>
100 )
+ );
+
+ $result = array();
+ while( $row = $dbr->fetchRow( $res ) ) {
+ $status = $row['pmq_status'];
+ $result[$status][] = $row;
+ }
+
+ if( isset( $result['new'] ) ) {
+ $msg = wfMsg( 'premoderation-list-new-h2' );
+ $wgOut->addWikiText( '<h2>' . $msg . '</h2>' );
+
+ $output = $this->getListTableHeader( 'new' );
+ foreach( $result['new'] as $row ) {
+ $output .= $this->formatListTableRow( $row );
+ }
+ $output .= Xml::closeElement( 'table' );
+
+ $wgOut->addHTML( $output );
+ }
+
+ if( isset( $result['declined'] ) ) {
+ $msg = wfMsg( 'premoderation-list-declined-h2' );
+ $wgOut->addWikiText( '<h2>' . $msg . '</h2>' );
+
+ $output = $this->getListTableHeader( 'declined' );
+ foreach( $result['declined'] as $row ) {
+ $output .= $this->formatListTableRow( $row );
+ }
+ $output .= Xml::closeElement( 'table' );
+
+ $wgOut->addHTML( $output );
+ }
+ }
+
+ protected function getListTableHeader( $type ) {
+ return Xml::openElement( 'table', array( 'id' => 'prem-table-'
. $type, 'class' => 'wikitable', 'style' => 'width: 90%' ) ) .
+ '<tr><th>' . wfMsg( 'premoderation-table-list-time' ) .
'</th>' .
+ '<th>' . wfMsg( 'premoderation-table-list-user' ) .
'</th>' .
+ '<th colspan="2">' . wfMsg(
'premoderation-table-list-title' ) . '</th>' .
+ '<th>' . wfMsg( 'premoderation-table-list-summary' ) .
'</th>' .
+ '<th>' . wfMsg( 'premoderation-table-list-status' ) .
'</th><tr>';
+ }
+
+ protected function formatListTableRow( $row ) {
+ global $wgLang, $wgArticlePath;
+
+ $articlePath = str_replace('$1', '', $wgArticlePath);
+ return '<tr><td>' . $wgLang->timeanddate( $row['pmq_timestamp']
) . '</td>' .
+ '<td>' . Linker::userLink( $row['pmq_user'],
$row['pmq_user_text'] ) . '</td>' .
+ '<td>' . Linker::link( Title::newFromText(
$row['pmq_page_title'], $row['pmq_page_ns'] ) ) .
+ '</td><td>' . ( $row['pmq_minor'] == 0 ? '' : ' ' .
wfMsg( 'minoreditletter' ) ) . '</td>' .
+ '<td>' . $row['pmq_summary'] . '</td><td>' . '<a
href="' . $articlePath .
+ 'Special:Premoderation/status/id/' . $row['pmq_id'] .
'">' .
+ wfMessage( 'premoderation-status-' . $row['pmq_status']
. ( $row['pmq_updated_user_text'] ? '-changed' : '-added' ),
+ array( $row['pmq_updated_user_text'] ) ) .
+ '</a></td></tr>';
+ }
+
+ protected function statusInterface() {
+ global $wgOut, $wgUser, $wgPremoderationStrict;
+
+ $params = $this->mParams;
+ if( !isset( $params['id'] ) ) {
+ $wgOut->setPageTitle( wfMsg(
'premoderation-manager-invalidaction' ) );
+ $wgOut->addWikiMsg( 'premoderation-invalidaction' );
+ return;
+ }
+
+ $id = intval( $params['id'] );
+ $dbr = wfGetDB( DB_SLAVE );
+ $res = $dbr->select(
+ 'pm_queue',
+ '*',
+ "pmq_id = '$id'", __METHOD__,
+ array( 'LIMIT' => 1 )
+ );
+ $row = $dbr->fetchRow( $res );
+ if( !$row ) {
+ $wgOut->setPageTitle( wfMsg(
'premoderation-manager-invalidaction' ) );
+ $wgOut->addWikiMsg( 'premoderation-notexists-id' );
+ return;
+ }
+
+ $wgOut->setPageTitle( wfMsg( 'premoderation-manager-status' ) );
+ $wgOut->addWikiMsg( 'premoderation-status-intro' );
+
+ $wgOut->addHTML( '<h2>' . wfMsg( 'premoderation-status-info' )
. '</h2>' .
+ $this->getListTableHeader( 'status' ) .
$this->formatListTableRow( $row ) . Xml::closeElement( 'table' ) );
+
+ if( $wgUser->isAllowed( 'premoderation-viewip' ) ) {
+ $wgOut->addHTML( wfMsg( 'premoderation-private-ip' ) .
' ' . $row['pmq_ip'] );
+ }
+
+ $rev = Revision::newFromID( $row['pmq_page_last_id'] );
+ $diff = new DifferenceEngine( $rev->getTitle() );
+ $diff->showDiffStyle();
+ $formattedDiff = $diff->generateDiffBody( $rev->getText(),
$row['pmq_text'] );
+
+ $wgOut->addHTML( '<h2>' . wfMsg( 'premoderation-diff-h2' ) .
'</h2>' .
+ "<table class='mw-abusefilter-diff-multiline'><col
class='diff-marker' />" .
+ "<col class='diff-content' /><col class='diff-marker'
/><col class='diff-content' />" .
+ "<tbody>" . $formattedDiff . "</tbody></table>" );
+
+ if( $row['pmq_status'] == 'approved' ) {
+ return;
+ }
+
+ $externalConflicts = $this->checkExternalConflicts(
$row['pmq_page_last_id'],
+ $row['pmq_page_ns'], $row['pmq_page_title'] );
+ if( $externalConflicts ) {
+ $wgOut->addHTML( '<h2>' . wfMsg(
'premoderation-external-conflicts-h2' ) . '</h2>' );
+ if( $wgPremoderationStrict ) {
+ $wgOut->addWikiMsg(
'premoderation-error-externals' );
+ return;
+ }
+ $wgOut->addWikiMsg( 'premoderation-external-edits' );
+ }
+
+ $this->checkInternalConflicts( $dbr, $id, $row['pmq_page_ns'],
$row['pmq_page_title'] );
+
+ $final = Xml::fieldset( wfMsg( 'premoderation-status-fieldset'
) ) .
+ Xml::openElement( 'form', array( 'id' =>
'prem-status-form', 'method' => 'post' ) ) .
+ $this->getStatusForm( $row['pmq_status'] ) . '<input
type="hidden" name="id" value="' . $id . '" />' .
+ Xml::closeElement( 'form' ) . Xml::closeElement(
'fieldset' );
+
+ $wgOut->addHTML( $final );
+ }
+
+ protected function checkExternalConflicts( $lastId, $ns, $page ) {
+ global $wgOut;
+
+ $title = Title::newFromText( $page, $ns );
+ return $title->getLatestRevID() > $lastId;
+ }
+
+ protected function checkInternalConflicts( $db, $id, $ns, $page ) {
+ global $wgOut;
+
+ $conds = 'pmq_page_ns = ' . $db->addQuotes( $ns ) . ' AND
pmq_page_title = ' .
+ $db->addQuotes( $page ) . ' AND pmq_id != ' . $id . '
AND pmq_status != "approved"';
+
+ $res = $db->select(
+ 'pm_queue', '*', $conds, __METHOD__,
+ array( 'ORDER BY' => 'pmq_timestamp DESC', 'LIMIT' =>
20 )
+ );
+
+ $test = $db->fetchRow( $res );
+ if( $test ) {
+ $output = '<h2>' . wfMsg(
'premoderation-internal-conflicts-h2' ) . '</h2>' .
+ wfMsg( 'premoderation-internal-conflicts-intro'
) . $this->getListTableHeader( 'int-conflicts' ) .
+ $this->formatListTableRow( $test );
+
+ while( $row = $db->fetchRow( $res ) ) {
+ $output .= $this->formatListTableRow( $row );
+ }
+ $output .= Xml::closeElement( 'table' );
+
+ $wgOut->addHTML( $output );
+ }
+ }
+
+ protected function getStatusForm( $status ) {
+ $statusList = ( $status == 'new' ) ? array( 'approved',
'declined' ) :
+ array( 'new', 'approved' );
+
+ $options = '';
+ foreach( $statusList as $item ) {
+ $options .= Xml::option(
wfMsg("premoderation-status-$item"), $item );
+ }
+
+ return "<table><tr><td><span style='white-space: nowrap'>" .
Xml::tags( 'select',
+ array( 'id' => 'prem-status-selector', 'name' =>
'statusselector' ), $options ) .
+ '</span></td></tr><tr><td>' . wfMsg( 'summary' ) . ' ' .
+ Xml::input( 'summary', 90, '', array( 'id' =>
'prem-summary' ) ) . '</td></tr><tr>' .
+ '<td>' . Xml::submitButton( wfMsg( 'htmlform-submit' ),
array( 'id' => 'prem-submit' ) ) .
+ '</td></tr></table>';
+ }
+
+ protected function performChanges() {
+ global $wgOut;
+
+ $data = $this->mRequest;
+
+ $newstatus = $data['statusselector'];
+ $id = intval( $data['id'] );
+ $this->mSummary = isset( $data['summary'] ) ? $data['summary']
: '';
+
+ if( !in_array( $newstatus, $this->mAllowedStatus ) || !$id ) {
+ $wgOut->setPageTitle( wfMsg(
'premoderation-manager-invalidaction' ) );
+ $wgOut->addWikiMsg( 'premoderation-bad-request' );
+ return;
+ }
+
+ if( $newstatus == 'approved' ) {
+ $ok = $this->approveRevision( $id );
+ $s = $this->changeStatus( $id, $newstatus );
+
+ if( $ok && $s ) {
+ $wgOut->setPageTitle( wfMsg(
'premoderation-success' ) );
+ $wgOut->addWikiMsg(
'premoderation-success-approved' );
+ }
+ } else {
+ $ok = $this->changeStatus( $id, $newstatus );
+
+ if( $ok && $this->addLogEntry( 'status', array( $id,
$newstatus ) ) ) {
+ $wgOut->setPageTitle( wfMsg(
'premoderation-success' ) );
+ $wgOut->addWikiMsg(
'premoderation-success-changed-text' );
+ }
+ }
+ }
+
+ protected function changeStatus( $id, $status ) {
+ global $wgUser;
+
+ $dbw = wfGetDB( DB_MASTER );
+ $query = array(
+ 'pmq_status' => $status,
+ 'pmq_updated' => $dbw->timestamp( wfTimestampNow() ),
+ 'pmq_updated_user' => $wgUser->getID(),
+ 'pmq_updated_user_text' => $wgUser->getName()
+ );
+ $ok = $dbw->update( 'pm_queue', $query, array( 'pmq_id' => $id
), __METHOD__ );
+
+ return $ok;
+ }
+
+ protected function approveRevision( $id ) {
+ $dbw = wfGetDB( DB_MASTER );
+ $res = $dbw->fetchRow( $dbw->select( 'pm_queue', '*', "pmq_id =
'$id'", __METHOD__ ) );
+
+ $title = Title::newFromText( $res['pmq_page_title'],
$res['pmq_page_ns'] );
+ $user = User::newFromName( $res['pmq_user_text'] );
+
+ $row = array(
+ 'page' => 0,
+ 'user' => $user->getID(),
+ 'user_text' => $user->getName(),
+ 'minor_edit' => $res['pmq_minor'],
+ 'timestamp' => $res['pmq_timestamp'],
+ 'comment' => $res['pmq_summary'],
+ 'text' => $res['pmq_text']
+ );
+
+ $rev = new Revision( $row );
+ $revId = $rev->insertOn( $dbw );
+
+ $conflict = $this->checkExternalConflicts(
$res['pmq_page_last_id'],
+ $res['pmq_page_ns'], $res['pmq_page_title'] );
+ if( !$conflict ) {
+ $wikipage = WikiPage::factory( $title );
+
+ if( $res['pmq_page_last_id'] == 0 ) {
+ $pageId = $wikipage->insertOn( $dbw );
+ $cond = array( 'page_id' => $pageId );
+ $actionType = 'create';
+ } else {
+ $wikipage->updateRevisionOn( $dbw, $rev );
+ $cond = array( 'page_latest' =>
$res['pmq_page_last_id'] );
+ $actionType = 'update';
+
+ $dbw->update(
+ 'revision', array( 'rev_page' =>
$title->getArticleID(), 'rev_parent_id' => $title->getLatestRevID() ),
+ array( 'rev_id' => $revId ), __METHOD__
+ );
+ }
+
+ $dbw->update(
+ 'page', array( 'page_latest' => $revId,
'page_len' => $rev->getSize() ),
+ $cond, __METHOD__
+ );
+ } else {
+ $actionType = 'updateold';
+
+ $latestRevId = intval( $title->getLatestRevID() );
+ $res = $dbw->fetchRow( $dbw->select( 'revision',
'rev_parent_id', "rev_id = '$latestRevId'", __METHOD__ ) );
+
+ $dbw->update(
+ 'revision', array( 'rev_page' =>
$title->getArticleID(), 'rev_parent_id' => $res['rev_parent_id'] ),
+ array( 'rev_id' => $revId ), __METHOD__
+ );
+ $dbw->update(
+ 'revision', array( 'rev_parent_id' => $revId ),
+ array( 'rev_id' => $latestRevId ), __METHOD__
+ );
+ }
+
+ if( isset( $pageId ) ) {
+ $dbw->update(
+ 'revision', array( 'rev_page' => $pageId ),
+ array( 'rev_id' => $revId ), __METHOD__
+ );
+ }
+
+ $dbw->commit();
+ $ok = $this->addLogEntry( $actionType, array(
$title->getDBkey(), $revId ), 'public' );
+
+ return $revId && $ok;
+ }
+
+ protected function addLogEntry( $type, $params = array(), $visible =
'private' ) {
+ $log = new LogPage( 'prem-' . $visible );
+
+ $self = $this->getTitle();
+ $ok = $log->addEntry( $type, $self, $this->mSummary, $params );
+
+ return $ok;
+ }
+}
\ No newline at end of file
Property changes on: trunk/extensions/Premoderation/SpecialPremoderation.php
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/extensions/Premoderation/SpecialPremoderationWhiteList.php
===================================================================
--- trunk/extensions/Premoderation/SpecialPremoderationWhiteList.php
(rev 0)
+++ trunk/extensions/Premoderation/SpecialPremoderationWhiteList.php
2011-11-06 01:17:04 UTC (rev 102139)
@@ -0,0 +1,113 @@
+<?php
+class SpecialPremoderationWhiteList extends SpecialPage {
+ protected $mParams = false;
+ protected $mPosted = false;
+ protected $mRequest = array();
+
+ function __construct() {
+ global $wgRequest;
+ parent::__construct( 'PremoderationWhiteList',
'premoderation-wlist' );
+
+ if( $wgRequest->wasPosted() ) {
+ $this->mPosted = true;
+ $this->mRequest = $wgRequest->getValues();
+ }
+ }
+
+ public function execute( $subpage ) {
+ global $wgUser, $wgOut;
+
+ if( !$wgUser->isAllowed( 'premoderation-wlist' ) ) {
+ $this->displayRestrictionError();
+ return;
+ }
+
+ $wgOut->setPageTitle( wfMsg( 'premoderationwhitelist' ) );
+ $wgOut->addWikiMsg( 'premoderation-whitelist-intro' );
+
+ $params = array_values( explode( '/', $subpage ) );
+ $action = array_shift( &$params );
+
+ if( $action == '' ) {
+ $action = 'list';
+ } elseif( $action == 'list' && isset( $params ) ) {
+ $this->mParams = Premoderation::formatParams( $params );
+ } else {
+ $wgOut->setPageTitle( wfMsg(
'premoderation-manager-invalidaction' ) );
+ $wgOut->addWikiMsg( 'premoderation-invalidaction' );
+ return;
+ }
+
+ if( $this->mPosted ) {
+ $msg = $this->updateList();
+ $wgOut->addHTML( '<p class="error">' . wfMsg( $msg ) .
'</p>' );
+ }
+
+ $wgOut->addHTML( $this->getAddForm() );
+
+ $whiteList = Premoderation::loadWhitelist();
+ if( is_array( $whiteList ) ) {
+ $output = '<table class="wikitable"><tr><th>' . wfMsg(
'premoderation-table-list-ip' ) .
+ '</th><th>' . wfMsg(
'premoderation-table-list-delete' ) . '</th></tr>';
+ foreach( $whiteList as $ip ) {
+ $output .= '<tr><td>' . $ip . '</td><td>' .
$this->getDeletionButton( $ip ) . '</td></tr>';
+ }
+ $output .= '</table>';
+ $wgOut->addHTML( $output );
+ } else {
+ $wgOut->addWikiMsg( 'premoderation-whitelist-empty' );
+ }
+ }
+
+ protected function getAddForm() {
+ return Xml::fieldset( wfMsg( 'premoderation-wl-addip-fieldset'
) ) .
+ Xml::openElement( 'form', array( 'id' =>
'prem-wl-form', 'method' => 'post' ) ) . '<table><tr><td>' .
+ wfMsg( 'premoderation-private-ip' ) . '</td><td>' .
Xml::input( 'ip', 50, '', array( 'id' => 'prem-whitelist-addip' ) ) .
+ '</td></tr><tr><td>' . wfMsg( 'summary' ) . '</td><td>'
. Xml::input( 'summary', 50, '',
+ array( 'id' => 'prem-summary' ) ) . '</td></tr><tr>' .
'<td>' . Xml::submitButton( wfMsg( 'htmlform-submit' ),
+ array( 'id' => 'prem-wl-submit' ) ) . '<input
type="hidden" name="action" value="add" />' .
+ '</td></tr></table>' . Xml::closeElement( 'form' ) .
Xml::closeElement( 'fieldset' );
+ }
+
+ protected function getDeletionButton( $ip ) {
+ return Xml::openElement( 'form', array( 'id' =>
'prem-wl-delete' . $ip, 'method' => 'post' ) ) .
+ Xml::submitButton( wfMsg(
'premoderation-table-list-delete' ) ) .
+ '<input type="hidden" name="action" value="delete"
/><input type="hidden" name="ip" value="' . $ip . '" />' .
+ Xml::closeElement( 'form' );
+ }
+
+ protected function updateList() {
+ $ip = $this->mRequest['ip'];
+
+ switch( $this->mRequest['action'] ) {
+ case 'add':
+ if( !IP::isIPAddress( $ip ) ) {
+ return 'prem-whitelist-invalid-ip';
+ }
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->insert( 'pm_whitelist', array( 'pmw_ip'
=> $ip ), __METHOD__ );
+ $this->addLogEntry( $this->mRequest['action'],
array( $ip ) );
+ return 'prem-whitelist-added';
+
+ case 'delete':
+ if( !IP::isIPAddress( $ip ) ) {
+ return 'prem-whitelist-invalid-ip';
+ }
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->delete( 'pm_whitelist', array( 'pmw_ip'
=> $ip ), __METHOD__ );
+ $this->addLogEntry( $this->mRequest['action'],
array( $ip ) );
+ return 'prem-whitelist-deleted';
+
+ default:
+ return 'prem-whitelist-error-action';
+ }
+ }
+
+ protected function addLogEntry( $action, $params ) {
+ $log = new LogPage( 'prem-whitelist' );
+
+ $self = $this->getTitle();
+ $summary = isset( $this->mRequest['summary'] ) ? strval(
$this->mRequest['summary'] ) : '';
+ $log->addEntry( $action, $self, $summary, $params );
+ }
+}
\ No newline at end of file
Property changes on:
trunk/extensions/Premoderation/SpecialPremoderationWhiteList.php
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/extensions/Premoderation/db_tables.sql
===================================================================
--- trunk/extensions/Premoderation/db_tables.sql
(rev 0)
+++ trunk/extensions/Premoderation/db_tables.sql 2011-11-06 01:17:04 UTC
(rev 102139)
@@ -0,0 +1,28 @@
+CREATE TABLE /*$wgDBprefix*/pm_queue (
+ pmq_id BIGINT unsigned NOT NULL AUTO_INCREMENT,
+ pmq_page_last_id INT unsigned NOT NULL,
+ pmq_page_ns INT NOT NULL,
+ pmq_page_title VARCHAR(255) BINARY NOT NULL,
+ pmq_user INT unsigned NOT NULL DEFAULT 0,
+ pmq_user_text VARCHAR(255) BINARY NOT NULL DEFAULT '',
+ pmq_timestamp BINARY(14) NOT NULL DEFAULT '',
+ pmq_minor TINYINT unsigned NOT NULL DEFAULT 0,
+ pmq_summary TINYBLOB NOT NULL,
+ pmq_len INT unsigned,
+ pmq_text MEDIUMBLOB NOT NULL,
+ pmq_flags tinyblob NOT NULL,
+ pmq_ip VARBINARY(40) NOT NULL DEFAULT '',
+ pmq_updated BINARY(14) DEFAULT NULL,
+ pmq_updated_user INT unsigned DEFAULT NULL,
+ pmq_updated_user_text VARCHAR(255) BINARY DEFAULT NULL,
+ pmq_status VARBINARY(40) NOT NULL DEFAULT '',
+
+ PRIMARY KEY (pmq_id),
+ KEY (pmq_user)
+) /*$wgDBTableOptions*/;
+
+CREATE TABLE /*$wgDBprefix*/pm_whitelist (
+ pmw_ip VARBINARY(40) NOT NULL DEFAULT '',
+
+ PRIMARY KEY (pmw_ip)
+) /*$wgDBTableOptions*/;
\ No newline at end of file
Property changes on: trunk/extensions/Premoderation/db_tables.sql
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/extensions/Premoderation/install.php
===================================================================
--- trunk/extensions/Premoderation/install.php (rev 0)
+++ trunk/extensions/Premoderation/install.php 2011-11-06 01:17:04 UTC (rev
102139)
@@ -0,0 +1,10 @@
+<?php
+/*
+ * Script for creating new database tables
+ */
+
+$dir = dirname( __FILE__ );
+require_once ( $dir . '/../../maintenance/commandLine.inc' );
+
+$dbw = wfGetDB( DB_MASTER );
+$dbw->sourceFile( $dir . '/db_tables.sql' );
\ No newline at end of file
Property changes on: trunk/extensions/Premoderation/install.php
___________________________________________________________________
Added: svn:eol-style
+ native
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs