TransPublisher::publishFile()   B
last analyzed

Complexity

Conditions 7
Paths 8

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7

Importance

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