[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/api/ -> ApiQueryInfo.php (source)

   1  <?php
   2  /**
   3   *
   4   *
   5   * Created on Sep 25, 2006
   6   *
   7   * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
   8   *
   9   * This program is free software; you can redistribute it and/or modify
  10   * it under the terms of the GNU General Public License as published by
  11   * the Free Software Foundation; either version 2 of the License, or
  12   * (at your option) any later version.
  13   *
  14   * This program is distributed in the hope that it will be useful,
  15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17   * GNU General Public License for more details.
  18   *
  19   * You should have received a copy of the GNU General Public License along
  20   * with this program; if not, write to the Free Software Foundation, Inc.,
  21   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22   * http://www.gnu.org/copyleft/gpl.html
  23   *
  24   * @file
  25   */
  26  
  27  /**
  28   * A query module to show basic page information.
  29   *
  30   * @ingroup API
  31   */
  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,
  37          $fld_notificationtimestamp = false,
  38          $fld_preload = false, $fld_displaytitle = false;
  39  
  40      private $params, $titles, $missing, $everything, $pageCounter;
  41  
  42      private $pageRestrictions, $pageIsRedir, $pageIsNew, $pageTouched,
  43          $pageLatest, $pageLength;
  44  
  45      private $protections, $watched, $watchers, $notificationtimestamps,
  46          $talkids, $subjectids, $displaytitles;
  47      private $showZeroWatchers = false;
  48  
  49      private $tokenFunctions;
  50  
  51  	public function __construct( ApiQuery $query, $moduleName ) {
  52          parent::__construct( $query, $moduleName, 'in' );
  53      }
  54  
  55      /**
  56       * @param ApiPageSet $pageSet
  57       * @return void
  58       */
  59  	public function requestExtraData( $pageSet ) {
  60          $pageSet->requestField( 'page_restrictions' );
  61          // when resolving redirects, no page will have this field
  62          if ( !$pageSet->isResolvingRedirects() ) {
  63              $pageSet->requestField( 'page_is_redirect' );
  64          }
  65          $pageSet->requestField( 'page_is_new' );
  66          $config = $this->getConfig();
  67          if ( !$config->get( 'DisableCounters' ) ) {
  68              $pageSet->requestField( 'page_counter' );
  69          }
  70          $pageSet->requestField( 'page_touched' );
  71          $pageSet->requestField( 'page_latest' );
  72          $pageSet->requestField( 'page_len' );
  73          if ( $config->get( 'ContentHandlerUseDB' ) ) {
  74              $pageSet->requestField( 'page_content_model' );
  75          }
  76      }
  77  
  78      /**
  79       * Get an array mapping token names to their handler functions.
  80       * The prototype for a token function is func($pageid, $title)
  81       * it should return a token or false (permission denied)
  82       * @deprecated since 1.24
  83       * @return array Array(tokenname => function)
  84       */
  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      /**
 115       * @deprecated since 1.24
 116       */
 117  	public static function resetTokenCache() {
 118          ApiQueryInfo::$cachedTokens = array();
 119      }
 120  
 121      /**
 122       * @deprecated since 1.24
 123       */
 124  	public static function getEditToken( $pageid, $title ) {
 125          // We could check for $title->userCan('edit') here,
 126          // but that's too expensive for this purpose
 127          // and would break caching
 128          global $wgUser;
 129          if ( !$wgUser->isAllowed( 'edit' ) ) {
 130              return false;
 131          }
 132  
 133          // The token is always the same, let's exploit that
 134          if ( !isset( ApiQueryInfo::$cachedTokens['edit'] ) ) {
 135              ApiQueryInfo::$cachedTokens['edit'] = $wgUser->getEditToken();
 136          }
 137  
 138          return ApiQueryInfo::$cachedTokens['edit'];
 139      }
 140  
 141      /**
 142       * @deprecated since 1.24
 143       */
 144  	public static function getDeleteToken( $pageid, $title ) {
 145          global $wgUser;
 146          if ( !$wgUser->isAllowed( 'delete' ) ) {
 147              return false;
 148          }
 149  
 150          // The token is always the same, let's exploit that
 151          if ( !isset( ApiQueryInfo::$cachedTokens['delete'] ) ) {
 152              ApiQueryInfo::$cachedTokens['delete'] = $wgUser->getEditToken();
 153          }
 154  
 155          return ApiQueryInfo::$cachedTokens['delete'];
 156      }
 157  
 158      /**
 159       * @deprecated since 1.24
 160       */
 161  	public static function getProtectToken( $pageid, $title ) {
 162          global $wgUser;
 163          if ( !$wgUser->isAllowed( 'protect' ) ) {
 164              return false;
 165          }
 166  
 167          // The token is always the same, let's exploit that
 168          if ( !isset( ApiQueryInfo::$cachedTokens['protect'] ) ) {
 169              ApiQueryInfo::$cachedTokens['protect'] = $wgUser->getEditToken();
 170          }
 171  
 172          return ApiQueryInfo::$cachedTokens['protect'];
 173      }
 174  
 175      /**
 176       * @deprecated since 1.24
 177       */
 178  	public static function getMoveToken( $pageid, $title ) {
 179          global $wgUser;
 180          if ( !$wgUser->isAllowed( 'move' ) ) {
 181              return false;
 182          }
 183  
 184          // The token is always the same, let's exploit that
 185          if ( !isset( ApiQueryInfo::$cachedTokens['move'] ) ) {
 186              ApiQueryInfo::$cachedTokens['move'] = $wgUser->getEditToken();
 187          }
 188  
 189          return ApiQueryInfo::$cachedTokens['move'];
 190      }
 191  
 192      /**
 193       * @deprecated since 1.24
 194       */
 195  	public static function getBlockToken( $pageid, $title ) {
 196          global $wgUser;
 197          if ( !$wgUser->isAllowed( 'block' ) ) {
 198              return false;
 199          }
 200  
 201          // The token is always the same, let's exploit that
 202          if ( !isset( ApiQueryInfo::$cachedTokens['block'] ) ) {
 203              ApiQueryInfo::$cachedTokens['block'] = $wgUser->getEditToken();
 204          }
 205  
 206          return ApiQueryInfo::$cachedTokens['block'];
 207      }
 208  
 209      /**
 210       * @deprecated since 1.24
 211       */
 212  	public static function getUnblockToken( $pageid, $title ) {
 213          // Currently, this is exactly the same as the block token
 214          return self::getBlockToken( $pageid, $title );
 215      }
 216  
 217      /**
 218       * @deprecated since 1.24
 219       */
 220  	public static function getEmailToken( $pageid, $title ) {
 221          global $wgUser;
 222          if ( !$wgUser->canSendEmail() || $wgUser->isBlockedFromEmailUser() ) {
 223              return false;
 224          }
 225  
 226          // The token is always the same, let's exploit that
 227          if ( !isset( ApiQueryInfo::$cachedTokens['email'] ) ) {
 228              ApiQueryInfo::$cachedTokens['email'] = $wgUser->getEditToken();
 229          }
 230  
 231          return ApiQueryInfo::$cachedTokens['email'];
 232      }
 233  
 234      /**
 235       * @deprecated since 1.24
 236       */
 237  	public static function getImportToken( $pageid, $title ) {
 238          global $wgUser;
 239          if ( !$wgUser->isAllowedAny( 'import', 'importupload' ) ) {
 240              return false;
 241          }
 242  
 243          // The token is always the same, let's exploit that
 244          if ( !isset( ApiQueryInfo::$cachedTokens['import'] ) ) {
 245              ApiQueryInfo::$cachedTokens['import'] = $wgUser->getEditToken();
 246          }
 247  
 248          return ApiQueryInfo::$cachedTokens['import'];
 249      }
 250  
 251      /**
 252       * @deprecated since 1.24
 253       */
 254  	public static function getWatchToken( $pageid, $title ) {
 255          global $wgUser;
 256          if ( !$wgUser->isLoggedIn() ) {
 257              return false;
 258          }
 259  
 260          // The token is always the same, let's exploit that
 261          if ( !isset( ApiQueryInfo::$cachedTokens['watch'] ) ) {
 262              ApiQueryInfo::$cachedTokens['watch'] = $wgUser->getEditToken( 'watch' );
 263          }
 264  
 265          return ApiQueryInfo::$cachedTokens['watch'];
 266      }
 267  
 268      /**
 269       * @deprecated since 1.24
 270       */
 271  	public static function getOptionsToken( $pageid, $title ) {
 272          global $wgUser;
 273          if ( !$wgUser->isLoggedIn() ) {
 274              return false;
 275          }
 276  
 277          // The token is always the same, let's exploit that
 278          if ( !isset( ApiQueryInfo::$cachedTokens['options'] ) ) {
 279              ApiQueryInfo::$cachedTokens['options'] = $wgUser->getEditToken();
 280          }
 281  
 282          return ApiQueryInfo::$cachedTokens['options'];
 283      }
 284  
 285  	public function execute() {
 286          $this->params = $this->extractRequestParams();
 287          if ( !is_null( $this->params['prop'] ) ) {
 288              $prop = array_flip( $this->params['prop'] );
 289              $this->fld_protection = isset( $prop['protection'] );
 290              $this->fld_watched = isset( $prop['watched'] );
 291              $this->fld_watchers = isset( $prop['watchers'] );
 292              $this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] );
 293              $this->fld_talkid = isset( $prop['talkid'] );
 294              $this->fld_subjectid = isset( $prop['subjectid'] );
 295              $this->fld_url = isset( $prop['url'] );
 296              $this->fld_readable = isset( $prop['readable'] );
 297              $this->fld_preload = isset( $prop['preload'] );
 298              $this->fld_displaytitle = isset( $prop['displaytitle'] );
 299          }
 300  
 301          $pageSet = $this->getPageSet();
 302          $this->titles = $pageSet->getGoodTitles();
 303          $this->missing = $pageSet->getMissingTitles();
 304          $this->everything = $this->titles + $this->missing;
 305          $result = $this->getResult();
 306  
 307          uasort( $this->everything, array( 'Title', 'compare' ) );
 308          if ( !is_null( $this->params['continue'] ) ) {
 309              // Throw away any titles we're gonna skip so they don't
 310              // clutter queries
 311              $cont = explode( '|', $this->params['continue'] );
 312              $this->dieContinueUsageIf( count( $cont ) != 2 );
 313              $conttitle = Title::makeTitleSafe( $cont[0], $cont[1] );
 314              foreach ( $this->everything as $pageid => $title ) {
 315                  if ( Title::compare( $title, $conttitle ) >= 0 ) {
 316                      break;
 317                  }
 318                  unset( $this->titles[$pageid] );
 319                  unset( $this->missing[$pageid] );
 320                  unset( $this->everything[$pageid] );
 321              }
 322          }
 323  
 324          $this->pageRestrictions = $pageSet->getCustomField( 'page_restrictions' );
 325          // when resolving redirects, no page will have this field
 326          $this->pageIsRedir = !$pageSet->isResolvingRedirects()
 327              ? $pageSet->getCustomField( 'page_is_redirect' )
 328              : array();
 329          $this->pageIsNew = $pageSet->getCustomField( 'page_is_new' );
 330  
 331          if ( !$this->getConfig()->get( 'DisableCounters' ) ) {
 332              $this->pageCounter = $pageSet->getCustomField( 'page_counter' );
 333          }
 334          $this->pageTouched = $pageSet->getCustomField( 'page_touched' );
 335          $this->pageLatest = $pageSet->getCustomField( 'page_latest' );
 336          $this->pageLength = $pageSet->getCustomField( 'page_len' );
 337  
 338          // Get protection info if requested
 339          if ( $this->fld_protection ) {
 340              $this->getProtectionInfo();
 341          }
 342  
 343          if ( $this->fld_watched || $this->fld_notificationtimestamp ) {
 344              $this->getWatchedInfo();
 345          }
 346  
 347          if ( $this->fld_watchers ) {
 348              $this->getWatcherInfo();
 349          }
 350  
 351          // Run the talkid/subjectid query if requested
 352          if ( $this->fld_talkid || $this->fld_subjectid ) {
 353              $this->getTSIDs();
 354          }
 355  
 356          if ( $this->fld_displaytitle ) {
 357              $this->getDisplayTitle();
 358          }
 359  
 360          /** @var $title Title */
 361          foreach ( $this->everything as $pageid => $title ) {
 362              $pageInfo = $this->extractPageInfo( $pageid, $title );
 363              $fit = $result->addValue( array(
 364                  'query',
 365                  'pages'
 366              ), $pageid, $pageInfo );
 367              if ( !$fit ) {
 368                  $this->setContinueEnumParameter( 'continue',
 369                      $title->getNamespace() . '|' .
 370                      $title->getText() );
 371                  break;
 372              }
 373          }
 374      }
 375  
 376      /**
 377       * Get a result array with information about a title
 378       * @param int $pageid Page ID (negative for missing titles)
 379       * @param Title $title
 380       * @return array
 381       */
 382  	private function extractPageInfo( $pageid, $title ) {
 383          $pageInfo = array();
 384          // $title->exists() needs pageid, which is not set for all title objects
 385          $titleExists = $pageid > 0;
 386          $ns = $title->getNamespace();
 387          $dbkey = $title->getDBkey();
 388  
 389          $pageInfo['contentmodel'] = $title->getContentModel();
 390          $pageInfo['pagelanguage'] = $title->getPageLanguage()->getCode();
 391  
 392          if ( $titleExists ) {
 393              $pageInfo['touched'] = wfTimestamp( TS_ISO_8601, $this->pageTouched[$pageid] );
 394              $pageInfo['lastrevid'] = intval( $this->pageLatest[$pageid] );
 395              $pageInfo['counter'] = $this->getConfig()->get( 'DisableCounters' )
 396                  ? ''
 397                  : intval( $this->pageCounter[$pageid] );
 398              $pageInfo['length'] = intval( $this->pageLength[$pageid] );
 399  
 400              if ( isset( $this->pageIsRedir[$pageid] ) && $this->pageIsRedir[$pageid] ) {
 401                  $pageInfo['redirect'] = '';
 402              }
 403              if ( $this->pageIsNew[$pageid] ) {
 404                  $pageInfo['new'] = '';
 405              }
 406          }
 407  
 408          if ( !is_null( $this->params['token'] ) ) {
 409              $tokenFunctions = $this->getTokenFunctions();
 410              $pageInfo['starttimestamp'] = wfTimestamp( TS_ISO_8601, time() );
 411              foreach ( $this->params['token'] as $t ) {
 412                  $val = call_user_func( $tokenFunctions[$t], $pageid, $title );
 413                  if ( $val === false ) {
 414                      $this->setWarning( "Action '$t' is not allowed for the current user" );
 415                  } else {
 416                      $pageInfo[$t . 'token'] = $val;
 417                  }
 418              }
 419          }
 420  
 421          if ( $this->fld_protection ) {
 422              $pageInfo['protection'] = array();
 423              if ( isset( $this->protections[$ns][$dbkey] ) ) {
 424                  $pageInfo['protection'] =
 425                      $this->protections[$ns][$dbkey];
 426              }
 427              $this->getResult()->setIndexedTagName( $pageInfo['protection'], 'pr' );
 428          }
 429  
 430          if ( $this->fld_watched && isset( $this->watched[$ns][$dbkey] ) ) {
 431              $pageInfo['watched'] = '';
 432          }
 433  
 434          if ( $this->fld_watchers ) {
 435              if ( isset( $this->watchers[$ns][$dbkey] ) ) {
 436                  $pageInfo['watchers'] = $this->watchers[$ns][$dbkey];
 437              } elseif ( $this->showZeroWatchers ) {
 438                  $pageInfo['watchers'] = 0;
 439              }
 440          }
 441  
 442          if ( $this->fld_notificationtimestamp ) {
 443              $pageInfo['notificationtimestamp'] = '';
 444              if ( isset( $this->notificationtimestamps[$ns][$dbkey] ) ) {
 445                  $pageInfo['notificationtimestamp'] =
 446                      wfTimestamp( TS_ISO_8601, $this->notificationtimestamps[$ns][$dbkey] );
 447              }
 448          }
 449  
 450          if ( $this->fld_talkid && isset( $this->talkids[$ns][$dbkey] ) ) {
 451              $pageInfo['talkid'] = $this->talkids[$ns][$dbkey];
 452          }
 453  
 454          if ( $this->fld_subjectid && isset( $this->subjectids[$ns][$dbkey] ) ) {
 455              $pageInfo['subjectid'] = $this->subjectids[$ns][$dbkey];
 456          }
 457  
 458          if ( $this->fld_url ) {
 459              $pageInfo['fullurl'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
 460              $pageInfo['editurl'] = wfExpandUrl( $title->getFullURL( 'action=edit' ), PROTO_CURRENT );
 461              $pageInfo['canonicalurl'] = wfExpandUrl( $title->getFullURL(), PROTO_CANONICAL );
 462          }
 463          if ( $this->fld_readable && $title->userCan( 'read', $this->getUser() ) ) {
 464              $pageInfo['readable'] = '';
 465          }
 466  
 467          if ( $this->fld_preload ) {
 468              if ( $titleExists ) {
 469                  $pageInfo['preload'] = '';
 470              } else {
 471                  $text = null;
 472                  wfRunHooks( 'EditFormPreloadText', array( &$text, &$title ) );
 473  
 474                  $pageInfo['preload'] = $text;
 475              }
 476          }
 477  
 478          if ( $this->fld_displaytitle ) {
 479              if ( isset( $this->displaytitles[$pageid] ) ) {
 480                  $pageInfo['displaytitle'] = $this->displaytitles[$pageid];
 481              } else {
 482                  $pageInfo['displaytitle'] = $title->getPrefixedText();
 483              }
 484          }
 485  
 486          return $pageInfo;
 487      }
 488  
 489      /**
 490       * Get information about protections and put it in $protections
 491       */
 492  	private function getProtectionInfo() {
 493          global $wgContLang;
 494          $this->protections = array();
 495          $db = $this->getDB();
 496  
 497          // Get normal protections for existing titles
 498          if ( count( $this->titles ) ) {
 499              $this->resetQueryParams();
 500              $this->addTables( 'page_restrictions' );
 501              $this->addFields( array( 'pr_page', 'pr_type', 'pr_level',
 502                  'pr_expiry', 'pr_cascade' ) );
 503              $this->addWhereFld( 'pr_page', array_keys( $this->titles ) );
 504  
 505              $res = $this->select( __METHOD__ );
 506              foreach ( $res as $row ) {
 507                  /** @var $title Title */
 508                  $title = $this->titles[$row->pr_page];
 509                  $a = array(
 510                      'type' => $row->pr_type,
 511                      'level' => $row->pr_level,
 512                      'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 )
 513                  );
 514                  if ( $row->pr_cascade ) {
 515                      $a['cascade'] = '';
 516                  }
 517                  $this->protections[$title->getNamespace()][$title->getDBkey()][] = $a;
 518              }
 519              // Also check old restrictions
 520              foreach ( $this->titles as $pageId => $title ) {
 521                  if ( $this->pageRestrictions[$pageId] ) {
 522                      $namespace = $title->getNamespace();
 523                      $dbKey = $title->getDBkey();
 524                      $restrictions = explode( ':', trim( $this->pageRestrictions[$pageId] ) );
 525                      foreach ( $restrictions as $restrict ) {
 526                          $temp = explode( '=', trim( $restrict ) );
 527                          if ( count( $temp ) == 1 ) {
 528                              // old old format should be treated as edit/move restriction
 529                              $restriction = trim( $temp[0] );
 530  
 531                              if ( $restriction == '' ) {
 532                                  continue;
 533                              }
 534                              $this->protections[$namespace][$dbKey][] = array(
 535                                  'type' => 'edit',
 536                                  'level' => $restriction,
 537                                  'expiry' => 'infinity',
 538                              );
 539                              $this->protections[$namespace][$dbKey][] = array(
 540                                  'type' => 'move',
 541                                  'level' => $restriction,
 542                                  'expiry' => 'infinity',
 543                              );
 544                          } else {
 545                              $restriction = trim( $temp[1] );
 546                              if ( $restriction == '' ) {
 547                                  continue;
 548                              }
 549                              $this->protections[$namespace][$dbKey][] = array(
 550                                  'type' => $temp[0],
 551                                  'level' => $restriction,
 552                                  'expiry' => 'infinity',
 553                              );
 554                          }
 555                      }
 556                  }
 557              }
 558          }
 559  
 560          // Get protections for missing titles
 561          if ( count( $this->missing ) ) {
 562              $this->resetQueryParams();
 563              $lb = new LinkBatch( $this->missing );
 564              $this->addTables( 'protected_titles' );
 565              $this->addFields( array( 'pt_title', 'pt_namespace', 'pt_create_perm', 'pt_expiry' ) );
 566              $this->addWhere( $lb->constructSet( 'pt', $db ) );
 567              $res = $this->select( __METHOD__ );
 568              foreach ( $res as $row ) {
 569                  $this->protections[$row->pt_namespace][$row->pt_title][] = array(
 570                      'type' => 'create',
 571                      'level' => $row->pt_create_perm,
 572                      'expiry' => $wgContLang->formatExpiry( $row->pt_expiry, TS_ISO_8601 )
 573                  );
 574              }
 575          }
 576  
 577          // Cascading protections
 578          $images = $others = array();
 579          foreach ( $this->everything as $title ) {
 580              if ( $title->getNamespace() == NS_FILE ) {
 581                  $images[] = $title->getDBkey();
 582              } else {
 583                  $others[] = $title;
 584              }
 585          }
 586  
 587          if ( count( $others ) ) {
 588              // Non-images: check templatelinks
 589              $lb = new LinkBatch( $others );
 590              $this->resetQueryParams();
 591              $this->addTables( array( 'page_restrictions', 'page', 'templatelinks' ) );
 592              $this->addFields( array( 'pr_type', 'pr_level', 'pr_expiry',
 593                  'page_title', 'page_namespace',
 594                  'tl_title', 'tl_namespace' ) );
 595              $this->addWhere( $lb->constructSet( 'tl', $db ) );
 596              $this->addWhere( 'pr_page = page_id' );
 597              $this->addWhere( 'pr_page = tl_from' );
 598              $this->addWhereFld( 'pr_cascade', 1 );
 599  
 600              $res = $this->select( __METHOD__ );
 601              foreach ( $res as $row ) {
 602                  $source = Title::makeTitle( $row->page_namespace, $row->page_title );
 603                  $this->protections[$row->tl_namespace][$row->tl_title][] = array(
 604                      'type' => $row->pr_type,
 605                      'level' => $row->pr_level,
 606                      'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 ),
 607                      'source' => $source->getPrefixedText()
 608                  );
 609              }
 610          }
 611  
 612          if ( count( $images ) ) {
 613              // Images: check imagelinks
 614              $this->resetQueryParams();
 615              $this->addTables( array( 'page_restrictions', 'page', 'imagelinks' ) );
 616              $this->addFields( array( 'pr_type', 'pr_level', 'pr_expiry',
 617                  'page_title', 'page_namespace', 'il_to' ) );
 618              $this->addWhere( 'pr_page = page_id' );
 619              $this->addWhere( 'pr_page = il_from' );
 620              $this->addWhereFld( 'pr_cascade', 1 );
 621              $this->addWhereFld( 'il_to', $images );
 622  
 623              $res = $this->select( __METHOD__ );
 624              foreach ( $res as $row ) {
 625                  $source = Title::makeTitle( $row->page_namespace, $row->page_title );
 626                  $this->protections[NS_FILE][$row->il_to][] = array(
 627                      'type' => $row->pr_type,
 628                      'level' => $row->pr_level,
 629                      'expiry' => $wgContLang->formatExpiry( $row->pr_expiry, TS_ISO_8601 ),
 630                      'source' => $source->getPrefixedText()
 631                  );
 632              }
 633          }
 634      }
 635  
 636      /**
 637       * Get talk page IDs (if requested) and subject page IDs (if requested)
 638       * and put them in $talkids and $subjectids
 639       */
 640  	private function getTSIDs() {
 641          $getTitles = $this->talkids = $this->subjectids = array();
 642  
 643          /** @var $t Title */
 644          foreach ( $this->everything as $t ) {
 645              if ( MWNamespace::isTalk( $t->getNamespace() ) ) {
 646                  if ( $this->fld_subjectid ) {
 647                      $getTitles[] = $t->getSubjectPage();
 648                  }
 649              } elseif ( $this->fld_talkid ) {
 650                  $getTitles[] = $t->getTalkPage();
 651              }
 652          }
 653          if ( !count( $getTitles ) ) {
 654              return;
 655          }
 656  
 657          $db = $this->getDB();
 658  
 659          // Construct a custom WHERE clause that matches
 660          // all titles in $getTitles
 661          $lb = new LinkBatch( $getTitles );
 662          $this->resetQueryParams();
 663          $this->addTables( 'page' );
 664          $this->addFields( array( 'page_title', 'page_namespace', 'page_id' ) );
 665          $this->addWhere( $lb->constructSet( 'page', $db ) );
 666          $res = $this->select( __METHOD__ );
 667          foreach ( $res as $row ) {
 668              if ( MWNamespace::isTalk( $row->page_namespace ) ) {
 669                  $this->talkids[MWNamespace::getSubject( $row->page_namespace )][$row->page_title] =
 670                      intval( $row->page_id );
 671              } else {
 672                  $this->subjectids[MWNamespace::getTalk( $row->page_namespace )][$row->page_title] =
 673                      intval( $row->page_id );
 674              }
 675          }
 676      }
 677  
 678  	private function getDisplayTitle() {
 679          $this->displaytitles = array();
 680  
 681          $pageIds = array_keys( $this->titles );
 682  
 683          if ( !count( $pageIds ) ) {
 684              return;
 685          }
 686  
 687          $this->resetQueryParams();
 688          $this->addTables( 'page_props' );
 689          $this->addFields( array( 'pp_page', 'pp_value' ) );
 690          $this->addWhereFld( 'pp_page', $pageIds );
 691          $this->addWhereFld( 'pp_propname', 'displaytitle' );
 692          $res = $this->select( __METHOD__ );
 693  
 694          foreach ( $res as $row ) {
 695              $this->displaytitles[$row->pp_page] = $row->pp_value;
 696          }
 697      }
 698  
 699      /**
 700       * Get information about watched status and put it in $this->watched
 701       * and $this->notificationtimestamps
 702       */
 703  	private function getWatchedInfo() {
 704          $user = $this->getUser();
 705  
 706          if ( $user->isAnon() || count( $this->everything ) == 0
 707              || !$user->isAllowed( 'viewmywatchlist' )
 708          ) {
 709              return;
 710          }
 711  
 712          $this->watched = array();
 713          $this->notificationtimestamps = array();
 714          $db = $this->getDB();
 715  
 716          $lb = new LinkBatch( $this->everything );
 717  
 718          $this->resetQueryParams();
 719          $this->addTables( array( 'watchlist' ) );
 720          $this->addFields( array( 'wl_title', 'wl_namespace' ) );
 721          $this->addFieldsIf( 'wl_notificationtimestamp', $this->fld_notificationtimestamp );
 722          $this->addWhere( array(
 723              $lb->constructSet( 'wl', $db ),
 724              'wl_user' => $user->getID()
 725          ) );
 726  
 727          $res = $this->select( __METHOD__ );
 728  
 729          foreach ( $res as $row ) {
 730              if ( $this->fld_watched ) {
 731                  $this->watched[$row->wl_namespace][$row->wl_title] = true;
 732              }
 733              if ( $this->fld_notificationtimestamp ) {
 734                  $this->notificationtimestamps[$row->wl_namespace][$row->wl_title] =
 735                      $row->wl_notificationtimestamp;
 736              }
 737          }
 738      }
 739  
 740      /**
 741       * Get the count of watchers and put it in $this->watchers
 742       */
 743  	private function getWatcherInfo() {
 744          if ( count( $this->everything ) == 0 ) {
 745              return;
 746          }
 747  
 748          $user = $this->getUser();
 749          $canUnwatchedpages = $user->isAllowed( 'unwatchedpages' );
 750          $unwatchedPageThreshold = $this->getConfig()->get( 'UnwatchedPageThreshold' );
 751          if ( !$canUnwatchedpages && !is_int( $unwatchedPageThreshold ) ) {
 752              return;
 753          }
 754  
 755          $this->watchers = array();
 756          $this->showZeroWatchers = $canUnwatchedpages;
 757          $db = $this->getDB();
 758  
 759          $lb = new LinkBatch( $this->everything );
 760  
 761          $this->resetQueryParams();
 762          $this->addTables( array( 'watchlist' ) );
 763          $this->addFields( array( 'wl_title', 'wl_namespace', 'count' => 'COUNT(*)' ) );
 764          $this->addWhere( array(
 765              $lb->constructSet( 'wl', $db )
 766          ) );
 767          $this->addOption( 'GROUP BY', array( 'wl_namespace', 'wl_title' ) );
 768          if ( !$canUnwatchedpages ) {
 769              $this->addOption( 'HAVING', "COUNT(*) >= $unwatchedPageThreshold" );
 770          }
 771  
 772          $res = $this->select( __METHOD__ );
 773  
 774          foreach ( $res as $row ) {
 775              $this->watchers[$row->wl_namespace][$row->wl_title] = (int)$row->count;
 776          }
 777      }
 778  
 779  	public function getCacheMode( $params ) {
 780          $publicProps = array(
 781              'protection',
 782              'talkid',
 783              'subjectid',
 784              'url',
 785              'preload',
 786              'displaytitle',
 787          );
 788          if ( !is_null( $params['prop'] ) ) {
 789              foreach ( $params['prop'] as $prop ) {
 790                  if ( !in_array( $prop, $publicProps ) ) {
 791                      return 'private';
 792                  }
 793              }
 794          }
 795          if ( !is_null( $params['token'] ) ) {
 796              return 'private';
 797          }
 798  
 799          return 'public';
 800      }
 801  
 802  	public function getAllowedParams() {
 803          return array(
 804              'prop' => array(
 805                  ApiBase::PARAM_DFLT => null,
 806                  ApiBase::PARAM_ISMULTI => true,
 807                  ApiBase::PARAM_TYPE => array(
 808                      'protection',
 809                      'talkid',
 810                      'watched', # private
 811                      'watchers', # private
 812                      'notificationtimestamp', # private
 813                      'subjectid',
 814                      'url',
 815                      'readable', # private
 816                      'preload',
 817                      'displaytitle',
 818                      // If you add more properties here, please consider whether they
 819                      // need to be added to getCacheMode()
 820                  ) ),
 821              'token' => array(
 822                  ApiBase::PARAM_DEPRECATED => true,
 823                  ApiBase::PARAM_DFLT => null,
 824                  ApiBase::PARAM_ISMULTI => true,
 825                  ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() )
 826              ),
 827              'continue' => null,
 828          );
 829      }
 830  
 831  	public function getParamDescription() {
 832          return array(
 833              'prop' => array(
 834                  'Which additional properties to get:',
 835                  ' protection            - List the protection level of each page',
 836                  ' talkid                - The page ID of the talk page for each non-talk page',
 837                  ' watched               - List the watched status of each page',
 838                  ' watchers              - The number of watchers, if allowed',
 839                  ' notificationtimestamp - The watchlist notification timestamp of each page',
 840                  ' subjectid             - The page ID of the parent page for each talk page',
 841                  ' url                   - Gives a full URL, an edit URL, and the canonical URL for each page',
 842                  ' readable              - Whether the user can read this page',
 843                  ' preload               - Gives the text returned by EditFormPreloadText',
 844                  ' displaytitle          - Gives the way the page title is actually displayed',
 845              ),
 846              'token' => 'Request a token to perform a data-modifying action on a page',
 847              'continue' => 'When more results are available, use this to continue',
 848          );
 849      }
 850  
 851  	public function getDescription() {
 852          return 'Get basic page information such as namespace, title, last touched date, ...';
 853      }
 854  
 855  	public function getExamples() {
 856          return array(
 857              'api.php?action=query&prop=info&titles=Main%20Page',
 858              'api.php?action=query&prop=info&inprop=protection&titles=Main%20Page'
 859          );
 860      }
 861  
 862  	public function getHelpUrls() {
 863          return 'https://www.mediawiki.org/wiki/API:Properties#info_.2F_in';
 864      }
 865  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1