Passed
Push — master ( 3262e9...f45074 )
by Tim
04:46
created

LibraryLoader::loadConfiguration()   B

Complexity

Conditions 7
Paths 13

Size

Total Lines 43
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 7
eloc 16
c 2
b 0
f 0
nc 13
nop 3
dl 0
loc 43
ccs 0
cts 24
cp 0
crap 56
rs 8.8333
1
<?php
2
3
/**
4
 * TechDivision\Import\Cli\Configuration\LibraryLoader
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\Configuration;
22
23
use Symfony\Component\Config\FileLocator;
24
use Symfony\Component\Config\Loader\LoaderInterface;
25
use Symfony\Component\DependencyInjection\ContainerInterface;
26
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
27
use TechDivision\Import\Configuration\ConfigurationInterface;
28
use TechDivision\Import\Cli\Utils\DependencyInjectionKeys;
29
30
/**
31
 * The library loader implementation.
32
 *
33
 * @author    Tim Wagner <[email protected]>
34
 * @copyright 2016 TechDivision GmbH <[email protected]>
35
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
36
 * @link      https://github.com/techdivision/import-cli-simple
37
 * @link      http://www.techdivision.com
38
 */
39
class LibraryLoader
40
{
41
42
    /**
43
     * The container instance.
44
     *
45
     * @var \Symfony\Component\DependencyInjection\ContainerInterface
46
     */
47
    protected $container;
48
49
    /**
50
     * Initializes the configuration loader.
51
     *
52
     * @param \Symfony\Component\DependencyInjection\ContainerInterface $container The container instance
53
     */
54
    public function __construct(ContainerInterface $container)
55
    {
56
        $this->container = $container;
57
    }
58
59
    /**
60
     * Return's the DI container instance.
61
     *
62
     * @return \Symfony\Component\DependencyInjection\ContainerInterface The DI container instance
63
     */
64
    protected function getContainer()
65
    {
66
        return $this->container;
67
    }
68
69
    /**
70
     * Return's the absolute path to the actual vendor directory.
71
     *
72
     * @return string The absolute path to the actual vendor directory
73
     */
74
    protected function getVendorDir()
75
    {
76
        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...
77
    }
78
79
    /**
80
     * Return's the relative path to the custom configuration directory.
81
     *
82
     * @return string The relative path to the custom configuration directory
83
     */
84
    protected function getCustomConfigurationDir()
85
    {
86
        return $this->getContainer()->getParameter(DependencyInjectionKeys::APPLICATION_CUSTOM_CONFIGURATION_DIR);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getContain...STOM_CONFIGURATION_DIR) also could return the type array|boolean which is incompatible with the documented return type string.
Loading history...
87
    }
88
89
    /**
90
     * Load's the external libraries registered in the passed configuration.
91
     *
92
     * @param \TechDivision\Import\Configuration\ConfigurationInterface $configuration The configuration instance
93
     *
94
     * @return void
95
     */
96
    public function load(ConfigurationInterface $configuration)
