TitleFormatter: Implement fbc144965315 and unify prefix logic
authorKunal Mehta <legoktm@member.fsf.org>
Sat, 18 Aug 2018 00:09:26 +0000 (17:09 -0700)
committerKunal Mehta <legoktm@member.fsf.org>
Sat, 18 Aug 2018 00:43:52 +0000 (17:43 -0700)
fbc144965315 (Make Titles with an unknown namespace ID refer to
Special:Badtitle.) was never implemented in TitleFormatter, so let's do
that.

While we're at it, formatTitle() is now structured in the same format as
Title::prefix(), to make it easier to compare code between the two
implementations. The existing tests verify that this is a no-op. There's
a little extra indirection in getPrefixedDBkey(), which now goes through
dbkeyform -> textform -> dbkeyform, but reduces duplication of code,
which I think is worth it.

Bug: T165149
Change-Id: I4e43487a52663d2a647f9e71d487f58e25474f7a

includes/title/MediaWikiTitleCodec.php
tests/phpunit/includes/title/MediaWikiTitleCodecTest.php

index 15f8ff0..3c14317 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;
        }
 
        /**
@@ -200,28 +201,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()
+               ), ' ', '_' );
        }
 
        /**
index e1b98ec..20f0039 100644 (file)
@@ -164,7 +164,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                        // getGenderCache() provides a mock that considers first
                        // names ending in "a" to be female.
                        [ NS_USER, 'Lisa_Müller', '', 'de', 'Benutzerin:Lisa Müller' ],
-                       [ 1000000, 'Invalid_namespace', '', 'en', ':Invalid namespace' ],
+                       [ 1000000, 'Invalid_namespace', '', 'en', 'Special:Badtitle/NS1000000:Invalid namespace' ],
                ];
        }
 
@@ -195,7 +195,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                        [ NS_MAIN, 'Remote_page', '', 'remotetestiw', 'en', 'remotetestiw:Remote_page' ],
 
                        // non-existent namespace
-                       [ 10000000, 'Foobar', '', '', 'en', ':Foobar' ],
+                       [ 10000000, 'Foobar', '', '', 'en', 'Special:Badtitle/NS10000000:Foobar' ],
                ];
        }