Completed
Push — master ( e1b55c...3262e9 )
by Tim
12s queued 11s
created

SimpleConfigurationLoader   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 471
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
eloc 122
dl 0
loc 471
ccs 0
cts 189
cp 0
rs 9.44
c 8
b 0
f 0
wmc 37

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 18 1
A load() 0 14 1
B createInstance() 0 59 6
B getEditionMapping() 0 61 6
A getConsoleOptionLoader() 0 3 1
A getContainer() 0 3 1
A isMagentoRootDir() 0 3 1
A getEntityTypeCode() 0 10 2
A getVendorDir() 0 3 1
A getMagentoEnv() 0 3 1
A getCommandName() 0 3 1
B createConfiguration() 0 78 11
A getDefaultLibraries() 0 22 4
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
        // load the actual vendor directory and entity type code
186
        $vendorDir = $this->getVendorDir();
187
188
        // the path of the JMS serializer directory, relative to the vendor directory
189
        $jmsDir = DIRECTORY_SEPARATOR . 'jms' . DIRECTORY_SEPARATOR . 'serializer' . DIRECTORY_SEPARATOR . 'src';
190
191
        // try to find the path to the JMS Serializer annotations
192
        if (!file_exists($annotationDir = $vendorDir . DIRECTORY_SEPARATOR . $jmsDir)) {
193
            // stop processing, if the JMS annotations can't be found
194
            throw new \Exception(
195
                sprintf(
196
                    'The jms/serializer libarary can not be found in one of "%s"',
197
                    implode(', ', $vendorDir)
0 ignored issues
show
Bug introduced by
$vendorDir of type string is incompatible with the type array expected by parameter $pieces of implode(). ( Ignorable by Annotation )

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

197
                    implode(', ', /** @scrutinizer ignore-type */ $vendorDir)
Loading history...
198
                )
199
            );
200
        }
201
202
        // register the autoloader for the JMS serializer annotations
203
        \Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace(
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\Common\Annotati...sterAutoloadNamespace() has been deprecated: This method is deprecated and will be removed in doctrine/annotations 2.0. Annotations will be autoloaded in 2.0. ( Ignorable by Annotation )

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

203
        /** @scrutinizer ignore-deprecated */ \Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace(

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

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

Loading history...
204
            'JMS\Serializer\Annotation',
205
            $annotationDir
206
        );
207
208
        // try to load the Magento installation directory
209
        $installationDir = $this->input->getOption(InputOptionKeysInterface::INSTALLATION_DIR);
210
211
        // query whether or not, a configuration file has been specified
212
        $configuration = $this->input->getOption(InputOptionKeysInterface::CONFIGURATION);
213
214
        // load the configuration from the file with the given filename
215
        $instance = $configuration ? $this->createConfiguration($configuration) : $this->createConfiguration();
216
217
        // query whether or not the installation directory is a valid Magento root directory
218
        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

218
        if ($this->isMagentoRootDir(/** @scrutinizer ignore-type */ $installationDir)) {
Loading history...
219
            // if yes, try to load the Magento Edition from the Composer configuration file
220
            $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

220
            $metadata = $this->getEditionMapping(/** @scrutinizer ignore-type */ $installationDir);
Loading history...
221
            // initialize/override the Magento edition/version with the values from the Magento installation
222
            $instance->setMagentoEdition($metadata[SimpleConfigurationLoader::EDITION]);
223
            $instance->setMagentoVersion($metadata[SimpleConfigurationLoader::VERSION]);
224
        }
225
226
        // initialize/override the Magento edition with the value from the command line
227
        if ($magentoEdition = $this->input->getOption(InputOptionKeysInterface::MAGENTO_EDITION)) {
228
            $instance->setMagentoEdition($magentoEdition);
229
        }
230
231
        // initialize/override the Magento version with the value from the command line
232
        if ($magentoVersion = $this->input->getOption(InputOptionKeysInterface::MAGENTO_VERSION)) {
233
            $instance->setMagentoVersion($magentoVersion);
234
        }
235
236
        // set the actual command name in the configuration
237
        $instance->setCommandName($this->input->getFirstArgument());
238
239
        // return the instance
240
        return $instance;
241
    }
242
243
    /**
244
     * Create and return a new configuration instance from the passed configuration filename
245
     * after merging additional specified params from the commandline.
246
     *
247
     * @param string|null $filename The configuration filename to use
248
     *
249
     * @return \TechDivision\Import\Configuration\ConfigurationInterface The configuration instance
250
     */
