Merge "Fix and make some types in PHPDoc and JSDoc tags more specific"
[lhc/web/wiklou.git] / includes / collation / NumericUppercaseCollation.php
index d15daec..8dd7a38 100644 (file)
  * Note that this only works in terms of sequences of digits, and the behavior for decimal fractions
  * or pretty-formatted numbers may be unexpected.
  *
+ * Digits will be based on the wiki's content language settings. If
+ * you change the content langauge of a wiki you will need to run
+ * updateCollation.php --force. Only English (ASCII 0-9) and the
+ * localized version will be counted. Localized digits from other languages
+ * or weird unicode digit equivalents (e.g. 4, 𝟜, ⓸ , ⁴, etc) will not count.
+ *
  * @since 1.28
  */
 class NumericUppercaseCollation extends UppercaseCollation {
+
+       /**
+        * @var $digitTransformLang Language How to convert digits (usually $wgContLang)
+        */
+       private $digitTransformLang;
+
+       /**
+        * @param $lang Language How to convert digits.
+        *  For example, if given language "my" than ၇ is treated like 7.
+        *
+        * It is expected that usually this is given $wgContLang.
+        */
+       public function __construct( Language $lang ) {
+               $this->digitTransformLang = $lang;
+               parent::__construct();
+       }
+
        public function getSortKey( $string ) {
                $sortkey = parent::getSortKey( $string );
-
+               $sortkey = $this->convertDigits( $sortkey );
                // For each sequence of digits, insert the digit '0' and then the length of the sequence
                // (encoded in two bytes) before it. That's all folks, it sorts correctly now! The '0' ensures
                // correct position (where digits would normally sort), then the length will be compared putting
@@ -48,11 +71,33 @@ class NumericUppercaseCollation extends UppercaseCollation {
                return $sortkey;
        }
 
+       /**
+        * Convert localized digits to english digits.
+        *
+        * based on Language::parseFormattedNumber but without commas.
+        *
+        * @param $string String sortkey to unlocalize digits of
+        * @return String Sortkey with all localized digits replaced with ASCII digits.
+        */
+       private function convertDigits( $string ) {
+               $table = $this->digitTransformLang->digitTransformTable();
+               if ( $table ) {
+                       $table = array_filter( $table );
+                       $flipped = array_flip( $table );
+                       // Some languages seem to also have commas in this table.
+                       $flipped = array_filter( $flipped, 'is_numeric' );
+                       $string = strtr( $string, $flipped );
+               }
+               return $string;
+       }
+
        public function getFirstLetter( $string ) {
-               if ( preg_match( '/^\d/', $string ) ) {
-                       // Note that we pass 0 and 9 as normal params, not numParams(). This only works for 0-9
-                       // and not localised digits, so we don't want them to be converted.
-                       return wfMessage( 'category-header-numerals' )->params( 0, 9 )->text();
+               $convertedString = $this->convertDigits( $string );
+
+               if ( preg_match( '/^\d/', $convertedString ) ) {
+                       return wfMessage( 'category-header-numerals' )
+                               ->numParams( 0, 9 )
+                               ->text();
                } else {
                        return parent::getFirstLetter( $string );
                }