97
    {
98
99
        // load the DI container, vendor and custom configuration
100
        // directory as well as the Magento version
101
        $container = $this->getContainer();
102
        $vendorDir = $this->getVendorDir();
103
        $magentoVersion = $configuration->getMagentoVersion();
104
        $customConfigurationDir = $this->getCustomConfigurationDir();
105
106
        // initialize the default loader and load the DI configuration for the this library
107
        $defaultLoader = new XmlFileLoader($container, new FileLocator($vendorDir));
108
109
        // load the DI configuration for all the extension libraries
110
        foreach ($configuration->getExtensionLibraries() as $library) {
111
            $this->loadConfiguration($defaultLoader, $magentoVersion, sprintf('%s/%s', $vendorDir, $library));
112
        }
113
114
        // register autoloaders for additional vendor directories
115
        $customLoader = new XmlFileLoader($container, new FileLocator());
116
        foreach ($configuration->getAdditionalVendorDirs() as $additionalVendorDir) {
117
            // try to load the vendor directory's auto loader, if available. Otherwise we assume
118
            // that the vendor directory uses an autoloader that has already been loaded, e. g. in
119
            // case of Magento which has app/code registered as vendor directory what we want to use
120
            if (file_exists($autoLoader = $additionalVendorDir->getVendorDir() . '/autoload.php')) {
121
                require $autoLoader;
122
            }
123
124
            // try to load the DI configuration for the configured extension libraries
125
            foreach ($additionalVendorDir->getLibraries() as $library) {
126
                // concatenate the directory for the library
127
                $libDir = sprintf('%s/%s', $additionalVendorDir->getVendorDir(), $library);
128
                // prepend the installation directory, if the vendor is relative to it
129
                if ($additionalVendorDir->isRelative()) {
130
                    $libDir = sprintf('%s/%s', $configuration->getInstallationDir(), $libDir);
131
                }
132
133
                // create the canonicalized absolute pathname and try to load the configuration
134
                if ($libraryDir = realpath($libDir)) {
135
                    $this->loadConfiguration($customLoader, $magentoVersion, $libraryDir);
136
                } else {
137
                    throw new \Exception(sprintf('Can\'t find find library directory "%s"', $libDir));
138
                }
139
            }
140
        }
141
142
        // initialize the project specific configuration loader for the DI configuration
143
        $projectLoader = new XmlFileLoader($container, new FileLocator(getcwd()));
144
145
        // finally load the project specific custom library configuration which overwrites the default one
146
        $this->loadConfiguration($projectLoader, $magentoVersion, $customConfigurationDir);
147
    }
148
149
    /**
150
     * Loads the version specific Symfony DI configuration.
151
     *
152
     * @param \Symfony\Component\Config\Loader\LoaderInterface $loader         The Symfony DI loader instance
153
     * @param string                                           $magentoVersion The Magento Version to load the configuration for
154
     * @param string                                           $libraryDir     The library directory
155
     *
156
     * @return boolean TRUE if the configuration file has been loaded, else FALSE
157
     */
158
    protected function loadConfiguration(LoaderInterface $loader, $magentoVersion, $libraryDir)
159
    {
160
161
        // load the default Symfony Di configuration
162
        if (file_exists($diConfiguration = sprintf('%s/symfony/Resources/config/services.xml', $libraryDir))) {
163
            // load the DI configuration
164
            $loader->load($diConfiguration);
165
            // initialize the array for the directories with the
166
            // available versions that'll override the defaults
167
            $versions = array();
168
            // load the directories that equals the versions custom configuration files are available for
169
            $iterator = new \GlobIterator(sprintf('%s/symfony/Resources/config/*', $libraryDir), \FilesystemIterator::SKIP_DOTS);
170
            // iterate over the subdirectories
171
            while ($iterator->valid()) {
172
                // query whether or not we've a directory, if yes we
173
                // assume it'll contain additional version information
174
                if ($iterator->isDir()) {
175
                    $versions[] = $iterator->current()->getPathname();
176
                }
177
                // continue reading the directry content
178
                $iterator->next();
179
            }
180
181
            // sort the directories descending by their version
182
            usort($versions, 'version_compare');
183
            krsort($versions);
184
185
            // override DI configuration with version specifc data
186
            foreach ($versions as $version) {
187
                if (version_compare(basename($version), $magentoVersion, '<=')) {
188
                    if (file_exists($diConfiguration = sprintf('%s/services.xml', $version))) {
189
                        // load the version specific DI configuration
190
                        $loader->load($diConfiguration);
191
                    }
192
                }
193
            }
194
195
            // return TRUE if the configuration has been loaded
196
            return true;
197
        }
198
199
        // return FALSE if the configuration file has NOT been available
200
        return false;
201
    }
202
}
203