ConfigurationLoader   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 262
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 78
c 5
b 0
f 0
dl 0
loc 262
ccs 0
cts 89
cp 0
rs 10
wmc 27

6 Methods

Rating   Name   Duplication   Size   Complexity  
A newDatabaseConfiguration() 0 29 4
C load() 0 104 14
A initializeAliases() 0 9 2
A getDefaultLibrariesByMagentoEdition() 0 16 2
A getMagentoDbConnection() 0 30 4
A newDsn() 0 3 1
1
<?php
2
3
/**
4
 * TechDivision\Import\Cli\ConfigurationLoader
5
 *
6
 * PHP version 7
7
 *
8
 * @author    Tim Wagner <[email protected]>
9
 * @copyright 2016 TechDivision GmbH <[email protected]>
10
 * @license   https://opensource.org/licenses/MIT
11
 * @link      https://github.com/techdivision/import-cli-simple
12
 * @link      http://www.techdivision.com
13
 */
14
15
namespace TechDivision\Import\Cli;
16
17
use Psr\Log\LogLevel;
18
use Ramsey\Uuid\Uuid;
19
use TechDivision\Import\Configuration\ConfigurationInterface;
20
use TechDivision\Import\Configuration\Jms\Configuration\Database;
21
use TechDivision\Import\Utils\InputOptionKeysInterface;
22
use TechDivision\Import\Utils\InputArgumentKeysInterface;
23
use TechDivision\Import\Cli\Utils\DependencyInjectionKeys;
24
use TechDivision\Import\Cli\Utils\MagentoConfigurationKeys;
25
26
/**
27
 * The configuration loader implementation.
28
 *
29
 * @author    Tim Wagner <[email protected]>
30
 * @copyright 2016 TechDivision GmbH <[email protected]>
31
 * @license   https://opensource.org/licenses/MIT
32
 * @link      https://github.com/techdivision/import-cli-simple
33
 * @link      http://www.techdivision.com
34
 */
