MediaWiki  master
SpecialWhatLinksHere.php
Go to the documentation of this file.
1 <?php
29 
37  protected $opts;
38 
39  protected $selfTitle;
40 
42  protected $target;
43 
45  private $loadBalancer;
46 
49 
52 
55 
57  private $namespaceInfo;
58 
59  protected $limits = [ 20, 50, 100, 250, 500 ];
60 
68  public function __construct(
74  ) {
75  parent::__construct( 'Whatlinkshere' );
76  $this->loadBalancer = $loadBalancer;
77  $this->linkBatchFactory = $linkBatchFactory;
78  $this->contentHandlerFactory = $contentHandlerFactory;
79  $this->searchEngineFactory = $searchEngineFactory;
80  $this->namespaceInfo = $namespaceInfo;
81  }
82 
83  public function execute( $par ) {
84  $out = $this->getOutput();
85 
86  $this->setHeaders();
87  $this->outputHeader();
88  $this->addHelpLink( 'Help:What links here' );
89  $out->addModuleStyles( 'mediawiki.special.changeslist' );
90  $out->addModules( 'mediawiki.special.recentchanges' );
91 
92  $opts = new FormOptions();
93 
94  $opts->add( 'target', '' );
95  $opts->add( 'namespace', '', FormOptions::INTNULL );
96  $opts->add( 'limit', $this->getConfig()->get( 'QueryPageDefaultLimit' ) );
97  $opts->add( 'offset', 0 );
98  $opts->add( 'from', 0 );
99  $opts->add( 'dir', 'next' );
100  $opts->add( 'hideredirs', false );
101  $opts->add( 'hidetrans', false );
102  $opts->add( 'hidelinks', false );
103  $opts->add( 'hideimages', false );
104  $opts->add( 'invert', false );
105 
107  $opts->validateIntBounds( 'limit', 0, 5000 );
108 
109  // Give precedence to subpage syntax
110  if ( $par !== null ) {
111  $opts->setValue( 'target', $par );
112  }
113 
114  // Bind to member variable
115  $this->opts = $opts;
116 
117  $this->target = Title::newFromText( $opts->getValue( 'target' ) );
118  if ( !$this->target ) {
119  if ( !$this->including() ) {
120  $out->addHTML( $this->whatlinkshereForm() );
121  }
122 
123  return;
124  }
125 
126  $this->getSkin()->setRelevantTitle( $this->target );
127 
128  $this->selfTitle = $this->getPageTitle( $this->target->getPrefixedDBkey() );
129 
130  $out->setPageTitle( $this->msg( 'whatlinkshere-title', $this->target->getPrefixedText() ) );
131  $out->addBacklinkSubtitle( $this->target );
132 
133  // Workaround for legacy 'from' and 'back' system.
134  // We need only 'from' param to get offset.
135  $from = $opts->getValue( 'from' );
136  $opts->reset( 'from' );
137  $dir = $from ? 'next' : $opts->getValue( 'dir' );
138  // 'from' was included in result set, offset is excluded. We need to align them.
139  $offset = $from ? $from - 1 : $opts->getValue( 'offset' );
140 
141  $this->showIndirectLinks(
142  0,
143  $this->target,
144  $opts->getValue( 'limit' ),
145  $offset,
146  $dir
147  );
148  }
149 
157  private function showIndirectLinks( $level, $target, $limit, $offset = 0, $dir = 'next' ) {
158  $out = $this->getOutput();
159  $dbr = $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA );
160 
161  $hidelinks = $this->opts->getValue( 'hidelinks' );
162  $hideredirs = $this->opts->getValue( 'hideredirs' );
163  $hidetrans = $this->opts->getValue( 'hidetrans' );
164  $hideimages = $target->getNamespace() !== NS_FILE || $this->opts->getValue( 'hideimages' );
165 
166  // For historical reasons `pagelinks` always contains an entry for the redirect target.
167  // So we only need to query `redirect` if `pagelinks` isn't being queried.
168  $fetchredirs = $hidelinks && !$hideredirs;
169 
170  // Build query conds in concert for all four tables...
171  $conds = [];
172  $conds['redirect'] = [
173  'rd_namespace' => $target->getNamespace(),
174  'rd_title' => $target->getDBkey(),
175  ];
176  $conds['pagelinks'] = [
177  'pl_namespace' => $target->getNamespace(),
178  'pl_title' => $target->getDBkey(),
179  ];
180  $conds['templatelinks'] = [
181  'tl_namespace' => $target->getNamespace(),
182  'tl_title' => $target->getDBkey(),
183  ];
184  $conds['imagelinks'] = [
185  'il_to' => $target->getDBkey(),
186  ];
187 
188  $namespace = $this->opts->getValue( 'namespace' );
189  if ( is_int( $namespace ) ) {
190  $invert = $this->opts->getValue( 'invert' );
191  if ( $invert ) {
192  // Select all namespaces except for the specified one.
193  // This allows the database to use the *_from_namespace index. (T241837)
194  $namespaces = array_diff(
195  $this->namespaceInfo->getValidNamespaces(), [ $namespace ] );
196  } else {
197  $namespaces = $namespace;
198  }
199  $conds['redirect']['page_namespace'] = $namespaces;
200  $conds['pagelinks']['pl_from_namespace'] = $namespaces;
201  $conds['templatelinks']['tl_from_namespace'] = $namespaces;
202  $conds['imagelinks']['il_from_namespace'] = $namespaces;
203  }
204 
205  if ( $offset ) {
206  $rel = $dir === 'prev' ? '<' : '>';
207  $conds['redirect'][] = "rd_from $rel $offset";
208  $conds['templatelinks'][] = "tl_from $rel $offset";
209  $conds['pagelinks'][] = "pl_from $rel $offset";
210  $conds['imagelinks'][] = "il_from $rel $offset";
211  }
212 
213  if ( $hideredirs ) {
214  // For historical reasons `pagelinks` always contains an entry for the redirect target.
215  // So we hide that link when $hideredirs is set. There's unfortunately no way to tell when a
216  // redirect's content also links to the target.
217  $conds['pagelinks']['rd_from'] = null;
218  }
219 
220  $sortDirection = $dir === 'prev' ? SelectQueryBuilder::SORT_DESC : SelectQueryBuilder::SORT_ASC;
221 
222  $fname = __METHOD__;
223  $queryFunc = static function ( IDatabase $dbr, $table, $fromCol ) use (
224  $conds, $target, $limit, $sortDirection, $fname
225  ) {
226  // Read an extra row as an at-end check
227  $queryLimit = $limit + 1;
228  $on = [
229  "rd_from = $fromCol",
230  'rd_title' => $target->getDBkey(),
231  'rd_namespace' => $target->getNamespace(),
232  'rd_interwiki = ' . $dbr->addQuotes( '' ) . ' OR rd_interwiki IS NULL'
233  ];
234  // Inner LIMIT is 2X in case of stale backlinks with wrong namespaces
235  $subQuery = $dbr->newSelectQueryBuilder()
236  ->table( $table )
237  ->fields( [ $fromCol, 'rd_from', 'rd_fragment' ] )
238  ->conds( $conds[$table] )
239  ->orderBy( $fromCol, $sortDirection )
240  ->limit( 2 * $queryLimit )
241  ->leftJoin( 'redirect', 'redirect', $on );
242 
243  return $dbr->newSelectQueryBuilder()
244  ->table( $subQuery, 'temp_backlink_range' )
245  ->join( 'page', 'page', "$fromCol = page_id" )
246  ->fields( [ 'page_id', 'page_namespace', 'page_title',
247  'rd_from', 'rd_fragment', 'page_is_redirect' ] )
248  ->orderBy( 'page_id', $sortDirection )
249  ->limit( $queryLimit )
250  ->caller( $fname )
251  ->fetchResultSet();
252  };
253 
254  if ( $fetchredirs ) {
255  $rdRes = $dbr->newSelectQueryBuilder()
256  ->table( 'redirect' )
257  ->fields( [ 'page_id', 'page_namespace', 'page_title', 'rd_from', 'rd_fragment', 'page_is_redirect' ] )
258  ->conds( $conds['redirect'] )
259  ->orderBy( 'rd_from', $sortDirection )
260  ->limit( $limit + 1 )
261  ->join( 'page', 'page', 'rd_from = page_id' )
262  ->caller( __METHOD__ )
263  ->fetchResultSet();
264  }
265 
266  if ( !$hidelinks ) {
267  $plRes = $queryFunc( $dbr, 'pagelinks', 'pl_from' );
268  }
269 
270  if ( !$hidetrans ) {
271  $tlRes = $queryFunc( $dbr, 'templatelinks', 'tl_from' );
272  }
273 
274  if ( !$hideimages ) {
275  $ilRes = $queryFunc( $dbr, 'imagelinks', 'il_from' );
276  }
277 
278  if ( ( !$fetchredirs || !$rdRes->numRows() )
279  && ( $hidelinks || !$plRes->numRows() )
280  && ( $hidetrans || !$tlRes->numRows() )
281  && ( $hideimages || !$ilRes->numRows() )
282  ) {
283  if ( $level == 0 && !$this->including() ) {
284  $out->addHTML( $this->whatlinkshereForm() );
285 
286  // Show filters only if there are links
287  if ( $hidelinks || $hidetrans || $hideredirs || $hideimages ) {
288  $out->addHTML( $this->getFilterPanel() );
289  }
290  $msgKey = is_int( $namespace ) ? 'nolinkshere-ns' : 'nolinkshere';
291  $link = $this->getLinkRenderer()->makeLink(
292  $this->target,
293  null,
294  [],
295  $this->target->isRedirect() ? [ 'redirect' => 'no' ] : []
296  );
297 
298  $errMsg = $this->msg( $msgKey )
299  ->params( $this->target->getPrefixedText() )
300  ->rawParams( $link )
301  ->parseAsBlock();
302  $out->addHTML( $errMsg );
303  $out->setStatusCode( 404 );
304  }
305 
306  return;
307  }
308 
309  // Read the rows into an array and remove duplicates
310  // templatelinks comes third so that the templatelinks row overwrites the
311  // pagelinks/redirect row, so we get (inclusion) rather than nothing
312  $rows = [];
313  if ( $fetchredirs ) {
314  foreach ( $rdRes as $row ) {
315  $row->is_template = 0;
316  $row->is_image = 0;
317  $rows[$row->page_id] = $row;
318  }
319  }
320  if ( !$hidelinks ) {
321  foreach ( $plRes as $row ) {
322  $row->is_template = 0;
323  $row->is_image = 0;
324  $rows[$row->page_id] = $row;
325  }
326  }
327  if ( !$hidetrans ) {
328  foreach ( $tlRes as $row ) {
329  $row->is_template = 1;
330  $row->is_image = 0;
331  $rows[$row->page_id] = $row;
332  }
333  }
334  if ( !$hideimages ) {
335  foreach ( $ilRes as $row ) {
336  $row->is_template = 0;
337  $row->is_image = 1;
338  $rows[$row->page_id] = $row;
339  }
340  }
341 
342  // Sort by key and then change the keys to 0-based indices
343  ksort( $rows );
344  $rows = array_values( $rows );
345 
346  $numRows = count( $rows );
347 
348  // Work out the start and end IDs, for prev/next links
349  if ( !$limit ) { // T289351
350  $nextId = $prevId = false;
351  $rows = [];
352  } elseif ( $dir === 'prev' ) {
353  if ( $numRows > $limit ) {
354  // More rows available after these ones
355  // Get the nextId from the last row in the result set
356  $nextId = $rows[$limit]->page_id;
357  // Remove undisplayed rows, for dir='prev' we need to discard first record after sorting
358  $rows = array_slice( $rows, 1, $limit );
359  // Get the prevId from the first displayed row
360  $prevId = $rows[0]->page_id;
361  } else {
362  // Get the nextId from the last displayed row
363  $nextId = $rows[$numRows - 1]->page_id;
364  $prevId = false;
365  }
366  } else {
367  // If offset is not set disable prev link
368  $prevId = $offset ? $rows[0]->page_id : false;
369  if ( $numRows > $limit ) {
370  // Get the nextId from the last displayed row
371  $nextId = $rows[$limit - 1]->page_id;
372  // Remove undisplayed rows
373  $rows = array_slice( $rows, 0, $limit );
374  } else {
375  $nextId = false;
376  }
377  }
378 
379  // use LinkBatch to make sure, that all required data (associated with Titles)
380  // is loaded in one query
381  $lb = $this->linkBatchFactory->newLinkBatch();
382  foreach ( $rows as $row ) {
383  $lb->add( $row->page_namespace, $row->page_title );
384  }
385  $lb->execute();
386 
387  if ( $level == 0 && !$this->including() ) {
388  $out->addHTML( $this->whatlinkshereForm() );
389  $out->addHTML( $this->getFilterPanel() );
390 
391  $link = $this->getLinkRenderer()->makeLink(
392  $this->target,
393  null,
394  [],
395  $this->target->isRedirect() ? [ 'redirect' => 'no' ] : []
396  );
397 
398  $msg = $this->msg( 'linkshere' )
399  ->params( $this->target->getPrefixedText() )
400  ->rawParams( $link )
401  ->parseAsBlock();
402  $out->addHTML( $msg );
403 
404  $out->addWikiMsg( 'whatlinkshere-count', Message::numParam( count( $rows ) ) );
405 
406  $prevnext = $this->getPrevNext( $prevId, $nextId );
407  $out->addHTML( $prevnext );
408  }
409  $out->addHTML( $this->listStart( $level ) );
410  foreach ( $rows as $row ) {
411  $nt = Title::makeTitle( $row->page_namespace, $row->page_title );
412 
413  if ( $row->rd_from && $level < 2 ) {
414  $out->addHTML( $this->listItem( $row, $nt, $target, true ) );
415  $this->showIndirectLinks(
416  $level + 1,
417  $nt,
418  $this->getConfig()->get( 'MaxRedirectLinksRetrieved' )
419  );
420  $out->addHTML( Xml::closeElement( 'li' ) );
421  } else {
422  $out->addHTML( $this->listItem( $row, $nt, $target ) );
423  }
424  }
425 
426  $out->addHTML( $this->listEnd() );
427 
428  if ( $level == 0 && !$this->including() ) {
429  $out->addHTML( $prevnext );
430  }
431  }
432 
433  protected function listStart( $level ) {
434  return Xml::openElement( 'ul', ( $level ? [] : [ 'id' => 'mw-whatlinkshere-list' ] ) );
435  }
436 
437  protected function listItem( $row, $nt, $target, $notClose = false ) {
438  $dirmark = $this->getLanguage()->getDirMark();
439 
440  if ( $row->rd_from ) {
441  $query = [ 'redirect' => 'no' ];
442  } else {
443  $query = [];
444  }
445 
446  $link = $this->getLinkRenderer()->makeKnownLink(
447  $nt,
448  null,
449  $row->page_is_redirect ? [ 'class' => 'mw-redirect' ] : [],
450  $query
451  );
452 
453  // Display properties (redirect or template)
454  $propsText = '';
455  $props = [];
456  if ( (string)$row->rd_fragment !== '' ) {
457  $props[] = $this->msg( 'whatlinkshere-sectionredir' )
458  ->rawParams( $this->getLinkRenderer()->makeLink(
459  $target->createFragmentTarget( $row->rd_fragment ),
460  $row->rd_fragment
461  ) )->escaped();
462  } elseif ( $row->rd_from ) {
463  $props[] = $this->msg( 'isredirect' )->escaped();
464  }
465  if ( $row->is_template ) {
466  $props[] = $this->msg( 'istemplate' )->escaped();
467  }
468  if ( $row->is_image ) {
469  $props[] = $this->msg( 'isimage' )->escaped();
470  }
471 
472  $this->getHookRunner()->onWhatLinksHereProps( $row, $nt, $target, $props );
473 
474  if ( count( $props ) ) {
475  $propsText = $this->msg( 'parentheses' )
476  ->rawParams( $this->getLanguage()->semicolonList( $props ) )->escaped();
477  }
478 
479  # Space for utilities links, with a what-links-here link provided
480  $wlhLink = $this->wlhLink(
481  $nt,
482  $this->msg( 'whatlinkshere-links' )->text(),
483  $this->msg( 'editlink' )->text()
484  );
485  $wlh = Xml::wrapClass(
486  $this->msg( 'parentheses' )->rawParams( $wlhLink )->escaped(),
487  'mw-whatlinkshere-tools'
488  );
489 
490  return $notClose ?
491  Xml::openElement( 'li' ) . "$link $propsText $dirmark $wlh\n" :
492  Xml::tags( 'li', null, "$link $propsText $dirmark $wlh" ) . "\n";
493  }
494 
495  protected function listEnd() {
496  return Xml::closeElement( 'ul' );
497  }
498 
499  protected function wlhLink( Title $target, $text, $editText ) {
500  static $title = null;
501  if ( $title === null ) {
502  $title = $this->getPageTitle();
503  }
504 
505  $linkRenderer = $this->getLinkRenderer();
506 
507  // always show a "<- Links" link
508  $links = [
509  'links' => $linkRenderer->makeKnownLink(
510  $title,
511  $text,
512  [],
513  [ 'target' => $target->getPrefixedText() ]
514  ),
515  ];
516 
517  // if the page is editable, add an edit link
518  if (
519  // check user permissions
520  $this->getAuthority()->isAllowed( 'edit' ) &&
521  // check, if the content model is editable through action=edit
522  $this->contentHandlerFactory->getContentHandler( $target->getContentModel() )
523  ->supportsDirectEditing()
524  ) {
525  $links['edit'] = $linkRenderer->makeKnownLink(
526  $target,
527  $editText,
528  [],
529  [ 'action' => 'edit' ]
530  );
531  }
532 
533  // build the links html
534  return $this->getLanguage()->pipeList( $links );
535  }
536 
537  private function makeSelfLink( $text, $query ) {
538  return $this->getLinkRenderer()->makeKnownLink(
539  $this->selfTitle,
540  $text,
541  [],
542  $query
543  );
544  }
545 
546  private function getPrevNext( $prevId, $nextId ) {
547  $currentLimit = $this->opts->getValue( 'limit' );
548  $prev = $this->msg( 'whatlinkshere-prev' )->numParams( $currentLimit )->text();
549  $next = $this->msg( 'whatlinkshere-next' )->numParams( $currentLimit )->text();
550 
551  $changed = $this->opts->getChangedValues();
552  unset( $changed['target'] ); // Already in the request title
553 
554  if ( $prevId != 0 ) {
555  $overrides = [ 'dir' => 'prev', 'offset' => $prevId, ];
556  $prev = Message::rawParam( $this->makeSelfLink( $prev, array_merge( $changed, $overrides ) ) );
557  }
558  if ( $nextId != 0 ) {
559  $overrides = [ 'dir' => 'next', 'offset' => $nextId, ];
560  $next = Message::rawParam( $this->makeSelfLink( $next, array_merge( $changed, $overrides ) ) );
561  }
562 
563  $limitLinks = [];
564  $lang = $this->getLanguage();
565  foreach ( $this->limits as $limit ) {
566  $prettyLimit = $lang->formatNum( $limit );
567  $overrides = [ 'limit' => $limit ];
568  $limitLinks[] = $this->makeSelfLink( $prettyLimit, array_merge( $changed, $overrides ) );
569  }
570 
571  $nums = $lang->pipeList( $limitLinks );
572 
573  return $this->msg( 'viewprevnext' )->params( $prev, $next )->rawParams( $nums )->escaped();
574  }
575 
576  private function whatlinkshereForm() {
577  // We get nicer value from the title object
578  $this->opts->consumeValue( 'target' );
579 
580  $target = $this->target ? $this->target->getPrefixedText() : '';
581  $namespace = $this->opts->consumeValue( 'namespace' );
582  $nsinvert = $this->opts->consumeValue( 'invert' );
583 
584  # Build up the form
585  $f = Xml::openElement( 'form', [ 'action' => wfScript() ] );
586 
587  # Values that should not be forgotten
588  $f .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() );
589  foreach ( $this->opts->getUnconsumedValues() as $name => $value ) {
590  $f .= Html::hidden( $name, $value );
591  }
592 
593  $f .= Xml::fieldset( $this->msg( 'whatlinkshere' )->text() );
594 
595  # Target input (.mw-searchInput enables suggestions)
596  $f .= Xml::inputLabel( $this->msg( 'whatlinkshere-page' )->text(), 'target',
597  'mw-whatlinkshere-target', 40, $target, [ 'class' => 'mw-searchInput' ] );
598 
599  $f .= ' ';
600 
601  # Namespace selector
603  [
604  'selected' => $namespace,
605  'all' => '',
606  'label' => $this->msg( 'namespace' )->text(),
607  'in-user-lang' => true,
608  ], [
609  'name' => 'namespace',
610  'id' => 'namespace',
611  'class' => 'namespaceselector',
612  ]
613  );
614 
615  $hidden = $namespace === '' ? ' mw-input-hidden' : '';
616  $f .= ' ' .
617  Html::rawElement( 'span',
618  [ 'class' => 'mw-input-with-label' . $hidden ],
620  $this->msg( 'invert' )->text(),
621  'invert',
622  'nsinvert',
623  $nsinvert,
624  [ 'title' => $this->msg( 'tooltip-whatlinkshere-invert' )->text() ]
625  )
626  );
627 
628  $f .= ' ';
629 
630  # Submit
631  $f .= Xml::submitButton( $this->msg( 'whatlinkshere-submit' )->text() );
632 
633  # Close
634  $f .= Xml::closeElement( 'fieldset' ) . Xml::closeElement( 'form' ) . "\n";
635 
636  return $f;
637  }
638 
644  private function getFilterPanel() {
645  $show = $this->msg( 'show' )->text();
646  $hide = $this->msg( 'hide' )->text();
647 
648  $changed = $this->opts->getChangedValues();
649  unset( $changed['target'] ); // Already in the request title
650 
651  $links = [];
652  $types = [ 'hidetrans', 'hidelinks', 'hideredirs' ];
653  if ( $this->target->getNamespace() === NS_FILE ) {
654  $types[] = 'hideimages';
655  }
656 
657  // Combined message keys: 'whatlinkshere-hideredirs', 'whatlinkshere-hidetrans',
658  // 'whatlinkshere-hidelinks', 'whatlinkshere-hideimages'
659  // To be sure they will be found by grep
660  foreach ( $types as $type ) {
661  $chosen = $this->opts->getValue( $type );
662  $msg = $chosen ? $show : $hide;
663  $overrides = [ $type => !$chosen ];
664  $links[] = $this->msg( "whatlinkshere-{$type}" )->rawParams(
665  $this->makeSelfLink( $msg, array_merge( $changed, $overrides ) ) )->escaped();
666  }
667 
668  return Xml::fieldset(
669  $this->msg( 'whatlinkshere-filters' )->text(),
670  $this->getLanguage()->pipeList( $links )
671  );
672  }
673 
682  public function prefixSearchSubpages( $search, $limit, $offset ) {
683  return $this->prefixSearchString( $search, $limit, $offset, $this->searchEngineFactory );
684  }
685 
686  protected function getGroupName() {
687  return 'pagetools';
688  }
689 }
SpecialPage\$linkRenderer
LinkRenderer null $linkRenderer
Definition: SpecialPage.php:80
SpecialPage\getPageTitle
getPageTitle( $subpage=false)
Get a self-referential title object.
Definition: SpecialPage.php:744
Message\numParam
static numParam( $num)
Definition: Message.php:1085
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:912
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:383
SpecialWhatLinksHere\$limits
$limits
Definition: SpecialWhatLinksHere.php:59
SpecialWhatLinksHere\listEnd
listEnd()
Definition: SpecialWhatLinksHere.php:495
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:790
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
FormOptions\getValue
getValue( $name)
Get the value for the given option name.
Definition: FormOptions.php:182
SpecialWhatLinksHere\$linkBatchFactory
LinkBatchFactory $linkBatchFactory
Definition: SpecialWhatLinksHere.php:48
FormOptions\INTNULL
const INTNULL
Integer type or null, maps to WebRequest::getIntOrNull() This is useful for the namespace selector.
Definition: FormOptions.php:55
Title\getPrefixedText
getPrefixedText()
Get the prefixed title with spaces.
Definition: Title.php:1912
SearchEngineFactory
Factory class for SearchEngine.
Definition: SearchEngineFactory.php:12
FormOptions\reset
reset( $name)
Delete the option value.
Definition: FormOptions.php:207
SpecialWhatLinksHere\$searchEngineFactory
SearchEngineFactory $searchEngineFactory
Definition: SpecialWhatLinksHere.php:54
SpecialWhatLinksHere\whatlinkshereForm
whatlinkshereForm()
Definition: SpecialWhatLinksHere.php:576
SpecialPage\getSkin
getSkin()
Shortcut to get the skin being used for this instance.
Definition: SpecialPage.php:820
SpecialWhatLinksHere\prefixSearchSubpages
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
Definition: SpecialWhatLinksHere.php:682
IncludableSpecialPage
Shortcut to construct an includable special page.
Definition: IncludableSpecialPage.php:29
SpecialPage\getAuthority
getAuthority()
Shortcut to get the Authority executing this instance.
Definition: SpecialPage.php:810
FormOptions\validateIntBounds
validateIntBounds( $name, $min, $max)
Definition: FormOptions.php:255
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:830
FormOptions\fetchValuesFromRequest
fetchValuesFromRequest(WebRequest $r, $optionKeys=null)
Fetch values for all options (or selected options) from the given WebRequest, making them available f...
Definition: FormOptions.php:346
Xml\openElement
static openElement( $element, $attribs=null)
This opens an XML element.
Definition: Xml.php:110
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
$dbr
$dbr
Definition: testCompression.php:54
Xml\fieldset
static fieldset( $legend=false, $content=false, $attribs=[])
Shortcut for creating fieldsets.
Definition: Xml.php:623
SpecialPage\prefixSearchString
prefixSearchString( $search, $limit, $offset, SearchEngineFactory $searchEngineFactory=null)
Perform a regular substring search for prefixSearchSubpages.
Definition: SpecialPage.php:577
FormOptions\add
add( $name, $default, $type=self::AUTO)
Add an option to be handled by this FormOptions instance.
Definition: FormOptions.php:83
SpecialPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: SpecialPage.php:948
Xml\wrapClass
static wrapClass( $text, $class, $tag='span', $attribs=[])
Shortcut to make a specific element with a class attribute.
Definition: Xml.php:268
Title\getDBkey
getDBkey()
Get the main part with underscores.
Definition: Title.php:1060
SpecialPage\getHookRunner
getHookRunner()
Definition: SpecialPage.php:1095
SpecialPage\getConfig
getConfig()
Shortcut to get main config object.
Definition: SpecialPage.php:878
SpecialWhatLinksHere\$loadBalancer
ILoadBalancer $loadBalancer
Definition: SpecialWhatLinksHere.php:45
wfScript
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Definition: GlobalFunctions.php:2285
Title\getNamespace
getNamespace()
Get the namespace index, i.e.
Definition: Title.php:1069
SpecialWhatLinksHere\getPrevNext
getPrevNext( $prevId, $nextId)
Definition: SpecialWhatLinksHere.php:546
SpecialWhatLinksHere\wlhLink
wlhLink(Title $target, $text, $editText)
Definition: SpecialWhatLinksHere.php:499
SpecialWhatLinksHere\__construct
__construct(ILoadBalancer $loadBalancer, LinkBatchFactory $linkBatchFactory, IContentHandlerFactory $contentHandlerFactory, SearchEngineFactory $searchEngineFactory, NamespaceInfo $namespaceInfo)
Definition: SpecialWhatLinksHere.php:68
MediaWiki\Cache\LinkBatchFactory
Definition: LinkBatchFactory.php:39
Wikimedia\Rdbms\SelectQueryBuilder
Definition: SelectQueryBuilder.php:11
SpecialWhatLinksHere
Implements Special:Whatlinkshere.
Definition: SpecialWhatLinksHere.php:35
$title
$title
Definition: testCompression.php:38
SpecialPage\setHeaders
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
Definition: SpecialPage.php:618
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:651
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
SpecialWhatLinksHere\showIndirectLinks
showIndirectLinks( $level, $target, $limit, $offset=0, $dir='next')
Definition: SpecialWhatLinksHere.php:157
FormOptions\setValue
setValue( $name, $value, $force=false)
Use to set the value of an option.
Definition: FormOptions.php:165
Title\createFragmentTarget
createFragmentTarget( $fragment)
Creates a new Title for a different fragment of the same page.
Definition: Title.php:1845
Html\hidden
static hidden( $name, $value, array $attribs=[])
Convenience function to produce an input element with type=hidden.
Definition: Html.php:831
SpecialWhatLinksHere\$namespaceInfo
NamespaceInfo $namespaceInfo
Definition: SpecialWhatLinksHere.php:57
MediaWiki\Content\IContentHandlerFactory
Definition: IContentHandlerFactory.php:10
Html\namespaceSelector
static namespaceSelector(array $params=[], array $selectAttribs=[])
Build a drop-down box for selecting a namespace.
Definition: Html.php:923
Message\rawParam
static rawParam( $raw)
Definition: Message.php:1074
Xml\tags
static tags( $element, $attribs, $contents)
Same as Xml::element(), but does not escape contents.
Definition: Xml.php:132
SpecialWhatLinksHere\execute
execute( $par)
Default execute method Checks user permissions.
Definition: SpecialWhatLinksHere.php:83
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:780
Title\getContentModel
getContentModel( $flags=0)
Get the page's content model id, see the CONTENT_MODEL_XXX constants.
Definition: Title.php:1081
SpecialWhatLinksHere\makeSelfLink
makeSelfLink( $text, $query)
Definition: SpecialWhatLinksHere.php:537
SpecialWhatLinksHere\$selfTitle
$selfTitle
Definition: SpecialWhatLinksHere.php:39
SpecialWhatLinksHere\listItem
listItem( $row, $nt, $target, $notClose=false)
Definition: SpecialWhatLinksHere.php:437
SpecialWhatLinksHere\$target
Title $target
Definition: SpecialWhatLinksHere.php:42
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:1028
Title
Represents a title within MediaWiki.
Definition: Title.php:48
SpecialWhatLinksHere\listStart
listStart( $level)
Definition: SpecialWhatLinksHere.php:433
Xml\closeElement
static closeElement( $element)
Shortcut to close an XML element.
Definition: Xml.php:119
SpecialWhatLinksHere\$contentHandlerFactory
IContentHandlerFactory $contentHandlerFactory
Definition: SpecialWhatLinksHere.php:51
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:210
SpecialWhatLinksHere\getFilterPanel
getFilterPanel()
Create filter panel.
Definition: SpecialWhatLinksHere.php:644
NamespaceInfo
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Definition: NamespaceInfo.php:35
FormOptions
Helper class to keep track of options when mixing links and form elements.
Definition: FormOptions.php:35
NS_FILE
const NS_FILE
Definition: Defines.php:70
Xml\inputLabel
static inputLabel( $label, $name, $id, $size=false, $value=false, $attribs=[])
Convenience function to build an HTML text input field with a label.
Definition: Xml.php:386
SpecialWhatLinksHere\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialWhatLinksHere.php:686
SpecialPage\outputHeader
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
Definition: SpecialPage.php:709
SpecialPage\including
including( $x=null)
Whether the special page is being evaluated via transclusion.
Definition: SpecialPage.php:266
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
SpecialWhatLinksHere\$opts
FormOptions $opts
Definition: SpecialWhatLinksHere.php:37
Xml\submitButton
static submitButton( $value, $attribs=[])
Convenience function to build an HTML submit button When $wgUseMediaWikiUIEverywhere is true it will ...
Definition: Xml.php:465
Xml\checkLabel
static checkLabel( $label, $name, $id, $checked=false, $attribs=[])
Convenience function to build an HTML checkbox with a label.
Definition: Xml.php:425
$type
$type
Definition: testCompression.php:52