Hygiene: Use strtr() instead of str_replace() for character swapping
authorTimo Tijhof <krinklemail@gmail.com>
Mon, 6 Jul 2015 09:17:47 +0000 (10:17 +0100)
committerKrinkle <krinklemail@gmail.com>
Mon, 6 Jul 2015 20:25:19 +0000 (20:25 +0000)
strtr() is marginally faster as it runs through the string only
once. A better fit for one-for-one character translation.

The strtr() function also supports an associative array as second
parameter for entire string replacements. This, too, has the same
performance and predictable behaviour (starts with the longest key).
Whereas str_replace is for more aggressive needs where you want
multiple passes until there are no further matches.

The associative array form is arguably also easier to understand
and harder to mess up since the needle/replacement pairs are
explicitly connected instead of two separate arrays.

Also:
* Use getFormattedNsText instead of strtr( getNsText, .. ) which
  reduces duplication of this fact through a more semantic intent.

Change-Id: Ie23e4210a5b6908dd79eebc8a2b931d12fe31af6

includes/Export.php
includes/GlobalFunctions.php
includes/Linker.php
includes/Title.php
includes/api/ApiQueryAllUsers.php
includes/cache/LinkBatch.php
includes/filerepo/LocalRepo.php
includes/resourceloader/ResourceLoaderModule.php
languages/Language.php

index 0d55d7d..adab21c 100644 (file)
@@ -874,7 +874,7 @@ class XmlDumpWriter {
                }
 
                global $wgContLang;
-               $prefix = str_replace( '_', ' ', $wgContLang->getNsText( $title->getNamespace() ) );
+               $prefix = $wgContLang->getFormattedNsText( $title->getNamespace() );
 
                if ( $prefix !== '' ) {
                        $prefix .= ':';
index 97042fd..3014070 100644 (file)
@@ -3505,8 +3505,7 @@ function wfMemcKey( /*...*/ ) {
        $prefix = $wgCachePrefix === false ? wfWikiID() : $wgCachePrefix;
        $args = func_get_args();
        $key = $prefix . ':' . implode( ':', $args );
-       $key = str_replace( ' ', '_', $key );
-       return $key;
+       return strtr( $key, ' ', '_' );
 }
 
 /**
@@ -3527,7 +3526,7 @@ function wfForeignMemcKey( $db, $prefix /*...*/ ) {
        } else {
                $key = $db . ':' . implode( ':', $args );
        }
