ApiQueryBacklinks   D
last analyzed

Complexity

Total Complexity 81

Size/Duplication

Total Lines 546
Duplicated Lines 6.59 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
dl 36
loc 546
rs 4.8717
c 0
b 0
f 0
wmc 81
lcom 1
cbo 7

10 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 28 2
A execute() 0 3 1
A getCacheMode() 0 3 1
A executeGenerator() 0 3 1
F runFirstQuery() 10 83 17
F runSecondQuery() 8 115 24
F run() 18 174 31
B getAllowedParams() 0 45 2
B getExamplesMessages() 0 24 1
A getHelpUrls() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ApiQueryBacklinks often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ApiQueryBacklinks, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 *
4
 *
5
 * Created on Oct 16, 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 is a three-in-one module to query:
29
 *   * backlinks  - links pointing to the given page,
30
 *   * embeddedin - what pages transclude the given page within themselves,
31
 *   * imageusage - what pages use the given image
32
 *
33
 * @ingroup API
34
 */
35
class ApiQueryBacklinks extends ApiQueryGeneratorBase {
36
37
	/**
38
	 * @var Title
39
	 */
40
	private $rootTitle;
41
42
	private $params, $cont, $redirect;
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
43
	private $bl_ns, $bl_from, $bl_from_ns, $bl_table, $bl_code, $bl_title, $bl_fields, $hasNS;
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
44
45
	/**
46
	 * Maps ns and title to pageid
47
	 *
48
	 * @var array
49
	 */
50
	private $pageMap = [];
51
	private $resultArr;
52
53
	private $redirTitles = [];
54
	private $continueStr = null;
55
56
	// output element name, database column field prefix, database table
57
	private $backlinksSettings = [
58
		'backlinks' => [
59
			'code' => 'bl',
60
			'prefix' => 'pl',
61
			'linktbl' => 'pagelinks',
62
			'helpurl' => 'https://www.mediawiki.org/wiki/API:Backlinks',
63
		],
64
		'embeddedin' => [
65
			'code' => 'ei',
66
			'prefix' => 'tl',
67
			'linktbl' => 'templatelinks',
68
			'helpurl' => 'https://www.mediawiki.org/wiki/API:Embeddedin',
69
		],
70
		'imageusage' => [
71
			'code' => 'iu',
72
			'prefix' => 'il',
73
			'linktbl' => 'imagelinks',
74
			'helpurl' => 'https://www.mediawiki.org/wiki/API:Imageusage',
75
		]
76
	];
77
78
	public function __construct( ApiQuery $query, $moduleName ) {
79
		$settings = $this->backlinksSettings[$moduleName];
80
		$prefix = $settings['prefix'];
81
		$code = $settings['code'];
82
		$this->resultArr = [];
83
84
		parent::__construct( $query, $moduleName, $code );
85
		$this->bl_ns = $prefix . '_namespace';
86
		$this->bl_from = $prefix . '_from';
87
		$this->bl_from_ns = $prefix . '_from_namespace';
88
		$this->bl_table = $settings['linktbl'];
89
		$this->bl_code = $code;
90
		$this->helpUrl = $settings['helpurl'];
0 ignored issues
show
Bug introduced by
The property helpUrl does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
91
92
		$this->hasNS = $moduleName !== 'imageusage';
93
		if ( $this->hasNS ) {
94
			$this->bl_title = $prefix . '_title';
95
			$this->bl_fields = [
96
				$this->bl_ns,
97
				$this->bl_title
98
			];
99
		} else {
100
			$this->bl_title = $prefix . '_to';
101
			$this->bl_fields = [
102
				$this->bl_title
103
			];
104
		}
105
	}
106
107
	public function execute() {
108
		$this->run();
109
	}
110
111
	public function getCacheMode( $params ) {
112
		return 'public';
113
	}
114
115
	public function executeGenerator( $resultPageSet ) {
116
		$this->run( $resultPageSet );
117
	}
118
119
	/**
120
	 * @param ApiPageSet $resultPageSet
121
	 * @return void
122
	 */
123
	private function runFirstQuery( $resultPageSet = null ) {
124
		$this->addTables( [ $this->bl_table, 'page' ] );
125
		$this->addWhere( "{$this->bl_from}=page_id" );
126
		if ( is_null( $resultPageSet ) ) {
127
			$this->addFields( [ 'page_id', 'page_title', 'page_namespace' ] );
128
		} else {
129
			$this->addFields( $resultPageSet->getPageTableFields() );
130
		}
131
		$this->addFields( [ 'page_is_redirect', 'from_ns' => 'page_namespace' ] );
132
133
		$this->addWhereFld( $this->bl_title, $this->rootTitle->getDBkey() );
134
		if ( $this->hasNS ) {
135
			$this->addWhereFld( $this->bl_ns, $this->rootTitle->getNamespace() );
136
		}
137
		$this->addWhereFld( $this->bl_from_ns, $this->params['namespace'] );
138
139
		if ( count( $this->cont ) >= 2 ) {
140
			$op = $this->params['dir'] == 'descending' ? '<' : '>';
141
			if ( count( $this->params['namespace'] ) > 1 ) {
142
				$this->addWhere(
143
					"{$this->bl_from_ns} $op {$this->cont[0]} OR " .
144
					"({$this->bl_from_ns} = {$this->cont[0]} AND " .
145
					"{$this->bl_from} $op= {$this->cont[1]})"
146
				);
147
			} else {
148
				$this->addWhere( "{$this->bl_from} $op= {$this->cont[1]}" );
149
			}
150
		}
151
152 View Code Duplication
		if ( $this->params['filterredir'] == 'redirects' ) {
153
			$this->addWhereFld( 'page_is_redirect', 1 );
154
		} elseif ( $this->params['filterredir'] == 'nonredirects' && !$this->redirect ) {
155
			// bug 22245 - Check for !redirect, as filtering nonredirects, when
156
			// getting what links to them is contradictory
157
			$this->addWhereFld( 'page_is_redirect', 0 );
158
		}
159
160
		$this->addOption( 'LIMIT', $this->params['limit'] + 1 );
161
		$sort = ( $this->params['dir'] == 'descending' ? ' DESC' : '' );
162
		$orderBy = [];
163 View Code Duplication
		if ( count( $this->params['namespace'] ) > 1 ) {
164
			$orderBy[] = $this->bl_from_ns . $sort;
165
		}
166
		$orderBy[] = $this->bl_from . $sort;
167
		$this->addOption( 'ORDER BY', $orderBy );
168
		$this->addOption( 'STRAIGHT_JOIN' );
169
170
		$res = $this->select( __METHOD__ );
171
		$count = 0;
172
		foreach ( $res as $row ) {
173
			if ( ++$count > $this->params['limit'] ) {
174
				// We've reached the one extra which shows that there are
175
				// additional pages to be had. Stop here...
176
				// Continue string may be overridden at a later step
177
				$this->continueStr = "{$row->from_ns}|{$row->page_id}";
178
				break;
179
			}
180
181
			// Fill in continuation fields for later steps
182
			if ( count( $this->cont ) < 2 ) {
183
				$this->cont[] = $row->from_ns;
184
				$this->cont[] = $row->page_id;
185
			}
186
187
			$this->pageMap[$row->page_namespace][$row->page_title] = $row->page_id;
188
			$t = Title::makeTitle( $row->page_namespace, $row->page_title );
189
			if ( $row->page_is_redirect ) {
190
				$this->redirTitles[] = $t;
191
			}
192
193
			if ( is_null( $resultPageSet ) ) {
194
				$a = [ 'pageid' => intval( $row->page_id ) ];
195
				ApiQueryBase::addTitleInfo( $a, $t );
196
				if ( $row->page_is_redirect ) {
197
					$a['redirect'] = true;
198
				}
199
				// Put all the results in an array first
200
				$this->resultArr[$a['pageid']] = $a;
201
			} else {
202
				$resultPageSet->processDbRow( $row );
203
			}
204
		}
205
	}
206
207
	/**
208
	 * @param ApiPageSet $resultPageSet
209
	 * @return void
210
	 */
211
	private function runSecondQuery( $resultPageSet = null ) {
212
		$db = $this->getDB();
213
		$this->addTables( [ 'page', $this->bl_table ] );
214
		$this->addWhere( "{$this->bl_from}=page_id" );
215
216
		if ( is_null( $resultPageSet ) ) {
217
			$this->addFields( [ 'page_id', 'page_title', 'page_namespace', 'page_is_redirect' ] );
218
		} else {
219
			$this->addFields( $resultPageSet->getPageTableFields() );
220
		}
221
222
		$this->addFields( [ $this->bl_title, 'from_ns' => 'page_namespace' ] );
223
		if ( $this->hasNS ) {
224
			$this->addFields( $this->bl_ns );
225
		}
226
227
		// We can't use LinkBatch here because $this->hasNS may be false
228
		$titleWhere = [];
229
		$allRedirNs = [];
230
		$allRedirDBkey = [];
231
		/** @var $t Title */
232
		foreach ( $this->redirTitles as $t ) {
233
			$redirNs = $t->getNamespace();
234
			$redirDBkey = $t->getDBkey();
235
			$titleWhere[] = "{$this->bl_title} = " . $db->addQuotes( $redirDBkey ) .
236
				( $this->hasNS ? " AND {$this->bl_ns} = {$redirNs}" : '' );
237
			$allRedirNs[$redirNs] = true;
238
			$allRedirDBkey[$redirDBkey] = true;
239
		}
240
		$this->addWhere( $db->makeList( $titleWhere, LIST_OR ) );
241
		$this->addWhereFld( 'page_namespace', $this->params['namespace'] );
242
243
		if ( count( $this->cont ) >= 6 ) {
244
			$op = $this->params['dir'] == 'descending' ? '<' : '>';
245
246
			$where = "{$this->bl_from} $op= {$this->cont[5]}";
247
			// Don't bother with namespace, title, or from_namespace if it's
248
			// otherwise constant in the where clause.
249
			if ( count( $this->params['namespace'] ) > 1 ) {
250
				$where = "{$this->bl_from_ns} $op {$this->cont[4]} OR " .
251
					"({$this->bl_from_ns} = {$this->cont[4]} AND ($where))";
252
			}
253
			if ( count( $allRedirDBkey ) > 1 ) {
254
				$title = $db->addQuotes( $this->cont[3] );
255
				$where = "{$this->bl_title} $op $title OR " .
256
					"({$this->bl_title} = $title AND ($where))";
257
			}
258
			if ( $this->hasNS && count( $allRedirNs ) > 1 ) {
259
				$where = "{$this->bl_ns} $op {$this->cont[2]} OR " .
260
					"({$this->bl_ns} = {$this->cont[2]} AND ($where))";
261
			}
262
263
			$this->addWhere( $where );
264
		}
265 View Code Duplication
		if ( $this->params['filterredir'] == 'redirects' ) {
266
			$this->addWhereFld( 'page_is_redirect', 1 );
267
		} elseif ( $this->params['filterredir'] == 'nonredirects' ) {
268
			$this->addWhereFld( 'page_is_redirect', 0 );
269
		}
270
271
		$this->addOption( 'LIMIT', $this->params['limit'] + 1 );
272
		$orderBy = [];
273
		$sort = ( $this->params['dir'] == 'descending' ? ' DESC' : '' );
274
		// Don't order by namespace/title/from_namespace if it's constant in the WHERE clause
275
		if ( $this->hasNS && count( $allRedirNs ) > 1 ) {
276
			$orderBy[] = $this->bl_ns . $sort;
277
		}
278
		if ( count( $allRedirDBkey ) > 1 ) {
279
			$orderBy[] = $this->bl_title . $sort;
280
		}
281 View Code Duplication
		if ( count( $this->params['namespace'] ) > 1 ) {
282
			$orderBy[] = $this->bl_from_ns . $sort;
283
		}
284
		$orderBy[] = $this->bl_from . $sort;
285
		$this->addOption( 'ORDER BY', $orderBy );
286
		$this->addOption( 'USE INDEX', [ 'page' => 'PRIMARY' ] );
287
288
		$res = $this->select( __METHOD__ );
289
		$count = 0;
290
		foreach ( $res as $row ) {
291
			$ns = $this->hasNS ? $row->{$this->bl_ns} : NS_FILE;
292
293
			if ( ++$count > $this->params['limit'] ) {
294
				// We've reached the one extra which shows that there are
295
				// additional pages to be had. Stop here...
296
				// Note we must keep the parameters for the first query constant
297
				// This may be overridden at a later step
298
				$title = $row->{$this->bl_title};
299
				$this->continueStr = implode( '|', array_slice( $this->cont, 0, 2 ) ) .
300
					"|$ns|$title|{$row->from_ns}|{$row->page_id}";
301
				break;
302
			}
303
304
			// Fill in continuation fields for later steps
305
			if ( count( $this->cont ) < 6 ) {
306
				$this->cont[] = $ns;
307
				$this->cont[] = $row->{$this->bl_title};
308
				$this->cont[] = $row->from_ns;
309
				$this->cont[] = $row->page_id;
310
			}
311
312
			if ( is_null( $resultPageSet ) ) {
313
				$a['pageid'] = intval( $row->page_id );
0 ignored issues
show
Coding Style Comprehensibility introduced by
$a was never initialized. Although not strictly required by PHP, it is generally a good practice to add $a = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
314
				ApiQueryBase::addTitleInfo( $a, Title::makeTitle( $row->page_namespace, $row->page_title ) );
315
				if ( $row->page_is_redirect ) {
316
					$a['redirect'] = true;
317
				}
318
				$parentID = $this->pageMap[$ns][$row->{$this->bl_title}];
319
				// Put all the results in an array first
320
				$this->resultArr[$parentID]['redirlinks'][$row->page_id] = $a;
321
			} else {
322
				$resultPageSet->processDbRow( $row );
0 ignored issues
show
Bug introduced by
It seems like $row defined by $row on line 290 can be null; however, ApiPageSet::processDbRow() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
323
			}
324
		}
325
	}
326
327
	/**
328
	 * @param ApiPageSet $resultPageSet
329
	 * @return void
330
	 */
331
	private function run( $resultPageSet = null ) {
332
		$this->params = $this->extractRequestParams( false );
333
		$this->redirect = isset( $this->params['redirect'] ) && $this->params['redirect'];
334
		$userMax = ( $this->redirect ? ApiBase::LIMIT_BIG1 / 2 : ApiBase::LIMIT_BIG1 );
335
		$botMax = ( $this->redirect ? ApiBase::LIMIT_BIG2 / 2 : ApiBase::LIMIT_BIG2 );
336
337
		$result = $this->getResult();
338
339
		if ( $this->params['limit'] == 'max' ) {
340
			$this->params['limit'] = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
341
			$result->addParsedLimit( $this->getModuleName(), $this->params['limit'] );
342
		} else {
343
			$this->params['limit'] = intval( $this->params['limit'] );
344
			$this->validateLimit( 'limit', $this->params['limit'], 1, $userMax, $botMax );
345
		}
346
347
		$this->rootTitle = $this->getTitleOrPageId( $this->params )->getTitle();
348
349
		// only image titles are allowed for the root in imageinfo mode
350
		if ( !$this->hasNS && $this->rootTitle->getNamespace() !== NS_FILE ) {
351
			$this->dieUsage(
352
				"The title for {$this->getModuleName()} query must be a file",
353
				'bad_image_title'
354
			);
355
		}
356
357
		// Parse and validate continuation parameter
358
		$this->cont = [];
359
		if ( $this->params['continue'] !== null ) {
360
			$cont = explode( '|', $this->params['continue'] );
361
362
			switch ( count( $cont ) ) {
363 View Code Duplication
				case 8:
364
					// redirect page ID for result adding
365
					$this->cont[7] = (int)$cont[7];
366
					$this->dieContinueUsageIf( $cont[7] !== (string)$this->cont[7] );
367
368
					/* Fall through */
369
370 View Code Duplication
				case 7:
371
					// top-level page ID for result adding
372
					$this->cont[6] = (int)$cont[6];
373
					$this->dieContinueUsageIf( $cont[6] !== (string)$this->cont[6] );
374
375
					/* Fall through */
376
377
				case 6:
378
					// ns for 2nd query (even for imageusage)
379
					$this->cont[2] = (int)$cont[2];
380
					$this->dieContinueUsageIf( $cont[2] !== (string)$this->cont[2] );
381
382
					// title for 2nd query
383
					$this->cont[3] = $cont[3];
384
385
					// from_ns for 2nd query
386
					$this->cont[4] = (int)$cont[4];
387
					$this->dieContinueUsageIf( $cont[4] !== (string)$this->cont[4] );
388
389
					// from_id for 1st query
390
					$this->cont[5] = (int)$cont[5];
391
					$this->dieContinueUsageIf( $cont[5] !== (string)$this->cont[5] );
392
393
					/* Fall through */
394
395
				case 2:
396
					// from_ns for 1st query
397
					$this->cont[0] = (int)$cont[0];
398
					$this->dieContinueUsageIf( $cont[0] !== (string)$this->cont[0] );
399
400
					// from_id for 1st query
401
					$this->cont[1] = (int)$cont[1];
402
					$this->dieContinueUsageIf( $cont[1] !== (string)$this->cont[1] );
403
404
					break;
405
406
				default:
407
					$this->dieContinueUsageIf( true );
408
			}
409
410
			ksort( $this->cont );
411
		}
412
413
		$this->runFirstQuery( $resultPageSet );
414
		if ( $this->redirect && count( $this->redirTitles ) ) {
415
			$this->resetQueryParams();
416
			$this->runSecondQuery( $resultPageSet );
417
		}
418
419
		// Fill in any missing fields in case it's needed below
420
		$this->cont += [ 0, 0, 0, '', 0, 0, 0 ];
421
422
		if ( is_null( $resultPageSet ) ) {
423
			// Try to add the result data in one go and pray that it fits
424
			$code = $this->bl_code;
425
			$data = array_map( function ( $arr ) use ( $result, $code ) {
426
				if ( isset( $arr['redirlinks'] ) ) {
427
					$arr['redirlinks'] = array_values( $arr['redirlinks'] );
428
					ApiResult::setIndexedTagName( $arr['redirlinks'], $code );
429
				}
430
				return $arr;
431
			}, array_values( $this->resultArr ) );
432
			$fit = $result->addValue( 'query', $this->getModuleName(), $data );
433
			if ( !$fit ) {
434
				// It didn't fit. Add elements one by one until the
435
				// result is full.
436
				ksort( $this->resultArr );
437
				if ( count( $this->cont ) >= 7 ) {
438
					$startAt = $this->cont[6];
439
				} else {
440
					reset( $this->resultArr );
441
					$startAt = key( $this->resultArr );
442
				}
443
				$idx = 0;
444
				foreach ( $this->resultArr as $pageID => $arr ) {
445
					if ( $pageID < $startAt ) {
446
						continue;
447
					}
448
449
					// Add the basic entry without redirlinks first
450
					$fit = $result->addValue(
451
						[ 'query', $this->getModuleName() ],
452
						$idx, array_diff_key( $arr, [ 'redirlinks' => '' ] ) );
453 View Code Duplication
					if ( !$fit ) {
454
						$this->continueStr = implode( '|', array_slice( $this->cont, 0, 6 ) ) .
455
							"|$pageID";
456
						break;
457
					}
458
459
					$hasRedirs = false;
460
					$redirLinks = isset( $arr['redirlinks'] ) ? (array)$arr['redirlinks'] : [];
461
					ksort( $redirLinks );
462
					if ( count( $this->cont ) >= 8 && $pageID == $startAt ) {
463
						$redirStartAt = $this->cont[7];
464
					} else {
465
						reset( $redirLinks );
466
						$redirStartAt = key( $redirLinks );
467
					}
468
					foreach ( $redirLinks as $key => $redir ) {
469
						if ( $key < $redirStartAt ) {
470
							continue;
471
						}
472
473
						$fit = $result->addValue(
474
							[ 'query', $this->getModuleName(), $idx, 'redirlinks' ],
475
							null, $redir );
476 View Code Duplication
						if ( !$fit ) {
477
							$this->continueStr = implode( '|', array_slice( $this->cont, 0, 6 ) ) .
478
								"|$pageID|$key";
479
							break;
480
						}
481
						$hasRedirs = true;
482
					}
483
					if ( $hasRedirs ) {
484
						$result->addIndexedTagName(
485
							[ 'query', $this->getModuleName(), $idx, 'redirlinks' ],
486
							$this->bl_code );
487
					}
488
					if ( !$fit ) {
489
						break;
490
					}
491
492
					$idx++;
493
				}
494
			}
495
496
			$result->addIndexedTagName(
497
				[ 'query', $this->getModuleName() ],
498
				$this->bl_code
499
			);
500
		}
501
		if ( !is_null( $this->continueStr ) ) {
502
			$this->setContinueEnumParameter( 'continue', $this->continueStr );
503
		}
504
	}
505
506
	public function getAllowedParams() {
507
		$retval = [
508
			'title' => [
509
				ApiBase::PARAM_TYPE => 'string',
510
			],
511
			'pageid' => [
512
				ApiBase::PARAM_TYPE => 'integer',
513
			],
514
			'continue' => [
515
				ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
516
			],
517
			'namespace' => [
518
				ApiBase::PARAM_ISMULTI => true,
519
				ApiBase::PARAM_TYPE => 'namespace'
520
			],
521
			'dir' => [
522
				ApiBase::PARAM_DFLT => 'ascending',
523
				ApiBase::PARAM_TYPE => [
524
					'ascending',
525
					'descending'
526
				]
527
			],
528
			'filterredir' => [
529
				ApiBase::PARAM_DFLT => 'all',
530
				ApiBase::PARAM_TYPE => [
531
					'all',
532
					'redirects',
533
					'nonredirects'
534
				]
535
			],
536
			'limit' => [
537
				ApiBase::PARAM_DFLT => 10,
538
				ApiBase::PARAM_TYPE => 'limit',
539
				ApiBase::PARAM_MIN => 1,
540
				ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
541
				ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
542
			]
543
		];
544
		if ( $this->getModuleName() == 'embeddedin' ) {
545
			return $retval;
546
		}
547
		$retval['redirect'] = false;
548
549
		return $retval;
550
	}
551
552
	protected function getExamplesMessages() {
553
		static $examples = [
554
			'backlinks' => [
555
				'action=query&list=backlinks&bltitle=Main%20Page'
556
					=> 'apihelp-query+backlinks-example-simple',
557
				'action=query&generator=backlinks&gbltitle=Main%20Page&prop=info'
558
					=> 'apihelp-query+backlinks-example-generator',
559
			],
560
			'embeddedin' => [
561
				'action=query&list=embeddedin&eititle=Template:Stub'
562
					=> 'apihelp-query+embeddedin-example-simple',
563
				'action=query&generator=embeddedin&geititle=Template:Stub&prop=info'
564
					=> 'apihelp-query+embeddedin-example-generator',
565
			],
566
			'imageusage' => [
567
				'action=query&list=imageusage&iutitle=File:Albert%20Einstein%20Head.jpg'
568
					=> 'apihelp-query+imageusage-example-simple',
569
				'action=query&generator=imageusage&giutitle=File:Albert%20Einstein%20Head.jpg&prop=info'
570
					=> 'apihelp-query+imageusage-example-generator',
571
			]
572
		];
573
574
		return $examples[$this->getModuleName()];
575
	}
576
577
	public function getHelpUrls() {
578
		return $this->helpUrl;
579
	}
580
}
581