Completed
Push — master ( d7e919...298f7d )
by Simonas
64:16
created

ImportManager::getFileTranslationMessages()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 25
rs 8.5806
cc 4
eloc 15
nc 4
nop 2
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 ONGR\ElasticsearchBundle\Service\Manager;
15
use ONGR\ElasticsearchBundle\Service\Repository;
16
use ONGR\ElasticsearchDSL\Query\FullText\MatchQuery;
17
use ONGR\TranslationsBundle\Document\Message;
18
use ONGR\TranslationsBundle\Document\Translation;
19
use Symfony\Component\Finder\Finder;
20
use Symfony\Component\Finder\SplFileInfo;
21
use Symfony\Component\Translation\Exception\InvalidResourceException;
22
use Symfony\Component\Translation\Loader\YamlFileLoader;
23
use Symfony\Component\Yaml\Exception\ParseException;
24
use Symfony\Component\Yaml\Parser as YamlParser;
25
26
/**
27
 * Collects translations.
28
 */
29
class ImportManager
30
{
31
    /**
32
     * @var array
33
     */
34
    private $locales;
35
36
    /**
37
     * @var Repository
38
     */
39
    private $repository;
40
41
    /**
42
     * @var Manager
43
     */
44
    private $manager;
45
46
    /**
47
     * @var YamlFileLoader
48
     */
49
    private $parser;
50
51
    /**
52
     * @var string
53
     */
54
    private $kernelRoot;
55
56
    /**
57
     * @param Repository $repository
58
     */
59
    public function __construct(
60
        Repository $repository,
61
        $kernelRoot
62
    )
63
    {
64
        $this->parser = new YamlParser();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Symfony\Component\Yaml\Parser() of type object<Symfony\Component\Yaml\Parser> is incompatible with the declared type object<Symfony\Component...\Loader\YamlFileLoader> of property $parser.

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...
65
        $this->repository = $repository;
66
        $this->manager = $repository->getManager();
67
        $this->kernelRoot = $kernelRoot;
68
    }
69
70
    /**
71
     * @return array
72
     */
73
    public function getLocales()
74
    {
75
        return $this->locales;
76
    }
77
78
    /**
79
     * @param array $locales
80
     */
81
    public function setLocales(array $locales)
82
    {
83
        $this->locales = $locales;
84
    }
85
86
    /**
87
     * Write translations to storage.
88
     *
89
     * @param $translations
90
     */
91
    public function writeToStorage($domain, $translations)
92
    {
93
        foreach ($translations as $keys) {
94
            foreach ($keys as $key => $transMeta) {
95
96
                $search = $this->repository->createSearch();
97
                $search->addQuery(new MatchQuery('key', $key));
98
                $results = $this->repository->findDocuments($search);
99
                if (count($results)) {
100
                    continue;
101
                }
102
103
                $document = new Translation();
104
                $document->setDomain($domain);
105
                $document->setKey($key);
106
                $document->setPath($transMeta['path']);
107
                $document->setFormat($transMeta['format']);
108
                foreach ($transMeta['messages'] as $locale => $text) {
109
                    $message = new Message();
110
                    $message->setLocale($locale);
111
                    $message->setMessage($text);
112
                    $document->addMessage($message);
113
                }
114
                $this->manager->persist($document);
115
            }
116
        }
117
118
        $this->manager->commit();
119
    }
120
121
    /**
122
     * Imports translation files from a directory.
123
     * @param string $dir
124
     */
125
    public function importTranslationFiles($domain, $dir)
126
    {
127
        $translations = $this->getTranslationsFromFiles($domain, $dir);
128
        $this->writeToStorage($domain, $translations);
129
    }
130
131
    /**
132
     * Return a Finder object if $path has a Resources/translations folder.
133
     *
134
     * @param string $domain
135
     * @param string $path
136
     * @param array $directories
137
     *
138
     * @return array
139
     */
140
    public function getTranslationsFromFiles($domain, $path, array $directories = [])
141
    {
142
        if (!$directories) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $directories of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
143
            $directories = [
144
                $path . 'Resources/translations',
145
                $this->kernelRoot . DIRECTORY_SEPARATOR . $domain . DIRECTORY_SEPARATOR . 'translations',
146
            ];
147
        }
148
149
        $finder = new Finder();
150
        $translations = [];
151
152
        foreach ($directories as $directory) {
153
            if (is_dir($directory)) {
154
                $finder->files()
155
                    ->name($this->getFileNamePattern())
156
                    ->in($directory);
157
158
                foreach ($finder as $file) {
159
                    $translations = array_replace_recursive($this->getFileTranslationMessages($file, $domain), $translations);
160
                }
161
            }
162
        }
163
164
        return $translations;
165
    }
166
167
    /**
168
     * @param SplFileInfo $file
169
     * @param string      $domain
170
     *
171
     * @return array
172
     */
173
    public function getFileTranslationMessages(SplFileInfo $file, $domain)
174
    {
175
        $locale = explode('.', $file->getFilename())[1];
176
177
        if (!in_array($locale, $this->getLocales())) {
178
            return [];
179
        }
180
181
        $translations = [];
182
183
        try {
184
            $domainMessages = $this->parser->parse(file_get_contents($file->getPath().DIRECTORY_SEPARATOR.$file->getFilename()));
0 ignored issues
show
Bug introduced by
The method parse() does not seem to exist on object<Symfony\Component...\Loader\YamlFileLoader>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
185
        } catch (ParseException $e) {
186
            throw new InvalidResourceException(sprintf('Error parsing YAML, invalid file "%s"', $file->getPath()), 0, $e);
187
        }
188
189
        $path = substr(pathinfo($file->getPathname(), PATHINFO_DIRNAME), strlen(getcwd()) + 1);
190
        foreach ($domainMessages as $key => $content) {
191
            $translations[$domain][$key]['messages'][$locale] = $content;
192
            $translations[$domain][$key]['path'] = $path;
193
            $translations[$domain][$key]['format'] = $file->getExtension();
194
        }
195
196
        return $translations;
197
    }
198
199
    /**
200
     * @return string
201
     */
202
    private function getFileNamePattern()
203
    {
204
        $regex = sprintf(
205
            '/(.*\.(%s)\.(%s))/',
206
            implode('|', $this->getLocales()),
207
            'yml'
208
        );
209
        return $regex;
210
    }
211
}
212