Completed
Branch master (939199)
by
unknown
39:35
created

includes/api/ApiQueryWatchlist.php (1 issue)

Check for unnecessary variable assignments.

Unused Code Major

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
use MediaWiki\MediaWikiServices;
28
29
/**
30
 * This query action allows clients to retrieve a list of recently modified pages
31
 * that are part of the logged-in user's watchlist.
32
 *
33
 * @ingroup API
34
 */
35
class ApiQueryWatchlist extends ApiQueryGeneratorBase {
36
37
	public function __construct( ApiQuery $query, $moduleName ) {
38
		parent::__construct( $query, $moduleName, 'wl' );
39
	}
40
41
	public function execute() {
42
		$this->run();
43
	}
44
45
	public function executeGenerator( $resultPageSet ) {
46
		$this->run( $resultPageSet );
47
	}
48
49
	private $fld_ids = false, $fld_title = false, $fld_patrol = false,
50
		$fld_flags = false, $fld_timestamp = false, $fld_user = false,
51
		$fld_comment = false, $fld_parsedcomment = false, $fld_sizes = false,
52
		$fld_notificationtimestamp = false, $fld_userid = false,
53
		$fld_loginfo = false;
54
55
	/**
56
	 * @param ApiPageSet $resultPageSet
57
	 * @return void
58
	 */
59
	private function run( $resultPageSet = null ) {
60
		$this->selectNamedDB( 'watchlist', DB_REPLICA, 'watchlist' );
61
62
		$params = $this->extractRequestParams();
63
64
		$user = $this->getUser();
65
		$wlowner = $this->getWatchlistUser( $params );
66
67
		if ( !is_null( $params['prop'] ) && is_null( $resultPageSet ) ) {
68
			$prop = array_flip( $params['prop'] );
69
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'] );
81
			$this->fld_loginfo = isset( $prop['loginfo'] );
82
83
			if ( $this->fld_patrol ) {
84
				if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
85
					$this->dieUsage( 'patrol property is not available', 'patrol' );
86
				}
87
			}
88
		}
89
90
		$options = [
91
			'dir' => $params['dir'] === 'older'
92
				? WatchedItemQueryService::DIR_OLDER
93
				: WatchedItemQueryService::DIR_NEWER,
94
		];
95
96
		if ( is_null( $resultPageSet ) ) {
97
			$options['includeFields'] = $this->getFieldsToInclude();
98
		} else {
99
			$options['usedInGenerator'] = true;
100
		}
101
102
		if ( $params['start'] ) {
103
			$options['start'] = $params['start'];
104
		}
105
		if ( $params['end'] ) {
106
			$options['end'] = $params['end'];
107
		}
108
109
		$startFrom = null;
110
		if ( !is_null( $params['continue'] ) ) {
111
			$cont = explode( '|', $params['continue'] );
112
			$this->dieContinueUsageIf( count( $cont ) != 2 );
113
			$continueTimestamp = $cont[0];
114
			$continueId = (int)$cont[1];
115
			$this->dieContinueUsageIf( $continueId != $cont[1] );
116
			$startFrom = [ $continueTimestamp, $continueId ];
117
		}
118
119
		if ( $wlowner !== $user ) {
120
			$options['watchlistOwner'] = $wlowner;
121
			$options['watchlistOwnerToken'] = $params['token'];
122
		}
123
124
		if ( !is_null( $params['namespace'] ) ) {
125
			$options['namespaceIds'] = $params['namespace'];
126
		}
127
128
		if ( $params['allrev'] ) {
129
			$options['allRevisions'] = true;
130
		}
131
132
		if ( !is_null( $params['show'] ) ) {
133
			$show = array_flip( $params['show'] );
134
135
			/* Check for conflicting parameters. */
136
			if ( $this->showParamsConflicting( $show ) ) {
137
				$this->dieUsageMsg( 'show' );
138
			}
139
140
			// Check permissions.
141
			if ( isset( $show[WatchedItemQueryService::FILTER_PATROLLED] )
142
				|| isset( $show[WatchedItemQueryService::FILTER_NOT_PATROLLED] )
143
			) {
144
				if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
145
					$this->dieUsage(
146
						'You need the patrol right to request the patrolled flag',
147
						'permissiondenied'
148
					);
149
				}
150
			}
151
152
			$options['filters'] = array_keys( $show );
153
		}