251
    protected function createConfiguration($filename = null)
252
    {
253
254
        // initialize the params specified with the --params parameter
255
        $params = null;
256
257
        // try to load the params from the commandline
258
        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

258
        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...
259
            $params = $this->input->getOption(InputOptionKeysInterface::PARAMS);
260
        }
261
262
        // initialize the params file specified with the --params-file parameter
263
        $paramsFile = null;
264
265
        // try to load the path of the params file from the commandline
266
        if ($this->input->hasOptionSpecified(InputOptionKeysInterface::PARAMS_FILE) && $this->input->getOption(InputOptionKeysInterface::PARAMS_FILE)) {
267
            $paramsFile = $this->input->getOption(InputOptionKeysInterface::PARAMS_FILE);
268
        }
269
270
        // if a filename has been passed, try to load the configuration from the file
271
        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

271
        if (is_file(/** @scrutinizer ignore-type */ $filename)) {
Loading history...
272
            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

272
            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

272
            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

272
            return $this->configurationFactory->factory($filename, pathinfo(/** @scrutinizer ignore-type */ $filename, PATHINFO_EXTENSION), $params, $paramsFile);
Loading history...
273
        }
274
275
        // initialize the array for the directories
276
        $directories = array();
277
278
        // set the default file format
279
        $format = 'json';
280
281
        // load the actual vendor directory and entity type code
282
        $vendorDir = $this->getVendorDir();
283
284
        // load the default configuration directory from the DI configuration
285
        $defaultConfigurationDir = $this->getContainer()->getParameter(DependencyInjectionKeys::APPLICATION_DEFAULT_CONFIGURATION_DIR);
286
287
        // load the directories that has to be parsed for configuration files1
288
        foreach ($this->getDefaultLibraries() as $defaultLibrary) {
289
            // initialize the directory name
290
            $directory = implode(
291
                DIRECTORY_SEPARATOR,
292
                array_merge(
293
                    array($vendorDir),
294
                    explode('/', $defaultLibrary),
295
                    explode('/', $defaultConfigurationDir)
296
                )
297
            );
298
299
            // query whether or not the directory is available1
300
            if (is_dir($directory)) {
301
                $directories[] = $directory;
302
            }
303
        }
304
305
        // load the assumed installation directory
306
        $installationDir = $this->input->getOption(InputOptionKeysInterface::INSTALLATION_DIR);
307
308
        // initialize the default custom configuration directory
309
        $customConfigurationDir = implode(
310
            DIRECTORY_SEPARATOR,
311
            array_merge(
312
                array($installationDir),
313
                explode('/', $this->getContainer()->getParameter(DependencyInjectionKeys::APPLICATION_CUSTOM_CONFIGURATION_DIR))
314
            )
315
        );
316
317
        // query whether or not a custom configuration directory has been speified, if yes override the default one
318
        if ($this->input->hasOptionSpecified(InputOptionKeysInterface::CUSTOM_CONFIGURATION_DIR) && $this->input->getOption(InputOptionKeysInterface::CUSTOM_CONFIGURATION_DIR)) {
319
            $customConfigurationDir = $this->input->getOption(InputOptionKeysInterface::CUSTOM_CONFIGURATION_DIR);
320
        }
321
322
        // specify the default directory for custom configuration files
323
        if (is_dir($customConfigurationDir)) {
324
            $directories[] = $customConfigurationDir;
325
        }
326
327
        // load and return the configuration from the files found in the passed directories
328
        return $this->configurationFactory->factoryFromDirectories($installationDir, $defaultConfigurationDir, $directories, $format, $params, $paramsFile);
0 ignored issues
show
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

328
        return $this->configurationFactory->factoryFromDirectories($installationDir, $defaultConfigurationDir, $directories, $format, /** @scrutinizer ignore-type */ $params, $paramsFile);
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

328
        return $this->configurationFactory->factoryFromDirectories($installationDir, $defaultConfigurationDir, $directories, $format, $params, /** @scrutinizer ignore-type */ $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

328
        return $this->configurationFactory->factoryFromDirectories(/** @scrutinizer ignore-type */ $installationDir, $defaultConfigurationDir, $directories, $format, $params, $paramsFile);
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 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
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

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