Completed
Push — 5.3 ( fe9840...e3c3bf )
by Jeroen
126:51 queued 120:15
created

ImportCommandHandler::executeImportCommand()   A

Complexity

Conditions 5
Paths 10

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 6.2017

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 7
cts 11
cp 0.6364
rs 9.2888
c 0
b 0
f 0
cc 5
nc 10
nop 1
crap 6.2017
1
<?php
2
3
namespace Kunstmaan\TranslatorBundle\Service\Command\Importer;
4
5
use Kunstmaan\TranslatorBundle\Model\Import\ImportCommand;
6
use Kunstmaan\TranslatorBundle\Service\Command\AbstractCommandHandler;
7
use Kunstmaan\TranslatorBundle\Service\Exception\TranslationsNotFoundException;
8
use Kunstmaan\TranslatorBundle\Service\TranslationFileExplorer;
9
use Symfony\Component\Finder\Finder;
10
use Symfony\Component\HttpKernel\Kernel;
11
12
/**
13
 * Parses an ImportCommand
14
 */
15
class ImportCommandHandler extends AbstractCommandHandler
16
{
17
    /**
18
     * TranslationFileExplorer
19
     *
20
     * @var TranslationFileExplorer
21
     */
22
    private $translationFileExplorer;
23
24
    /**
25
     * Importer
26
     *
27
     * @var Importer
28
     */
29
    private $importer;
30
31
    /**
32
     * Execute an import command
33
     *
34
     * @param ImportCommand $importCommand
35
     *
36
     * @return int total number of files imported
0 ignored issues
show
Documentation introduced by
Should the return type not be false|integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
37
     */
38 1
    public function executeImportCommand(ImportCommand $importCommand)
39
    {
40 1
        $amount = 0;
41 1
        $defaultBundleNotSet = $importCommand->getDefaultBundle() === false || $importCommand->getDefaultBundle() === null;
42
43 1
        if ($importCommand->getGlobals()) {
44 1
            $amount = $this->importGlobalTranslationFiles($importCommand);
45 1
            if ($defaultBundleNotSet) {
46 1
                return $amount;
47
            }
48
        }
49
50
        if ($defaultBundleNotSet) {
51
            $importCommand->setDefaultBundle('all');
52
        }
53
54
        $amount += $this->importBundleTranslationFiles($importCommand);
55
56
        return $amount;
57
    }
58
59
    /**
60
     * Import all translation files from app resources
61
     *
62
     * @param ImportCommand $importCommand
63
     *
64
     * @return int total number of files imported
0 ignored issues
show
Documentation introduced by
Should the return type not be false|integer?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
65
     */
66 1
    private function importGlobalTranslationFiles(ImportCommand $importCommand)
67
    {
68 1
        $baseDir = Kernel::VERSION_ID >= 40000 ? $this->kernel->getProjectDir() : $this->kernel->getRootDir();
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\HttpKernel\Kernel::getRootDir() has been deprecated with message: since Symfony 4.2, use getProjectDir() instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
69 1
        $translationsDir = Kernel::VERSION_ID >= 40000 ? 'translations' : null;
70 1
        $locales = $this->determineLocalesToImport($importCommand);
71 1
        $finder = $this->translationFileExplorer->find($baseDir, $locales, $translationsDir);
72
73 1
        return $this->importTranslationFiles($finder, $importCommand->getForce());
74
    }
75
76
    /**
77
     * Import all translation files from a specific bundle, bundle name will be lowercased so cases don't matter
78
     *
79
     * @param ImportCommand $importCommand
80
     *
81
     * @return int total number of files imported
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
82
     */
83 1
    public function importBundleTranslationFiles(ImportCommand $importCommand)
84
    {
85 1
        $importBundle = strtolower($importCommand->getDefaultBundle());
86
87 1
        if ($importBundle == 'all') {
88
            $importCount = $this->importAllBundlesTranslationFiles($importCommand);
89
90
            if (Kernel::VERSION_ID >= 40000) {
91
                $importCount += $this->importSf4TranslationFiles($importCommand);
92
            }
93
94
            return $importCount;
95 1
        } elseif ($importBundle == 'custom') {
96
            return $this->importCustomBundlesTranslationFiles($importCommand);
97
        } else {
98 1
            if (Kernel::VERSION_ID >= 40000) {
99 1
                return $this->importSf4TranslationFiles($importCommand);
100
            }
101
102
            return $this->importOwnBundlesTranslationFiles($importCommand);
103
        }
104
    }
105
106
    /**
107
     * Import all translation files from all registered bundles (in AppKernel)
108
     *
109
     * @param ImportCommand $importCommand
110
     *
111
     * @return int total number of files imported
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
112
     */
113 View Code Duplication
    private function importAllBundlesTranslationFiles(ImportCommand $importCommand)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
114
    {
115
        $bundles = array_map('strtolower', array_keys($this->kernel->getBundles()));
116
        $imported = 0;
117
118
        foreach ($bundles as $bundle) {
119
            $importCommand->setDefaultBundle($bundle);
120
121
            try {
122
                $imported += $this->importSingleBundleTranslationFiles($importCommand);
123
            } catch (TranslationsNotFoundException $e) {
124
                continue;
125
            }
126
        }
127
128
        return $imported;
129
    }
130
131
    /**
132
     * Import all translation files from your own registered bundles (in src/ directory)
133
     *
134
     * @param ImportCommand $importCommand
135
     *
136
     * @return int The total number of imported files
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
137
     */
138
    private function importOwnBundlesTranslationFiles(ImportCommand $importCommand)
139
    {
140
        $imported = 0;
141
        $srcDir = $this->kernel->getProjectDir().'/src';
142
143
        foreach ($this->kernel->getBundles() as $name => $bundle) {
144
            if (strpos($bundle->getPath(), $srcDir) !== false) {
145
                $importCommand->setDefaultBundle(strtolower($name));
146
147
                try {
148
                    $imported += $this->importSingleBundleTranslationFiles($importCommand);
149
                } catch (TranslationsNotFoundException $e) {
150
                    continue;
151
                }
152
            }
153
        }
154
155
        return $imported;
156
    }
157
158
    /**
159
     * Import the translation files from the defined bundles.
160
     *
161
     * @param ImportCommand $importCommand
162
     *
163
     * @return int The total number of imported files
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
164
     */
165 View Code Duplication
    private function importCustomBundlesTranslationFiles(ImportCommand $importCommand)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
166
    {
167
        $imported = 0;
168
169
        foreach ($importCommand->getBundles() as $bundle) {
170
            $importCommand->setDefaultBundle(strtolower($bundle));
171
172
            try {
173
                $imported += $this->importSingleBundleTranslationFiles($importCommand);
174
            } catch (TranslationsNotFoundException $e) {
175
                continue;
176
            }
177
        }
178
179
        return $imported;
180
    }
181
182
    /**
183
     * Import all translation files from a single bundle
184
     *
185
     * @param ImportCommand $importCommand
186
     *
187
     * @return int total number of files imported
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
188
     */
189
    private function importSingleBundleTranslationFiles(ImportCommand $importCommand)
190
    {
191
        $this->validateBundleName($importCommand->getDefaultBundle());
0 ignored issues
show
Documentation introduced by
$importCommand->getDefaultBundle() is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
192
        $bundles = array_change_key_case($this->kernel->getBundles(), CASE_LOWER);
193
        $finder = $this->translationFileExplorer->find($bundles[strtolower($importCommand->getDefaultBundle())]->getPath(), $this->determineLocalesToImport($importCommand));
194
195
        if ($finder === null) {
196
            return 0;
197
        }
198
199
        return $this->importTranslationFiles($finder, $importCommand->getForce());
200
    }
201
202
    /**
203
     * Import translation files from a specific Finder object
204
     * The finder object shoud already have the files to look for defined;
205
     * Forcing the import will override all existing translations in the stasher
206
     *
207
     * @param Finder $finder
208
     * @param bool   $force  override identical translations in the stasher (domain/locale and keyword combination)
209
     *
210
     * @return int total number of files imported
0 ignored issues
show
Documentation introduced by
Should the return type not be false|integer?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
211
     */
212 2
    private function importTranslationFiles(Finder $finder, $force = flase)
213
    {
214 2
        if (!$finder instanceof Finder) {
215
            return false;
216
        }
217
218 2
        $imported = 0;
219
220 2
        foreach ($finder as $file) {
221 2
            $imported += $this->importer->import($file, $force);
222
        }
223
224 2
        return $imported;
225
    }
226
227
    /**
228
     * Validates that a bundle is registered in the AppKernel
229
     *
230
     * @param string $bundle
231
     *
232
     * @return bool bundle is valid or not
233
     *
234
     * @throws \Exception If the bundlename isn't valid
235
     */
236
    public function validateBundleName($bundle)
237
    {
238
        // strtolower all bundle names
239
        $bundles = array_map('strtolower', array_keys($this->kernel->getBundles()));
240
241
        if (in_array(strtolower(trim($bundle)), $bundles)) {
242
            return true;
243
        }
244
245
        throw new \Exception(sprintf('bundle "%s" not found in available bundles: %s', $bundle, implode(', ', $bundles)));
246
    }
247
248
    /**
249
     * Gives an array with all languages that needs to be imported (from the given ImportCommand)
250
     * If non is given, all managed locales will be used (defined in config)
251
     *
252
     * @param ImportCommand $importCommand
253
     *
254
     * @return array all locales to import by the given ImportCommand
255
     */
256 3
    public function determineLocalesToImport(ImportCommand $importCommand)
257
    {
258 3
        if ($importCommand->getLocales() === false || $importCommand->getLocales() === null) {
259 3
            return $this->managedLocales;
260
        }
261
262
        return $this->parseRequestedLocales($importCommand->getLocales());
0 ignored issues
show
Documentation introduced by
$importCommand->getLocales() is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
263
    }
264
265 6
    public function setTranslationFileExplorer($translationFileExplorer)
266
    {
267 6
        $this->translationFileExplorer = $translationFileExplorer;
268 6
    }
269
270 6
    public function setImporter($importer)
271
    {
272 6
        $this->importer = $importer;
273 6
    }
274
275 1
    private function importSf4TranslationFiles($importCommand)
276
    {
277 1
        $finder = $this->translationFileExplorer->find($this->kernel->getProjectDir(), $this->determineLocalesToImport($importCommand), 'translations');
278
279 1
        if ($finder === null) {
280
            return 0;
281
        }
282
283 1
        return $this->importTranslationFiles($finder, $importCommand->getForce());
284
    }
285
}
286