154
155 View Code Duplication
		if ( !is_null( $params['type'] ) ) {
156
			try {
157
				$options['rcTypes'] = RecentChange::parseToRCType( $params['type'] );
158
			} catch ( Exception $e ) {
159
				ApiBase::dieDebug( __METHOD__, $e->getMessage() );
160
			}
161
		}
162
163 View Code Duplication
		if ( !is_null( $params['user'] ) && !is_null( $params['excludeuser'] ) ) {
164
			$this->dieUsage( 'user and excludeuser cannot be used together', 'user-excludeuser' );
165
		}
166
		if ( !is_null( $params['user'] ) ) {
167
			$options['onlyByUser'] = $params['user'];
168
		}
169
		if ( !is_null( $params['excludeuser'] ) ) {
170
			$options['notByUser'] = $params['excludeuser'];
171
		}
172
173
		$options['limit'] = $params['limit'];
174
175
		Hooks::run( 'ApiQueryWatchlistPrepareWatchedItemQueryServiceOptions', [
176
			$this, $params, &$options
177
		] );
178
179
		$ids = [];
180
		$count = 0;
0 ignored issues
show
$count is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
181
		$watchedItemQuery = MediaWikiServices::getInstance()->getWatchedItemQueryService();
182
		$items = $watchedItemQuery->getWatchedItemsWithRecentChangeInfo( $wlowner, $options, $startFrom );
183
184
		foreach ( $items as list ( $watchedItem, $recentChangeInfo ) ) {
185
			/** @var WatchedItem $watchedItem */
186
			if ( is_null( $resultPageSet ) ) {
187
				$vals = $this->extractOutputData( $watchedItem, $recentChangeInfo );
188
				$fit = $this->getResult()->addValue( [ 'query', $this->getModuleName() ], null, $vals );
189
				if ( !$fit ) {
190
					$startFrom = [ $recentChangeInfo['rc_timestamp'], $recentChangeInfo['rc_id'] ];
191
					break;
192
				}
193
			} else {
194
				if ( $params['allrev'] ) {
195
					$ids[] = intval( $recentChangeInfo['rc_this_oldid'] );
196
				} else {
197
					$ids[] = intval( $recentChangeInfo['rc_cur_id'] );
198
				}
199
			}
200
		}
201
202
		if ( $startFrom !== null ) {
203
			$this->setContinueEnumParameter( 'continue', implode( '|', $startFrom ) );
204
		}
205
206 View Code Duplication
		if ( is_null( $resultPageSet ) ) {
207
			$this->getResult()->addIndexedTagName(
208
				[ 'query', $this->getModuleName() ],
209
				'item'
210
			);
211
		} elseif ( $params['allrev'] ) {
212
			$resultPageSet->populateFromRevisionIDs( $ids );
213
		} else {
214
			$resultPageSet->populateFromPageIDs( $ids );
215
		}
216
	}
217
218
	private function getFieldsToInclude() {
219
		$includeFields = [];
220
		if ( $this->fld_flags ) {
221
			$includeFields[] = WatchedItemQueryService::INCLUDE_FLAGS;
222
		}
223
		if ( $this->fld_user || $this->fld_userid ) {
224
			$includeFields[] = WatchedItemQueryService::INCLUDE_USER_ID;
225
		}
226
		if ( $this->fld_user ) {
227
			$includeFields[] = WatchedItemQueryService::INCLUDE_USER;
228
		}
229
		if ( $this->fld_comment || $this->fld_parsedcomment ) {
230
			$includeFields[] = WatchedItemQueryService::INCLUDE_COMMENT;
231
		}
232
		if ( $this->fld_patrol ) {
233
			$includeFields[] = WatchedItemQueryService::INCLUDE_PATROL_INFO;
234
		}
235
		if ( $this->fld_sizes ) {
236
			$includeFields[] = WatchedItemQueryService::INCLUDE_SIZES;
237
		}
238
		if ( $this->fld_loginfo ) {
239
			$includeFields[] = WatchedItemQueryService::INCLUDE_LOG_INFO;
240
		}
241
		return $includeFields;
242
	}
