r28051 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r28050‎ | r28051 | r28052 >
Date:14:24, 2 December 2007
Author:catrope
Status:old
Tags:
Comment:
APIEDIT BRANCH MERGE: Adding apiedit modules: action={block,changerights,delete,move,protect,rollback,unblock,undelete} and list={blocks,deletedrevs}. $wgEnableWriteAPI must be explicitly set to enable these modules.
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/api/ApiBlock.php (added) (history)
  • /trunk/phase3/includes/api/ApiChangeRights.php (added) (history)
  • /trunk/phase3/includes/api/ApiDelete.php (added) (history)
  • /trunk/phase3/includes/api/ApiMain.php (modified) (history)
  • /trunk/phase3/includes/api/ApiMove.php (added) (history)
  • /trunk/phase3/includes/api/ApiProtect.php (added) (history)
  • /trunk/phase3/includes/api/ApiQuery.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQueryBlocks.php (added) (history)
  • /trunk/phase3/includes/api/ApiQueryDeletedrevs.php (added) (history)
  • /trunk/phase3/includes/api/ApiRollback.php (added) (history)
  • /trunk/phase3/includes/api/ApiUnblock.php (added) (history)
  • /trunk/phase3/includes/api/ApiUndelete.php (added) (history)

Diff [purge]

Index: trunk/phase3/includes/api/ApiQuery.php
@@ -62,7 +62,9 @@
6363 'alllinks' => 'ApiQueryAllLinks',
6464 'allusers' => 'ApiQueryAllUsers',
6565 'backlinks' => 'ApiQueryBacklinks',
 66+ 'blocks' => 'ApiQueryBlocks',
6667 'categorymembers' => 'ApiQueryCategoryMembers',
 68+ 'deletedrevs' => 'ApiQueryDeletedrevs',
6769 'embeddedin' => 'ApiQueryBacklinks',
6870 'imageusage' => 'ApiQueryBacklinks',
6971 'logevents' => 'ApiQueryLogEvents',
Index: trunk/phase3/includes/api/ApiMove.php
@@ -0,0 +1,182 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Oct 31, 2007
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+
 32+/**
 33+ * @addtogroup API
 34+ */
 35+class ApiMove extends ApiBase {
 36+
 37+ public function __construct($main, $action) {
 38+ parent :: __construct($main, $action);
 39+ }
 40+
 41+ public function execute() {
 42+ global $wgUser;
 43+ $this->requestWriteMode();
 44+ $params = $this->extractRequestParams();
 45+ if(is_null($params['reason']))
 46+ $params['reason'] = '';
 47+
 48+ $titleObj = NULL;
 49+ if(!isset($params['from']))
 50+ $this->dieUsage('The from parameter must be set', 'nofrom');
 51+ if(!isset($params['to']))
 52+ $this->dieUsage('The to parameter must be set', 'noto');
 53+ if(!isset($params['token']))
 54+ $this->dieUsage('The token parameter must be set', 'notoken');
 55+ if(!$wgUser->matchEditToken($params['token']))
 56+ $this->dieUsage('Invalid token', 'badtoken');
 57+
 58+ if($wgUser->isBlocked())
 59+ $this->dieUsage('You have been blocked from editing', 'blocked');
 60+ if(wfReadOnly())
 61+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 62+ if($params['noredirect'] && !$wgUser->isAllowed('suppressredirect'))
 63+ $this->dieUsage("You don't have permission to suppress redirect creation", 'nosuppress');
 64+
 65+ $fromTitle = Title::newFromText($params['from']);
 66+ if(!$fromTitle)
 67+ $this->dieUsage("Bad title ``{$params['from']}''", 'invalidtitle');
 68+ if(!$fromTitle->exists())
 69+ $this->dieUsage("``{$params['from']}'' doesn't exist", 'missingtitle');
 70+ $fromTalk = $fromTitle->getTalkPage();
 71+
 72+
 73+ $toTitle = Title::newFromText($params['to']);
 74+ if(!$toTitle)
 75+ $this->dieUsage("Bad title ``{$params['to']}''", 'invalidtitle');
 76+ $toTalk = $toTitle->getTalkPage();
 77+
 78+ $dbw = wfGetDB(DB_MASTER);
 79+ $dbw->begin();
 80+ $retval = $fromTitle->moveTo($toTitle, true, $params['reason'], !$params['noredirect']);
 81+ if($retval !== true)
 82+ switch($retval)
 83+ {
 84+ // case 'badtitletext': Can't happen
 85+ // case 'badarticleerror': Can't happen
 86+ case 'selfmove':
 87+ $this->dieUsage("Can't move ``{$params['from']}'' to itself", 'selfmove');
 88+ case 'immobile_namespace':
 89+ if($fromTitle->isMovable())
 90+ $this->dieUsage("Pages in the ``{$fromTitle->getNsText()}'' namespace can't be moved", 'immobilenamespace-from');
 91+ $this->dieUsage("Pages in the ``{$toTitle->getNsText()}'' namespace can't be moved", 'immobilenamespace-to');
 92+ case 'articleexists':
 93+ $this->dieUsage("``{$toTitle->getPrefixedText()}'' already exists and is not a redirect to ``{$fromTitle->getPrefixedText()}''", 'targetexists');
 94+ case 'protectedpage':
 95+ $this->dieUsage("You don't have permission to move ``{$fromTitle->getPrefixedText()}'' to ``{$toTitle->getPrefixedText()}''", 'permissiondenied');
 96+ default:
 97+ throw new MWException( "Title::moveTo: Unknown return value ``{$retval}''" );
 98+ }
 99+ $r = array('from' => $fromTitle->getPrefixedText(), 'to' => $toTitle->getPrefixedText(), 'reason' => $params['reason']);
 100+ if(!$params['noredirect'])
 101+ $r['redirectcreated'] = '';
 102+
 103+ if($params['movetalk'] && $fromTalk->exists() && !$fromTitle->isTalkPage())
 104+ {
 105+ // We need to move the talk page as well
 106+ $toTalk = $toTitle->getTalkPage();
 107+ $retval = $fromTalk->moveTo($toTalk, true, $params['reason'], !$params['noredirect']);
 108+ if($retval === true)
 109+ {
 110+ $r['talkfrom'] = $fromTalk->getPrefixedText();
 111+ $r['talkto'] = $toTalk->getPrefixedText();
 112+ }
 113+ // We're not gonna dieUsage() on failure, since we already changed something
 114+ else
 115+ switch($retval)
 116+ {
 117+ case 'immobile_namespace':
 118+ if($fromTalk->isMovable())
 119+ {
 120+ $r['talkmove-error-code'] = 'immobilenamespace-from';
 121+ $r['talkmove-error-info'] = "Pages in the ``{$fromTalk->getNsText()}'' namespace can't be moved";
 122+ }
 123+ else
 124+ {
 125+ $r['talkmove-error-code'] = 'immobilenamespace-to';
 126+ $r['talkmove-error-info'] = "Pages in the ``{$toTalk->getNsText()}'' namespace can't be moved";
 127+ }
 128+ break;
 129+ case 'articleexists':
 130+ $r['talkmove-error-code'] = 'targetexists';
 131+ $r['talkmove-error-info'] = "``{$toTalk->getPrefixedText()}'' already exists and is not a redirect to ``{$fromTalk->getPrefixedText()}''";
 132+ break;
 133+ case 'protectedpage':
 134+ $r['talkmove-error-code'] = 'permissiondenied';
 135+ $r['talkmove-error-info'] = "You don't have permission to move ``{$fromTalk->getPrefixedText()}'' to ``{$toTalk->getPrefixedText()}''";
 136+ default:
 137+ $r['talkmove-error-code'] = 'unknownerror';
 138+ $r['talkmove-error-info'] = "Unknown error ``$retval''";
 139+ }
 140+ }
 141+ $dbw->commit(); // Make sure all changes are really written to the DB
 142+ $this->getResult()->addValue(null, $this->getModuleName(), $r);
 143+ }
 144+
 145+ protected function getAllowedParams() {
 146+ return array (
 147+ 'from' => null,
 148+ 'to' => null,
 149+ 'token' => null,
 150+ 'reason' => null,
 151+ 'movetalk' => false,
 152+ 'noredirect' => false
 153+ );
 154+ }
 155+
 156+ protected function getParamDescription() {
 157+ return array (
 158+ 'from' => 'Title of the page you want to move.',
 159+ 'to' => 'Title you want to rename the page to.',
 160+ 'token' => 'A move token previously retrieved through prop=info',
 161+ 'reason' => 'Reason for the move (optional).',
 162+ 'movetalk' => 'Move the talk page, if it exists.',
 163+ 'noredirect' => 'Don\'t create a redirect'
 164+ );
 165+ }
 166+
 167+ protected function getDescription() {
 168+ return array(
 169+ 'Moves a page.'
 170+ );
 171+ }
 172+
 173+ protected function getExamples() {
 174+ return array (
 175+ 'api.php?action=move&from=Exampel&to=Example&token=123ABC&reason=Misspelled%20title&movetalk&noredirect'
 176+ );
 177+ }
 178+
 179+ public function getVersion() {
 180+ return __CLASS__ . ': $Id$';
 181+ }
 182+}
 183+
