Completed
Push — master ( 740372...dc5b6e )
by Tobias
10:09
created

StorageService::delete()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 7
cts 7
cp 1
rs 9.6666
c 0
b 0
f 0
cc 3
eloc 4
nc 3
nop 3
crap 3
1
<?php
2
3
/*
4
 * This file is part of the PHP Translation package.
5
 *
6
 * (c) PHP Translation team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Translation\Bundle\Service;
13
14
use Symfony\Component\Translation\MessageCatalogue;
15
use Translation\Bundle\Catalogue\CatalogueFetcher;
16
use Translation\Bundle\Catalogue\CatalogueWriter;
17
use Translation\Bundle\Model\Configuration;
18
use Translation\Common\Exception\LogicException;
19
use Translation\Common\Model\Message;
20
use Translation\Common\Storage;
21
use Translation\Common\TransferableStorage;
22
23
/**
24
 * A service that you use to handle the storages.
25
 *
26
 * @author Tobias Nyholm <[email protected]>
27
 */
28
final class StorageService implements Storage
29
{
30
    const DIRECTION_UP = 'up';
31
    const DIRECTION_DOWN = 'down';
32
33
    /**
34
     * @var Storage[]
35
     */
36
    private $localStorages = [];
37
38
    /**
39
     * @var Storage[]
40
     */
41
    private $remoteStorages = [];
42
43
    /**
44
     * @var CatalogueFetcher
45
     */
46
    private $catalogueFetcher;
47
48
    /**
49
     * @var CatalogueWriter
50
     */
51
    private $catalogueWriter;
52
53
    /**
54
     * @var Configuration
55
     */
56
    private $config;
57
58
    /**
59
     * @param CatalogueFetcher $catalogueFetcher
60
     * @param CatalogueWriter  $catalogueWriter
61
     * @param Configuration    $config
62
     */
63 4
    public function __construct(
64
        CatalogueFetcher $catalogueFetcher,
65
        CatalogueWriter $catalogueWriter,
66
        Configuration $config
67
    ) {
68 4
        $this->catalogueFetcher = $catalogueFetcher;
69 4
        $this->catalogueWriter = $catalogueWriter;
70 4
        $this->config = $config;
71 4
    }
72
73
    /**
74
     * Download all remote storages into all local storages.
75
     * This will overwrite your local copy.
76
     */
77
    public function download()
78
    {
79
        $catalogues = $this->doDownload();
80
81
        $this->catalogueWriter->writeCatalogues($this->config, $catalogues);
82
    }
83
84
    /**
85
     * Synchronize translations with remote.
86
     */
87
    public function sync($direction = self::DIRECTION_DOWN)
88
    {
89
        switch ($direction) {
90
            case self::DIRECTION_DOWN:
91
                $this->mergeDown();
92
                $this->mergeUp();
93
94
                break;
95
            case self::DIRECTION_UP:
96
                $this->mergeUp();
97
                $this->mergeDown();
98
99
                break;
100
            default:
101
                throw new LogicException(sprintf('Direction must be either "up" or "down". Value "%s" was provided', $direction));
102
        }
103
    }
104
105
    /**
106
     * Download and merge all translations from remote storages down to your local storages.
107
     * Only the local storages will be changed.
108
     */
109
    public function mergeDown()
110
    {
111
        $catalogues = $this->doDownload();
112
113
        foreach ($catalogues as $locale => $catalogue) {
114
            foreach ($catalogue->all() as $domain => $messages) {
115
                foreach ($messages as $key => $translation) {
116
                    $message = new Message($key, $domain, $locale, $translation);
117
                    $this->updateStorages($this->localStorages, $message);
118
                }
119
            }
120
        }
121
    }
122
123
    /**
124
     * Upload and merge all translations from local storages up to your remote storages.
125
     * Only the remote storages will be changed.
126
     *
127
     * This will overwrite your remote copy.
128
     */
129
    public function mergeUp()
130
    {
131
        $catalogues = $this->catalogueFetcher->getCatalogues($this->config);
132
        foreach ($catalogues as $catalogue) {
133
            foreach ($this->remoteStorages as $storage) {
134
                if ($storage instanceof TransferableStorage) {
135
                    $storage->import($catalogue);
136
                }
137
            }
138
        }
139
    }
140
141
    /**
142
     * Get the very latest version we know of a message. First look at the remote storage
143
     * fall back on the local ones.
144
     *
145
     * @param string $locale
146
     * @param string $domain
147
     * @param string $key
148
     *
149
     * @return null|Message
150
     */
151
    public function syncAndFetchMessage($locale, $domain, $key)
152
    {
153
        if (null === $message = $this->getFromStorages($this->remoteStorages, $locale, $domain, $key)) {
154
            // If message is not in remote storages, try local
155
            $message = $this->getFromStorages($this->localStorages, $locale, $domain, $key);
156
        }
157
158
        if (!$message) {
159
            return;
160
        }
161
162
        $this->updateStorages($this->localStorages, $message);
163
164
        return $message;
165
    }
166
167
    /**
168
     * Try to get a translation from all the storages, start looking in the first
169
     * local storage and then move on to the remote storages.
170
     * {@inheritdoc}
171
     */
172
    public function get($locale, $domain, $key)
173
    {
174
        foreach ([$this->localStorages, $this->remoteStorages] as $storages) {
175
            $value = $this->getFromStorages($storages, $locale, $domain, $key);
176
            if (!empty($value)) {
177
                return $value;
178
            }
179
        }
180
181
        return;
182
    }
183
184
    /**
185
     * @param Storage[] $storages
186
     * @param string    $locale
187
     * @param string    $domain
188
     * @param string    $key
189
     *
190
     * @return null|Message
191
     */
192
    private function getFromStorages(array $storages, $locale, $domain, $key)
193
    {
194
        foreach ($storages as $storage) {
195
            $value = $storage->get($locale, $domain, $key);
196
            if (!empty($value)) {
197
                return $value;
198
            }
199
        }
200
201
        return;
202
    }
203
204
    /**
205
     * Create all configured storages with this message. This will not overwrite
206
     * existing message.
207
     *
208
     * {@inheritdoc}
209
     */
210 1
    public function create(Message $message)
211
    {
212
        // Validate if message actually has data
213 1
        if (empty((array) $message)) {
214
            return;
215
        }
216
217 1
        foreach ([$this->localStorages, $this->remoteStorages] as $storages) {
218
            /** @var Storage $storage */
219 1
            foreach ($storages as $storage) {
220 1
                $storage->create($message);
221 1
            }
222 1
        }
223 1
    }
224
225
    /**
226
     * Update all configured storages with this message. If messages does not exist
227
     * it will be created.
228
     *
229
     * {@inheritdoc}
230
     */
231 1
    public function update(Message $message)
232
    {
233 1
        foreach ([$this->localStorages, $this->remoteStorages] as $storages) {
234 1
            $this->updateStorages($storages, $message);
235 1
        }
236 1
    }
237
238
    /**
239
     * @param Storage[] $storages
240
     * @param Message   $message
241
     */
242 1
    private function updateStorages(array $storages, Message $message)
243
    {
244
        // Validate if message actually has data
245 1
        if (empty((array) $message)) {
246
            return;
247
        }
248
249 1
        foreach ($storages as $storage) {
250 1
            $storage->update($message);
251 1
        }
252 1
    }
253
254
    /**
255
     * Delete the message form all storages.
256
     *
257
     * {@inheritdoc}
258
     */
259 1
    public function delete($locale, $domain, $key)
260
    {
261 1
        foreach ([$this->localStorages, $this->remoteStorages] as $storages) {
262
            /** @var Storage $storage */
263 1
            foreach ($storages as $storage) {
264 1
                $storage->delete($locale, $domain, $key);
265 1
            }
266 1
        }
267 1
    }
268
269
    /**
270
     * @param Storage $localStorage
271
     *
272
     * @return StorageService
273
     */
274 4
    public function addLocalStorage(Storage $localStorage)
275
    {
276 4
        $this->localStorages[] = $localStorage;
277
278 4
        return $this;
279
    }
280
281
    /**
282
     * @param Storage $remoteStorage
283
     *
284
     * @return StorageService
285
     */
286
    public function addRemoteStorage(Storage $remoteStorage)
287
    {
288
        $this->remoteStorages[] = $remoteStorage;
289
290
        return $this;
291
    }
292
293
    /**
294
     * Download catalogues from all storages.
295
     *
296
     * @return MessageCatalogue[]
297
     */
298
    private function doDownload()
299
    {
300
        $catalogues = [];
301
        foreach ($this->config->getLocales() as $locale) {
302
            $catalogues[$locale] = new MessageCatalogue($locale);
303
            foreach ($this->remoteStorages as $storage) {
304
                if ($storage instanceof TransferableStorage) {
305
                    $storage->export($catalogues[$locale]);
306
                }
307
            }
308
        }
309
310
        return $catalogues;
311
    }
312
}
313