Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
40.98% covered (danger)
40.98%
25 / 61
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
RequestConfig
40.98% covered (danger)
40.98%
25 / 61
75.00% covered (warning)
75.00%
3 / 4
76.40
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 getConfigArray
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 getConfigHash
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTemplateLanguages
26.53% covered (danger)
26.53%
13 / 49
0.00% covered (danger)
0.00%
0 / 1
80.02
1<?php
2
3namespace MediaWiki\Extension\MediaUploader\Config;
4
5use Collator;
6use FormatJson;
7use Language;
8use LanguageCode;
9use MediaWiki\Cache\LinkBatchFactory;
10use MediaWiki\Languages\LanguageNameUtils;
11use Title;
12use WANObjectCache;
13
14/**
15 * Config with fields dependent on the specific request.
16 *
17 * This means things like the current language can be taken into account.
18 *
19 * @internal Only for use by GlobalParsedConfig and CampaignParsedConfig.
20 */
21class RequestConfig extends ConfigBase {
22
23    /**
24     * Raw config's value enhanced with request-dependent settings.
25     *
26     * @var array|null
27     */
28    private $config = null;
29
30    /** @var WANObjectCache */
31    protected $cache;
32
33    /** @var Language */
34    private $language;
35
36    /** @var RawConfig */
37    private $rawConfig;
38
39    /** @var LanguageNameUtils */
40    private $languageNameUtils;
41
42    /** @var LinkBatchFactory */
43    private $linkBatchFactory;
44
45    /**
46     * @param WANObjectCache $cache
47     * @param LanguageNameUtils $languageNameUtils
48     * @param LinkBatchFactory $linkBatchFactory
49     * @param Language $language
50     * @param RawConfig $rawConfig
51     *
52     * @internal Only for use by ConfigFactory
53     */
54    public function __construct(
55        WANObjectCache $cache,
56        LanguageNameUtils $languageNameUtils,
57        LinkBatchFactory $linkBatchFactory,
58        Language $language,
59        RawConfig $rawConfig
60    ) {
61        $this->cache = $cache;
62        $this->language = $language;
63        $this->rawConfig = $rawConfig;
64        $this->languageNameUtils = $languageNameUtils;
65        $this->linkBatchFactory = $linkBatchFactory;
66    }
67
68    /**
69     * Returns the unparsed configuration array with all dynamically
70     * generated defaults applied.
71     *
72     * @return array
73     */
74    public function getConfigArray(): array {
75        if ( $this->config !== null ) {
76            return $this->config;
77        }
78
79        // Set request-dependent defaults
80        $this->config = $this->rawConfig->getConfigWithAdditionalDefaults( [
81            'languages' => $this->getTemplateLanguages(),
82        ] );
83
84        return $this->config;
85    }
86
87    /**
88     * @return string
89     */
90    public function getConfigHash(): string {
91        return md5( FormatJson::encode( $this->getConfigArray() ) );
92    }
93
94    /**
95     * Generates the 'languages' setting's default value.
96     * TODO: Execute this only if the wizard is configured with multi-language fields.
97     *
98     * @return array
99     */
100    private function getTemplateLanguages(): array {
101        // We need to get a list of languages for the description dropdown.
102        // Increase the 'version' number in the options below if this logic or format changes.
103        return $this->cache->getWithSetCallback(
104            $this->cache->makeKey(
105                'mediauploader',
106                'language-templates',
107                $this->language->getCode()
108            ),
109            $this->cache::TTL_DAY,
110            function () {
111                $languages = [];
112
113                // First, get a list of languages we support.
114                $baseLangs = $this->languageNameUtils->getLanguageNames(
115                    $this->language->getCode(),
116                    LanguageNameUtils::ALL
117                );
118
119                // We need to take into account languageTemplateFixups
120                $languageFixups = $this->rawConfig->getSetting(
121                    'languageTemplateFixups',
122                    []
123                );
124
125                // Use LinkBatch to make this a little bit more faster.
126                // It works because $title->exists (below) will use LinkCache.
127                $linkBatch = $this->linkBatchFactory->newLinkBatch();
128                foreach ( $baseLangs as $code => $name ) {
129                    $fixedCode = $languageFixups[$code] ?? $code;
130                    if ( is_string( $fixedCode ) && $fixedCode !== '' ) {
131                        $title = Title::makeTitle(
132                            NS_TEMPLATE,
133                            Title::capitalize( $fixedCode, NS_TEMPLATE )
134                        );
135                        $linkBatch->addObj( $title );
136                    }
137                }
138                $linkBatch->execute();
139
140                // Then, check that there's a template for each one.
141                foreach ( $baseLangs as $code => $name ) {
142                    $fixedCode = $languageFixups[$code] ?? $code;
143                    if ( is_string( $fixedCode ) && $fixedCode !== '' ) {
144                        $title = Title::makeTitle(
145                            NS_TEMPLATE,
146                            Title::capitalize( $fixedCode, NS_TEMPLATE )
147                        );
148                        if ( $title->exists() ) {
149                            // If there is, then it's in the final picks!
150                            $languages[$code] = $name;
151                        }
152                    }
153                }
154
155                // Skip the duplicate deprecated language codes if the new one is okay to use.
156                foreach ( LanguageCode::getDeprecatedCodeMapping() as $oldKey => $newKey ) {
157                    if ( isset( $languages[$newKey] ) && isset( $languages[$oldKey] ) ) {
158                        unset( $languages[$oldKey] );
159                    }
160                }
161
162                // Sort the list by the language name.
163                if ( class_exists( Collator::class ) ) {
164                    // If a specific collation is not available for the user's language,
165                    // this falls back to a generic 'root' one.
166                    $collator = Collator::create( $this->language->getCode() );
167                    $collator->asort( $languages );
168                } else {
169                    natcasesort( $languages );
170                }
171
172                // Fallback just in case
173                return $languages ?: [ 'en' => 'English' ];
174            },
175            [
176                'version' => 1,
177            ]
178        );
179    }
180}