Index: trunk/phase3/includes/api/ApiChangeRights.php
@@ -0,0 +1,170 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Sep 11, 2007
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+/**
 32+ * @addtogroup API
 33+ */
 34+class ApiChangeRights extends ApiBase {
 35+
 36+ public function __construct($main, $action) {
 37+ parent :: __construct($main, $action);
 38+ }
 39+
 40+ public function execute() {
 41+ global $wgUser, $wgRequest;
 42+ $this->requestWriteMode();
 43+
 44+ if(wfReadOnly())
 45+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 46+ $params = $this->extractRequestParams();
 47+
 48+ $ur = new UserrightsForm($wgRequest);
 49+ $allowed = $ur->changeableGroups();
 50+ $res = array();
 51+
 52+ if(is_null($params['user']))
 53+ $this->dieUsage('The user parameter must be set', 'nouser');
 54+
 55+ $uName = User::getCanonicalName($params['user']);
 56+ $u = User::newFromName($uName);
 57+ if(!$u)
 58+ $this->dieUsage("Invalid username ``{$params['user']}''", 'invaliduser');
 59+ if($u->getId() == 0) // Anon or non-existent
 60+ $this->dieUsage("User ``{$params['user']}'' doesn't exist", 'nosuchuser');
 61+
 62+ $curgroups = $u->getGroups();
 63+
 64+ if($params['listgroups'])
 65+ {
 66+ $res['user'] = $uName;
 67+ $res['allowedgroups'] = $allowed;
 68+ $res['ingroups'] = $curgroups;
 69+ $this->getResult()->setIndexedTagName($res['ingroups'], 'group');
 70+ $this->getResult()->setIndexedTagName($res['allowedgroups']['add'], 'group');
 71+ $this->getResult()->setIndexedTagName($res['allowedgroups']['remove'], 'group');
 72+ }
 73+;
 74+ if($params['gettoken'])
 75+ {
 76+ $res['changerightstoken'] = $wgUser->editToken($uName);
 77+ $this->getResult()->addValue(null, $this->getModuleName(), $res);
 78+ return;
 79+ }
 80+
 81+ if(empty($params['addto']) && empty($params['rmfrom']))
 82+ $this->dieUsage('At least one of the addto and rmfrom parameters must be set', 'noaddrm');
 83+ if(is_null($params['token']))
 84+ $this->dieUsage('The token parameter must be set', 'notoken');
 85+ if(!$wgUser->matchEditToken($params['token'], $uName))
 86+ $this->dieUsage('Invalid token', 'badtoken');
 87+
 88+ if(!$wgUser->isAllowed('userrights'))
 89+ $this->dieUsage('You don\'t have permission to change users\' rights', 'permissiondenied');
 90+
 91+ // First let's remove redundant groups and check permissions while we're at it
 92+ if(is_null($params['addto']))
 93+ $params['addto'] = array();
 94+ $addto = array();
 95+ foreach($params['addto'] as $g)
 96+ {
 97+ if(!in_array($g, $allowed['add']))
 98+ $this->dieUsage("You don't have permission to add to group ``$g''", 'cantadd');
 99+ if(!in_array($g, $curgroups))
 100+ $addto[] = $g;
 101+ }
 102+
 103+ if(is_null($params['rmfrom']))
 104+ $params['rmfrom'] = array();
 105+ $rmfrom = array();
 106+ foreach($params['rmfrom'] as $g)
 107+ {
 108+ if(!in_array($g, $allowed['remove']))
 109+ $this->dieUsage("You don't have permission to remove from group ``$g''", 'cantremove');
 110+ if(in_array($g, $curgroups))
 111+ $rmfrom[] = $g;
 112+ }
 113+ $dbw = wfGetDb(DB_MASTER);
 114+ $dbw->begin();
 115+ $ur->doSaveUserGroups($u, $rmfrom, $addto, $params['reason']);
 116+ $dbw->commit();
 117+ $res['user'] = $uName;
 118+ $res['addedto'] = $addto;
 119+ $res['removedfrom'] = $rmfrom;
 120+ $res['reason'] = $params['reason'];
 121+
 122+ $this->getResult()->setIndexedTagName($res['addedto'], 'group');
 123+ $this->getResult()->setIndexedTagName($res['removedfrom'], 'group');
 124+ $this->getResult()->addValue(null, $this->getModuleName(), $res);
 125+ }
 126+
 127+ protected function getAllowedParams() {
 128+ return array (
 129+ 'user' => null,
 130+ 'token' => null,
 131+ 'gettoken' => false,
 132+ 'listgroups' => false,
 133+ 'addto' => array(
 134+ ApiBase :: PARAM_ISMULTI => true,
 135+ ),
 136+ 'rmfrom' => array(
 137+ ApiBase :: PARAM_ISMULTI => true,
 138+ ),
 139+ 'reason' => ''
 140+ );
 141+ }
 142+
 143+ protected function getParamDescription() {
 144+ return array (
 145+ 'user' => 'The user you want to add to or remove from groups.',
 146+ 'token' => 'A changerights token previously obtained through the gettoken parameter.',
 147+ 'gettoken' => 'Output a token. Note that the user parameter still has to be set.',
 148+ 'listgroups' => 'List the groups the user is in, and the ones you can add them to and remove them from.',
 149+ 'addto' => 'Pipe-separated list of groups to add this user to',
 150+ 'rmfrom' => 'Pipe-separated list of groups to remove this user from',
 151+ 'reason' => 'Reason for change (optional)'
 152+ );
 153+ }
 154+
 155+ protected function getDescription() {
 156+ return array(
 157+ 'Add or remove a user from certain groups.'
 158+ );
 159+ }
 160+
 161+ protected function getExamples() {
 162+ return array (
 163+ 'api.php?action=changerights&user=Bob&gettoken&listgroups',
 164+ 'api.php?action=changerights&user=Bob&token=123ABC&addto=sysop&reason=Promoting%20per%20RFA'
 165+ );
 166+ }
 167+
 168+ public function getVersion() {
 169+ return __CLASS__ . ': $Id$';
 170+ }
 171+}
