coding style tweaks + removed some PHP4-isms
[lhc/web/wiklou.git] / includes / Namespace.php
1 <?php
2 /**
3 * Provide things related to namespaces
4 * @file
5 */
6
7 /**
8 * This is a utility class with only static functions
9 * for dealing with namespaces that encodes all the
10 * "magic" behaviors of them based on index. The textual
11 * names of the namespaces are handled by Language.php.
12 *
13 * These are synonyms for the names given in the language file
14 * Users and translators should not change them
15 *
16 */
17
18 class MWNamespace {
19
20 /**
21 * These namespaces should always be first-letter capitalized, now and
22 * forevermore. Historically, they could've probably been lowercased too,
23 * but some things are just too ingrained now. :)
24 */
25 private static $alwaysCapitalizedNamespaces = array( NS_SPECIAL, NS_USER, NS_MEDIAWIKI );
26
27 /**
28 * Throw an exception when trying to get the subject or talk page
29 * for a given namespace where it does not make sense.
30 * Special namespaces are defined in includes/define.php and have
31 * a value below 0 (ex: NS_SPECIAL = -1 , NS_MEDIA = -2)
32 *
33 * @param $index
34 * @param $method
35 *
36 * @return true
37 */
38 private static function isMethodValidFor( $index, $method ) {
39 if( $index < NS_MAIN ) {
40 throw new MWException( "$method does not make any sense for given namespace $index" );
41 }
42 return true;
43 }
44
45 /**
46 * Can pages in the given namespace be moved?
47 *
48 * @param $index Int: namespace index
49 * @return bool
50 */
51 public static function isMovable( $index ) {
52 global $wgAllowImageMoving;
53 return !( $index < NS_MAIN || ($index == NS_FILE && !$wgAllowImageMoving) || $index == NS_CATEGORY );
54 }
55
56 /**
57 * Is the given namespace is a subject (non-talk) namespace?
58 *
59 * @param $index Int: namespace index
60 * @return bool
61 */
62 public static function isMain( $index ) {
63 return !self::isTalk( $index );
64 }
65
66 /**
67 * Is the given namespace a talk namespace?
68 *
69 * @param $index Int: namespace index
70 * @return bool
71 */
72 public static function isTalk( $index ) {
73 return $index > NS_MAIN
74 && $index % 2;
75 }
76
77 /**
78 * Get the talk namespace index for a given namespace
79 *
80 * @param $index Int: namespace index
81 * @return int
82 */
83 public static function getTalk( $index ) {
84 self::isMethodValidFor( $index, __METHOD__ );
85 return self::isTalk( $index )
86 ? $index
87 : $index + 1;
88 }
89
90 /**
91 * Get the subject namespace index for a given namespace
92 * Special namespaces (NS_MEDIA, NS_SPECIAL) are always the subject.
93 *
94 * @param $index Int: Namespace index
95 * @return int
96 */
97 public static function getSubject( $index ) {
98 # Handle special namespaces
99 if( $index < NS_MAIN ) {
100 return $index;
101 }
102
103 return self::isTalk( $index )
104 ? $index - 1
105 : $index;
106 }
107
108 /**
109 * Get the associated namespace.
110 * For talk namespaces, returns the subject (non-talk) namespace
111 * For subject (non-talk) namespaces, returns the talk namespace
112 *
113 * @param $index Int: namespace index
114 * @return int or null if no associated namespace could be found
115 */
116 public static function getAssociated( $index ) {
117 self::isMethodValidFor( $index, __METHOD__ );
118
119 if( self::isMain( $index ) ) {
120 return self::getTalk( $index );
121 } elseif( self::isTalk( $index ) ) {
122 return self::getSubject( $index );
123 } else {
124 return null;
125 }
126 }
127
128 /**
129 * Returns whether the specified namespace exists
130 *
131 * @param $index
132 *
133 * @return bool
134 */
135 public static function exists( $index ) {
136 $nslist = self::getCanonicalNamespaces();
137 return isset( $nslist[$index] );
138 }
139
140 /**
141 * Returns array of all defined namespaces with their canonical
142 * (English) names.
143 *
144 * @return \array
145 * @since 1.17
146 */
147 public static function getCanonicalNamespaces() {
148 static $namespaces = null;
149 if ( $namespaces === null ) {
150 global $wgExtraNamespaces, $wgCanonicalNamespaceNames;
151 $namespaces = array( NS_MAIN => '' ) + $wgCanonicalNamespaceNames;
152 if ( is_array( $wgExtraNamespaces ) ) {
153 $namespaces += $wgExtraNamespaces;
154 }
155 wfRunHooks( 'CanonicalNamespaces', array( &$namespaces ) );
156 }
157 return $namespaces;
158 }
159
160 /**
161 * Returns the canonical (English) name for a given index
162 *
163 * @param $index Int: namespace index
164 * @return string or false if no canonical definition.
165 */
166 public static function getCanonicalName( $index ) {
167 $nslist = self::getCanonicalNamespaces();
168 if( isset( $nslist[$index] ) ) {
169 return $nslist[$index];
170 } else {
171 return false;
172 }
173 }
174
175 /**
176 * Returns the index for a given canonical name, or NULL
177 * The input *must* be converted to lower case first
178 *
179 * @param $name String: namespace name
180 * @return int
181 */
182 public static function getCanonicalIndex( $name ) {
183 static $xNamespaces = false;
184 if ( $xNamespaces === false ) {
185 $xNamespaces = array();
186 foreach ( self::getCanonicalNamespaces() as $i => $text ) {
187 $xNamespaces[strtolower($text)] = $i;
188 }
189 }
190 if ( array_key_exists( $name, $xNamespaces ) ) {
191 return $xNamespaces[$name];
192 } else {
193 return null;
194 }
195 }
196
197 /**
198 * Returns an array of the namespaces (by integer id) that exist on the
199 * wiki. Used primarily by the api in help documentation.
200 * @return array
201 */
202 public static function getValidNamespaces() {
203 static $mValidNamespaces = null;
204
205 if ( is_null( $mValidNamespaces ) ) {
206 foreach ( array_keys( self::getCanonicalNamespaces() ) as $ns ) {
207 if ( $ns >= 0 ) {
208 $mValidNamespaces[] = $ns;
209 }
210 }
211 }
212
213 return $mValidNamespaces;
214 }
215
216 /**
217 * Can this namespace ever have a talk namespace?
218 *
219 * @param $index Int: namespace index
220 * @return bool
221 */
222 public static function canTalk( $index ) {
223 return $index >= NS_MAIN;
224 }
225
226 /**
227 * Does this namespace contain content, for the purposes of calculating
228 * statistics, etc?
229 *
230 * @param $index Int: index to check
231 * @return bool
232 */
233 public static function isContent( $index ) {
234 global $wgContentNamespaces;
235 return $index == NS_MAIN || in_array( $index, $wgContentNamespaces );
236 }
237
238 /**
239 * Can pages in a namespace be watched?
240 *
241 * @param $index Int
242 * @return bool
243 */
244 public static function isWatchable( $index ) {
245 return $index >= NS_MAIN;
246 }
247
248 /**
249 * Does the namespace allow subpages?
250 *
251 * @param $index int Index to check
252 * @return bool
253 */
254 public static function hasSubpages( $index ) {
255 global $wgNamespacesWithSubpages;
256 return !empty( $wgNamespacesWithSubpages[$index] );
257 }
258
259 /**
260 * Get a list of all namespace indices which are considered to contain content
261 * @return array of namespace indices
262 */
263 public static function getContentNamespaces() {
264 global $wgContentNamespaces;
265 if( !is_array( $wgContentNamespaces ) || $wgContentNamespaces === array() ) {
266 return NS_MAIN;
267 } elseif ( !in_array( NS_MAIN, $wgContentNamespaces ) ) {
268 // always force NS_MAIN to be part of array (to match the algorithm used by isContent)
269 return array_merge( array( NS_MAIN ), $wgContentNamespaces );
270 } else {
271 return $wgContentNamespaces;
272 }
273 }
274 /**
275 * Is the namespace first-letter capitalized?
276 *
277 * @param $index int Index to check
278 * @return bool
279 */
280 public static function isCapitalized( $index ) {
281 global $wgCapitalLinks, $wgCapitalLinkOverrides;
282 // Turn NS_MEDIA into NS_FILE
283 $index = $index === NS_MEDIA ? NS_FILE : $index;
284
285 // Make sure to get the subject of our namespace
286 $index = self::getSubject( $index );
287
288 // Some namespaces are special and should always be upper case
289 if ( in_array( $index, self::$alwaysCapitalizedNamespaces ) ) {
290 return true;
291 }
292 if ( isset( $wgCapitalLinkOverrides[ $index ] ) ) {
293 // $wgCapitalLinkOverrides is explicitly set
294 return $wgCapitalLinkOverrides[ $index ];
295 }
296 // Default to the global setting
297 return $wgCapitalLinks;
298 }
299
300 /**
301 * Does the namespace (potentially) have different aliases for different
302 * genders. Not all languages make a distinction here.
303 *
304 * @since 1.18
305 * @param $index int Index to check
306 * @return bool
307 */
308 public static function hasGenderDistinction( $index ) {
309 return $index == NS_USER || $index == NS_USER_TALK;
310 }
311
312 }