Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 127
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialNamespaceInfo
0.00% covered (danger)
0.00%
0 / 127
0.00% covered (danger)
0.00%
0 / 4
600
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 1
12
 makeNamespaceRow
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 1
380
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * @license GPL-2.0-or-later
5 * @file
6 * @ingroup SpecialPage
7 */
8
9namespace MediaWiki\Specials;
10
11use MediaWiki\Html\Html;
12use MediaWiki\Language\Language;
13use MediaWiki\MainConfigNames;
14use MediaWiki\SpecialPage\SpecialPage;
15use MediaWiki\Title\NamespaceInfo;
16
17/**
18 * Show information about the different namespaces
19 *
20 * @since 1.43
21 * @author DannyS712
22 * @ingroup SpecialPage
23 */
24class SpecialNamespaceInfo extends SpecialPage {
25
26    public function __construct(
27        private readonly NamespaceInfo $namespaceInfo,
28        private readonly Language $contentLanguage
29    ) {
30        parent::__construct( 'NamespaceInfo' );
31    }
32
33    /**
34     * @param string|null $par
35     */
36    public function execute( $par ) {
37        $this->setHeaders();
38        $this->outputHeader();
39
40        $out = $this->getOutput();
41
42        $idHeading = Html::element(
43            'th',
44            [],
45            $this->msg( 'namespaceinfo-heading-id' )->text()
46        );
47        $canonicalHeading = Html::element(
48            'th',
49            [],
50            $this->msg( 'namespaceinfo-heading-canonical' )->text()
51        );
52        $localHeading = Html::element(
53            'th',
54            [],
55            $this->msg( 'namespaceinfo-heading-local' )->text()
56        );
57        $aliasHeading = Html::element(
58            'th',
59            [],
60            $this->msg( 'namespaceinfo-heading-aliases' )->text()
61        );
62        $infoHeading = Html::element(
63            'th',
64            [],
65            $this->msg( 'namespaceinfo-heading-info' )->text()
66        );
67        $tableHeadingRow = Html::rawElement(
68            'tr',
69            [],
70            $idHeading . $canonicalHeading . $localHeading . $aliasHeading . $infoHeading
71        );
72
73        $allAliases = $this->contentLanguage->getNamespaceAliases();
74
75        $aliases = [];
76        foreach ( $allAliases as $alias => $ns ) {
77            $aliases[$ns][] = $alias;
78        }
79
80        $tableBodyRows = '';
81        foreach ( $this->getContentLanguage()->getFormattedNamespaces() as $ns => $localName ) {
82            $namespaceAliases = $aliases[$ns] ?? [];
83            $tableBodyRows .= $this->makeNamespaceRow( $ns, $localName, $namespaceAliases );
84        }
85
86        $table = Html::rawElement(
87            'table',
88            [ 'class' => 'wikitable' ],
89            $tableHeadingRow . $tableBodyRows
90        );
91
92        $out->addHtml( $table );
93    }
94
95    /**
96     * Get the HTML for a row for a specific namespace
97     *
98     * @param int $ns
99     * @param string $localName
100     * @return string
101     */
102    private function makeNamespaceRow( int $ns, string $localName, array $aliases = [] ): string {
103        $canonicalName = $this->namespaceInfo->getCanonicalName( $ns );
104        if ( $canonicalName ) {
105            $canonicalName = strtr( $canonicalName, '_', ' ' );
106        } else {
107            $canonicalName = '';
108        }
109
110        // Special handling for main namespace
111        if ( $ns === NS_MAIN ) {
112            $localName = $this->msg( 'blanknamespace' )->escaped();
113            $canonicalName = $this->msg( 'blanknamespace' )->inLanguage( 'en' )->escaped();
114        }
115
116        $description = $this->msg( 'namespaceinfo-description-ns' . $ns );
117        if ( $description->isDisabled() ) {
118            // Custom namespace with no message
119
120            if ( $this->namespaceInfo->isTalk( $ns ) ) {
121                $subjectNs = $this->namespaceInfo->getSubject( $ns );
122                $subjectName = strtr(
123                    $this->namespaceInfo->getCanonicalName( $subjectNs ),
124                    '_',
125                    ' '
126                );
127                $description = $this->msg( 'namespaceinfo-description-custom-talk',
128                    $subjectName,
129                    $subjectNs
130                );
131            } else {
132                $description = $this->msg( 'namespaceinfo-description-custom', $localName );
133            }
134        }
135        $descriptionText = $description->parse();
136
137        $properties = [];
138        if ( $ns >= NS_MAIN ) {
139            // Don't talk about immovable namespaces for virtual NS_SPECIAL or NS_MEDIA
140            $namespaceProtection = $this->getConfig()->get( MainConfigNames::NamespaceProtection );
141            if ( isset( $namespaceProtection[$ns] ) ) {
142                $rightsNeeded = $namespaceProtection[$ns];
143                if ( !is_array( $rightsNeeded ) ) {
144                    $rightsNeeded = [ $rightsNeeded ];
145                }
146                foreach ( $rightsNeeded as $right ) {
147                    $properties[] = $this->msg( 'namespaceinfo-namespace-protection-right', $right )
148                        ->parse();
149                }
150            }
151
152            if ( !$this->namespaceInfo->isMovable( $ns ) ) {
153                $properties[] = $this->msg( 'namespaceinfo-namespace-immovable' )->parse();
154            }
155            if ( $this->namespaceInfo->isContent( $ns ) ) {
156                $properties[] = $this->msg( 'namespaceinfo-namespace-iscontent' )->parse();
157            }
158            if ( $this->namespaceInfo->hasSubpages( $ns ) ) {
159                $properties[] = $this->msg( 'namespaceinfo-namespace-subpages' )->parse();
160            }
161            if ( $this->namespaceInfo->isNonincludable( $ns ) ) {
162                $properties[] = $this->msg( 'namespaceinfo-namespace-nonincludable' )->parse();
163            }
164            $contentModel = $this->namespaceInfo->getNamespaceContentModel( $ns );
165            if ( $contentModel !== null ) {
166                $properties[] = $this->msg( 'namespaceinfo-namespace-default-contentmodel' )
167                    ->params( $contentModel )
168                    ->parse();
169            }
170        }
171
172        // Convert to a string
173        $namespaceProperties = '';
174        if ( $properties !== [] ) {
175            $namespaceProperties = Html::openElement( 'ul' );
176            foreach ( $properties as $propertyText ) {
177                $namespaceProperties .= Html::rawElement(
178                    'li',
179                    [],
180                    $propertyText
181                );
182            }
183            $namespaceProperties .= Html::closeElement( 'ul' );
184        }
185
186        $namespaceAliases = '';
187        if ( $aliases !== [] ) {
188            if ( count( $aliases ) === 1 ) {
189                $namespaceAliases = htmlspecialchars( str_replace( '_', ' ', $aliases[0] ) );
190            } else {
191                $namespaceAliases = Html::openElement( 'ul' );
192                foreach ( $aliases as $alias ) {
193                    // cleanup _ for display, since _ is only used internally and not for display
194                    $alias = str_replace( "_", " ", $alias );
195                    $namespaceAliases .= Html::element(
196                        'li',
197                        [],
198                        $alias
199                    );
200                }
201                $namespaceAliases .= Html::closeElement( 'ul' );
202            }
203
204        }
205
206        $idField = Html::rawElement( 'td', [], (string)$ns );
207        $canonicalField = Html::rawElement( 'td', [], $canonicalName );
208        $localField = Html::rawElement( 'td', [], $localName );
209        $aliasesField = Html::rawElement( 'td', [], $namespaceAliases );
210        $infoField = Html::rawElement( 'td', [], $descriptionText . $namespaceProperties );
211
212        return Html::rawElement(
213            'tr',
214            [],
215            $idField . $canonicalField . $localField . $aliasesField . $infoField
216        );
217    }
218
219    /**
220     * @return string
221     */
222    protected function getGroupName() {
223        return 'wiki';
224    }
225
226}