Index: trunk/phase3/includes/api/ApiProtect.php
@@ -0,0 +1,142 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Sep 1, 2007
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+/**
 32+ * @addtogroup API
 33+ */
 34+class ApiProtect extends ApiBase {
 35+
 36+ public function __construct($main, $action) {
 37+ parent :: __construct($main, $action);
 38+ }
 39+
 40+ public function execute() {
 41+ global $wgUser;
 42+ $this->requestWriteMode();
 43+ $params = $this->extractRequestParams();
 44+
 45+ $titleObj = NULL;
 46+ if(!isset($params['title']))
 47+ $this->dieUsage('The title parameter must be set', 'notitle');
 48+ if(!isset($params['token']))
 49+ $this->dieUsage('The token parameter must be set', 'notoken');
 50+ if(!isset($params['protections']) || empty($params['protections']))
 51+ $this->dieUsage('The protections parameter must be set', 'noprotections');
 52+
 53+ if($wgUser->isBlocked())
 54+ $this->dieUsage('You have been blocked from editing', 'blocked');
 55+ if(wfReadOnly())
 56+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 57+ if(!$wgUser->matchEditToken($params['token']))
 58+ $this->dieUsage('Invalid token', 'badtoken');
 59+
 60+ $titleObj = Title::newFromText($params['title']);
 61+ if(!$titleObj)
 62+ $this->dieUsage("Bad title ``{$params['title']}''", 'invalidtitle');
 63+ if(!$titleObj->exists())
 64+ $this->dieUsage("``{$params['title']}'' doesn't exist", 'missingtitle');
 65+ if(!$titleObj->userCan('protect'))
 66+ $this->dieUsage('You don\'t have permission to change protection levels', 'permissiondenied');
 67+ $articleObj = new Article($titleObj);
 68+
 69+ if(in_array($params['expiry'], array('infinite', 'indefinite', 'never')))
 70+ $expiry = Block::infinity();
 71+ else
 72+ {
 73+ $expiry = strtotime($params['expiry']);
 74+ if($expiry < 0 || $expiry == false)
 75+ $this->dieUsage('Invalid expiry time', 'invalidexpiry');
 76+
 77+ $expiry = wfTimestamp(TS_MW, $expiry);
 78+ if($expiry < wfTimestampNow())
 79+ $this->dieUsage('Expiry time is in the past', 'pastexpiry');
 80+ }
 81+
 82+ $protections = array();
 83+ foreach($params['protections'] as $prot)
 84+ {
 85+ $p = explode('=', $prot);
 86+ $protections[$p[0]] = ($p[1] == 'all' ? '' : $p[1]);
 87+ }
 88+
 89+ $dbw = wfGetDb(DB_MASTER);
 90+ $dbw->begin();
 91+ $ok = $articleObj->updateRestrictions($protections, $params['reason'], $params['cascade'], $expiry);
 92+ if(!$ok)
 93+ // This is very weird. Maybe the article was deleted or the user was blocked/desysopped in the meantime?
 94+ $this->dieUsage('Unknown error', 'unknownerror');
 95+ $dbw->commit();
 96+ $res = array('title' => $titleObj->getPrefixedText(), 'reason' => $params['reason'], 'expiry' => $expiry);
 97+ if($params['cascade'])
 98+ $res['cascade'] = '';
 99+ $res['protections'] = $protections;
 100+ $this->getResult()->addValue(null, $this->getModuleName(), $res);
 101+ }
 102+
 103+ protected function getAllowedParams() {
 104+ return array (
 105+ 'title' => null,
 106+ 'token' => null,
 107+ 'protections' => array(
 108+ ApiBase :: PARAM_ISMULTI => true
 109+ ),
 110+ 'expiry' => 'infinite',
 111+ 'reason' => '',
 112+ 'cascade' => false
 113+ );
 114+ }
 115+
 116+ protected function getParamDescription() {
 117+ return array (
 118+ 'title' => 'Title of the page you want to restore.',
 119+ 'token' => 'A protect token previously retrieved through prop=info',
 120+ 'protections' => 'Pipe-separated list of protection levels, formatted action=group (e.g. edit=sysop)',
 121+ 'expiry' => 'Expiry timestamp. If set to \'infinite\', \'indefinite\' or \'never\', the protection will never expire.',
 122+ 'reason' => 'Reason for (un)protecting (optional)',
 123+ 'cascade' => 'Enable cascading protection (i.e. protect pages included in this page)'
 124+ );
 125+ }
 126+
 127+ protected function getDescription() {
 128+ return array(
 129+ 'Change the protection level of a page.'
 130+ );
 131+ }
 132+
 133+ protected function getExamples() {
 134+ return array (
 135+ 'api.php?action=protect&title=Main%20Page&token=123ABC&protections=edit=sysop|move=sysop&cascade&expiry=20070901163000',
 136+ 'api.php?action=protect&title=Main%20Page&token=123ABC&protections=edit=all|move=all&reason=Lifting%20restrictions'
 137+ );
 138+ }
 139+
 140+ public function getVersion() {
 141+ return __CLASS__ . ': $Id$';
 142+ }
 143+}
Index: trunk/phase3/includes/api/ApiMain.php
@@ -57,6 +57,14 @@
5858 'expandtemplates' => 'ApiExpandTemplates',
5959 'render' => 'ApiRender',
6060 'parse' => 'ApiParse',
 61+ 'rollback' => 'ApiRollback',
 62+ 'delete' => 'ApiDelete',
 63+ 'undelete' => 'ApiUndelete',
 64+ 'protect' => 'ApiProtect',
 65+ 'block' => 'ApiBlock',
 66+ 'unblock' => 'ApiUnblock',
 67+ 'changerights' => 'ApiChangeRights',
 68+ 'move' => 'ApiMove',
6169 'opensearch' => 'ApiOpenSearch',
6270 'feedwatchlist' => 'ApiFeedWatchlist',
6371 'help' => 'ApiHelp',
Index: trunk/phase3/includes/api/ApiRollback.php
@@ -0,0 +1,156 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Jun 20, 2007
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+/**
 32+ * @addtogroup API
 33+ */
 34+class ApiRollback extends ApiBase {
 35+
 36+ public function __construct($main, $action) {
 37+ parent :: __construct($main, $action);
 38+ }
 39+
 40+ public function execute() {
 41+ global $wgUser;
 42+ $this->requestWriteMode();
 43+ $params = $this->extractRequestParams();
 44+
 45+ $titleObj = NULL;
 46+ if(!isset($params['title']))
 47+ $this->dieUsage('The title parameter must be set', 'notitle');
 48+ if(!isset($params['user']))
 49+ $this->dieUsage('The user parameter must be set', 'nouser');
 50+ if(!isset($params['token']))
 51+ $this->dieUsage('The token parameter must be set', 'notoken');
 52+
 53+ // doRollback() also checks for these, but we wanna save some work
 54+ if($wgUser->isBlocked())
 55+ $this->dieUsage('You have been blocked from editing', 'blocked');
 56+ if(wfReadOnly())
 57+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 58+
 59+ $titleObj = Title::newFromText($params['title']);
 60+ if(!$titleObj)
 61+ $this->dieUsage("Bad title ``{$params['title']}''", 'invalidtitle');
 62+ if(!$titleObj->userCan('rollback'))
 63+ $this->dieUsage('You don\'t have permission to rollback', 'permissiondenied');
 64+
 65+ $username = User::getCanonicalName($params['user']);
 66+ if(!$username)
 67+ $this->dieUsage("Invalid username ``{$params['user']}''", 'invaliduser');
 68+
 69+ $articleObj = new Article($titleObj);
 70+ $summary = (isset($params['summary']) ? $params['summary'] : "");
 71+ $details = NULL;
 72+ $dbw = wfGetDb(DB_MASTER);
 73+ $dbw->begin();
 74+ $retval = $articleObj->doRollback($username, $summary, $params['token'], $params['markbot'], &$details);
 75+
 76+ switch($retval)
 77+ {
 78+ case Article::SUCCESS:
 79+ break; // We'll deal with that later
 80+ case Article::PERM_DENIED:
 81+ $this->dieUsage("You don't have permission to rollback", 'permissiondenied');
 82+ case Article::BLOCKED: // If we get BLOCKED or PERM_DENIED that's very weird, but it's possible
 83+ $this->dieUsage('You have been blocked from editing', 'blocked');
 84+ case Article::READONLY:
 85+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 86+ case Article::BAD_TOKEN:
 87+ $this->dieUsage('Invalid token', 'badtoken');
 88+ case Article::BAD_TITLE:
 89+ $this->dieUsage("``{$params['title']}'' doesn't exist", 'missingtitle');
 90+ case Article::ALREADYROLLED:
 91+ $current = $details['current'];
 92+ $currentID = $current->getId();
 93+ $this->dieUsage("The edit(s) you tried to rollback is/are already rolled back." .
 94+ "The current revision ID is ``$currentID''", 'alreadyrolled');
 95+ case Article::ONLY_AUTHOR:
 96+ $this->dieUsage("User ``$username'' is the only author of the page", 'onlyauthor');
 97+ case Article::RATE_LIMITED:
 98+ $this->dieUsage("You can't rollback too many articles in too short a time. Please wait a little while and try again", 'ratelimited');
 99+ default:
 100+ // rollback() has apparently invented a new error, which is extremely weird
 101+ $this->dieDebug(__METHOD__, "rollback() returned an unknown error ($retval)");
 102+ }
 103+ // $retval has to be Article::SUCCESS if we get here
 104+ $dbw->commit();
 105+ $current = $target = $summary = NULL;
 106+ extract($details);
 107+
 108+ $info = array(
 109+ 'title' => $titleObj->getPrefixedText(),
 110+ 'pageid' => $current->getPage(),
 111+ 'summary' => $summary,
 112+ 'revid' => $titleObj->getLatestRevID(),
 113+ 'old_revid' => $current->getID(),
 114+ 'last_revid' => $target->getID()
 115+ );
 116+
 117+ $this->getResult()->addValue(null, $this->getModuleName(), $info);
 118+ }
 119+
 120+ protected function getAllowedParams() {
 121+ return array (
 122+ 'title' => null,
 123+ 'user' => null,
 124+ 'token' => null,
 125+ 'summary' => null,
 126+ 'markbot' => false
 127+ );
 128+ }
 129+
 130+ protected function getParamDescription() {
 131+ return array (
 132+ 'title' => 'Title of the page you want to rollback.',
 133+ 'user' => 'Name of the user whose edits are to be rolled back. If set incorrectly, you\'ll get a badtoken error.',
 134+ 'token' => 'A rollback token previously retrieved through prop=info',
 135+ 'summary' => 'Custom edit summary. If not set, default summary will be used.',
 136+ 'markbot' => 'Mark the reverted edits and the revert as bot edits'
 137+ );
 138+ }
 139+
 140+ protected function getDescription() {
 141+ return array(
 142+ 'Undoes the last edit to the page. If the last user who edited the page made multiple edits in a row,',
 143+ 'they will all be rolled back. You need to be logged in as a sysop to use this function, see also action=login.'
 144+ );
 145+ }
 146+
 147+ protected function getExamples() {
 148+ return array (
 149+ 'api.php?action=rollback&title=Main%20Page&user=Catrope&token=123ABC',
 150+ 'api.php?action=rollback&title=Main%20Page&user=217.121.114.116&token=123ABC&summary=Reverting%20vandalism&markbot=1'
 151+ );
 152+ }
 153+
 154+ public function getVersion() {
 155+ return __CLASS__ . ': $Id: ApiRollback.php 22289 2007-05-20 23:31:44Z yurik $';
 156+ }
 157+}
