Completed
Push — master ( 6197de...1878e1 )
by Tim
02:31
created

ConfigurationLoader::getDefaultDirectory()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 13
rs 10
1
<?php
2
3
/**
4
 * TechDivision\Import\Cli\ConfigurationLoader
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 Psr\Log\LogLevel;
24
use Ramsey\Uuid\Uuid;
25
use TechDivision\Import\ConfigurationInterface;
26
use TechDivision\Import\Configuration\Jms\Configuration\Database;
27
use TechDivision\Import\Cli\Command\InputArgumentKeys;
28
use TechDivision\Import\Cli\Command\InputOptionKeys;
29
use TechDivision\Import\Cli\Utils\DependencyInjectionKeys;
30
use TechDivision\Import\Cli\Utils\MagentoConfigurationKeys;
31
32
/**
33
 * The configuration loader implementation.
34
 *
35
 * @author    Tim Wagner <[email protected]>
36
 * @copyright 2016 TechDivision GmbH <[email protected]>
37
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
38
 * @link      https://github.com/techdivision/import-cli-simple
39
 * @link      http://www.techdivision.com
40
 */
41
class ConfigurationLoader extends SimpleConfigurationLoader
42
{
43
44
    /**
45
     * Factory implementation to create a new initialized configuration instance.
46
     *
47
     * If command line options are specified, they will always override the
48
     * values found in the configuration file.
49
     *
50
     * @return \TechDivision\Import\ConfigurationInterface The configuration instance
51
     * @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
52
     */
53
    public function load()
54
    {
55
56
        // load the configuration instance
57
        $instance = parent::load();
58
59
        // set the serial that has been specified as command line option (or the default value)
60
        $instance->setSerial($this->input->getOption(InputOptionKeys::SERIAL));
61
62
        // query whether or not an operation name has been specified as command line
63
        // option, if yes override the value from the configuration file
64
        if ($operationName = $this->input->getArgument(InputArgumentKeys::OPERATION_NAME)) {
65
            $instance->setOperationName($operationName);
66
        }
67
68
        // query whether or not a Magento version has been specified as command line
69
        // option, if yes override the value from the configuration file
70
        if ($magentoVersion = $this->input->getOption(InputOptionKeys::MAGENTO_VERSION)) {
71
            $instance->setMagentoVersion($magentoVersion);
72
        }
73
74
        // query whether or not a directory containing the imported files has been specified as command line
75
        // option, if yes override the value from the configuration file
76
        if ($targetDir = $this->input->getOption(InputOptionKeys::TARGET_DIR)) {
77
            $instance->setTargetDir($targetDir);
78
        }
79
80
        // query whether or not a directory containing the archived imported files has been specified as command line
81
        // option, if yes override the value from the configuration file
82
        if ($archiveDir = $this->input->getOption(InputOptionKeys::ARCHIVE_DIR)) {
83
            $instance->setArchiveDir($archiveDir);
84
        }
85
86
        // query whether or not the debug mode has been specified as command line
87
        // option, if yes override the value from the configuration file
88
        if ($archiveArtefacts = $this->input->getOption(InputOptionKeys::ARCHIVE_ARTEFACTS)) {
89
            $instance->setArchiveArtefacts($instance->mapBoolean($archiveArtefacts));
90
        }
91
92
        // query whether or not a source date format has been specified as command
93
        // line  option, if yes override the value from the configuration file
94
        if ($sourceDateFormat = $this->input->getOption(InputOptionKeys::SOURCE_DATE_FORMAT)) {
95
            $instance->setSourceDateFormat($sourceDateFormat);
96
        }
97
98
        // query whether or not the debug mode has been specified as command line
99
        // option, if yes override the value from the configuration file
100
        if ($debugMode = $this->input->getOption(InputOptionKeys::DEBUG_MODE)) {
101
            $instance->setDebugMode($instance->mapBoolean($debugMode));
102
        }
103
104
        // query whether or not the log level has been specified as command line
105
        // option, if yes override the value from the configuration file
106
        if ($logLevel = $this->input->getOption(InputOptionKeys::LOG_LEVEL)) {
107
            $instance->setLogLevel($logLevel);
108
        }
109
110
        // query whether or not the single transaction flag has been specified as command line
111
        // option, if yes override the value from the configuration file
112
        if ($singleTransaction = $this->input->getOption(InputOptionKeys::SINGLE_TRANSACTION)) {
113
            $instance->setSingleTransaction($instance->mapBoolean($singleTransaction));
114
        }
115
116
        // query whether or not the cache flag has been specified as command line
117
        // option, if yes override the value from the configuration file
118
        if ($cacheEnabled = $this->input->getOption(InputOptionKeys::CACHE_ENABLED)) {
119
            $instance->setCacheEnabled($instance->mapBoolean($cacheEnabled));
120
        }
121
122
        // query whether or not we've an valid Magento root directory specified
123
        if ($this->isMagentoRootDir($installationDir = $instance->getInstallationDir())) {
124
            // if yes, add the database configuration
125
            $instance->addDatabase($this->getMagentoDbConnection($installationDir));
0 ignored issues
show
Bug introduced by
$this->getMagentoDbConnection($installationDir) 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

125
            $instance->addDatabase(/** @scrutinizer ignore-type */ $this->getMagentoDbConnection($installationDir));
Loading history...
126
127
            // add the source directory if NOT specified in the configuration file
128
            if (($sourceDir = $instance->getSourceDir()) === null) {
0 ignored issues
show
introduced by
The condition $sourceDir = $instance->getSourceDir() === null is always false.
Loading history...
129
                $instance->setSourceDir($sourceDir = sprintf('%s/var/importexport', $installationDir));
130
            }
131
132
            // add the target directory if NOT specified in the configuration file
133
            if ($instance->getTargetDir() === null) {
0 ignored issues
show
introduced by
The condition $instance->getTargetDir() === null is always false.
Loading history...
134
                $instance->setTargetDir($sourceDir);
135
            }
136
        }
137
138
        // query whether or not a DB ID has been specified as command line
139
        // option, if yes override the value from the configuration file
140
        if ($useDbId = $this->input->getOption(InputOptionKeys::USE_DB_ID)) {
141
            $instance->setUseDbId($useDbId);
142
        } else {
143
            // query whether or not a PDO DSN has been specified as command line
144
            // option, if yes override the value from the configuration file
145
            if ($dsn = $this->input->getOption(InputOptionKeys::DB_PDO_DSN)) {
146
                // first REMOVE all other database configurations
147
                $instance->clearDatabases();
148
149
                // add the database configuration
150
                $instance->addDatabase(
151
                    $this->newDatabaseConfiguration(
152
                        $dsn,
153
                        $this->input->getOption(InputOptionKeys::DB_USERNAME),
154
                        $this->input->getOption(InputOptionKeys::DB_PASSWORD)
155
                    )
156
                );
157
            }
158
        }
159
160
        // extend the plugins with the main configuration instance
161
        /** @var \TechDivision\Import\Cli\Configuration\Subject $subject */
162
        foreach ($instance->getPlugins() as $plugin) {
163
            // set the configuration instance on the plugin
164
            $plugin->setConfiguration($instance);
165
166
            // query whether or not the plugin has subjects configured
167
            if ($subjects = $plugin->getSubjects()) {
168
                // extend the plugin's subjects with the main configuration instance
169
                /** @var \TechDivision\Import\Cli\Configuration\Subject $subject */
170
                foreach ($subjects as $subject) {
171
                    // set the configuration instance on the subject
172
                    $subject->setConfiguration($instance);
173
                }
174
            }
175
        }
176
177
        // query whether or not the debug mode is enabled and log level
178
        // has NOT been overwritten with a commandline option
179
        if ($instance->isDebugMode() && !$this->input->getOption(InputOptionKeys::LOG_LEVEL)) {
180
            // set debug log level, if log level has NOT been overwritten on command line
181
            $instance->setLogLevel(LogLevel::DEBUG);
182
        }
183
184
        // prepend the array with the Magento Edition specific core libraries
185
        $instance->setExtensionLibraries(
186
            array_merge(
187
                $this->getDefaultLibraries($instance->getMagentoEdition()),
188
                $instance->getExtensionLibraries()
189
            )
190
        );
191
192
        // load the extension libraries, if configured
193
        $this->libraryLoader->load($instance);
194
195
        // register the configured aliases in the DI container, this MUST
196
        // happen after the libraries have been loaded, else it would not
197
        // be possible to override existing aliases
198
        $this->initializeAliases($instance);
199
200
        // return the initialized configuration instance
201
        return $instance;
202
    }
203
204
    /**
205
     * Query whether or not, the passed directory is a Magento root directory.
206
     *
207
     * @param string $dir The directory to query
208
     *
209
     * @return boolean TRUE if the directory is a Magento root directory, else FALSE
210
     */
211
    protected function isMagentoRootDir($dir)
212
    {
213
        return is_file($this->getMagentoEnv($dir));
214
    }
215
216
    /**
217
     * Return's the path to the Magento file with the environment configuration.
218
     *
219
     * @param string $dir The path to the Magento root directory
220
     *
221
     * @return string The path to the Magento file with the environment configuration
222
     */
223
    protected function getMagentoEnv($dir)
224
    {
225
        return sprintf('%s/app/etc/env.php', $dir);
226
    }
227
228
    /**
229
     * Return's the requested Magento DB connction data.
230
     *
231
     * @param string $dir            The path to the Magento root directory
232
     * @param string $connectionName The connection name to return the data for
233
     *
234
     * @return array The connection data
235
     * @throws \Exception Is thrown, if the requested DB connection is not available
236
     */
237
    protected function getMagentoDbConnection($dir, $connectionName = 'default')
238
    {
239
240
        // load the magento environment
241
        $env = require $this->getMagentoEnv($dir);
242
243
        // query whether or not, the requested connection is available
244
        if (isset($env[MagentoConfigurationKeys::DB][MagentoConfigurationKeys::CONNECTION][$connectionName])) {
245
            // load the connection data
246
            $connection = $env[MagentoConfigurationKeys::DB][MagentoConfigurationKeys::CONNECTION][$connectionName];
247
248
            // create and return a new database configuration
249
            return $this->newDatabaseConfiguration(
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->newDatabas...Keys::PASSWORD], false) returns the type TechDivision\Import\Conf...\Configuration\Database which is incompatible with the documented return type array.
Loading history...
250
                $this->newDsn($connection[MagentoConfigurationKeys::HOST], $connection[MagentoConfigurationKeys::DBNAME]),
251
                $connection[MagentoConfigurationKeys::USERNAME],
252
                $connection[MagentoConfigurationKeys::PASSWORD],
253
                false
254
            );
255
        }
