Completed
Push — develop ( 0d976a...21f0a6 )
by ARCANEDEV
13:35 queued 12:35
created

TransPublisher::publishJson()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 6.4222

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 8
cts 13
cp 0.6153
rs 9.2728
c 0
b 0
f 0
cc 5
nc 3
nop 3
crap 6.4222
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arcanedev\LaravelLang;
6
7
use Arcanedev\LaravelLang\Contracts\TransPublisher as TransPublisherContract;
8
use Arcanedev\LaravelLang\Contracts\TransManager as TransManagerContract;
9
use Arcanedev\LaravelLang\Exceptions\LangPublishException;
10
use Illuminate\Filesystem\Filesystem;
11
use Illuminate\Support\Str;
12
use SplFileInfo;
13
14
/**
15
 * Class     TransPublisher
16
 *
17
 * @package  Arcanedev\LaravelLang
18
 * @author   ARCANEDEV <[email protected]>
19
 */
20
class TransPublisher implements TransPublisherContract
21
{
22
    /* -----------------------------------------------------------------
23
     |  Properties
24
     | -----------------------------------------------------------------
25
     */
26
27
    /**
28
     * The filesystem instance.
29
     *
30
     * @var \Illuminate\Filesystem\Filesystem
31
     */
32
    private $filesystem;
33
34
    /**
35
     * The TransManager instance.
36
     *
37
     * @var \Arcanedev\LaravelLang\Contracts\TransManager
38
     */
39
    private $manager;
40
41
    /**
42
     * Available locales.
43
     *
44
     * @var \Arcanedev\LaravelLang\Entities\LocaleCollection
45
     */
46
    private $locales;
47
48
    /**
49
     * The application lang path.
50
     *
51
     * @var string
52
     */
53
    private $langPath;
54
55
    /**
56
     * Publish's results.
57
     *
58
     * @var array
59
     */
60
    private $results = [];
61
62
    /* -----------------------------------------------------------------
63
     |  Constructor
64
     | -----------------------------------------------------------------
65
     */
66
67
    /**
68
     * Make TransPublisher instance.
69
     *
70
     * @param  \Illuminate\Filesystem\Filesystem              $filesystem
71
     * @param  \Arcanedev\LaravelLang\Contracts\TransManager  $manager
72
     * @param  string                                         $langPath
73
     */
74 56
    public function __construct(Filesystem $filesystem, TransManagerContract $manager, string $langPath)
75
    {
76 56
        $this->filesystem = $filesystem;
77 56
        $this->manager    = $manager;
78 56
        $this->langPath   = realpath($langPath);
79
80 56
        $this->init();
81 56
    }
82
83
    /**
84
     * Start the engine.
85
     */
86 56
    private function init(): void
87
    {
88 56
        $this->locales = $this->manager->getCollection('vendor-php');
89 56
    }
90
91
    /* -----------------------------------------------------------------
92
     |  Getters & Setters
93
     | -----------------------------------------------------------------
94
     */
95
96
    /**
97
     * Get the locale destination path.
98
     *
99
     * @param  string  $locale
100
     *
101
     * @return string
102
     */
103 32
    private function getDestinationPath(string $locale): string
104
    {
105 32
        return $this->langPath.DIRECTORY_SEPARATOR.$locale;
106
    }
107
108
    /**
109
     * Get a locale from the collection.
110
     *
111
     * @param  string  $key
112
     * @param  mixed   $default
113
     *
114
     * @return \Arcanedev\LaravelLang\Entities\Locale|mixed
115
     */
116 32
    private function getLocale(string $key, $default = null)
117
    {
118 32
        return $this->locales->get($key, $default);
119
    }
120
121
    /* -----------------------------------------------------------------
122
     |  Main Methods
123
     | -----------------------------------------------------------------
124
     */
125
126
    /**
127
     * Publish a lang.
128
     *
129
     * @param  string  $locale
130
     * @param  array   $options
131
     *
132
     * @return array
133
     */
134 40
    public function publish(string $locale, array $options = []): array
135
    {
136 40
        $this->resetResults();
137
138 40
        $locale = trim($locale);
139
140 40
        if ($this->isDefault($locale)) {
141 4
            $this->results['skipped'][] = $locale;
142
143 4
            return $this->results;
144
        }
145
146 36
        $this->checkLocale($locale);
147
148 32
        $source      = $this->getLocale($locale)->getPath();
149 32
        $destination = $this->getDestinationPath($locale);
150
151 32
        $this->filesystem->ensureDirectoryExists($destination);
152
153
        // Publish the PHP Translations
154 32
        foreach ($this->filesystem->files($source) as $file) {
155 32
            $this->publishFile($file, $locale, $destination, $options);
156
        }
157
158
        // Publish the JSON Translation
159 32
        if ($options['json'] ?? false) {
160 4
            $this->publishJson($locale, $destination);
161
        }
162
163 32
        return $this->results;
164
    }
165
166
    /**
167
     * Publish the json file.
168
     *
169
     * @param  string  $locale
170
     * @param  string  $destination
171
     * @param  array   $options
172
     *
173
     * @return bool
174
     */
175 4
    private function publishJson(string $locale, string $destination, array $options = []): bool
176
    {
177 4
        $file = $this->manager->getCollection('vendor-json')->get($locale);
178
179 4
        if (is_null($file)) {
180
            $this->results['skipped'][] = "{$locale}.json";
181
            return false;
182
        }
183
184 4
        if ($this->filesystem->exists($destFile = $destination.'.json') && ($options['force'] ?? false) === false) {
185
            $this->results['skipped'][] = "{$locale}.json";
186
            return false;
187
        }
188
189 4
        return tap($this->filesystem->copy($file->getPath(), $destFile), function (bool $published) use ($locale) {
190 4
            if ($published)
191 4
                $this->results['published'][] = "{$locale}.json";
192
            else
193
                $this->results['skipped'][] = "{$locale}.json";
194 4
        });
195
    }
196
197
    /* -----------------------------------------------------------------
198
     |  Check Methods
199
     | -----------------------------------------------------------------
200
     */
201
202
    /**
203
     * Check if the locale is a default one (English is shipped with laravel).
204
     *
205
     * @param  string  $locale
206
     *
207
     * @return bool
208
     */
209 44
    public function isDefault(string $locale): bool
210
    {
211 44
        return $locale === 'en';
212
    }
213
214
    /**
215
     * Check if the locale is supported.
216
     *
217
     * @param  string  $key
218
     *
219
     * @return bool
220
     */
221 36
    public function isSupported(string $key): bool
222
    {
223 36
        return $this->locales->has($key);
224
    }
225
226
    /**
227
     * Check if the locale is supported or fail.
228
     *
229
     * @param  string  $locale
230
     *
231
     * @throws \Arcanedev\LaravelLang\Exceptions\LangPublishException
232
     */
233 36
    private function checkLocale(string $locale): void
234
    {
235 36
        if ( ! $this->isSupported($locale)) {
236 4
            throw new LangPublishException("The locale [$locale] is not supported.");
237
        }
238 32
    }
239
240
    /* -----------------------------------------------------------------
241
     |  Other Methods
242
     | -----------------------------------------------------------------
243
     */
244
245
    /**
246
     * Publish the translation file.
247
     *
248
     * @param  SplFileInfo  $file
249
     * @param  string       $locale
250
     * @param  string       $destination
251
     * @param  array        $options
252
     */
253 32
    private function publishFile(SplFileInfo $file, string $locale, string $destination, array $options): void
254
    {
255 32
        $isInlineFile = Str::endsWith($file->getFilename(), '-inline.php');
256 32
        $destFile = $isInlineFile
257 32
            ? Str::replaceLast('-inline.php', '.php', $file->getFilename())
258 32
            : $file->getFilename();
259
260 32
        if ($this->isInResults($key = "{$locale}/{$destFile}"))
261 4
            return;
262
263
        // Ignore if inline option is not enabled
264 32
        if ($isInlineFile && (($options['inline'] ?? false) === false))
265 28
            return;
266
267
        // Ignore if force option is not enabled
268 32
        if ($this->filesystem->exists($destination.DIRECTORY_SEPARATOR.$destFile) && ($options['force'] ?? false) === false) {
269 8
            $this->results['skipped'][] = $key;
270 8
            return;
271
        }
272
273 32
        $this->filesystem->copy($file->getRealPath(), $destination.DIRECTORY_SEPARATOR.$destFile);
274 32
        $this->results['published'][] = $key;
275 32
    }
276
277
    /**
278
     * Reset the publish results.
279
     */
280 40
    private function resetResults(): void
281
    {
282 40
        $this->results = [
283
            'published' => [],
284
            'skipped'   => [],
285
        ];
286 40
    }
287
288
    /**
289
     * Check if the given key exists in results.
290
     *
291
     * @param  string  $key
292
     *
293
     * @return bool
294
     */
295 32
    private function isInResults(string $key): bool
296
    {
297 32
        return in_array($key, $this->results['published'])
298 32
            || in_array($key, $this->results['skipped']);
299
    }
300
}
301