25 parent::__construct(
'Specialpages' );
33 $out->getMetadata()->setPreventClickjacking(
false );
34 $out->addModuleStyles(
'mediawiki.special' );
36 $groups = $this->getPageGroups();
38 if ( $groups ===
false ) {
43 $this->outputPageList( $groups );
47 private function getPageGroups() {
50 if ( $pages === [] ) {
57 foreach ( $pages as $page ) {
58 $group = $page->getFinalGroupName();
59 $desc = $page->getDescription();
61 if ( !$desc->isDisabled() ) {
62 $groups[$group][$desc->text()] = [
63 $page->getPageTitle(),
64 $page->isRestricted(),
71 foreach ( $groups as $group => $sortedPages ) {
72 ksort( $groups[$group] );
76 if ( array_key_exists(
'other', $groups ) ) {
77 $other = $groups[
'other'];
78 unset( $groups[
'other'] );
79 $groups[
'other'] = $other;
85 private function outputPageList( array $groups ) {
88 $out->addModules(
'mediawiki.special.specialpages' );
92 $includesRestrictedPages =
false;
93 $includesCachedPages =
false;
94 foreach ( $groups as $group => $sortedPages ) {
95 foreach ( $sortedPages as $desc => [ $title, $restricted, $cached ] ) {
97 $includesCachedPages =
true;
100 $includesRestrictedPages =
true;
106 if ( $includesRestrictedPages ) {
107 $restricedMsg = $this->
msg(
'specialpages-note-restricted' );
108 if ( !$restricedMsg->isDisabled() ) {
109 $notes[] = $restricedMsg->parse();
112 if ( $includesCachedPages ) {
113 $cachedMsg = $this->
msg(
'specialpages-note-cached' );
114 if ( !$cachedMsg->isDisabled() ) {
115 $notes[] = $cachedMsg->parse();
118 if ( $notes !== [] ) {
119 $legendHeading = $this->
msg(
'specialpages-note-top' )->parse();
121 $legend = Html::rawElement(
123 [
'class' => [
'mw-changeslist-legend',
'mw-specialpages-notes' ] ],
124 $legendHeading . implode(
"\n", $notes )
127 $out->addHTML( $legend );
128 $out->addModuleStyles(
'mediawiki.special.changeslist.legend' );
131 $out->addHTML( (
new FieldLayout(
132 new SearchInputWidget( [
133 'placeholder' => $this->
msg(
'specialpages-header-search' )->text(),
136 'classes' => [
'mw-special-pages-search' ],
137 'label' => $this->
msg(
'specialpages-header-search' )->text(),
138 'invisibleLabel' =>
true,
144 $tocData =
new TOCData();
146 foreach ( $groups as $group => $sortedPages ) {
147 if ( !str_contains( $group,
'/' ) ) {
149 $tocData->addSection(
new SectionMetadata(
152 $this->
msg(
"specialpages-group-$group" )->escaped(),
157 "mw-specialpagesgroup-$group",
158 "mw-specialpagesgroup-$group"
163 $out->addTOCPlaceholder( $tocData );
167 foreach ( $groups as $group => $sortedPages ) {
168 if ( str_contains( $group,
'/' ) ) {
169 [ $group, $subGroup ] = explode(
'/', $group, 2 );
172 [
'class' =>
"mw-specialpagessubgroup" ],
173 $this->
msg(
"specialpages-group-$group-$subGroup" )->text()
178 [
'class' =>
"mw-specialpagesgroup",
'id' =>
"mw-specialpagesgroup-$group" ],
179 $this->
msg(
"specialpages-group-$group" )->text()
183 Html::openElement(
'div', [
'class' =>
'mw-specialpages-list' ] )
186 foreach ( $sortedPages as $desc => [ $title, $restricted, $cached ] ) {
187 $indexAttr = [
'data-search-index-0' => $language->lc( $title->getText() ) ];
189 foreach ( $aliases as $alias => $target ) {
192 $target == $title->getText() &&
193 $language->lc( $alias ) !== $language->lc( $title->getText() )
195 $indexAttr[
'data-search-index-' . $c ] = $language->lc( $alias );
201 $pageClasses[] =
'mw-specialpagecached';
204 $pageClasses[] =
'mw-specialpagerestricted';
208 $out->addHTML( Html::rawElement(
210 $indexAttr + [
'class' => $pageClasses ],
215 Html::closeElement(
'ul' ) .
216 Html::closeElement(
'div' )