-       return str_replace( ' ', '_', $key );
+       return strtr( $key, ' ', '_' );
 }
 
 /**
@@ -3544,8 +3543,7 @@ function wfForeignMemcKey( $db, $prefix /*...*/ ) {
 function wfGlobalCacheKey( /*...*/ ) {
        $args = func_get_args();
        $key = 'global:' . implode( ':', $args );
-       $key = str_replace( ' ', '_', $key );
-       return $key;
+       return strtr( $key, ' ', '_' );
 }
 
 /**
index 4a1aa87..bb65cdf 100644 (file)
@@ -77,7 +77,7 @@ class Linker {
                wfDeprecated( __METHOD__, '1.25' );
 
                $title = urldecode( $title );
-               $title = str_replace( '_', ' ', $title );
+               $title = strtr( $title, '_', ' ' );
                return self::getLinkAttributesInternal( $title, $class );
        }
 
@@ -1414,10 +1414,9 @@ class Linker {
 
                                # fix up urlencoded title texts (copied from Parser::replaceInternalLinks)
                                if ( strpos( $match[1], '%' ) !== false ) {
-                                       $match[1] = str_replace(
-                                               array( '<', '>' ),
-                                               array( '&lt;', '&gt;' ),
-                                               rawurldecode( $match[1] )
+                                       $match[1] = strtr(
+                                               rawurldecode( $match[1] ),
+                                               array( '<' => '&lt;', '>' => '&gt;' )
                                        );
                                }
 
index 9c8ed47..1ab88a6 100644 (file)
@@ -313,7 +313,7 @@ class Title {
                $filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text );
 
                $t = new Title();
-               $t->mDbkeyform = str_replace( ' ', '_', $filteredText );
+               $t->mDbkeyform = strtr( $filteredText, ' ', '_' );
                $t->mDefaultNamespace = intval( $defaultNamespace );
 
                $t->secureAndSplit();
@@ -345,10 +345,10 @@ class Title {
                # but some URLs used it as a space replacement and they still come
                # from some external search tools.
                if ( strpos( self::legalChars(), '+' ) === false ) {
-                       $url = str_replace( '+', ' ', $url );
+                       $url = strtr( $url, '+', ' ' );
                }
 
-               $t->mDbkeyform = str_replace( ' ', '_', $url );
+               $t->mDbkeyform = strtr( $url, ' ', '_' );
 
                try {
                        $t->secureAndSplit();
@@ -509,10 +509,10 @@ class Title {
                $t->mInterwiki = $interwiki;
                $t->mFragment = $fragment;
                $t->mNamespace = $ns = intval( $ns );
-               $t->mDbkeyform = str_replace( ' ', '_', $title );
+               $t->mDbkeyform = strtr( $title, ' ', '_' );
                $t->mArticleID = ( $ns >= 0 ) ? -1 : 0;
                $t->mUrlform = wfUrlencode( $t->mDbkeyform );
-               $t->mTextform = str_replace( '_', ' ', $title );
+               $t->mTextform = strtr( $title, '_', ' ' );
                $t->mContentModel = false; # initialized lazily in getContentModel()
                return $t;
        }
@@ -1419,7 +1419,7 @@ class Title {
         * @param string $fragment Text
         */
        public function setFragment( $fragment ) {
-               $this->mFragment = str_replace( '_', ' ', substr( $fragment, 1 ) );
+               $this->mFragment = strtr( substr( $fragment, 1 ), '_', ' ' );
        }
 
        /**
@@ -1449,7 +1449,7 @@ class Title {
         */
        public function getPrefixedDBkey() {
                $s = $this->prefix( $this->mDbkeyform );
-               $s = str_replace( ' ', '_', $s );
+               $s = strtr( $s, ' ', '_' );
                return $s;
        }
 
@@ -1462,7 +1462,7 @@ class Title {
        public function getPrefixedText() {
                if ( $this->mPrefixedText === null ) {
                        $s = $this->prefix( $this->mTextform );
-                       $s = str_replace( '_', ' ', $s );
+                       $s = strtr( $s, '_', ' ' );
                        $this->mPrefixedText = $s;
                }
                return $this->mPrefixedText;
@@ -1610,7 +1610,7 @@ class Title {
         */
        public function getSubpageUrlForm() {
                $text = $this->getSubpageText();
-               $text = wfUrlencode( str_replace( ' ', '_', $text ) );
+               $text = wfUrlencode( strtr( $text, ' ', '_' ) );
                return $text;
        }
 
@@ -1621,7 +1621,7 @@ class Title {
         */
        public function getPrefixedURL() {
                $s = $this->prefix( $this->mDbkeyform );
-               $s = wfUrlencode( str_replace( ' ', '_', $s ) );
+               $s = wfUrlencode( strtr( $s, ' ', '_' ) );
                return $s;
        }
 
@@ -3370,7 +3370,7 @@ class Title {
 
                $this->mDbkeyform = $parts['dbkey'];
                $this->mUrlform = wfUrlencode( $this->mDbkeyform );
-               $this->mTextform = str_replace( '_', ' ', $this->mDbkeyform );
+               $this->mTextform = strtr( $this->mDbkeyform, '_', ' ' );
 
                # We already know that some pages won't be in the database!
                if ( $this->isExternal() || $this->mNamespace == NS_SPECIAL ) {
@@ -4738,7 +4738,7 @@ class Title {
                        }
                } else {
                        // Even if there are no subpages in namespace, we still don't want "/" in MediaWiki message keys
-                       $editnoticeText = $editnotice_ns . '-' . str_replace( '/', '-', $this->getDBkey() );
+                       $editnoticeText = $editnotice_ns . '-' . strtr( $this->getDBkey(), '/', '-' );
                        $msg = wfMessage( $editnoticeText );
                        if ( $msg->exists() ) {
                                $html = $msg->parseAsBlock();
index 05daa7a..b52b1c6 100644 (file)
@@ -41,7 +41,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
         * @return string
         */
        private function getCanonicalUserName( $name ) {
-               return str_replace( '_', ' ', $name );
+               return strtr( $name, '_', ' ' );
        }
 
        public function execute() {
index 77e4d49..698b304 100644 (file)
@@ -78,7 +78,7 @@ class LinkBatch {
                        $this->data[$ns] = array();
                }
 
-               $this->data[$ns][str_replace( ' ', '_', $dbkey )] = 1;
+               $this->data[$ns][strtr( $dbkey, ' ', '_' )] = 1;
        }
 
        /**
index ef402ea..800a230 100644 (file)
@@ -285,7 +285,7 @@ class LocalRepo extends FileRepo {
                                $file = $that->newFileFromRow( $row );
                                // There must have been a search for this DB key, but this has to handle the
                                // cases were title capitalization is different on the client and repo wikis.
-                               $dbKeysLook = array( str_replace( ' ', '_', $file->getName() ) );
+                               $dbKeysLook = array( strtr( $file->getName(), ' ', '_' ) );
                                if ( !empty( $info['initialCapital'] ) ) {
                                        // Search keys for "hi.png" and "Hi.png" should use the "Hi.png file"
                                        $dbKeysLook[] = $wgContLang->lcfirst( $file->getName() );
index 94edb36..46b786d 100644 (file)
@@ -571,7 +571,7 @@ abstract class ResourceLoaderModule {
                }
 
                $statTiming = microtime( true ) - $statStart;
-               $statName = str_replace( '.', '_', $this->getName() );
+               $statName = strtr( $this->getName(), '.', '_' );
                $stats->timing( "resourceloader_build.all", $statTiming );
                $stats->timing( "resourceloader_build.$statName", $statTiming );
 
index b1d88bc..fdffbec 100644 (file)
@@ -525,10 +525,8 @@ class Language {
        }
 
        /**
-        * A convenience function that returns the same thing as
-        * getNamespaces() except with the array values changed to ' '
-        * where it found '_', useful for producing output to be displayed
-        * e.g. in <select> forms.
+        * A convenience function that returns getNamespaces() with spaces instead of underscores
+        * in values. Useful for producing output to be displayed e.g. in `<select>` forms.
         *
         * @return array
         */
@@ -542,6 +540,7 @@ class Language {
 
        /**
         * Get a namespace value by key
+        *
         * <code>
         * $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
         * echo $mw_ns; // prints 'MediaWiki'
@@ -552,7 +551,6 @@ class Language {
         */
        function getNsText( $index ) {
                $ns = $this->getNamespaces();
-
                return isset( $ns[$index] ) ? $ns[$index] : false;
        }
 
@@ -571,7 +569,6 @@ class Language {
         */
        function getFormattedNsText( $index ) {
                $ns = $this->getNsText( $index );
-
                return strtr( $ns, '_', ' ' );
        }