From 3bc410efa7f58b0cf148ba4440260e04e31d0086 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Wed, 16 Feb 2011 07:24:36 +0000 Subject: [PATCH] * Fix for r81960: List the local magic word synonyms first, so that they will be returned by $magic->getSynonym( 0 ). Apply array_values() to fix up the keys, potentially corrupted by array_unique(). * In MagicWord::initRegex(), put the longest synonyms first in the alternation. This means that when one synonym is an initial substring of another, the longest one will match in precedence, which is generally in line with user expectations. --- includes/LocalisationCache.php | 3 ++- includes/MagicWord.php | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/includes/LocalisationCache.php b/includes/LocalisationCache.php index af2ed65ce5..888722ad23 100644 --- a/includes/LocalisationCache.php +++ b/includes/LocalisationCache.php @@ -448,7 +448,8 @@ class LocalisationCache { } else { $oldSynonyms = array_slice( $fallbackInfo, 1 ); $newSynonyms = array_slice( $value[$magicName], 1 ); - $synonyms = array_unique( array_merge( $oldSynonyms, $newSynonyms ) ); + $synonyms = array_values( array_unique( array_merge( + $newSynonyms, $oldSynonyms ) ) ); $value[$magicName] = array_merge( array( $fallbackInfo[0] ), $synonyms ); } } diff --git a/includes/MagicWord.php b/includes/MagicWord.php index 9988232f5c..a0c14c265c 100644 --- a/includes/MagicWord.php +++ b/includes/MagicWord.php @@ -273,13 +273,13 @@ class MagicWord { * @private */ function initRegex() { - #$variableClass = Title::legalChars(); - # This was used for matching "$1" variables, but different uses of the feature will have - # different restrictions, which should be checked *after* the MagicWord has been matched, - # not here. - IMSoP + // Sort the synonyms by length, descending, so that the longest synonym + // matches in precedence to the shortest + $synonyms = $this->mSynonyms; + usort( $synonyms, array( $this, 'compareStringLength' ) ); $escSyn = array(); - foreach ( $this->mSynonyms as $synonym ) + foreach ( $synonyms as $synonym ) // In case a magic word contains /, like that's going to happen;) $escSyn[] = preg_quote( $synonym, '/' ); $this->mBaseRegex = implode( '|', $escSyn ); @@ -292,6 +292,23 @@ class MagicWord { "/^(?:{$this->mBaseRegex})$/{$case}" ); } + /** + * A comparison function that returns -1, 0 or 1 depending on whether the + * first string is longer, the same length or shorter than the second + * string. + */ + function compareStringLength( $s1, $s2 ) { + $l1 = strlen( $s1 ); + $l2 = strlen( $s2 ); + if ( $l1 < $l2 ) { + return 1; + } elseif ( $l1 > $l2 ) { + return -1; + } else { + return 0; + } + } + /** * Gets a regex representing matching the word */ -- 2.20.1