00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 if (!defined('MEDIAWIKI')) {
00027
00028 require_once ('ApiQueryBase.php');
00029 }
00030
00036 class ApiQueryDeletedrevs extends ApiQueryBase {
00037
00038 public function __construct($query, $moduleName) {
00039 parent :: __construct($query, $moduleName, 'dr');
00040 }
00041
00042 public function execute() {
00043
00044 global $wgUser;
00045
00046 if(!$wgUser->isAllowed('deletedhistory'))
00047 $this->dieUsage('You don\'t have permission to view deleted revision information', 'permissiondenied');
00048
00049 $db = $this->getDB();
00050 $params = $this->extractRequestParams(false);
00051 $prop = array_flip($params['prop']);
00052 $fld_revid = isset($prop['revid']);
00053 $fld_user = isset($prop['user']);
00054 $fld_comment = isset($prop['comment']);
00055 $fld_minor = isset($prop['minor']);
00056 $fld_len = isset($prop['len']);
00057 $fld_content = isset($prop['content']);
00058 $fld_token = isset($prop['token']);
00059
00060 $result = $this->getResult();
00061 $pageSet = $this->getPageSet();
00062 $titles = $pageSet->getTitles();
00063 $data = array();
00064
00065
00066
00067
00068
00069 $mode = 'all';
00070 if(count($titles) > 0)
00071 $mode = 'revs';
00072 else if(!is_null($params['user']))
00073 $mode = 'user';
00074
00075 if(!is_null($params['user']) && !is_null($params['excludeuser']))
00076 $this->dieUsage('user and excludeuser cannot be used together', 'badparams');
00077
00078 $this->addTables('archive');
00079 $this->addWhere('ar_deleted = 0');
00080 $this->addFields(array('ar_title', 'ar_namespace', 'ar_timestamp'));
00081 if($fld_revid)
00082 $this->addFields('ar_rev_id');
00083 if($fld_user)
00084 $this->addFields('ar_user_text');
00085 if($fld_comment)
00086 $this->addFields('ar_comment');
00087 if($fld_minor)
00088 $this->addFields('ar_minor_edit');
00089 if($fld_len)
00090 $this->addFields('ar_len');
00091 if($fld_content)
00092 {
00093 $this->addTables('text');
00094 $this->addFields(array('ar_text', 'ar_text_id', 'old_text', 'old_flags'));
00095 $this->addWhere('ar_text_id = old_id');
00096
00097
00098 if(!$wgUser->isAllowed('undelete'))
00099 $this->dieUsage('You don\'t have permission to view deleted revision content', 'permissiondenied');
00100 }
00101
00102 $userMax = $fld_content ? ApiBase :: LIMIT_SML1 : ApiBase :: LIMIT_BIG1;
00103 $botMax = $fld_content ? ApiBase :: LIMIT_SML2 : ApiBase :: LIMIT_BIG2;
00104
00105 $limit = $params['limit'];
00106
00107 if( $limit == 'max' ) {
00108 $limit = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
00109 $this->getResult()->addValue( 'limits', $this->getModuleName(), $limit );
00110 }
00111
00112 $this->validateLimit('limit', $limit, 1, $userMax, $botMax);
00113
00114 if($fld_token)
00115
00116 $token = $wgUser->editToken();
00117
00118
00119 if($mode == 'revs')
00120 {
00121 $lb = new LinkBatch($titles);
00122 $where = $lb->constructSet('ar', $db);
00123 $this->addWhere($where);
00124 }
00125 elseif($mode == 'all')
00126 {
00127 $this->addWhereFld('ar_namespace', $params['namespace']);
00128 if(!is_null($params['from']))
00129 {
00130 $from = $this->getDB()->strencode($this->titleToKey($params['from']));
00131 $this->addWhere("ar_title >= '$from'");
00132 }
00133 }
00134
00135 if(!is_null($params['user'])) {
00136 $this->addWhereFld('ar_user_text', $params['user']);
00137 } elseif(!is_null($params['excludeuser'])) {
00138 $this->addWhere('ar_user_text != ' .
00139 $this->getDB()->addQuotes($params['excludeuser']));
00140 }
00141
00142 if(!is_null($params['continue']) && ($mode == 'all' || $mode == 'revs'))
00143 {
00144 $cont = explode('|', $params['continue']);
00145 if(count($cont) != 3)
00146 $this->dieUsage("Invalid continue param. You should pass the original value returned by the previous query", "badcontinue");
00147 $ns = intval($cont[0]);
00148 $title = $this->getDB()->strencode($this->titleToKey($cont[1]));
00149 $ts = $this->getDB()->strencode($cont[2]);
00150 $op = ($params['dir'] == 'newer' ? '>' : '<');
00151 $this->addWhere("ar_namespace $op $ns OR " .
00152 "(ar_namespace = $ns AND " .
00153 "(ar_title $op '$title' OR " .
00154 "(ar_title = '$title' AND " .
00155 "ar_timestamp = '$ts')))");
00156 }
00157
00158 $this->addOption('LIMIT', $limit + 1);
00159 $this->addOption('USE INDEX', array('archive' => ($mode == 'user' ? 'usertext_timestamp' : 'name_title_timestamp')));
00160 if($mode == 'all')
00161 {
00162 if($params['unique'])
00163 {
00164 $this->addOption('GROUP BY', 'ar_title');
00165 $this->addOption('ORDER BY', 'ar_title');
00166 }
00167 else
00168 $this->addOption('ORDER BY', 'ar_title, ar_timestamp');
00169 }
00170 else
00171 {
00172 if($mode == 'revs')
00173 {
00174
00175 $this->addWhereRange('ar_namespace', $params['dir'], null, null);
00176 $this->addWhereRange('ar_title', $params['dir'], null, null);
00177 }
00178 $this->addWhereRange('ar_timestamp', $params['dir'], $params['start'], $params['end']);
00179 }
00180 $res = $this->select(__METHOD__);
00181 $pageMap = array();
00182 $count = 0;
00183 $newPageID = 0;
00184 while($row = $db->fetchObject($res))
00185 {
00186 if(++$count > $limit)
00187 {
00188
00189 if($mode == 'all' || $mode == 'revs')
00190 $this->setContinueEnumParameter('continue', intval($row->ar_namespace) . '|' .
00191 $this->keyToTitle($row->ar_title) . '|' . $row->ar_timestamp);
00192 else
00193 $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->ar_timestamp));
00194 break;
00195 }
00196
00197 $rev = array();
00198 $rev['timestamp'] = wfTimestamp(TS_ISO_8601, $row->ar_timestamp);
00199 if($fld_revid)
00200 $rev['revid'] = intval($row->ar_rev_id);
00201 if($fld_user)
00202 $rev['user'] = $row->ar_user_text;
00203 if($fld_comment)
00204 $rev['comment'] = $row->ar_comment;
00205 if($fld_minor)
00206 if($row->ar_minor_edit == 1)
00207 $rev['minor'] = '';
00208 if($fld_len)
00209 $rev['len'] = $row->ar_len;
00210 if($fld_content)
00211 ApiResult::setContent($rev, Revision::getRevisionText($row));
00212
00213 if(!isset($pageMap[$row->ar_namespace][$row->ar_title]))
00214 {
00215 $pageID = $newPageID++;
00216 $pageMap[$row->ar_namespace][$row->ar_title] = $pageID;
00217 $t = Title::makeTitle($row->ar_namespace, $row->ar_title);
00218 $a['revisions'] = array($rev);
00219 $result->setIndexedTagName($a['revisions'], 'rev');
00220 ApiQueryBase::addTitleInfo($a, $t);
00221 if($fld_token)
00222 $a['token'] = $token;
00223 $fit = $result->addValue(array('query', $this->getModuleName()), $pageID, $a);
00224 }
00225 else
00226 {
00227 $pageID = $pageMap[$row->ar_namespace][$row->ar_title];
00228 $fit = $result->addValue(
00229 array('query', $this->getModuleName(), $pageID, 'revisions'),
00230 null, $rev);
00231 }
00232 if(!$fit)
00233 {
00234 if($mode == 'all' || $mode == 'revs')
00235 $this->setContinueEnumParameter('continue', intval($row->ar_namespace) . '|' .
00236 $this->keyToTitle($row->ar_title) . '|' . $row->ar_timestamp);
00237 else
00238 $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->ar_timestamp));
00239 break;
00240 }
00241 }
00242 $db->freeResult($res);
00243 $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'page');
00244 }
00245
00246 public function getAllowedParams() {
00247 return array (
00248 'start' => array(
00249 ApiBase :: PARAM_TYPE => 'timestamp'
00250 ),
00251 'end' => array(
00252 ApiBase :: PARAM_TYPE => 'timestamp',
00253 ),
00254 'dir' => array(
00255 ApiBase :: PARAM_TYPE => array(
00256 'newer',
00257 'older'
00258 ),
00259 ApiBase :: PARAM_DFLT => 'older'
00260 ),
00261 'from' => null,
00262 'continue' => null,
00263 'unique' => false,
00264 'user' => array(
00265 ApiBase :: PARAM_TYPE => 'user'
00266 ),
00267 'excludeuser' => array(
00268 ApiBase :: PARAM_TYPE => 'user'
00269 ),
00270 'namespace' => array(
00271 ApiBase :: PARAM_TYPE => 'namespace',
00272 ApiBase :: PARAM_DFLT => 0,
00273 ),
00274 'limit' => array(
00275 ApiBase :: PARAM_DFLT => 10,
00276 ApiBase :: PARAM_TYPE => 'limit',
00277 ApiBase :: PARAM_MIN => 1,
00278 ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
00279 ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
00280 ),
00281 'prop' => array(
00282 ApiBase :: PARAM_DFLT => 'user|comment',
00283 ApiBase :: PARAM_TYPE => array(
00284 'revid',
00285 'user',
00286 'comment',
00287 'minor',
00288 'len',
00289 'content',
00290 'token'
00291 ),
00292 ApiBase :: PARAM_ISMULTI => true
00293 ),
00294 );
00295 }
00296
00297 public function getParamDescription() {
00298 return array (
00299 'start' => 'The timestamp to start enumerating from. (1,2)',
00300 'end' => 'The timestamp to stop enumerating at. (1,2)',
00301 'dir' => 'The direction in which to enumerate. (1,2)',
00302 'limit' => 'The maximum amount of revisions to list',
00303 'prop' => 'Which properties to get',
00304 'namespace' => 'Only list pages in this namespace (3)',
00305 'user' => 'Only list revisions by this user',
00306 'excludeuser' => 'Don\'t list revisions by this user',
00307 'from' => 'Start listing at this title (3)',
00308 'continue' => 'When more results are available, use this to continue (3)',
00309 'unique' => 'List only one revision for each page (3)',
00310 );
00311 }
00312
00313 public function getDescription() {
00314 return array( 'List deleted revisions.',
00315 'This module operates in three modes:',
00316 '1) List deleted revisions for the given title(s), sorted by timestamp',
00317 '2) List deleted contributions for the given user, sorted by timestamp (no titles specified)',
00318 '3) List all deleted revisions in the given namespace, sorted by title and timestamp (no titles specified, druser not set)',
00319 'Certain parameters only apply to some modes and are ignored in others.',
00320 'For instance, a parameter marked (1) only applies to mode 1 and is ignored in modes 2 and 3.',
00321 );
00322 }
00323
00324 protected function getExamples() {
00325 return array (
00326 'List the last deleted revisions of Main Page and Talk:Main Page, with content (mode 1):',
00327 ' api.php?action=query&list=deletedrevs&titles=Main%20Page|Talk:Main%20Page&drprop=user|comment|content',
00328 'List the last 50 deleted contributions by Bob (mode 2):',
00329 ' api.php?action=query&list=deletedrevs&druser=Bob&drlimit=50',
00330 'List the first 50 deleted revisions in the main namespace (mode 3):',
00331 ' api.php?action=query&list=deletedrevs&drdir=newer&drlimit=50',
00332 'List the first 50 deleted pages in the Talk namespace (mode 3):',
00333 ' api.php?action=query&list=deletedrevs&drdir=newer&drlimit=50&drnamespace=1&drunique',
00334 );
00335 }
00336
00337 public function getVersion() {
00338 return __CLASS__ . ': $Id: ApiQueryDeletedrevs.php 50220 2009-05-05 14:07:59Z tstarling $';
00339 }
00340 }