Passed
Push — master ( d69c68...bb63c1 )
by Tim
02:59
created

SimpleConfigurationLoader::createInstance()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 36
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 5
eloc 13
c 3
b 0
f 0
nc 16
nop 0
dl 0
loc 36
ccs 0
cts 18
cp 0
crap 30
rs 9.5222
1
<?php
2
3
/**
4
 * TechDivision\Import\Cli\SimpleConfigurationLoader
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2016 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import-cli-simple
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Cli;
22
23
use Symfony\Component\Console\Input\InputInterface;
24
use Symfony\Component\DependencyInjection\ContainerInterface;
25
use TechDivision\Import\ConsoleOptionLoaderInterface;
26
use TechDivision\Import\Cli\Configuration\LibraryLoader;
27
use TechDivision\Import\Cli\Utils\DependencyInjectionKeys;
28
use TechDivision\Import\Cli\Utils\MagentoConfigurationKeys;
29
use TechDivision\Import\Utils\CommandNames;
30
use TechDivision\Import\Utils\EditionNamesInterface;
31
use TechDivision\Import\Utils\InputOptionKeysInterface;
32
use TechDivision\Import\Utils\Mappings\CommandNameToEntityTypeCode;
33
use TechDivision\Import\Configuration\ConfigurationFactoryInterface;
34
35
/**
36
 * The configuration loader implementation.
37
 *
38
 * @author    Tim Wagner <[email protected]>
39
 * @copyright 2016 TechDivision GmbH <[email protected]>
40
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
41
 * @link      https://github.com/techdivision/import-cli-simple
42
 * @link      http://www.techdivision.com
43
 */