256
257
        // throw an execption if not
258
        throw new \Exception(sprintf('Requested Magento DB connection "%s" not found in Magento "%s"', $connectionName, $dir));
259
    }
260
261
    /**
262
     * Create's and return's a new database configuration instance, initialized with
263
     * the passed values.
264
     *
265
     * @param string      $dsn      The DSN to use
266
     * @param string      $username The username to  use
267
     * @param string|null $password The passed to use
268
     * @param boolean     $default  TRUE if this should be the default connection
269
     * @param string      $id       The ID to use
270
     *
271
     * @return \TechDivision\Import\Configuration\Jms\Configuration\Database The database configuration instance
272
     */
273
    protected function newDatabaseConfiguration($dsn, $username = 'root', $password = null, $default = true, $id = null)
274
    {
275
276
        // initialize a new database configuration
277
        $database = new Database();
278
        $database->setDsn($dsn);
279
        $database->setDefault($default);
280
        $database->setUsername($username);
281
282
        // query whether or not an ID has been passed
283
        if ($id === null) {
284
            $id = Uuid::uuid4()->__toString();
0 ignored issues
show
Bug introduced by
The method __toString() does not exist on Ramsey\Uuid\UuidInterface. Did you maybe mean toString()? ( Ignorable by Annotation )

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

284
            $id = Uuid::uuid4()->/** @scrutinizer ignore-call */ __toString();

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...
285
        }
286
287
        // set the ID
288
        $database->setId($id);
289
290
        // query whether or not a password has been passed
291
        if ($password) {
292
            $database->setPassword($password);
293
        }
294
295
        // return the database configuration
296
        return $database;
297
    }
