From c318e3a265f28043038115ad4e027d2dc7a6c030 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Mon, 6 Jul 2015 10:17:47 +0100 Subject: [PATCH] Hygiene: Use strtr() instead of str_replace() for character swapping 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 | 2 +- includes/GlobalFunctions.php | 8 +++---- includes/Linker.php | 9 ++++--- includes/Title.php | 24 +++++++++---------- includes/api/ApiQueryAllUsers.php | 2 +- includes/cache/LinkBatch.php | 2 +- includes/filerepo/LocalRepo.php | 2 +- .../resourceloader/ResourceLoaderModule.php | 2 +- languages/Language.php | 9 +++---- 9 files changed, 27 insertions(+), 33 deletions(-) diff --git a/includes/Export.php b/includes/Export.php index 0d55d7dbc1..adab21c32c 100644 --- a/includes/Export.php +++ b/includes/Export.php @@ -874,7 +874,7 @@ class XmlDumpWriter { } global $wgContLang; - $prefix = str_replace( '_', ' ', $wgContLang->getNsText( $title->getNamespace() ) ); + $prefix = $wgContLang->getFormattedNsText( $title->getNamespace() ); if ( $prefix !== '' ) { $prefix .= ':'; diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 97042fd1f0..30140709a1 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -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, ' ', '_' ); } /** diff --git a/includes/Linker.php b/includes/Linker.php index 4a1aa872d8..bb65cdf3d7 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -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( '<', '>' ), - rawurldecode( $match[1] ) + $match[1] = strtr( + rawurldecode( $match[1] ), + array( '<' => '<', '>' => '>' ) ); } diff --git a/includes/Title.php b/includes/Title.php index 9c8ed477e6..1ab88a6dd4 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -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(); diff --git a/includes/api/ApiQueryAllUsers.php b/includes/api/ApiQueryAllUsers.php index 05daa7ab36..b52b1c6aa3 100644 --- a/includes/api/ApiQueryAllUsers.php +++ b/includes/api/ApiQueryAllUsers.php @@ -41,7 +41,7 @@ class ApiQueryAllUsers extends ApiQueryBase { * @return string */ private function getCanonicalUserName( $name ) { - return str_replace( '_', ' ', $name ); + return strtr( $name, '_', ' ' ); } public function execute() { diff --git a/includes/cache/LinkBatch.php b/includes/cache/LinkBatch.php index 77e4d4901e..698b3046f3 100644 --- a/includes/cache/LinkBatch.php +++ b/includes/cache/LinkBatch.php @@ -78,7 +78,7 @@ class LinkBatch { $this->data[$ns] = array(); } - $this->data[$ns][str_replace( ' ', '_', $dbkey )] = 1; + $this->data[$ns][strtr( $dbkey, ' ', '_' )] = 1; } /** diff --git a/includes/filerepo/LocalRepo.php b/includes/filerepo/LocalRepo.php index ef402ea984..800a230de9 100644 --- a/includes/filerepo/LocalRepo.php +++ b/includes/filerepo/LocalRepo.php @@ -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() ); diff --git a/includes/resourceloader/ResourceLoaderModule.php b/includes/resourceloader/ResourceLoaderModule.php index 94edb36b16..46b786d08a 100644 --- a/includes/resourceloader/ResourceLoaderModule.php +++ b/includes/resourceloader/ResourceLoaderModule.php @@ -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 ); diff --git a/languages/Language.php b/languages/Language.php index b1d88bce38..fdffbec63d 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -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 ` forms. * * @return array */ @@ -542,6 +540,7 @@ class Language { /** * Get a namespace value by key + * * * $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, '_', ' ' ); } -- 2.20.1