[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/api/ -> ApiQueryWatchlist.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   * This query action allows clients to retrieve a list of recently modified pages
  29   * that are part of the logged-in user's watchlist.
  30   *
  31   * @ingroup API
  32   */
  33  class ApiQueryWatchlist extends ApiQueryGeneratorBase {
  34  
  35  	public function __construct( ApiQuery $query, $moduleName ) {
  36          parent::__construct( $query, $moduleName, 'wl' );
  37      }
  38  
  39  	public function execute() {
  40          $this->run();
  41      }
  42  
  43  	public function executeGenerator( $resultPageSet ) {
  44          $this->run( $resultPageSet );
  45      }
  46  
  47      private $fld_ids = false, $fld_title = false, $fld_patrol = false,
  48          $fld_flags = false, $fld_timestamp = false, $fld_user = false,
  49          $fld_comment = false, $fld_parsedcomment = false, $fld_sizes = false,
  50          $fld_notificationtimestamp = false, $fld_userid = false,
  51          $fld_loginfo = false;
  52  
  53      /**
  54       * @param ApiPageSet $resultPageSet
  55       * @return void
  56       */
  57  	private function run( $resultPageSet = null ) {
  58          $this->selectNamedDB( 'watchlist', DB_SLAVE, 'watchlist' );
  59  
  60          $params = $this->extractRequestParams();
  61  
  62          $user = $this->getUser();
  63          $wlowner = $this->getWatchlistUser( $params );
  64  
  65          if ( !is_null( $params['prop'] ) && is_null( $resultPageSet ) ) {
  66              $prop = array_flip( $params['prop'] );
  67  
  68              $this->fld_ids = isset( $prop['ids'] );
  69              $this->fld_title = isset( $prop['title'] );
  70              $this->fld_flags = isset( $prop['flags'] );
  71              $this->fld_user = isset( $prop['user'] );
  72              $this->fld_userid = isset( $prop['userid'] );
  73              $this->fld_comment = isset( $prop['comment'] );
  74              $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
  75              $this->fld_timestamp = isset( $prop['timestamp'] );
  76              $this->fld_sizes = isset( $prop['sizes'] );
  77              $this->fld_patrol = isset( $prop['patrol'] );
  78              $this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] );
  79              $this->fld_loginfo = isset( $prop['loginfo'] );
  80  
  81              if ( $this->fld_patrol ) {
  82                  if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
  83                      $this->dieUsage( 'patrol property is not available', 'patrol' );
  84                  }
  85              }
  86          }
  87  
  88          $this->addFields( array(
  89              'rc_id',
  90              'rc_namespace',
  91              'rc_title',
  92              'rc_timestamp',
  93              'rc_type',
  94              'rc_deleted',
  95          ) );
  96  
  97          if ( is_null( $resultPageSet ) ) {
  98              $this->addFields( array(
  99                  'rc_cur_id',
 100                  'rc_this_oldid',
 101                  'rc_last_oldid',
 102              ) );
 103  
 104              $this->addFieldsIf( array( 'rc_type', 'rc_minor', 'rc_bot' ), $this->fld_flags );
 105              $this->addFieldsIf( 'rc_user', $this->fld_user || $this->fld_userid );
 106              $this->addFieldsIf( 'rc_user_text', $this->fld_user );
 107              $this->addFieldsIf( 'rc_comment', $this->fld_comment || $this->fld_parsedcomment );
 108              $this->addFieldsIf( 'rc_patrolled', $this->fld_patrol );
 109              $this->addFieldsIf( array( 'rc_old_len', 'rc_new_len' ), $this->fld_sizes );
 110              $this->addFieldsIf( 'wl_notificationtimestamp', $this->fld_notificationtimestamp );
 111              $this->addFieldsIf(
 112                  array( 'rc_logid', 'rc_log_type', 'rc_log_action', 'rc_params' ),
 113                  $this->fld_loginfo
 114              );
 115          } elseif ( $params['allrev'] ) {
 116              $this->addFields( 'rc_this_oldid' );
 117          } else {
 118              $this->addFields( 'rc_cur_id' );
 119          }
 120  
 121          $this->addTables( array(
 122              'recentchanges',
 123              'watchlist',
 124          ) );
 125  
 126          $userId = $wlowner->getId();
 127          $this->addJoinConds( array( 'watchlist' => array( 'INNER JOIN',
 128              array(
 129                  'wl_user' => $userId,
 130                  'wl_namespace=rc_namespace',
 131                  'wl_title=rc_title'
 132              )
 133          ) ) );
 134  
 135          $db = $this->getDB();
 136  
 137          $this->addTimestampWhereRange( 'rc_timestamp', $params['dir'],
 138              $params['start'], $params['end'] );
 139          // Include in ORDER BY for uniqueness
 140          $this->addWhereRange( 'rc_id', $params['dir'], null, null );
 141  
 142          if ( !is_null( $params['continue'] ) ) {
 143              $cont = explode( '|', $params['continue'] );
 144              $this->dieContinueUsageIf( count( $cont ) != 2 );
 145              $op = ( $params['dir'] === 'newer' ? '>' : '<' );
 146              $continueTimestamp = $db->addQuotes( $db->timestamp( $cont[0] ) );
 147              $continueId = (int)$cont[1];
 148              $this->dieContinueUsageIf( $continueId != $cont[1] );
 149              $this->addWhere( "rc_timestamp $op $continueTimestamp OR " .
 150                  "(rc_timestamp = $continueTimestamp AND " .
 151                  "rc_id $op= $continueId)"
 152              );
 153          }
 154  
 155          $this->addWhereFld( 'wl_namespace', $params['namespace'] );
 156  
 157          if ( !$params['allrev'] ) {
 158              $this->addTables( 'page' );
 159              $this->addJoinConds( array( 'page' => array( 'LEFT JOIN', 'rc_cur_id=page_id' ) ) );
 160              $this->addWhere( 'rc_this_oldid=page_latest OR rc_type=' . RC_LOG );
 161          }
 162  
 163          if ( !is_null( $params['show'] ) ) {
 164              $show = array_flip( $params['show'] );
 165  
 166              /* Check for conflicting parameters. */
 167              if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) )
 168                  || ( isset( $show['bot'] ) && isset( $show['!bot'] ) )
 169                  || ( isset( $show['anon'] ) && isset( $show['!anon'] ) )
 170                  || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
 171                  || ( isset( $show['unread'] ) && isset( $show['!unread'] ) )
 172              ) {
 173                  $this->dieUsageMsg( 'show' );
 174              }
 175  
 176              // Check permissions.
 177              if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) {
 178                  if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
 179                      $this->dieUsage(
 180                          'You need the patrol right to request the patrolled flag',
 181                          'permissiondenied'
 182                      );
 183                  }
 184              }
 185  
 186              /* Add additional conditions to query depending upon parameters. */
 187              $this->addWhereIf( 'rc_minor = 0', isset( $show['!minor'] ) );
 188              $this->addWhereIf( 'rc_minor != 0', isset( $show['minor'] ) );
 189              $this->addWhereIf( 'rc_bot = 0', isset( $show['!bot'] ) );
 190              $this->addWhereIf( 'rc_bot != 0', isset( $show['bot'] ) );
 191              $this->addWhereIf( 'rc_user = 0', isset( $show['anon'] ) );
 192              $this->addWhereIf( 'rc_user != 0', isset( $show['!anon'] ) );
 193              $this->addWhereIf( 'rc_patrolled = 0', isset( $show['!patrolled'] ) );
 194              $this->addWhereIf( 'rc_patrolled != 0', isset( $show['patrolled'] ) );
 195              $this->addWhereIf( 'wl_notificationtimestamp IS NOT NULL', isset( $show['unread'] ) );
 196              $this->addWhereIf( 'wl_notificationtimestamp IS NULL', isset( $show['!unread'] ) );
 197          }
 198  
 199          if ( !is_null( $params['type'] ) ) {
 200              try {
 201                  $this->addWhereFld( 'rc_type', RecentChange::parseToRCType( $params['type'] ) );
 202              } catch ( MWException $e ) {
 203                  ApiBase::dieDebug( __METHOD__, $e->getMessage() );
 204              }
 205          }
 206  
 207          if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
 208              $this->dieUsage( 'user and excludeuser cannot be used together', 'user-excludeuser' );
 209          }
 210          if ( !is_null( $params['user'] ) ) {
 211              $this->addWhereFld( 'rc_user_text', $params['user'] );
 212          }
 213          if ( !is_null( $params['excludeuser'] ) ) {
 214              $this->addWhere( 'rc_user_text != ' . $db->addQuotes( $params['excludeuser'] ) );
 215          }
 216  
 217          // This is an index optimization for mysql, as done in the Special:Watchlist page
 218          $this->addWhereIf(
 219              "rc_timestamp > ''",
 220              !isset( $params['start'] ) && !isset( $params['end'] ) && $db->getType() == 'mysql'
 221          );
 222  
 223          // Paranoia: avoid brute force searches (bug 17342)
 224          if ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ) {
 225              if ( !$user->isAllowed( 'deletedhistory' ) ) {
 226                  $bitmask = Revision::DELETED_USER;
 227              } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
 228                  $bitmask = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
 229              } else {
 230                  $bitmask = 0;
 231              }
 232              if ( $bitmask ) {
 233                  $this->addWhere( $this->getDB()->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask" );
 234              }
 235          }
 236  
 237          // LogPage::DELETED_ACTION hides the affected page, too. So hide those
 238          // entirely from the watchlist, or someone could guess the title.
 239          if ( !$user->isAllowed( 'deletedhistory' ) ) {
 240              $bitmask = LogPage::DELETED_ACTION;
 241          } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) {
 242              $bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
 243          } else {
 244              $bitmask = 0;
 245          }
 246          if ( $bitmask ) {
 247              $this->addWhere( $this->getDB()->makeList( array(
 248                  'rc_type != ' . RC_LOG,
 249                  $this->getDB()->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask",
 250              ), LIST_OR ) );
 251          }
 252  
 253          $this->addOption( 'LIMIT', $params['limit'] + 1 );
 254  
 255          $ids = array();
 256          $count = 0;
 257          $res = $this->select( __METHOD__ );
 258  
 259          foreach ( $res as $row ) {
 260              if ( ++$count > $params['limit'] ) {
 261                  // We've reached the one extra which shows that there are
 262                  // additional pages to be had. Stop here...
 263                  $this->setContinueEnumParameter( 'continue', "$row->rc_timestamp|$row->rc_id" );
 264                  break;
 265              }
 266  
 267              if ( is_null( $resultPageSet ) ) {
 268                  $vals = $this->extractRowInfo( $row );
 269                  $fit = $this->getResult()->addValue( array( 'query', $this->getModuleName() ), null, $vals );
 270                  if ( !$fit ) {
 271                      $this->setContinueEnumParameter( 'continue', "$row->rc_timestamp|$row->rc_id" );
 272                      break;
 273                  }
 274              } else {
 275                  if ( $params['allrev'] ) {
 276                      $ids[] = intval( $row->rc_this_oldid );
 277                  } else {
 278                      $ids[] = intval( $row->rc_cur_id );
 279                  }
 280              }
 281          }
 282  
 283          if ( is_null( $resultPageSet ) ) {
 284              $this->getResult()->setIndexedTagName_internal(
 285                  array( 'query', $this->getModuleName() ),
 286                  'item'
 287              );
 288          } elseif ( $params['allrev'] ) {
 289              $resultPageSet->populateFromRevisionIDs( $ids );
 290          } else {
 291              $resultPageSet->populateFromPageIDs( $ids );
 292          }
 293      }
 294  
 295  	private function extractRowInfo( $row ) {
 296          /* Determine the title of the page that has been changed. */
 297          $title = Title::makeTitle( $row->rc_namespace, $row->rc_title );
 298          $user = $this->getUser();
 299  
 300          /* Our output data. */
 301          $vals = array();
 302          $type = intval( $row->rc_type );
 303          $vals['type'] = RecentChange::parseFromRCType( $type );
 304          $anyHidden = false;
 305  
 306          /* Create a new entry in the result for the title. */
 307          if ( $this->fld_title || $this->fld_ids ) {
 308              // These should already have been filtered out of the query, but just in case.
 309              if ( $type === RC_LOG && ( $row->rc_deleted & LogPage::DELETED_ACTION ) ) {
 310                  $vals['actionhidden'] = '';
 311                  $anyHidden = true;
 312              }
 313              if ( $type !== RC_LOG ||
 314                  LogEventsList::userCanBitfield( $row->rc_deleted, LogPage::DELETED_ACTION, $user )
 315              ) {
 316                  if ( $this->fld_title ) {
 317                      ApiQueryBase::addTitleInfo( $vals, $title );
 318                  }
 319                  if ( $this->fld_ids ) {
 320                      $vals['pageid'] = intval( $row->rc_cur_id );
 321                      $vals['revid'] = intval( $row->rc_this_oldid );
 322                      $vals['old_revid'] = intval( $row->rc_last_oldid );
 323                  }
 324              }
 325          }
 326  
 327          /* Add user data and 'anon' flag, if user is anonymous. */
 328          if ( $this->fld_user || $this->fld_userid ) {
 329              if ( $row->rc_deleted & Revision::DELETED_USER ) {
 330                  $vals['userhidden'] = '';
 331                  $anyHidden = true;
 332              }
 333              if ( Revision::userCanBitfield( $row->rc_deleted, Revision::DELETED_USER, $user ) ) {
 334                  if ( $this->fld_userid ) {
 335                      $vals['userid'] = $row->rc_user;
 336                      // for backwards compatibility
 337                      $vals['user'] = $row->rc_user;
 338                  }
 339  
 340                  if ( $this->fld_user ) {
 341                      $vals['user'] = $row->rc_user_text;
 342                  }
 343  
 344                  if ( !$row->rc_user ) {
 345                      $vals['anon'] = '';
 346                  }
 347              }
 348          }
 349  
 350          /* Add flags, such as new, minor, bot. */
 351          if ( $this->fld_flags ) {
 352              if ( $row->rc_bot ) {
 353                  $vals['bot'] = '';
 354              }
 355              if ( $row->rc_type == RC_NEW ) {
 356                  $vals['new'] = '';
 357              }
 358              if ( $row->rc_minor ) {
 359                  $vals['minor'] = '';
 360              }
 361          }
 362  
 363          /* Add sizes of each revision. (Only available on 1.10+) */
 364          if ( $this->fld_sizes ) {
 365              $vals['oldlen'] = intval( $row->rc_old_len );
 366              $vals['newlen'] = intval( $row->rc_new_len );
 367          }
 368  
 369          /* Add the timestamp. */
 370          if ( $this->fld_timestamp ) {
 371              $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $row->rc_timestamp );
 372          }
 373  
 374          if ( $this->fld_notificationtimestamp ) {
 375              $vals['notificationtimestamp'] = ( $row->wl_notificationtimestamp == null )
 376                  ? ''
 377                  : wfTimestamp( TS_ISO_8601, $row->wl_notificationtimestamp );
 378          }
 379  
 380          /* Add edit summary / log summary. */
 381          if ( $this->fld_comment || $this->fld_parsedcomment ) {
 382              if ( $row->rc_deleted & Revision::DELETED_COMMENT ) {
 383                  $vals['commenthidden'] = '';
 384                  $anyHidden = true;
 385              }
 386              if ( Revision::userCanBitfield( $row->rc_deleted, Revision::DELETED_COMMENT, $user ) ) {
 387                  if ( $this->fld_comment && isset( $row->rc_comment ) ) {
 388                      $vals['comment'] = $row->rc_comment;
 389                  }
 390  
 391                  if ( $this->fld_parsedcomment && isset( $row->rc_comment ) ) {
 392                      $vals['parsedcomment'] = Linker::formatComment( $row->rc_comment, $title );
 393                  }
 394              }
 395          }
 396  
 397          /* Add the patrolled flag */
 398          if ( $this->fld_patrol && $row->rc_patrolled == 1 ) {
 399              $vals['patrolled'] = '';
 400          }
 401  
 402          if ( $this->fld_patrol && ChangesList::isUnpatrolled( $row, $user ) ) {
 403              $vals['unpatrolled'] = '';
 404          }
 405  
 406          if ( $this->fld_loginfo && $row->rc_type == RC_LOG ) {
 407              if ( $row->rc_deleted & LogPage::DELETED_ACTION ) {
 408                  $vals['actionhidden'] = '';
 409                  $anyHidden = true;
 410              }
 411              if ( LogEventsList::userCanBitfield( $row->rc_deleted, LogPage::DELETED_ACTION, $user ) ) {
 412                  $vals['logid'] = intval( $row->rc_logid );
 413                  $vals['logtype'] = $row->rc_log_type;
 414                  $vals['logaction'] = $row->rc_log_action;
 415                  $logEntry = DatabaseLogEntry::newFromRow( (array)$row );
 416                  ApiQueryLogEvents::addLogParams(
 417                      $this->getResult(),
 418                      $vals,
 419                      $logEntry->getParameters(),
 420                      $logEntry->getType(),
 421                      $logEntry->getSubtype(),
 422                      $logEntry->getTimestamp()
 423                  );
 424              }
 425          }
 426  
 427          if ( $anyHidden && ( $row->rc_deleted & Revision::DELETED_RESTRICTED ) ) {
 428              $vals['suppressed'] = '';
 429          }
 430  
 431          return $vals;
 432      }
 433  
 434  	public function getAllowedParams() {
 435          return array(
 436              'allrev' => false,
 437              'start' => array(
 438                  ApiBase::PARAM_TYPE => 'timestamp'
 439              ),
 440              'end' => array(
 441                  ApiBase::PARAM_TYPE => 'timestamp'
 442              ),
 443              'namespace' => array(
 444                  ApiBase::PARAM_ISMULTI => true,
 445                  ApiBase::PARAM_TYPE => 'namespace'
 446              ),
 447              'user' => array(
 448                  ApiBase::PARAM_TYPE => 'user',
 449              ),
 450              'excludeuser' => array(
 451                  ApiBase::PARAM_TYPE => 'user',
 452              ),
 453              'dir' => array(
 454                  ApiBase::PARAM_DFLT => 'older',
 455                  ApiBase::PARAM_TYPE => array(
 456                      'newer',
 457                      'older'
 458                  )
 459              ),
 460              'limit' => array(
 461                  ApiBase::PARAM_DFLT => 10,
 462                  ApiBase::PARAM_TYPE => 'limit',
 463                  ApiBase::PARAM_MIN => 1,
 464                  ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
 465                  ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
 466              ),
 467              'prop' => array(
 468                  ApiBase::PARAM_ISMULTI => true,
 469                  ApiBase::PARAM_DFLT => 'ids|title|flags',
 470                  ApiBase::PARAM_TYPE => array(
 471                      'ids',
 472                      'title',
 473                      'flags',
 474                      'user',
 475                      'userid',
 476                      'comment',
 477                      'parsedcomment',
 478                      'timestamp',
 479                      'patrol',
 480                      'sizes',
 481                      'notificationtimestamp',
 482                      'loginfo',
 483                  )
 484              ),
 485              'show' => array(
 486                  ApiBase::PARAM_ISMULTI => true,
 487                  ApiBase::PARAM_TYPE => array(
 488                      'minor',
 489                      '!minor',
 490                      'bot',
 491                      '!bot',
 492                      'anon',
 493                      '!anon',
 494                      'patrolled',
 495                      '!patrolled',
 496                      'unread',
 497                      '!unread',
 498                  )
 499              ),
 500              'type' => array(
 501                  ApiBase::PARAM_ISMULTI => true,
 502                  ApiBase::PARAM_TYPE => array(
 503                      'edit',
 504                      'external',
 505                      'new',
 506                      'log',
 507                  )
 508              ),
 509              'owner' => array(
 510                  ApiBase::PARAM_TYPE => 'user'
 511              ),
 512              'token' => array(
 513                  ApiBase::PARAM_TYPE => 'string'
 514              ),
 515              'continue' => null,
 516          );
 517      }
 518  
 519  	public function getParamDescription() {
 520          $p = $this->getModulePrefix();
 521  
 522          return array(
 523              'allrev' => 'Include multiple revisions of the same page within given timeframe',
 524              'start' => 'The timestamp to start enumerating from',
 525              'end' => 'The timestamp to end enumerating',
 526              'namespace' => 'Filter changes to only the given namespace(s)',
 527              'user' => 'Only list changes by this user',
 528              'excludeuser' => 'Don\'t list changes by this user',
 529              'dir' => $this->getDirectionDescription( $p ),
 530              'limit' => 'How many total results to return per request',
 531              'prop' => array(
 532                  'Which additional items to get (non-generator mode only).',
 533                  ' ids                    - Adds revision ids and page ids',
 534                  ' title                  - Adds title of the page',
 535                  ' flags                  - Adds flags for the edit',
 536                  ' user                   - Adds the user who made the edit',
 537                  ' userid                 - Adds user id of whom made the edit',
 538                  ' comment                - Adds comment of the edit',
 539                  ' parsedcomment          - Adds parsed comment of the edit',
 540                  ' timestamp              - Adds timestamp of the edit',
 541                  ' patrol                 - Tags edits that are patrolled',
 542                  ' sizes                  - Adds the old and new lengths of the page',
 543                  ' notificationtimestamp  - Adds timestamp of when the user was last notified about the edit',
 544                  ' loginfo                - Adds log information where appropriate',
 545              ),
 546              'show' => array(
 547                  'Show only items that meet this criteria.',
 548                  "For example, to see only minor edits done by logged-in users, set {$p}show=minor|!anon"
 549              ),
 550              'type' => array(
 551                  'Which types of changes to show',
 552                  ' edit           - Regular page edits',
 553                  ' external       - External changes',
 554                  ' new            - Page creations',
 555                  ' log            - Log entries',
 556              ),
 557              'owner' => 'The name of the user whose watchlist you\'d like to access',
 558              'token' => 'Give a security token (settable in preferences) to ' .
 559                  'allow access to another user\'s watchlist',
 560              'continue' => 'When more results are available, use this to continue',
 561          );
 562      }
 563  
 564  	public function getDescription() {
 565          return "Get all recent changes to pages in the logged in user's watchlist.";
 566      }
 567  
 568  	public function getExamples() {
 569          return array(
 570              'api.php?action=query&list=watchlist',
 571              'api.php?action=query&list=watchlist&wlprop=ids|title|timestamp|user|comment',
 572              'api.php?action=query&list=watchlist&wlallrev=&wlprop=ids|title|timestamp|user|comment',
 573              'api.php?action=query&generator=watchlist&prop=info',
 574              'api.php?action=query&generator=watchlist&gwlallrev=&prop=revisions&rvprop=timestamp|user',
 575              'api.php?action=query&list=watchlist&wlowner=Bob_Smith&wltoken=123ABC'
 576          );
 577      }
 578  
 579  	public function getHelpUrls() {
 580          return 'https://www.mediawiki.org/wiki/API:Watchlist';
 581      }
 582  }


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