Completed
Push — develop ( bdb11d...45f5c6 )
by Neomerx
04:46
created

BundleEncoder::assertLocale()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 1
nop 1
crap 2
1
<?php namespace Limoncello\l10n\Messages;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Limoncello\l10n\Contracts\Messages\BundleEncoderInterface;
20
use Limoncello\l10n\Contracts\Messages\BundleStorageInterface;
21
use Limoncello\l10n\Contracts\Messages\ResourceBundleInterface;
22
23
/**
24
 * @package Limoncello\l10n
25
 */
26
class BundleEncoder implements BundleEncoderInterface
27
{
28
    /**
29
     * @var array
30
     */
31
    private $bundles = [];
32
33
    /**
34
     * @inheritdoc
35
     */
36 5
    public function addBundle(ResourceBundleInterface $bundle): BundleEncoderInterface
37
    {
38 5
        assert($this->hasLocalizedNamespace($bundle->getLocale(), $bundle->getNamespace()) === false);
39
40 5
        $this->bundles[$bundle->getLocale()][$bundle->getNamespace()] = $bundle;
41
42 5
        return $this;
43
    }
44
45
    /**
46
     * @inheritdoc
47
     */
48 5
    public function getStorageData(string  $defaultLocale): array
49
    {
50 5
        $defaultNamespaces = $this->getNamespaces($defaultLocale);
51
52 5
        $data = [];
53 5
        foreach ($this->getLocales() as $locale) {
54 5
            $localizedNamespaces = $this->getNamespaces($locale);
55 5
            $combinedNamespaces  = $defaultNamespaces + $localizedNamespaces;
56 5
            foreach ($combinedNamespaces as $namespace) {
57 5
                $bundle = $this->getBundle($locale, $namespace);
58 5
                $bundle = $bundle !== null ? $bundle : $this->getBundle($defaultLocale, $namespace);
59 5
                $data[$locale][$namespace] = $defaultLocale === $locale ? $this->encodeBundle($bundle) :
60 5
                    $this->encodeMergedBundles($bundle, $this->getBundle($defaultLocale, $namespace));
61
            }
62
        }
63
64
        return [
65 5
            BundleStorage::INDEX_DEFAULT_LOCALE => $defaultLocale,
66 5
            BundleStorage::INDEX_DATA           => $data
67
        ];
68
    }
69
70
    /**
71
     * @return array
72
     */
73 5
    protected function getBundles(): array
74
    {
75 5
        return $this->bundles;
76
    }
77
78
    /**
79
     * @param ResourceBundleInterface $bundle
80
     *
81
     * @return array
82
     */
83 5
    private function encodeBundle(ResourceBundleInterface $bundle): array
84
    {
85 5
        $encodedBundle = [];
86 5
        foreach ($bundle->getKeys() as $key) {
87 5
            $encodedBundle[$key] = $this->getBundleValue($bundle, $key);
88
        }
89
90 5
        return $encodedBundle;
91
    }
92
93
    /**
94
     * @param string $locale
95
     * @param string $namespace
96
     *
97
     * @return null|ResourceBundleInterface
98
     */
99 5
    private function getBundle(string $locale, string $namespace)
100
    {
101 5
        $this->assertLocale($locale);
102 5
        $this->assertNamespace($namespace);
103
104 5
        $bundles   = $this->getBundles();
105 5
        $hasBundle = isset($bundles[$locale][$namespace]) === true;
106 5
        $result    = $hasBundle === true ? $bundles[$locale][$namespace] : null;
107
108 5
        return $result;
109
    }
110
111
    /**
112
     * @param ResourceBundleInterface      $localizedBundle
113
     * @param ResourceBundleInterface|null $defaultBundle
114
     *
115
     * @return array
116
     */
117 5
    private function encodeMergedBundles(
118
        ResourceBundleInterface $localizedBundle,
119
        ResourceBundleInterface $defaultBundle = null
120
    ): array {
121 5
        if ($defaultBundle === null) {
122
            // there is no default bundle for this localized one
123 4
            return $this->encodeBundle($localizedBundle);
124
        }
125
126 2
        $localizedKeys = $localizedBundle->getKeys();
127 2
        $defaultKeys   = $defaultBundle->getKeys();
128
129 2
        $commonKeys        = array_intersect($localizedKeys, $defaultKeys);
130 2
        $localizedOnlyKeys = array_diff($localizedKeys, $commonKeys);
131 2
        $defaultOnlyKeys   = array_diff($defaultKeys, $commonKeys);
132
133 2
        $encodedBundle = [];
134
135 2
        foreach ($commonKeys as $key) {
136 2
            $encodedBundle[$key] = $this->getBundleValue($localizedBundle, $key);
137
        }
138 2
        foreach ($localizedOnlyKeys as $key) {
139 1
            $encodedBundle[$key] = $this->getBundleValue($localizedBundle, $key);
140
        }
141 2
        foreach ($defaultOnlyKeys as $key) {
142 1
            $encodedBundle[$key] = $this->getBundleValue($defaultBundle, $key);
143
        }
144
145 2
        return $encodedBundle;
146
    }
147
148
    /**
149
     * @return array
150
     */
151 5
    private function getLocales(): array
152
    {
153 5
        return array_keys($this->getBundles());
154
    }
155
156
    /**
157
     * @param string $locale
158
     *
159
     * @return bool
160
     */
161 5
    private function hasLocale(string $locale): bool
162
    {
163 5
        $this->assertLocale($locale);
164 5
        $result = in_array($locale, $this->getLocales());
165
166 5
        return $result;
167
    }
168
169
    /**
170
     * @param string $locale
171
     *
172
     * @return string[]
173
     */
174 5
    private function getNamespaces(string $locale): array
175
    {
176 5
        $result = $this->hasLocale($locale) === true ? array_keys($this->getBundles()[$locale]) : [];
177
178 5
        return $result;
179
    }
180
181
    /**
182
     * @param string $locale
183
     * @param string $namespace
184
     *
185
     * @return bool
186
     */
187 5
    private function hasLocalizedNamespace(string $locale, string $namespace): bool
188
    {
189 5
        $this->assertNamespace($namespace);
190
191 5
        $result = in_array($namespace, $this->getNamespaces($locale));
192
193 5
        return $result;
194
    }
195
196
    /**
197
     * @param string $locale
198
     *
199
     * @return void
200
     */
201 5
    private function assertLocale(string $locale)
202
    {
203 5
        assert(is_string($locale) === true && empty($locale) === false);
204
    }
205
206
    /**
207
     * @param string $namespace
208
     *
209
     * @return void
210
     */
211 5
    private function assertNamespace(string $namespace)
212
    {
213 5
        assert(empty($namespace) === false);
214
    }
215
216
    /**
217
     * @param ResourceBundleInterface $bundle
218
     * @param string                  $key
219
     *
220
     * @return string[]
221
     */
222 5
    private function getBundleValue(ResourceBundleInterface $bundle, $key): array
223
    {
224
        return [
225 5
            BundleStorageInterface::INDEX_PAIR_VALUE  => $bundle->getValue($key),
226 5
            BundleStorageInterface::INDEX_PAIR_LOCALE => $bundle->getLocale(),
227
        ];
228
    }
229
}
230