Completed
Pull Request — master (#89)
by
unknown
65:00
created

Import   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 323
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 36
c 0
b 0
f 0
lcom 1
cbo 5
dl 0
loc 323
rs 8.8

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
A import() 0 8 1
A getTranslations() 0 8 2
B writeToStorage() 0 23 5
A importAppTranslationFiles() 0 5 1
A importBundlesTranslationFiles() 0 10 3
A importBundleTranslationFiles() 0 5 1
A importComponentTranslationFiles() 0 21 3
B findTranslationsFiles() 0 21 5
A getFileNamePattern() 0 19 2
A importTranslationFiles() 0 8 3
A getDomains() 0 4 1
A setDomains() 0 4 1
A getLocales() 0 4 1
A setLocales() 0 4 1
A getFormats() 0 4 1
A setFormats() 0 4 1
A getFinder() 0 4 1
A getConfigBundles() 0 4 1
A getBundles() 0 4 1
1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[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 ONGR\TranslationsBundle\Service\Import;
13
14
use Elasticsearch\Common\Exceptions\BadRequest400Exception;
15
use ONGR\ElasticsearchBundle\Service\Manager;
16
use ONGR\TranslationsBundle\Document\Message;
17
use ONGR\TranslationsBundle\Document\Translation;
18
use Symfony\Component\Finder\Finder;
19
20
/**
21
 * Collects translations.
22
 */
23
class Import
24
{
25
    /**
26
     * @var FileImport
27
     */
28
    private $fileImport;
29
30
    /**
31
     * @var array
32
     */
33
    private $locales;
34
35
    /**
36
     * @var array
37
     */
38
    private $domains;
39
40
    /**
41
     * @var string
42
     */
43
    private $kernelDir;
44
45
    /**
46
     * @var array
47
     */
48
    private $bundles;
49
50
    /**
51
     * @var array
52
     */
53
    private $formats;
54
55
    /**
56
     * @var array
57
     */
58
    private $translations = [];
59
60
    /**
61
     * @var Manager
62
     */
63
    private $esManager;
64
65
    /**
66
     * @var array
67
     */
68
    private $configBundles;
69
70
    /**
71
     * @param FileImport $fileImport
72
     * @param Manager    $esManager
73
     * @param string     $kernelDir
74
     * @param array      $kernelBundles
75
     * @param array      $configBundles
76
     */
77
    public function __construct(
78
        FileImport $fileImport,
79
        Manager $esManager,
80
        $kernelDir,
81
        $kernelBundles,
82
        $configBundles
83
    ) {
84
        $this->fileImport = $fileImport;
85
        $this->esManager = $esManager;
86
        $this->kernelDir = $kernelDir;
87
        $this->bundles = $kernelBundles;
88
        $this->configBundles = $configBundles;
89
    }
90
91
    /**
92
     * Collects translations.
93
     */
94
    public function import()
95
    {
96
        $this->importAppTranslationFiles();
97
98
        $this->importBundlesTranslationFiles(array_merge($this->getConfigBundles(), $this->getBundles()));
99
100
        $this->importComponentTranslationFiles();
101
    }
102
103
    /**
104
     * Returns all translations as array.
105
     *
106
     * @return array
107
     */
108
    public function getTranslations()
109
    {
110
        if (empty($this->translations)) {
111
            $this->import();
112
        }
113
114
        return $this->translations;
115
    }
116
117
    /**
118
     * Write translations to storage.
119
     */
120
    public function writeToStorage()
121
    {
122
        foreach ($this->translations as $path => $domains) {
123
            foreach ($domains as $domain => $transMeta) {
124
                foreach ($transMeta['translations'] as $key => $keyTrans) {
125
                    $document = new Translation();
126
                    $document->setDomain($domain);
127
                    $document->setKey($key);
128
                    $document->setPath($path);
129
                    $document->setFormat($transMeta['format']);
130
                    foreach ($keyTrans as $locale => $trans) {
131
                        $message = new Message();
132
                        $message->setLocale($locale);
133
                        $message->setMessage($trans);
134
                        $document->addMessage($message);
135
                    }
136
                    $this->esManager->persist($document);
137
                }
138
            }
139
        }
140
141
        $this->esManager->commit();
142
    }
143
144
    /**
145
     * Imports application translation files.
146
     */
147
    public function importAppTranslationFiles()
148
    {
149
        $finder = $this->findTranslationsFiles($this->kernelDir);
150
        $this->importTranslationFiles($finder);
0 ignored issues
show
Bug introduced by
It seems like $finder defined by $this->findTranslationsFiles($this->kernelDir) on line 149 can be null; however, ONGR\TranslationsBundle\...mportTranslationFiles() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
151
    }
152
153
    /**
154
     * Imports translation files form all bundles.
155
     *
156
     * @param array $bundles
157
     * @param bool  $isBundle
158
     */
159
    public function importBundlesTranslationFiles($bundles, $isBundle = false)
160
    {
161
        foreach ($bundles as $bundle) {
162
            $dir = $isBundle?
163
                dir($bundle->getPath())->path :
0 ignored issues
show
Bug introduced by
The property path does not seem to exist in Directory.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
164
                dirname((new \ReflectionClass($bundle))->getFilename());
165
166
            $this->importBundleTranslationFiles($dir);
167
        }
168
    }
169
170
    /**
171
     * Imports translation files form the specific bundles.
172
     *
173
     * @param string $bundle
174
     */
175
    public function importBundleTranslationFiles($bundle)
176
    {
177
        $finder = $this->findTranslationsFiles($bundle);
178
        $this->importTranslationFiles($finder);
0 ignored issues
show
Bug introduced by
It seems like $finder defined by $this->findTranslationsFiles($bundle) on line 177 can be null; however, ONGR\TranslationsBundle\...mportTranslationFiles() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
179
    }
180
181
    /**
182
     * Imports Symfony's components translation files.
183
     */
184
    public function importComponentTranslationFiles()
185
    {
186
        $classes = [
187
            'Symfony\Component\Validator\ValidatorBuilder' => '/Resources/translations',
188
            'Symfony\Component\Form\Form' => '/Resources/translations',
189
            'Symfony\Component\Security\Core\Exception\AuthenticationException' => '/../../Resources/translations',
190
        ];
191
192
        $dirs = [];
193
        foreach ($classes as $namespace => $translationDir) {
194
            $reflection = new \ReflectionClass($namespace);
195
            $dirs[] = dirname($reflection->getFilename()) . $translationDir;
196
        }
197
198
        $finder = $this->getFinder();
199
        $finder->files()
200
            ->name($this->getFileNamePattern())
201
            ->in($dirs);
202
203
        $this->importTranslationFiles($finder->count() > 0 ? $finder : null);
0 ignored issues
show
Bug introduced by
It seems like $finder->count() > 0 ? $finder : null can be null; however, importTranslationFiles() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
204
    }
205
206
    /**
207
     * Return a Finder object if $path has a Resources/translations folder.
208
     *
209
     * @param string $path
210
     *
211
     * @return Finder
212
     */
213
    protected function findTranslationsFiles($path)
214
    {
215
        $finder = null;
216
217
        if (preg_match('#^win#i', PHP_OS)) {
218
            $path = preg_replace('#' . preg_quote(DIRECTORY_SEPARATOR, '#') . '#', '/', $path);
219
        } else {
220
            $path = str_replace('\\', '/', $path);
221
        }
222
223
        $dir = $path . '/Resources/translations';
224
225
        if (is_dir($dir)) {
226
            $finder = $this->getFinder();
227
            $finder->files()
228
                ->name($this->getFileNamePattern())
229
                ->in($dir);
230
        }
231
232
        return (null !== $finder && $finder->count() > 0) ? $finder : null;
233
    }
234
235
    /**
236
     * @return string
237
     */
238
    protected function getFileNamePattern()
239
    {
240
        if (count($this->getDomains())) {
241
            $regex = sprintf(
242
                '/((%s)\.(%s)\.(%s))/',
243
                implode('|', $this->getDomains()),
244
                implode('|', $this->getLocales()),
245
                implode('|', $this->getFormats())
246
            );
247
        } else {
248
            $regex = sprintf(
249
                '/(.*\.(%s)\.(%s))/',
250
                implode('|', $this->getLocales()),
251
                implode('|', $this->getFormats())
252
            );
253
        }
254
255
        return $regex;
256
    }
257
258
    /**
259
     * Imports some translations files.
260
     *
261
     * @param Finder $finder
262
     */
263
    protected function importTranslationFiles($finder)
264
    {
265
        if ($finder instanceof Finder) {
266
            foreach ($finder as $file) {
267
                $this->translations = array_replace_recursive($this->fileImport->import($file), $this->translations);
268
            }
269
        }
270
    }
271
272
    /**
273
     * @return mixed
274
     */
275
    public function getDomains()
276
    {
277
        return $this->domains;
278
    }
279
280
    /**
281
     * @param mixed $domains
282
     */
283
    public function setDomains($domains)
284
    {
285
        $this->domains = $domains;
0 ignored issues
show
Documentation Bug introduced by
It seems like $domains of type * is incompatible with the declared type array of property $domains.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
286
    }
287
288
    /**
289
     * @return mixed
290
     */
291
    public function getLocales()
292
    {
293
        return $this->locales;
294
    }
295
296
    /**
297
     * @param mixed $locales
298
     */
299
    public function setLocales($locales)
300
    {
301
        $this->locales = $locales;
0 ignored issues
show
Documentation Bug introduced by
It seems like $locales of type * is incompatible with the declared type array of property $locales.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
302
    }
303
304
    /**
305
     * @return mixed
306
     */
307
    public function getFormats()
308
    {
309
        return $this->formats;
310
    }
311
312
    /**
313
     * @param mixed $formats
314
     */
315
    public function setFormats($formats)
316
    {
317
        $this->formats = $formats;
0 ignored issues
show
Documentation Bug introduced by
It seems like $formats of type * is incompatible with the declared type array of property $formats.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
318
    }
319
320
    /**
321
     * Returns Finder object.
322
     *
323
     * @return Finder
324
     */
325
    protected function getFinder()
326
    {
327
        return new Finder();
328
    }
329
330
    /**
331
     * @return array
332
     */
333
    public function getConfigBundles()
334
    {
335
        return $this->configBundles;
336
    }
337
338
    /**
339
     * @return array
340
     */
341
    public function getBundles()
342
    {
343
        return $this->bundles;
344
    }
345
}
346