Completed
Push — develop ( 6d6fd1...6374f4 )
by Neomerx
23:45
created

BundleStorage::checkNamespaceResources()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.6111
c 0
b 0
f 0
cc 5
nc 5
nop 1
crap 5
1
<?php declare (strict_types = 1);
2
3
namespace Limoncello\l10n\Messages;
4
5
/**
6
 * Copyright 2015-2019 [email protected]
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 * http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
use function assert;
22
use function array_keys;
23
use function count;
24
use function locale_lookup;
25
use function is_array;
26
use Limoncello\l10n\Contracts\Messages\BundleStorageInterface;
27
28
/**
29
 * @package Limoncello\l10n
30
 */
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);
0 ignored issues
show
Documentation Bug introduced by
It seems like \array_keys($encodedData) of type array<integer,integer|string> is incompatible with the declared type array<integer,string> of property $locales.

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..

Loading history...
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
242
    {
243
        $result =
244 7
            count($valueAndLocale) === 2 &&
245 7
            empty($valueAndLocale[static::INDEX_PAIR_VALUE]) === false &&
246 7
            empty($valueAndLocale[static::INDEX_PAIR_LOCALE]) === false;
247
248 7
        return $result;
249
    }
250
}
251