298
299
    /**
300
     * Create's and return's a new DSN from the passed values.
301
     *
302
     * @param string $host    The host to use
303
     * @param string $dbName  The database name to use
304
     * @param string $charset The charset to use
305
     *
306
     * @return string The DSN
307
     */
308
    protected function newDsn($host, $dbName, $charset = 'utf8')
309
    {
310
        return sprintf('mysql:host=%s;dbname=%s;charset=%s', $host, $dbName, $charset);
311
    }
312
313
    /**
314
     * Return's the Magento Edition specific default libraries. Supported Magento Editions are CE or EE.
315
     *
316
     * @param string $magentoEdition The Magento Edition to return the libraries for
317
     *
318
     * @return array The Magento Edition specific default libraries
319
     * @throws \Exception Is thrown, if the passed Magento Edition is NOT supported
320
     */
321
    protected function getDefaultLibraries($magentoEdition)
322
    {
323
324
        // load the default libraries from the configuration
325
        $defaultLibraries = $this->getContainer()->getParameter(DependencyInjectionKeys::APPLICATION_DEFAULT_LIBRARIES);
326
327
        // query whether or not, default libraries for the passed edition are available
328
        if (isset($defaultLibraries[$edition = strtolower($magentoEdition)])) {
329
            return $defaultLibraries[$edition];
330
        }
331
332
        // throw an exception, if the passed edition is not supported
333
        throw new \Exception(
334
            sprintf(
335
                'Default libraries for Magento \'%s\' not supported (MUST be one of CE or EE)',
336
                $magentoEdition
337
            )
338
        );
339
    }
340
341
    /**
342
     * Registers the configured aliases in the DI container.
343
     *
344
     * @param \TechDivision\Import\ConfigurationInterface $configuration The configuration with the aliases to register
345
     *
346
     * @return void
347
     */
348
    protected function initializeAliases(ConfigurationInterface $configuration)
349
    {
350
351
        // load the DI aliases
352
        $aliases = $configuration->getAliases();
353
354
        // register the DI aliases
355
        foreach ($aliases as $alias) {
356
            $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

356
            $this->getContainer()->/** @scrutinizer ignore-call */ setAlias($alias->getId(), $alias->getTarget());
Loading history...
357
        }
358
    }
359
}
360