maintenance
* New hook AbortNewAccountAuto, called before account creation from AuthPlugin-
or ExtUser-driven requests.
+* $wgCapitalLinkOverrides added to configure per-namespace capitalization
=== New features in 1.16 ===
called after a user's email has been successfully confirmed or invalidated.
* (bug 19741) Moved the XCF files out of the main MediaWiki distribution, for
a smaller subversion checkout.
-
+* (bug 13750) First letter capitalization can now be a per-namespace setting
=== Bug fixes in 1.16 ===
as a list of defined namespaces.
Version 0.4 adds per-revision delete flags, log exports,
- discussion threading data, and a per-page redirect flag.
-
+ discussion threading data, a per-page redirect flag, and
+ per-namespace capitalization.
+
The canonical URL to the schema document is:
http://www.mediawiki.org/xml/export-0.4.xsd
<simpleContent>
<extension base="string">
<attribute name="key" type="integer" />
+ <attribute name="case" type="mw:CaseType" />
</extension>
</simpleContent>
</complexType>
* thumbScriptUrl The URL for thumb.php (optional, not recommended)
* transformVia404 Whether to skip media file transformation on parse and rely on a 404
* handler instead.
- * initialCapital Equivalent to $wgCapitalLinks, determines whether filenames implicitly
- * start with a capital letter. The current implementation may give incorrect
- * description page links when the local $wgCapitalLinks and initialCapital
- * are mismatched.
+ * initialCapital Equivalent to $wgCapitalLinks (or $wgCapitalLinkOverrides[NS_FILE],
+ * determines whether filenames implicitly start with a capital letter.
+ * The current implementation may give incorrect description page links
+ * when the local $wgCapitalLinks and initialCapital are mismatched.
* pathDisclosureProtection
* May be 'paranoid' to remove all parameters from error messages, 'none' to
* leave the paths in unchanged, or 'simple' to replace paths with
*/
$wgCapitalLinks = true;
+/**
+ * @since 1.16 - This can now be set per-namespace. Some special namespaces (such
+ * as Special, see Namespace::$alwaysCapitalizedNamespaces for the full list) must be
+ * true by default (and setting them has no effect), due to various things that
+ * require them to be so. Also, since Talk namespaces need to directly mirror their
+ * associated content namespaces, the values for those are ignored in favor of the
+ * subject namespace's setting. Setting for NS_MEDIA is taken automatically from
+ * NS_FILE.
+ * EX: $wgCapitalLinkOverrides[ NS_FILE ] = false;
+ */
+$wgCapitalLinkOverrides = array();
+
/**
* List of interwiki prefixes for wikis we'll accept as sources for
* Special:Import (for sysops). Since complete page history can be imported,
* 'Main_Page' => 'noindex,follow',
* # "Project", not the actual project name!
* 'Project:X' => 'index,follow',
- * # Needs to be "Abc", not "abc" (unless $wgCapitalLinks is false)!
+ * # Needs to be "Abc", not "abc" (unless $wgCapitalLinks is false for that namespace)!
* 'abc' => 'noindex,nofollow'
* );
*/
global $wgContLang;
$spaces = "<namespaces>\n";
foreach( $wgContLang->getFormattedNamespaces() as $ns => $title ) {
- $spaces .= ' ' . Xml::element( 'namespace', array( 'key' => $ns ), $title ) . "\n";
+ $spaces .= ' ' .
+ Xml::element( 'namespace',
+ array( 'key' => $ns,
+ 'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive',
+ ), $title ) . "\n";
}
$spaces .= " </namespaces>";
return $spaces;
class MWNamespace {
+ /**
+ * These namespaces should always be first-letter capitalized, now and
+ * forevermore. Historically, they could've probably been lowercased too,
+ * but some things are just too ingrained now. :)
+ */
+ private static $alwaysCapitalizedNamespaces = array( NS_SPECIAL, NS_MEDIAWIKI );
+
/**
* Can pages in the given namespace be moved?
*
global $wgNamespacesWithSubpages;
return !empty( $wgNamespacesWithSubpages[$index] );
}
-
+
+ /**
+ * Is the namespace first-letter capitalized?
+ *
+ * @param $index int Index to check
+ * @return bool
+ */
+ public static function isCapitalized( $index ) {
+ global $wgCapitalLinks, $wgCapitalLinkOverrides;
+ // Turn NS_MEDIA into NS_FILE
+ $index = $index === NS_MEDIA ? NS_FILE : $index;
+
+ // Make sure to get the subject of our namespace
+ $index = self::getSubject( $index );
+
+ // Some namespaces are special and should always be upper case
+ if ( in_array( $index, self::$alwaysCapitalizedNamespaces ) ) {
+ return true;
+ }
+ if ( isset( $wgCapitalLinkOverrides[ $index ] ) ) {
+ // $wgCapitalLinkOverrides is explicitly set
+ return $wgCapitalLinkOverrides[ $index ];
+ }
+ // Default to the global setting
+ return $wgCapitalLinks;
+ }
}
* MEDIAWIKI is defined
*/
if( !defined( 'MEDIAWIKI' ) ) {
- echo "This file is part of MediaWiki, it is not a valid entry point.\n";
exit( 1 );
}
'hashLevels' => $wgHashedUploadDirectory ? 2 : 0,
'thumbScriptUrl' => $wgThumbnailScriptPath,
'transformVia404' => !$wgGenerateThumbnailOnParse,
- 'initialCapital' => $wgCapitalLinks,
'deletedDir' => $wgFileStore['deleted']['directory'],
'deletedHashLevels' => $wgFileStore['deleted']['hash']
);
return $rxTc;
}
+
+ /**
+ * Capitalize a text if it belongs to a namespace that capitalizes
+ */
+ public static function capitalize( $text, $ns = NS_MAIN ) {
+ global $wgContLang;
+
+ if ( MWNamespace::isCapitalized( $ns ) )
+ return $wgContLang->ucfirst( $text );
+ else
+ return $text;
+ }
/**
* Secure and split - main initialisation function for this object
* @return \type{\bool} true on success
*/
private function secureAndSplit() {
- global $wgContLang, $wgLocalInterwiki, $wgCapitalLinks;
+ global $wgContLang, $wgLocalInterwiki;
# Initialisation
$rxTc = self::getTitleInvalidRegex();
* site might be case-sensitive.
*/
$this->mUserCaseDBKey = $dbkey;
- if( $wgCapitalLinks && $this->mInterwiki == '') {
- $dbkey = $wgContLang->ucfirst( $dbkey );
+ if( $this->mInterwiki == '') {
+ $dbkey = self::capitalize( $dbkey, $this->mNamespace );
}
/**
|| User::isIP( $name )
|| strpos( $name, '/' ) !== false
|| strlen( $name ) > $wgMaxNameChars
- || $name != $wgContLang->ucfirst( $name ) ) {
+ || $name != Title::capitalize( $name, NS_USER ) ) {
wfDebugLog( 'username', __METHOD__ .
": '$name' invalid due to empty, IP, slash, length, or lowercase" );
return false;
* - 'creatable' Valid for batch processes, login and account creation
*/
static function getCanonicalName( $name, $validate = 'valid' ) {
- # Force usernames to capital
- global $wgContLang;
- $name = $wgContLang->ucfirst( $name );
+ # Maybe force usernames to capital
+ $name = Title::capitalize( $name, NS_USER );
# Reject names containing '#'; these will be cleaned up
# with title normalisation, but then it's too late to
foreach( $wgContLang->getFormattedNamespaces() as $ns => $title )
{
$data[$ns] = array(
- 'id' => intval($ns)
+ 'id' => intval($ns),
+ 'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive',
);
ApiResult :: setContent( $data[$ns], $title );
$canonical = MWNamespace::getCanonicalName( $ns );
$this->name = $info['name'];
// Optional settings
- $this->initialCapital = true; // by default
+ $this->initialCapital = MWNamespace::isCapitalized( NS_FILE );
foreach ( array( 'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription',
'thumbScriptUrl', 'initialCapital', 'pathDisclosureProtection',
'descriptionCacheExpiry', 'hashLevels', 'url', 'thumbUrl' ) as $var )
*/
function getNameFromTitle( $title ) {
global $wgCapitalLinks;
- if ( $this->initialCapital != $wgCapitalLinks ) {
+ if ( $this->initialCapital != MWNamespace::isCapitalized( NS_FILE ) ) {
global $wgContLang;
$name = $title->getUserCaseDBKey();
if ( $this->initialCapital ) {
parent::__construct();
$from = str_replace( ' ', '_', $from );
if( $from !== '' ) {
- global $wgCapitalLinks, $wgContLang;
- if( $wgCapitalLinks ) {
- $from = $wgContLang->ucfirst( $from );
- }
+ $from = Title::capitalize( $from, NS_CATEGORY );
$this->mOffset = $from;
}
}
}
function wfSpecialWithoutinterwiki() {
- global $wgRequest, $wgContLang, $wgCapitalLinks;
+ global $wgRequest, $wgContLang;
list( $limit, $offset ) = wfCheckLimits();
- if( $wgCapitalLinks ) {
- $prefix = $wgContLang->ucfirst( $wgRequest->getVal( 'prefix' ) );
- } else {
- $prefix = $wgRequest->getVal( 'prefix' );
- }
+ // Only searching the mainspace anyway
+ $prefix = Title::capitalize( $wgRequest->getVal( 'prefix' ), NS_MAIN );
$wip = new WithoutInterwikiPage();
$wip->setPrefix( $prefix );
$wip->doQuery( $offset, $limit );
* but ignore things like ucfirst() and spaces/underscore things
*/
$comparableName = str_replace( ' ', '_', $this->mDesiredDestName );
- global $wgCapitalLinks, $wgContLang;
- if ( $wgCapitalLinks ) {
- $comparableName = $wgContLang->ucfirst( $comparableName );
- }
+ $comparableName = Title::capitalize( $comparableName, NS_FILE );
if( $this->mDesiredDestName != $filename && $comparableName != $filename )
$warnings['badfilename'] = $filename;