MediaWiki REL1_34
NamespaceInfo.php
Go to the documentation of this file.
1<?php
26
34
41
43 private $canonicalNamespaces = null;
44
46 private $namespaceIndexes = false;
47
49 private $validNamespaces = null;
50
52 private $options;
53
62 public static $canonicalNames = [
63 NS_MEDIA => 'Media',
64 NS_SPECIAL => 'Special',
65 NS_MAIN => '',
66 NS_TALK => 'Talk',
67 NS_USER => 'User',
68 NS_USER_TALK => 'User_talk',
69 NS_PROJECT => 'Project',
70 NS_PROJECT_TALK => 'Project_talk',
71 NS_FILE => 'File',
72 NS_FILE_TALK => 'File_talk',
73 NS_MEDIAWIKI => 'MediaWiki',
74 NS_MEDIAWIKI_TALK => 'MediaWiki_talk',
75 NS_TEMPLATE => 'Template',
76 NS_TEMPLATE_TALK => 'Template_talk',
77 NS_HELP => 'Help',
78 NS_HELP_TALK => 'Help_talk',
79 NS_CATEGORY => 'Category',
80 NS_CATEGORY_TALK => 'Category_talk',
81 ];
82
89 public static $constructorOptions = [
90 'AllowImageMoving',
91 'CanonicalNamespaceNames',
92 'CapitalLinkOverrides',
93 'CapitalLinks',
94 'ContentNamespaces',
95 'ExtraNamespaces',
96 'ExtraSignatureNamespaces',
97 'NamespaceContentModels',
98 'NamespacesWithSubpages',
99 'NonincludableNamespaces',
100 ];
101
105 public function __construct( ServiceOptions $options ) {
106 $options->assertRequiredOptions( self::$constructorOptions );
107 $this->options = $options;
108 }
109
122 private function isMethodValidFor( $index, $method ) {
123 if ( $index < NS_MAIN ) {
124 throw new MWException( "$method does not make any sense for given namespace $index" );
125 }
126 return true;
127 }
128
135 public function isMovable( $index ) {
136 $result = $index >= NS_MAIN &&
137 ( $index != NS_FILE || $this->options->get( 'AllowImageMoving' ) );
138
142 Hooks::run( 'NamespaceIsMovable', [ $index, &$result ] );
143
144 return $result;
145 }
146
153 public function isSubject( $index ) {
154 return !$this->isTalk( $index );
155 }
156
163 public function isTalk( $index ) {
164 return $index > NS_MAIN
165 && $index % 2;
166 }
167
176 public function getTalk( $index ) {
177 $this->isMethodValidFor( $index, __METHOD__ );
178 return $this->isTalk( $index )
179 ? $index
180 : $index + 1;
181 }
182
192 public function getTalkPage( LinkTarget $target ) : LinkTarget {
193 if ( $target->getText() === '' ) {
194 throw new MWException( 'Can\'t determine talk page associated with relative section link' );
195 }
196
197 if ( $target->getInterwiki() !== '' ) {
198 throw new MWException( 'Can\'t determine talk page associated with interwiki link' );
199 }
200
201 if ( $this->isTalk( $target->getNamespace() ) ) {
202 return $target;
203 }
204
205 // NOTE: getTalk throws on bad namespaces!
206 return new TitleValue( $this->getTalk( $target->getNamespace() ), $target->getDBkey() );
207 }
208
220 public function canHaveTalkPage( LinkTarget $target ) {
221 if ( $target->getText() === '' || $target->getInterwiki() !== '' ) {
222 return false;
223 }
224
225 if ( $target->getNamespace() < NS_MAIN ) {
226 return false;
227 }
228
229 return true;
230 }
231
239 public function getSubject( $index ) {
240 # Handle special namespaces
241 if ( $index < NS_MAIN ) {
242 return $index;
243 }
244
245 return $this->isTalk( $index )
246 ? $index - 1
247 : $index;
248 }
249
254 public function getSubjectPage( LinkTarget $target ) : LinkTarget {
255 if ( $this->isSubject( $target->getNamespace() ) ) {
256 return $target;
257 }
258 return new TitleValue( $this->getSubject( $target->getNamespace() ), $target->getDBkey() );
259 }
260
270 public function getAssociated( $index ) {
271 $this->isMethodValidFor( $index, __METHOD__ );
272
273 if ( $this->isSubject( $index ) ) {
274 return $this->getTalk( $index );
275 }
276 return $this->getSubject( $index );
277 }
278
285 public function getAssociatedPage( LinkTarget $target ) : LinkTarget {
286 if ( $target->getText() === '' ) {
287 throw new MWException( 'Can\'t determine talk page associated with relative section link' );
288 }
289
290 if ( $target->getInterwiki() !== '' ) {
291 throw new MWException( 'Can\'t determine talk page associated with interwiki link' );
292 }
293
294 return new TitleValue(
295 $this->getAssociated( $target->getNamespace() ), $target->getDBkey() );
296 }
297
305 public function exists( $index ) {
306 $nslist = $this->getCanonicalNamespaces();
307 return isset( $nslist[$index] );
308 }
309
323 public function equals( $ns1, $ns2 ) {
324 return $ns1 == $ns2;
325 }
326
337 public function subjectEquals( $ns1, $ns2 ) {
338 return $this->getSubject( $ns1 ) == $this->getSubject( $ns2 );
339 }
340
347 public function getCanonicalNamespaces() {
348 if ( $this->canonicalNamespaces === null ) {
349 $this->canonicalNamespaces =
350 [ NS_MAIN => '' ] + $this->options->get( 'CanonicalNamespaceNames' );
351 $this->canonicalNamespaces +=
352 ExtensionRegistry::getInstance()->getAttribute( 'ExtensionNamespaces' );
353 if ( is_array( $this->options->get( 'ExtraNamespaces' ) ) ) {
354 $this->canonicalNamespaces += $this->options->get( 'ExtraNamespaces' );
355 }
356 Hooks::run( 'CanonicalNamespaces', [ &$this->canonicalNamespaces ] );
357 }
358 return $this->canonicalNamespaces;
359 }
360
367 public function getCanonicalName( $index ) {
368 $nslist = $this->getCanonicalNamespaces();
369 return $nslist[$index] ?? false;
370 }
371
379 public function getCanonicalIndex( $name ) {
380 if ( $this->namespaceIndexes === false ) {
381 $this->namespaceIndexes = [];
382 foreach ( $this->getCanonicalNamespaces() as $i => $text ) {
383 $this->namespaceIndexes[strtolower( $text )] = $i;
384 }
385 }
386 if ( array_key_exists( $name, $this->namespaceIndexes ) ) {
387 return $this->namespaceIndexes[$name];
388 } else {
389 return null;
390 }
391 }
392
398 public function getValidNamespaces() {
399 if ( is_null( $this->validNamespaces ) ) {
400 $this->validNamespaces = [];
401 foreach ( array_keys( $this->getCanonicalNamespaces() ) as $ns ) {
402 if ( $ns >= 0 ) {
403 $this->validNamespaces[] = $ns;
404 }
405 }
406 // T109137: sort numerically
407 sort( $this->validNamespaces, SORT_NUMERIC );
408 }
409
410 return $this->validNamespaces;
411 }
412
413 /*
414
421 public function hasTalkNamespace( $index ) {
422 return $index >= NS_MAIN;
423 }
424
432 public function isContent( $index ) {
433 return $index == NS_MAIN || in_array( $index, $this->options->get( 'ContentNamespaces' ) );
434 }
435
443 public function wantSignatures( $index ) {
444 return $this->isTalk( $index ) ||
445 in_array( $index, $this->options->get( 'ExtraSignatureNamespaces' ) );
446 }
447
454 public function isWatchable( $index ) {
455 return $index >= NS_MAIN;
456 }
457
464 public function hasSubpages( $index ) {
465 return !empty( $this->options->get( 'NamespacesWithSubpages' )[$index] );
466 }
467
472 public function getContentNamespaces() {
473 $contentNamespaces = $this->options->get( 'ContentNamespaces' );
474 if ( !is_array( $contentNamespaces ) || $contentNamespaces === [] ) {
475 return [ NS_MAIN ];
476 } elseif ( !in_array( NS_MAIN, $contentNamespaces ) ) {
477 // always force NS_MAIN to be part of array (to match the algorithm used by isContent)
478 return array_merge( [ NS_MAIN ], $contentNamespaces );
479 } else {
480 return $contentNamespaces;
481 }
482 }
483
490 public function getSubjectNamespaces() {
491 return array_filter(
492 $this->getValidNamespaces(),
493 [ $this, 'isSubject' ]
494 );
495 }
496
503 public function getTalkNamespaces() {
504 return array_filter(
505 $this->getValidNamespaces(),
506 [ $this, 'isTalk' ]
507 );
508 }
509
516 public function isCapitalized( $index ) {
517 // Turn NS_MEDIA into NS_FILE
518 $index = $index === NS_MEDIA ? NS_FILE : $index;
519
520 // Make sure to get the subject of our namespace
521 $index = $this->getSubject( $index );
522
523 // Some namespaces are special and should always be upper case
524 if ( in_array( $index, $this->alwaysCapitalizedNamespaces ) ) {
525 return true;
526 }
527 $overrides = $this->options->get( 'CapitalLinkOverrides' );
528 if ( isset( $overrides[$index] ) ) {
529 // CapitalLinkOverrides is explicitly set
530 return $overrides[$index];
531 }
532 // Default to the global setting
533 return $this->options->get( 'CapitalLinks' );
534 }
535
543 public function hasGenderDistinction( $index ) {
544 return $index == NS_USER || $index == NS_USER_TALK;
545 }
546
553 public function isNonincludable( $index ) {
554 $namespaces = $this->options->get( 'NonincludableNamespaces' );
555 return $namespaces && in_array( $index, $namespaces );
556 }
557
568 public function getNamespaceContentModel( $index ) {
569 return $this->options->get( 'NamespaceContentModels' )[$index] ?? null;
570 }
571
581 public function getRestrictionLevels( $index, User $user = null ) {
582 // PermissionManager is not injected because adding an explicit dependency
583 // breaks MW installer by adding a dependency chain on the database before
584 // it was set up. Also, the method is deprecated and will be soon removed.
585 return MediaWikiServices::getInstance()
586 ->getPermissionManager()
587 ->getNamespaceRestrictionLevels( $index, $user );
588 }
589
599 public function getCategoryLinkType( $index ) {
600 $this->isMethodValidFor( $index, __METHOD__ );
601
602 if ( $index == NS_CATEGORY ) {
603 return 'subcat';
604 } elseif ( $index == NS_FILE ) {
605 return 'file';
606 } else {
607 return 'page';
608 }
609 }
610
618 public static function getCommonNamespaces() {
619 return array_keys( self::$canonicalNames );
620 }
621}
MediaWiki exception.
A class for passing options to services.
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
MediaWikiServices is the service locator for the application scope of MediaWiki.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
getAssociatedPage(LinkTarget $target)
ServiceOptions $options
__construct(ServiceOptions $options)
static array $canonicalNames
Definitions of the NS_ constants are in Defines.php.
equals( $ns1, $ns2)
Returns whether the specified namespaces are the same namespace.
subjectEquals( $ns1, $ns2)
Returns whether the specified namespaces share the same subject.
getCanonicalName( $index)
Returns the canonical (English) name for a given index.
string[] null $canonicalNamespaces
Canonical namespaces cache.
isSubject( $index)
Is the given namespace is a subject (non-talk) namespace?
$alwaysCapitalizedNamespaces
These namespaces should always be first-letter capitalized, now and forevermore.
getValidNamespaces()
Returns an array of the namespaces (by integer id) that exist on the wiki.
exists( $index)
Returns whether the specified namespace exists.
getSubjectPage(LinkTarget $target)
isMethodValidFor( $index, $method)
Throw an exception when trying to get the subject or talk page for a given namespace where it does no...
int[] null $validNamespaces
Valid namespaces cache.
getCanonicalNamespaces()
Returns array of all defined namespaces with their canonical (English) names.
getSubject( $index)
Get the subject namespace index for a given namespace Special namespaces (NS_MEDIA,...
static array $constructorOptions
TODO Make this const when HHVM support is dropped (T192166)
array false $namespaceIndexes
Canonical namespaces index cache.
canHaveTalkPage(LinkTarget $target)
Can the title have a corresponding talk page?
getTalk( $index)
Get the talk namespace index for a given namespace.
isMovable( $index)
Can pages in the given namespace be moved?
getAssociated( $index)
Get the associated namespace.
getTalkPage(LinkTarget $target)
Get a LinkTarget referring to the talk page of $target.
isTalk( $index)
Is the given namespace a talk namespace?
getCanonicalIndex( $name)
Returns the index for a given canonical name, or NULL The input must be converted to lower case first...
Represents a page (or page fragment) title within MediaWiki.
const NS_HELP
Definition Defines.php:81
const NS_USER
Definition Defines.php:71
const NS_FILE
Definition Defines.php:75
const NS_MEDIAWIKI_TALK
Definition Defines.php:78
const NS_MAIN
Definition Defines.php:69
const NS_PROJECT_TALK
Definition Defines.php:74
const NS_MEDIAWIKI
Definition Defines.php:77
const NS_TEMPLATE
Definition Defines.php:79
const NS_SPECIAL
Definition Defines.php:58
const NS_FILE_TALK
Definition Defines.php:76
const NS_HELP_TALK
Definition Defines.php:82
const NS_CATEGORY_TALK
Definition Defines.php:84
const NS_MEDIA
Definition Defines.php:57
const NS_TALK
Definition Defines.php:70
const NS_USER_TALK
Definition Defines.php:72
const NS_PROJECT
Definition Defines.php:73
const NS_CATEGORY
Definition Defines.php:83
const NS_TEMPLATE_TALK
Definition Defines.php:80
if($IP===false)
getInterwiki()
The interwiki component of this LinkTarget.
getNamespace()
Get the namespace index.
getText()
Returns the link in text form, without namespace prefix or fragment.