SpecialProtectedpages::showOptions()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 19
nc 1
nop 8
dl 0
loc 22
rs 9.2
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Implements Special:Protectedpages
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 * http://www.gnu.org/copyleft/gpl.html
19
 *
20
 * @file
21
 * @ingroup SpecialPage
22
 */
23
24
use MediaWiki\Linker\LinkRenderer;
25
26
/**
27
 * A special page that lists protected pages
28
 *
29
 * @ingroup SpecialPage
30
 */
31
class SpecialProtectedpages extends SpecialPage {
32
	protected $IdLevel = 'level';
33
	protected $IdType = 'type';
34
35
	public function __construct() {
36
		parent::__construct( 'Protectedpages' );
37
	}
38
39
	public function execute( $par ) {
40
		$this->setHeaders();
41
		$this->outputHeader();
42
		$this->getOutput()->addModuleStyles( 'mediawiki.special' );
43
44
		$request = $this->getRequest();
45
		$type = $request->getVal( $this->IdType );
46
		$level = $request->getVal( $this->IdLevel );
47
		$sizetype = $request->getVal( 'sizetype' );
48
		$size = $request->getIntOrNull( 'size' );
49
		$ns = $request->getIntOrNull( 'namespace' );
50
		$indefOnly = $request->getBool( 'indefonly' ) ? 1 : 0;
51
		$cascadeOnly = $request->getBool( 'cascadeonly' ) ? 1 : 0;
52
		$noRedirect = $request->getBool( 'noredirect' ) ? 1 : 0;
53
54
		$pager = new ProtectedPagesPager(
55
			$this,
56
			[],
57
			$type,
58
			$level,
59
			$ns,
60
			$sizetype,
61
			$size,
62
			$indefOnly,
63
			$cascadeOnly,
64
			$noRedirect,
65
			$this->getLinkRenderer()
66
		);
67
68
		$this->getOutput()->addHTML( $this->showOptions(
69
			$ns,
70
			$type,
71
			$level,
72
			$sizetype,
73
			$size,
74
			$indefOnly,
75
			$cascadeOnly,
76
			$noRedirect
77
		) );
78
79
		if ( $pager->getNumRows() ) {
80
			$this->getOutput()->addParserOutputContent( $pager->getFullOutput() );
81
		} else {
82
			$this->getOutput()->addWikiMsg( 'protectedpagesempty' );
83
		}
84
	}
85
86
	/**
87
	 * @param int $namespace
88
	 * @param string $type Restriction type
89
	 * @param string $level Restriction level
90
	 * @param string $sizetype "min" or "max"
91
	 * @param int $size
92
	 * @param bool $indefOnly Only indefinite protection
93
	 * @param bool $cascadeOnly Only cascading protection
94
	 * @param bool $noRedirect Don't show redirects
95
	 * @return string Input form
96
	 */
97
	protected function showOptions( $namespace, $type = 'edit', $level, $sizetype,
98
		$size, $indefOnly, $cascadeOnly, $noRedirect
99
	) {
100
		$title = $this->getPageTitle();
101
102
		return Xml::openElement( 'form', [ 'method' => 'get', 'action' => wfScript() ] ) .
103
			Xml::openElement( 'fieldset' ) .
104
			Xml::element( 'legend', [], $this->msg( 'protectedpages' )->text() ) .
105
			Html::hidden( 'title', $title->getPrefixedDBkey() ) . "\n" .
106
			$this->getNamespaceMenu( $namespace ) . "\n" .
107
			$this->getTypeMenu( $type ) . "\n" .
108
			$this->getLevelMenu( $level ) . "\n" .
109
			"<br />\n" .
110
			$this->getExpiryCheck( $indefOnly ) . "\n" .
111
			$this->getCascadeCheck( $cascadeOnly ) . "\n" .
112
			$this->getRedirectCheck( $noRedirect ) . "\n" .
113
			"<br />\n" .
114
			$this->getSizeLimit( $sizetype, $size ) . "\n" .
115
			Xml::submitButton( $this->msg( 'protectedpages-submit' )->text() ) . "\n" .
116
			Xml::closeElement( 'fieldset' ) .
117
			Xml::closeElement( 'form' );
118
	}
119
120
	/**
121
	 * Prepare the namespace filter drop-down; standard namespace
122
	 * selector, sans the MediaWiki namespace
123
	 *
124
	 * @param string|null $namespace Pre-select namespace
125
	 * @return string
126
	 */
127
	protected function getNamespaceMenu( $namespace = null ) {
128
		return Html::rawElement( 'span', [ 'class' => 'mw-input-with-label' ],
129
			Html::namespaceSelector(
130
				[
131
					'selected' => $namespace,
132
					'all' => '',
133
					'label' => $this->msg( 'namespace' )->text()
134
				], [
135
					'name' => 'namespace',
136
					'id' => 'namespace',
137
					'class' => 'namespaceselector',
138
				]
139
			)
140
		);
141
	}
142
143
	/**
144
	 * @param bool $indefOnly
145
	 * @return string Formatted HTML
146
	 */
147
	protected function getExpiryCheck( $indefOnly ) {
148
		return '<span class="mw-input-with-label">' . Xml::checkLabel(
149
			$this->msg( 'protectedpages-indef' )->text(),
150
			'indefonly',
151
			'indefonly',
152
			$indefOnly
153
		) . "</span>\n";
154
	}
155
156
	/**
157
	 * @param bool $cascadeOnly
158
	 * @return string Formatted HTML
159
	 */
160
	protected function getCascadeCheck( $cascadeOnly ) {
161
		return '<span class="mw-input-with-label">' . Xml::checkLabel(
162
			$this->msg( 'protectedpages-cascade' )->text(),
163
			'cascadeonly',
164
			'cascadeonly',
165
			$cascadeOnly
166
		) . "</span>\n";
167
	}
168
169
	/**
170
	 * @param bool $noRedirect
171
	 * @return string Formatted HTML
172
	 */
173
	protected function getRedirectCheck( $noRedirect ) {
174
		return '<span class="mw-input-with-label">' . Xml::checkLabel(
175
			$this->msg( 'protectedpages-noredirect' )->text(),
176
			'noredirect',
177
			'noredirect',
178
			$noRedirect
179
		) . "</span>\n";
180
	}
181
182
	/**
183
	 * @param string $sizetype "min" or "max"
184
	 * @param mixed $size
185
	 * @return string Formatted HTML
186
	 */
187
	protected function getSizeLimit( $sizetype, $size ) {
188
		$max = $sizetype === 'max';
189
190
		return '<span class="mw-input-with-label">' . Xml::radioLabel(
191
			$this->msg( 'minimum-size' )->text(),
192
			'sizetype',
193
			'min',
194
			'wpmin',
195
			!$max
196
		) .
197
			' ' .
198
			Xml::radioLabel(
199
				$this->msg( 'maximum-size' )->text(),
200
				'sizetype',
201
				'max',
202
				'wpmax',
203
				$max
204
			) .
205
			' ' .
206
			Xml::input( 'size', 9, $size, [ 'id' => 'wpsize' ] ) .
207
			' ' .
208
			Xml::label( $this->msg( 'pagesize' )->text(), 'wpsize' ) . "</span>\n";
209
	}
210
211
	/**
212
	 * Creates the input label of the restriction type
213
	 * @param string $pr_type Protection type
214
	 * @return string Formatted HTML
215
	 */
216
	protected function getTypeMenu( $pr_type ) {
217
		$m = []; // Temporary array
218
		$options = [];
219
220
		// First pass to load the log names
221
		foreach ( Title::getFilteredRestrictionTypes( true ) as $type ) {
222
			// Messages: restriction-edit, restriction-move, restriction-create, restriction-upload
223
			$text = $this->msg( "restriction-$type" )->text();
224
			$m[$text] = $type;
225
		}
226
227
		// Third pass generates sorted XHTML content
228
		foreach ( $m as $text => $type ) {
229
			$selected = ( $type == $pr_type );
230
			$options[] = Xml::option( $text, $type, $selected ) . "\n";
231
		}
232
233
		return '<span class="mw-input-with-label">' .
234
			Xml::label( $this->msg( 'restriction-type' )->text(), $this->IdType ) . ' ' .
235
			Xml::tags( 'select',
236
				[ 'id' => $this->IdType, 'name' => $this->IdType ],
237
				implode( "\n", $options ) ) . "</span>";
238
	}
239
240
	/**
241
	 * Creates the input label of the restriction level
242
	 * @param string $pr_level Protection level
243
	 * @return string Formatted HTML
244
	 */
245
	protected function getLevelMenu( $pr_level ) {
246
		// Temporary array
247
		$m = [ $this->msg( 'restriction-level-all' )->text() => 0 ];
248
		$options = [];
249
250
		// First pass to load the log names
251 View Code Duplication
		foreach ( $this->getConfig()->get( 'RestrictionLevels' ) as $type ) {
252
			// Messages used can be 'restriction-level-sysop' and 'restriction-level-autoconfirmed'
253
			if ( $type != '' && $type != '*' ) {
254
				$text = $this->msg( "restriction-level-$type" )->text();
255
				$m[$text] = $type;
256
			}
257
		}
258
259
		// Third pass generates sorted XHTML content
260 View Code Duplication
		foreach ( $m as $text => $type ) {
261
			$selected = ( $type == $pr_level );
262
			$options[] = Xml::option( $text, $type, $selected );
263
		}
264
265
		return '<span class="mw-input-with-label">' .
266
			Xml::label( $this->msg( 'restriction-level' )->text(), $this->IdLevel ) . ' ' .
267
			Xml::tags( 'select',
268
				[ 'id' => $this->IdLevel, 'name' => $this->IdLevel ],
269
				implode( "\n", $options ) ) . "</span>";
270
	}
271
272
	protected function getGroupName() {
273
		return 'maintenance';
274
	}
275
}
276
277
/**
278
 * @todo document
279
 * @ingroup Pager
280
 */
