Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
77.36% covered (warning)
77.36%
41 / 53
70.00% covered (warning)
70.00%
7 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
ZMultiLingualStringSet
77.36% covered (warning)
77.36%
41 / 53
70.00% covered (warning)
70.00%
7 / 10
26.12
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getDefinition
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
1
 isValid
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getZValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getValueAsList
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getAliasesForLanguageCode
66.67% covered (warning)
66.67%
4 / 6
0.00% covered (danger)
0.00%
0 / 1
3.33
 getAliasesForLanguage
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 isLanguageProvidedValue
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 setMonoLingualStringSet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSerialized
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * WikiLambda ZMultiLingualStringSet
4 *
5 * @file
6 * @ingroup Extensions
7 * @copyright 2020– Abstract Wikipedia team; see AUTHORS.txt
8 * @license MIT
9 */
10
11namespace MediaWiki\Extension\WikiLambda\ZObjects;
12
13use MediaWiki\Extension\WikiLambda\Registry\ZLangRegistry;
14use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry;
15use MediaWiki\Extension\WikiLambda\ZErrorException;
16use MediaWiki\Extension\WikiLambda\ZObjectUtils;
17use MediaWiki\Language\Language;
18use MediaWiki\Languages\LanguageFallback;
19use MediaWiki\MediaWikiServices;
20
21class ZMultiLingualStringSet extends ZObject {
22
23    /**
24     * Construct a ZMultiLingualStringSet instance given an array or a ZTypedList
25     * of ZMonoLingualStringSet instances.
26     *
27     * @param ZTypedList|array $strings
28     */
29    public function __construct( $strings = [] ) {
30        foreach ( ZObjectUtils::getIterativeList( $strings ) as $index => $monoLingualStringSet ) {
31            if ( $monoLingualStringSet instanceof ZMonoLingualStringSet ) {
32                $this->setMonoLingualStringSet( $monoLingualStringSet );
33            }
34        }
35    }
36
37    /**
38     * @inheritDoc
39     */
40    public static function getDefinition(): array {
41        return [
42            'type' => [
43                'type' => ZTypeRegistry::Z_REFERENCE,
44                'value' => ZTypeRegistry::Z_MULTILINGUALSTRINGSET,
45            ],
46            'keys' => [
47                ZTypeRegistry::Z_MULTILINGUALSTRINGSET_VALUE => [
48                    'type' => ZTypeRegistry::HACK_ARRAY_Z_MONOLINGUALSTRINGSET,
49                    'required' => true,
50                ],
51            ],
52        ];
53    }
54
55    /**
56     * @inheritDoc
57     */
58    public function isValid(): bool {
59        $stringsets = $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRINGSET_VALUE ] ?? [];
60        // @phan-suppress-next-line PhanTypeSuspiciousNonTraversableForeach; it's a ZMonoLingualStringSet[]
61        foreach ( $stringsets as $lang => $monolingualString ) {
62            if ( !$monolingualString->isValid() ) {
63                return false;
64            }
65        }
66        return true;
67    }
68
69    /**
70     * Get the list of ZMonoLingualStringSets that represent the value of
71     * this ZMultiLingualStringSet
72     *
73     * @return array
74     */
75    public function getZValue() {
76        return $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRINGSET_VALUE ] ?? [];
77    }
78
79    /**
80     * Get the values of this ZMultiLingualStringSet in the shape of an
81     * array with language as key and array of strings as value.
82     *
83     * @return array
84     */
85    public function getValueAsList() {
86        $multi = [];
87        foreach ( $this->getZValue() as $mono ) {
88            $multi[ $mono->getLanguage() ] = $mono->getStringSet();
89        }
90        return $multi;
91    }
92
93    /**
94     * Fetch the ZMultiLingualStringSet's stored values for a given MediaWiki language code (e.g.
95     * 'en' or 'zh-hant'). Note that this is a raw fetch and does not walk the language fallback
96     * chain; users are expected to use getStringForLanguage() which does.
97     *
98     * @param string $languageCode The MediaWiki language code in which the string is wanted.
99     * @return string[] The aliases list, possibly empty.
100     */
101    public function getAliasesForLanguageCode( string $languageCode ): array {
102        try {
103            $languageZid = ZLangRegistry::singleton()->getLanguageZidFromCode( $languageCode );
104        } catch ( ZErrorException $e ) {
105            return [];
106        }
107        return array_key_exists( $languageZid, $this->getZValue() )
108            ? $this->getZValue()[ $languageZid ]->getStringSet()
109            : [];
110    }
111
112    /**
113     * Fetch the ZMultiLingualStringSet's stored value for a given MediaWiki language class. This will
114     * walk the language fallback chain until there is a set value to return.
115     *
116     * @param Language $language The MediaWiki language class in which the string is wanted.
117     * @return string[] The aliases, possibly empty.
118     */
119    public function getAliasesForLanguage( Language $language ): array {
120        if ( $this->isLanguageProvidedValue( $language->getCode() ) ) {
121            return $this->getAliasesForLanguageCode( $language->getCode() );
122        }
123
124        // TODO (T362246): Dependency-inject
125        $fallbacks = MediaWikiServices::getInstance()->getLanguageFallback()->getAll(
126            $language->getCode(),
127            /* Don't try for en unless it's an accepted fallback. */ LanguageFallback::STRICT
128        );
129
130        foreach ( $fallbacks as $index => $languageCode ) {
131            if ( $this->isLanguageProvidedValue( $languageCode ) ) {
132                return $this->getAliasesForLanguageCode( $languageCode );
133            }
134        }
135
136        return [];
137    }
138
139    /**
140     * Check if the ZMultiLingualStringSet has a stored value for a given MediaWiki language code (e.g.
141     * 'en' or 'zh-hant'). Note that this is a raw check and does not walk the language fallback
142     * chain.
143     *
144     * @param string $languageCode The MediaWiki language code in which the string is wanted.
145     * @return bool If there is a list stored.
146     */
147    public function isLanguageProvidedValue( string $languageCode ): bool {
148        try {
149            $languageZid = ZLangRegistry::singleton()->getLanguageZidFromCode( $languageCode );
150        } catch ( ZErrorException $e ) {
151            return false;
152        }
153        $aliases = $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRINGSET_VALUE ][ $languageZid ] ?? [];
154        return ( $aliases !== [] );
155    }
156
157    /**
158     * Add or replace a ZMonoLingualStringSet.
159     *
160     * @param ZMonoLingualStringSet $value The new value to set.
161     */
162    public function setMonoLingualStringSet( ZMonoLingualStringSet $value ): void {
163        $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRINGSET_VALUE ][ $value->getLanguage() ] = $value;
164    }
165
166    /**
167     * Convert this ZObject into its serialized canonical representation
168     *
169     * @param int $form
170     * @return \stdClass|array|string
171     */
172    public function getSerialized( $form = self::FORM_CANONICAL ) {
173        $listType = new ZReference( ZTypeRegistry::Z_MONOLINGUALSTRINGSET );
174        $typedList = new ZTypedList( ZTypedList::buildType( $listType ), array_values( $this->getZValue() ) );
175        return (object)[
176            ZTypeRegistry::Z_OBJECT_TYPE => $this->getZTypeObject()->getSerialized( $form ),
177            ZTypeRegistry::Z_MULTILINGUALSTRINGSET_VALUE => $typedList->getSerialized( $form )
178        ];
179    }
180}