MediaWiki master
SpecialSpecialPages.php
Go to the documentation of this file.
1<?php
7namespace MediaWiki\Specials;
8
10use MediaWiki\Html\TocGeneratorTrait;
12use OOUI\FieldLayout;
13use OOUI\SearchInputWidget;
14
21 use TocGeneratorTrait;
22
23 public function __construct() {
24 parent::__construct( 'Specialpages' );
25 }
26
28 public function execute( $par ) {
29 $out = $this->getOutput();
30 $this->setHeaders();
31 $this->outputHeader();
32 $out->getMetadata()->setPreventClickjacking( false );
33 $out->addModuleStyles( 'mediawiki.special' );
34
35 $groups = $this->getPageGroups();
36
37 if ( $groups === false ) {
38 return;
39 }
40
41 $this->addHelpLink( 'Help:Special pages' );
42 $this->outputPageList( $groups );
43 }
44
46 private function getPageGroups() {
47 $pages = $this->getSpecialPageFactory()->getUsablePages( $this->getUser(), $this->getContext() );
48
49 if ( $pages === [] ) {
50 // Yeah, that was pointless. Thanks for coming.
51 return false;
52 }
53
54 // Put them into a sortable array
55 $groups = [];
56 foreach ( $pages as $page ) {
57 $group = $page->getFinalGroupName();
58 $desc = $page->getDescription();
59 // (T360723) Only show an entry if the message isn't blanked, to allow on-wiki unlisting
60 if ( !$desc->isDisabled() ) {
61 $groups[$group][$desc->text()] = [
62 $page->getPageTitle(),
63 $page->isRestricted(),
64 $page->isCached()
65 ];
66 }
67 }
68
69 // Sort
70 foreach ( $groups as $group => $sortedPages ) {
71 ksort( $groups[$group] );
72 }
73
74 // Always move "other" to end
75 if ( array_key_exists( 'other', $groups ) ) {
76 $other = $groups['other'];
77 unset( $groups['other'] );
78 $groups['other'] = $other;
79 }
80
81 return $groups;
82 }
83
84 private function outputPageList( array $groups ) {
85 $out = $this->getOutput();
86 $out->addModules( 'mediawiki.special.specialpages' );
87 $out->enableOOUI();
88
89 // Legend
90 $includesRestrictedPages = false;
91 $includesCachedPages = false;
92 foreach ( $groups as $group => $sortedPages ) {
93 foreach ( $sortedPages as $desc => [ $title, $restricted, $cached ] ) {
94 if ( $cached ) {
95 $includesCachedPages = true;
96 }
97 if ( $restricted ) {
98 $includesRestrictedPages = true;
99 }
100 }
101 }
102
103 $notes = [];
104 if ( $includesRestrictedPages ) {
105 $restrictedMsg = $this->msg( 'specialpages-note-restricted' );
106 if ( !$restrictedMsg->isDisabled() ) {
107 $notes[] = $restrictedMsg->parse();
108 }
109 }
110 if ( $includesCachedPages ) {
111 $cachedMsg = $this->msg( 'specialpages-note-cached' );
112 if ( !$cachedMsg->isDisabled() ) {
113 $notes[] = $cachedMsg->parse();
114 }
115 }
116 if ( $notes !== [] ) {
117 $legendHeading = $this->msg( 'specialpages-note-top' )->parse();
118
119 $legend = Html::rawElement(
120 'div',
121 [ 'class' => [ 'mw-changeslist-legend', 'mw-specialpages-notes' ] ],
122 $legendHeading . implode( "\n", $notes )
123 );
124
125 $out->addHTML( $legend );
126 $out->addModuleStyles( 'mediawiki.special.changeslist.legend' );
127 }
128
129 $out->addHTML( ( new FieldLayout(
130 new SearchInputWidget( [
131 'placeholder' => $this->msg( 'specialpages-header-search' )->text(),
132 ] ),
133 [
134 'classes' => [ 'mw-special-pages-search' ],
135 'label' => $this->msg( 'specialpages-header-search' )->text(),
136 'invisibleLabel' => true,
137 'infusable' => true,
138 ]
139 ) )->toString() );
140
141 // Format table of contents
142 foreach ( $groups as $group => $sortedPages ) {
143 if ( !str_contains( $group, '/' ) ) {
144 $this->addTocSection(
145 id: "mw-specialpagesgroup-$group",
146 msg: "specialpages-group-$group"
147 );
148 }
149 }
150 $out->addTOCPlaceholder( $this->getTocData() );
151
152 // Format contents
153 $aliases = $this->getContentLanguage()->getSpecialPageAliases();
154 $language = $this->getLanguage();
155 foreach ( $groups as $group => $sortedPages ) {
156 if ( str_contains( $group, '/' ) ) {
157 [ $group, $subGroup ] = explode( '/', $group, 2 );
158 $out->addHTML( Html::element(
159 'h3',
160 [ 'class' => "mw-specialpagessubgroup" ],
161 $this->msg( "specialpages-group-$group-$subGroup" )->text()
162 ) . "\n" );
163 } else {
164 $out->addHTML( Html::element(
165 'h2',
166 [ 'class' => "mw-specialpagesgroup", 'id' => "mw-specialpagesgroup-$group" ],
167 $this->msg( "specialpages-group-$group" )->text()
168 ) . "\n" );
169 }
170 $out->addHTML(
171 Html::openElement( 'div', [ 'class' => 'mw-specialpages-list' ] )
172 . '<ul>'
173 );
174 foreach ( $sortedPages as $desc => [ $title, $restricted, $cached ] ) {
175 [ $canonicalName ] = $this->getSpecialPageFactory()->resolveAlias( $title->getDBkey() );
176 $indexAttr = [];
177 if ( $canonicalName !== null ) {
178 $c = 0;
179 foreach ( $aliases[ $canonicalName ] ?? [] as $alias ) {
180 $indexAttr[ 'data-search-index-' . $c ] = str_replace( '_', ' ', $language->lc( $alias ) );
181 ++$c;
182 }
183 }
184 $pageClasses = [];
185 if ( $cached ) {
186 $pageClasses[] = 'mw-specialpagecached';
187 }
188 if ( $restricted ) {
189 $pageClasses[] = 'mw-specialpagerestricted';
190 }
191
192 $link = $this->getLinkRenderer()->makeKnownLink( $title, $desc );
193 $out->addHTML( Html::rawElement(
194 'li',
195 $indexAttr + [ 'class' => $pageClasses ],
196 $link
197 ) . "\n" );
198 }
199 $out->addHTML(
200 Html::closeElement( 'ul' ) .
201 Html::closeElement( 'div' )
202 );
203 }
204 }
205}
206
207// @codeCoverageIgnoreStart
212class_alias( SpecialSpecialPages::class, 'SpecialSpecialpages' );
213// @codeCoverageIgnoreEnd
This class is a collection of static functions that serve two purposes:
Definition Html.php:44
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getUser()
Shortcut to get the User executing this instance.
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getContentLanguage()
Shortcut to get content language.
getLanguage()
Shortcut to get user's language.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages By default the message key is the canonical name of...
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Shortcut to construct a special page which is unlisted by default.
A special page that lists special pages.
execute( $par)
Default execute method Checks user permissions.This must be overridden by subclasses; it will be made...
element(SerializerNode $parent, SerializerNode $node, $contents)
addTocSection(string $id, string $msg,... $params)
Add a section to the table of contents.