Index: trunk/phase3/docs/export-0.4.xsd |
— | — | @@ -10,8 +10,9 @@ |
11 | 11 | as a list of defined namespaces. |
12 | 12 | |
13 | 13 | Version 0.4 adds per-revision delete flags, log exports, |
14 | | - discussion threading data, and a per-page redirect flag. |
15 | | - |
| 14 | + discussion threading data, a per-page redirect flag, and |
| 15 | + per-namespace capitalization. |
| 16 | + |
16 | 17 | The canonical URL to the schema document is: |
17 | 18 | http://www.mediawiki.org/xml/export-0.4.xsd |
18 | 19 | |
— | — | @@ -90,6 +91,7 @@ |
91 | 92 | <simpleContent> |
92 | 93 | <extension base="string"> |
93 | 94 | <attribute name="key" type="integer" /> |
| 95 | + <attribute name="case" type="mw:CaseType" /> |
94 | 96 | </extension> |
95 | 97 | </simpleContent> |
96 | 98 | </complexType> |
Index: trunk/phase3/includes/upload/UploadBase.php |
— | — | @@ -305,10 +305,7 @@ |
306 | 306 | * but ignore things like ucfirst() and spaces/underscore things |
307 | 307 | */ |
308 | 308 | $comparableName = str_replace( ' ', '_', $this->mDesiredDestName ); |
309 | | - global $wgCapitalLinks, $wgContLang; |
310 | | - if ( $wgCapitalLinks ) { |
311 | | - $comparableName = $wgContLang->ucfirst( $comparableName ); |
312 | | - } |
| 309 | + $comparableName = Title::capitalize( $comparableName, NS_FILE ); |
313 | 310 | if( $this->mDesiredDestName != $filename && $comparableName != $filename ) |
314 | 311 | $warnings['badfilename'] = $filename; |
315 | 312 | |
Index: trunk/phase3/includes/filerepo/FileRepo.php |
— | — | @@ -28,7 +28,7 @@ |
29 | 29 | $this->name = $info['name']; |
30 | 30 | |
31 | 31 | // Optional settings |
32 | | - $this->initialCapital = true; // by default |
| 32 | + $this->initialCapital = MWNamespace::isCapitalized( NS_FILE ); |
33 | 33 | foreach ( array( 'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription', |
34 | 34 | 'thumbScriptUrl', 'initialCapital', 'pathDisclosureProtection', |
35 | 35 | 'descriptionCacheExpiry', 'hashLevels', 'url', 'thumbUrl' ) as $var ) |
— | — | @@ -256,7 +256,7 @@ |
257 | 257 | */ |
258 | 258 | function getNameFromTitle( $title ) { |
259 | 259 | global $wgCapitalLinks; |
260 | | - if ( $this->initialCapital != $wgCapitalLinks ) { |
| 260 | + if ( $this->initialCapital != MWNamespace::isCapitalized( NS_FILE ) ) { |
261 | 261 | global $wgContLang; |
262 | 262 | $name = $title->getUserCaseDBKey(); |
263 | 263 | if ( $this->initialCapital ) { |
Index: trunk/phase3/includes/Namespace.php |
— | — | @@ -46,6 +46,13 @@ |
47 | 47 | class MWNamespace { |
48 | 48 | |
49 | 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_MEDIAWIKI ); |
| 55 | + |
| 56 | + /** |
50 | 57 | * Can pages in the given namespace be moved? |
51 | 58 | * |
52 | 59 | * @param $index Int: namespace index |
— | — | @@ -181,5 +188,30 @@ |
182 | 189 | global $wgNamespacesWithSubpages; |
183 | 190 | return !empty( $wgNamespacesWithSubpages[$index] ); |
184 | 191 | } |
185 | | - |
| 192 | + |
| 193 | + /** |
| 194 | + * Is the namespace first-letter capitalized? |
| 195 | + * |
| 196 | + * @param $index int Index to check |
| 197 | + * @return bool |
| 198 | + */ |
| 199 | + public static function isCapitalized( $index ) { |
| 200 | + global $wgCapitalLinks, $wgCapitalLinkOverrides; |
| 201 | + // Turn NS_MEDIA into NS_FILE |
| 202 | + $index = $index === NS_MEDIA ? NS_FILE : $index; |
| 203 | + |
| 204 | + // Make sure to get the subject of our namespace |
| 205 | + $index = self::getSubject( $index ); |
| 206 | + |
| 207 | + // Some namespaces are special and should always be upper case |
| 208 | + if ( in_array( $index, self::$alwaysCapitalizedNamespaces ) ) { |
| 209 | + return true; |
| 210 | + } |
| 211 | + if ( isset( $wgCapitalLinkOverrides[ $index ] ) ) { |
| 212 | + // $wgCapitalLinkOverrides is explicitly set |
| 213 | + return $wgCapitalLinkOverrides[ $index ]; |
| 214 | + } |
| 215 | + // Default to the global setting |
| 216 | + return $wgCapitalLinks; |
| 217 | + } |
186 | 218 | } |
Index: trunk/phase3/includes/api/ApiQuerySiteinfo.php |
— | — | @@ -164,7 +164,8 @@ |
165 | 165 | foreach( $wgContLang->getFormattedNamespaces() as $ns => $title ) |
166 | 166 | { |
167 | 167 | $data[$ns] = array( |
168 | | - 'id' => intval($ns) |
| 168 | + 'id' => intval($ns), |
| 169 | + 'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive', |
169 | 170 | ); |
170 | 171 | ApiResult :: setContent( $data[$ns], $title ); |
171 | 172 | $canonical = MWNamespace::getCanonicalName( $ns ); |
Index: trunk/phase3/includes/Setup.php |
— | — | @@ -8,7 +8,6 @@ |
9 | 9 | * MEDIAWIKI is defined |
10 | 10 | */ |
11 | 11 | if( !defined( 'MEDIAWIKI' ) ) { |
12 | | - echo "This file is part of MediaWiki, it is not a valid entry point.\n"; |
13 | 12 | exit( 1 ); |
14 | 13 | } |
15 | 14 | |
— | — | @@ -87,7 +86,6 @@ |
88 | 87 | 'hashLevels' => $wgHashedUploadDirectory ? 2 : 0, |
89 | 88 | 'thumbScriptUrl' => $wgThumbnailScriptPath, |
90 | 89 | 'transformVia404' => !$wgGenerateThumbnailOnParse, |
91 | | - 'initialCapital' => $wgCapitalLinks, |
92 | 90 | 'deletedDir' => $wgFileStore['deleted']['directory'], |
93 | 91 | 'deletedHashLevels' => $wgFileStore['deleted']['hash'] |
94 | 92 | ); |
Index: trunk/phase3/includes/specials/SpecialCategories.php |
— | — | @@ -36,10 +36,7 @@ |
37 | 37 | parent::__construct(); |
38 | 38 | $from = str_replace( ' ', '_', $from ); |
39 | 39 | if( $from !== '' ) { |
40 | | - global $wgCapitalLinks, $wgContLang; |
41 | | - if( $wgCapitalLinks ) { |
42 | | - $from = $wgContLang->ucfirst( $from ); |
43 | | - } |
| 40 | + $from = Title::capitalize( $from, NS_CATEGORY ); |
44 | 41 | $this->mOffset = $from; |
45 | 42 | } |
46 | 43 | } |
Index: trunk/phase3/includes/specials/SpecialWithoutinterwiki.php |
— | — | @@ -75,13 +75,10 @@ |
76 | 76 | } |
77 | 77 | |
78 | 78 | function wfSpecialWithoutinterwiki() { |
79 | | - global $wgRequest, $wgContLang, $wgCapitalLinks; |
| 79 | + global $wgRequest, $wgContLang; |
80 | 80 | list( $limit, $offset ) = wfCheckLimits(); |
81 | | - if( $wgCapitalLinks ) { |
82 | | - $prefix = $wgContLang->ucfirst( $wgRequest->getVal( 'prefix' ) ); |
83 | | - } else { |
84 | | - $prefix = $wgRequest->getVal( 'prefix' ); |
85 | | - } |
| 81 | + // Only searching the mainspace anyway |
| 82 | + $prefix = Title::capitalize( $wgRequest->getVal( 'prefix' ), NS_MAIN ); |
86 | 83 | $wip = new WithoutInterwikiPage(); |
87 | 84 | $wip->setPrefix( $prefix ); |
88 | 85 | $wip->doQuery( $offset, $limit ); |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -213,10 +213,10 @@ |
214 | 214 | * thumbScriptUrl The URL for thumb.php (optional, not recommended) |
215 | 215 | * transformVia404 Whether to skip media file transformation on parse and rely on a 404 |
216 | 216 | * handler instead. |
217 | | - * initialCapital Equivalent to $wgCapitalLinks, determines whether filenames implicitly |
218 | | - * start with a capital letter. The current implementation may give incorrect |
219 | | - * description page links when the local $wgCapitalLinks and initialCapital |
220 | | - * are mismatched. |
| 217 | + * initialCapital Equivalent to $wgCapitalLinks (or $wgCapitalLinkOverrides[NS_FILE], |
| 218 | + * determines whether filenames implicitly start with a capital letter. |
| 219 | + * The current implementation may give incorrect description page links |
| 220 | + * when the local $wgCapitalLinks and initialCapital are mismatched. |
221 | 221 | * pathDisclosureProtection |
222 | 222 | * May be 'paranoid' to remove all parameters from error messages, 'none' to |
223 | 223 | * leave the paths in unchanged, or 'simple' to replace paths with |
— | — | @@ -2437,6 +2437,18 @@ |
2438 | 2438 | $wgCapitalLinks = true; |
2439 | 2439 | |
2440 | 2440 | /** |
| 2441 | + * @since 1.16 - This can now be set per-namespace. Some special namespaces (such |
| 2442 | + * as Special, see Namespace::$alwaysCapitalizedNamespaces for the full list) must be |
| 2443 | + * true by default (and setting them has no effect), due to various things that |
| 2444 | + * require them to be so. Also, since Talk namespaces need to directly mirror their |
| 2445 | + * associated content namespaces, the values for those are ignored in favor of the |
| 2446 | + * subject namespace's setting. Setting for NS_MEDIA is taken automatically from |
| 2447 | + * NS_FILE. |
| 2448 | + * EX: $wgCapitalLinkOverrides[ NS_FILE ] = false; |
| 2449 | + */ |
| 2450 | +$wgCapitalLinkOverrides = array(); |
| 2451 | + |
| 2452 | +/** |
2441 | 2453 | * List of interwiki prefixes for wikis we'll accept as sources for |
2442 | 2454 | * Special:Import (for sysops). Since complete page history can be imported, |
2443 | 2455 | * these should be 'trusted'. |
— | — | @@ -3448,7 +3460,7 @@ |
3449 | 3461 | * 'Main_Page' => 'noindex,follow', |
3450 | 3462 | * # "Project", not the actual project name! |
3451 | 3463 | * 'Project:X' => 'index,follow', |
3452 | | - * # Needs to be "Abc", not "abc" (unless $wgCapitalLinks is false)! |
| 3464 | + * # Needs to be "Abc", not "abc" (unless $wgCapitalLinks is false for that namespace)! |
3453 | 3465 | * 'abc' => 'noindex,nofollow' |
3454 | 3466 | * ); |
3455 | 3467 | */ |
Index: trunk/phase3/includes/Title.php |
— | — | @@ -2229,6 +2229,18 @@ |
2230 | 2230 | |
2231 | 2231 | return $rxTc; |
2232 | 2232 | } |
| 2233 | + |
| 2234 | + /** |
| 2235 | + * Capitalize a text if it belongs to a namespace that capitalizes |
| 2236 | + */ |
| 2237 | + public static function capitalize( $text, $ns = NS_MAIN ) { |
| 2238 | + global $wgContLang; |
| 2239 | + |
| 2240 | + if ( MWNamespace::isCapitalized( $ns ) ) |
| 2241 | + return $wgContLang->ucfirst( $text ); |
| 2242 | + else |
| 2243 | + return $text; |
| 2244 | + } |
2233 | 2245 | |
2234 | 2246 | /** |
2235 | 2247 | * Secure and split - main initialisation function for this object |
— | — | @@ -2241,7 +2253,7 @@ |
2242 | 2254 | * @return \type{\bool} true on success |
2243 | 2255 | */ |
2244 | 2256 | private function secureAndSplit() { |
2245 | | - global $wgContLang, $wgLocalInterwiki, $wgCapitalLinks; |
| 2257 | + global $wgContLang, $wgLocalInterwiki; |
2246 | 2258 | |
2247 | 2259 | # Initialisation |
2248 | 2260 | $rxTc = self::getTitleInvalidRegex(); |
— | — | @@ -2403,8 +2415,8 @@ |
2404 | 2416 | * site might be case-sensitive. |
2405 | 2417 | */ |
2406 | 2418 | $this->mUserCaseDBKey = $dbkey; |
2407 | | - if( $wgCapitalLinks && $this->mInterwiki == '') { |
2408 | | - $dbkey = $wgContLang->ucfirst( $dbkey ); |
| 2419 | + if( $this->mInterwiki == '') { |
| 2420 | + $dbkey = self::capitalize( $dbkey, $this->mNamespace ); |
2409 | 2421 | } |
2410 | 2422 | |
2411 | 2423 | /** |
Index: trunk/phase3/includes/User.php |
— | — | @@ -521,7 +521,7 @@ |
522 | 522 | || User::isIP( $name ) |
523 | 523 | || strpos( $name, '/' ) !== false |
524 | 524 | || strlen( $name ) > $wgMaxNameChars |
525 | | - || $name != $wgContLang->ucfirst( $name ) ) { |
| 525 | + || $name != Title::capitalize( $name, NS_USER ) ) { |
526 | 526 | wfDebugLog( 'username', __METHOD__ . |
527 | 527 | ": '$name' invalid due to empty, IP, slash, length, or lowercase" ); |
528 | 528 | return false; |
— | — | @@ -669,9 +669,8 @@ |
670 | 670 | * - 'creatable' Valid for batch processes, login and account creation |
671 | 671 | */ |
672 | 672 | static function getCanonicalName( $name, $validate = 'valid' ) { |
673 | | - # Force usernames to capital |
674 | | - global $wgContLang; |
675 | | - $name = $wgContLang->ucfirst( $name ); |
| 673 | + # Maybe force usernames to capital |
| 674 | + $name = Title::capitalize( $name, NS_USER ); |
676 | 675 | |
677 | 676 | # Reject names containing '#'; these will be cleaned up |
678 | 677 | # with title normalisation, but then it's too late to |
Index: trunk/phase3/includes/Export.php |
— | — | @@ -414,7 +414,11 @@ |
415 | 415 | global $wgContLang; |
416 | 416 | $spaces = "<namespaces>\n"; |
417 | 417 | foreach( $wgContLang->getFormattedNamespaces() as $ns => $title ) { |
418 | | - $spaces .= ' ' . Xml::element( 'namespace', array( 'key' => $ns ), $title ) . "\n"; |
| 418 | + $spaces .= ' ' . |
| 419 | + Xml::element( 'namespace', |
| 420 | + array( 'key' => $ns, |
| 421 | + 'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive', |
| 422 | + ), $title ) . "\n"; |
419 | 423 | } |
420 | 424 | $spaces .= " </namespaces>"; |
421 | 425 | return $spaces; |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -89,6 +89,7 @@ |
90 | 90 | maintenance |
91 | 91 | * New hook AbortNewAccountAuto, called before account creation from AuthPlugin- |
92 | 92 | or ExtUser-driven requests. |
| 93 | +* $wgCapitalLinkOverrides added to configure per-namespace capitalization |
93 | 94 | |
94 | 95 | === New features in 1.16 === |
95 | 96 | |
— | — | @@ -241,8 +242,8 @@ |
242 | 243 | called after a user's email has been successfully confirmed or invalidated. |
243 | 244 | * (bug 19741) Moved the XCF files out of the main MediaWiki distribution, for |
244 | 245 | a smaller subversion checkout. |
| 246 | +* (bug 13750) First letter capitalization can now be a per-namespace setting |
245 | 247 | |
246 | | - |
247 | 248 | === Bug fixes in 1.16 === |
248 | 249 | |
249 | 250 | * (bug 18031) Make namespace selector on Special:Export remember the previous |