5 * Created on Sep 25, 2006
7 * Copyright © 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
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.
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.
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
27 if ( !defined( 'MEDIAWIKI' ) ) {
28 // Eclipse helper - will be ignored in production
29 require_once( 'ApiQueryBase.php' );
33 * This query action allows clients to retrieve a list of recently modified pages
34 * that are part of the logged-in user's watchlist.
38 class ApiQueryWatchlist
extends ApiQueryGeneratorBase
{
40 public function __construct( $query, $moduleName ) {
41 parent
::__construct( $query, $moduleName, 'wl' );
44 public function execute() {
48 public function executeGenerator( $resultPageSet ) {
49 $this->run( $resultPageSet );
52 private $fld_ids = false, $fld_title = false, $fld_patrol = false, $fld_flags = false,
53 $fld_timestamp = false, $fld_user = false, $fld_comment = false, $fld_parsedcomment = false, $fld_sizes = false,
54 $fld_notificationtimestamp = false, $fld_userid = false;
57 * @param $resultPageSet ApiPageSet
60 private function run( $resultPageSet = null ) {
61 $this->selectNamedDB( 'watchlist', DB_SLAVE
, 'watchlist' );
63 $params = $this->extractRequestParams();
65 $user = $this->getWatchlistUser( $params );
67 if ( !is_null( $params['prop'] ) && is_null( $resultPageSet ) ) {
68 $prop = array_flip( $params['prop'] );
70 $this->fld_ids
= isset( $prop['ids'] );
71 $this->fld_title
= isset( $prop['title'] );
72 $this->fld_flags
= isset( $prop['flags'] );
73 $this->fld_user
= isset( $prop['user'] );
74 $this->fld_userid
= isset( $prop['userid'] );
75 $this->fld_comment
= isset( $prop['comment'] );
76 $this->fld_parsedcomment
= isset ( $prop['parsedcomment'] );
77 $this->fld_timestamp
= isset( $prop['timestamp'] );
78 $this->fld_sizes
= isset( $prop['sizes'] );
79 $this->fld_patrol
= isset( $prop['patrol'] );
80 $this->fld_notificationtimestamp
= isset( $prop['notificationtimestamp'] );
82 if ( $this->fld_patrol
) {
83 if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
84 $this->dieUsage( 'patrol property is not available', 'patrol' );
89 $this->addFields( array(
95 if ( is_null( $resultPageSet ) ) {
96 $this->addFields( array(
101 $this->addFieldsIf( 'rc_new', $this->fld_flags
);
102 $this->addFieldsIf( 'rc_minor', $this->fld_flags
);
103 $this->addFieldsIf( 'rc_bot', $this->fld_flags
);
104 $this->addFieldsIf( 'rc_user', $this->fld_user ||
$this->fld_userid
);
105 $this->addFieldsIf( 'rc_user_text', $this->fld_user
);
106 $this->addFieldsIf( 'rc_comment', $this->fld_comment ||
$this->fld_parsedcomment
);
107 $this->addFieldsIf( 'rc_patrolled', $this->fld_patrol
);
108 $this->addFieldsIf( 'rc_old_len', $this->fld_sizes
);
109 $this->addFieldsIf( 'rc_new_len', $this->fld_sizes
);
110 $this->addFieldsIf( 'wl_notificationtimestamp', $this->fld_notificationtimestamp
);
111 } elseif ( $params['allrev'] ) {
112 $this->addFields( 'rc_this_oldid' );
114 $this->addFields( 'rc_cur_id' );
117 $this->addTables( array(
123 $userId = $user->getId();
124 $this->addWhere( array(
125 'wl_namespace = rc_namespace',
126 'wl_title = rc_title',
127 'rc_cur_id = page_id',
128 'wl_user' => $userId,
132 $db = $this->getDB();
134 $this->addWhereRange( 'rc_timestamp', $params['dir'],
135 $db->timestamp( $params['start'] ),
136 $db->timestamp( $params['end'] ) );
137 $this->addWhereFld( 'wl_namespace', $params['namespace'] );
138 $this->addWhereIf( 'rc_this_oldid=page_latest', !$params['allrev'] );
140 if ( !is_null( $params['show'] ) ) {
141 $show = array_flip( $params['show'] );
143 /* Check for conflicting parameters. */
144 if ( ( isset ( $show['minor'] ) && isset ( $show['!minor'] ) )
145 ||
( isset ( $show['bot'] ) && isset ( $show['!bot'] ) )
146 ||
( isset ( $show['anon'] ) && isset ( $show['!anon'] ) )
147 ||
( isset ( $show['patrolled'] ) && isset ( $show['!patrolled'] ) )
150 $this->dieUsageMsg( array( 'show' ) );
153 // Check permissions.
154 if ( isset( $show['patrolled'] ) ||
isset( $show['!patrolled'] ) ) {
156 if ( !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol() ) {
157 $this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
161 /* Add additional conditions to query depending upon parameters. */
162 $this->addWhereIf( 'rc_minor = 0', isset( $show['!minor'] ) );
163 $this->addWhereIf( 'rc_minor != 0', isset( $show['minor'] ) );
164 $this->addWhereIf( 'rc_bot = 0', isset( $show['!bot'] ) );
165 $this->addWhereIf( 'rc_bot != 0', isset( $show['bot'] ) );
166 $this->addWhereIf( 'rc_user = 0', isset( $show['anon'] ) );
167 $this->addWhereIf( 'rc_user != 0', isset( $show['!anon'] ) );
168 $this->addWhereIf( 'rc_patrolled = 0', isset( $show['!patrolled'] ) );
169 $this->addWhereIf( 'rc_patrolled != 0', isset( $show['patrolled'] ) );
172 if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
173 $this->dieUsage( 'user and excludeuser cannot be used together', 'user-excludeuser' );
175 if ( !is_null( $params['user'] ) ) {
176 $this->addWhereFld( 'rc_user_text', $params['user'] );
178 if ( !is_null( $params['excludeuser'] ) ) {
179 $this->addWhere( 'rc_user_text != ' . $this->getDB()->addQuotes( $params['excludeuser'] ) );
184 // This is an index optimization for mysql, as done in the Special:Watchlist page
185 $this->addWhereIf( "rc_timestamp > ''", !isset( $params['start'] ) && !isset( $params['end'] ) && $db->getType() == 'mysql' );
187 $this->addOption( 'LIMIT', $params['limit'] +
1 );
191 $res = $this->select( __METHOD__
);
193 foreach ( $res as $row ) {
194 if ( ++
$count > $params['limit'] ) {
195 // We've reached the one extra which shows that there are additional pages to be had. Stop here...
196 $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601
, $row->rc_timestamp
) );
200 if ( is_null( $resultPageSet ) ) {
201 $vals = $this->extractRowInfo( $row );
202 $fit = $this->getResult()->addValue( array( 'query', $this->getModuleName() ), null, $vals );
204 $this->setContinueEnumParameter( 'start',
205 wfTimestamp( TS_ISO_8601
, $row->rc_timestamp
) );
209 if ( $params['allrev'] ) {
210 $ids[] = intval( $row->rc_this_oldid
);
212 $ids[] = intval( $row->rc_cur_id
);
217 if ( is_null( $resultPageSet ) ) {
218 $this->getResult()->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'item' );
219 } elseif ( $params['allrev'] ) {
220 $resultPageSet->populateFromRevisionIDs( $ids );
222 $resultPageSet->populateFromPageIDs( $ids );
226 private function extractRowInfo( $row ) {
229 if ( $this->fld_ids
) {
230 $vals['pageid'] = intval( $row->rc_cur_id
);
231 $vals['revid'] = intval( $row->rc_this_oldid
);
234 $title = Title
::makeTitle( $row->rc_namespace
, $row->rc_title
);
236 if ( $this->fld_title
) {
237 ApiQueryBase
::addTitleInfo( $vals, $title );
240 if ( $this->fld_user ||
$this->fld_userid
) {
242 if ( $this->fld_user
) {
243 $vals['user'] = $row->rc_user_text
;
246 if ( $this->fld_userid
) {
247 $vals['user'] = $row->rc_user
;
250 if ( !$row->rc_user
) {
255 if ( $this->fld_flags
) {
256 if ( $row->rc_new
) {
259 if ( $row->rc_minor
) {
262 if ( $row->rc_bot
) {
267 if ( $this->fld_patrol
&& isset( $row->rc_patrolled
) ) {
268 $vals['patrolled'] = '';
271 if ( $this->fld_timestamp
) {
272 $vals['timestamp'] = wfTimestamp( TS_ISO_8601
, $row->rc_timestamp
);
275 if ( $this->fld_sizes
) {
276 $vals['oldlen'] = intval( $row->rc_old_len
);
277 $vals['newlen'] = intval( $row->rc_new_len
);
280 if ( $this->fld_notificationtimestamp
) {
281 $vals['notificationtimestamp'] = ( $row->wl_notificationtimestamp
== null )
283 : wfTimestamp( TS_ISO_8601
, $row->wl_notificationtimestamp
);
286 if ( $this->fld_comment
&& isset( $row->rc_comment
) ) {
287 $vals['comment'] = $row->rc_comment
;
290 if ( $this->fld_parsedcomment
&& isset( $row->rc_comment
) ) {
292 $vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->rc_comment
, $title );
298 public function getAllowedParams() {
302 ApiBase
::PARAM_TYPE
=> 'timestamp'
305 ApiBase
::PARAM_TYPE
=> 'timestamp'
307 'namespace' => array (
308 ApiBase
::PARAM_ISMULTI
=> true,
309 ApiBase
::PARAM_TYPE
=> 'namespace'
312 ApiBase
::PARAM_TYPE
=> 'user',
314 'excludeuser' => array(
315 ApiBase
::PARAM_TYPE
=> 'user',
318 ApiBase
::PARAM_DFLT
=> 'older',
319 ApiBase
::PARAM_TYPE
=> array(
325 ApiBase
::PARAM_DFLT
=> 10,
326 ApiBase
::PARAM_TYPE
=> 'limit',
327 ApiBase
::PARAM_MIN
=> 1,
328 ApiBase
::PARAM_MAX
=> ApiBase
::LIMIT_BIG1
,
329 ApiBase
::PARAM_MAX2
=> ApiBase
::LIMIT_BIG2
332 ApiBase
::PARAM_ISMULTI
=> true,
333 ApiBase
::PARAM_DFLT
=> 'ids|title|flags',
334 ApiBase
::PARAM_TYPE
=> array(
345 'notificationtimestamp'
349 ApiBase
::PARAM_ISMULTI
=> true,
350 ApiBase
::PARAM_TYPE
=> array(
362 ApiBase
::PARAM_TYPE
=> 'user'
365 ApiBase
::PARAM_TYPE
=> 'string'
370 public function getParamDescription() {
371 $p = $this->getModulePrefix();
373 'allrev' => 'Include multiple revisions of the same page within given timeframe',
374 'start' => 'The timestamp to start enumerating from',
375 'end' => 'The timestamp to end enumerating',
376 'namespace' => 'Filter changes to only the given namespace(s)',
377 'user' => 'Only list changes by this user',
378 'excludeuser' => 'Don\'t list changes by this user',
379 'dir' => $this->getDirectionDescription( $p ),
380 'limit' => 'How many total results to return per request',
382 'Which additional items to get (non-generator mode only).',
383 ' ids - Adds revision ids and page ids',
384 ' title - Adds title of the page',
385 ' flags - Adds flags for the edit',
386 ' user - Adds the user who made the edit',
387 ' userid - Adds user id of whom made the edit',
388 ' comment - Adds comment of the edit',
389 ' parsedcomment - Adds parsed comment of the edit',
390 ' timestamp - Adds timestamp of the edit',
391 ' patrol - Tags edits that are patrolled',
392 ' size - Adds the old and new lengths of the page',
393 ' notificationtimestamp - Adds timestamp of when the user was last notified about the edit',
396 'Show only items that meet this criteria.',
397 "For example, to see only minor edits done by logged-in users, set {$p}show=minor|!anon"
399 'owner' => 'The name of the user whose watchlist you\'d like to access',
400 'token' => 'Give a security token (settable in preferences) to allow access to another user\'s watchlist'
404 public function getDescription() {
405 return "Get all recent changes to pages in the logged in user's watchlist";
408 public function getPossibleErrors() {
409 return array_merge( parent
::getPossibleErrors(), array(
410 array( 'code' => 'bad_wlowner', 'info' => 'Specified user does not exist' ),
411 array( 'code' => 'bad_wltoken', 'info' => 'Incorrect watchlist token provided -- please set a correct token in Special:Preferences' ),
412 array( 'code' => 'notloggedin', 'info' => 'You must be logged-in to have a watchlist' ),
413 array( 'code' => 'patrol', 'info' => 'patrol property is not available' ),
415 array( 'code' => 'permissiondenied', 'info' => 'You need the patrol right to request the patrolled flag' ),
416 array( 'code' => 'user-excludeuser', 'info' => 'user and excludeuser cannot be used together' ),
420 protected function getExamples() {
422 'api.php?action=query&list=watchlist',
423 'api.php?action=query&list=watchlist&wlprop=ids|title|timestamp|user|comment',
424 'api.php?action=query&list=watchlist&wlallrev=&wlprop=ids|title|timestamp|user|comment',
425 'api.php?action=query&generator=watchlist&prop=info',
426 'api.php?action=query&generator=watchlist&gwlallrev=&prop=revisions&rvprop=timestamp|user',
427 'api.php?action=query&list=watchlist&wlowner=Bob_Smith&wltoken=d8d562e9725ea1512894cdab28e5ceebc7f20237'
431 public function getVersion() {
432 return __CLASS__
. ': $Id$';