1 | <?php declare (strict_types = 1); |
||
31 | class BundleStorage implements BundleStorageInterface |
||
32 | { |
||
33 | /** Encode index */ |
||
34 | const INDEX_DEFAULT_LOCALE = 0; |
||
35 | |||
36 | /** Encode index */ |
||
37 | const INDEX_DATA = self::INDEX_DEFAULT_LOCALE + 1; |
||
38 | |||
39 | /** |
||
40 | * @var array |
||
41 | */ |
||
42 | private $encodedStorage; |
||
43 | |||
44 | /** |
||
45 | * @var string[] |
||
46 | */ |
||
47 | private $locales; |
||
48 | |||
49 | /** |
||
50 | * @var string |
||
51 | */ |
||
52 | private $defaultLocale; |
||
53 | |||
54 | /** |
||
55 | * @param array $encodedStorage |
||
56 | */ |
||
57 | 7 | public function __construct(array $encodedStorage) |
|
58 | { |
||
59 | 7 | $this->setEncodedStorage($encodedStorage); |
|
60 | } |
||
61 | |||
62 | /** |
||
63 | * @inheritdoc |
||
64 | */ |
||
65 | 7 | public function has(string $locale, string $namespace, string $key): bool |
|
66 | { |
||
67 | 7 | assert(empty($locale) === false && empty($namespace) === false && empty($key) === false); |
|
68 | |||
69 | 7 | $has = isset($this->getEncodedStorage()[$locale][$namespace][$key]); |
|
70 | |||
71 | 7 | return $has; |
|
72 | } |
||
73 | |||
74 | /** |
||
75 | * @inheritdoc |
||
76 | */ |
||
77 | 7 | public function get(string $locale, string $namespace, string $key): ?array |
|
78 | { |
||
79 | 7 | $locale = $this->lookupLocale($this->getLocales(), $locale, $this->getDefaultLocale()); |
|
80 | |||
81 | 7 | $result = $this->has($locale, $namespace, $key) === true ? |
|
82 | 7 | $this->getEncodedStorage()[$locale][$namespace][$key] : null; |
|
83 | |||
84 | 7 | assert($result === null || $this->checkValueWithLocale($result) === true); |
|
85 | |||
86 | 7 | return $result; |
|
87 | } |
||
88 | |||
89 | /** |
||
90 | * @inheritdoc |
||
91 | */ |
||
92 | 1 | public function hasResources(string $locale, string $namespace): bool |
|
93 | { |
||
94 | 1 | assert(empty($locale) === false && empty($namespace) === false); |
|
95 | |||
96 | 1 | $has = isset($this->getEncodedStorage()[$locale][$namespace]); |
|
97 | |||
98 | 1 | return $has; |
|
99 | } |
||
100 | |||
101 | /** |
||
102 | * @inheritdoc |
||
103 | */ |
||
104 | 1 | public function getResources(string $locale, string $namespace): array |
|
105 | { |
||
106 | 1 | $locale = $this->lookupLocale($this->getLocales(), $locale, $this->getDefaultLocale()); |
|
107 | |||
108 | 1 | assert($this->hasResources($locale, $namespace) === true); |
|
109 | |||
110 | 1 | $result = $this->getEncodedStorage()[$locale][$namespace]; |
|
111 | |||
112 | 1 | return $result; |
|
113 | } |
||
114 | |||
115 | /** |
||
116 | * @inheritdoc |
||
117 | */ |
||
118 | 7 | public function getDefaultLocale(): string |
|
119 | { |
||
120 | 7 | return $this->defaultLocale; |
|
121 | } |
||
122 | |||
123 | /** |
||
124 | * @return array |
||
125 | */ |
||
126 | 7 | protected function getEncodedStorage(): array |
|
127 | { |
||
128 | 7 | return $this->encodedStorage; |
|
129 | } |
||
130 | |||
131 | /** |
||
132 | * @param string[] $locales |
||
133 | * @param string $locale |
||
134 | * @param string $defaultLocale |
||
135 | * |
||
136 | * @return string |
||
137 | */ |
||
138 | 7 | protected function lookupLocale(array $locales, string $locale, string $defaultLocale): string |
|
139 | { |
||
140 | // for some odd reason locale_lookup returns empty string but not default locale if input locales are empty |
||
141 | 7 | return empty($locales) === true ? $defaultLocale : locale_lookup($locales, $locale, false, $defaultLocale); |
|
142 | } |
||
143 | |||
144 | /** |
||
145 | * @return string[] |
||
146 | */ |
||
147 | 7 | protected function getLocales(): array |
|
148 | { |
||
149 | 7 | return $this->locales; |
|
150 | } |
||
151 | |||
152 | /** |
||
153 | * @param array $encodedStorage |
||
154 | * |
||
155 | * @return self |
||
156 | */ |
||
157 | 7 | protected function setEncodedStorage(array $encodedStorage): self |
|
158 | { |
||
159 | 7 | assert(count($encodedStorage) === 2); |
|
160 | |||
161 | 7 | $encodedData = $encodedStorage[static::INDEX_DATA]; |
|
162 | |||
163 | // check storage has 3 levels locale -> namespace -> key & value + culture pairs and |
||
164 | // keys, values and cultures are non-empty strings |
||
165 | 7 | assert(is_array($encodedData) === true && $this->checkEncodedData($encodedData) === true); |
|
166 | |||
167 | 7 | $this->defaultLocale = $encodedStorage[static::INDEX_DEFAULT_LOCALE]; |
|
168 | 7 | $this->encodedStorage = $encodedData; |
|
169 | 7 | $this->locales = array_keys($encodedData); |
|
|
|||
170 | |||
171 | 7 | return $this; |
|
172 | } |
||
173 | |||
174 | /** |
||
175 | * @param array $encodedData |
||
176 | * |
||
177 | * @return bool |
||
178 | */ |
||
179 | 7 | private function checkEncodedData(array $encodedData): bool |
|
180 | { |
||
181 | 7 | $isValid = true; |
|
182 | 7 | foreach ($encodedData as $locale => $namespaceResources) { |
|
183 | 7 | $isValid = $isValid === true && |
|
184 | 7 | empty($locale) === false && |
|
185 | 7 | is_array($namespaceResources) === true && $this->checkNamespaceResources($namespaceResources); |
|
186 | } |
||
187 | |||
188 | 7 | return $isValid; |
|
189 | } |
||
190 | |||
191 | /** |
||
192 | * @param array $namespaceResources |
||
193 | * |
||
194 | * @return bool |
||
195 | */ |
||
196 | 7 | private function checkNamespaceResources(array $namespaceResources): bool |
|
197 | { |
||
198 | 7 | $isValid = true; |
|
199 | 7 | foreach ($namespaceResources as $namespace => $resources) { |
|
200 | 7 | $isValid = $isValid === true && |
|
201 | 7 | empty($namespace) === false && |
|
202 | 7 | is_array($resources) === true && $this->checkResources($resources); |
|
203 | } |
||
204 | |||
205 | 7 | return $isValid; |
|
206 | } |
||
207 | |||
208 | /** |
||
209 | * @param array $resources |
||
210 | * |
||
211 | * @return bool |
||
212 | */ |
||
213 | 7 | private function checkResources(array $resources): bool |
|
214 | { |
||
215 | 7 | $isValid = true; |
|
216 | 7 | foreach ($resources as $key => $valueAndLocale) { |
|
217 | 7 | $isValid = $isValid === true && $this->checkPair($key, $valueAndLocale); |
|
218 | } |
||
219 | |||
220 | 7 | return $isValid; |
|
221 | } |
||
222 | |||
223 | /** |
||
224 | * @param string $key |
||
225 | * @param array $valueAndLocale |
||
226 | * |
||
227 | * @return bool |
||
228 | */ |
||
229 | 7 | private function checkPair(string $key, array $valueAndLocale): bool |
|
230 | { |
||
231 | 7 | $result = empty($key) === false && $this->checkValueWithLocale($valueAndLocale) === true; |
|
232 | |||
233 | 7 | return $result; |
|
234 | } |
||
235 | |||
236 | /** |
||
237 | * @param array $valueAndLocale |
||
238 | * |
||
239 | * @return bool |
||
240 | */ |
||
241 | 7 | private function checkValueWithLocale(array $valueAndLocale): bool |
|
250 | } |
||
251 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..