Index: trunk/phase3/includes/api/ApiBlock.php
@@ -0,0 +1,164 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Sep 4, 2007
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+/**
 32+ * @addtogroup API
 33+ */
 34+class ApiBlock extends ApiBase {
 35+
 36+ public function __construct($main, $action) {
 37+ parent :: __construct($main, $action);
 38+ }
 39+
 40+ public function execute() {
 41+ global $wgUser;
 42+ $this->requestWriteMode();
 43+ $params = $this->extractRequestParams();
 44+
 45+ if($params['gettoken'])
 46+ {
 47+ $res['blocktoken'] = $wgUser->editToken();
 48+ $this->getResult()->addValue(null, $this->getModuleName(), $res);
 49+ return;
 50+ }
 51+
 52+ if(is_null($params['user']))
 53+ $this->dieUsage('The user parameter must be set', 'nouser');
 54+ if(is_null($params['token']))
 55+ $this->dieUsage('The token parameter must be set', 'notoken');
 56+ if(!$wgUser->matchEditToken($params['token']))
 57+ $this->dieUsage('Invalid token', 'badtoken');
 58+ if(!$wgUser->isAllowed('block'))
 59+ $this->dieUsage('You don\'t have permission to block users', 'permissiondenied');
 60+ if($params['hidename'] && !$wgUser->isAllowed('hideuser'))
 61+ $this->dieUsage('You don\'t have permission to hide user names from the block log', 'nohide');
 62+ if(wfReadOnly())
 63+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 64+
 65+ $form = new IPBlockForm('');
 66+ $form->BlockAddress = $params['user'];
 67+ $form->BlockReason = $params['reason'];
 68+ $form->BlockReasonList = 'other';
 69+ $form->BlockExpiry = ($params['expiry'] == 'never' ? 'infinite' : $params['expiry']);
 70+ $form->BlockOther = '';
 71+ $form->BlockAnonOnly = $params['anononly'];
 72+ $form->BlockCreateAccount = $params['nocreate'];
 73+ $form->BlockEnableAutoBlock = $params['autoblock'];
 74+ $form->BlockEmail = $params['noemail'];
 75+ $form->BlockHideName = $params['hidename'];
 76+
 77+ $dbw = wfGetDb(DB_MASTER);
 78+ $dbw->begin();
 79+ $retval = $form->doBlock($userID, $expiry);
 80+ switch($retval)
 81+ {
 82+ case IPBlockForm::BLOCK_SUCCESS:
 83+ break; // We'll deal with that later
 84+ case IPBlockForm::BLOCK_RANGE_INVALID:
 85+ $this->dieUsage("Invalid IP range ``{$params['user']}''", 'invalidrange');
 86+ case IPBlockForm::BLOCK_RANGE_DISABLED:
 87+ $this->dieUsage('Blocking IP ranges has been disabled', 'rangedisabled');
 88+ case IPBlockForm::BLOCK_NONEXISTENT_USER:
 89+ $this->dieUsage("User ``{$params['user']}'' doesn't exist", 'nosuchuser');
 90+ case IPBlockForm::BLOCK_IP_INVALID:
 91+ $this->dieUsage("Invaild IP address ``{$params['user']}''", 'invalidip');
 92+ case IPBlockForm::BLOCK_EXPIRY_INVALID:
 93+ $this->dieUsage("Invalid expiry time ``{$params['expiry']}''", 'invalidexpiry');
 94+ case IPBlockForm::BLOCK_ALREADY_BLOCKED:
 95+ $this->dieUsage("User ``{$params['user']}'' is already blocked", 'alreadyblocked');
 96+ default:
 97+ $this->dieDebug(__METHOD__, "IPBlockForm::doBlock() returned an unknown error ($retval)");
 98+ }
 99+ $dbw->commit();
 100+
 101+ $res['user'] = $params['user'];
 102+ $res['userID'] = $userID;
 103+ $res['expiry'] = ($expiry == Block::infinity() ? 'infinite' : $expiry);
 104+ $res['reason'] = $params['reason'];
 105+ if($params['anononly'])
 106+ $res['anononly'] = '';
 107+ if($params['nocreate'])
 108+ $res['nocreate'] = '';
 109+ if($params['autoblock'])
 110+ $res['autoblock'] = '';
 111+ if($params['noemail'])
 112+ $res['noemail'] = '';
 113+ if($params['hidename'])
 114+ $res['hidename'] = '';
 115+
 116+ $this->getResult()->addValue(null, $this->getModuleName(), $res);
 117+ }
 118+
 119+ protected function getAllowedParams() {
 120+ return array (
 121+ 'user' => null,
 122+ 'token' => null,
 123+ 'gettoken' => false,
 124+ 'expiry' => 'never',
 125+ 'reason' => null,
 126+ 'anononly' => false,
 127+ 'nocreate' => false,
 128+ 'autoblock' => false,
 129+ 'noemail' => false,
 130+ 'hidename' => false,
 131+ );
 132+ }
 133+
 134+ protected function getParamDescription() {
 135+ return array (
 136+ 'user' => 'Username, IP address or IP range you want to block',
 137+ 'token' => 'A block token previously obtained through the gettoken parameter',
 138+ 'gettoken' => 'If set, a block token will be returned, and no other action will be taken',
 139+ 'expiry' => 'Relative expiry time, e.g. \'5 months\' or \'2 weeks\'. If set to \'infinite\', \'indefinite\' or \'never\', the block will never expire.',
 140+ 'reason' => 'Reason for block (optional)',
 141+ 'anononly' => 'Block anonymous users only (i.e. disable anonymous edits for this IP)',
 142+ 'nocreate' => 'Prevent account creation',
 143+ 'autoblock' => 'Automatically block the last used IP address, and any subsequent IP addresses they try to login from',
 144+ 'noemail' => 'Prevent user from sending e-mail through the wiki',
 145+ 'hidename' => 'Hide the username from the block log.'
 146+ );
 147+ }
 148+
 149+ protected function getDescription() {
 150+ return array(
 151+ 'Block a user.'
 152+ );
 153+ }
 154+
 155+ protected function getExamples() {
 156+ return array (
 157+ 'api.php?action=block&user=123.5.5.12&expiry=3%20days&reason=First%20strike',
 158+ 'api.php?action=block&user=Vandal&expiry=never&reason=Vandalism&nocreate&autoblock&noemail'
 159+ );
 160+ }
 161+
 162+ public function getVersion() {
 163+ return __CLASS__ . ': $Id$';
 164+ }
 165+}
