Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
50 / 50
100.00% covered (success)
100.00%
13 / 13
CRAP
100.00% covered (success)
100.00%
1 / 1
ZMultiLingualString
100.00% covered (success)
100.00%
50 / 50
100.00% covered (success)
100.00%
13 / 13
21
100.00% covered (success)
100.00%
1 / 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%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getSerialized
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 getZValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getValueAsList
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getStringForLanguageCode
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 isLanguageProvidedValue
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getStringForLanguage
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 buildStringForLanguage
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setMonoLingualString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setStringForLanguage
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 removeValue
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * WikiLambda ZMultiLingualString
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 Language;
14use MediaWiki\Extension\WikiLambda\Registry\ZLangRegistry;
15use MediaWiki\Extension\WikiLambda\Registry\ZTypeRegistry;
16use MediaWiki\Extension\WikiLambda\ZErrorException;
17use MediaWiki\Extension\WikiLambda\ZObjectUtils;
18
19class ZMultiLingualString extends ZObject {
20
21    /**
22     * Create a ZMultiLingualString instance given an array or a ZTypedList of
23     * ZMonoLingualString instances. Internally this class bypasses ZTypedList
24     * and stores an array with the language Zid as key.
25     *
26     * @param ZTypedList|array $strings
27     */
28    public function __construct( $strings = [] ) {
29        foreach ( ZObjectUtils::getIterativeList( $strings ) as $index => $monoLingualString ) {
30            if ( $monoLingualString instanceof ZMonoLingualString ) {
31                $this->setMonoLingualString( $monoLingualString );
32            }
33        }
34    }
35
36    /**
37     * @inheritDoc
38     */
39    public static function getDefinition(): array {
40        return [
41            'type' => [
42                'type' => ZTypeRegistry::Z_REFERENCE,
43                'value' => ZTypeRegistry::Z_MULTILINGUALSTRING,
44            ],
45            'keys' => [
46                ZTypeRegistry::Z_MULTILINGUALSTRING_VALUE => [
47                    'type' => ZTypeRegistry::HACK_ARRAY_Z_MONOLINGUALSTRING,
48                    'required' => true,
49                ],
50            ],
51        ];
52    }
53
54    /**
55     * @inheritDoc
56     */
57    public function isValid(): bool {
58        // @phan-suppress-next-line PhanTypeSuspiciousNonTraversableForeach; it's a ZMonoLingualString[]
59        foreach ( $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRING_VALUE ] ?? [] as $lang => $monolingualString ) {
60            if ( !$monolingualString->isValid() ) {
61                return false;
62            }
63        }
64        return true;
65    }
66
67    /**
68     * @inheritDoc
69     */
70    public function getSerialized( $form = self::FORM_CANONICAL ) {
71        $listType = new ZReference( ZTypeRegistry::Z_MONOLINGUALSTRING );
72        $typedList = new ZTypedList( ZTypedList::buildType( $listType ), array_values( $this->getZValue() ) );
73        return (object)[
74            ZTypeRegistry::Z_OBJECT_TYPE => $this->getZTypeObject()->getSerialized( $form ),
75            ZTypeRegistry::Z_MULTILINGUALSTRING_VALUE => $typedList->getSerialized( $form )
76        ];
77    }
78
79    /**
80     * Get the list of ZMonoLingualStrings that represent the value of this ZMultiLingualString
81     *
82     * @return array
83     */
84    public function getZValue() {
85        return $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRING_VALUE ] ?? [];
86    }
87
88    /**
89     * Get the values of this ZMultiLingualString in the shape of an array
90     * with language as key and string as value
91     *
92     * @return array
93     */
94    public function getValueAsList() {
95        $multi = [];
96        foreach ( $this->getZValue() as $mono ) {
97            $multi[ $mono->getLanguage() ] = $mono->getString();
98        }
99        return $multi;
100    }
101
102    /**
103     * Fetch the ZMultiLingualString's stored value for a given MediaWiki language code (e.g.
104     * 'en' or 'zh-hant'). Note that this is a raw fetch and does not walk the language fallback
105     * chain; users are expected to use getStringForLanguage() which does.
106     *
107     * @param string $languageCode The MediaWiki language code in which the string is wanted.
108     * @return string The string, or the empty string if .
109     */
110    public function getStringForLanguageCode( string $languageCode ): string {
111        try {
112            $languageZid = ZLangRegistry::singleton()->getLanguageZidFromCode( $languageCode );
113        } catch ( ZErrorException $e ) {
114            return '';
115        }
116        return array_key_exists( $languageZid, $this->getZValue() )
117            ? $this->getZValue()[ $languageZid ]->getString()
118            : '';
119    }
120
121    /**
122     * Check if the ZMultiLingualString has a stored value for a given MediaWiki language code (e.g.
123     * 'en' or 'zh-hant'). Note that this is a raw check and does not walk the language fallback
124     * chain.
125     *
126     * @param string $languageCode The MediaWiki language code in which the string is wanted.
127     * @return bool If there is a string stored.
128     */
129    public function isLanguageProvidedValue( string $languageCode ): bool {
130        try {
131            $languageZid = ZLangRegistry::singleton()->getLanguageZidFromCode( $languageCode );
132        } catch ( ZErrorException $e ) {
133            return false;
134        }
135        return array_key_exists( $languageZid, $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRING_VALUE ] ?? [] );
136    }
137
138    /**
139     * Fetch the ZMultiLingualString's stored value for a given MediaWiki language class. This will
140     * walk the language fallback chain, and provide a fallback message if there is no label defined
141     * in the given language or any of its fallback languages.
142     *
143     * @param Language $language The MediaWiki language class in which the string is wanted.
144     * @return string|null The string, the value of the wikilambda-multilingualstring-nofallback message, or null.
145     */
146    public function getStringForLanguage( Language $language ): ?string {
147        return $this->buildStringForLanguage( $language )->placeholderNoFallback()->getString();
148    }
149
150    /**
151     * Instantiate a chained builder with which you can ask for a fallback in English,
152     * or define a placeholder. At the end, either call `getString()` or `getStringAndLanguageCode()`.
153     *
154     * @param Language $language
155     * @return StringForLanguageBuilder
156     */
157    public function buildStringForLanguage( Language $language ): StringForLanguageBuilder {
158        return new StringForLanguageBuilder( $language, $this );
159    }
160
161    /**
162     * @param ZMonoLingualString $value The new value to set.
163     */
164    public function setMonoLingualString( ZMonoLingualString $value ): void {
165        $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRING_VALUE ][ $value->getLanguage() ?? '' ] = $value;
166    }
167
168    /**
169     * @param Language $language The MediaWiki language class in which the string is to be set.
170     * @param string $value The new string to set.
171     */
172    public function setStringForLanguage( Language $language, string $value ): void {
173        $languageCode = $language->getCode();
174        $languageZid = ZLangRegistry::singleton()->getLanguageZidFromCode( $languageCode );
175        $monolingualString = new ZMonoLingualString( new ZReference( $languageZid ), new ZString( $value ) );
176        $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRING_VALUE ][ $languageZid ] = $monolingualString;
177    }
178
179    /**
180     * @param Language $language The MediaWiki language class in which the string is to be unset.
181     */
182    public function removeValue( Language $language ): void {
183        $languageCode = $language->getCode();
184        $languageZid = ZLangRegistry::singleton()->getLanguageZidFromCode( $languageCode );
185        unset( $this->data[ ZTypeRegistry::Z_MULTILINGUALSTRING_VALUE ][ $languageZid ] );
186    }
187}