MediaWiki REL1_39
SpecialPrefixindex.php
Go to the documentation of this file.
1<?php
25
32
37 protected $stripPrefix = false;
38
39 protected $hideRedirects = false;
40
41 // Inherit $maxPerPage
42
44 private $loadBalancer;
45
47 private $linkCache;
48
53 public function __construct(
54 ILoadBalancer $loadBalancer,
55 LinkCache $linkCache
56 ) {
57 parent::__construct( $loadBalancer );
58 $this->mName = 'Prefixindex';
59 $this->loadBalancer = $loadBalancer;
60 $this->linkCache = $linkCache;
61 }
62
67 public function execute( $par ) {
68 $this->setHeaders();
69 $this->outputHeader();
70
71 $out = $this->getOutput();
72 $out->addModuleStyles( 'mediawiki.special' );
73
74 # GET values
75 $request = $this->getRequest();
76 $from = $request->getVal( 'from', '' );
77 $prefix = $request->getVal( 'prefix', '' );
78 $ns = $request->getIntOrNull( 'namespace' );
79 $namespace = (int)$ns; // if no namespace given, use 0 (NS_MAIN).
80 $this->hideRedirects = $request->getBool( 'hideredirects', $this->hideRedirects );
81 $this->stripPrefix = $request->getBool( 'stripprefix', $this->stripPrefix );
82
83 $namespaces = $this->getContentLanguage()->getNamespaces();
84 $out->setPageTitle(
85 ( $namespace > 0 && array_key_exists( $namespace, $namespaces ) )
86 ? $this->msg( 'prefixindex-namespace', str_replace( '_', ' ', $namespaces[$namespace] ) )
87 : $this->msg( 'prefixindex' )
88 );
89
90 $showme = '';
91 if ( $par !== null ) {
92 $showme = $par;
93 } elseif ( $prefix != '' ) {
94 $showme = $prefix;
95 } elseif ( $from != '' && $ns === null ) {
96 // For back-compat with Special:Allpages
97 // Don't do this if namespace is passed, so paging works when doing NS views.
98 $showme = $from;
99 }
100
101 // T29864: if transcluded, show all pages instead of the form.
102 if ( $this->including() || $showme != '' || $ns !== null ) {
103 $this->showPrefixChunk( $namespace, $showme, $from );
104 } else {
105 $out->addHTML( $this->namespacePrefixForm( $namespace, '' ) );
106 }
107 }
108
115 protected function namespacePrefixForm( $namespace = NS_MAIN, $from = '' ) {
116 $formDescriptor = [
117 'prefix' => [
118 'label-message' => 'allpagesprefix',
119 'name' => 'prefix',
120 'id' => 'nsfrom',
121 'type' => 'text',
122 'size' => '30',
123 'default' => str_replace( '_', ' ', $from ),
124 ],
125 'namespace' => [
126 'type' => 'namespaceselect',
127 'name' => 'namespace',
128 'id' => 'namespace',
129 'label-message' => 'namespace',
130 'all' => null,
131 'default' => $namespace,
132 ],
133 'hidedirects' => [
134 'class' => HTMLCheckField::class,
135 'name' => 'hideredirects',
136 'label-message' => 'allpages-hide-redirects',
137 ],
138 'stripprefix' => [
139 'class' => HTMLCheckField::class,
140 'name' => 'stripprefix',
141 'label-message' => 'prefixindex-strip',
142 ],
143 ];
144 $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
145 ->setMethod( 'get' )
146 ->setTitle( $this->getPageTitle() ) // Remove subpage
147 ->setWrapperLegendMsg( 'prefixindex' )
148 ->setSubmitTextMsg( 'prefixindex-submit' );
149
150 return $htmlForm->prepareForm()->getHTML( false );
151 }
152
158 protected function showPrefixChunk( $namespace, $prefix, $from = null ) {
159 if ( $from === null ) {
160 $from = $prefix;
161 }
162
163 $fromList = $this->getNamespaceKeyAndText( $namespace, $from );
164 $prefixList = $this->getNamespaceKeyAndText( $namespace, $prefix );
165 $namespaces = $this->getContentLanguage()->getNamespaces();
166 $res = null;
167 $n = 0;
168 $nextRow = null;
169
170 if ( !$prefixList || !$fromList ) {
171 $out = $this->msg( 'allpagesbadtitle' )->parseAsBlock();
172 } elseif ( !array_key_exists( $namespace, $namespaces ) ) {
173 // Show errormessage and reset to NS_MAIN
174 $out = $this->msg( 'allpages-bad-ns', $namespace )->parse();
175 $namespace = NS_MAIN;
176 } else {
177 list( $namespace, $prefixKey, $prefix ) = $prefixList;
178 list( /* $fromNS */, $fromKey, ) = $fromList;
179
180 # ## @todo FIXME: Should complain if $fromNs != $namespace
181
182 $dbr = $this->loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA );
183
184 $conds = [
185 'page_namespace' => $namespace,
186 'page_title' . $dbr->buildLike( $prefixKey, $dbr->anyString() ),
187 'page_title >= ' . $dbr->addQuotes( $fromKey ),
188 ];
189
190 if ( $this->hideRedirects ) {
191 $conds['page_is_redirect'] = 0;
192 }
193
194 $res = $dbr->select( 'page',
195 LinkCache::getSelectFields(),
196 $conds,
197 __METHOD__,
198 [
199 'ORDER BY' => 'page_title',
200 'LIMIT' => $this->maxPerPage + 1,
201 'USE INDEX' => 'page_name_title',
202 ]
203 );
204
205 // @todo FIXME: Side link to previous
206
207 if ( $res->numRows() > 0 ) {
208 $out = Html::openElement( 'ul', [ 'class' => 'mw-prefixindex-list' ] );
209
210 $prefixLength = strlen( $prefix );
211 foreach ( $res as $row ) {
212 if ( $n >= $this->maxPerPage ) {
213 $nextRow = $row;
214 break;
215 }
216 $title = Title::newFromRow( $row );
217 // Make sure it gets into LinkCache
218 $this->linkCache->addGoodLinkObjFromRow( $title, $row );
219 $displayed = $title->getText();
220 // Try not to generate unclickable links
221 if ( $this->stripPrefix && $prefixLength !== strlen( $displayed ) ) {
222 $displayed = substr( $displayed, $prefixLength );
223 }
224 $link = ( $title->isRedirect() ? '<div class="allpagesredirect">' : '' ) .
225 $this->getLinkRenderer()->makeKnownLink(
226 $title,
227 $displayed
228 ) .
229 ( $title->isRedirect() ? '</div>' : '' );
230
231 $out .= "<li>$link</li>\n";
232 $n++;
233
234 }
235 $out .= Html::closeElement( 'ul' );
236
237 if ( $res->numRows() > 2 ) {
238 // Only apply CSS column styles if there's more than 2 entries.
239 // Otherwise rendering is broken as "mw-prefixindex-body"'s CSS column count is 3.
240 $out = Html::rawElement( 'div', [ 'class' => 'mw-prefixindex-body' ], $out );
241 }
242 } else {
243 $out = '';
244 }
245 }
246
247 $output = $this->getOutput();
248
249 if ( $this->including() ) {
250 // We don't show the nav-links and the form when included into other
251 // pages so let's just finish here.
252 $output->addHTML( $out );
253 return;
254 }
255
256 $topOut = $this->namespacePrefixForm( $namespace, $prefix );
257
258 if ( $res && ( $n == $this->maxPerPage ) && $nextRow ) {
259 $query = [
260 'from' => $nextRow->page_title,
261 'prefix' => $prefix,
262 'hideredirects' => $this->hideRedirects,
263 'stripprefix' => $this->stripPrefix,
264 ];
265
266 if ( $namespace || $prefix == '' ) {
267 // Keep the namespace even if it's 0 for empty prefixes.
268 // This tells us we're not just a holdover from old links.
269 $query['namespace'] = $namespace;
270 }
271
272 $nextLink = $this->getLinkRenderer()->makeKnownLink(
273 $this->getPageTitle(),
274 $this->msg( 'nextpage', str_replace( '_', ' ', $nextRow->page_title ) )->text(),
275 [],
276 $query
277 );
278
279 // Link shown at the top of the page below the form
280 $topOut .= Html::rawElement( 'div',
281 [ 'class' => 'mw-prefixindex-nav' ],
282 $nextLink
283 );
284
285 // Link shown at the footer
286 $out .= "\n" . Html::element( 'hr' ) .
287 Html::rawElement(
288 'div',
289 [ 'class' => 'mw-prefixindex-nav' ],
290 $nextLink
291 );
292
293 }
294
295 $output->addHTML( $topOut . $out );
296 }
297
298 protected function getGroupName() {
299 return 'pages';
300 }
301}
const NS_MAIN
Definition Defines.php:64
Cache for article titles (prefixed DB keys) and ids linked from one source.
Definition LinkCache.php:42
Implements Special:Allpages.
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.
getRequest()
Get the WebRequest being used for this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
getContentLanguage()
Shortcut to get content language.
including( $x=null)
Whether the special page is being evaluated via transclusion.
Implements Special:Prefixindex.
showPrefixChunk( $namespace, $prefix, $from=null)
namespacePrefixForm( $namespace=NS_MAIN, $from='')
HTML for the top form.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
__construct(ILoadBalancer $loadBalancer, LinkCache $linkCache)
$stripPrefix
Whether to remove the searched prefix from the displayed link.
execute( $par)
Entry point : initialise variables and call subfunctions.
Create and track the database connections and transactions for a given database cluster.