281
class ProtectedPagesPager extends TablePager {
282
	public $mForm, $mConds;
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...
283
	private $type, $level, $namespace, $sizetype, $size, $indefonly, $cascadeonly, $noredirect;
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...
284
285
	/**
286
	 * @var LinkRenderer
287
	 */
288
	private $linkRenderer;
289
290
	/**
291
	 * @param SpecialProtectedpages $form
292
	 * @param array $conds
293
	 * @param $type
294
	 * @param $level
295
	 * @param $namespace
296
	 * @param string $sizetype
297
	 * @param int $size
298
	 * @param bool $indefonly
299
	 * @param bool $cascadeonly
300
	 * @param bool $noredirect
301
	 * @param LinkRenderer $linkRenderer
302
	 */
303
	function __construct( $form, $conds = [], $type, $level, $namespace,
304
		$sizetype = '', $size = 0, $indefonly = false, $cascadeonly = false, $noredirect = false,
305
		LinkRenderer $linkRenderer
306
	) {
307
		$this->mForm = $form;
308
		$this->mConds = $conds;
309
		$this->type = ( $type ) ? $type : 'edit';
310
		$this->level = $level;
311
		$this->namespace = $namespace;
312
		$this->sizetype = $sizetype;
313
		$this->size = intval( $size );
314
		$this->indefonly = (bool)$indefonly;
315
		$this->cascadeonly = (bool)$cascadeonly;
316
		$this->noredirect = (bool)$noredirect;
317
		$this->linkRenderer = $linkRenderer;
318
		parent::__construct( $form->getContext() );
319
	}
320
321
	function preprocessResults( $result ) {
322
		# Do a link batch query
323
		$lb = new LinkBatch;
324
		$userids = [];
325
326
		foreach ( $result as $row ) {
327
			$lb->add( $row->page_namespace, $row->page_title );
328
			// field is nullable, maybe null on old protections
329
			if ( $row->log_user !== null ) {
330
				$userids[] = $row->log_user;
331
			}
332
		}
333
334
		// fill LinkBatch with user page and user talk
335
		if ( count( $userids ) ) {
336
			$userCache = UserCache::singleton();
337
			$userCache->doQuery( $userids, [], __METHOD__ );
338
			foreach ( $userids as $userid ) {
339
				$name = $userCache->getProp( $userid, 'name' );
340
				if ( $name !== false ) {
341
					$lb->add( NS_USER, $name );
342
					$lb->add( NS_USER_TALK, $name );
343
				}
344
			}
345
		}
346
347
		$lb->execute();
348
	}
349
350
	function getFieldNames() {
351
		static $headers = null;
352
353
		if ( $headers == [] ) {
354
			$headers = [
355
				'log_timestamp' => 'protectedpages-timestamp',
356
				'pr_page' => 'protectedpages-page',
357
				'pr_expiry' => 'protectedpages-expiry',
358
				'log_user' => 'protectedpages-performer',
359
				'pr_params' => 'protectedpages-params',
360
				'log_comment' => 'protectedpages-reason',
361
			];
362
			foreach ( $headers as $key => $val ) {
363
				$headers[$key] = $this->msg( $val )->text();
364
			}
365
		}
366
367
		return $headers;
368
	}
369
370
	/**
371
	 * @param string $field
372
	 * @param string $value
373
	 * @return string HTML
374
	 * @throws MWException
375
	 */
376
	function formatValue( $field, $value ) {
377
		/** @var $row object */
378
		$row = $this->mCurrentRow;
379
380
		switch ( $field ) {
381
			case 'log_timestamp':
382
				// when timestamp is null, this is a old protection row
383
				if ( $value === null ) {
384
					$formatted = Html::rawElement(
385
						'span',
386
						[ 'class' => 'mw-protectedpages-unknown' ],
387
						$this->msg( 'protectedpages-unknown-timestamp' )->escaped()
388
					);
389
				} else {
390
					$formatted = htmlspecialchars( $this->getLanguage()->userTimeAndDate(
391
						$value, $this->getUser() ) );
392
				}
393
				break;
394
395
			case 'pr_page':
396
				$title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
397
				if ( !$title ) {
398
					$formatted = Html::element(
399
						'span',
400
						[ 'class' => 'mw-invalidtitle' ],
401
						Linker::getInvalidTitleDescription(
402
							$this->getContext(),
403
							$row->page_namespace,
404
							$row->page_title
405
						)
406
					);
407
				} else {
408
					$formatted = $this->linkRenderer->makeLink( $title );
409
				}
410
				if ( !is_null( $row->page_len ) ) {
411
					$formatted .= $this->getLanguage()->getDirMark() .
412
						' ' . Html::rawElement(
413
						'span',
414
						[ 'class' => 'mw-protectedpages-length' ],
415
						Linker::formatRevisionSize( $row->page_len )
416
					);
417
				}
418
				break;
419
420
			case 'pr_expiry':
421
				$formatted = htmlspecialchars( $this->getLanguage()->formatExpiry(
422
					$value, /* User preference timezone */true ) );
423
				$title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
424
				if ( $this->getUser()->isAllowed( 'protect' ) && $title ) {
425
					$changeProtection = $this->linkRenderer->makeKnownLink(
426
						$title,
427
						$this->msg( 'protect_change' )->text(),
428
						[],
429
						[ 'action' => 'unprotect' ]
430
					);
431
					$formatted .= ' ' . Html::rawElement(
432
						'span',
433
						[ 'class' => 'mw-protectedpages-actions' ],
434
						$this->msg( 'parentheses' )->rawParams( $changeProtection )->escaped()
435
					);
436
				}
437
				break;
438
439
			case 'log_user':
440
				// when timestamp is null, this is a old protection row
441
				if ( $row->log_timestamp === null ) {
442
					$formatted = Html::rawElement(
443
						'span',
444
						[ 'class' => 'mw-protectedpages-unknown' ],
445
						$this->msg( 'protectedpages-unknown-performer' )->escaped()
446
					);
447
				} else {
448
					$username = UserCache::singleton()->getProp( $value, 'name' );
449
					if ( LogEventsList::userCanBitfield(
450
						$row->log_deleted,
451
						LogPage::DELETED_USER,
452
						$this->getUser()
453
					) ) {
454
						if ( $username === false ) {
455
							$formatted = htmlspecialchars( $value );
456
						} else {
457
							$formatted = Linker::userLink( $value, $username )
458
								. Linker::userToolLinks( $value, $username );
459
						}
460
					} else {
461
						$formatted = $this->msg( 'rev-deleted-user' )->escaped();
462
					}
463
					if ( LogEventsList::isDeleted( $row, LogPage::DELETED_USER ) ) {
464
						$formatted = '<span class="history-deleted">' . $formatted . '</span>';
465
					}
466
				}
467
				break;
468
469
			case 'pr_params':
470
				$params = [];
471
				// Messages: restriction-level-sysop, restriction-level-autoconfirmed
472
				$params[] = $this->msg( 'restriction-level-' . $row->pr_level )->escaped();
473
				if ( $row->pr_cascade ) {
474
					$params[] = $this->msg( 'protect-summary-cascade' )->escaped();
475
				}
476
				$formatted = $this->getLanguage()->commaList( $params );
477
				break;
478
479
			case 'log_comment':
480
				// when timestamp is null, this is an old protection row
481
				if ( $row->log_timestamp === null ) {
482
					$formatted = Html::rawElement(
483
						'span',
484
						[ 'class' => 'mw-protectedpages-unknown' ],
485
						$this->msg( 'protectedpages-unknown-reason' )->escaped()
486
					);
487
				} else {
488
					if ( LogEventsList::userCanBitfield(
489
						$row->log_deleted,
490
						LogPage::DELETED_COMMENT,
491
						$this->getUser()
492
					) ) {
493
						$formatted = Linker::formatComment( $value !== null ? $value : '' );
494
					} else {
495
						$formatted = $this->msg( 'rev-deleted-comment' )->escaped();
496
					}
497
					if ( LogEventsList::isDeleted( $row, LogPage::DELETED_COMMENT ) ) {
498
						$formatted = '<span class="history-deleted">' . $formatted . '</span>';
499
					}
500
				}
501
				break;
502
503
			default:
504
				throw new MWException( "Unknown field '$field'" );
505
		}
506
507
		return $formatted;
508
	}
509
510
	function getQueryInfo() {
511
		$conds = $this->mConds;
512
		$conds[] = 'pr_expiry > ' . $this->mDb->addQuotes( $this->mDb->timestamp() ) .
513
			' OR pr_expiry IS NULL';
514
		$conds[] = 'page_id=pr_page';
515
		$conds[] = 'pr_type=' . $this->mDb->addQuotes( $this->type );
516
517
		if ( $this->sizetype == 'min' ) {
518
			$conds[] = 'page_len>=' . $this->size;
519
		} elseif ( $this->sizetype == 'max' ) {
520
			$conds[] = 'page_len<=' . $this->size;
521
		}
522
523
		if ( $this->indefonly ) {
524
			$infinity = $this->mDb->addQuotes( $this->mDb->getInfinity() );
525
			$conds[] = "pr_expiry = $infinity OR pr_expiry IS NULL";
526
		}
527
		if ( $this->cascadeonly ) {
528
			$conds[] = 'pr_cascade = 1';
529
		}
530
		if ( $this->noredirect ) {
531
			$conds[] = 'page_is_redirect = 0';
532
		}
533
534
		if ( $this->level ) {
535
			$conds[] = 'pr_level=' . $this->mDb->addQuotes( $this->level );
536
		}
537 View Code Duplication
		if ( !is_null( $this->namespace ) ) {
538
			$conds[] = 'page_namespace=' . $this->mDb->addQuotes( $this->namespace );
539
		}
540
541
		return [
542
			'tables' => [ 'page', 'page_restrictions', 'log_search', 'logging' ],
543
			'fields' => [
544
				'pr_id',
545
				'page_namespace',
546
				'page_title',
547
				'page_len',
548
				'pr_type',
549
				'pr_level',
550
				'pr_expiry',
551
				'pr_cascade',
552
				'log_timestamp',
553
				'log_user',
554
				'log_comment',
555
				'log_deleted',
556
			],
557
			'conds' => $conds,
558
			'join_conds' => [
559
				'log_search' => [
560
					'LEFT JOIN', [
561
						'ls_field' => 'pr_id', 'ls_value = ' . $this->mDb->buildStringCast( 'pr_id' )
562
					]
563
				],
564
				'logging' => [
565
					'LEFT JOIN', [
566
						'ls_log_id = log_id'
567
					]
568
				]
569
			]
570
		];
571
	}
572
573
	protected function getTableClass() {
574
		return parent::getTableClass() . ' mw-protectedpages';
575
	}
576
577
	function getIndexField() {
578
		return 'pr_id';
579
	}
580
581
	function getDefaultSort() {
582
		return 'pr_id';
583
	}
584
585
	function isFieldSortable( $field ) {
586
		// no index for sorting exists
587
		return false;
588
	}
589
}
590