MediaWiki master
SpecialSpecialPages.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Specials;
22
29use Wikimedia\Parsoid\Core\SectionMetadata;
30use Wikimedia\Parsoid\Core\TOCData;
31
38
39 public function __construct() {
40 parent::__construct( 'Specialpages' );
41 }
42
43 public function execute( $par ) {
44 $out = $this->getOutput();
45 $this->setHeaders();
46 $this->outputHeader();
47 $out->setPreventClickjacking( false );
48 $out->addModuleStyles( 'mediawiki.special' );
49
50 $groups = $this->getPageGroups();
51
52 if ( $groups === false ) {
53 return;
54 }
55
56 $this->addHelpLink( 'Help:Special pages' );
57 $this->outputPageList( $groups );
58 }
59
60 private function getPageGroups() {
61 $pages = $this->getSpecialPageFactory()->getUsablePages( $this->getUser() );
62
63 if ( $pages === [] ) {
64 // Yeah, that was pointless. Thanks for coming.
65 return false;
66 }
67
68 // Put them into a sortable array
69 $groups = [];
70 foreach ( $pages as $page ) {
71 $group = $page->getFinalGroupName();
72 $desc = $page->getDescription();
73 // T343849
74 if ( is_string( $desc ) ) {
75 wfDeprecated( "string return from {$page->getName()}::getDescription()", '1.41' );
76 $desc = ( new RawMessage( '$1' ) )->rawParams( $desc );
77 }
78 $groups[$group][$desc->text()] = [
79 $page->getPageTitle(),
80 $page->isRestricted(),
81 $page->isCached()
82 ];
83 }
84
85 // Sort
86 foreach ( $groups as $group => $sortedPages ) {
87 ksort( $groups[$group] );
88 }
89
90 // Always move "other" to end
91 if ( array_key_exists( 'other', $groups ) ) {
92 $other = $groups['other'];
93 unset( $groups['other'] );
94 $groups['other'] = $other;
95 }
96
97 return $groups;
98 }
99
100 private function outputPageList( $groups ) {
101 $out = $this->getOutput();
102
103 // Legend
104 $includesRestrictedPages = false;
105 $includesCachedPages = false;
106 foreach ( $groups as $group => $sortedPages ) {
107 foreach ( $sortedPages as $desc => [ $title, $restricted, $cached ] ) {
108 if ( $cached ) {
109 $includesCachedPages = true;
110 }
111 if ( $restricted ) {
112 $includesRestrictedPages = true;
113 }
114 }
115 }
116
117 $notes = [];
118 if ( $includesRestrictedPages ) {
119 $restricedMsg = $this->msg( 'specialpages-note-restricted' );
120 if ( !$restricedMsg->isDisabled() ) {
121 $notes[] = $restricedMsg->parse();
122 }
123 }
124 if ( $includesCachedPages ) {
125 $cachedMsg = $this->msg( 'specialpages-note-cached' );
126 if ( !$cachedMsg->isDisabled() ) {
127 $notes[] = $cachedMsg->parse();
128 }
129 }
130 if ( $notes !== [] ) {
131 $legendHeading = $this->msg( 'specialpages-note-top' )->parse();
132
133 $legend = Html::rawElement(
134 'div',
135 [ 'class' => 'mw-changeslist-legend mw-specialpages-notes' ],
136 $legendHeading . implode( "\n", $notes )
137 );
138
139 $out->addHTML( $legend );
140 $out->addModuleStyles( 'mediawiki.special.changeslist.legend' );
141 }
142
143 // Format table of contents
144 $tocData = new TOCData();
145 $tocLength = 0;
146 foreach ( $groups as $group => $sortedPages ) {
147 if ( !str_contains( $group, '/' ) ) {
148 ++$tocLength;
149 $tocData->addSection( new SectionMetadata(
150 1,
151 2,
152 $this->msg( "specialpages-group-$group" )->escaped(),
153 $this->getLanguage()->formatNum( $tocLength ),
154 (string)$tocLength,
155 null,
156 null,
157 "mw-specialpagesgroup-$group",
158 "mw-specialpagesgroup-$group"
159 ) );
160 }
161 }
162
163 $pout = new ParserOutput;
164 $pout->setTOCData( $tocData );
165 $pout->setOutputFlag( ParserOutputFlags::SHOW_TOC );
166 $pout->setRawText( Parser::TOC_PLACEHOLDER );
167 $out->addParserOutput( $pout );
168
169 // Format contents
170 foreach ( $groups as $group => $sortedPages ) {
171 if ( str_contains( $group, '/' ) ) {
172 [ $group, $subGroup ] = explode( '/', $group, 2 );
173 $out->addHTML( Html::element(
174 'h3',
175 [ 'class' => "mw-specialpagessubgroup" ],
176 $this->msg( "specialpages-group-$group-$subGroup" )->text()
177 ) . "\n" );
178 } else {
179 $out->addHTML( Html::element(
180 'h2',
181 [ 'class' => "mw-specialpagesgroup", 'id' => "mw-specialpagesgroup-$group" ],
182 $this->msg( "specialpages-group-$group" )->text()
183 ) . "\n" );
184 }
185 $out->addHTML(
186 Html::openElement( 'div', [ 'class' => 'mw-specialpages-list' ] )
187 . '<ul>'
188 );
189 foreach ( $sortedPages as $desc => [ $title, $restricted, $cached ] ) {
190 $pageClasses = [];
191 if ( $cached ) {
192 $pageClasses[] = 'mw-specialpagecached';
193 }
194 if ( $restricted ) {
195 $pageClasses[] = 'mw-specialpagerestricted';
196 }
197
198 $link = $this->getLinkRenderer()->makeKnownLink( $title, $desc );
199 $out->addHTML( Html::rawElement(
200 'li',
201 [ 'class' => $pageClasses ],
202 $link
203 ) . "\n" );
204 }
205 $out->addHTML(
206 Html::closeElement( 'ul' ) .
207 Html::closeElement( 'div' )
208 );
209 }
210 }
211}
212
217class_alias( SpecialSpecialPages::class, 'SpecialSpecialpages' );
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
This class is a collection of static functions that serve two purposes:
Definition Html.php:56
Variant of the Message class.
ParserOutput is a rendering of a Content object or a message.
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition Parser.php:156
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getUser()
Shortcut to get the User executing this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
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.
element(SerializerNode $parent, SerializerNode $node, $contents)