243
244
	private function showParamsConflicting( array $show ) {
245
		return ( isset( $show[WatchedItemQueryService::FILTER_MINOR] )
246
			&& isset( $show[WatchedItemQueryService::FILTER_NOT_MINOR] ) )
247
		|| ( isset( $show[WatchedItemQueryService::FILTER_BOT] )
248
			&& isset( $show[WatchedItemQueryService::FILTER_NOT_BOT] ) )
249
		|| ( isset( $show[WatchedItemQueryService::FILTER_ANON] )
250
			&& isset( $show[WatchedItemQueryService::FILTER_NOT_ANON] ) )
251
		|| ( isset( $show[WatchedItemQueryService::FILTER_PATROLLED] )
252
			&& isset( $show[WatchedItemQueryService::FILTER_NOT_PATROLLED] ) )
253
		|| ( isset( $show[WatchedItemQueryService::FILTER_UNREAD] )
254
			&& isset( $show[WatchedItemQueryService::FILTER_NOT_UNREAD] ) );
255
	}
256
257
	private function extractOutputData( WatchedItem $watchedItem, array $recentChangeInfo ) {
258
		/* Determine the title of the page that has been changed. */
259
		$title = Title::makeTitle(
260
			$watchedItem->getLinkTarget()->getNamespace(),
261
			$watchedItem->getLinkTarget()->getDBkey()
262
		);
263
		$user = $this->getUser();
264
265
		/* Our output data. */
266
		$vals = [];
267
		$type = intval( $recentChangeInfo['rc_type'] );
268
		$vals['type'] = RecentChange::parseFromRCType( $type );
269
		$anyHidden = false;
270
271
		/* Create a new entry in the result for the title. */
272
		if ( $this->fld_title || $this->fld_ids ) {
273
			// These should already have been filtered out of the query, but just in case.
274 View Code Duplication
			if ( $type === RC_LOG && ( $recentChangeInfo['rc_deleted'] & LogPage::DELETED_ACTION ) ) {
275
				$vals['actionhidden'] = true;
276
				$anyHidden = true;
277
			}
278
			if ( $type !== RC_LOG ||
279
				LogEventsList::userCanBitfield(
280
					$recentChangeInfo['rc_deleted'],
281
					LogPage::DELETED_ACTION,
282
					$user
283
				)
284
			) {
285
				if ( $this->fld_title ) {
286
					ApiQueryBase::addTitleInfo( $vals, $title );
287
				}
288
				if ( $this->fld_ids ) {
289
					$vals['pageid'] = intval( $recentChangeInfo['rc_cur_id'] );
290
					$vals['revid'] = intval( $recentChangeInfo['rc_this_oldid'] );
291
					$vals['old_revid'] = intval( $recentChangeInfo['rc_last_oldid'] );
292
				}
293
			}
294
		}
295
296
		/* Add user data and 'anon' flag, if user is anonymous. */
297
		if ( $this->fld_user || $this->fld_userid ) {
298 View Code Duplication
			if ( $recentChangeInfo['rc_deleted'] & Revision::DELETED_USER ) {
299
				$vals['userhidden'] = true;
300
				$anyHidden = true;
301
			}
302
			if ( Revision::userCanBitfield(
303
				$recentChangeInfo['rc_deleted'],
304
				Revision::DELETED_USER,
305
				$user
306
			) ) {
307
				if ( $this->fld_userid ) {
308
					$vals['userid'] = (int)$recentChangeInfo['rc_user'];
309
					// for backwards compatibility
310
					$vals['user'] = (int)$recentChangeInfo['rc_user'];
311
				}
312
313
				if ( $this->fld_user ) {
314
					$vals['user'] = $recentChangeInfo['rc_user_text'];
315
				}
316
317
				if ( !$recentChangeInfo['rc_user'] ) {
318
					$vals['anon'] = true;
319
				}
320
			}
321
		}
322
323
		/* Add flags, such as new, minor, bot. */
324
		if ( $this->fld_flags ) {
325
			$vals['bot'] = (bool)$recentChangeInfo['rc_bot'];
326
			$vals['new'] = $recentChangeInfo['rc_type'] == RC_NEW;
327
			$vals['minor'] = (bool)$recentChangeInfo['rc_minor'];
328
		}
329
330
		/* Add sizes of each revision. (Only available on 1.10+) */
331
		if ( $this->fld_sizes ) {
332
			$vals['oldlen'] = intval( $recentChangeInfo['rc_old_len'] );
333
			$vals['newlen'] = intval( $recentChangeInfo['rc_new_len'] );
334
		}
335
336
		/* Add the timestamp. */
337
		if ( $this->fld_timestamp ) {
338
			$vals['timestamp'] = wfTimestamp( TS_ISO_8601, $recentChangeInfo['rc_timestamp'] );
339
		}
340
341
		if ( $this->fld_notificationtimestamp ) {
342
			$vals['notificationtimestamp'] = ( $watchedItem->getNotificationTimestamp() == null )
343
				? ''
344
				: wfTimestamp( TS_ISO_8601, $watchedItem->getNotificationTimestamp() );
345
		}
346
347
		/* Add edit summary / log summary. */
348
		if ( $this->fld_comment || $this->fld_parsedcomment ) {
349 View Code Duplication
			if ( $recentChangeInfo['rc_deleted'] & Revision::DELETED_COMMENT ) {
350
				$vals['commenthidden'] = true;
351
				$anyHidden = true;
352
			}
353
			if ( Revision::userCanBitfield(
354
				$recentChangeInfo['rc_deleted'],
355
				Revision::DELETED_COMMENT,
356
				$user
357
			) ) {
358
				if ( $this->fld_comment && isset( $recentChangeInfo['rc_comment'] ) ) {
359
					$vals['comment'] = $recentChangeInfo['rc_comment'];
360
				}
361
362
				if ( $this->fld_parsedcomment && isset( $recentChangeInfo['rc_comment'] ) ) {
363
					$vals['parsedcomment'] = Linker::formatComment( $recentChangeInfo['rc_comment'], $title );
364
				}
365
			}
366
		}
367
368
		/* Add the patrolled flag */
369 View Code Duplication
		if ( $this->fld_patrol ) {
370
			$vals['patrolled'] = $recentChangeInfo['rc_patrolled'] == 1;
371
			$vals['unpatrolled'] = ChangesList::isUnpatrolled( (object)$recentChangeInfo, $user );
372
		}
373
374
		if ( $this->fld_loginfo && $recentChangeInfo['rc_type'] == RC_LOG ) {
375 View Code Duplication
			if ( $recentChangeInfo['rc_deleted'] & LogPage::DELETED_ACTION ) {
376
				$vals['actionhidden'] = true;
377
				$anyHidden = true;
378
			}
379
			if ( LogEventsList::userCanBitfield(
380
				$recentChangeInfo['rc_deleted'],
381
				LogPage::DELETED_ACTION,
382
				$user
383
			) ) {
384
				$vals['logid'] = intval( $recentChangeInfo['rc_logid'] );
385
				$vals['logtype'] = $recentChangeInfo['rc_log_type'];
386
				$vals['logaction'] = $recentChangeInfo['rc_log_action'];
387
				$vals['logparams'] = LogFormatter::newFromRow( $recentChangeInfo )->formatParametersForApi();
388
			}
389
		}
390
391
		if ( $anyHidden && ( $recentChangeInfo['rc_deleted'] & Revision::DELETED_RESTRICTED ) ) {
392
			$vals['suppressed'] = true;
393
		}
394
395
		Hooks::run( 'ApiQueryWatchlistExtractOutputData', [
396
			$this, $watchedItem, $recentChangeInfo, &$vals
397
		] );
398
399
		return $vals;
400
	}