35
class ConfigurationLoader extends SimpleConfigurationLoader
36
{
37
38
    /**
39
     * Factory implementation to create a new initialized configuration instance.
40
     *
41
     * If command line options are specified, they will always override the
42
     * values found in the configuration file.
43
     *
44
     * @return \TechDivision\Import\Configuration\ConfigurationInterface The configuration instance
45
     * @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
46
     */
47
    public function load()
48
    {
49
50
        // load the configuration instance
51
        $instance = parent::load();
52
53
        // query whether or not a shortcut has been specified as command line
54
        // argument, if yes override the value from the configuration file
55
        if ($this->input->hasArgument(InputArgumentKeysInterface::SHORTCUT)) {
56
            $instance->setShortcut($this->input->getArgument(InputArgumentKeysInterface::SHORTCUT));
57
        }
58
59
        // query whether or not an explicit filename has been specified as command
60
        // line argument, if yes override the value from the configuration file
61
        if ($this->input->hasArgument(InputArgumentKeysInterface::FILENAME) &&
62
            $filename = $this->input->getArgument(InputArgumentKeysInterface::FILENAME)
63
        ) {
64
            // try to load the realpath of the given filename
65
            $filename = realpath($filename);
66
            // query whether or not the file is available
67
            if (is_file($filename)) {
68
                // set the filename in the configuration
69
                $instance->setFilename($filename);
70
                // AND update the source directory to the directory
71
                // where the specified file has been sourced
72
                $instance->setSourceDir(dirname($filename));
73
            } else {
74
                throw new \InvalidArgumentException(
75
                    sprintf('Can\'t find file "%s" that has to be imported', $this->input->getArgument(InputArgumentKeysInterface::FILENAME))
76
                );
77
            }
78
        }
79
80
        // query whether or not operation names has been specified as command line
81
        // option, if yes override the value from the configuration file
82
        if ($this->input->hasArgument(InputArgumentKeysInterface::OPERATION_NAMES)) {
83
            // load the operation names from the commandline
84
            $operationNames = $this->input->getArgument(InputArgumentKeysInterface::OPERATION_NAMES);
85
            // append the names of the operations we want to execute to the configuration
86
            foreach ($operationNames as $operationName) {
87
                $instance->addOperationName($operationName);
88
            }
89
        }
90
91
        // query whether or not we've an valid Magento root directory specified
92
        $configurationDir = $instance->getEtcDir() ?: $instance->getInstallationDir() . SimpleConfigurationLoader::CONFIGENVPATH;
93
        if ($this->isMagentoRootDir($configurationDir)) {
94
            // if yes, add the database configuration
95
            $instance->addDatabase($this->getMagentoDbConnection($configurationDir));
0 ignored issues
show
Bug introduced by
$this->getMagentoDbConnection($configurationDir) of type array is incompatible with the type TechDivision\Import\Conf...eConfigurationInterface expected by parameter $database of TechDivision\Import\Conf...nterface::addDatabase(). ( Ignorable by Annotation )

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

95
            $instance->addDatabase(/** @scrutinizer ignore-type */ $this->getMagentoDbConnection($configurationDir));
Loading history...
96
        }
97
98
        // query whether or not a DB ID has been specified as command line
99
        // option, if yes override the value from the configuration file
100
        if ($useDbId = $this->input->getOption(InputOptionKeysInterface::USE_DB_ID)) {
101
            $instance->setUseDbId($useDbId);
102
        } else {
103
            // query whether or not a PDO DSN has been specified as command line
104
            // option, if yes override the value from the configuration file
105
            if ($dsn = $this->input->getOption(InputOptionKeysInterface::DB_PDO_DSN)) {
106
                // first REMOVE all other database configurations
107
                $instance->clearDatabases();
108
109
                // add the database configuration
110
                $instance->addDatabase(
111
                    $this->newDatabaseConfiguration(
112
                        $dsn,
113
                        $this->input->getOption(InputOptionKeysInterface::DB_USERNAME),
114
                        $this->input->getOption(InputOptionKeysInterface::DB_PASSWORD)
115
                    )
116
                );
117
            }
118
        }
119
120
        // query whether or not a DB ID has been specified as command line
121
        // option, if yes override the value from the configuration file
122
        if ($tablePrefix = $this->input->getOption(InputOptionKeysInterface::DB_TABLE_PREFIX)) {
123
            $instance->getDatabase()->setTablePrefix($tablePrefix);
124
        }
125
126
        // query whether or not the debug mode is enabled and log level
127
        // has NOT been overwritten with a commandline option
128
        if ($instance->isDebugMode() && !$this->input->getOption(InputOptionKeysInterface::LOG_LEVEL)) {
129
            // set debug log level, if log level has NOT been overwritten on command line
130
            $instance->setLogLevel(LogLevel::DEBUG);
131
        }
132
133
        // prepend the array with the Magento Edition specific core libraries
134
        $instance->setExtensionLibraries(
135
            array_merge(
136
                $this->getDefaultLibrariesByMagentoEdition($instance->getMagentoEdition()),
137
                $instance->getExtensionLibraries()
138
            )
139
        );
140
141
        // load the extension libraries, if configured
142
        $this->libraryLoader->load($instance);
143
144
        // register the configured aliases in the DI container, this MUST
145
        // happen after the libraries have been loaded, else it would not
146
        // be possible to override existing aliases
147
        $this->initializeAliases($instance);
148
149
        // return the initialized configuration instance
150
        return $instance;
151
    }
152
153
    /**
154
     * Return's the requested Magento DB connection data.
155
     *
156
     * @param string $dir            The path to the Magento root directory
157
     * @param string $connectionName The connection name to return the data for
158
     *
159
     * @return array The connection data
160
     * @throws \Exception Is thrown, if the requested DB connection is not available
161
     */
162
    protected function getMagentoDbConnection($dir, $connectionName = 'default')
163
    {
164
165
        // load the magento environment
166
        $env = require $this->getMagentoEnv($dir);
167
168
        // query whether or not, the requested connection is available
169
        if (isset($env[MagentoConfigurationKeys::DB][MagentoConfigurationKeys::CONNECTION][$connectionName])) {
170
            // load the databaase connection
171
            $db = $env[MagentoConfigurationKeys::DB];
172
            // load the connection data
173
            $connection = $db[MagentoConfigurationKeys::CONNECTION][$connectionName];
174
175
            // try to load port and table prefix (they're optional)
176
            $port = isset($connection[MagentoConfigurationKeys::PORT]) ? $connection[MagentoConfigurationKeys::PORT] : 3306;
177
            $tablePrefix = isset($db[MagentoConfigurationKeys::TABLE_PREFIX]) ? $db[MagentoConfigurationKeys::TABLE_PREFIX] : null;
178
179
            // create and return a new database configuration
180
            return $this->newDatabaseConfiguration(
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->newDatabas...se, null, $tablePrefix) returns the type TechDivision\Import\Conf...\Configuration\Database which is incompatible with the documented return type array.
Loading history...
181
                $this->newDsn($connection[MagentoConfigurationKeys::HOST], $port, $connection[MagentoConfigurationKeys::DBNAME]),
182
                $connection[MagentoConfigurationKeys::USERNAME],
183
                $connection[MagentoConfigurationKeys::PASSWORD],
184
                false,
185
                null,
186
                $tablePrefix
187
            );
188
        }
189
190
        // throw an execption if not
191
        throw new \Exception(sprintf('Requested Magento DB connection "%s" not found in Magento "%s"', $connectionName, $dir));
192
    }
