MediaWiki fundraising/REL1_35
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
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
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
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}
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
An IContextSource implementation which will inherit context from another source but allow individual ...
Shortcut to construct an includable special page.
Implements Special:Allpages.
int $maxPerPage
Maximum number of pages to show on single subpage.
__construct( $name='Allpages')
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
showToplevel( $namespace=NS_MAIN, $from='', $to='', $hideredirects=false)
execute( $par)
Entry point : initialise variables and call subfunctions.
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
showChunk( $namespace=NS_MAIN, $from=false, $to=false, $hideredirects=false)
string $nsfromMsg
Determines, which message describes the input field 'nsfrom'.
outputHTMLForm( $namespace=NS_MAIN, $from='', $to='', $hideRedirects=false)
Outputs the HTMLForm used on this page.
getNamespaceKeyAndText( $ns, $text)
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!...
getOutput()
Get the OutputPage being used for this instance.
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
getLanguage()
Shortcut to get user's language.
including( $x=null)
Whether the special page is being evaluated via transclusion.
prefixSearchString( $search, $limit, $offset)
Perform a regular substring search for prefixSearchSubpages.
MediaWiki Linker LinkRenderer null $linkRenderer
const NS_MAIN
Definition Defines.php:70
const DB_REPLICA
Definition defines.php:25