Normalize input to TitleParser::parseTitle()
[lhc/web/wiklou.git] / includes / title / MediaWikiTitleCodec.php
index 15f8ff0..b2c8521 100644 (file)
@@ -79,7 +79,7 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
         * @param string $text
         *
         * @throws InvalidArgumentException If the namespace is invalid
-        * @return string
+        * @return string Namespace name with underscores (not spaces)
         */
        public function getNamespaceName( $namespace, $text ) {
                if ( $this->language->needsGenderDistinction() &&
@@ -112,29 +112,30 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
         * @return string
         */
        public function formatTitle( $namespace, $text, $fragment = '', $interwiki = '' ) {
-               if ( $namespace !== 0 && $namespace !== false ) {
-                       // Try to get a namespace name, but fallback
-                       // to empty string if it doesn't exist. And
-                       // assume that ns 0 is the empty string.
+               $out = '';
+               if ( $interwiki !== '' ) {
+                       $out = $interwiki . ':';
+               }
+
+               if ( $namespace != 0 ) {
                        try {
                                $nsName = $this->getNamespaceName( $namespace, $text );
                        } catch ( InvalidArgumentException $e ) {
-                               $nsName = '';
+                               // See T165149. Awkward, but better than erroneously linking to the main namespace.
+                               $nsName = $this->language->getNsText( NS_SPECIAL ) . ":Badtitle/NS{$namespace}";
                        }
-                       $text = $nsName . ':' . $text;
-               }
 
-               if ( $fragment !== '' ) {
-                       $text = $text . '#' . $fragment;
+                       $out .= $nsName . ':';
                }
+               $out .= $text;
 
-               if ( $interwiki !== '' ) {
-                       $text = $interwiki . ':' . $text;
+               if ( $fragment !== '' ) {
+                       $out .= '#' . $fragment;
                }
 
-               $text = str_replace( '_', ' ', $text );
+               $out = str_replace( '_', ' ', $out );
 
-               return $text;
+               return $out;
        }
 
        /**
@@ -148,10 +149,13 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
         * @return TitleValue
         */
        public function parseTitle( $text, $defaultNamespace = NS_MAIN ) {
+               // Convert things like é ā or 〗 into normalized (T16952) text
+               $filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text );
+
                // NOTE: this is an ugly cludge that allows this class to share the
                // code for parsing with the old Title class. The parser code should
                // be refactored to avoid this.
-               $parts = $this->splitTitleString( $text, $defaultNamespace );
+               $parts = $this->splitTitleString( $filteredText, $defaultNamespace );
 
                // Relative fragment links are not supported by TitleValue
                if ( $parts['dbkey'] === '' ) {
@@ -185,12 +189,16 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
         * @return string
         */
        public function getPrefixedText( LinkTarget $title ) {
-               return $this->formatTitle(
-                       $title->getNamespace(),
-                       $title->getText(),
-                       '',
-                       $title->getInterwiki()
-               );
+               if ( !isset( $title->prefixedText ) ) {
+                       $title->prefixedText = $this->formatTitle(
+                               $title->getNamespace(),
+                               $title->getText(),
+                               '',
+                               $title->getInterwiki()
+                       );
+               }
+
+               return $title->prefixedText;
        }
 
        /**
@@ -200,28 +208,12 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
         * @return string
         */
        public function getPrefixedDBkey( LinkTarget $target ) {
-               $key = '';
-               if ( $target->isExternal() ) {
-                       $key .= $target->getInterwiki() . ':';
-               }
-               // Try to get a namespace name, but fallback
-               // to empty string if it doesn't exist
-               try {
-                       $nsName = $this->getNamespaceName(
-                               $target->getNamespace(),
-                               $target->getText()
-                       );
-               } catch ( InvalidArgumentException $e ) {
-                       $nsName = '';
-               }
-
-               if ( $target->getNamespace() !== 0 ) {
-                       $key .= $nsName . ':';
-               }
-
-               $key .= $target->getText();
-
-               return strtr( $key, ' ', '_' );
+               return strtr( $this->formatTitle(
+                       $target->getNamespace(),
+                       $target->getDBkey(),
+                       '',
+                       $target->getInterwiki()
+               ), ' ', '_' );
        }
 
        /**
@@ -336,7 +328,7 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
 
                                        # Redundant interwiki prefix to the local wiki
                                        foreach ( $this->localInterwikis as $localIW ) {
-                                               if ( 0 == strcasecmp( $parts['interwiki'], $localIW ) ) {
+                                               if ( strcasecmp( $parts['interwiki'], $localIW ) == 0 ) {
                                                        if ( $dbkey == '' ) {
                                                                # Empty self-links should point to the Main Page, to ensure
                                                                # compatibility with cross-wiki transclusions and the like.
@@ -374,7 +366,7 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
                } while ( true );
 
                $fragment = strstr( $dbkey, '#' );
-               if ( false !== $fragment ) {
+               if ( $fragment !== false ) {
                        $parts['fragment'] = str_replace( '_', ' ', substr( $fragment, 1 ) );
                        $dbkey = substr( $dbkey, 0, strlen( $dbkey ) - strlen( $fragment ) );
                        # remove whitespace again: prevents "Foo_bar_#"
@@ -432,10 +424,8 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
 
                # Can't make a link to a namespace alone... "empty" local links can only be
                # self-links with a fragment identifier.
-               if ( $dbkey == '' && $parts['interwiki'] === '' ) {
-                       if ( $parts['namespace'] != NS_MAIN ) {
-                               throw new MalformedTitleException( 'title-invalid-empty', $text );
-                       }
+               if ( $dbkey == '' && $parts['interwiki'] === '' && $parts['namespace'] != NS_MAIN ) {
+                       throw new MalformedTitleException( 'title-invalid-empty', $text );
                }
 
                // Allow IPv6 usernames to start with '::' by canonicalizing IPv6 titles.
@@ -449,7 +439,7 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
                }
 
                // Any remaining initial :s are illegal.
-               if ( $dbkey !== '' && ':' == $dbkey[0] ) {
+               if ( $dbkey !== '' && $dbkey[0] == ':' ) {
                        throw new MalformedTitleException( 'title-invalid-leading-colon', $text );
                }