Index: trunk/phase3/includes/api/ApiQueryDeletedrevs.php
@@ -0,0 +1,232 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Jul 2, 2007
 6+ *
 7+ * API for MediaWiki 1.8+
 8+ *
 9+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 10+ *
 11+ * This program is free software; you can redistribute it and/or modify
 12+ * it under the terms of the GNU General Public License as published by
 13+ * the Free Software Foundation; either version 2 of the License, or
 14+ * (at your option) any later version.
 15+ *
 16+ * This program is distributed in the hope that it will be useful,
 17+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 19+ * GNU General Public License for more details.
 20+ *
 21+ * You should have received a copy of the GNU General Public License along
 22+ * with this program; if not, write to the Free Software Foundation, Inc.,
 23+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 24+ * http://www.gnu.org/copyleft/gpl.html
 25+ */
 26+
 27+if (!defined('MEDIAWIKI')) {
 28+ // Eclipse helper - will be ignored in production
 29+ require_once ('ApiQueryBase.php');
 30+}
 31+
 32+/**
 33+ * Query module to enumerate all available pages.
 34+ *
 35+ * @addtogroup API
 36+ */
 37+class ApiQueryDeletedrevs extends ApiQueryBase {
 38+
 39+ public function __construct($query, $moduleName) {
 40+ parent :: __construct($query, $moduleName, 'dr');
 41+ }
 42+
 43+ public function execute() {
 44+ $this->run();
 45+ }
 46+
 47+ private function run() {
 48+
 49+ global $wgUser;
 50+ // Before doing anything at all, let's check permissions
 51+ if(!$wgUser->isAllowed('deletedhistory'))
 52+ $this->dieUsage('You don\'t have permission to view deleted revisions', 'permissiondenied');
 53+
 54+ $db = $this->getDB();
 55+ $params = $this->extractRequestParams();
 56+ $prop = array_flip($params['prop']);
 57+ $fld_revid = isset($prop['revid']);
 58+ $fld_user = isset($prop['user']);
 59+ $fld_comment = isset($prop['comment']);
 60+ $fld_minor = isset($prop['minor']);
 61+ $fld_len = isset($prop['len']);
 62+ $fld_content = isset($prop['content']);
 63+ $fld_token = isset($prop['token']);
 64+
 65+ $result = $this->getResult();
 66+ $pageSet = $this->getPageSet();
 67+ $titles = $pageSet->getTitles();
 68+ $data = array();
 69+
 70+ $this->addTables('archive');
 71+ $this->addFields(array('ar_title', 'ar_namespace', 'ar_timestamp'));
 72+ if($fld_revid)
 73+ $this->addFields('ar_rev_id');
 74+ if($fld_user)
 75+ $this->addFields('ar_user_text');
 76+ if($fld_comment)
 77+ $this->addFields('ar_comment');
 78+ if($fld_minor)
 79+ $this->addFields('ar_minor_edit');
 80+ if($fld_len)
 81+ $this->addFields('ar_len');
 82+ if($fld_content)
 83+ {
 84+ $this->addTables('text');
 85+ $this->addFields(array('ar_text', 'ar_text_id', 'old_text', 'old_flags'));
 86+ $this->addWhere('ar_text_id = old_id');
 87+
 88+ // This also means stricter limits
 89+ $userMax = 50;
 90+ $botMax = 200;
 91+ $this->validateLimit('limit', $params['limit'], 1, $userMax, $botMax);
 92+ }
 93+ if($fld_token)
 94+ // Undelete tokens are identical for all pages, so we cache one here
 95+ $token = $wgUser->editToken();
 96+
 97+ // We need a custom WHERE clause that matches all titles.
 98+ if(count($titles) > 0)
 99+ {
 100+ $lb = new LinkBatch($titles);
 101+ $where = $lb->constructSet('ar', $db);
 102+ $this->addWhere($where);
 103+ }
 104+
 105+ $this->addOption('LIMIT', $params['limit'] + 1);
 106+ $this->addWhereRange('ar_timestamp', $params['dir'], $params['start'], $params['end']);
 107+ if(isset($params['namespace']))
 108+ $this->addWhereFld('ar_namespace', $params['namespace']);
 109+ $res = $this->select(__METHOD__);
 110+ $pages = array();
 111+ $count = 0;
 112+ // First populate the $pages array
 113+ while($row = $db->fetchObject($res))
 114+ {
 115+ if($count++ == $params['limit'])
 116+ {
 117+ // We've had enough
 118+ $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->ar_timestamp));
 119+ break;
 120+ }
 121+
 122+ $rev = array();
 123+ $rev['timestamp'] = wfTimestamp(TS_ISO_8601, $row->ar_timestamp);
 124+ if($fld_revid)
 125+ $rev['revid'] = $row->ar_rev_id;
 126+ if($fld_user)
 127+ $rev['user'] = $row->ar_user_text;
 128+ if($fld_comment)
 129+ $rev['comment'] = $row->ar_comment;
 130+ if($fld_minor)
 131+ if($row->ar_minor_edit == 1)
 132+ $rev['minor'] = '';
 133+ if($fld_len)
 134+ $rev['len'] = $row->ar_len;
 135+ if($fld_content)
 136+ ApiResult::setContent($rev, Revision::getRevisionText($row));
 137+
 138+ $t = Title::makeTitle($row->ar_namespace, $row->ar_title);
 139+ if(!isset($pages[$t->getPrefixedText()]))
 140+ {
 141+ $pages[$t->getPrefixedText()] = array(
 142+ 'title' => $t->getPrefixedText(),
 143+ 'ns' => intval($row->ar_namespace),
 144+ 'revisions' => array($rev)
 145+ );
 146+ if($fld_token)
 147+ $pages[$t->getPrefixedText()]['token'] = $token;
 148+ }
 149+ else
 150+ $pages[$t->getPrefixedText()]['revisions'][] = $rev;
 151+ }
 152+ $db->freeResult($res);
 153+
 154+ // We don't want entire pagenames as keys, so let's make this array indexed
 155+ foreach($pages as $page)
 156+ {
 157+ $result->setIndexedTagName($page['revisions'], 'rev');
 158+ $data[] = $page;
 159+ }
 160+ $result->setIndexedTagName($data, 'page');
 161+ $result->addValue('query', $this->getModuleName(), $data);
 162+ }
 163+
 164+ protected function getAllowedParams() {
 165+ return array (
 166+ 'start' => array(
 167+ ApiBase :: PARAM_TYPE => 'timestamp'
 168+ ),
 169+ 'end' => array(
 170+ ApiBase :: PARAM_TYPE => 'timestamp',
 171+ ),
 172+ 'dir' => array(
 173+ ApiBase :: PARAM_TYPE => array(
 174+ 'newer',
 175+ 'older'
 176+ ),
 177+ ApiBase :: PARAM_DFLT => 'older'
 178+ ),
 179+ 'namespace' => array(
 180+ ApiBase :: PARAM_ISMULTI => true,
 181+ ApiBase :: PARAM_TYPE => 'namespace'
 182+ ),
 183+ 'limit' => array(
 184+ ApiBase :: PARAM_DFLT => 10,
 185+ ApiBase :: PARAM_TYPE => 'limit',
 186+ ApiBase :: PARAM_MIN => 1,
 187+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
 188+ ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
 189+ ),
 190+ 'prop' => array(
 191+ ApiBase :: PARAM_DFLT => 'user|comment',
 192+ ApiBase :: PARAM_TYPE => array(
 193+ 'revid',
 194+ 'user',
 195+ 'comment',
 196+ 'minor',
 197+ 'len',
 198+ 'content',
 199+ 'token'
 200+ ),
 201+ ApiBase :: PARAM_ISMULTI => true
 202+ )
 203+ );
 204+ }
 205+
 206+ protected function getParamDescription() {
 207+ return array (
 208+ 'start' => 'The timestamp to start enumerating from',
 209+ 'end' => 'The timestamp to stop enumerating at',
 210+ 'dir' => 'The direction in which to enumerate',
 211+ 'namespace' => 'The namespaces to search in',
 212+ 'limit' => 'The maximum amount of revisions to list',
 213+ 'prop' => 'Which properties to get'
 214+ );
 215+ }
 216+
 217+ protected function getDescription() {
 218+ return 'List deleted revisions.';
 219+ }
 220+
 221+ protected function getExamples() {
 222+ return array (
 223+ 'List the first 50 deleted revisions in the Category and Category talk namespaces',
 224+ ' api.php?action=query&list=deletedrevs&drdir=newer&drlimit=50&drnamespace=14|15',
 225+ 'List the last deleted revisions of Main Page and Talk:Main Page, with content:',
 226+ ' api.php?action=query&list=deletedrevs&titles=Main%20Page|Talk:Main%20Page&drprop=user|comment|content'
 227+ );
 228+ }
 229+
 230+ public function getVersion() {
 231+ return __CLASS__ . ': $Id: ApiQueryDeletedrevs.php 23531 2007-06-30 01:19:14Z simetrical $';
 232+ }
 233+}
