Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.00% covered (success)
92.00%
23 / 25
80.00% covered (warning)
80.00%
4 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
LanguageConverterFactory
95.83% covered (success)
95.83%
23 / 24
80.00% covered (warning)
80.00%
4 / 5
8
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 instantiateConverter
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 getLanguageConverter
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
2.02
 isConversionDisabled
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isLinkConversionDisabled
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace MediaWiki\Language;
8
9use BanConverter;
10use CrhConverter;
11use EnConverter;
12use GanConverter;
13use IuConverter;
14use KuConverter;
15use MediaWiki\Config\ServiceOptions;
16use MediaWiki\MainConfigNames;
17use MediaWiki\StubObject\StubUserLang;
18use MniConverter;
19use ShConverter;
20use ShiConverter;
21use SrConverter;
22use TgConverter;
23use TlyConverter;
24use TrivialLanguageConverter;
25use UzConverter;
26use Wikimedia\ObjectFactory\ObjectFactory;
27use WuuConverter;
28use ZghConverter;
29use ZhConverter;
30
31/**
32 * An interface for creating language converters.
33 *
34 * @since 1.35
35 * @ingroup Language
36 */
37class LanguageConverterFactory {
38
39    /** @var ILanguageConverter[] */
40    private $cache = [];
41    /**
42     * @var array
43     * @phpcs-require-sorted-array
44     */
45    private $converterList = [
46        'ban' => [
47            'class' => BanConverter::class,
48        ],
49        'crh' => [
50            'class' => CrhConverter::class,
51        ],
52        'gan' => [
53            'class' => GanConverter::class,
54        ],
55        'iu' => [
56            'class' => IuConverter::class,
57        ],
58        'ku' => [
59            'class' => KuConverter::class,
60        ],
61        'mni' => [
62            'class' => MniConverter::class,
63        ],
64        'sh' => [
65            'class' => ShConverter::class,
66        ],
67        'shi' => [
68            'class' => ShiConverter::class,
69        ],
70        'sr' => [
71            'class' => SrConverter::class,
72        ],
73        'tg' => [
74            'class' => TgConverter::class,
75        ],
76        'tly' => [
77            'class' => TlyConverter::class,
78        ],
79        'uz' => [
80            'class' => UzConverter::class,
81        ],
82        'wuu' => [
83            'class' => WuuConverter::class,
84        ],
85        'zgh' => [
86            'class' => ZghConverter::class,
87        ],
88        'zh' => [
89            'class' => ZhConverter::class,
90        ],
91    ];
92
93    private const DEFAULT_CONVERTER = [
94        'class' => TrivialLanguageConverter::class,
95        'services' => [
96            'TitleFormatter',
97        ]
98    ];
99
100    private const EN_CONVERTER = [
101        'class' => EnConverter::class,
102    ];
103
104    /**
105     * @internal For use by ServiceWiring
106     */
107    public const CONSTRUCTOR_OPTIONS = [
108        MainConfigNames::UsePigLatinVariant,
109        MainConfigNames::DisableLangConversion,
110        MainConfigNames::DisableTitleConversion,
111    ];
112
113    private ServiceOptions $options;
114    private ObjectFactory $objectFactory;
115
116    /**
117     * @var callable callback of "() : Language"
118     */
119    private $defaultLanguage;
120
121    /**
122     * @param ServiceOptions $options
123     * @param ObjectFactory $objectFactory
124     * @param callable $defaultLanguage callback of "() : Language", should return
125     *  default language. Used in getLanguageConverter when $language is null.
126     *
127     * @internal Should be called from MediaWikiServices only.
128     */
129    public function __construct(
130        ServiceOptions $options,
131        ObjectFactory $objectFactory,
132        callable $defaultLanguage
133    ) {
134        $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
135        $this->options = $options;
136        $this->objectFactory = $objectFactory;
137        if ( $options->get( MainConfigNames::UsePigLatinVariant ) ) {
138            $this->converterList['en'] = self::EN_CONVERTER;
139        }
140        $this->defaultLanguage = $defaultLanguage;
141    }
142
143    /**
144     * Returns Converter instance for a given language object
145     *
146     * @param Language|StubUserLang $lang
147     * @return ILanguageConverter
148     */
149    private function instantiateConverter( $lang ): ILanguageConverter {
150        $code = mb_strtolower( $lang->getCode() );
151        $spec = $this->converterList[$code] ?? self::DEFAULT_CONVERTER;
152        // ObjectFactory::createObject accepts an array, not just a callable (phan bug)
153        // @phan-suppress-next-line PhanTypeInvalidCallableArrayKey, PhanTypeInvalidCallableArraySize
154        return $this->objectFactory->createObject(
155            $spec,
156            [
157                'assertClass' => ILanguageConverter::class,
158                'extraArgs' => [ $lang ],
159            ]
160        );
161    }
162
163    /**
164     * Provide a LanguageConverter for given language
165     *
166     * @param Language|StubUserLang|null $language for which a LanguageConverter should be provided.
167     * If it is null, then the LanguageConverter provided for current content language as returned
168     * by the callback provided to the constructor.
169     *
170     * @return ILanguageConverter
171     */
172    public function getLanguageConverter( $language = null ): ILanguageConverter {
173        $lang = $language ?? ( $this->defaultLanguage )();
174        if ( isset( $this->cache[$lang->getCode()] ) ) {
175            return $this->cache[$lang->getCode()];
176        }
177        // @phan-suppress-next-line PhanTypeMismatchArgumentNullable False positive
178        $converter = $this->instantiateConverter( $lang );
179        $this->cache[$lang->getCode()] = $converter;
180        return $converter;
181    }
182
183    /**
184     * Whether to disable language variant conversion.
185     *
186     * @return bool
187     */
188    public function isConversionDisabled() {
189        return $this->options->get( MainConfigNames::DisableLangConversion );
190    }
191
192    /**
193     * Whether to disable language variant conversion for links.
194     *
195     * @return bool
196     */
197    public function isLinkConversionDisabled() {
198        return $this->options->get( MainConfigNames::DisableLangConversion ) ||
199            // Note that this configuration option is misnamed.
200            $this->options->get( MainConfigNames::DisableTitleConversion );
201    }
202}
203
204/** @deprecated class alias since 1.45 */
205class_alias( LanguageConverterFactory::class, 'MediaWiki\\Languages\\LanguageConverterFactory' );