44
class SimpleConfigurationLoader implements ConfigurationLoaderInterface
45
{
46
47
    /**
48
     * The key for the Magento Edition in the metadata extracted from the Composer configuration.
49
     *
50
     * @var string
51
     */
52
    const EDITION = 'edition';
53
54
    /**
55
     * The key for the Magento Version in the metadata extracted from the Composer configuration.
56
     *
57
     * @var string
58
     */
59
    const VERSION = 'version';
60
61
    /**
62
     * The container instance.
63
     *
64
     * @var \Symfony\Component\DependencyInjection\ContainerInterface
65
     */
66
    protected $container;
67
68
    /**
69
     * The actual input instance.
70
     *
71
     * @var \Symfony\Component\Console\Input\InputInterface
72
     */
73
    protected $input;
74
75
    /**
76
     * The library loader instance.
77
     *
78
     * @param \TechDivision\Import\Cli\LibraryLoader
79
     */
80
    protected $libraryLoader;
81
82
    /**
83
     * The configuration factory instance.
84
     *
85
     * @var \TechDivision\Import\Configuration\ConfigurationFactoryInterface
86
     */
87
    protected $configurationFactory;
88
89
    /**
90
     * The available command names.
91
     *
92
     * @var \TechDivision\Import\Utils\CommandNames
93
     */
94
    protected $commandNames;
95
96
    /**
97
     * The mapping of the command names to the entity type codes
98
     *
99
     * @var \TechDivision\Import\Utils\Mappings\CommandNameToEntityTypeCode
100
     */
101
    protected $commandNameToEntityTypeCode;
102
103
    /**
104
     * The console option loader instance.
105
     *
106
     * @var \TechDivision\Import\ConsoleOptionLoaderInterface
107
     */
108
    protected $consoleOptionLoader;
109
110
    /**
111
     * The default sorting for the edition detection.
112
     *
113
     * @var array
114
     */
115
    protected $editionSortOrder = array(
116
        EditionNamesInterface::EE,
117
        EditionNamesInterface::CE
118
    );
119
120
    /**
121
     * Initializes the configuration loader.
122
     *
123
     * @param \Symfony\Component\Console\Input\InputInterface                  $input                        The input instance
124
     * @param \Symfony\Component\DependencyInjection\ContainerInterface        $container                    The container instance
125
     * @param \TechDivision\Import\Cli\Configuration\LibraryLoader             $libraryLoader                The configuration loader instance
126
     * @param \TechDivision\Import\Configuration\ConfigurationFactoryInterface $configurationFactory         The configuration factory instance
127
     * @param \TechDivision\Import\Utils\CommandNames                          $commandNames                 The available command names
128
     * @param \TechDivision\Import\Utils\Mappings\CommandNameToEntityTypeCode  $commandNameToEntityTypeCodes The mapping of the command names to the entity type codes
129
     * @param \TechDivision\Import\ConsoleOptionLoaderInterface                $consoleOptionLoader          The console option loader instance
130
     */
131
    public function __construct(
132
        InputInterface $input,
133
        ContainerInterface $container,
134
        LibraryLoader $libraryLoader,
135
        ConfigurationFactoryInterface $configurationFactory,
136
        CommandNames $commandNames,
137
        CommandNameToEntityTypeCode $commandNameToEntityTypeCodes,
138
        ConsoleOptionLoaderInterface $consoleOptionLoader
139
    ) {
140
141
        // set the passed instances
142
        $this->input = $input;
143
        $this->container = $container;
144
        $this->libraryLoader = $libraryLoader;
145
        $this->configurationFactory = $configurationFactory;
146
        $this->commandNames = $commandNames;
147
        $this->commandNameToEntityTypeCode = $commandNameToEntityTypeCodes;
148
        $this->consoleOptionLoader = $consoleOptionLoader;
149
    }
150
151
    /**
152
     * Factory implementation to create a new initialized configuration instance.
153
     *
154
     * If command line options are specified, they will always override the
155
     * values found in the configuration file.
156
     *
157
     * @return \TechDivision\Import\Configuration\ConfigurationInterface The configuration instance
158
     */
159
    public function load()
160
    {
161
162
        // initially try to create the configuration instance
163
        $instance = $this->createInstance();
164
165
        // we have to set the entity type code at least
166
        $instance->setEntityTypeCode($this->getEntityTypeCode());
167
168
        // load and merge the console options
169
        $this->getConsoleOptionLoader()->load($instance);
170
171
        // return the initialized configuration instance
172
        return $instance;
173
    }
174
175
    /**
176
     * This method create the configuration instance from the configuration file
177
     * defined by the commandline args and options.
178
     *
179
     * @return \TechDivision\Import\Configuration\ConfigurationInterface The configuration instance loaded from the configuration file
180
     * @throws \Exception Is thrown, if the specified configuration file doesn't exist or the mandatory arguments/options to run the requested operation are not available
181
     */
182
    protected function createInstance()
183
    {
184
185
        // try to load the Magento installation directory
186
        $installationDir = $this->input->getOption(InputOptionKeysInterface::INSTALLATION_DIR);
187
188
        // query whether or not, a configuration file has been specified
189
        $configuration = $this->input->getOption(InputOptionKeysInterface::CONFIGURATION);
190
191
        // load the configuration from the file with the given filename
192
        $instance = $configuration ? $this->createConfiguration($configuration) : $this->createConfiguration();
193
194
        // query whether or not the installation directory is a valid Magento root directory
195
        if ($this->isMagentoRootDir($installationDir)) {
0 ignored issues
show
Bug introduced by
It seems like $installationDir can also be of type string[]; however, parameter $dir of TechDivision\Import\Cli\...der::isMagentoRootDir() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

195
        if ($this->isMagentoRootDir(/** @scrutinizer ignore-type */ $installationDir)) {
Loading history...
196
            // if yes, try to load the Magento Edition from the Composer configuration file
197
            $metadata = $this->getEditionMapping($installationDir);
0 ignored issues
show
Bug introduced by
It seems like $installationDir can also be of type string[]; however, parameter $installationDir of TechDivision\Import\Cli\...er::getEditionMapping() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

197
            $metadata = $this->getEditionMapping(/** @scrutinizer ignore-type */ $installationDir);
Loading history...
198
            // initialize/override the Magento edition/version with the values from the Magento installation
199
            $instance->setMagentoEdition($metadata[SimpleConfigurationLoader::EDITION]);
200
            $instance->setMagentoVersion($metadata[SimpleConfigurationLoader::VERSION]);
201
        }
202
203
        // initialize/override the Magento edition with the value from the command line
204
        if ($magentoEdition = $this->input->getOption(InputOptionKeysInterface::MAGENTO_EDITION)) {
205
            $instance->setMagentoEdition($magentoEdition);
206
        }
207
208
        // initialize/override the Magento version with the value from the command line
209
        if ($magentoVersion = $this->input->getOption(InputOptionKeysInterface::MAGENTO_VERSION)) {
210
            $instance->setMagentoVersion($magentoVersion);
211
        }
212
213
        // set the actual command name in the configuration
214
        $instance->setCommandName($this->input->getFirstArgument());
215
216
        // return the instance
217
        return $instance;
218
    }
219
220
    /**
221
     * Create and return a new configuration instance from the passed configuration filename
222
     * after merging additional specified params from the commandline.
223
     *
224
     * @param string|null $filename The configuration filename to use
225
     *
226
     * @return \TechDivision\Import\Configuration\ConfigurationInterface The configuration instance
227
     */
228
    protected function createConfiguration($filename = null)
229
    {
230
231
        // initialize the params specified with the --params parameter
232
        $params = null;
233
234
        // try to load the params from the commandline
235
        if ($this->input->hasOptionSpecified(InputOptionKeysInterface::PARAMS) && $this->input->getOption(InputOptionKeysInterface::PARAMS)) {
0 ignored issues
show
Bug introduced by
The method hasOptionSpecified() does not exist on Symfony\Component\Console\Input\InputInterface. Did you maybe mean hasOption()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

235
        if ($this->input->/** @scrutinizer ignore-call */ hasOptionSpecified(InputOptionKeysInterface::PARAMS) && $this->input->getOption(InputOptionKeysInterface::PARAMS)) {

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...
236
            $params = $this->input->getOption(InputOptionKeysInterface::PARAMS);
237
        }
238
239
        // initialize the params file specified with the --params-file parameter
240
        $paramsFile = null;
241
242
        // try to load the path of the params file from the commandline
243
        if ($this->input->hasOptionSpecified(InputOptionKeysInterface::PARAMS_FILE) && $this->input->getOption(InputOptionKeysInterface::PARAMS_FILE)) {
244
            $paramsFile = $this->input->getOption(InputOptionKeysInterface::PARAMS_FILE);
245
        }
246
247
        // if a filename has been passed, try to load the configuration from the file
248
        if (is_file($filename)) {
0 ignored issues
show
Bug introduced by
It seems like $filename can also be of type null; however, parameter $filename of is_file() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

248
        if (is_file(/** @scrutinizer ignore-type */ $filename)) {
Loading history...
249
            return $this->configurationFactory->factory($filename, pathinfo($filename, PATHINFO_EXTENSION), $params, $paramsFile);
0 ignored issues
show
Unused Code introduced by
The call to TechDivision\Import\Conf...oryInterface::factory() has too many arguments starting with $params. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

249
            return $this->configurationFactory->/** @scrutinizer ignore-call */ factory($filename, pathinfo($filename, PATHINFO_EXTENSION), $params, $paramsFile);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug introduced by
It seems like pathinfo($filename, Tech...Cli\PATHINFO_EXTENSION) can also be of type array; however, parameter $type of TechDivision\Import\Conf...oryInterface::factory() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

249
            return $this->configurationFactory->factory($filename, /** @scrutinizer ignore-type */ pathinfo($filename, PATHINFO_EXTENSION), $params, $paramsFile);
Loading history...
Bug introduced by
It seems like $filename can also be of type null; however, parameter $path of pathinfo() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

249
            return $this->configurationFactory->factory($filename, pathinfo(/** @scrutinizer ignore-type */ $filename, PATHINFO_EXTENSION), $params, $paramsFile);
Loading history...
250
        }
251
252
        // initialize the array for the directories
253
        $directories = array();
254
255
        // set the default file format
256
        $format = 'json';
257
258
        // load the actual vendor directory and entity type code
259
        $vendorDir = $this->getVendorDir();
260
261
        // load the default configuration directory from the DI configuration
262
        $defaultConfigurationDir = $this->getContainer()->getParameter(DependencyInjectionKeys::APPLICATION_DEFAULT_CONFIGURATION_DIR);
263
264
        // load the directories that has to be parsed for configuration files1
265
        foreach ($this->getDefaultLibraries() as $defaultLibrary) {
266
            // initialize the directory name
267
            $directory = implode(
268
                DIRECTORY_SEPARATOR,
269
                array_merge(
270
                    array($vendorDir),
271
                    explode('/', $defaultLibrary),
272
                    explode('/', $defaultConfigurationDir)
273
                )
274
            );
275
276
            // query whether or not the directory is available1
277
            if (is_dir($directory)) {
278
                $directories[] = $directory;
279
            }
280
        }
281
282
        // load the assumed installation directory
283
        $installationDir = $this->input->getOption(InputOptionKeysInterface::INSTALLATION_DIR);
284
285
        // initialize the default custom configuration directory
286
        $customConfigurationDir = implode(
287
            DIRECTORY_SEPARATOR,
288
            array_merge(
289
                array($installationDir),
290
                explode('/', $this->getContainer()->getParameter(DependencyInjectionKeys::APPLICATION_CUSTOM_CONFIGURATION_DIR))
291
            )
292
        );
293
294
        // query whether or not a custom configuration directory has been speified, if yes override the default one
295
        if ($this->input->hasOptionSpecified(InputOptionKeysInterface::CUSTOM_CONFIGURATION_DIR) && $this->input->getOption(InputOptionKeysInterface::CUSTOM_CONFIGURATION_DIR)) {
296
            $customConfigurationDir = $this->input->getOption(InputOptionKeysInterface::CUSTOM_CONFIGURATION_DIR);
297
        }
298
299
        // specify the default directory for custom configuration files
300
        if (is_dir($customConfigurationDir)) {
301
            $directories[] = $customConfigurationDir;
302
        }
303
304
        // load and return the configuration from the files found in the passed directories
305
        return $this->configurationFactory->factoryFromDirectories($installationDir, $defaultConfigurationDir, $directories, $format, $params, $paramsFile);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->configurat..., $params, $paramsFile) returns the type void which is incompatible with the documented return type TechDivision\Import\Conf...\ConfigurationInterface.
Loading history...
Bug introduced by
Are you sure the usage of $this->configurationFact..., $params, $paramsFile) targeting TechDivision\Import\Conf...actoryFromDirectories() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
It seems like $paramsFile can also be of type string[]; however, parameter $paramsFile of TechDivision\Import\Conf...actoryFromDirectories() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

305
        return $this->configurationFactory->factoryFromDirectories($installationDir, $defaultConfigurationDir, $directories, $format, $params, /** @scrutinizer ignore-type */ $paramsFile);
Loading history...
Bug introduced by
It seems like $defaultConfigurationDir can also be of type array; however, parameter $defaultConfigurationDir of TechDivision\Import\Conf...actoryFromDirectories() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

305
        return $this->configurationFactory->factoryFromDirectories($installationDir, /** @scrutinizer ignore-type */ $defaultConfigurationDir, $directories, $format, $params, $paramsFile);
Loading history...
Bug introduced by
It seems like $params can also be of type string[]; however, parameter $params of TechDivision\Import\Conf...actoryFromDirectories() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

305
        return $this->configurationFactory->factoryFromDirectories($installationDir, $defaultConfigurationDir, $directories, $format, /** @scrutinizer ignore-type */ $params, $paramsFile);
Loading history...
Bug introduced by
It seems like $installationDir can also be of type string[]; however, parameter $installationDir of TechDivision\Import\Conf...actoryFromDirectories() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

305
        return $this->configurationFactory->factoryFromDirectories(/** @scrutinizer ignore-type */ $installationDir, $defaultConfigurationDir, $directories, $format, $params, $paramsFile);
Loading history...
306
    }
307
308
    /**
309
     * Return's the DI container instance.
310
     *
311
     * @return \Symfony\Component\DependencyInjection\ContainerInterface The DI container instance
312
     */
313
    protected function getContainer()
314
    {
315
        return $this->container;
316
    }
317
318
    /**
319
     * The console option loader instance.
320
     *
321
     * @return \TechDivision\Import\ConsoleOptionLoaderInterface The instance
322
     */
323
    protected function getConsoleOptionLoader()
324
    {
325
        return $this->consoleOptionLoader;
326
    }
327
328
    /**
329
     * Return's the absolute path to the actual vendor directory.
330
     *
331
     * @return string The absolute path to the actual vendor directory
332
     * @throws \Exception Is thrown, if none of the possible vendor directories can be found
333
     */
334
    protected function getVendorDir()
335
    {
336
        return $this->getContainer()->getParameter(DependencyInjectionKeys::CONFIGURATION_VENDOR_DIR);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getContain...NFIGURATION_VENDOR_DIR) also could return the type array|boolean which is incompatible with the documented return type string.
Loading history...
337
    }
338
339
    /**
340
     * Return's the actual command name.
341
     *
342
     * @return string The actual command name
343
     */
344
    protected function getCommandName()
345
    {
346
        return $this->input->getArgument('command');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->input->getArgument('command') also could return the type string[] which is incompatible with the documented return type string.
Loading history...
347
    }
348
349
    /**
350
     * Return's the command's entity type code.
351
     *
352
     * @return string The command's entity type code
353
     * @throws \Exception Is thrown, if the command name can not be mapped
354
     */
355
    protected function getEntityTypeCode()
356
    {
357
358
        // try to map the command name to a entity type code
359
        if (array_key_exists($commandName = $this->getCommandName(), (array) $this->commandNameToEntityTypeCode)) {
360
            return $this->commandNameToEntityTypeCode[$commandName];
361
        }
362
363
        // throw an exception if not possible
364
        throw new \Exception(sprintf('Can\'t map command name %s to a entity type', $commandName));
365
    }
366
367
    /**
368
     * Returns the mapped Magento Edition from the passed Magento installation.
369
     *
370
     * @param string $installationDir The Magento installation directory
371
     *
372
     * @return array The array with the mapped Magento Edition (either CE or EE) + the Version
373
     * @throws \Exception Is thrown, if the passed installation directory doesn't contain a valid Magento installation
374
     */
375
    protected function getEditionMapping($installationDir)
376
    {
377
378
        // load the default edition mappings from the configuration
379
        $editionMappings = $this->getContainer()->getParameter(DependencyInjectionKeys::APPLICATION_EDITION_MAPPINGS);
380
381
        // load the composer file from the Magento root directory
382
        $composer = json_decode(file_get_contents($composerFile = sprintf('%s/composer.lock', $installationDir)), true);
383
384
        // initialize the array that contains the packages to identify the Magento edition
385
        $packages = array();
386
387
        // query whether or not packages are available in the composer file
388
        if (isset($composer[MagentoConfigurationKeys::COMPOSER_PACKAGES])) {
389
            // iterate over the available packages to figure out the ones that allows us to identify the Magento edition
390
            foreach ($composer[MagentoConfigurationKeys::COMPOSER_PACKAGES] as $package) {
391
                // try to load and explode the Magento Edition identifier from the Composer name
392
                $possibleEdition = $package[MagentoConfigurationKeys::COMPOSER_EDITION_NAME_ATTRIBUTE];
393
394
                // try to load and explode the Magento Edition from the Composer configuration
395
                if (isset($editionMappings[$possibleEdition])) {
396
                    // try to load and explode the Magento Version from the Composer configuration
397
                    if (isset($package[MagentoConfigurationKeys::COMPOSER_EDITION_VERSION_ATTRIBUTE])) {
398
                        // add Magento edition => version mapping and continue
399
                        $packages[$editionMappings[$possibleEdition]] = $package[MagentoConfigurationKeys::COMPOSER_EDITION_VERSION_ATTRIBUTE];
400
                        continue;
401
                    }
402
403
                    // throw an exception if the package has NO version defineds
404
                    throw new \Exception(
405
                        sprintf(
406
                            'Can\'t detect a valid Magento version for package "%s" in "%s", please set Magento Version with the "--magento-version" option',
407
                            $possibleEdition,
408
                            $composerFile
409
                        )
410
                    );
411
                }
412
            }
413
        }
414
415
        // create the default sort order for the edition detection
416
        $editionSortOrder = array_flip($this->editionSortOrder);
417
418
        // sort the packages according the default sort order
419
        uksort($packages, function ($a, $b) use ($editionSortOrder) {
420
            return $editionSortOrder[$a] <=> $editionSortOrder[$b];
421
        });
422
423
        // return the array with the Magento Version/Edition data
424
        foreach ($packages as $edition => $version) {
425
            return array(
426
                SimpleConfigurationLoader::EDITION => $edition,
427
                SimpleConfigurationLoader::VERSION => $version
428
            );
429
        }
430
431
        // throw an exception if NO edition information can be found in the composer.lock file
432
        throw new \Exception(
433
            sprintf(
434
                'Can\'t detect a valid Magento edition/version in "%s", please pass them with the "--magento-edition" and "--magento-version" options',
435
                $composerFile
436
            )
437
        );
438
    }
439
440
441
    /**
442
     * Return's the application's default libraries.
443
     *
444
     * @return array The default libraries
445
     */
446
    protected function getDefaultLibraries()
447
    {
448
449
        // load the default libraries from the configuration
450
        $defaultLibraries = $this->getContainer()->getParameter(DependencyInjectionKeys::APPLICATION_DEFAULT_LIBRARIES);
451
452
        // initialize the array for the libraries
453
        $libraries = array();
454
455
        // append each library only ONCE
456
        foreach ($defaultLibraries as $libraries) {
457
            foreach ($libraries as $library) {
458
                if (in_array($library, $libraries)) {
459
                    continue;
460
                }
461
                // append the library
462
                $libraries[] = $library;
463
            }
464
        }
465
466
        // return the array with the libraries
467
        return $libraries;
468
    }
469
470
    /**
471
     * Query whether or not, the passed directory is a Magento root directory.
472
     *
473
     * @param string $dir The directory to query
474
     *
475
     * @return boolean TRUE if the directory is a Magento root directory, else FALSE
476
     */
477
    protected function isMagentoRootDir($dir)
478
    {
479
        return is_file($this->getMagentoEnv($dir));
480
    }
481
482
    /**
483
     * Return's the path to the Magento file with the environment configuration.
484
     *
485
     * @param string $dir The path to the Magento root directory
486
     *
487
     * @return string The path to the Magento file with the environment configuration
488
     */
489
    protected function getMagentoEnv($dir)
490
    {
491
        return sprintf('%s/app/etc/env.php', $dir);
492
    }
493
}
494