Index: trunk/phase3/includes/api/ApiDelete.php
@@ -0,0 +1,172 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Jun 30, 2007
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+
 32+/**
 33+ * @addtogroup API
 34+ */
 35+class ApiDelete extends ApiBase {
 36+
 37+ public function __construct($main, $action) {
 38+ parent :: __construct($main, $action);
 39+ }
 40+
 41+ /**
 42+ * We have our own delete() function, since Article.php's implementation is split in two phases
 43+ * @param Article $article - Article object to work on
 44+ * @param string $token - Delete token (same as edit token)
 45+ * @param string $reason - Reason for the deletion. Autogenerated if NULL
 46+ * @return DELETE_SUCCESS on success, DELETE_* on failure
 47+ */
 48+
 49+ const DELETE_SUCCESS = 0;
 50+ const DELETE_PERM = 1;
 51+ const DELETE_BLOCKED = 2;
 52+ const DELETE_READONLY = 3;
 53+ const DELETE_BADTOKEN = 4;
 54+ const DELETE_BADARTICLE = 5;
 55+
 56+ public static function delete(&$article, $token, &$reason = NULL)
 57+ {
 58+ global $wgUser;
 59+
 60+ // Check permissions first
 61+ if(!$article->mTitle->userCan('delete'))
 62+ return self::DELETE_PERM;
 63+ if($wgUser->isBlocked())
 64+ return self::DELETE_BLOCKED;
 65+ if(wfReadOnly())
 66+ return self::DELETE_READONLY;
 67+
 68+ // Check token
 69+ if(!$wgUser->matchEditToken($token))
 70+ return self::DELETE_BADTOKEN;
 71+
 72+ // Auto-generate a summary, if necessary
 73+ if(is_null($reason))
 74+ {
 75+ $reason = $article->generateReason($hasHistory);
 76+ if($reason === false)
 77+ return self::DELETE_BADARTICLE;
 78+ }
 79+
 80+ // Luckily, Article.php provides a reusable delete function that does the hard work for us
 81+ if($article->doDeleteArticle($reason))
 82+ return self::DELETE_SUCCESS;
 83+ return self::DELETE_BADARTICLE;
 84+ }
 85+
 86+ public function execute() {
 87+ global $wgUser;
 88+ $this->requestWriteMode();
 89+ $params = $this->extractRequestParams();
 90+
 91+ $titleObj = NULL;
 92+ if(!isset($params['title']))
 93+ $this->dieUsage('The title parameter must be set', 'notitle');
 94+ if(!isset($params['token']))
 95+ $this->dieUsage('The token parameter must be set', 'notoken');
 96+
 97+ // delete() also checks for these, but we wanna save some work
 98+ if(!$wgUser->isAllowed('delete'))
 99+ $this->dieUsage('You don\'t have permission to delete pages', 'permissiondenied');
 100+ if($wgUser->isBlocked())
 101+ $this->dieUsage('You have been blocked from editing', 'blocked');
 102+ if(wfReadOnly())
 103+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 104+
 105+ $titleObj = Title::newFromText($params['title']);
 106+ if(!$titleObj)
 107+ $this->dieUsage("Bad title ``{$params['title']}''", 'invalidtitle');
 108+ if(!$titleObj->exists())
 109+ $this->dieUsage("``{$params['title']}'' doesn't exist", 'missingtitle');
 110+
 111+ $articleObj = new Article($titleObj);
 112+ $reason = (isset($params['reason']) ? $params['reason'] : NULL);
 113+ $dbw = wfGetDb(DB_MASTER);
 114+ $dbw->begin();
 115+ $retval = self::delete(&$articleObj, $params['token'], &$reason);
 116+
 117+ switch($retval)
 118+ {
 119+ case self::DELETE_SUCCESS:
 120+ break; // We'll deal with that later
 121+ case self::DELETE_PERM: // If we get PERM, BLOCKED or READONLY that's weird, but it's possible
 122+ $this->dieUsage('You don\'t have permission to delete', 'permissiondenied');
 123+ case self::DELETE_BLOCKED:
 124+ $this->dieUsage('You have been blocked from editing', 'blocked');
 125+ case self::DELETE_READONLY:
 126+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 127+ case self::DELETE_BADTOKEN:
 128+ $this->dieUsage('Invalid token', 'badtoken');
 129+ case self::DELETE_BADARTICLE:
 130+ $this->dieUsage("The article ``{$params['title']}'' doesn't exist or has already been deleted", 'missingtitle');
 131+ default:
 132+ // delete() has apparently invented a new error, which is extremely weird
 133+ $this->dieDebug(__METHOD__, "delete() returned an unknown error ($retval)");
 134+ }
 135+ // $retval has to be self::DELETE_SUCCESS if we get here
 136+ $dbw->commit();
 137+ $r = array('title' => $titleObj->getPrefixedText(), 'reason' => $reason);
 138+ $this->getResult()->addValue(null, $this->getModuleName(), $r);
 139+ }
 140+
 141+ protected function getAllowedParams() {
 142+ return array (
 143+ 'title' => null,
 144+ 'token' => null,
 145+ 'reason' => null,
 146+ );
 147+ }
 148+
 149+ protected function getParamDescription() {
 150+ return array (
 151+ 'title' => 'Title of the page you want to delete.',
 152+ 'token' => 'A delete token previously retrieved through prop=info',
 153+ 'reason' => 'Reason for the deletion. If not set, an automatically generated reason will be used.'
 154+ );
 155+ }
 156+
 157+ protected function getDescription() {
 158+ return array(
 159+ 'Deletes a page. You need to be logged in as a sysop to use this function, see also action=login.'
 160+ );
 161+ }
 162+
 163+ protected function getExamples() {
 164+ return array (
 165+ 'api.php?action=delete&title=Main%20Page&token=123ABC',
 166+ 'api.php?action=delete&title=Main%20Page&token=123ABC&reason=Preparing%20for%20move'
 167+ );
 168+ }
 169+
 170+ public function getVersion() {
 171+ return __CLASS__ . ': $Id: ApiDelete.php 22289 2007-05-20 23:31:44Z yurik $';
 172+ }
 173+}
