Merge "Introduce constants for fetchLanguageName(s)"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 13 Sep 2018 06:24:09 +0000 (06:24 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 13 Sep 2018 06:24:09 +0000 (06:24 +0000)
1  2 
languages/Language.php

diff --combined languages/Language.php
@@@ -33,6 -33,25 +33,25 @@@ use CLDRPluralRuleParser\Evaluator
   * @ingroup Language
   */
  class Language {
+       /**
+        * Return autonyms in fetchLanguageName(s).
+        * @since 1.32
+        */
+       const AS_AUTONYMS = null;
+       /**
+        * Return all known languages in fetchLanguageName(s).
+        * @since 1.32
+        */
+       const ALL = 'all';
+       /**
+        * Return in fetchLanguageName(s) only the languages for which we have at
+        * least some localisation.
+        * @since 1.32
+        */
+       const SUPPORTED = 'mwfile';
        /**
         * @var LanguageConverter
         */
  
                // Check if there is a language class for the code
                $class = self::classFromCode( $code, $fallback );
 -              if ( class_exists( $class ) ) {
 +              // LanguageCode does not inherit Language
 +              if ( class_exists( $class ) && is_a( $class, 'Language', true ) ) {
                        $lang = new $class;
                        return $lang;
                }
                throw new MWException( "Invalid fallback sequence for language '$code'" );
        }
  
 +      /**
 +       * Intended for tests that may change configuration in a way that invalidates caches.
 +       *
 +       * @since 1.32
 +       */
 +      public static function clearCaches() {
 +              if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
 +                      throw new MWException( __METHOD__ . ' must not be used outside tests' );
 +              }
 +              self::$dataCache = null;
 +              // Reinitialize $dataCache, since it's expected to always be available
 +              self::getLocalisationCache();
 +              self::$mLangObjCache = [];
 +              self::$fallbackLanguageCache = [];
 +              self::$grammarTransformations = null;
 +              self::$languageNameCache = null;
 +      }
 +
        /**
         * Checks whether any localisation is available for that language tag
         * in MediaWiki (MessagesXx.php exists).
         * Get a namespace value by key
         *
         * <code>
 -       * $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
 +       * $mw_ns = $lang->getNsText( NS_MEDIAWIKI );
         * echo $mw_ns; // prints 'MediaWiki'
         * </code>
         *
         * producing output.
         *
         * <code>
 -       * $mw_ns = $wgContLang->getFormattedNsText( NS_MEDIAWIKI_TALK );
 +       * $mw_ns = $lang->getFormattedNsText( NS_MEDIAWIKI_TALK );
         * echo $mw_ns; // prints 'MediaWiki talk'
         * </code>
         *
        /**
         * Get an array of language names, indexed by code.
         * @param null|string $inLanguage Code of language in which to return the names
-        *              Use null for autonyms (native names)
+        *              Use self::AS_AUTONYMS for autonyms (native names)
         * @param string $include One of:
-        *              'all' all available languages
+        *              self::ALL all available languages
         *              'mw' only if the language is defined in MediaWiki or wgExtraLanguageNames (default)
-        *              'mwfile' only if the language is in 'mw' *and* has a message file
+        *              self::SUPPORTED only if the language is in 'mw' *and* has a message file
         * @return array Language code => language name (sorted by key)
         * @since 1.20
         */
-       public static function fetchLanguageNames( $inLanguage = null, $include = 'mw' ) {
-               $cacheKey = $inLanguage === null ? 'null' : $inLanguage;
+       public static function fetchLanguageNames( $inLanguage = self::AS_AUTONYMS, $include = 'mw' ) {
+               $cacheKey = $inLanguage === self::AS_AUTONYMS ? 'null' : $inLanguage;
                $cacheKey .= ":$include";
                if ( self::$languageNameCache === null ) {
                        self::$languageNameCache = new HashBagOStuff( [ 'maxKeys' => 20 ] );
        /**
         * Uncached helper for fetchLanguageNames
         * @param null|string $inLanguage Code of language in which to return the names
-        *              Use null for autonyms (native names)
+        *              Use self::AS_AUTONYMS for autonyms (native names)
         * @param string $include One of:
-        *              'all' all available languages
+        *              self::ALL all available languages
         *              'mw' only if the language is defined in MediaWiki or wgExtraLanguageNames (default)
-        *              'mwfile' only if the language is in 'mw' *and* has a message file
+        *              self::SUPPORTED only if the language is in 'mw' *and* has a message file
         * @return array Language code => language name (sorted by key)
         */
-       private static function fetchLanguageNamesUncached( $inLanguage = null, $include = 'mw' ) {
+       private static function fetchLanguageNamesUncached(
+               $inLanguage = self::AS_AUTONYMS,
+               $include = 'mw'
+       ) {
                global $wgExtraLanguageNames, $wgUsePigLatinVariant;
  
                // If passed an invalid language code to use, fallback to en
-               if ( $inLanguage !== null && !self::isValidCode( $inLanguage ) ) {
+               if ( $inLanguage !== self::AS_AUTONYMS && !self::isValidCode( $inLanguage ) ) {
                        $inLanguage = 'en';
                }
  
                        }
                }
  
-               if ( $include === 'all' ) {
+               if ( $include === self::ALL ) {
                        ksort( $names );
                        return $names;
                }
                        $returnMw[$coreCode] = $names[$coreCode];
                }
  
-               if ( $include === 'mwfile' ) {
+               if ( $include === self::SUPPORTED ) {
                        $namesMwFile = [];
                        # We do this using a foreach over the codes instead of a directory
                        # loop so that messages files in extensions will work correctly.
  
        /**
         * @param string $code The code of the language for which to get the name
-        * @param null|string $inLanguage Code of language in which to return the name (null for autonyms)
-        * @param string $include 'all', 'mw' or 'mwfile'; see fetchLanguageNames()
+        * @param null|string $inLanguage Code of language in which to return the name
+        *   (SELF::AS_AUTONYMS for autonyms)
+        * @param string $include See fetchLanguageNames()
         * @return string Language name or empty
         * @since 1.20
         */
-       public static function fetchLanguageName( $code, $inLanguage = null, $include = 'all' ) {
+       public static function fetchLanguageName(
+               $code,
+               $inLanguage = self::AS_AUTONYMS,
+               $include = self::ALL
+       ) {
                $code = strtolower( $code );
                $array = self::fetchLanguageNames( $inLanguage, $include );
                return !array_key_exists( $code, $array ) ? '' : $array[$code];
         * @param string $ts 14-character timestamp
         *      YYYYMMDDHHMMSS
         *      01234567890123
 -       * @param DateTimeZone $zone Timezone of $ts
 +       * @param DateTimeZone|null $zone Timezone of $ts
         * @param int &$ttl The amount of time (in seconds) the output may be cached for.
         * Only makes sense if $ts is the current time.
         * @todo handling of "o" format character for Iranian, Hebrew, Hijri & Thai?
                        # Add 543 years to the Gregorian calendar
                        # Months and days are identical
                        $gy_offset = $gy + 543;
 +                      # fix for dates between 1912 and 1941
 +                      # https://en.wikipedia.org/?oldid=836596673#New_year
 +                      if ( $gy >= 1912 && $gy <= 1940 ) {
 +                              if ( $gm <= 3 ) {
 +                                      $gy_offset--;
 +                              }
 +                              $gm = ( $gm - 3 ) % 12;
 +                      }
                } elseif ( ( !strcmp( $cName, 'minguo' ) ) || !strcmp( $cName, 'juche' ) ) {
                        # Minguo dates
                        # Deduct 1911 years from the Gregorian calendar
         *
         * @return string
         */
 -      function normalize( $s ) {
 +      public function normalize( $s ) {
                global $wgAllUnicodeFixes;
                $s = UtfNormal\Validator::cleanUp( $s );
                if ( $wgAllUnicodeFixes ) {
         * Take a list of strings and build a locale-friendly comma-separated
         * list, using the local comma-separator message.
         * The last two strings are chained with an "and".
 -       * NOTE: This function will only work with standard numeric array keys (0, 1, 2…)
         *
 -       * @param string[] $l
 +       * @param string[] $list
         * @return string
         */
 -      function listToText( array $l ) {
 -              $m = count( $l ) - 1;
 -              if ( $m < 0 ) {
 +      public function listToText( array $list ) {
 +              $itemCount = count( $list );
 +              if ( $itemCount < 1 ) {
                        return '';
                }
 -              if ( $m > 0 ) {
 +              $text = array_pop( $list );
 +              if ( $itemCount > 1 ) {
                        $and = $this->msg( 'and' )->escaped();
                        $space = $this->msg( 'word-separator' )->escaped();
 -                      if ( $m > 1 ) {
 +                      $comma = '';
 +                      if ( $itemCount > 2 ) {
                                $comma = $this->msg( 'comma-separator' )->escaped();
                        }
 +                      $text = implode( $comma, $list ) . $and . $space . $text;
                }
 -              $s = $l[$m];
 -              for ( $i = $m - 1; $i >= 0; $i-- ) {
 -                      if ( $i == $m - 1 ) {
 -                              $s = $l[$i] . $and . $space . $s;
 -                      } else {
 -                              $s = $l[$i] . $comma . $s;
 -                      }
 -              }
 -              return $s;
 +              return $text;
        }
  
        /**
         * @return string
         */
        function truncate( $string, $length, $ellipsis = '...', $adjustLength = true ) {
 +              wfDeprecated( __METHOD__, '1.31' );
                return $this->truncateForDatabase( $string, $length, $ellipsis, $adjustLength );
        }
  
         * match up with it.
         *
         * @param string $str The validated block duration in English
 -       * @param User $user User object to use timezone from or null for $wgUser
 +       * @param User|null $user User object to use timezone from or null for $wgUser
         * @param int $now Current timestamp, for formatting relative block durations
         * @return string Somehow translated block duration
         * @see LanguageFi.php for example implementation
        /**
         * convert text to different variants of a language.
         *
 -       * @param string $text
 -       * @return string
 +       * @warning Glossary state is maintained between calls. This means
 +       *  if you pass unescaped text to this method it can cause an XSS
 +       *  in later calls to this method, even if the later calls have properly
 +       *  escaped the input. Never feed this method user controlled text that
 +       *  is not properly escaped!
 +       * @param string $text Content that has been already escaped for use in HTML
 +       * @return string HTML
         */
        public function convert( $text ) {
                return $this->mConverter->convert( $text );
         * @return bool
         */
        public function equals( Language $lang ) {
 -              return $lang->getCode() === $this->mCode;
 +              return $lang === $this || $lang->getCode() === $this->mCode;
        }
  
        /**