MediaWiki
REL1_20
|
00001 <?php 00032 class ApiQueryInfo extends ApiQueryBase { 00033 00034 private $fld_protection = false, $fld_talkid = false, 00035 $fld_subjectid = false, $fld_url = false, 00036 $fld_readable = false, $fld_watched = false, $fld_notificationtimestamp = false, 00037 $fld_preload = false, $fld_displaytitle = false; 00038 00039 private $params, $titles, $missing, $everything, $pageCounter; 00040 00041 private $pageRestrictions, $pageIsRedir, $pageIsNew, $pageTouched, 00042 $pageLatest, $pageLength; 00043 00044 private $protections, $watched, $notificationtimestamps, $talkids, $subjectids, $displaytitles; 00045 00046 private $tokenFunctions; 00047 00048 public function __construct( $query, $moduleName ) { 00049 parent::__construct( $query, $moduleName, 'in' ); 00050 } 00051 00056 public function requestExtraData( $pageSet ) { 00057 global $wgDisableCounters; 00058 00059 $pageSet->requestField( 'page_restrictions' ); 00060 // when resolving redirects, no page will have this field 00061 if( !$pageSet->isResolvingRedirects() ) { 00062 $pageSet->requestField( 'page_is_redirect' ); 00063 } 00064 $pageSet->requestField( 'page_is_new' ); 00065 if ( !$wgDisableCounters ) { 00066 $pageSet->requestField( 'page_counter' ); 00067 } 00068 $pageSet->requestField( 'page_touched' ); 00069 $pageSet->requestField( 'page_latest' ); 00070 $pageSet->requestField( 'page_len' ); 00071 } 00072 00079 protected function getTokenFunctions() { 00080 // Don't call the hooks twice 00081 if ( isset( $this->tokenFunctions ) ) { 00082 return $this->tokenFunctions; 00083 } 00084 00085 // If we're in JSON callback mode, no tokens can be obtained 00086 if ( !is_null( $this->getMain()->getRequest()->getVal( 'callback' ) ) ) { 00087 return array(); 00088 } 00089 00090 $this->tokenFunctions = array( 00091 'edit' => array( 'ApiQueryInfo', 'getEditToken' ), 00092 'delete' => array( 'ApiQueryInfo', 'getDeleteToken' ), 00093 'protect' => array( 'ApiQueryInfo', 'getProtectToken' ), 00094 'move' => array( 'ApiQueryInfo', 'getMoveToken' ), 00095 'block' => array( 'ApiQueryInfo', 'getBlockToken' ), 00096 'unblock' => array( 'ApiQueryInfo', 'getUnblockToken' ), 00097 'email' => array( 'ApiQueryInfo', 'getEmailToken' ), 00098 'import' => array( 'ApiQueryInfo', 'getImportToken' ), 00099 'watch' => array( 'ApiQueryInfo', 'getWatchToken'), 00100 ); 00101 wfRunHooks( 'APIQueryInfoTokens', array( &$this->tokenFunctions ) ); 00102 return $this->tokenFunctions; 00103 } 00104 00105 static $cachedTokens = array(); 00106 00107 public static function resetTokenCache() { 00108 ApiQueryInfo::$cachedTokens = array(); 00109 } 00110 00111 public static function getEditToken( $pageid, $title ) { 00112 // We could check for $title->userCan('edit') here, 00113 // but that's too expensive for this purpose 00114 // and would break caching 00115 global $wgUser; 00116 if ( !$wgUser->isAllowed( 'edit' ) ) { 00117 return false; 00118 } 00119 00120 // The token is always the same, let's exploit that 00121 if ( !isset( ApiQueryInfo::$cachedTokens[ 'edit' ] ) ) { 00122 ApiQueryInfo::$cachedTokens[ 'edit' ] = $wgUser->getEditToken(); 00123 } 00124 00125 return ApiQueryInfo::$cachedTokens[ 'edit' ]; 00126 } 00127 00128 public static function getDeleteToken( $pageid, $title ) { 00129 global $wgUser; 00130 if ( !$wgUser->isAllowed( 'delete' ) ) { 00131 return false; 00132 } 00133 00134 // The token is always the same, let's exploit that 00135 if ( !isset( ApiQueryInfo::$cachedTokens[ 'delete' ] ) ) { 00136 ApiQueryInfo::$cachedTokens[ 'delete' ] = $wgUser->getEditToken(); 00137 } 00138 00139 return ApiQueryInfo::$cachedTokens[ 'delete' ]; 00140 } 00141 00142 public static function getProtectToken( $pageid, $title ) { 00143 global $wgUser; 00144 if ( !$wgUser->isAllowed( 'protect' ) ) { 00145 return false; 00146 } 00147 00148 // The token is always the same, let's exploit that 00149 if ( !isset( ApiQueryInfo::$cachedTokens[ 'protect' ] ) ) { 00150 ApiQueryInfo::$cachedTokens[ 'protect' ] = $wgUser->getEditToken(); 00151 } 00152 00153 return ApiQueryInfo::$cachedTokens[ 'protect' ]; 00154 } 00155 00156 public static function getMoveToken( $pageid, $title ) { 00157 global $wgUser; 00158 if ( !$wgUser->isAllowed( 'move' ) ) { 00159 return false; 00160 } 00161 00162 // The token is always the same, let's exploit that 00163 if ( !isset( ApiQueryInfo::$cachedTokens[ 'move' ] ) ) { 00164 ApiQueryInfo::$cachedTokens[ 'move' ] = $wgUser->getEditToken(); 00165 } 00166 00167 return ApiQueryInfo::$cachedTokens[ 'move' ]; 00168 } 00169 00170 public static function getBlockToken( $pageid, $title ) { 00171 global $wgUser; 00172 if ( !$wgUser->isAllowed( 'block' ) ) { 00173 return false; 00174 } 00175 00176 // The token is always the same, let's exploit that 00177 if ( !isset( ApiQueryInfo::$cachedTokens[ 'block' ] ) ) { 00178 ApiQueryInfo::$cachedTokens[ 'block' ] = $wgUser->getEditToken(); 00179 } 00180 00181 return ApiQueryInfo::$cachedTokens[ 'block' ]; 00182 } 00183 00184 public static function getUnblockToken( $pageid, $title ) { 00185 // Currently, this is exactly the same as the block token 00186 return self::getBlockToken( $pageid, $title ); 00187 } 00188 00189 public static function getEmailToken( $pageid, $title ) { 00190 global $wgUser; 00191 if ( !$wgUser->canSendEmail() || $wgUser->isBlockedFromEmailUser() ) { 00192 return false; 00193 } 00194 00195 // The token is always the same, let's exploit that 00196 if ( !isset( ApiQueryInfo::$cachedTokens[ 'email' ] ) ) { 00197 ApiQueryInfo::$cachedTokens[ 'email' ] = $wgUser->getEditToken(); 00198 } 00199 00200 return ApiQueryInfo::$cachedTokens[ 'email' ]; 00201 } 00202 00203 public static function getImportToken( $pageid, $title ) { 00204 global $wgUser; 00205 if ( !$wgUser->isAllowedAny( 'import', 'importupload' ) ) { 00206 return false; 00207 } 00208 00209 // The token is always the same, let's exploit that 00210 if ( !isset( ApiQueryInfo::$cachedTokens[ 'import' ] ) ) { 00211 ApiQueryInfo::$cachedTokens[ 'import' ] = $wgUser->getEditToken(); 00212 } 00213 00214 return ApiQueryInfo::$cachedTokens[ 'import' ]; 00215 } 00216 00217 public static function getWatchToken( $pageid, $title ) { 00218 global $wgUser; 00219 if ( !$wgUser->isLoggedIn() ) { 00220 return false; 00221 } 00222 00223 // The token is always the same, let's exploit that 00224 if ( !isset( ApiQueryInfo::$cachedTokens[ 'watch' ] ) ) { 00225 ApiQueryInfo::$cachedTokens[ 'watch' ] = $wgUser->getEditToken( 'watch' ); 00226 } 00227 00228 return ApiQueryInfo::$cachedTokens[ 'watch' ]; 00229 } 00230 00231 public static function getOptionsToken( $pageid, $title ) { 00232 global $wgUser; 00233 if ( !$wgUser->isLoggedIn() ) { 00234 return false; 00235 } 00236 00237 // The token is always the same, let's exploit that 00238 if ( !isset( ApiQueryInfo::$cachedTokens[ 'options' ] ) ) { 00239 ApiQueryInfo::$cachedTokens[ 'options' ] = $wgUser->getEditToken(); 00240 } 00241 00242 return ApiQueryInfo::$cachedTokens[ 'options' ]; 00243 } 00244 00245 public function execute() { 00246 $this->params = $this->extractRequestParams(); 00247 if ( !is_null( $this->params['prop'] ) ) { 00248 $prop = array_flip( $this->params['prop'] ); 00249 $this->fld_protection = isset( $prop['protection'] ); 00250 $this->fld_watched = isset( $prop['watched'] ); 00251 $this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] ); 00252 $this->fld_talkid = isset( $prop['talkid'] ); 00253 $this->fld_subjectid = isset( $prop['subjectid'] ); 00254 $this->fld_url = isset( $prop['url'] ); 00255 $this->fld_readable = isset( $prop['readable'] ); 00256 $this->fld_preload = isset( $prop['preload'] ); 00257 $this->fld_displaytitle = isset( $prop['displaytitle'] ); 00258 } 00259 00260 $pageSet = $this->getPageSet(); 00261 $this->titles = $pageSet->getGoodTitles(); 00262 $this->missing = $pageSet->getMissingTitles(); 00263 $this->everything = $this->titles + $this->missing; 00264 $result = $this->getResult(); 00265 00266 uasort( $this->everything, array( 'Title', 'compare' ) ); 00267 if ( !is_null( $this->params['continue'] ) ) { 00268 // Throw away any titles we're gonna skip so they don't 00269 // clutter queries 00270 $cont = explode( '|', $this->params['continue'] ); 00271 if ( count( $cont ) != 2 ) { 00272 $this->dieUsage( 'Invalid continue param. You should pass the original ' . 00273 'value returned by the previous query', '_badcontinue' ); 00274 } 00275 $conttitle = Title::makeTitleSafe( $cont[0], $cont[1] ); 00276 foreach ( $this->everything as $pageid => $title ) { 00277 if ( Title::compare( $title, $conttitle ) >= 0 ) { 00278 break; 00279 } 00280 unset( $this->titles[$pageid] ); 00281 unset( $this->missing[$pageid] ); 00282 unset( $this->everything[$pageid] ); 00283 } 00284 } 00285 00286 $this->pageRestrictions = $pageSet->getCustomField( 'page_restrictions' ); 00287 // when resolving redirects, no page will have this field 00288 $this->pageIsRedir = !$pageSet->isResolvingRedirects() 00289 ? $pageSet->getCustomField( 'page_is_redirect' ) 00290 : array(); 00291 $this->pageIsNew = $pageSet->getCustomField( 'page_is_new' ); 00292 00293 global $wgDisableCounters; 00294 00295 if ( !$wgDisableCounters ) { 00296 $this->pageCounter = $pageSet->getCustomField( 'page_counter' ); 00297 } 00298 $this->pageTouched = $pageSet->getCustomField( 'page_touched' ); 00299 $this->pageLatest = $pageSet->getCustomField( 'page_latest' ); 00300 $this->pageLength = $pageSet->getCustomField( 'page_len' ); 00301 00302 // Get protection info if requested 00303 if ( $this->fld_protection ) { 00304 $this->getProtectionInfo(); 00305 } 00306 00307 if ( $this->fld_watched || $this->fld_notificationtimestamp ) { 00308 $this->getWatchedInfo(); 00309 } 00310 00311 // Run the talkid/subjectid query if requested 00312 if ( $this->fld_talkid || $this->fld_subjectid ) { 00313 $this->getTSIDs(); 00314 } 00315 00316 if ( $this->fld_displaytitle ) { 00317 $this->getDisplayTitle(); 00318 } 00319 00320 foreach ( $this->everything as $pageid => $title ) { 00321 $pageInfo = $this->extractPageInfo( $pageid, $title ); 00322 $fit = $result->addValue( array( 00323 'query', 00324 'pages' 00325 ), $pageid, $pageInfo ); 00326 if ( !$fit ) { 00327 $this->setContinueEnumParameter( 'continue', 00328 $title->getNamespace() . '|' . 00329 $title->getText() ); 00330 break; 00331 } 00332 } 00333 } 00334 00341 private function extractPageInfo( $pageid, $title ) { 00342 $pageInfo = array(); 00343 $titleExists = $pageid > 0; //$title->exists() needs pageid, which is not set for all title objects 00344 $ns = $title->getNamespace(); 00345 $dbkey = $title->getDBkey(); 00346 if ( $titleExists ) { 00347 global $wgDisableCounters; 00348 00349 $pageInfo['touched'] = wfTimestamp( TS_ISO_8601, $this->pageTouched[$pageid] ); 00350 $pageInfo['lastrevid'] = intval( $this->pageLatest[$pageid] ); 00351 $pageInfo['counter'] = $wgDisableCounters 00352 ? "" 00353 : intval( $this->pageCounter[$pageid] ); 00354 $pageInfo['length'] = intval( $this->pageLength[$pageid] ); 00355 00356 if ( isset( $this->pageIsRedir[$pageid] ) && $this->pageIsRedir[$pageid] ) { 00357 $pageInfo['redirect'] = ''; 00358 } 00359 if ( $this->pageIsNew[$pageid] ) { 00360 $pageInfo['new'] = ''; 00361 } 00362 } 00363 00364 if ( !is_null( $this->params['token'] ) ) { 00365 $tokenFunctions = $this->getTokenFunctions(); 00366 $pageInfo['starttimestamp'] = wfTimestamp( TS_ISO_8601, time() ); 00367 foreach ( $this->params['token'] as $t ) { 00368 $val = call_user_func( $tokenFunctions[$t], $pageid, $title ); 00369 if ( $val === false ) { 00370 $this->setWarning( "Action '$t' is not allowed for the current user" ); 00371 } else { 00372 $pageInfo[$t . 'token'] = $val; 00373 } 00374 } 00375 } 00376 00377 if ( $this->fld_protection ) { 00378 $pageInfo['protection'] = array(); 00379 if ( isset( $this->protections[$ns][$dbkey] ) ) { 00380 $pageInfo['protection'] = 00381 $this->protections[$ns][$dbkey]; 00382 } 00383 $this->getResult()->setIndexedTagName( $pageInfo['protection'], 'pr' ); 00384 } 00385 00386 if ( $this->fld_watched && isset( $this->watched[$ns][$dbkey] ) ) { 00387 $pageInfo['watched'] = ''; 00388 } 00389 00390 if ( $this->fld_notificationtimestamp ) { 00391 $pageInfo['notificationtimestamp'] = ''; 00392 if ( isset( $this->notificationtimestamps[$ns][$dbkey] ) ) { 00393 $pageInfo['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $this->notificationtimestamps[$ns][$dbkey] ); 00394 } 00395 } 00396 00397 if ( $this->fld_talkid && isset( $this->talkids[$ns][$dbkey] ) ) { 00398 $pageInfo['talkid'] = $this->talkids[$ns][$dbkey]; 00399 } 00400 00401 if ( $this->fld_subjectid && isset( $this->subjectids[$ns][$dbkey] ) ) { 00402 $pageInfo['subjectid'] = $this->subjectids[$ns][$dbkey]; 00403 } 00404 00405 if ( $this->fld_url ) { 00406 $pageInfo['fullurl'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT ); 00407 $pageInfo['editurl'] = wfExpandUrl( $title->getFullURL( 'action=edit' ), PROTO_CURRENT ); 00408 } 00409 if ( $this->fld_readable && $title->userCan( 'read' ) ) { 00410 $pageInfo['readable'] = ''; 00411 } 00412 00413 if ( $this->fld_preload ) { 00414 if ( $titleExists ) { 00415 $pageInfo['preload'] = ''; 00416 } else { 00417 $text = null; 00418 wfRunHooks( 'EditFormPreloadText', array( &$text, &$title ) ); 00419 00420 $pageInfo['preload'] = $text; 00421 } 00422 } 00423 00424 if ( $this->fld_displaytitle ) { 00425 if ( isset( $this->displaytitles[$pageid] ) ) { 00426 $pageInfo['displaytitle'] = $this->displaytitles[$pageid]; 00427 } else { 00428 $pageInfo['displaytitle'] = $title->getPrefixedText(); 00429 } 00430 } 00431 00432 return $pageInfo; 00433 } 00434 00438 private function getProtectionInfo() { 00439 global $wgContLang; 00440 $this->protections = array(); 00441 $db = $this->getDB(); 00442 00443 // Get normal protections for existing titles 00444 if ( count( $this->titles ) ) { 00445 $this->resetQueryParams(); 00446 $this->addTables( 'page_restrictions' ); 00447 $this->addFields( array( 'pr_page', 'pr_type', 'pr_level', 00448 'pr_expiry', 'pr_cascade' ) ); 00449 $this->addWhereFld( 'pr_page', array_keys( $this->titles ) ); 00450 00451 $res = $this->select( __METHOD__ ); 00452 foreach ( $res as $row ) { 00453 $title = $this->titles[$row->pr_page]; 00454 $a = array( 00455 'type' => $row->pr_type, 00456 'level' => $row->pr_level, 00457 'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 ) 00458 ); 00459 if ( $row->pr_cascade ) { 00460 $a['cascade'] = ''; 00461 } 00462 $this->protections[$title->getNamespace()][$title->getDBkey()][] = $a; 00463 } 00464 // Also check old restrictions 00465 foreach( $this->titles as $pageId => $title ) { 00466 if ( $this->pageRestrictions[$pageId] ) { 00467 $namespace = $title->getNamespace(); 00468 $dbKey = $title->getDBkey(); 00469 $restrictions = explode( ':', trim( $this->pageRestrictions[$pageId] ) ); 00470 foreach ( $restrictions as $restrict ) { 00471 $temp = explode( '=', trim( $restrict ) ); 00472 if ( count( $temp ) == 1 ) { 00473 // old old format should be treated as edit/move restriction 00474 $restriction = trim( $temp[0] ); 00475 00476 if ( $restriction == '' ) { 00477 continue; 00478 } 00479 $this->protections[$namespace][$dbKey][] = array( 00480 'type' => 'edit', 00481 'level' => $restriction, 00482 'expiry' => 'infinity', 00483 ); 00484 $this->protections[$namespace][$dbKey][] = array( 00485 'type' => 'move', 00486 'level' => $restriction, 00487 'expiry' => 'infinity', 00488 ); 00489 } else { 00490 $restriction = trim( $temp[1] ); 00491 if ( $restriction == '' ) { 00492 continue; 00493 } 00494 $this->protections[$namespace][$dbKey][] = array( 00495 'type' => $temp[0], 00496 'level' => $restriction, 00497 'expiry' => 'infinity', 00498 ); 00499 } 00500 } 00501 } 00502 } 00503 } 00504 00505 // Get protections for missing titles 00506 if ( count( $this->missing ) ) { 00507 $this->resetQueryParams(); 00508 $lb = new LinkBatch( $this->missing ); 00509 $this->addTables( 'protected_titles' ); 00510 $this->addFields( array( 'pt_title', 'pt_namespace', 'pt_create_perm', 'pt_expiry' ) ); 00511 $this->addWhere( $lb->constructSet( 'pt', $db ) ); 00512 $res = $this->select( __METHOD__ ); 00513 foreach ( $res as $row ) { 00514 $this->protections[$row->pt_namespace][$row->pt_title][] = array( 00515 'type' => 'create', 00516 'level' => $row->pt_create_perm, 00517 'expiry' => $wgContLang->formatExpiry( $row->pt_expiry, TS_ISO_8601 ) 00518 ); 00519 } 00520 } 00521 00522 // Cascading protections 00523 $images = $others = array(); 00524 foreach ( $this->everything as $title ) { 00525 if ( $title->getNamespace() == NS_FILE ) { 00526 $images[] = $title->getDBkey(); 00527 } else { 00528 $others[] = $title; 00529 } 00530 } 00531 00532 if ( count( $others ) ) { 00533 // Non-images: check templatelinks 00534 $lb = new LinkBatch( $others ); 00535 $this->resetQueryParams(); 00536 $this->addTables( array( 'page_restrictions', 'page', 'templatelinks' ) ); 00537 $this->addFields( array( 'pr_type', 'pr_level', 'pr_expiry', 00538 'page_title', 'page_namespace', 00539 'tl_title', 'tl_namespace' ) ); 00540 $this->addWhere( $lb->constructSet( 'tl', $db ) ); 00541 $this->addWhere( 'pr_page = page_id' ); 00542 $this->addWhere( 'pr_page = tl_from' ); 00543 $this->addWhereFld( 'pr_cascade', 1 ); 00544 00545 $res = $this->select( __METHOD__ ); 00546 foreach ( $res as $row ) { 00547 $source = Title::makeTitle( $row->page_namespace, $row->page_title ); 00548 $this->protections[$row->tl_namespace][$row->tl_title][] = array( 00549 'type' => $row->pr_type, 00550 'level' => $row->pr_level, 00551 'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 ), 00552 'source' => $source->getPrefixedText() 00553 ); 00554 } 00555 } 00556 00557 if ( count( $images ) ) { 00558 // Images: check imagelinks 00559 $this->resetQueryParams(); 00560 $this->addTables( array( 'page_restrictions', 'page', 'imagelinks' ) ); 00561 $this->addFields( array( 'pr_type', 'pr_level', 'pr_expiry', 00562 'page_title', 'page_namespace', 'il_to' ) ); 00563 $this->addWhere( 'pr_page = page_id' ); 00564 $this->addWhere( 'pr_page = il_from' ); 00565 $this->addWhereFld( 'pr_cascade', 1 ); 00566 $this->addWhereFld( 'il_to', $images ); 00567 00568 $res = $this->select( __METHOD__ ); 00569 foreach ( $res as $row ) { 00570 $source = Title::makeTitle( $row->page_namespace, $row->page_title ); 00571 $this->protections[NS_FILE][$row->il_to][] = array( 00572 'type' => $row->pr_type, 00573 'level' => $row->pr_level, 00574 'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 ), 00575 'source' => $source->getPrefixedText() 00576 ); 00577 } 00578 } 00579 } 00580 00585 private function getTSIDs() { 00586 $getTitles = $this->talkids = $this->subjectids = array(); 00587 00588 foreach ( $this->everything as $t ) { 00589 if ( MWNamespace::isTalk( $t->getNamespace() ) ) { 00590 if ( $this->fld_subjectid ) { 00591 $getTitles[] = $t->getSubjectPage(); 00592 } 00593 } elseif ( $this->fld_talkid ) { 00594 $getTitles[] = $t->getTalkPage(); 00595 } 00596 } 00597 if ( !count( $getTitles ) ) { 00598 return; 00599 } 00600 00601 $db = $this->getDB(); 00602 00603 // Construct a custom WHERE clause that matches 00604 // all titles in $getTitles 00605 $lb = new LinkBatch( $getTitles ); 00606 $this->resetQueryParams(); 00607 $this->addTables( 'page' ); 00608 $this->addFields( array( 'page_title', 'page_namespace', 'page_id' ) ); 00609 $this->addWhere( $lb->constructSet( 'page', $db ) ); 00610 $res = $this->select( __METHOD__ ); 00611 foreach ( $res as $row ) { 00612 if ( MWNamespace::isTalk( $row->page_namespace ) ) { 00613 $this->talkids[MWNamespace::getSubject( $row->page_namespace )][$row->page_title] = 00614 intval( $row->page_id ); 00615 } else { 00616 $this->subjectids[MWNamespace::getTalk( $row->page_namespace )][$row->page_title] = 00617 intval( $row->page_id ); 00618 } 00619 } 00620 } 00621 00622 private function getDisplayTitle() { 00623 $this->displaytitles = array(); 00624 00625 $pageIds = array_keys( $this->titles ); 00626 00627 if ( !count( $pageIds ) ) { 00628 return; 00629 } 00630 00631 $this->resetQueryParams(); 00632 $this->addTables( 'page_props' ); 00633 $this->addFields( array( 'pp_page', 'pp_value' ) ); 00634 $this->addWhereFld( 'pp_page', $pageIds ); 00635 $this->addWhereFld( 'pp_propname', 'displaytitle' ); 00636 $res = $this->select( __METHOD__ ); 00637 00638 foreach ( $res as $row ) { 00639 $this->displaytitles[$row->pp_page] = $row->pp_value; 00640 } 00641 } 00642 00647 private function getWatchedInfo() { 00648 $user = $this->getUser(); 00649 00650 if ( $user->isAnon() || count( $this->everything ) == 0 ) { 00651 return; 00652 } 00653 00654 $this->watched = array(); 00655 $this->notificationtimestamps = array(); 00656 $db = $this->getDB(); 00657 00658 $lb = new LinkBatch( $this->everything ); 00659 00660 $this->resetQueryParams(); 00661 $this->addTables( array( 'watchlist' ) ); 00662 $this->addFields( array( 'wl_title', 'wl_namespace' ) ); 00663 $this->addFieldsIf( 'wl_notificationtimestamp', $this->fld_notificationtimestamp ); 00664 $this->addWhere( array( 00665 $lb->constructSet( 'wl', $db ), 00666 'wl_user' => $user->getID() 00667 ) ); 00668 00669 $res = $this->select( __METHOD__ ); 00670 00671 foreach ( $res as $row ) { 00672 if ( $this->fld_watched ) { 00673 $this->watched[$row->wl_namespace][$row->wl_title] = true; 00674 } 00675 if ( $this->fld_notificationtimestamp ) { 00676 $this->notificationtimestamps[$row->wl_namespace][$row->wl_title] = $row->wl_notificationtimestamp; 00677 } 00678 } 00679 } 00680 00681 public function getCacheMode( $params ) { 00682 $publicProps = array( 00683 'protection', 00684 'talkid', 00685 'subjectid', 00686 'url', 00687 'preload', 00688 'displaytitle', 00689 ); 00690 if ( !is_null( $params['prop'] ) ) { 00691 foreach ( $params['prop'] as $prop ) { 00692 if ( !in_array( $prop, $publicProps ) ) { 00693 return 'private'; 00694 } 00695 } 00696 } 00697 if ( !is_null( $params['token'] ) ) { 00698 return 'private'; 00699 } 00700 return 'public'; 00701 } 00702 00703 public function getAllowedParams() { 00704 return array( 00705 'prop' => array( 00706 ApiBase::PARAM_DFLT => null, 00707 ApiBase::PARAM_ISMULTI => true, 00708 ApiBase::PARAM_TYPE => array( 00709 'protection', 00710 'talkid', 00711 'watched', # private 00712 'notificationtimestamp', # private 00713 'subjectid', 00714 'url', 00715 'readable', # private 00716 'preload', 00717 'displaytitle', 00718 // If you add more properties here, please consider whether they 00719 // need to be added to getCacheMode() 00720 ) ), 00721 'token' => array( 00722 ApiBase::PARAM_DFLT => null, 00723 ApiBase::PARAM_ISMULTI => true, 00724 ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() ) 00725 ), 00726 'continue' => null, 00727 ); 00728 } 00729 00730 public function getParamDescription() { 00731 return array( 00732 'prop' => array( 00733 'Which additional properties to get:', 00734 ' protection - List the protection level of each page', 00735 ' talkid - The page ID of the talk page for each non-talk page', 00736 ' watched - List the watched status of each page', 00737 ' notificationtimestamp - The watchlist notification timestamp of each page', 00738 ' subjectid - The page ID of the parent page for each talk page', 00739 ' url - Gives a full URL to the page, and also an edit URL', 00740 ' readable - Whether the user can read this page', 00741 ' preload - Gives the text returned by EditFormPreloadText', 00742 ' displaytitle - Gives the way the page title is actually displayed', 00743 ), 00744 'token' => 'Request a token to perform a data-modifying action on a page', 00745 'continue' => 'When more results are available, use this to continue', 00746 ); 00747 } 00748 00749 public function getResultProperties() { 00750 $props = array( 00751 ApiBase::PROP_LIST => false, 00752 '' => array( 00753 'touched' => 'timestamp', 00754 'lastrevid' => 'integer', 00755 'counter' => array( 00756 ApiBase::PROP_TYPE => 'integer', 00757 ApiBase::PROP_NULLABLE => true 00758 ), 00759 'length' => 'integer', 00760 'redirect' => 'boolean', 00761 'new' => 'boolean', 00762 'starttimestamp' => array( 00763 ApiBase::PROP_TYPE => 'timestamp', 00764 ApiBase::PROP_NULLABLE => true 00765 ) 00766 ), 00767 'watched' => array( 00768 'watched' => 'boolean' 00769 ), 00770 'notificationtimestamp' => array( 00771 'notificationtimestamp' => array( 00772 ApiBase::PROP_TYPE => 'timestamp', 00773 ApiBase::PROP_NULLABLE => true 00774 ) 00775 ), 00776 'talkid' => array( 00777 'talkid' => array( 00778 ApiBase::PROP_TYPE => 'integer', 00779 ApiBase::PROP_NULLABLE => true 00780 ) 00781 ), 00782 'subjectid' => array( 00783 'subjectid' => array( 00784 ApiBase::PROP_TYPE => 'integer', 00785 ApiBase::PROP_NULLABLE => true 00786 ) 00787 ), 00788 'url' => array( 00789 'fullurl' => 'string', 00790 'editurl' => 'string' 00791 ), 00792 'readable' => array( 00793 'readable' => 'boolean' 00794 ), 00795 'preload' => array( 00796 'preload' => 'string' 00797 ), 00798 'displaytitle' => array( 00799 'displaytitle' => 'string' 00800 ) 00801 ); 00802 00803 self::addTokenProperties( $props, $this->getTokenFunctions() ); 00804 00805 return $props; 00806 } 00807 00808 public function getDescription() { 00809 return 'Get basic page information such as namespace, title, last touched date, ...'; 00810 } 00811 00812 public function getPossibleErrors() { 00813 return array_merge( parent::getPossibleErrors(), array( 00814 array( 'code' => '_badcontinue', 'info' => 'Invalid continue param. You should pass the original value returned by the previous query' ), 00815 ) ); 00816 } 00817 00818 public function getExamples() { 00819 return array( 00820 'api.php?action=query&prop=info&titles=Main%20Page', 00821 'api.php?action=query&prop=info&inprop=protection&titles=Main%20Page' 00822 ); 00823 } 00824 00825 public function getHelpUrls() { 00826 return 'https://www.mediawiki.org/wiki/API:Properties#info_.2F_in'; 00827 } 00828 00829 public function getVersion() { 00830 return __CLASS__ . ': $Id$'; 00831 } 00832 }