Index: trunk/phase3/includes/api/ApiQueryBlocks.php
@@ -0,0 +1,241 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Sep 10, 2007
 6+ *
 7+ * API for MediaWiki 1.8+
 8+ *
 9+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 10+ *
 11+ * This program is free software; you can redistribute it and/or modify
 12+ * it under the terms of the GNU General Public License as published by
 13+ * the Free Software Foundation; either version 2 of the License, or
 14+ * (at your option) any later version.
 15+ *
 16+ * This program is distributed in the hope that it will be useful,
 17+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 19+ * GNU General Public License for more details.
 20+ *
 21+ * You should have received a copy of the GNU General Public License along
 22+ * with this program; if not, write to the Free Software Foundation, Inc.,
 23+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 24+ * http://www.gnu.org/copyleft/gpl.html
 25+ */
 26+
 27+if (!defined('MEDIAWIKI')) {
 28+ // Eclipse helper - will be ignored in production
 29+ require_once ('ApiQueryBase.php');
 30+}
 31+
 32+/**
 33+ * Query module to enumerate all available pages.
 34+ *
 35+ * @addtogroup API
 36+ */
 37+class ApiQueryBlocks extends ApiQueryBase {
 38+
 39+ public function __construct($query, $moduleName) {
 40+ parent :: __construct($query, $moduleName, 'bk');
 41+ }
 42+
 43+ public function execute() {
 44+ $this->run();
 45+ }
 46+
 47+ private function run() {
 48+ global $wgUser;
 49+
 50+ $params = $this->extractRequestParams();
 51+ $prop = array_flip($params['prop']);
 52+ $fld_id = isset($prop['id']);
 53+ $fld_user = isset($prop['user']);
 54+ $fld_by = isset($prop['by']);
 55+ $fld_timestamp = isset($prop['timestamp']);
 56+ $fld_expiry = isset($prop['expiry']);
 57+ $fld_reason = isset($prop['reason']);
 58+ $fld_range = isset($prop['range']);
 59+ $fld_flags = isset($prop['flags']);
 60+
 61+ $result = $this->getResult();
 62+ $pageSet = $this->getPageSet();
 63+ $titles = $pageSet->getTitles();
 64+ $data = array();
 65+
 66+ $this->addTables('ipblocks');
 67+ if($fld_id)
 68+ $this->addFields('ipb_id');
 69+ if($fld_user)
 70+ $this->addFields(array('ipb_address', 'ipb_user'));
 71+ if($fld_by)
 72+ {
 73+ $this->addTables('user');
 74+ $this->addFields(array('ipb_by', 'user_name'));
 75+ $this->addWhere('user_id = ipb_by');
 76+ }
 77+ if($fld_timestamp)
 78+ $this->addFields('ipb_timestamp');
 79+ if($fld_expiry)
 80+ $this->addFields('ipb_expiry');
 81+ if($fld_reason)
 82+ $this->addFields('ipb_reason');
 83+ if($fld_range)
 84+ $this->addFields(array('ipb_range_start', 'ipb_range_end'));
 85+ if($fld_flags)
 86+ $this->addFields(array('ipb_auto', 'ipb_anon_only', 'ipb_create_account', 'ipb_enable_autoblock', 'ipb_block_email', 'ipb_deleted'));
 87+
 88+ $this->addOption('LIMIT', $params['limit'] + 1);
 89+ $this->addWhereRange('ipb_timestamp', $params['dir'], $params['start'], $params['end']);
 90+ if(isset($params['ids']))
 91+ $this->addWhere(array('ipb_id' => $params['ids']));
 92+ if(isset($params['users']))
 93+ $this->addWhere(array('ipb_address' => $params['users']));
 94+ if(!$wgUser->isAllowed('oversight'))
 95+ $this->addWhere(array('ipb_deleted' => 0));
 96+
 97+ // Purge expired entries on one in every 10 queries
 98+ if(!mt_rand(0, 10))
 99+ Block::purgeExpired();
 100+
 101+ $res = $this->select(__METHOD__);
 102+ $db = wfGetDB();
 103+
 104+ $count = 0;
 105+ while($row = $db->fetchObject($res))
 106+ {
 107+ if($count++ == $params['limit'])
 108+ {
 109+ // We've had enough
 110+ $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->ipb_timestamp));
 111+ break;
 112+ }
 113+ $block = array();
 114+ if($fld_id)
 115+ $block['id'] = $row->ipb_id;
 116+ if($fld_user)
 117+ {
 118+ $block['user'] = $row->ipb_address;
 119+ $block['userid'] = $row->ipb_user;
 120+ }
 121+ if($fld_by)
 122+ {
 123+ $block['by'] = $row->user_name;
 124+ $block['byuserid'] = $row->ipb_by;
 125+ }
 126+ if($fld_timestamp)
 127+ $block['timestamp'] = wfTimestamp(TS_ISO_8601, $row->ipb_timestamp);
 128+ if($fld_expiry)
 129+ $block['expiry'] = Block::decodeExpiry($row->ipb_expiry, TS_ISO_8601);
 130+ if($fld_reason)
 131+ $block['reason'] = $row->ipb_reason;
 132+ if($fld_range)
 133+ {
 134+ $block['rangestart'] = $this->convertHexIP($row->ipb_range_start);
 135+ $block['rangeend'] = $this->convertHexIP($row->ipb_range_end);
 136+ }
 137+ if($fld_flags)
 138+ {
 139+ // For clarity, these flags use the same names as their action=block counterparts
 140+ if($row->ipb_auto)
 141+ $block['automatic'] = '';
 142+ if($row->ipb_anon_only)
 143+ $block['anononly'] = '';
 144+ if($row->ipb_create_account)
 145+ $block['nocreate'] = '';
 146+ if($row->ipb_enable_autoblock)
 147+ $block['autoblock'] = '';
 148+ if($row->ipb_block_email)
 149+ $block['noemail'] = '';
 150+ if($row->ipb_deleted)
 151+ $block['hidden'] = '';
 152+ }
 153+ $data[] = $block;
 154+ }
 155+ $result->setIndexedTagName($data, 'block');
 156+ $result->addValue('query', $this->getModuleName(), $data);
 157+ }
 158+
 159+ protected function convertHexIP($ip)
 160+ {
 161+ // Converts a hexadecimal IP to nnn.nnn.nnn.nnn format
 162+ $dec = wfBaseConvert($ip, 16, 10);
 163+ $parts[0] = (int)($dec / (256*256*256));
 164+ $dec %= 256*256*256;
 165+ $parts[1] = (int)($dec / (256*256));
 166+ $dec %= 256*256;
 167+ $parts[2] = (int)($dec / 256);
 168+ $parts[3] = $dec % 256;
 169+ return implode('.', $parts);
 170+ }
 171+
 172+ protected function getAllowedParams() {
 173+ return array (
 174+ 'start' => array(
 175+ ApiBase :: PARAM_TYPE => 'timestamp'
 176+ ),
 177+ 'end' => array(
 178+ ApiBase :: PARAM_TYPE => 'timestamp',
 179+ ),
 180+ 'dir' => array(
 181+ ApiBase :: PARAM_TYPE => array(
 182+ 'newer',
 183+ 'older'
 184+ ),
 185+ ApiBase :: PARAM_DFLT => 'older'
 186+ ),
 187+ 'ids' => array(
 188+ ApiBase :: PARAM_TYPE => 'integer',
 189+ ApiBase :: PARAM_ISMULTI => true
 190+ ),
 191+ 'users' => array(
 192+ ApiBase :: PARAM_ISMULTI => true
 193+ ),
 194+ 'limit' => array(
 195+ ApiBase :: PARAM_DFLT => 10,
 196+ ApiBase :: PARAM_TYPE => 'limit',
 197+ ApiBase :: PARAM_MIN => 1,
 198+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
 199+ ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
 200+ ),
 201+ 'prop' => array(
 202+ ApiBase :: PARAM_DFLT => 'id|user|by|timestamp|expiry|reason|flags',
 203+ ApiBase :: PARAM_TYPE => array(
 204+ 'id',
 205+ 'user',
 206+ 'by',
 207+ 'timestamp',
 208+ 'expiry',
 209+ 'reason',
 210+ 'range',
 211+ 'flags'
 212+ ),
 213+ ApiBase :: PARAM_ISMULTI => true
 214+ )
 215+ );
 216+ }
 217+
 218+ protected function getParamDescription() {
 219+ return array (
 220+ 'start' => 'The timestamp to start enumerating from',
 221+ 'end' => 'The timestamp to stop enumerating at',
 222+ 'dir' => 'The direction in which to enumerate',
 223+ 'ids' => 'Pipe-separated list of block IDs to list (optional)',
 224+ 'users' => 'Pipe-separated list of users to search for (optional)',
 225+ 'limit' => 'The maximum amount of blocks to list',
 226+ 'prop' => 'Which properties to get',
 227+ );
 228+ }
 229+
 230+ protected function getDescription() {
 231+ return 'List all blocked users and IP addresses.';
 232+ }
 233+
 234+ protected function getExamples() {
 235+ return array (
 236+ );
 237+ }
 238+
 239+ public function getVersion() {
 240+ return __CLASS__ . ': $Id$';
 241+ }
 242+}
Index: trunk/phase3/includes/api/ApiUndelete.php
@@ -0,0 +1,129 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Jul 3, 2007
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+/**
 32+ * @addtogroup API
 33+ */
 34+class ApiUndelete extends ApiBase {
 35+
 36+ public function __construct($main, $action) {
 37+ parent :: __construct($main, $action);
 38+ }
 39+
 40+ public function execute() {
 41+ global $wgUser;
 42+ $this->requestWriteMode();
 43+ $params = $this->extractRequestParams();
 44+
 45+ $titleObj = NULL;
 46+ if(!isset($params['title']))
 47+ $this->dieUsage('The title parameter must be set', 'notitle');
 48+ if(!isset($params['token']))
 49+ $this->dieUsage('The token parameter must be set', 'notoken');
 50+
 51+ if(!$wgUser->isAllowed('delete'))
 52+ $this->dieUsage('You don\'t have permission to restore deleted revisions', 'permissiondenied');
 53+ if($wgUser->isBlocked())
 54+ $this->dieUsage('You have been blocked from editing', 'blocked');
 55+ if(wfReadOnly())
 56+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 57+ if(!$wgUser->matchEditToken($params['token']))
 58+ $this->dieUsage('Invalid token', 'badtoken');
 59+
 60+ $titleObj = Title::newFromText($params['title']);
 61+ if(!$titleObj)
 62+ $this->dieUsage("Bad title ``{$params['title']}''", 'invalidtitle');
 63+
 64+ // Convert timestamps
 65+ if(!is_array($params['timestamps']))
 66+ $params['timestamps'] = array($params['timestamps']);
 67+ foreach($params['timestamps'] as $i => $ts)
 68+ $params['timestamps'][$i] = wfTimestamp(TS_MW, $ts);
 69+
 70+ $pa = new PageArchive($titleObj);
 71+ $dbw = wfGetDb(DB_MASTER);
 72+ $dbw->begin();
 73+ $retval = $pa->undelete((isset($params['timestamps']) ? $params['timestamps'] : array()), $params['reason']);
 74+ if(!is_array($retval))
 75+ switch($retval)
 76+ {
 77+ case PageArchive::UNDELETE_NOTHINGRESTORED:
 78+ $this->dieUsage('No revisions could be restored', 'norevs');
 79+ case PageArchive::UNDELETE_NOTAVAIL:
 80+ $this->dieUsage('Not all requested revisions could be found', 'revsnotfound');
 81+ case PageArchive::UNDELETE_UNKNOWNERR:
 82+ $this->dieUsage('Undeletion failed with unknown error', 'unknownerror');
 83+ }
 84+ $dbw->commit();
 85+
 86+ $info['title'] = $titleObj->getPrefixedText();
 87+ $info['revisions'] = $retval[0];
 88+ $info['fileversions'] = $retval[1];
 89+ $info['reason'] = $retval[2];
 90+ $this->getResult()->addValue(null, $this->getModuleName(), $info);
 91+ }
 92+
 93+ protected function getAllowedParams() {
 94+ return array (
 95+ 'title' => null,
 96+ 'token' => null,
 97+ 'reason' => "",
 98+ 'timestamps' => array(
 99+ ApiBase :: PARAM_ISMULTI => true
 100+ )
 101+ );
 102+ }
 103+
 104+ protected function getParamDescription() {
 105+ return array (
 106+ 'title' => 'Title of the page you want to restore.',
 107+ 'token' => 'An undelete token previously retrieved through list=deletedrevs',
 108+ 'reason' => 'Reason for restoring (optional)',
 109+ 'timestamps' => 'Timestamps of the revisions to restore. If not set, all revisions will be restored.'
 110+ );
 111+ }
 112+
 113+ protected function getDescription() {
 114+ return array(
 115+ 'Restore certain revisions of a deleted page. A list of deleted revisions (including timestamps) can be',
 116+ 'retrieved through list=deletedrevs'
 117+ );
 118+ }
 119+
 120+ protected function getExamples() {
 121+ return array (
 122+ 'api.php?action=undelete&title=Main%20Page&token=123ABC&reason=Restoring%20main%20page',
 123+ 'api.php?action=undelete&title=Main%20Page&token=123ABC&timestamps=20070703220045|20070702194856'
 124+ );
 125+ }
 126+
 127+ public function getVersion() {
 128+ return __CLASS__ . ': $Id: ApiUndelete.php 22289 2007-05-20 23:31:44Z yurik $';
 129+ }
 130+}
