21 use TocGeneratorTrait;
24 parent::__construct(
'Specialpages' );
32 $out->getMetadata()->setPreventClickjacking(
false );
33 $out->addModuleStyles(
'mediawiki.special' );
35 $groups = $this->getPageGroups();
37 if ( $groups ===
false ) {
42 $this->outputPageList( $groups );
46 private function getPageGroups() {
49 if ( $pages === [] ) {
56 foreach ( $pages as $page ) {
57 $group = $page->getFinalGroupName();
58 $desc = $page->getDescription();
60 if ( !$desc->isDisabled() ) {
61 $groups[$group][$desc->text()] = [
62 $page->getPageTitle(),
63 $page->isRestricted(),
70 foreach ( $groups as $group => $sortedPages ) {
71 ksort( $groups[$group] );
75 if ( array_key_exists(
'other', $groups ) ) {
76 $other = $groups[
'other'];
77 unset( $groups[
'other'] );
78 $groups[
'other'] = $other;
84 private function outputPageList( array $groups ) {
86 $out->addModules(
'mediawiki.special.specialpages' );
90 $includesRestrictedPages =
false;
91 $includesCachedPages =
false;
92 foreach ( $groups as $group => $sortedPages ) {
93 foreach ( $sortedPages as $desc => [ $title, $restricted, $cached ] ) {
95 $includesCachedPages =
true;
98 $includesRestrictedPages =
true;
104 if ( $includesRestrictedPages ) {
105 $restrictedMsg = $this->
msg(
'specialpages-note-restricted' );
106 if ( !$restrictedMsg->isDisabled() ) {
107 $notes[] = $restrictedMsg->parse();
110 if ( $includesCachedPages ) {
111 $cachedMsg = $this->
msg(
'specialpages-note-cached' );
112 if ( !$cachedMsg->isDisabled() ) {
113 $notes[] = $cachedMsg->parse();
116 if ( $notes !== [] ) {
117 $legendHeading = $this->
msg(
'specialpages-note-top' )->parse();
119 $legend = Html::rawElement(
121 [
'class' => [
'mw-changeslist-legend',
'mw-specialpages-notes' ] ],
122 $legendHeading . implode(
"\n", $notes )
125 $out->addHTML( $legend );
126 $out->addModuleStyles(
'mediawiki.special.changeslist.legend' );
129 $out->addHTML( (
new FieldLayout(
130 new SearchInputWidget( [
131 'placeholder' => $this->
msg(
'specialpages-header-search' )->text(),
134 'classes' => [
'mw-special-pages-search' ],
135 'label' => $this->
msg(
'specialpages-header-search' )->text(),
136 'invisibleLabel' =>
true,
142 foreach ( $groups as $group => $sortedPages ) {
143 if ( !str_contains( $group,
'/' ) ) {
145 id:
"mw-specialpagesgroup-$group",
146 msg:
"specialpages-group-$group"
150 $out->addTOCPlaceholder( $this->
getTocData() );
155 foreach ( $groups as $group => $sortedPages ) {
156 if ( str_contains( $group,
'/' ) ) {
157 [ $group, $subGroup ] = explode(
'/', $group, 2 );
160 [
'class' =>
"mw-specialpagessubgroup" ],
161 $this->
msg(
"specialpages-group-$group-$subGroup" )->text()
166 [
'class' =>
"mw-specialpagesgroup",
'id' =>
"mw-specialpagesgroup-$group" ],
167 $this->
msg(
"specialpages-group-$group" )->text()
171 Html::openElement(
'div', [
'class' =>
'mw-specialpages-list' ] )
174 foreach ( $sortedPages as $desc => [ $title, $restricted, $cached ] ) {
177 if ( $canonicalName !==
null ) {
179 foreach ( $aliases[ $canonicalName ] ?? [] as $alias ) {
180 $indexAttr[
'data-search-index-' . $c ] = str_replace(
'_',
' ', $language->lc( $alias ) );
186 $pageClasses[] =
'mw-specialpagecached';
189 $pageClasses[] =
'mw-specialpagerestricted';
193 $out->addHTML( Html::rawElement(
195 $indexAttr + [
'class' => $pageClasses ],
200 Html::closeElement(
'ul' ) .
201 Html::closeElement(
'div' )