MediaWiki  master
SpecialAllPages.php
Go to the documentation of this file.
1 <?php
31 
37  protected $maxPerPage = 345;
38 
44  protected $nsfromMsg = 'allpagesfrom';
45 
49  public function __construct( $name = 'Allpages' ) {
50  parent::__construct( $name );
51  }
52 
58  public function execute( $par ) {
59  $request = $this->getRequest();
60  $out = $this->getOutput();
61 
62  $this->setHeaders();
63  $this->outputHeader();
64  $out->allowClickjacking();
65 
66  # GET values
67  $from = $request->getVal( 'from', null );
68  $to = $request->getVal( 'to', null );
69  $namespace = $request->getInt( 'namespace' );
70 
71  $miserMode = (bool)$this->getConfig()->get( 'MiserMode' );
72 
73  // Redirects filter is disabled in MiserMode
74  $hideredirects = $request->getBool( 'hideredirects', false ) && !$miserMode;
75 
76  $namespaces = $this->getLanguage()->getNamespaces();
77 
78  $out->setPageTitle(
79  ( $namespace > 0 && array_key_exists( $namespace, $namespaces ) ) ?
80  $this->msg( 'allinnamespace', str_replace( '_', ' ', $namespaces[$namespace] ) ) :
81  $this->msg( 'allarticles' )
82  );
83  $out->addModuleStyles( 'mediawiki.special' );
84 
85  if ( $par !== null ) {
86  $this->showChunk( $namespace, $par, $to, $hideredirects );
87  } elseif ( $from !== null && $to === null ) {
88  $this->showChunk( $namespace, $from, $to, $hideredirects );
89  } else {
90  $this->showToplevel( $namespace, $from, $to, $hideredirects );
91  }
92  }
93 
102  protected function outputHTMLForm( $namespace = NS_MAIN,
103  $from = '', $to = '', $hideRedirects = false
104  ) {
105  $miserMode = (bool)$this->getConfig()->get( 'MiserMode' );
106  $formDescriptor = [
107  'from' => [
108  'type' => 'text',
109  'name' => 'from',
110  'id' => 'nsfrom',
111  'size' => 30,
112  'label-message' => 'allpagesfrom',
113  'default' => str_replace( '_', ' ', $from ),
114  ],
115  'to' => [
116  'type' => 'text',
117  'name' => 'to',
118  'id' => 'nsto',
119  'size' => 30,
120  'label-message' => 'allpagesto',
121  'default' => str_replace( '_', ' ', $to ),
122  ],
123  'namespace' => [
124  'type' => 'namespaceselect',
125  'name' => 'namespace',
126  'id' => 'namespace',
127  'label-message' => 'namespace',
128  'all' => null,
129  'default' => $namespace,
130  ],
131  'hideredirects' => [
132  'type' => 'check',
133  'name' => 'hideredirects',
134  'id' => 'hidredirects',
135  'label-message' => 'allpages-hide-redirects',
136  'value' => $hideRedirects,
137  ],
138  ];
139 
140  if ( $miserMode ) {
141  unset( $formDescriptor['hideredirects'] );
142  }
143 
144  $context = new DerivativeContext( $this->getContext() );
145  $context->setTitle( $this->getPageTitle() ); // Remove subpage
146  $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $context );
147  $htmlForm
148  ->setMethod( 'get' )
149  ->setWrapperLegendMsg( 'allpages' )
150  ->setSubmitTextMsg( 'allpagessubmit' )
151  ->prepareForm()
152  ->displayForm( false );
153  }
154 
161  private function showToplevel(
162  $namespace = NS_MAIN, $from = '', $to = '', $hideredirects = false
163  ) {
164  $from = Title::makeTitleSafe( $namespace, $from );
165  $to = Title::makeTitleSafe( $namespace, $to );
166  $from = ( $from && $from->isLocal() ) ? $from->getDBkey() : null;
167  $to = ( $to && $to->isLocal() ) ? $to->getDBkey() : null;
168 
169  $this->showChunk( $namespace, $from, $to, $hideredirects );
170  }
171 
178  private function showChunk(
179  $namespace = NS_MAIN, $from = false, $to = false, $hideredirects = false
180  ) {
181  $output = $this->getOutput();
182 
183  $fromList = $this->getNamespaceKeyAndText( $namespace, $from );
184  $toList = $this->getNamespaceKeyAndText( $namespace, $to );
185  $namespaces = $this->getContext()->getLanguage()->getNamespaces();
186  $n = 0;
187  $prevTitle = null;
188 
189  if ( !$fromList || !$toList ) {
190  $out = $this->msg( 'allpagesbadtitle' )->parseAsBlock();
191  } elseif ( !array_key_exists( $namespace, $namespaces ) ) {
192  // Show errormessage and reset to NS_MAIN
193  $out = $this->msg( 'allpages-bad-ns', $namespace )->parse();
194  $namespace = NS_MAIN;
195  } else {
196  list( $namespace, $fromKey, $from ) = $fromList;
197  list( , $toKey, $to ) = $toList;
198 
199  $dbr = wfGetDB( DB_REPLICA );
200  $filterConds = [ 'page_namespace' => $namespace ];
201  if ( $hideredirects ) {
202  $filterConds['page_is_redirect'] = 0;
203  }
204 
205  $conds = $filterConds;
206  $conds[] = 'page_title >= ' . $dbr->addQuotes( $fromKey );
207  if ( $toKey !== "" ) {
208  $conds[] = 'page_title <= ' . $dbr->addQuotes( $toKey );
209  }
210 
211  $res = $dbr->select( 'page',
212  [ 'page_namespace', 'page_title', 'page_is_redirect', 'page_id' ],
213  $conds,
214  __METHOD__,
215  [
216  'ORDER BY' => 'page_title',
217  'LIMIT' => $this->maxPerPage + 1,
218  'USE INDEX' => 'name_title',
219  ]
220  );
221 
222  $linkRenderer = $this->getLinkRenderer();
223  if ( $res->numRows() > 0 ) {
224  $out = Html::openElement( 'ul', [ 'class' => 'mw-allpages-chunk' ] );
225 
226  while ( ( $n < $this->maxPerPage ) && ( $s = $res->fetchObject() ) ) {
227  $t = Title::newFromRow( $s );
228  if ( $t ) {
229  $out .= '<li' .
230  ( $s->page_is_redirect ? ' class="allpagesredirect"' : '' ) .
231  '>' .
232  $linkRenderer->makeLink( $t ) .
233  "</li>\n";
234  } else {
235  $out .= '<li>[[' . htmlspecialchars( $s->page_title ) . "]]</li>\n";
236  }
237  $n++;
238  }
239  $out .= Html::closeElement( 'ul' );
240 
241  if ( $res->numRows() > 2 ) {
242  // Only apply CSS column styles if there's more than 2 entries.
243  // Otherwise, rendering is broken as "mw-allpages-body"'s CSS column count is 3.
244  $out = Html::rawElement( 'div', [ 'class' => 'mw-allpages-body' ], $out );
245  }
246  } else {
247  $out = '';
248  }
249 
250  if ( $fromKey !== '' && !$this->including() ) {
251  # Get the first title from previous chunk
252  $prevConds = $filterConds;
253  $prevConds[] = 'page_title < ' . $dbr->addQuotes( $fromKey );
254  $prevKey = $dbr->selectField(
255  'page',
256  'page_title',
257  $prevConds,
258  __METHOD__,
259  [ 'ORDER BY' => 'page_title DESC', 'OFFSET' => $this->maxPerPage - 1 ]
260  );
261 
262  if ( $prevKey === false ) {
263  # The previous chunk is not complete, need to link to the very first title
264  # available in the database
265  $prevKey = $dbr->selectField(
266  'page',
267  'page_title',
268  $prevConds,
269  __METHOD__,
270  [ 'ORDER BY' => 'page_title' ]
271  );
272  }
273 
274  if ( $prevKey !== false ) {
275  $prevTitle = Title::makeTitle( $namespace, $prevKey );
276  }
277  }
278  }
279 
280  if ( $this->including() ) {
281  $output->addHTML( $out );
282  return;
283  }
284 
285  $navLinks = [];
286  $self = $this->getPageTitle();
287 
288  $linkRenderer = $this->getLinkRenderer();
289  // Generate a "previous page" link if needed
290  if ( $prevTitle ) {
291  $query = [ 'from' => $prevTitle->getText() ];
292 
293  if ( $namespace ) {
294  $query['namespace'] = $namespace;
295  }
296 
297  if ( $hideredirects ) {
298  $query['hideredirects'] = $hideredirects;
299  }
300 
301  $navLinks[] = $linkRenderer->makeKnownLink(
302  $self,
303  $this->msg( 'prevpage', $prevTitle->getText() )->text(),
304  [],
305  $query
306  );
307 
308  }
309 
310  // Generate a "next page" link if needed
311  if ( $n == $this->maxPerPage && $s = $res->fetchObject() ) {
312  # $s is the first link of the next chunk
313  $t = Title::makeTitle( $namespace, $s->page_title );
314  $query = [ 'from' => $t->getText() ];
315 
316  if ( $namespace ) {
317  $query['namespace'] = $namespace;
318  }
319 
320  if ( $hideredirects ) {
321  $query['hideredirects'] = $hideredirects;
322  }
323 
324  $navLinks[] = $linkRenderer->makeKnownLink(
325  $self,
326  $this->msg( 'nextpage', $t->getText() )->text(),
327  [],
328  $query
329  );
330  }
331 
332  $this->outputHTMLForm( $namespace, $from, $to, $hideredirects );
333 
334  if ( count( $navLinks ) ) {
335  // Add pagination links
336  $pagination = Html::rawElement( 'div',
337  [ 'class' => 'mw-allpages-nav' ],
338  $this->getLanguage()->pipeList( $navLinks )
339  );
340 
341  $output->addHTML( $pagination );
342  $out .= Html::element( 'hr' ) . $pagination; // Footer
343  }
344 
345  $output->addHTML( $out );
346  }
347 
353  protected function getNamespaceKeyAndText( $ns, $text ) {
354  if ( $text == '' ) {
355  # shortcut for common case
356  return [ $ns, '', '' ];
357  }
358 
359  $t = Title::makeTitleSafe( $ns, $text );
360  if ( $t && $t->isLocal() ) {
361  return [ $t->getNamespace(), $t->getDBkey(), $t->getText() ];
362  } elseif ( $t ) {
363  return null;
364  }
365 
366  # try again, in case the problem was an empty pagename
367  $text = preg_replace( '/(#|$)/', 'X$1', $text );
368  $t = Title::makeTitleSafe( $ns, $text );
369  if ( $t && $t->isLocal() ) {
370  return [ $t->getNamespace(), '', '' ];
371  } else {
372  return null;
373  }
374  }
375 
384  public function prefixSearchSubpages( $search, $limit, $offset ) {
385  return $this->prefixSearchString( $search, $limit, $offset );
386  }
387 
388  protected function getGroupName() {
389  return 'pages';
390  }
391 }
SpecialAllPages\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialAllPages.php:388
SpecialPage\getPageTitle
getPageTitle( $subpage=false)
Get a self-referential title object.
Definition: SpecialPage.php:669
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:800
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:716
SpecialAllPages\execute
execute( $par)
Entry point : initialise variables and call subfunctions.
Definition: SpecialAllPages.php:58
SpecialAllPages\$maxPerPage
int $maxPerPage
Maximum number of pages to show on single subpage.
Definition: SpecialAllPages.php:37
SpecialAllPages\showToplevel
showToplevel( $namespace=NS_MAIN, $from='', $to='', $hideredirects=false)
Definition: SpecialAllPages.php:161
$s
$s
Definition: mergeMessageFileList.php:185
IncludableSpecialPage
Shortcut to construct an includable special page.
Definition: IncludableSpecialPage.php:29
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:746
$res
$res
Definition: testCompression.php:57
SpecialAllPages\__construct
__construct( $name='Allpages')
Definition: SpecialAllPages.php:49
$dbr
$dbr
Definition: testCompression.php:54
NS_MAIN
const NS_MAIN
Definition: Defines.php:69
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:315
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:30
SpecialPage\prefixSearchString
prefixSearchString( $search, $limit, $offset)
Perform a regular substring search for prefixSearchSubpages.
Definition: SpecialPage.php:515
SpecialPage\getConfig
getConfig()
Shortcut to get main config object.
Definition: SpecialPage.php:766
Title\newFromRow
static newFromRow( $row)
Make a Title object from a DB row.
Definition: Title.php:524
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2464
SpecialPage\setHeaders
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
Definition: SpecialPage.php:551
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:592
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
SpecialPage\getContext
getContext()
Gets the context this SpecialPage is executed in.
Definition: SpecialPage.php:689
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:618
SpecialAllPages\prefixSearchSubpages
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
Definition: SpecialAllPages.php:384
SpecialAllPages\outputHTMLForm
outputHTMLForm( $namespace=NS_MAIN, $from='', $to='', $hideRedirects=false)
Outputs the HTMLForm used on this page.
Definition: SpecialAllPages.php:102
SpecialAllPages\getNamespaceKeyAndText
getNamespaceKeyAndText( $ns, $text)
Definition: SpecialAllPages.php:353
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:706
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:912
$self
$self
Definition: doMaintenance.php:63
SpecialAllPages
Implements Special:Allpages.
Definition: SpecialAllPages.php:30
Html\openElement
static openElement( $element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition: Html.php:251
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:209
SpecialAllPages\showChunk
showChunk( $namespace=NS_MAIN, $from=false, $to=false, $hideredirects=false)
Definition: SpecialAllPages.php:178
$t
$t
Definition: testCompression.php:74
SpecialPage\$linkRenderer
MediaWiki Linker LinkRenderer null $linkRenderer
Definition: SpecialPage.php:69
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:231
SpecialAllPages\$nsfromMsg
string $nsfromMsg
Determines, which message describes the input field 'nsfrom'.
Definition: SpecialAllPages.php:44
HTMLForm\factory
static factory( $displayFormat,... $arguments)
Construct a HTMLForm object for given display type.
Definition: HTMLForm.php:311
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:636
SpecialPage\including
including( $x=null)
Whether the special page is being evaluated via transclusion.
Definition: SpecialPage.php:243