401
402
	public function getAllowedParams() {
403
		return [
404
			'allrev' => false,
405
			'start' => [
406
				ApiBase::PARAM_TYPE => 'timestamp'
407
			],
408
			'end' => [
409
				ApiBase::PARAM_TYPE => 'timestamp'
410
			],
411
			'namespace' => [
412
				ApiBase::PARAM_ISMULTI => true,
413
				ApiBase::PARAM_TYPE => 'namespace'
414
			],
415
			'user' => [
416
				ApiBase::PARAM_TYPE => 'user',
417
			],
418
			'excludeuser' => [
419
				ApiBase::PARAM_TYPE => 'user',
420
			],
421
			'dir' => [
422
				ApiBase::PARAM_DFLT => 'older',
423
				ApiBase::PARAM_TYPE => [
424
					'newer',
425
					'older'
426
				],
427
				ApiHelp::PARAM_HELP_MSG => 'api-help-param-direction',
428
			],
429
			'limit' => [
430
				ApiBase::PARAM_DFLT => 10,
431
				ApiBase::PARAM_TYPE => 'limit',
432
				ApiBase::PARAM_MIN => 1,
433
				ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
434
				ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
435
			],
436
			'prop' => [
437
				ApiBase::PARAM_ISMULTI => true,
438
				ApiBase::PARAM_DFLT => 'ids|title|flags',
439
				ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
440
				ApiBase::PARAM_TYPE => [
441
					'ids',
442
					'title',
443
					'flags',
444
					'user',
445
					'userid',
446
					'comment',
447
					'parsedcomment',
448
					'timestamp',
449
					'patrol',
450
					'sizes',
451
					'notificationtimestamp',
452
					'loginfo',
453
				]
454
			],
455
			'show' => [
456
				ApiBase::PARAM_ISMULTI => true,
457
				ApiBase::PARAM_TYPE => [
458
					WatchedItemQueryService::FILTER_MINOR,
459
					WatchedItemQueryService::FILTER_NOT_MINOR,
460
					WatchedItemQueryService::FILTER_BOT,
461
					WatchedItemQueryService::FILTER_NOT_BOT,
462
					WatchedItemQueryService::FILTER_ANON,
463
					WatchedItemQueryService::FILTER_NOT_ANON,
464
					WatchedItemQueryService::FILTER_PATROLLED,
465
					WatchedItemQueryService::FILTER_NOT_PATROLLED,
466
					WatchedItemQueryService::FILTER_UNREAD,
467
					WatchedItemQueryService::FILTER_NOT_UNREAD,
468
				]
469
			],
470
			'type' => [
471
				ApiBase::PARAM_DFLT => 'edit|new|log|categorize',
472
				ApiBase::PARAM_ISMULTI => true,
473
				ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
474
				ApiBase::PARAM_TYPE => RecentChange::getChangeTypes()
475
			],
476
			'owner' => [
477
				ApiBase::PARAM_TYPE => 'user'
478
			],
479
			'token' => [
480
				ApiBase::PARAM_TYPE => 'string'
481
			],
482
			'continue' => [
483
				ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
484
			],
485
		];
486
	}
487
488
	protected function getExamplesMessages() {
489
		return [
490
			'action=query&list=watchlist'
491
				=> 'apihelp-query+watchlist-example-simple',
492
			'action=query&list=watchlist&wlprop=ids|title|timestamp|user|comment'
493
				=> 'apihelp-query+watchlist-example-props',
494
			'action=query&list=watchlist&wlallrev=&wlprop=ids|title|timestamp|user|comment'
495
				=> 'apihelp-query+watchlist-example-allrev',
496
			'action=query&generator=watchlist&prop=info'
497
				=> 'apihelp-query+watchlist-example-generator',
498
			'action=query&generator=watchlist&gwlallrev=&prop=revisions&rvprop=timestamp|user'
499
				=> 'apihelp-query+watchlist-example-generator-rev',
500
			'action=query&list=watchlist&wlowner=Example&wltoken=123ABC'
501
				=> 'apihelp-query+watchlist-example-wlowner',
502
		];
503
	}
504
505
	public function getHelpUrls() {
506
		return 'https://www.mediawiki.org/wiki/API:Watchlist';
507
	}
508
}
509