193
194
    /**
195
     * Create's and return's a new database configuration instance, initialized with
196
     * the passed values.
197
     *
198
     * @param string      $dsn         The DSN to use
199
     * @param string      $username    The username to  use
200
     * @param string|null $password    The passed to use
201
     * @param boolean     $default     TRUE if this should be the default connection
202
     * @param string      $id          The ID to use
203
     * @param string      $tablePrefix The table prefix to use
204
     *
205
     * @return \TechDivision\Import\Configuration\Jms\Configuration\Database The database configuration instance
206
     */
207
    protected function newDatabaseConfiguration($dsn, $username = 'root', $password = null, $default = true, $id = null, $tablePrefix = null)
208
    {
209
210
        // initialize a new database configuration
211
        $database = new Database();
212
        $database->setDsn($dsn);
213
        $database->setDefault($default);
214
        $database->setUsername($username);
215
216
        // query whether or not an ID has been passed
217
        if ($id === null) {
218
            $id = Uuid::uuid4()->__toString();
219
        }
220
221
        // set the ID
222
        $database->setId($id);
223
224
        // query whether or not a password has been passed
225
        if ($password) {
226
            $database->setPassword($password);
227
        }
228
229
        // query whether or not a table prefix has been passed
230
        if ($tablePrefix) {
231
            $database->setTablePrefix($tablePrefix);
232
        }
233
234
        // return the database configuration
235
        return $database;
236
    }
237
238
    /**
239
     * Create's and return's a new DSN from the passed values.
240
     *
241
     * @param string  $host    The host to use
242
     * @param integer $port    The port to use
243
     * @param string  $dbName  The database name to use
244
     * @param string  $charset The charset to use
245
     *
246
     * @return string The DSN
247
     */
248
    protected function newDsn($host, $port = 3306, $dbName = 'magento', $charset = 'utf8')
249
    {
250
        return sprintf('mysql:host=%s;port=%d;dbname=%s;charset=%s', $host, $port, $dbName, $charset);
251
    }
252
253
    /**
254
     * Return's the Magento Edition specific default libraries. Supported Magento Editions are CE or EE.
255
     *
256
     * @param string $magentoEdition The Magento Edition to return the libraries for
257
     *
258
     * @return array The Magento Edition specific default libraries
259
     * @throws \Exception Is thrown, if the passed Magento Edition is NOT supported
260
     */
261
    protected function getDefaultLibrariesByMagentoEdition($magentoEdition)
262
    {
263
264
        // load the default libraries from the configuration
265
        $defaultLibraries = $this->getContainer()->getParameter(DependencyInjectionKeys::APPLICATION_DEFAULT_LIBRARIES);
266
267
        // query whether or not, default libraries for the passed edition are available
268
        if (isset($defaultLibraries[$edition = strtolower($magentoEdition)])) {
269
            return $defaultLibraries[$edition];
270
        }
271
272
        // throw an exception, if the passed edition is not supported
273
        throw new \Exception(
274
            sprintf(
275
                'Default libraries for Magento \'%s\' not supported (MUST be one of CE or EE)',
276
                $magentoEdition
277
            )
278
        );
279
    }
280
281
    /**
282
     * Registers the configured aliases in the DI container.
283
     *
284
     * @param \TechDivision\Import\Configuration\ConfigurationInterface $configuration The configuration with the aliases to register
285
     *
286
     * @return void
287
     */
288
    protected function initializeAliases(ConfigurationInterface $configuration)
289
    {
290
291
        // load the DI aliases
292
        $aliases = $configuration->getAliases();
293
294
        // register the DI aliases
295
        foreach ($aliases as $alias) {
296
            $this->getContainer()->setAlias($alias->getId(), $alias->getTarget());
0 ignored issues
show
Bug introduced by
The method setAlias() does not exist on Symfony\Component\Depend...tion\ContainerInterface. It seems like you code against a sub-type of Symfony\Component\Depend...tion\ContainerInterface such as Symfony\Component\Depend...ection\ContainerBuilder or Symfony\Component\Depend...ection\ContainerBuilder. ( Ignorable by Annotation )

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

296
            $this->getContainer()->/** @scrutinizer ignore-call */ setAlias($alias->getId(), $alias->getTarget());
Loading history...
297
        }
298
    }
299
}
300