Index: trunk/phase3/includes/api/ApiUnblock.php
@@ -0,0 +1,130 @@
 2+<?php
 3+
 4+/*
 5+ * Created on Sep 7, 2007
 6+ * API for MediaWiki 1.8+
 7+ *
 8+ * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+if (!defined('MEDIAWIKI')) {
 27+ // Eclipse helper - will be ignored in production
 28+ require_once ("ApiBase.php");
 29+}
 30+
 31+/**
 32+ * @addtogroup API
 33+ */
 34+class ApiUnblock extends ApiBase {
 35+
 36+ public function __construct($main, $action) {
 37+ parent :: __construct($main, $action);
 38+ }
 39+
 40+ public function execute() {
 41+ global $wgUser;
 42+ $this->requestWriteMode();
 43+ $params = $this->extractRequestParams();
 44+
 45+ if($params['gettoken'])
 46+ {
 47+ $res['unblocktoken'] = $wgUser->editToken();
 48+ $this->getResult()->addValue(null, $this->getModuleName(), $res);
 49+ return;
 50+ }
 51+
 52+ if(is_null($params['id']) && is_null($params['user']))
 53+ $this->dieUsage('Either the id or the user parameter must be set', 'notarget');
 54+ if(!is_null($params['id']) && !is_null($params['user']))
 55+ $this->dieUsage('The id and user parameters can\'t be used together', 'idanduser');
 56+ if(is_null($params['token']))
 57+ $this->dieUsage('The token parameter must be set', 'notoken');
 58+ if(!$wgUser->matchEditToken($params['token']))
 59+ $this->dieUsage('Invalid token', 'badtoken');
 60+ if(!$wgUser->isAllowed('block'))
 61+ $this->dieUsage('You don\'t have permission to unblock users', 'permissiondenied');
 62+ if(wfReadOnly())
 63+ $this->dieUsage('The wiki is in read-only mode', 'readonly');
 64+
 65+ $id = $params['id'];
 66+ $user = $params['user'];
 67+ $reason = $params['reason'];
 68+ $dbw = wfGetDb(DB_MASTER);
 69+ $dbw->begin();
 70+ $retval = IPUnblockForm::doUnblock(&$id, &$user, &$reason, &$range);
 71+
 72+ switch($retval)
 73+ {
 74+ case IPUnblockForm::UNBLOCK_SUCCESS:
 75+ break; // We'll deal with that later
 76+ case IPUnblockForm::UNBLOCK_NO_SUCH_ID:
 77+ $this->dieUsage("There is no block with ID ``$id''", 'nosuchid');
 78+ case IPUnblockForm::UNBLOCK_USER_NOT_BLOCKED:
 79+ $this->dieUsage("User ``$user'' is not blocked", 'notblocked');
 80+ case IPUnblockForm::UNBLOCK_BLOCKED_AS_RANGE:
 81+ $this->dieUsage("IP address ``$user'' was blocked as part of range ``$range''. You can't unblock the IP invidually, but you can unblock the range as a whole.", 'blockedasrange');
 82+ case IPUnblockForm::UNBLOCK_UNKNOWNERR:
 83+ $this->dieUsage("Unknown error", 'unknownerr');
 84+ default:
 85+ $this->dieDebug(__METHOD__, "IPBlockForm::doBlock() returned an unknown error ($retval)");
 86+ }
 87+ $dbw->commit();
 88+
 89+ $res['id'] = $id;
 90+ $res['user'] = $user;
 91+ $res['reason'] = $reason;
 92+ $this->getResult()->addValue(null, $this->getModuleName(), $res);
 93+ }
 94+
 95+ protected function getAllowedParams() {
 96+ return array (
 97+ 'id' => null,
 98+ 'user' => null,
 99+ 'token' => null,
 100+ 'gettoken' => false,
 101+ 'reason' => null,
 102+ );
 103+ }
 104+
 105+ protected function getParamDescription() {
 106+ return array (
 107+ 'id' => 'ID of the block you want to unblock (obtained through list=blocks). Cannot be user together with user',
 108+ 'user' => 'Username, IP address or IP range you want to unblock. Cannot be used together with id',
 109+ 'token' => 'An unblock token previously obtained through the gettoken parameter',
 110+ 'gettoken' => 'If set, an unblock token will be returned, and no other action will be taken',
 111+ 'reason' => 'Reason for unblock (optional)',
 112+ );
 113+ }
 114+
 115+ protected function getDescription() {
 116+ return array(
 117+ 'Unblock a user.'
 118+ );
 119+ }
 120+
 121+ protected function getExamples() {
 122+ return array (
 123+ 'api.php?action=unblock&id=105',
 124+ 'api.php?action=unblock&user=Bob&reason=Sorry%20Bob'
 125+ );
 126+ }
 127+
 128+ public function getVersion() {
 129+ return __CLASS__ . ': $Id$';
 130+ }
 131+}
Index: trunk/phase3/includes/AutoLoader.php
@@ -344,6 +344,18 @@
345345 'ApiQueryWatchlist' => 'includes/api/ApiQueryWatchlist.php',
346346 'ApiRender' => 'includes/api/ApiRender.php',
347347 'ApiResult' => 'includes/api/ApiResult.php',
 348+
 349+ # apiedit branch
 350+ 'ApiBlock' => 'includes/api/ApiBlock.php',
 351+ 'ApiChangeRights' => 'includes/api/ApiChangeRights.php',
 352+ 'ApiDelete' => 'includes/api/ApiDelete.php',
 353+ 'ApiMove' => 'includes/api/ApiMove.php',
 354+ 'ApiProtect' => 'includes/api/ApiProtect.php',
 355+ 'ApiQueryBlocks' => 'includes/api/ApiQueryBlocks.php',
 356+ 'ApiQueryDeletedrevs' => 'includes/api/ApiQueryDeletedrevs.php',
 357+ 'ApiRollback' => 'includes/api/ApiRollback.php',
 358+ 'ApiUnblock' => 'includes/api/ApiUnblock.php',
 359+ 'ApiUndelete' => 'includes/api/ApiUndelete.php'
348360 );
349361
350362 wfProfileIn( __METHOD__ );
Index: trunk/phase3/RELEASE-NOTES
@@ -315,6 +315,7 @@
316316 * Add rvtoken=rollback to prop=revisions
317317 * Add meta=allmessages to get messages from site's messages cache.
318318 * Use bold and italics highlighting only in API help
 319+* Added action={block,changerights,delete,move,protect,rollback,unblock,undelete} and list={blocks,deletedrevs}\
319320
320321 === Languages updated in 1.12 ===
321322

Status & tagging log