Added a hook into MWNamespace::getCanonicalNamespaces() to provide safe way to
[lhc/web/wiklou.git] / includes / Namespace.php
1 <?php
2 /**
3 * Provide things related to namespaces
4 * @file
5 */
6
7 /**
8 * Definitions of the NS_ constants are in Defines.php
9 * @private
10 */
11 $wgCanonicalNamespaceNames = array(
12 NS_MEDIA => 'Media',
13 NS_SPECIAL => 'Special',
14 NS_TALK => 'Talk',
15 NS_USER => 'User',
16 NS_USER_TALK => 'User_talk',
17 NS_PROJECT => 'Project',
18 NS_PROJECT_TALK => 'Project_talk',
19 NS_FILE => 'File',
20 NS_FILE_TALK => 'File_talk',
21 NS_MEDIAWIKI => 'MediaWiki',
22 NS_MEDIAWIKI_TALK => 'MediaWiki_talk',
23 NS_TEMPLATE => 'Template',
24 NS_TEMPLATE_TALK => 'Template_talk',
25 NS_HELP => 'Help',
26 NS_HELP_TALK => 'Help_talk',
27 NS_CATEGORY => 'Category',
28 NS_CATEGORY_TALK => 'Category_talk',
29 );
30
31 /// @todo UGLY UGLY
32 if( is_array( $wgExtraNamespaces ) ) {
33 $wgCanonicalNamespaceNames = $wgCanonicalNamespaceNames + $wgExtraNamespaces;
34 }
35
36 /**
37 * This is a utility class with only static functions
38 * for dealing with namespaces that encodes all the
39 * "magic" behaviors of them based on index. The textual
40 * names of the namespaces are handled by Language.php.
41 *
42 * These are synonyms for the names given in the language file
43 * Users and translators should not change them
44 *
45 */
46
47 class MWNamespace {
48
49 /**
50 * These namespaces should always be first-letter capitalized, now and
51 * forevermore. Historically, they could've probably been lowercased too,
52 * but some things are just too ingrained now. :)
53 */
54 private static $alwaysCapitalizedNamespaces = array( NS_SPECIAL, NS_USER, NS_MEDIAWIKI );
55
56 /**
57 * Can pages in the given namespace be moved?
58 *
59 * @param $index Int: namespace index
60 * @return bool
61 */
62 public static function isMovable( $index ) {
63 global $wgAllowImageMoving;
64 return !( $index < NS_MAIN || ($index == NS_FILE && !$wgAllowImageMoving) || $index == NS_CATEGORY );
65 }
66
67 /**
68 * Is the given namespace is a subject (non-talk) namespace?
69 *
70 * @param $index Int: namespace index
71 * @return bool
72 */
73 public static function isMain( $index ) {
74 return !self::isTalk( $index );
75 }
76
77 /**
78 * Is the given namespace a talk namespace?
79 *
80 * @param $index Int: namespace index
81 * @return bool
82 */
83 public static function isTalk( $index ) {
84 return $index > NS_MAIN
85 && $index % 2;
86 }
87
88 /**
89 * Get the talk namespace index for a given namespace
90 *
91 * @param $index Int: namespace index
92 * @return int
93 */
94 public static function getTalk( $index ) {
95 return self::isTalk( $index )
96 ? $index
97 : $index + 1;
98 }
99
100 /**
101 * Get the subject namespace index for a given namespace
102 *
103 * @param $index Int: Namespace index
104 * @return int
105 */
106 public static function getSubject( $index ) {
107 return self::isTalk( $index )
108 ? $index - 1
109 : $index;
110 }
111
112 /**
113 * Returns whether the specified namespace exists
114 */
115 public static function exists( $index ) {
116 $nslist = self::getCanonicalNamespaces();
117 return isset( $nslist[$index] );
118 }
119
120
121 /**
122 * Returns array of all defined namespaces with their canonical
123 * (English) names.
124 *
125 * @return \array
126 * @since 1.17
127 */
128 public static function getCanonicalNamespaces() {
129 static $namespaces = null;
130 if ( $namespaces === null ) {
131 global $wgExtraNamespaces, $wgCanonicalNamespaceNames;
132 if ( is_array( $wgExtraNamespaces ) ) {
133 $namespaces = $wgCanonicalNamespaceNames + $wgExtraNamespaces;
134 } else {
135 $namespaces = $wgCanonicalNamespaceNames;
136 }
137 $namespaces[NS_MAIN] = '';
138 wfRunHooks( 'CanonicalNamespaces', array( &$namespaces ) );
139 }
140 return $namespaces;
141 }
142
143 /**
144 * Returns the canonical (English) name for a given index
145 *
146 * @param $index Int: namespace index
147 * @return string or false if no canonical definition.
148 */
149 public static function getCanonicalName( $index ) {
150 $nslist = self::getCanonicalNamespaces();
151 if( isset( $nslist[$index] ) ) {
152 return $nslist[$index];
153 } else {
154 return false;
155 }
156 }
157
158 /**
159 * Returns the index for a given canonical name, or NULL
160 * The input *must* be converted to lower case first
161 *
162 * @param $name String: namespace name
163 * @return int
164 */
165 public static function getCanonicalIndex( $name ) {
166 static $xNamespaces = false;
167 if ( $xNamespaces === false ) {
168 $xNamespaces = array();
169 foreach ( self::getCanonicalNamespaces() as $i => $text ) {
170 $xNamespaces[strtolower($text)] = $i;
171 }
172 }
173 if ( array_key_exists( $name, $xNamespaces ) ) {
174 return $xNamespaces[$name];
175 } else {
176 return null;
177 }
178 }
179
180 /**
181 * Returns an array of the namespaces (by integer id) that exist on the
182 * wiki. Used primarily by the api in help documentation.
183 * @return array
184 */
185 public static function getValidNamespaces() {
186 static $mValidNamespaces = null;
187
188 if ( is_null( $mValidNamespaces ) ) {
189 foreach ( array_keys( self::getCanonicalNamespaces() ) as $ns ) {
190 if ( $ns >= 0 ) {
191 $mValidNamespaces[] = $ns;
192 }
193 }
194 }
195
196 return $mValidNamespaces;
197 }
198
199 /**
200 * Can this namespace ever have a talk namespace?
201 *
202 * @param $index Int: namespace index
203 * @return bool
204 */
205 public static function canTalk( $index ) {
206 return $index >= NS_MAIN;
207 }
208
209 /**
210 * Does this namespace contain content, for the purposes of calculating
211 * statistics, etc?
212 *
213 * @param $index Int: index to check
214 * @return bool
215 */
216 public static function isContent( $index ) {
217 global $wgContentNamespaces;
218 return $index == NS_MAIN || in_array( $index, $wgContentNamespaces );
219 }
220
221 /**
222 * Can pages in a namespace be watched?
223 *
224 * @param $index Int
225 * @return bool
226 */
227 public static function isWatchable( $index ) {
228 return $index >= NS_MAIN;
229 }
230
231 /**
232 * Does the namespace allow subpages?
233 *
234 * @param $index int Index to check
235 * @return bool
236 */
237 public static function hasSubpages( $index ) {
238 global $wgNamespacesWithSubpages;
239 return !empty( $wgNamespacesWithSubpages[$index] );
240 }
241
242 /**
243 * Is the namespace first-letter capitalized?
244 *
245 * @param $index int Index to check
246 * @return bool
247 */
248 public static function isCapitalized( $index ) {
249 global $wgCapitalLinks, $wgCapitalLinkOverrides;
250 // Turn NS_MEDIA into NS_FILE
251 $index = $index === NS_MEDIA ? NS_FILE : $index;
252
253 // Make sure to get the subject of our namespace
254 $index = self::getSubject( $index );
255
256 // Some namespaces are special and should always be upper case
257 if ( in_array( $index, self::$alwaysCapitalizedNamespaces ) ) {
258 return true;
259 }
260 if ( isset( $wgCapitalLinkOverrides[ $index ] ) ) {
261 // $wgCapitalLinkOverrides is explicitly set
262 return $wgCapitalLinkOverrides[ $index ];
263 }
264 // Default to the global setting
265 return $wgCapitalLinks;
266 }
267 }