[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

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

   1  <?php
   2  /**
   3   *
   4   *
   5   * Created on Oct 19, 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 action to enumerate the recent changes that were done to the wiki.
  29   * Various filters are supported.
  30   *
  31   * @ingroup API
  32   */
  33  class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
  34  
  35  	public function __construct( ApiQuery $query, $moduleName ) {
  36          parent::__construct( $query, $moduleName, 'rc' );
  37      }
  38  
  39      private $fld_comment = false, $fld_parsedcomment = false, $fld_user = false, $fld_userid = false,
  40          $fld_flags = false, $fld_timestamp = false, $fld_title = false, $fld_ids = false,
  41          $fld_sizes = false, $fld_redirect = false, $fld_patrolled = false, $fld_loginfo = false,
  42          $fld_tags = false, $fld_sha1 = false, $token = array();
  43  
  44      private $tokenFunctions;
  45  
  46      /**
  47       * Get an array mapping token names to their handler functions.
  48       * The prototype for a token function is func($pageid, $title, $rc)
  49       * it should return a token or false (permission denied)
  50       * @deprecated since 1.24
  51       * @return array Array(tokenname => function)
  52       */
  53  	protected function getTokenFunctions() {
  54          // Don't call the hooks twice
  55          if ( isset( $this->tokenFunctions ) ) {
  56              return $this->tokenFunctions;
  57          }
  58  
  59          // If we're in JSON callback mode, no tokens can be obtained
  60          if ( !is_null( $this->getMain()->getRequest()->getVal( 'callback' ) ) ) {
  61              return array();
  62          }
  63  
  64          $this->tokenFunctions = array(
  65              'patrol' => array( 'ApiQueryRecentChanges', 'getPatrolToken' )
  66          );
  67          wfRunHooks( 'APIQueryRecentChangesTokens', array( &$this->tokenFunctions ) );
  68  
  69          return $this->tokenFunctions;
  70      }
  71  
  72      /**
  73       * @deprecated since 1.24
  74       * @param int $pageid
  75       * @param Title $title
  76       * @param RecentChange|null $rc
  77       * @return bool|string
  78       */
  79  	public static function getPatrolToken( $pageid, $title, $rc = null ) {
  80          global $wgUser;
  81  
  82          $validTokenUser = false;
  83  
  84          if ( $rc ) {
  85              if ( ( $wgUser->useRCPatrol() && $rc->getAttribute( 'rc_type' ) == RC_EDIT ) ||
  86                  ( $wgUser->useNPPatrol() && $rc->getAttribute( 'rc_type' ) == RC_NEW )
  87              ) {
  88                  $validTokenUser = true;
  89              }
  90          } elseif ( $wgUser->useRCPatrol() || $wgUser->useNPPatrol() ) {
  91              $validTokenUser = true;
  92          }
  93  
  94          if ( $validTokenUser ) {
  95              // The patrol token is always the same, let's exploit that
  96              static $cachedPatrolToken = null;
  97  
  98              if ( is_null( $cachedPatrolToken ) ) {
  99                  $cachedPatrolToken = $wgUser->getEditToken( 'patrol' );
 100              }
 101  
 102              return $cachedPatrolToken;
 103          }
 104  
 105          return false;
 106      }
 107  
 108      /**
 109       * Sets internal state to include the desired properties in the output.
 110       * @param array $prop Associative array of properties, only keys are used here
 111       */
 112  	public function initProperties( $prop ) {
 113          $this->fld_comment = isset( $prop['comment'] );
 114          $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
 115          $this->fld_user = isset( $prop['user'] );
 116          $this->fld_userid = isset( $prop['userid'] );
 117          $this->fld_flags = isset( $prop['flags'] );
 118          $this->fld_timestamp = isset( $prop['timestamp'] );
 119          $this->fld_title = isset( $prop['title'] );
 120          $this->fld_ids = isset( $prop['ids'] );
 121          $this->fld_sizes = isset( $prop['sizes'] );
 122          $this->fld_redirect = isset( $prop['redirect'] );
 123          $this->fld_patrolled = isset( $prop['patrolled'] );
 124          $this->fld_loginfo = isset( $prop['loginfo'] );
 125          $this->fld_tags = isset( $prop['tags'] );
 126          $this->fld_sha1 = isset( $prop['sha1'] );
 127      }
 128  
 129  	public function execute() {
 130          $this->run();
 131      }
 132  
 133  	public function executeGenerator( $resultPageSet ) {
 134          $this->run( $resultPageSet );
 135      }
 136  
 137      /**
 138       * Generates and outputs the result of this query based upon the provided parameters.
 139       *
 140       * @param ApiPageSet $resultPageSet
 141       */
 142  	public function run( $resultPageSet = null ) {
 143          $user = $this->getUser();
 144          /* Get the parameters of the request. */
 145          $params = $this->extractRequestParams();
 146  
 147          /* Build our basic query. Namely, something along the lines of:
 148           * SELECT * FROM recentchanges WHERE rc_timestamp > $start
 149           *         AND rc_timestamp < $end AND rc_namespace = $namespace
 150           */
 151          $this->addTables( 'recentchanges' );
 152          $index = array( 'recentchanges' => 'rc_timestamp' ); // May change
 153          $this->addTimestampWhereRange( 'rc_timestamp', $params['dir'], $params['start'], $params['end'] );
 154  
 155          if ( !is_null( $params['continue'] ) ) {
 156              $cont = explode( '|', $params['continue'] );
 157              $this->dieContinueUsageIf( count( $cont ) != 2 );
 158              $db = $this->getDB();
 159              $timestamp = $db->addQuotes( $db->timestamp( $cont[0] ) );
 160              $id = intval( $cont[1] );
 161              $this->dieContinueUsageIf( $id != $cont[1] );
 162              $op = $params['dir'] === 'older' ? '<' : '>';
 163              $this->addWhere(
 164                  "rc_timestamp $op $timestamp OR " .
 165                  "(rc_timestamp = $timestamp AND " .
 166                  "rc_id $op= $id)"
 167              );
 168          }
 169  
 170          $order = $params['dir'] === 'older' ? 'DESC' : 'ASC';
 171          $this->addOption( 'ORDER BY', array(
 172              "rc_timestamp $order",
 173              "rc_id $order",
 174          ) );
 175  
 176          $this->addWhereFld( 'rc_namespace', $params['namespace'] );
 177  
 178          if ( !is_null( $params['type'] ) ) {
 179              try {
 180                  $this->addWhereFld( 'rc_type', RecentChange::parseToRCType( $params['type'] ) );
 181              } catch ( MWException $e ) {
 182                  ApiBase::dieDebug( __METHOD__, $e->getMessage() );
 183              }
 184          }
 185  
 186          if ( !is_null( $params['show'] ) ) {
 187              $show = array_flip( $params['show'] );
 188  
 189              /* Check for conflicting parameters. */
 190              if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) )
 191                  || ( isset( $show['bot'] ) && isset( $show['!bot'] ) )
 192                  || ( isset( $show['anon'] ) && isset( $show['!anon'] ) )
 193                  || ( isset( $show['redirect'] ) && isset( $show['!redirect'] ) )
 194                  || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
 195                  || ( isset( $show['patrolled'] ) && isset( $show['unpatrolled'] ) )
 196                  || ( isset( $show['!patrolled'] ) && isset( $show['unpatrolled'] ) )
 197              ) {
 198                  $this->dieUsageMsg( 'show' );
 199              }
 200  
 201              // Check permissions
 202              if ( isset( $show['patrolled'] )
 203                  || isset( $show['!patrolled'] )
 204                  || isset( $show['unpatrolled'] )
 205              ) {
 206                  if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
 207                      $this->dieUsage(
 208                          'You need the patrol right to request the patrolled flag',
 209                          'permissiondenied'
 210                      );
 211                  }
 212              }
 213  
 214              /* Add additional conditions to query depending upon parameters. */
 215              $this->addWhereIf( 'rc_minor = 0', isset( $show['!minor'] ) );
 216              $this->addWhereIf( 'rc_minor != 0', isset( $show['minor'] ) );
 217              $this->addWhereIf( 'rc_bot = 0', isset( $show['!bot'] ) );
 218              $this->addWhereIf( 'rc_bot != 0', isset( $show['bot'] ) );
 219              $this->addWhereIf( 'rc_user = 0', isset( $show['anon'] ) );
 220              $this->addWhereIf( 'rc_user != 0', isset( $show['!anon'] ) );
 221              $this->addWhereIf( 'rc_patrolled = 0', isset( $show['!patrolled'] ) );
 222              $this->addWhereIf( 'rc_patrolled != 0', isset( $show['patrolled'] ) );
 223              $this->addWhereIf( 'page_is_redirect = 1', isset( $show['redirect'] ) );
 224  
 225              if ( isset( $show['unpatrolled'] ) ) {
 226                  // See ChangesList:isUnpatrolled
 227                  if ( $user->useRCPatrol() ) {
 228                      $this->addWhere( 'rc_patrolled = 0' );
 229                  } elseif ( $user->useNPPatrol() ) {
 230                      $this->addWhere( 'rc_patrolled = 0' );
 231                      $this->addWhereFld( 'rc_type', RC_NEW );
 232                  }
 233              }
 234  
 235              // Don't throw log entries out the window here
 236              $this->addWhereIf(
 237                  'page_is_redirect = 0 OR page_is_redirect IS NULL',
 238                  isset( $show['!redirect'] )
 239              );
 240          }
 241  
 242          if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
 243              $this->dieUsage( 'user and excludeuser cannot be used together', 'user-excludeuser' );
 244          }
 245  
 246          if ( !is_null( $params['user'] ) ) {
 247              $this->addWhereFld( 'rc_user_text', $params['user'] );
 248              $index['recentchanges'] = 'rc_user_text';
 249          }
 250  
 251          if ( !is_null( $params['excludeuser'] ) ) {
 252              // We don't use the rc_user_text index here because
 253              // * it would require us to sort by rc_user_text before rc_timestamp
 254              // * the != condition doesn't throw out too many rows anyway
 255              $this->addWhere( 'rc_user_text != ' . $this->getDB()->addQuotes( $params['excludeuser'] ) );
 256          }
 257  
 258          /* Add the fields we're concerned with to our query. */
 259          $this->addFields( array(
 260              'rc_id',
 261              'rc_timestamp',
 262              'rc_namespace',
 263              'rc_title',
 264              'rc_cur_id',
 265              'rc_type',
 266              'rc_deleted'
 267          ) );
 268  
 269          $showRedirects = false;
 270          /* Determine what properties we need to display. */
 271          if ( !is_null( $params['prop'] ) ) {
 272              $prop = array_flip( $params['prop'] );
 273  
 274              /* Set up internal members based upon params. */
 275              $this->initProperties( $prop );
 276  
 277              if ( $this->fld_patrolled && !$user->useRCPatrol() && !$user->useNPPatrol() ) {
 278                  $this->dieUsage(
 279                      'You need the patrol right to request the patrolled flag',
 280                      'permissiondenied'
 281                  );
 282              }
 283  
 284              /* Add fields to our query if they are specified as a needed parameter. */
 285              $this->addFieldsIf( array( 'rc_this_oldid', 'rc_last_oldid' ), $this->fld_ids );
 286              $this->addFieldsIf( 'rc_comment', $this->fld_comment || $this->fld_parsedcomment );
 287              $this->addFieldsIf( 'rc_user', $this->fld_user || $this->fld_userid );
 288              $this->addFieldsIf( 'rc_user_text', $this->fld_user );
 289              $this->addFieldsIf( array( 'rc_minor', 'rc_type', 'rc_bot' ), $this->fld_flags );
 290              $this->addFieldsIf( array( 'rc_old_len', 'rc_new_len' ), $this->fld_sizes );
 291              $this->addFieldsIf( 'rc_patrolled', $this->fld_patrolled );
 292              $this->addFieldsIf(
 293                  array( 'rc_logid', 'rc_log_type', 'rc_log_action', 'rc_params' ),
 294                  $this->fld_loginfo
 295              );
 296              $showRedirects = $this->fld_redirect || isset( $show['redirect'] )
 297                  || isset( $show['!redirect'] );
 298          }
 299  
 300          if ( $this->fld_tags ) {
 301              $this->addTables( 'tag_summary' );
 302              $this->addJoinConds( array( 'tag_summary' => array( 'LEFT JOIN', array( 'rc_id=ts_rc_id' ) ) ) );
 303              $this->addFields( 'ts_tags' );
 304          }
 305  
 306          if ( $this->fld_sha1 ) {
 307              $this->addTables( 'revision' );
 308              $this->addJoinConds( array( 'revision' => array( 'LEFT JOIN',
 309                  array( 'rc_this_oldid=rev_id' ) ) ) );
 310              $this->addFields( array( 'rev_sha1', 'rev_deleted' ) );
 311          }
 312  
 313          if ( $params['toponly'] || $showRedirects ) {
 314              $this->addTables( 'page' );
 315              $this->addJoinConds( array( 'page' => array( 'LEFT JOIN',
 316                  array( 'rc_namespace=page_namespace', 'rc_title=page_title' ) ) ) );
 317              $this->addFields( 'page_is_redirect' );
 318  
 319              if ( $params['toponly'] ) {
 320                  $this->addWhere( 'rc_this_oldid = page_latest' );
 321              }
 322          }
 323  
 324          if ( !is_null( $params['tag'] ) ) {
 325              $this->addTables( 'change_tag' );
 326              $this->addJoinConds( array( 'change_tag' => array( 'INNER JOIN', array( 'rc_id=ct_rc_id' ) ) ) );
 327              $this->addWhereFld( 'ct_tag', $params['tag'] );
 328          }
 329  
 330          // Paranoia: avoid brute force searches (bug 17342)
 331          if ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ) {
 332              if ( !$user->isAllowed( 'deletedhistory' ) ) {
 333                  $bitmask = Revision::DELETED_USER;
 334              } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
 335                  $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
 336              } else {
 337                  $bitmask = 0;
 338              }
 339              if ( $bitmask ) {
 340                  $this->addWhere( $this->getDB()->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask" );
 341              }
 342          }
 343          if ( $this->getRequest()->getCheck( 'namespace' ) ) {
 344              // LogPage::DELETED_ACTION hides the affected page, too.
 345              if ( !$user->isAllowed( 'deletedhistory' ) ) {
 346                  $bitmask = LogPage::DELETED_ACTION;
 347              } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
 348                  $bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
 349              } else {
 350                  $bitmask = 0;
 351              }
 352              if ( $bitmask ) {
 353                  $this->addWhere( $this->getDB()->makeList( array(
 354                      'rc_type != ' . RC_LOG,
 355                      $this->getDB()->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask",
 356                  ), LIST_OR ) );
 357              }
 358          }
 359  
 360          $this->token = $params['token'];
 361          $this->addOption( 'LIMIT', $params['limit'] + 1 );
 362          $this->addOption( 'USE INDEX', $index );
 363  
 364          $count = 0;
 365          /* Perform the actual query. */
 366          $res = $this->select( __METHOD__ );
 367  
 368          $titles = array();
 369  
 370          $result = $this->getResult();
 371  
 372          /* Iterate through the rows, adding data extracted from them to our query result. */
 373          foreach ( $res as $row ) {
 374              if ( ++$count > $params['limit'] ) {
 375                  // We've reached the one extra which shows that there are
 376                  // additional pages to be had. Stop here...
 377                  $this->setContinueEnumParameter( 'continue', "$row->rc_timestamp|$row->rc_id" );
 378                  break;
 379              }
 380  
 381              if ( is_null( $resultPageSet ) ) {
 382                  /* Extract the data from a single row. */
 383                  $vals = $this->extractRowInfo( $row );
 384  
 385                  /* Add that row's data to our final output. */
 386                  if ( !$vals ) {
 387                      continue;
 388                  }
 389                  $fit = $result->addValue( array( 'query', $this->getModuleName() ), null, $vals );
 390                  if ( !$fit ) {
 391                      $this->setContinueEnumParameter( 'continue', "$row->rc_timestamp|$row->rc_id" );
 392                      break;
 393                  }
 394              } else {
 395                  $titles[] = Title::makeTitle( $row->rc_namespace, $row->rc_title );
 396              }
 397          }
 398  
 399          if ( is_null( $resultPageSet ) ) {
 400              /* Format the result */
 401              $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'rc' );
 402          } else {
 403              $resultPageSet->populateFromTitles( $titles );
 404          }
 405      }
 406  
 407      /**
 408       * Extracts from a single sql row the data needed to describe one recent change.
 409       *
 410       * @param stdClass $row The row from which to extract the data.
 411       * @return array An array mapping strings (descriptors) to their respective string values.
 412       * @access public
 413       */
 414  	public function extractRowInfo( $row ) {
 415          /* Determine the title of the page that has been changed. */
 416          $title = Title::makeTitle( $row->rc_namespace, $row->rc_title );
 417          $user = $this->getUser();
 418  
 419          /* Our output data. */
 420          $vals = array();
 421  
 422          $type = intval( $row->rc_type );
 423          $vals['type'] = RecentChange::parseFromRCType( $type );
 424  
 425          $anyHidden = false;
 426  
 427          /* Create a new entry in the result for the title. */
 428          if ( $this->fld_title || $this->fld_ids ) {
 429              if ( $type === RC_LOG && ( $row->rc_deleted & LogPage::DELETED_ACTION ) ) {
 430                  $vals['actionhidden'] = '';
 431                  $anyHidden = true;
 432              }
 433              if ( $type !== RC_LOG ||
 434                  LogEventsList::userCanBitfield( $row->rc_deleted, LogPage::DELETED_ACTION, $user )
 435              ) {
 436                  if ( $this->fld_title ) {
 437                      ApiQueryBase::addTitleInfo( $vals, $title );
 438                  }
 439                  if ( $this->fld_ids ) {
 440                      $vals['pageid'] = intval( $row->rc_cur_id );
 441                      $vals['revid'] = intval( $row->rc_this_oldid );
 442                      $vals['old_revid'] = intval( $row->rc_last_oldid );
 443                  }
 444              }
 445          }
 446  
 447          if ( $this->fld_ids ) {
 448              $vals['rcid'] = intval( $row->rc_id );
 449          }
 450  
 451          /* Add user data and 'anon' flag, if user is anonymous. */
 452          if ( $this->fld_user || $this->fld_userid ) {
 453              if ( $row->rc_deleted & Revision::DELETED_USER ) {
 454                  $vals['userhidden'] = '';
 455                  $anyHidden = true;
 456              }
 457              if ( Revision::userCanBitfield( $row->rc_deleted, Revision::DELETED_USER, $user ) ) {
 458                  if ( $this->fld_user ) {
 459                      $vals['user'] = $row->rc_user_text;
 460                  }
 461  
 462                  if ( $this->fld_userid ) {
 463                      $vals['userid'] = $row->rc_user;
 464                  }
 465  
 466                  if ( !$row->rc_user ) {
 467                      $vals['anon'] = '';
 468                  }
 469              }
 470          }
 471  
 472          /* Add flags, such as new, minor, bot. */
 473          if ( $this->fld_flags ) {
 474              if ( $row->rc_bot ) {
 475                  $vals['bot'] = '';
 476              }
 477              if ( $row->rc_type == RC_NEW ) {
 478                  $vals['new'] = '';
 479              }
 480              if ( $row->rc_minor ) {
 481                  $vals['minor'] = '';
 482              }
 483          }
 484  
 485          /* Add sizes of each revision. (Only available on 1.10+) */
 486          if ( $this->fld_sizes ) {
 487              $vals['oldlen'] = intval( $row->rc_old_len );
 488              $vals['newlen'] = intval( $row->rc_new_len );
 489          }
 490  
 491          /* Add the timestamp. */
 492          if ( $this->fld_timestamp ) {
 493              $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $row->rc_timestamp );
 494          }
 495  
 496          /* Add edit summary / log summary. */
 497          if ( $this->fld_comment || $this->fld_parsedcomment ) {
 498              if ( $row->rc_deleted & Revision::DELETED_COMMENT ) {
 499                  $vals['commenthidden'] = '';
 500                  $anyHidden = true;
 501              }
 502              if ( Revision::userCanBitfield( $row->rc_deleted, Revision::DELETED_COMMENT, $user ) ) {
 503                  if ( $this->fld_comment && isset( $row->rc_comment ) ) {
 504                      $vals['comment'] = $row->rc_comment;
 505                  }
 506  
 507                  if ( $this->fld_parsedcomment && isset( $row->rc_comment ) ) {
 508                      $vals['parsedcomment'] = Linker::formatComment( $row->rc_comment, $title );
 509                  }
 510              }
 511          }
 512  
 513          if ( $this->fld_redirect ) {
 514              if ( $row->page_is_redirect ) {
 515                  $vals['redirect'] = '';
 516              }
 517          }
 518  
 519          /* Add the patrolled flag */
 520          if ( $this->fld_patrolled && $row->rc_patrolled == 1 ) {
 521              $vals['patrolled'] = '';
 522          }
 523  
 524          if ( $this->fld_patrolled && ChangesList::isUnpatrolled( $row, $user ) ) {
 525              $vals['unpatrolled'] = '';
 526          }
 527  
 528          if ( $this->fld_loginfo && $row->rc_type == RC_LOG ) {
 529              if ( $row->rc_deleted & LogPage::DELETED_ACTION ) {
 530                  $vals['actionhidden'] = '';
 531                  $anyHidden = true;
 532              }
 533              if ( LogEventsList::userCanBitfield( $row->rc_deleted, LogPage::DELETED_ACTION, $user ) ) {
 534                  $vals['logid'] = intval( $row->rc_logid );
 535                  $vals['logtype'] = $row->rc_log_type;
 536                  $vals['logaction'] = $row->rc_log_action;
 537                  $logEntry = DatabaseLogEntry::newFromRow( (array)$row );
 538                  ApiQueryLogEvents::addLogParams(
 539                      $this->getResult(),
 540                      $vals,
 541                      $logEntry->getParameters(),
 542                      $logEntry->getType(),
 543                      $logEntry->getSubtype(),
 544                      $logEntry->getTimestamp()
 545                  );
 546              }
 547          }
 548  
 549          if ( $this->fld_tags ) {
 550              if ( $row->ts_tags ) {
 551                  $tags = explode( ',', $row->ts_tags );
 552                  $this->getResult()->setIndexedTagName( $tags, 'tag' );
 553                  $vals['tags'] = $tags;
 554              } else {
 555                  $vals['tags'] = array();
 556              }
 557          }
 558  
 559          if ( $this->fld_sha1 && $row->rev_sha1 !== null ) {
 560              if ( $row->rev_deleted & Revision::DELETED_TEXT ) {
 561                  $vals['sha1hidden'] = '';
 562                  $anyHidden = true;
 563              }
 564              if ( Revision::userCanBitfield( $row->rev_deleted, Revision::DELETED_TEXT, $user ) ) {
 565                  if ( $row->rev_sha1 !== '' ) {
 566                      $vals['sha1'] = wfBaseConvert( $row->rev_sha1, 36, 16, 40 );
 567                  } else {
 568                      $vals['sha1'] = '';
 569                  }
 570              }
 571          }
 572  
 573          if ( !is_null( $this->token ) ) {
 574              $tokenFunctions = $this->getTokenFunctions();
 575              foreach ( $this->token as $t ) {
 576                  $val = call_user_func( $tokenFunctions[$t], $row->rc_cur_id,
 577                      $title, RecentChange::newFromRow( $row ) );
 578                  if ( $val === false ) {
 579                      $this->setWarning( "Action '$t' is not allowed for the current user" );
 580                  } else {
 581                      $vals[$t . 'token'] = $val;
 582                  }
 583              }
 584          }
 585  
 586          if ( $anyHidden && ( $row->rc_deleted & Revision::DELETED_RESTRICTED ) ) {
 587              $vals['suppressed'] = '';
 588          }
 589  
 590          return $vals;
 591      }
 592  
 593  	public function getCacheMode( $params ) {
 594          if ( isset( $params['show'] ) ) {
 595              foreach ( $params['show'] as $show ) {
 596                  if ( $show === 'patrolled' || $show === '!patrolled' ) {
 597                      return 'private';
 598                  }
 599              }
 600          }
 601          if ( isset( $params['token'] ) ) {
 602              return 'private';
 603          }
 604          if ( $this->userCanSeeRevDel() ) {
 605              return 'private';
 606          }
 607          if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) {
 608              // formatComment() calls wfMessage() among other things
 609              return 'anon-public-user-private';
 610          }
 611  
 612          return 'public';
 613      }
 614  
 615  	public function getAllowedParams() {
 616          return array(
 617              'start' => array(
 618                  ApiBase::PARAM_TYPE => 'timestamp'
 619              ),
 620              'end' => array(
 621                  ApiBase::PARAM_TYPE => 'timestamp'
 622              ),
 623              'dir' => array(
 624                  ApiBase::PARAM_DFLT => 'older',
 625                  ApiBase::PARAM_TYPE => array(
 626                      'newer',
 627                      'older'
 628                  )
 629              ),
 630              'namespace' => array(
 631                  ApiBase::PARAM_ISMULTI => true,
 632                  ApiBase::PARAM_TYPE => 'namespace'
 633              ),
 634              'user' => array(
 635                  ApiBase::PARAM_TYPE => 'user'
 636              ),
 637              'excludeuser' => array(
 638                  ApiBase::PARAM_TYPE => 'user'
 639              ),
 640              'tag' => null,
 641              'prop' => array(
 642                  ApiBase::PARAM_ISMULTI => true,
 643                  ApiBase::PARAM_DFLT => 'title|timestamp|ids',
 644                  ApiBase::PARAM_TYPE => array(
 645                      'user',
 646                      'userid',
 647                      'comment',
 648                      'parsedcomment',
 649                      'flags',
 650                      'timestamp',
 651                      'title',
 652                      'ids',
 653                      'sizes',
 654                      'redirect',
 655                      'patrolled',
 656                      'loginfo',
 657                      'tags',
 658                      'sha1',
 659                  )
 660              ),
 661              'token' => array(
 662                  ApiBase::PARAM_DEPRECATED => true,
 663                  ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() ),
 664                  ApiBase::PARAM_ISMULTI => true
 665              ),
 666              'show' => array(
 667                  ApiBase::PARAM_ISMULTI => true,
 668                  ApiBase::PARAM_TYPE => array(
 669                      'minor',
 670                      '!minor',
 671                      'bot',
 672                      '!bot',
 673                      'anon',
 674                      '!anon',
 675                      'redirect',
 676                      '!redirect',
 677                      'patrolled',
 678                      '!patrolled',
 679                      'unpatrolled'
 680                  )
 681              ),
 682              'limit' => array(
 683                  ApiBase::PARAM_DFLT => 10,
 684                  ApiBase::PARAM_TYPE => 'limit',
 685                  ApiBase::PARAM_MIN => 1,
 686                  ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
 687                  ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
 688              ),
 689              'type' => array(
 690                  ApiBase::PARAM_ISMULTI => true,
 691                  ApiBase::PARAM_TYPE => array(
 692                      'edit',
 693                      'external',
 694                      'new',
 695                      'log'
 696                  )
 697              ),
 698              'toponly' => false,
 699              'continue' => null,
 700          );
 701      }
 702  
 703  	public function getParamDescription() {
 704          $p = $this->getModulePrefix();
 705  
 706          return array(
 707              'start' => 'The timestamp to start enumerating from',
 708              'end' => 'The timestamp to end enumerating',
 709              'dir' => $this->getDirectionDescription( $p ),
 710              'namespace' => 'Filter log entries to only this namespace(s)',
 711              'user' => 'Only list changes by this user',
 712              'excludeuser' => 'Don\'t list changes by this user',
 713              'prop' => array(
 714                  'Include additional pieces of information',
 715                  ' user           - Adds the user responsible for the edit and tags if they are an IP',
 716                  ' userid         - Adds the user id responsible for the edit',
 717                  ' comment        - Adds the comment for the edit',
 718                  ' parsedcomment  - Adds the parsed comment for the edit',
 719                  ' flags          - Adds flags for the edit',
 720                  ' timestamp      - Adds timestamp of the edit',
 721                  ' title          - Adds the page title of the edit',
 722                  ' ids            - Adds the page ID, recent changes ID and the new and old revision ID',
 723                  ' sizes          - Adds the new and old page length in bytes',
 724                  ' redirect       - Tags edit if page is a redirect',
 725                  ' patrolled      - Tags patrollable edits as being patrolled or unpatrolled',
 726                  ' loginfo        - Adds log information (logid, logtype, etc) to log entries',
 727                  ' tags           - Lists tags for the entry',
 728                  ' sha1           - Adds the content checksum for entries associated with a revision',
 729              ),
 730              'token' => 'Which tokens to obtain for each change',
 731              'show' => array(
 732                  'Show only items that meet this criteria.',
 733                  "For example, to see only minor edits done by logged-in users, set {$p}show=minor|!anon"
 734              ),
 735              'type' => 'Which types of changes to show',
 736              'limit' => 'How many total changes to return',
 737              'tag' => 'Only list changes tagged with this tag',
 738              'toponly' => 'Only list changes which are the latest revision',
 739              'continue' => 'When more results are available, use this to continue',
 740          );
 741      }
 742  
 743  	public function getDescription() {
 744          return 'Enumerate recent changes.';
 745      }
 746  
 747  	public function getExamples() {
 748          return array(
 749              'api.php?action=query&list=recentchanges'
 750          );
 751      }
 752  
 753  	public function getHelpUrls() {
 754          return 'https://www.mediawiki.org/wiki/API:Recentchanges';
 755      }
 756  }


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