StorageService::delete()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 3
c 2
b 0
f 0
nc 3
nop 3
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 12
rs 10
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\Model\Configuration;
17
use Translation\Common\Exception\LogicException;
18
use Translation\Common\Model\Message;
19
use Translation\Common\Model\MessageInterface;
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
32
    const DIRECTION_DOWN = 'down';
33
34
    /**
35
     * @var Storage[]
36
     */
37
    private $localStorages = [];
38
39
    /**
40
     * @var Storage[]
41
     */
42
    private $remoteStorages = [];
43
44
    private $catalogueFetcher;
45
    private $config;
46
47
    public function __construct(CatalogueFetcher $catalogueFetcher, Configuration $config)
48
    {
49
        $this->catalogueFetcher = $catalogueFetcher;
50
        $this->config = $config;
51
    }
52
53
    /**
54
     * Download catalogues from all storages.
55
     *
56
     * @return MessageCatalogue[]
57
     */
58
    public function download(array $exportOptions = []): array
59
    {
60
        $catalogues = [];
61
        foreach ($this->config->getLocales() as $locale) {
62
            $catalogues[$locale] = new MessageCatalogue($locale);
63
            foreach ($this->remoteStorages as $storage) {
64
                if ($storage instanceof TransferableStorage) {
65
                    $storage->export($catalogues[$locale], $exportOptions);
66
                }
67
            }
68
        }
69
70
        return $catalogues;
71
    }
72
73
    /**
74
     * Synchronize translations with remote.
75
     */
76
    public function sync(string $direction = self::DIRECTION_DOWN, array $importOptions = [], array $exportOptions = []): void
77
    {
78
        switch ($direction) {
79
            case self::DIRECTION_DOWN:
80
                $this->mergeDown($exportOptions);
81
                $this->mergeUp($importOptions);
82
83
                break;
84
            case self::DIRECTION_UP:
85
                $this->mergeUp($importOptions);
86
                $this->mergeDown($exportOptions);
87
88
                break;
89
            default:
90
                throw new LogicException(\sprintf('Direction must be either "up" or "down". Value "%s" was provided', $direction));
91
        }
92
    }
93
94
    /**
95
     * Download and merge all translations from remote storages down to your local storages.
96
     * Only the local storages will be changed.
97
     */
98
    public function mergeDown(array $exportOptions = []): void
99
    {
100
        $catalogues = $this->download($exportOptions);
101
102
        foreach ($catalogues as $locale => $catalogue) {
103
            foreach ($catalogue->all() as $domain => $messages) {
104
                foreach ($messages as $key => $translation) {
105
                    $message = new Message($key, $domain, $locale, $translation);
106
                    $this->updateStorages($this->localStorages, $message);
107
                }
108
            }
109
        }
110
    }
111
112
    /**
113
     * Upload and merge all translations from local storages up to your remote storages.
114
     * Only the remote storages will be changed.
115
     *
116
     * This will overwrite your remote copy.
117
     */
118
    public function mergeUp(array $importOptions = []): void
119
    {
120
        $catalogues = $this->catalogueFetcher->getCatalogues($this->config);
121
        foreach ($catalogues as $catalogue) {
122
            foreach ($this->remoteStorages as $storage) {
123
                if ($storage instanceof TransferableStorage) {
124
                    $storage->import($catalogue, $importOptions);
125
                }
126
            }
127
        }
128
    }
129
130
    /**
131
     * Get the very latest version we know of a message. First look at the remote storage
132
     * fall back on the local ones.
133
     */
134
    public function syncAndFetchMessage(string $locale, string $domain, string $key): ?Message
135
    {
136
        if (null === $message = $this->getFromStorages($this->remoteStorages, $locale, $domain, $key)) {
137
            // If message is not in remote storages, try local
138
            $message = $this->getFromStorages($this->localStorages, $locale, $domain, $key);
139
        }
140
141
        if (!$message) {
0 ignored issues
show
introduced by
$message is of type Translation\Common\Model\Message, thus it always evaluated to true.
Loading history...
142
            return null;
143
        }
144
145
        $this->updateStorages($this->localStorages, $message);
146
147
        return $message;
148
    }
149
150
    /**
151
     * Try to get a translation from all the storages, start looking in the first
152
     * local storage and then move on to the remote storages.
153
     * {@inheritdoc}
154
     */
155
    public function get(string $locale, string $domain, string $key): ?MessageInterface
156
    {
157
        foreach ([$this->localStorages, $this->remoteStorages] as $storages) {
158
            $value = $this->getFromStorages($storages, $locale, $domain, $key);
159
            if (null !== $value) {
160
                return $value;
161
            }
162
        }
163
164
        return null;
165
    }
166
167
    /**
168
     * @param Storage[] $storages
169
     */
170
    private function getFromStorages(array $storages, string $locale, string $domain, string $key): ?Message
171
    {
172
        foreach ($storages as $storage) {
173
            $value = $storage->get($locale, $domain, $key);
174
            if (null !== $value) {
175
                return $value;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $value returns the type Translation\Common\Model\MessageInterface which includes types incompatible with the type-hinted return Translation\Common\Model\Message|null.
Loading history...
176
            }
177
        }
178
179
        return null;
180
    }
181
182
    /**
183
     * Create all configured storages with this message. This will not overwrite
184
     * existing message.
185
     *
186
     * {@inheritdoc}
187
     */
188
    public function create(MessageInterface $message): void
189
    {
190
        // Validate if message actually has data
191
        if (empty((array) $message)) {
192
            return;
193
        }
194
195
        foreach ([$this->localStorages, $this->remoteStorages] as $storages) {
196
            /** @var Storage $storage */
197
            foreach ($storages as $storage) {
198
                $storage->create($message);
199
            }
200
        }
201
    }
202
203
    /**
204
     * Update all configured storages with this message. If messages does not exist
205
     * it will be created.
206
     *
207
     * {@inheritdoc}
208
     */
209
    public function update(MessageInterface $message): void
210
    {
211
        foreach ([$this->localStorages, $this->remoteStorages] as $storages) {
212
            $this->updateStorages($storages, $message);
213
        }
214
    }
215
216
    /**
217
     * @param Storage[] $storages
218
     */
219
    private function updateStorages(array $storages, MessageInterface $message): void
220
    {
221
        // Validate if message actually has data
222
        if (empty((array) $message)) {
223
            return;
224
        }
225
226
        foreach ($storages as $storage) {
227
            $storage->update($message);
228
        }
229
    }
230
231
    /**
232
     * Delete the message form all storages.
233
     *
234
     * {@inheritdoc}
235
     */
236
    public function delete(string $locale, string $domain, string $key): void
237
    {
238
        foreach ([$this->localStorages, $this->remoteStorages] as $storages) {
239
            /** @var Storage $storage */
240
            foreach ($storages as $storage) {
241
                $storage->delete($locale, $domain, $key);
242
            }
243
        }
244
    }
245
246
    public function addLocalStorage(Storage $localStorage): self
247
    {
248
        $this->localStorages[] = $localStorage;
249
250
        return $this;
251
    }
252
253
    public function addRemoteStorage(Storage $remoteStorage): self
254
    {
255
        $this->remoteStorages[] = $remoteStorage;
256
257
        return $this;
258
    }
259
}
260