* Fix for r81960: List the local magic word synonyms first, so that they will be...
authorTim Starling <tstarling@users.mediawiki.org>
Wed, 16 Feb 2011 07:24:36 +0000 (07:24 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Wed, 16 Feb 2011 07:24:36 +0000 (07:24 +0000)
* 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
includes/MagicWord.php

index af2ed65..888722a 100644 (file)
@@ -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 );
                        }
                }
index 9988232..a0c14c2 100644 (file)
@@ -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
         */