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 ApiQueryInfo extends ApiQueryBase {
00037
00038 private $fld_protection = false, $fld_talkid = false,
00039 $fld_subjectid = false, $fld_url = false,
00040 $fld_readable = false;
00041
00042 public function __construct($query, $moduleName) {
00043 parent :: __construct($query, $moduleName, 'in');
00044 }
00045
00046 public function requestExtraData($pageSet) {
00047 $pageSet->requestField('page_restrictions');
00048 $pageSet->requestField('page_is_redirect');
00049 $pageSet->requestField('page_is_new');
00050 $pageSet->requestField('page_counter');
00051 $pageSet->requestField('page_touched');
00052 $pageSet->requestField('page_latest');
00053 $pageSet->requestField('page_len');
00054 }
00055
00062 protected function getTokenFunctions() {
00063
00064 if(isset($this->tokenFunctions))
00065 return $this->tokenFunctions;
00066
00067
00068 if(!is_null($this->getMain()->getRequest()->getVal('callback')))
00069 return array();
00070
00071 $this->tokenFunctions = array(
00072 'edit' => array( 'ApiQueryInfo', 'getEditToken' ),
00073 'delete' => array( 'ApiQueryInfo', 'getDeleteToken' ),
00074 'protect' => array( 'ApiQueryInfo', 'getProtectToken' ),
00075 'move' => array( 'ApiQueryInfo', 'getMoveToken' ),
00076 'block' => array( 'ApiQueryInfo', 'getBlockToken' ),
00077 'unblock' => array( 'ApiQueryInfo', 'getUnblockToken' ),
00078 'email' => array( 'ApiQueryInfo', 'getEmailToken' ),
00079 'import' => array( 'ApiQueryInfo', 'getImportToken' ),
00080 );
00081 wfRunHooks('APIQueryInfoTokens', array(&$this->tokenFunctions));
00082 return $this->tokenFunctions;
00083 }
00084
00085 public static function getEditToken($pageid, $title)
00086 {
00087
00088
00089
00090 global $wgUser;
00091 if(!$wgUser->isAllowed('edit'))
00092 return false;
00093
00094
00095 static $cachedEditToken = null;
00096 if(!is_null($cachedEditToken))
00097 return $cachedEditToken;
00098
00099 $cachedEditToken = $wgUser->editToken();
00100 return $cachedEditToken;
00101 }
00102
00103 public static function getDeleteToken($pageid, $title)
00104 {
00105 global $wgUser;
00106 if(!$wgUser->isAllowed('delete'))
00107 return false;
00108
00109 static $cachedDeleteToken = null;
00110 if(!is_null($cachedDeleteToken))
00111 return $cachedDeleteToken;
00112
00113 $cachedDeleteToken = $wgUser->editToken();
00114 return $cachedDeleteToken;
00115 }
00116
00117 public static function getProtectToken($pageid, $title)
00118 {
00119 global $wgUser;
00120 if(!$wgUser->isAllowed('protect'))
00121 return false;
00122
00123 static $cachedProtectToken = null;
00124 if(!is_null($cachedProtectToken))
00125 return $cachedProtectToken;
00126
00127 $cachedProtectToken = $wgUser->editToken();
00128 return $cachedProtectToken;
00129 }
00130
00131 public static function getMoveToken($pageid, $title)
00132 {
00133 global $wgUser;
00134 if(!$wgUser->isAllowed('move'))
00135 return false;
00136
00137 static $cachedMoveToken = null;
00138 if(!is_null($cachedMoveToken))
00139 return $cachedMoveToken;
00140
00141 $cachedMoveToken = $wgUser->editToken();
00142 return $cachedMoveToken;
00143 }
00144
00145 public static function getBlockToken($pageid, $title)
00146 {
00147 global $wgUser;
00148 if(!$wgUser->isAllowed('block'))
00149 return false;
00150
00151 static $cachedBlockToken = null;
00152 if(!is_null($cachedBlockToken))
00153 return $cachedBlockToken;
00154
00155 $cachedBlockToken = $wgUser->editToken();
00156 return $cachedBlockToken;
00157 }
00158
00159 public static function getUnblockToken($pageid, $title)
00160 {
00161
00162 return self::getBlockToken($pageid, $title);
00163 }
00164
00165 public static function getEmailToken($pageid, $title)
00166 {
00167 global $wgUser;
00168 if(!$wgUser->canSendEmail() || $wgUser->isBlockedFromEmailUser())
00169 return false;
00170
00171 static $cachedEmailToken = null;
00172 if(!is_null($cachedEmailToken))
00173 return $cachedEmailToken;
00174
00175 $cachedEmailToken = $wgUser->editToken();
00176 return $cachedEmailToken;
00177 }
00178
00179 public static function getImportToken($pageid, $title)
00180 {
00181 global $wgUser;
00182 if(!$wgUser->isAllowed('import'))
00183 return false;
00184
00185 static $cachedImportToken = null;
00186 if(!is_null($cachedImportToken))
00187 return $cachedImportToken;
00188
00189 $cachedImportToken = $wgUser->editToken();
00190 return $cachedImportToken;
00191 }
00192
00193 public function execute() {
00194 $this->params = $this->extractRequestParams();
00195 if(!is_null($this->params['prop'])) {
00196 $prop = array_flip($this->params['prop']);
00197 $this->fld_protection = isset($prop['protection']);
00198 $this->fld_talkid = isset($prop['talkid']);
00199 $this->fld_subjectid = isset($prop['subjectid']);
00200 $this->fld_url = isset($prop['url']);
00201 $this->fld_readable = isset($prop['readable']);
00202 }
00203
00204 $pageSet = $this->getPageSet();
00205 $this->titles = $pageSet->getGoodTitles();
00206 $this->missing = $pageSet->getMissingTitles();
00207 $this->everything = $this->titles + $this->missing;
00208 $result = $this->getResult();
00209
00210 uasort($this->everything, array('Title', 'compare'));
00211 if(!is_null($this->params['continue']))
00212 {
00213
00214
00215 $cont = explode('|', $this->params['continue']);
00216 if(count($cont) != 2)
00217 $this->dieUsage("Invalid continue param. You should pass the original " .
00218 "value returned by the previous query", "_badcontinue");
00219 $conttitle = Title::makeTitleSafe($cont[0], $cont[1]);
00220 foreach($this->everything as $pageid => $title)
00221 {
00222 if(Title::compare($title, $conttitle) >= 0)
00223 break;
00224 unset($this->titles[$pageid]);
00225 unset($this->missing[$pageid]);
00226 unset($this->everything[$pageid]);
00227 }
00228 }
00229
00230 $this->pageRestrictions = $pageSet->getCustomField('page_restrictions');
00231 $this->pageIsRedir = $pageSet->getCustomField('page_is_redirect');
00232 $this->pageIsNew = $pageSet->getCustomField('page_is_new');
00233 $this->pageCounter = $pageSet->getCustomField('page_counter');
00234 $this->pageTouched = $pageSet->getCustomField('page_touched');
00235 $this->pageLatest = $pageSet->getCustomField('page_latest');
00236 $this->pageLength = $pageSet->getCustomField('page_len');
00237
00238 $db = $this->getDB();
00239
00240 if ($this->fld_protection)
00241 $this->getProtectionInfo();
00242
00243
00244 if($this->fld_talkid || $this->fld_subjectid)
00245 $this->getTSIDs();
00246
00247 foreach($this->everything as $pageid => $title) {
00248 $pageInfo = $this->extractPageInfo($pageid, $title);
00249 $fit = $result->addValue(array (
00250 'query',
00251 'pages'
00252 ), $pageid, $pageInfo);
00253 if(!$fit)
00254 {
00255 $this->setContinueEnumParameter('continue',
00256 $title->getNamespace() . '|' .
00257 $title->getText());
00258 break;
00259 }
00260 }
00261 }
00262
00269 private function extractPageInfo($pageid, $title)
00270 {
00271 $pageInfo = array();
00272 if($title->exists())
00273 {
00274 $pageInfo['touched'] = wfTimestamp(TS_ISO_8601, $this->pageTouched[$pageid]);
00275 $pageInfo['lastrevid'] = intval($this->pageLatest[$pageid]);
00276 $pageInfo['counter'] = intval($this->pageCounter[$pageid]);
00277 $pageInfo['length'] = intval($this->pageLength[$pageid]);
00278 if ($this->pageIsRedir[$pageid])
00279 $pageInfo['redirect'] = '';
00280 if ($this->pageIsNew[$pageid])
00281 $pageInfo['new'] = '';
00282 }
00283
00284 if (!is_null($this->params['token'])) {
00285 $tokenFunctions = $this->getTokenFunctions();
00286 $pageInfo['starttimestamp'] = wfTimestamp(TS_ISO_8601, time());
00287 foreach($this->params['token'] as $t)
00288 {
00289 $val = call_user_func($tokenFunctions[$t], $pageid, $title);
00290 if($val === false)
00291 $this->setWarning("Action '$t' is not allowed for the current user");
00292 else
00293 $pageInfo[$t . 'token'] = $val;
00294 }
00295 }
00296
00297 if($this->fld_protection) {
00298 $pageInfo['protection'] = array();
00299 if (isset($this->protections[$title->getNamespace()][$title->getDBkey()]))
00300 $pageInfo['protection'] =
00301 $this->protections[$title->getNamespace()][$title->getDBkey()];
00302 $this->getResult()->setIndexedTagName($pageInfo['protection'], 'pr');
00303 }
00304 if($this->fld_talkid && isset($this->talkids[$title->getNamespace()][$title->getDBKey()]))
00305 $pageInfo['talkid'] = $this->talkids[$title->getNamespace()][$title->getDBKey()];
00306 if($this->fld_subjectid && isset($this->subjectids[$title->getNamespace()][$title->getDBKey()]))
00307 $pageInfo['subjectid'] = $this->subjectids[$title->getNamespace()][$title->getDBKey()];
00308 if($this->fld_url) {
00309 $pageInfo['fullurl'] = $title->getFullURL();
00310 $pageInfo['editurl'] = $title->getFullURL('action=edit');
00311 }
00312 if($this->fld_readable)
00313 if($title->userCanRead())
00314 $pageInfo['readable'] = '';
00315 return $pageInfo;
00316 }
00317
00321 private function getProtectionInfo()
00322 {
00323 $this->protections = array();
00324 $db = $this->getDB();
00325
00326
00327 if(count($this->titles))
00328 {
00329 $this->addTables(array('page_restrictions', 'page'));
00330 $this->addWhere('page_id=pr_page');
00331 $this->addFields(array('pr_page', 'pr_type', 'pr_level',
00332 'pr_expiry', 'pr_cascade', 'page_namespace',
00333 'page_title'));
00334 $this->addWhereFld('pr_page', array_keys($this->titles));
00335
00336 $res = $this->select(__METHOD__);
00337 while($row = $db->fetchObject($res)) {
00338 $a = array(
00339 'type' => $row->pr_type,
00340 'level' => $row->pr_level,
00341 'expiry' => Block::decodeExpiry($row->pr_expiry, TS_ISO_8601)
00342 );
00343 if($row->pr_cascade)
00344 $a['cascade'] = '';
00345 $this->protections[$row->page_namespace][$row->page_title][] = $a;
00346
00347 # Also check old restrictions
00348 if($this->pageRestrictions[$row->pr_page]) {
00349 $restrictions = explode(':', trim($this->pageRestrictions[$row->pr_page]));
00350 foreach($restrictions as $restrict) {
00351 $temp = explode('=', trim($restrict));
00352 if(count($temp) == 1) {
00353
00354 $restriction = trim($temp[0]);
00355
00356 if($restriction == '')
00357 continue;
00358 $this->protections[$row->page_namespace][$row->page_title][] = array(
00359 'type' => 'edit',
00360 'level' => $restriction,
00361 'expiry' => 'infinity',
00362 );
00363 $this->protections[$row->page_namespace][$row->page_title][] = array(
00364 'type' => 'move',
00365 'level' => $restriction,
00366 'expiry' => 'infinity',
00367 );
00368 } else {
00369 $restriction = trim($temp[1]);
00370 if($restriction == '')
00371 continue;
00372 $this->protections[$row->page_namespace][$row->page_title][] = array(
00373 'type' => $temp[0],
00374 'level' => $restriction,
00375 'expiry' => 'infinity',
00376 );
00377 }
00378 }
00379 }
00380 }
00381 $db->freeResult($res);
00382 }
00383
00384
00385 if(count($this->missing))
00386 {
00387 $this->resetQueryParams();
00388 $lb = new LinkBatch($this->missing);
00389 $this->addTables('protected_titles');
00390 $this->addFields(array('pt_title', 'pt_namespace', 'pt_create_perm', 'pt_expiry'));
00391 $this->addWhere($lb->constructSet('pt', $db));
00392 $res = $this->select(__METHOD__);
00393 while($row = $db->fetchObject($res)) {
00394 $this->protections[$row->pt_namespace][$row->pt_title][] = array(
00395 'type' => 'create',
00396 'level' => $row->pt_create_perm,
00397 'expiry' => Block::decodeExpiry($row->pt_expiry, TS_ISO_8601)
00398 );
00399 }
00400 $db->freeResult($res);
00401 }
00402
00403
00404 $images = $others = array();
00405 foreach ($this->everything as $title)
00406 if ($title->getNamespace() == NS_FILE)
00407 $images[] = $title->getDBKey();
00408 else
00409 $others[] = $title;
00410
00411 if (count($others)) {
00412
00413 $lb = new LinkBatch($others);
00414 $this->resetQueryParams();
00415 $this->addTables(array('page_restrictions', 'page', 'templatelinks'));
00416 $this->addFields(array('pr_type', 'pr_level', 'pr_expiry',
00417 'page_title', 'page_namespace',
00418 'tl_title', 'tl_namespace'));
00419 $this->addWhere($lb->constructSet('tl', $db));
00420 $this->addWhere('pr_page = page_id');
00421 $this->addWhere('pr_page = tl_from');
00422 $this->addWhereFld('pr_cascade', 1);
00423
00424 $res = $this->select(__METHOD__);
00425 while($row = $db->fetchObject($res)) {
00426 $source = Title::makeTitle($row->page_namespace, $row->page_title);
00427 $this->protections[$row->tl_namespace][$row->tl_title][] = array(
00428 'type' => $row->pr_type,
00429 'level' => $row->pr_level,
00430 'expiry' => Block::decodeExpiry($row->pr_expiry, TS_ISO_8601),
00431 'source' => $source->getPrefixedText()
00432 );
00433 }
00434 $db->freeResult($res);
00435 }
00436
00437 if (count($images)) {
00438
00439 $this->resetQueryParams();
00440 $this->addTables(array('page_restrictions', 'page', 'imagelinks'));
00441 $this->addFields(array('pr_type', 'pr_level', 'pr_expiry',
00442 'page_title', 'page_namespace', 'il_to'));
00443 $this->addWhere('pr_page = page_id');
00444 $this->addWhere('pr_page = il_from');
00445 $this->addWhereFld('pr_cascade', 1);
00446 $this->addWhereFld('il_to', $images);
00447
00448 $res = $this->select(__METHOD__);
00449 while($row = $db->fetchObject($res)) {
00450 $source = Title::makeTitle($row->page_namespace, $row->page_title);
00451 $this->protections[NS_FILE][$row->il_to][] = array(
00452 'type' => $row->pr_type,
00453 'level' => $row->pr_level,
00454 'expiry' => Block::decodeExpiry($row->pr_expiry, TS_ISO_8601),
00455 'source' => $source->getPrefixedText()
00456 );
00457 }
00458 $db->freeResult($res);
00459 }
00460 }
00461
00466 private function getTSIDs()
00467 {
00468 $getTitles = $this->talkids = $this->subjectids = array();
00469 $db = $this->getDB();
00470 foreach($this->everything as $t)
00471 {
00472 if(MWNamespace::isTalk($t->getNamespace()))
00473 {
00474 if($this->fld_subjectid)
00475 $getTitles[] = $t->getSubjectPage();
00476 }
00477 else if($this->fld_talkid)
00478 $getTitles[] = $t->getTalkPage();
00479 }
00480 if(!count($getTitles))
00481 return;
00482
00483
00484
00485 $lb = new LinkBatch($getTitles);
00486 $this->resetQueryParams();
00487 $this->addTables('page');
00488 $this->addFields(array('page_title', 'page_namespace', 'page_id'));
00489 $this->addWhere($lb->constructSet('page', $db));
00490 $res = $this->select(__METHOD__);
00491 while($row = $db->fetchObject($res))
00492 {
00493 if(MWNamespace::isTalk($row->page_namespace))
00494 $this->talkids[MWNamespace::getSubject($row->page_namespace)][$row->page_title] =
00495 intval($row->page_id);
00496 else
00497 $this->subjectids[MWNamespace::getTalk($row->page_namespace)][$row->page_title] =
00498 intval($row->page_id);
00499 }
00500 }
00501
00502 public function getAllowedParams() {
00503 return array (
00504 'prop' => array (
00505 ApiBase :: PARAM_DFLT => NULL,
00506 ApiBase :: PARAM_ISMULTI => true,
00507 ApiBase :: PARAM_TYPE => array (
00508 'protection',
00509 'talkid',
00510 'subjectid',
00511 'url',
00512 'readable',
00513 )),
00514 'token' => array (
00515 ApiBase :: PARAM_DFLT => NULL,
00516 ApiBase :: PARAM_ISMULTI => true,
00517 ApiBase :: PARAM_TYPE => array_keys($this->getTokenFunctions())
00518 ),
00519 'continue' => null,
00520 );
00521 }
00522
00523 public function getParamDescription() {
00524 return array (
00525 'prop' => array (
00526 'Which additional properties to get:',
00527 ' protection - List the protection level of each page',
00528 ' talkid - The page ID of the talk page for each non-talk page',
00529 ' subjectid - The page ID of the parent page for each talk page'
00530 ),
00531 'token' => 'Request a token to perform a data-modifying action on a page',
00532 'continue' => 'When more results are available, use this to continue',
00533 );
00534 }
00535
00536 public function getDescription() {
00537 return 'Get basic page information such as namespace, title, last touched date, ...';
00538 }
00539
00540 protected function getExamples() {
00541 return array (
00542 'api.php?action=query&prop=info&titles=Main%20Page',
00543 'api.php?action=query&prop=info&inprop=protection&titles=Main%20Page'
00544 );
00545 }
00546
00547 public function getVersion() {
00548 return __CLASS__ . ': $Id: ApiQueryInfo.php 48488 2009-03-17 15:18:26Z catrope $';
00549 }
00550 }