]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/specials/SpecialPrefixindex.php
MediaWiki 1.30.2-scripts2
[autoinstallsdev/mediawiki.git] / includes / specials / SpecialPrefixindex.php
1 <?php
2 /**
3  * Implements Special:Prefixindex
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 use MediaWiki\MediaWikiServices;
24
25 /**
26  * Implements Special:Prefixindex
27  *
28  * @ingroup SpecialPage
29  */
30 class SpecialPrefixindex extends SpecialAllPages {
31
32         /**
33          * Whether to remove the searched prefix from the displayed link. Useful
34          * for inclusion of a set of sub pages in a root page.
35          */
36         protected $stripPrefix = false;
37
38         protected $hideRedirects = false;
39
40         // Inherit $maxPerPage
41
42         function __construct() {
43                 parent::__construct( 'Prefixindex' );
44         }
45
46         /**
47          * Entry point : initialise variables and call subfunctions.
48          * @param string $par Becomes "FOO" when called like Special:Prefixindex/FOO (default null)
49          */
50         function execute( $par ) {
51                 global $wgContLang;
52
53                 $this->setHeaders();
54                 $this->outputHeader();
55
56                 $out = $this->getOutput();
57                 $out->addModuleStyles( 'mediawiki.special' );
58
59                 # GET values
60                 $request = $this->getRequest();
61                 $from = $request->getVal( 'from', '' );
62                 $prefix = $request->getVal( 'prefix', '' );
63                 $ns = $request->getIntOrNull( 'namespace' );
64                 $namespace = (int)$ns; // if no namespace given, use 0 (NS_MAIN).
65                 $this->hideRedirects = $request->getBool( 'hideredirects', $this->hideRedirects );
66                 $this->stripPrefix = $request->getBool( 'stripprefix', $this->stripPrefix );
67
68                 $namespaces = $wgContLang->getNamespaces();
69                 $out->setPageTitle(
70                         ( $namespace > 0 && array_key_exists( $namespace, $namespaces ) )
71                                 ? $this->msg( 'prefixindex-namespace', str_replace( '_', ' ', $namespaces[$namespace] ) )
72                                 : $this->msg( 'prefixindex' )
73                 );
74
75                 $showme = '';
76                 if ( $par !== null ) {
77                         $showme = $par;
78                 } elseif ( $prefix != '' ) {
79                         $showme = $prefix;
80                 } elseif ( $from != '' && $ns === null ) {
81                         // For back-compat with Special:Allpages
82                         // Don't do this if namespace is passed, so paging works when doing NS views.
83                         $showme = $from;
84                 }
85
86                 // T29864: if transcluded, show all pages instead of the form.
87                 if ( $this->including() || $showme != '' || $ns !== null ) {
88                         $this->showPrefixChunk( $namespace, $showme, $from );
89                 } else {
90                         $out->addHTML( $this->namespacePrefixForm( $namespace, null ) );
91                 }
92         }
93
94         /**
95          * HTML for the top form
96          * @param int $namespace A namespace constant (default NS_MAIN).
97          * @param string $from DbKey we are starting listing at.
98          * @return string
99          */
100         protected function namespacePrefixForm( $namespace = NS_MAIN, $from = '' ) {
101                 $out = Xml::openElement( 'div', [ 'class' => 'namespaceoptions' ] );
102                 $out .= Xml::openElement(
103                         'form',
104                         [ 'method' => 'get', 'action' => $this->getConfig()->get( 'Script' ) ]
105                 );
106                 $out .= Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() );
107                 $out .= Xml::openElement( 'fieldset' );
108                 $out .= Xml::element( 'legend', null, $this->msg( 'allpages' )->text() );
109                 $out .= Xml::openElement( 'table', [ 'id' => 'nsselect', 'class' => 'allpages' ] );
110                 $out .= "<tr>
111                                 <td class='mw-label'>" .
112                         Xml::label( $this->msg( 'allpagesprefix' )->text(), 'nsfrom' ) .
113                         "</td>
114                                 <td class='mw-input'>" .
115                         Xml::input( 'prefix', 30, str_replace( '_', ' ', $from ), [ 'id' => 'nsfrom' ] ) .
116                         "</td>
117                         </tr>
118                         <tr>
119                         <td class='mw-label'>" .
120                         Xml::label( $this->msg( 'namespace' )->text(), 'namespace' ) .
121                         "</td>
122                                 <td class='mw-input'>" .
123                         Html::namespaceSelector( [
124                                 'selected' => $namespace,
125                         ], [
126                                 'name' => 'namespace',
127                                 'id' => 'namespace',
128                                 'class' => 'namespaceselector',
129                         ] ) .
130                         Xml::checkLabel(
131                                 $this->msg( 'allpages-hide-redirects' )->text(),
132                                 'hideredirects',
133                                 'hideredirects',
134                                 $this->hideRedirects
135                         ) . ' ' .
136                         Xml::checkLabel(
137                                 $this->msg( 'prefixindex-strip' )->text(),
138                                 'stripprefix',
139                                 'stripprefix',
140                                 $this->stripPrefix
141                         ) . ' ' .
142                         Xml::submitButton( $this->msg( 'prefixindex-submit' )->text() ) .
143                         "</td>
144                         </tr>";
145                 $out .= Xml::closeElement( 'table' );
146                 $out .= Xml::closeElement( 'fieldset' );
147                 $out .= Xml::closeElement( 'form' );
148                 $out .= Xml::closeElement( 'div' );
149
150                 return $out;
151         }
152
153         /**
154          * @param int $namespace Default NS_MAIN
155          * @param string $prefix
156          * @param string $from List all pages from this name (default false)
157          */
158         protected function showPrefixChunk( $namespace = NS_MAIN, $prefix, $from = null ) {
159                 global $wgContLang;
160
161                 if ( $from === null ) {
162                         $from = $prefix;
163                 }
164
165                 $fromList = $this->getNamespaceKeyAndText( $namespace, $from );
166                 $prefixList = $this->getNamespaceKeyAndText( $namespace, $prefix );
167                 $namespaces = $wgContLang->getNamespaces();
168                 $res = null;
169                 $n = 0;
170                 $nextRow = null;
171
172                 if ( !$prefixList || !$fromList ) {
173                         $out = $this->msg( 'allpagesbadtitle' )->parseAsBlock();
174                 } elseif ( !array_key_exists( $namespace, $namespaces ) ) {
175                         // Show errormessage and reset to NS_MAIN
176                         $out = $this->msg( 'allpages-bad-ns', $namespace )->parse();
177                         $namespace = NS_MAIN;
178                 } else {
179                         list( $namespace, $prefixKey, $prefix ) = $prefixList;
180                         list( /* $fromNS */, $fromKey, ) = $fromList;
181
182                         # ## @todo FIXME: Should complain if $fromNs != $namespace
183
184                         $dbr = wfGetDB( DB_REPLICA );
185
186                         $conds = [
187                                 'page_namespace' => $namespace,
188                                 'page_title' . $dbr->buildLike( $prefixKey, $dbr->anyString() ),
189                                 'page_title >= ' . $dbr->addQuotes( $fromKey ),
190                         ];
191
192                         if ( $this->hideRedirects ) {
193                                 $conds['page_is_redirect'] = 0;
194                         }
195
196                         $res = $dbr->select( 'page',
197                                 array_merge(
198                                         [ 'page_namespace', 'page_title' ],
199                                         LinkCache::getSelectFields()
200                                 ),
201                                 $conds,
202                                 __METHOD__,
203                                 [
204                                         'ORDER BY' => 'page_title',
205                                         'LIMIT' => $this->maxPerPage + 1,
206                                         'USE INDEX' => 'name_title',
207                                 ]
208                         );
209
210                         // @todo FIXME: Side link to previous
211
212                         if ( $res->numRows() > 0 ) {
213                                 $out = Html::openElement( 'ul', [ 'class' => 'mw-prefixindex-list' ] );
214                                 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
215
216                                 $prefixLength = strlen( $prefix );
217                                 foreach ( $res as $row ) {
218                                         if ( $n >= $this->maxPerPage ) {
219                                                 $nextRow = $row;
220                                                 break;
221                                         }
222                                         $title = Title::newFromRow( $row );
223                                         // Make sure it gets into LinkCache
224                                         $linkCache->addGoodLinkObjFromRow( $title, $row );
225                                         $displayed = $title->getText();
226                                         // Try not to generate unclickable links
227                                         if ( $this->stripPrefix && $prefixLength !== strlen( $displayed ) ) {
228                                                 $displayed = substr( $displayed, $prefixLength );
229                                         }
230                                         $link = ( $title->isRedirect() ? '<div class="allpagesredirect">' : '' ) .
231                                                 $this->getLinkRenderer()->makeKnownLink(
232                                                         $title,
233                                                         $displayed
234                                                 ) .
235                                                 ( $title->isRedirect() ? '</div>' : '' );
236
237                                         $out .= "<li>$link</li>\n";
238                                         $n++;
239
240                                 }
241                                 $out .= Html::closeElement( 'ul' );
242
243                                 if ( $res->numRows() > 2 ) {
244                                         // Only apply CSS column styles if there's more than 2 entries.
245                                         // Otherwise rendering is broken as "mw-prefixindex-body"'s CSS column count is 3.
246                                         $out = Html::rawElement( 'div', [ 'class' => 'mw-prefixindex-body' ], $out );
247                                 }
248                         } else {
249                                 $out = '';
250                         }
251                 }
252
253                 $output = $this->getOutput();
254
255                 if ( $this->including() ) {
256                         // We don't show the nav-links and the form when included into other
257                         // pages so let's just finish here.
258                         $output->addHTML( $out );
259                         return;
260                 }
261
262                 $topOut = $this->namespacePrefixForm( $namespace, $prefix );
263
264                 if ( $res && ( $n == $this->maxPerPage ) && $nextRow ) {
265                         $query = [
266                                 'from' => $nextRow->page_title,
267                                 'prefix' => $prefix,
268                                 'hideredirects' => $this->hideRedirects,
269                                 'stripprefix' => $this->stripPrefix,
270                         ];
271
272                         if ( $namespace || $prefix == '' ) {
273                                 // Keep the namespace even if it's 0 for empty prefixes.
274                                 // This tells us we're not just a holdover from old links.
275                                 $query['namespace'] = $namespace;
276                         }
277
278                         $nextLink = $this->getLinkRenderer()->makeKnownLink(
279                                 $this->getPageTitle(),
280                                 $this->msg( 'nextpage', str_replace( '_', ' ', $nextRow->page_title ) )->text(),
281                                 [],
282                                 $query
283                         );
284
285                         // Link shown at the top of the page below the form
286                         $topOut .= Html::rawElement( 'div',
287                                 [ 'class' => 'mw-prefixindex-nav' ],
288                                 $nextLink
289                         );
290
291                         // Link shown at the footer
292                         $out .= "\n" . Html::element( 'hr' ) .
293                                 Html::rawElement(
294                                         'div',
295                                         [ 'class' => 'mw-prefixindex-nav' ],
296                                         $nextLink
297                                 );
298
299                 }
300
301                 $output->addHTML( $topOut . $out );
302         }
303
304         /**
305          * Return an array of subpages beginning with $search that this special page will accept.
306          *
307          * @param string $search Prefix to search for
308          * @param int $limit Maximum number of results to return (usually 10)
309          * @param int $offset Number of results to skip (usually 0)
310          * @return string[] Matching subpages
311          */
312         public function prefixSearchSubpages( $search, $limit, $offset ) {
313                 return $this->prefixSearchString( $search, $limit, $offset );
314         }
315
316         protected function getGroupName() {
317                 return 'pages';
318         }
319 }