MediaWiki  1.23.12
ApiQueryInfo.php
Go to the documentation of this file.
1 <?php
32 class ApiQueryInfo extends ApiQueryBase {
33 
34  private $fld_protection = false, $fld_talkid = false,
35  $fld_subjectid = false, $fld_url = false,
36  $fld_readable = false, $fld_watched = false, $fld_watchers = false,
38  $fld_preload = false, $fld_displaytitle = false;
39 
41 
44 
47  private $showZeroWatchers = false;
48 
49  private $tokenFunctions;
50 
51  public function __construct( $query, $moduleName ) {
52  parent::__construct( $query, $moduleName, 'in' );
53  }
54 
59  public function requestExtraData( $pageSet ) {
60  global $wgDisableCounters, $wgContentHandlerUseDB;
61 
62  $pageSet->requestField( 'page_restrictions' );
63  // when resolving redirects, no page will have this field
64  if ( !$pageSet->isResolvingRedirects() ) {
65  $pageSet->requestField( 'page_is_redirect' );
66  }
67  $pageSet->requestField( 'page_is_new' );
68  if ( !$wgDisableCounters ) {
69  $pageSet->requestField( 'page_counter' );
70  }
71  $pageSet->requestField( 'page_touched' );
72  $pageSet->requestField( 'page_latest' );
73  $pageSet->requestField( 'page_len' );
74  if ( $wgContentHandlerUseDB ) {
75  $pageSet->requestField( 'page_content_model' );
76  }
77  }
78 
85  protected function getTokenFunctions() {
86  // Don't call the hooks twice
87  if ( isset( $this->tokenFunctions ) ) {
88  return $this->tokenFunctions;
89  }
90 
91  // If we're in JSON callback mode, no tokens can be obtained
92  if ( !is_null( $this->getMain()->getRequest()->getVal( 'callback' ) ) ) {
93  return array();
94  }
95 
96  $this->tokenFunctions = array(
97  'edit' => array( 'ApiQueryInfo', 'getEditToken' ),
98  'delete' => array( 'ApiQueryInfo', 'getDeleteToken' ),
99  'protect' => array( 'ApiQueryInfo', 'getProtectToken' ),
100  'move' => array( 'ApiQueryInfo', 'getMoveToken' ),
101  'block' => array( 'ApiQueryInfo', 'getBlockToken' ),
102  'unblock' => array( 'ApiQueryInfo', 'getUnblockToken' ),
103  'email' => array( 'ApiQueryInfo', 'getEmailToken' ),
104  'import' => array( 'ApiQueryInfo', 'getImportToken' ),
105  'watch' => array( 'ApiQueryInfo', 'getWatchToken' ),
106  );
107  wfRunHooks( 'APIQueryInfoTokens', array( &$this->tokenFunctions ) );
108 
109  return $this->tokenFunctions;
110  }
111 
112  static protected $cachedTokens = array();
113 
114  public static function resetTokenCache() {
116  }
117 
118  public static function getEditToken( $pageid, $title ) {
119  // We could check for $title->userCan('edit') here,
120  // but that's too expensive for this purpose
121  // and would break caching
122  global $wgUser;
123  if ( !$wgUser->isAllowed( 'edit' ) ) {
124  return false;
125  }
126 
127  // The token is always the same, let's exploit that
128  if ( !isset( ApiQueryInfo::$cachedTokens['edit'] ) ) {
129  ApiQueryInfo::$cachedTokens['edit'] = $wgUser->getEditToken();
130  }
131 
132  return ApiQueryInfo::$cachedTokens['edit'];
133  }
134 
135  public static function getDeleteToken( $pageid, $title ) {
136  global $wgUser;
137  if ( !$wgUser->isAllowed( 'delete' ) ) {
138  return false;
139  }
140 
141  // The token is always the same, let's exploit that
142  if ( !isset( ApiQueryInfo::$cachedTokens['delete'] ) ) {
143  ApiQueryInfo::$cachedTokens['delete'] = $wgUser->getEditToken();
144  }
145 
146  return ApiQueryInfo::$cachedTokens['delete'];
147  }
148 
149  public static function getProtectToken( $pageid, $title ) {
150  global $wgUser;
151  if ( !$wgUser->isAllowed( 'protect' ) ) {
152  return false;
153  }
154 
155  // The token is always the same, let's exploit that
156  if ( !isset( ApiQueryInfo::$cachedTokens['protect'] ) ) {
157  ApiQueryInfo::$cachedTokens['protect'] = $wgUser->getEditToken();
158  }
159 
160  return ApiQueryInfo::$cachedTokens['protect'];
161  }
162 
163  public static function getMoveToken( $pageid, $title ) {
164  global $wgUser;
165  if ( !$wgUser->isAllowed( 'move' ) ) {
166  return false;
167  }
168 
169  // The token is always the same, let's exploit that
170  if ( !isset( ApiQueryInfo::$cachedTokens['move'] ) ) {
171  ApiQueryInfo::$cachedTokens['move'] = $wgUser->getEditToken();
172  }
173 
174  return ApiQueryInfo::$cachedTokens['move'];
175  }
176 
177  public static function getBlockToken( $pageid, $title ) {
178  global $wgUser;
179  if ( !$wgUser->isAllowed( 'block' ) ) {
180  return false;
181  }
182 
183  // The token is always the same, let's exploit that
184  if ( !isset( ApiQueryInfo::$cachedTokens['block'] ) ) {
185  ApiQueryInfo::$cachedTokens['block'] = $wgUser->getEditToken();
186  }
187 
188  return ApiQueryInfo::$cachedTokens['block'];
189  }
190 
191  public static function getUnblockToken( $pageid, $title ) {
192  // Currently, this is exactly the same as the block token
193  return self::getBlockToken( $pageid, $title );
194  }
195 
196  public static function getEmailToken( $pageid, $title ) {
197  global $wgUser;
198  if ( !$wgUser->canSendEmail() || $wgUser->isBlockedFromEmailUser() ) {
199  return false;
200  }
201 
202  // The token is always the same, let's exploit that
203  if ( !isset( ApiQueryInfo::$cachedTokens['email'] ) ) {
204  ApiQueryInfo::$cachedTokens['email'] = $wgUser->getEditToken();
205  }
206 
207  return ApiQueryInfo::$cachedTokens['email'];
208  }
209 
210  public static function getImportToken( $pageid, $title ) {
211  global $wgUser;
212  if ( !$wgUser->isAllowedAny( 'import', 'importupload' ) ) {
213  return false;
214  }
215 
216  // The token is always the same, let's exploit that
217  if ( !isset( ApiQueryInfo::$cachedTokens['import'] ) ) {
218  ApiQueryInfo::$cachedTokens['import'] = $wgUser->getEditToken();
219  }
220 
221  return ApiQueryInfo::$cachedTokens['import'];
222  }
223 
224  public static function getWatchToken( $pageid, $title ) {
225  global $wgUser;
226  if ( !$wgUser->isLoggedIn() ) {
227  return false;
228  }
229 
230  // The token is always the same, let's exploit that
231  if ( !isset( ApiQueryInfo::$cachedTokens['watch'] ) ) {
232  ApiQueryInfo::$cachedTokens['watch'] = $wgUser->getEditToken( 'watch' );
233  }
234 
235  return ApiQueryInfo::$cachedTokens['watch'];
236  }
237 
238  public static function getOptionsToken( $pageid, $title ) {
239  global $wgUser;
240  if ( !$wgUser->isLoggedIn() ) {
241  return false;
242  }
243 
244  // The token is always the same, let's exploit that
245  if ( !isset( ApiQueryInfo::$cachedTokens['options'] ) ) {
246  ApiQueryInfo::$cachedTokens['options'] = $wgUser->getEditToken();
247  }
248 
249  return ApiQueryInfo::$cachedTokens['options'];
250  }
251 
252  public function execute() {
253  $this->params = $this->extractRequestParams();
254  if ( !is_null( $this->params['prop'] ) ) {
255  $prop = array_flip( $this->params['prop'] );
256  $this->fld_protection = isset( $prop['protection'] );
257  $this->fld_watched = isset( $prop['watched'] );
258  $this->fld_watchers = isset( $prop['watchers'] );
259  $this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] );
260  $this->fld_talkid = isset( $prop['talkid'] );
261  $this->fld_subjectid = isset( $prop['subjectid'] );
262  $this->fld_url = isset( $prop['url'] );
263  $this->fld_readable = isset( $prop['readable'] );
264  $this->fld_preload = isset( $prop['preload'] );
265  $this->fld_displaytitle = isset( $prop['displaytitle'] );
266  }
267 
268  $pageSet = $this->getPageSet();
269  $this->titles = $pageSet->getGoodTitles();
270  $this->missing = $pageSet->getMissingTitles();
271  $this->everything = $this->titles + $this->missing;
272  $result = $this->getResult();
273 
274  uasort( $this->everything, array( 'Title', 'compare' ) );
275  if ( !is_null( $this->params['continue'] ) ) {
276  // Throw away any titles we're gonna skip so they don't
277  // clutter queries
278  $cont = explode( '|', $this->params['continue'] );
279  $this->dieContinueUsageIf( count( $cont ) != 2 );
280  $conttitle = Title::makeTitleSafe( $cont[0], $cont[1] );
281  foreach ( $this->everything as $pageid => $title ) {
282  if ( Title::compare( $title, $conttitle ) >= 0 ) {
283  break;
284  }
285  unset( $this->titles[$pageid] );
286  unset( $this->missing[$pageid] );
287  unset( $this->everything[$pageid] );
288  }
289  }
290 
291  $this->pageRestrictions = $pageSet->getCustomField( 'page_restrictions' );
292  // when resolving redirects, no page will have this field
293  $this->pageIsRedir = !$pageSet->isResolvingRedirects()
294  ? $pageSet->getCustomField( 'page_is_redirect' )
295  : array();
296  $this->pageIsNew = $pageSet->getCustomField( 'page_is_new' );
297 
298  global $wgDisableCounters;
299 
300  if ( !$wgDisableCounters ) {
301  $this->pageCounter = $pageSet->getCustomField( 'page_counter' );
302  }
303  $this->pageTouched = $pageSet->getCustomField( 'page_touched' );
304  $this->pageLatest = $pageSet->getCustomField( 'page_latest' );
305  $this->pageLength = $pageSet->getCustomField( 'page_len' );
306 
307  // Get protection info if requested
308  if ( $this->fld_protection ) {
309  $this->getProtectionInfo();
310  }
311 
312  if ( $this->fld_watched || $this->fld_notificationtimestamp ) {
313  $this->getWatchedInfo();
314  }
315 
316  if ( $this->fld_watchers ) {
317  $this->getWatcherInfo();
318  }
319 
320  // Run the talkid/subjectid query if requested
321  if ( $this->fld_talkid || $this->fld_subjectid ) {
322  $this->getTSIDs();
323  }
324 
325  if ( $this->fld_displaytitle ) {
326  $this->getDisplayTitle();
327  }
328 
330  foreach ( $this->everything as $pageid => $title ) {
331  $pageInfo = $this->extractPageInfo( $pageid, $title );
332  $fit = $result->addValue( array(
333  'query',
334  'pages'
335  ), $pageid, $pageInfo );
336  if ( !$fit ) {
337  $this->setContinueEnumParameter( 'continue',
338  $title->getNamespace() . '|' .
339  $title->getText() );
340  break;
341  }
342  }
343  }
344 
351  private function extractPageInfo( $pageid, $title ) {
352  $pageInfo = array();
353  // $title->exists() needs pageid, which is not set for all title objects
354  $titleExists = $pageid > 0;
355  $ns = $title->getNamespace();
356  $dbkey = $title->getDBkey();
357 
358  $pageInfo['contentmodel'] = $title->getContentModel();
359  $pageInfo['pagelanguage'] = $title->getPageLanguage()->getCode();
360 
361  if ( $titleExists ) {
362  global $wgDisableCounters;
363 
364  $pageInfo['touched'] = wfTimestamp( TS_ISO_8601, $this->pageTouched[$pageid] );
365  $pageInfo['lastrevid'] = intval( $this->pageLatest[$pageid] );
366  $pageInfo['counter'] = $wgDisableCounters
367  ? ''
368  : intval( $this->pageCounter[$pageid] );
369  $pageInfo['length'] = intval( $this->pageLength[$pageid] );
370 
371  if ( isset( $this->pageIsRedir[$pageid] ) && $this->pageIsRedir[$pageid] ) {
372  $pageInfo['redirect'] = '';
373  }
374  if ( $this->pageIsNew[$pageid] ) {
375  $pageInfo['new'] = '';
376  }
377  }
378 
379  if ( !is_null( $this->params['token'] ) ) {
381  $pageInfo['starttimestamp'] = wfTimestamp( TS_ISO_8601, time() );
382  foreach ( $this->params['token'] as $t ) {
383  $val = call_user_func( $tokenFunctions[$t], $pageid, $title );
384  if ( $val === false ) {
385  $this->setWarning( "Action '$t' is not allowed for the current user" );
386  } else {
387  $pageInfo[$t . 'token'] = $val;
388  }
389  }
390  }
391 
392  if ( $this->fld_protection ) {
393  $pageInfo['protection'] = array();
394  if ( isset( $this->protections[$ns][$dbkey] ) ) {
395  $pageInfo['protection'] =
396  $this->protections[$ns][$dbkey];
397  }
398  $this->getResult()->setIndexedTagName( $pageInfo['protection'], 'pr' );
399  }
400 
401  if ( $this->fld_watched && isset( $this->watched[$ns][$dbkey] ) ) {
402  $pageInfo['watched'] = '';
403  }
404 
405  if ( $this->fld_watchers ) {
406  if ( isset( $this->watchers[$ns][$dbkey] ) ) {
407  $pageInfo['watchers'] = $this->watchers[$ns][$dbkey];
408  } elseif ( $this->showZeroWatchers ) {
409  $pageInfo['watchers'] = 0;
410  }
411  }
412 
413  if ( $this->fld_notificationtimestamp ) {
414  $pageInfo['notificationtimestamp'] = '';
415  if ( isset( $this->notificationtimestamps[$ns][$dbkey] ) ) {
416  $pageInfo['notificationtimestamp'] =
417  wfTimestamp( TS_ISO_8601, $this->notificationtimestamps[$ns][$dbkey] );
418  }
419  }
420 
421  if ( $this->fld_talkid && isset( $this->talkids[$ns][$dbkey] ) ) {
422  $pageInfo['talkid'] = $this->talkids[$ns][$dbkey];
423  }
424 
425  if ( $this->fld_subjectid && isset( $this->subjectids[$ns][$dbkey] ) ) {
426  $pageInfo['subjectid'] = $this->subjectids[$ns][$dbkey];
427  }
428 
429  if ( $this->fld_url ) {
430  $pageInfo['fullurl'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
431  $pageInfo['editurl'] = wfExpandUrl( $title->getFullURL( 'action=edit' ), PROTO_CURRENT );
432  }
433  if ( $this->fld_readable && $title->userCan( 'read', $this->getUser() ) ) {
434  $pageInfo['readable'] = '';
435  }
436 
437  if ( $this->fld_preload ) {
438  if ( $titleExists ) {
439  $pageInfo['preload'] = '';
440  } else {
441  $text = null;
442  wfRunHooks( 'EditFormPreloadText', array( &$text, &$title ) );
443 
444  $pageInfo['preload'] = $text;
445  }
446  }
447 
448  if ( $this->fld_displaytitle ) {
449  if ( isset( $this->displaytitles[$pageid] ) ) {
450  $pageInfo['displaytitle'] = $this->displaytitles[$pageid];
451  } else {
452  $pageInfo['displaytitle'] = $title->getPrefixedText();
453  }
454  }
455 
456  return $pageInfo;
457  }
458 
462  private function getProtectionInfo() {
464  $this->protections = array();
465  $db = $this->getDB();
466 
467  // Get normal protections for existing titles
468  if ( count( $this->titles ) ) {
469  $this->resetQueryParams();
470  $this->addTables( 'page_restrictions' );
471  $this->addFields( array( 'pr_page', 'pr_type', 'pr_level',
472  'pr_expiry', 'pr_cascade' ) );
473  $this->addWhereFld( 'pr_page', array_keys( $this->titles ) );
474 
475  $res = $this->select( __METHOD__ );
476  foreach ( $res as $row ) {
478  $title = $this->titles[$row->pr_page];
479  $a = array(
480  'type' => $row->pr_type,
481  'level' => $row->pr_level,
482  'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 )
483  );
484  if ( $row->pr_cascade ) {
485  $a['cascade'] = '';
486  }
487  $this->protections[$title->getNamespace()][$title->getDBkey()][] = $a;
488  }
489  // Also check old restrictions
490  foreach ( $this->titles as $pageId => $title ) {
491  if ( $this->pageRestrictions[$pageId] ) {
492  $namespace = $title->getNamespace();
493  $dbKey = $title->getDBkey();
494  $restrictions = explode( ':', trim( $this->pageRestrictions[$pageId] ) );
495  foreach ( $restrictions as $restrict ) {
496  $temp = explode( '=', trim( $restrict ) );
497  if ( count( $temp ) == 1 ) {
498  // old old format should be treated as edit/move restriction
499  $restriction = trim( $temp[0] );
500 
501  if ( $restriction == '' ) {
502  continue;
503  }
504  $this->protections[$namespace][$dbKey][] = array(
505  'type' => 'edit',
506  'level' => $restriction,
507  'expiry' => 'infinity',
508  );
509  $this->protections[$namespace][$dbKey][] = array(
510  'type' => 'move',
511  'level' => $restriction,
512  'expiry' => 'infinity',
513  );
514  } else {
515  $restriction = trim( $temp[1] );
516  if ( $restriction == '' ) {
517  continue;
518  }
519  $this->protections[$namespace][$dbKey][] = array(
520  'type' => $temp[0],
521  'level' => $restriction,
522  'expiry' => 'infinity',
523  );
524  }
525  }
526  }
527  }
528  }
529 
530  // Get protections for missing titles
531  if ( count( $this->missing ) ) {
532  $this->resetQueryParams();
533  $lb = new LinkBatch( $this->missing );
534  $this->addTables( 'protected_titles' );
535  $this->addFields( array( 'pt_title', 'pt_namespace', 'pt_create_perm', 'pt_expiry' ) );
536  $this->addWhere( $lb->constructSet( 'pt', $db ) );
537  $res = $this->select( __METHOD__ );
538  foreach ( $res as $row ) {
539  $this->protections[$row->pt_namespace][$row->pt_title][] = array(
540  'type' => 'create',
541  'level' => $row->pt_create_perm,
542  'expiry' => $wgContLang->formatExpiry( $row->pt_expiry, TS_ISO_8601 )
543  );
544  }
545  }
546 
547  // Cascading protections
548  $images = $others = array();
549  foreach ( $this->everything as $title ) {
550  if ( $title->getNamespace() == NS_FILE ) {
551  $images[] = $title->getDBkey();
552  } else {
553  $others[] = $title;
554  }
555  }
556 
557  if ( count( $others ) ) {
558  // Non-images: check templatelinks
559  $lb = new LinkBatch( $others );
560  $this->resetQueryParams();
561  $this->addTables( array( 'page_restrictions', 'page', 'templatelinks' ) );
562  $this->addFields( array( 'pr_type', 'pr_level', 'pr_expiry',
563  'page_title', 'page_namespace',
564  'tl_title', 'tl_namespace' ) );
565  $this->addWhere( $lb->constructSet( 'tl', $db ) );
566  $this->addWhere( 'pr_page = page_id' );
567  $this->addWhere( 'pr_page = tl_from' );
568  $this->addWhereFld( 'pr_cascade', 1 );
569 
570  $res = $this->select( __METHOD__ );
571  foreach ( $res as $row ) {
572  $source = Title::makeTitle( $row->page_namespace, $row->page_title );
573  $this->protections[$row->tl_namespace][$row->tl_title][] = array(
574  'type' => $row->pr_type,
575  'level' => $row->pr_level,
576  'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 ),
577  'source' => $source->getPrefixedText()
578  );
579  }
580  }
581 
582  if ( count( $images ) ) {
583  // Images: check imagelinks
584  $this->resetQueryParams();
585  $this->addTables( array( 'page_restrictions', 'page', 'imagelinks' ) );
586  $this->addFields( array( 'pr_type', 'pr_level', 'pr_expiry',
587  'page_title', 'page_namespace', 'il_to' ) );
588  $this->addWhere( 'pr_page = page_id' );
589  $this->addWhere( 'pr_page = il_from' );
590  $this->addWhereFld( 'pr_cascade', 1 );
591  $this->addWhereFld( 'il_to', $images );
592 
593  $res = $this->select( __METHOD__ );
594  foreach ( $res as $row ) {
595  $source = Title::makeTitle( $row->page_namespace, $row->page_title );
596  $this->protections[NS_FILE][$row->il_to][] = array(
597  'type' => $row->pr_type,
598  'level' => $row->pr_level,
599  'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 ),
600  'source' => $source->getPrefixedText()
601  );
602  }
603  }
604  }
605 
610  private function getTSIDs() {
611  $getTitles = $this->talkids = $this->subjectids = array();
612 
614  foreach ( $this->everything as $t ) {
615  if ( MWNamespace::isTalk( $t->getNamespace() ) ) {
616  if ( $this->fld_subjectid ) {
617  $getTitles[] = $t->getSubjectPage();
618  }
619  } elseif ( $this->fld_talkid ) {
620  $getTitles[] = $t->getTalkPage();
621  }
622  }
623  if ( !count( $getTitles ) ) {
624  return;
625  }
626 
627  $db = $this->getDB();
628 
629  // Construct a custom WHERE clause that matches
630  // all titles in $getTitles
631  $lb = new LinkBatch( $getTitles );
632  $this->resetQueryParams();
633  $this->addTables( 'page' );
634  $this->addFields( array( 'page_title', 'page_namespace', 'page_id' ) );
635  $this->addWhere( $lb->constructSet( 'page', $db ) );
636  $res = $this->select( __METHOD__ );
637  foreach ( $res as $row ) {
638  if ( MWNamespace::isTalk( $row->page_namespace ) ) {
639  $this->talkids[MWNamespace::getSubject( $row->page_namespace )][$row->page_title] =
640  intval( $row->page_id );
641  } else {
642  $this->subjectids[MWNamespace::getTalk( $row->page_namespace )][$row->page_title] =
643  intval( $row->page_id );
644  }
645  }
646  }
647 
648  private function getDisplayTitle() {
649  $this->displaytitles = array();
650 
651  $pageIds = array_keys( $this->titles );
652 
653  if ( !count( $pageIds ) ) {
654  return;
655  }
656 
657  $this->resetQueryParams();
658  $this->addTables( 'page_props' );
659  $this->addFields( array( 'pp_page', 'pp_value' ) );
660  $this->addWhereFld( 'pp_page', $pageIds );
661  $this->addWhereFld( 'pp_propname', 'displaytitle' );
662  $res = $this->select( __METHOD__ );
663 
664  foreach ( $res as $row ) {
665  $this->displaytitles[$row->pp_page] = $row->pp_value;
666  }
667  }
668 
673  private function getWatchedInfo() {
674  $user = $this->getUser();
675 
676  if ( $user->isAnon() || count( $this->everything ) == 0
677  || !$user->isAllowed( 'viewmywatchlist' )
678  ) {
679  return;
680  }
681 
682  $this->watched = array();
683  $this->notificationtimestamps = array();
684  $db = $this->getDB();
685 
686  $lb = new LinkBatch( $this->everything );
687 
688  $this->resetQueryParams();
689  $this->addTables( array( 'watchlist' ) );
690  $this->addFields( array( 'wl_title', 'wl_namespace' ) );
691  $this->addFieldsIf( 'wl_notificationtimestamp', $this->fld_notificationtimestamp );
692  $this->addWhere( array(
693  $lb->constructSet( 'wl', $db ),
694  'wl_user' => $user->getID()
695  ) );
696 
697  $res = $this->select( __METHOD__ );
698 
699  foreach ( $res as $row ) {
700  if ( $this->fld_watched ) {
701  $this->watched[$row->wl_namespace][$row->wl_title] = true;
702  }
703  if ( $this->fld_notificationtimestamp ) {
704  $this->notificationtimestamps[$row->wl_namespace][$row->wl_title] =
705  $row->wl_notificationtimestamp;
706  }
707  }
708  }
709 
713  private function getWatcherInfo() {
714  global $wgUnwatchedPageThreshold;
715 
716  if ( count( $this->everything ) == 0 ) {
717  return;
718  }
719 
720  $user = $this->getUser();
721  $canUnwatchedpages = $user->isAllowed( 'unwatchedpages' );
722  if ( !$canUnwatchedpages && !is_int( $wgUnwatchedPageThreshold ) ) {
723  return;
724  }
725 
726  $this->watchers = array();
727  $this->showZeroWatchers = $canUnwatchedpages;
728  $db = $this->getDB();
729 
730  $lb = new LinkBatch( $this->everything );
731 
732  $this->resetQueryParams();
733  $this->addTables( array( 'watchlist' ) );
734  $this->addFields( array( 'wl_title', 'wl_namespace', 'count' => 'COUNT(*)' ) );
735  $this->addWhere( array(
736  $lb->constructSet( 'wl', $db )
737  ) );
738  $this->addOption( 'GROUP BY', array( 'wl_namespace', 'wl_title' ) );
739  if ( !$canUnwatchedpages ) {
740  $this->addOption( 'HAVING', "COUNT(*) >= $wgUnwatchedPageThreshold" );
741  }
742 
743  $res = $this->select( __METHOD__ );
744 
745  foreach ( $res as $row ) {
746  $this->watchers[$row->wl_namespace][$row->wl_title] = (int)$row->count;
747  }
748  }
749 
750  public function getCacheMode( $params ) {
751  $publicProps = array(
752  'protection',
753  'talkid',
754  'subjectid',
755  'url',
756  'preload',
757  'displaytitle',
758  );
759  if ( !is_null( $params['prop'] ) ) {
760  foreach ( $params['prop'] as $prop ) {
761  if ( !in_array( $prop, $publicProps ) ) {
762  return 'private';
763  }
764  }
765  }
766  if ( !is_null( $params['token'] ) ) {
767  return 'private';
768  }
769 
770  return 'public';
771  }
772 
773  public function getAllowedParams() {
774  return array(
775  'prop' => array(
776  ApiBase::PARAM_DFLT => null,
777  ApiBase::PARAM_ISMULTI => true,
779  'protection',
780  'talkid',
781  'watched', # private
782  'watchers', # private
783  'notificationtimestamp', # private
784  'subjectid',
785  'url',
786  'readable', # private
787  'preload',
788  'displaytitle',
789  // If you add more properties here, please consider whether they
790  // need to be added to getCacheMode()
791  ) ),
792  'token' => array(
793  ApiBase::PARAM_DFLT => null,
794  ApiBase::PARAM_ISMULTI => true,
795  ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() )
796  ),
797  'continue' => null,
798  );
799  }
800 
801  public function getParamDescription() {
802  return array(
803  'prop' => array(
804  'Which additional properties to get:',
805  ' protection - List the protection level of each page',
806  ' talkid - The page ID of the talk page for each non-talk page',
807  ' watched - List the watched status of each page',
808  ' watchers - The number of watchers, if allowed',
809  ' notificationtimestamp - The watchlist notification timestamp of each page',
810  ' subjectid - The page ID of the parent page for each talk page',
811  ' url - Gives a full URL to the page, and also an edit URL',
812  ' readable - Whether the user can read this page',
813  ' preload - Gives the text returned by EditFormPreloadText',
814  ' displaytitle - Gives the way the page title is actually displayed',
815  ),
816  'token' => 'Request a token to perform a data-modifying action on a page',
817  'continue' => 'When more results are available, use this to continue',
818  );
819  }
820 
821  public function getResultProperties() {
822  $props = array(
823  ApiBase::PROP_LIST => false,
824  '' => array(
825  'touched' => 'timestamp',
826  'lastrevid' => 'integer',
827  'counter' => array(
828  ApiBase::PROP_TYPE => 'integer',
829  ApiBase::PROP_NULLABLE => true
830  ),
831  'length' => 'integer',
832  'redirect' => 'boolean',
833  'new' => 'boolean',
834  'starttimestamp' => array(
835  ApiBase::PROP_TYPE => 'timestamp',
836  ApiBase::PROP_NULLABLE => true
837  ),
838  'contentmodel' => 'string',
839  ),
840  'watched' => array(
841  'watched' => 'boolean'
842  ),
843  'watchers' => array(
844  'watchers' => array(
845  ApiBase::PROP_TYPE => 'integer',
846  ApiBase::PROP_NULLABLE => true
847  )
848  ),
849  'notificationtimestamp' => array(
850  'notificationtimestamp' => array(
851  ApiBase::PROP_TYPE => 'timestamp',
852  ApiBase::PROP_NULLABLE => true
853  )
854  ),
855  'talkid' => array(
856  'talkid' => array(
857  ApiBase::PROP_TYPE => 'integer',
858  ApiBase::PROP_NULLABLE => true
859  )
860  ),
861  'subjectid' => array(
862  'subjectid' => array(
863  ApiBase::PROP_TYPE => 'integer',
864  ApiBase::PROP_NULLABLE => true
865  )
866  ),
867  'url' => array(
868  'fullurl' => 'string',
869  'editurl' => 'string'
870  ),
871  'readable' => array(
872  'readable' => 'boolean'
873  ),
874  'preload' => array(
875  'preload' => 'string'
876  ),
877  'displaytitle' => array(
878  'displaytitle' => 'string'
879  )
880  );
881 
882  self::addTokenProperties( $props, $this->getTokenFunctions() );
883 
884  return $props;
885  }
886 
887  public function getDescription() {
888  return 'Get basic page information such as namespace, title, last touched date, ...';
889  }
890 
891  public function getExamples() {
892  return array(
893  'api.php?action=query&prop=info&titles=Main%20Page',
894  'api.php?action=query&prop=info&inprop=protection&titles=Main%20Page'
895  );
896  }
897 
898  public function getHelpUrls() {
899  return 'https://www.mediawiki.org/wiki/API:Properties#info_.2F_in';
900  }
901 }
ApiQueryInfo\$talkids
$talkids
Definition: ApiQueryInfo.php:45
ApiQueryInfo\extractPageInfo
extractPageInfo( $pageid, $title)
Get a result array with information about a title.
Definition: ApiQueryInfo.php:351
Title\makeTitle
static & makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:398
$wgUser
$wgUser
Definition: Setup.php:572
$result
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. $reader:XMLReader object $logInfo:Array of information Return false to stop further processing of the tag 'ImportHandlePageXMLTag':When parsing a XML tag in a page. $reader:XMLReader object $pageInfo:Array of information Return false to stop further processing of the tag 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information Return false to stop further processing of the tag 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. $reader:XMLReader object Return false to stop further processing of the tag 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. $reader:XMLReader object $revisionInfo:Array of information Return false to stop further processing of the tag 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. $title:Title object for the current page $request:WebRequest $ignoreRedirect:boolean to skip redirect check $target:Title/string of redirect target $article:Article object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) $article:article(object) being checked 'IsTrustedProxy':Override the result of wfIsTrustedProxy() $ip:IP being check $result:Change this value to override the result of wfIsTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of User::isValidEmailAddr(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetMagic':DEPRECATED, use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetSpecialPageAliases':DEPRECATED, use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Associative array mapping language codes to prefixed links of the form "language:title". & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LinkBegin':Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:1528
ApiQueryBase\addFields
addFields( $value)
Add a set of fields to select to the internal array.
Definition: ApiQueryBase.php:117
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
ApiQueryInfo\$fld_url
$fld_url
Definition: ApiQueryInfo.php:35
ApiQueryInfo\$subjectids
$subjectids
Definition: ApiQueryInfo.php:45
ApiQueryInfo\$displaytitles
$displaytitles
Definition: ApiQueryInfo.php:45
ApiQueryInfo\$missing
$missing
Definition: ApiQueryInfo.php:40
MWNamespace\isTalk
static isTalk( $index)
Is the given namespace a talk namespace?
Definition: Namespace.php:107
ApiQueryBase\resetQueryParams
resetQueryParams()
Blank the internal arrays with query parameters.
Definition: ApiQueryBase.php:68
LinkBatch
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:30
ApiQueryInfo\getProtectionInfo
getProtectionInfo()
Get information about protections and put it in $protections.
Definition: ApiQueryInfo.php:462
ApiQueryInfo\getUnblockToken
static getUnblockToken( $pageid, $title)
Definition: ApiQueryInfo.php:191
ApiQueryInfo\__construct
__construct( $query, $moduleName)
Definition: ApiQueryInfo.php:51
ApiQueryInfo\$pageTouched
$pageTouched
Definition: ApiQueryInfo.php:42
ApiQueryInfo\$showZeroWatchers
$showZeroWatchers
Definition: ApiQueryInfo.php:47
ApiQueryInfo\resetTokenCache
static resetTokenCache()
Definition: ApiQueryInfo.php:114
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:2530
ApiQueryInfo\$tokenFunctions
$tokenFunctions
Definition: ApiQueryInfo.php:49
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:50
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:205
ApiQueryBase\select
select( $method, $extraQuery=array())
Execute a SELECT query based on the values in the internal arrays.
Definition: ApiQueryBase.php:274
NS_FILE
const NS_FILE
Definition: Defines.php:85
ApiQueryInfo\getExamples
getExamples()
Returns usage examples for this module.
Definition: ApiQueryInfo.php:891
ContextSource\getRequest
getRequest()
Get the WebRequest object.
Definition: ContextSource.php:77
$wgContLang
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the content language as $wgContLang
Definition: design.txt:56
ApiQueryBase\addOption
addOption( $name, $value=null)
Add an option such as LIMIT or USE INDEX.
Definition: ApiQueryBase.php:252
ContextSource\getUser
getUser()
Get the User object.
Definition: ContextSource.php:132
ApiQueryInfo
A query module to show basic page information.
Definition: ApiQueryInfo.php:32
ApiQueryBase\addFieldsIf
addFieldsIf( $value, $condition)
Same as addFields(), but add the fields only if a condition is met.
Definition: ApiQueryBase.php:131
ApiBase\PROP_LIST
const PROP_LIST
Definition: ApiBase.php:73
$lb
if( $wgAPIRequestLog) $lb
Definition: api.php:126
ApiQueryInfo\getEmailToken
static getEmailToken( $pageid, $title)
Definition: ApiQueryInfo.php:196
ApiQueryInfo\getProtectToken
static getProtectToken( $pageid, $title)
Definition: ApiQueryInfo.php:149
ApiQueryInfo\getDescription
getDescription()
Returns the description string for this module.
Definition: ApiQueryInfo.php:887
ApiQueryBase
This is a base class for all Query modules.
Definition: ApiQueryBase.php:34
TS_ISO_8601
const TS_ISO_8601
ISO 8601 format with no timezone: 1986-02-09T20:00:00Z.
Definition: GlobalFunctions.php:2495
ApiQueryInfo\getWatchToken
static getWatchToken( $pageid, $title)
Definition: ApiQueryInfo.php:224
ApiQueryInfo\$pageRestrictions
$pageRestrictions
Definition: ApiQueryInfo.php:42
ApiQueryBase\getDB
getDB()
Get the Query database connection (read-only)
Definition: ApiQueryBase.php:417
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:270
wfRunHooks
wfRunHooks( $event, array $args=array(), $deprecatedVersion=null)
Call hook functions defined in $wgHooks.
Definition: GlobalFunctions.php:4058
ApiQueryBase\addTables
addTables( $tables, $alias=null)
Add a set of tables to the internal array.
Definition: ApiQueryBase.php:82
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
ApiQueryInfo\$fld_talkid
$fld_talkid
Definition: ApiQueryInfo.php:34
ApiQueryInfo\$pageCounter
$pageCounter
Definition: ApiQueryInfo.php:40
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
ApiQueryInfo\$fld_displaytitle
$fld_displaytitle
Definition: ApiQueryInfo.php:38
ApiQueryInfo\$titles
$titles
Definition: ApiQueryInfo.php:40
ApiBase\PROP_TYPE
const PROP_TYPE
Definition: ApiBase.php:74
ApiQueryInfo\$notificationtimestamps
$notificationtimestamps
Definition: ApiQueryInfo.php:45
ApiQueryInfo\getDeleteToken
static getDeleteToken( $pageid, $title)
Definition: ApiQueryInfo.php:135
ApiQueryInfo\getTSIDs
getTSIDs()
Get talk page IDs (if requested) and subject page IDs (if requested) and put them in $talkids and $su...
Definition: ApiQueryInfo.php:610
ApiQueryInfo\$everything
$everything
Definition: ApiQueryInfo.php:40
ApiQueryInfo\getWatchedInfo
getWatchedInfo()
Get information about watched status and put it in $this->watched and $this->notificationtimestamps.
Definition: ApiQueryInfo.php:673
ApiQueryInfo\$watched
$watched
Definition: ApiQueryInfo.php:45
Title\compare
static compare( $a, $b)
Callback for usort() to do title sorts by (namespace, title)
Definition: Title.php:738
ApiQueryInfo\$params
$params
Definition: ApiQueryInfo.php:40
ApiQueryInfo\getHelpUrls
getHelpUrls()
Definition: ApiQueryInfo.php:898
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:422
ApiBase\extractRequestParams
extractRequestParams( $parseLimit=true)
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:687
$title
presenting them properly to the user as errors is done by the caller $title
Definition: hooks.txt:1324
ApiQueryInfo\getImportToken
static getImportToken( $pageid, $title)
Definition: ApiQueryInfo.php:210
ApiQueryInfo\$pageIsNew
$pageIsNew
Definition: ApiQueryInfo.php:42
ApiBase\dieContinueUsageIf
dieContinueUsageIf( $condition)
Die with the $prefix.
Definition: ApiBase.php:1969
ApiQueryInfo\getTokenFunctions
getTokenFunctions()
Get an array mapping token names to their handler functions.
Definition: ApiQueryInfo.php:85
ApiQueryInfo\getResultProperties
getResultProperties()
Returns possible properties in the result, grouped by the value of the prop parameter that shows them...
Definition: ApiQueryInfo.php:821
ApiQueryInfo\$fld_preload
$fld_preload
Definition: ApiQueryInfo.php:38
ApiBase\addTokenProperties
static addTokenProperties(&$props, $tokenFunctions)
Add token properties to the array used by getResultProperties, based on a token functions mapping.
Definition: ApiBase.php:646
ApiBase\PROP_NULLABLE
const PROP_NULLABLE
Definition: ApiBase.php:76
ApiQueryBase\addWhereFld
addWhereFld( $field, $value)
Equivalent to addWhere(array($field => $value))
Definition: ApiQueryBase.php:185
ApiQueryBase\getPageSet
getPageSet()
Get the PageSet object to work on.
Definition: ApiQueryBase.php:441
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:237
ApiQueryInfo\$fld_watchers
$fld_watchers
Definition: ApiQueryInfo.php:36
ApiQueryInfo\getCacheMode
getCacheMode( $params)
Get the cache mode for the data generated by this module.
Definition: ApiQueryInfo.php:750
ApiBase\setWarning
setWarning( $warning)
Set warning section for this module.
Definition: ApiBase.php:245
ApiQueryInfo\$fld_subjectid
$fld_subjectid
Definition: ApiQueryInfo.php:35
ApiQueryInfo\$fld_watched
$fld_watched
Definition: ApiQueryInfo.php:36
ApiQueryInfo\getDisplayTitle
getDisplayTitle()
Definition: ApiQueryInfo.php:648
ApiQueryInfo\$fld_protection
$fld_protection
Definition: ApiQueryInfo.php:34
ApiQueryInfo\$watchers
$watchers
Definition: ApiQueryInfo.php:45
ApiQueryInfo\getEditToken
static getEditToken( $pageid, $title)
Definition: ApiQueryInfo.php:118
ApiQueryInfo\$pageLatest
$pageLatest
Definition: ApiQueryInfo.php:42
ApiBase\PARAM_DFLT
const PARAM_DFLT
Definition: ApiBase.php:46
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
ApiQueryInfo\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiQueryInfo.php:773
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
Definition: ApiBase.php:48
ApiQueryInfo\$protections
$protections
Definition: ApiQueryInfo.php:45
ApiQueryInfo\getParamDescription
getParamDescription()
Returns an array of parameter descriptions.
Definition: ApiQueryInfo.php:801
$source
if(PHP_SAPI !='cli') $source
Definition: mwdoc-filter.php:18
ApiQueryInfo\getMoveToken
static getMoveToken( $pageid, $title)
Definition: ApiQueryInfo.php:163
ApiQueryInfo\getOptionsToken
static getOptionsToken( $pageid, $title)
Definition: ApiQueryInfo.php:238
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:188
ApiQueryInfo\$fld_notificationtimestamp
$fld_notificationtimestamp
Definition: ApiQueryInfo.php:37
ApiQueryBase\addWhere
addWhere( $value)
Add a set of WHERE clauses to the internal array.
Definition: ApiQueryBase.php:152
$t
$t
Definition: testCompression.php:65
ApiQueryBase\setContinueEnumParameter
setContinueEnumParameter( $paramName, $paramValue)
Set a query-continue value.
Definition: ApiQueryBase.php:404
ApiQueryInfo\$pageIsRedir
$pageIsRedir
Definition: ApiQueryInfo.php:42
ApiQueryInfo\$cachedTokens
static $cachedTokens
Definition: ApiQueryInfo.php:112
MWNamespace\getTalk
static getTalk( $index)
Get the talk namespace index for a given namespace.
Definition: Namespace.php:118
ApiQueryInfo\getBlockToken
static getBlockToken( $pageid, $title)
Definition: ApiQueryInfo.php:177
$query
return true to allow those checks to and false if checking is done use this to change the tables headers temp or archived zone change it to an object instance and return false override the list derivative used the name of the old file when set the default code will be skipped add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition: hooks.txt:1105
MWNamespace\getSubject
static getSubject( $index)
Get the subject namespace index for a given namespace Special namespaces (NS_MEDIA,...
Definition: Namespace.php:132
ApiQueryInfo\$fld_readable
$fld_readable
Definition: ApiQueryInfo.php:36
ApiQueryInfo\requestExtraData
requestExtraData( $pageSet)
Definition: ApiQueryInfo.php:59
ApiQueryInfo\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiQueryInfo.php:252
$res
$res
Definition: database.txt:21
ApiQueryInfo\getWatcherInfo
getWatcherInfo()
Get the count of watchers and put it in $this->watchers.
Definition: ApiQueryInfo.php:713
ApiQueryInfo\$pageLength
$pageLength
Definition: ApiQueryInfo.php:42
wfExpandUrl
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
Definition: GlobalFunctions.php:544