Completed
Pull Request — master (#50)
by Tim
03:01
created

AbstractImportCommand::configure()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 115
Code Lines 93

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 115
ccs 0
cts 113
cp 0
rs 8.2857
cc 1
eloc 93
nc 1
nop 0
crap 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * TechDivision\Import\Cli\Command\ImportCommandTrait
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\Command;
22
23
use Rhumsaa\Uuid\Uuid;
24
use Psr\Log\LogLevel;
25
use Monolog\Logger;
26
use Monolog\Handler\ErrorLogHandler;
27
use JMS\Serializer\SerializerBuilder;
28
use TechDivision\Import\Cli\Simple;
29
use TechDivision\Import\Cli\Configuration;
30
use TechDivision\Import\Cli\Services\ImportProcessorFactory;
31
use TechDivision\Import\Cli\Services\RegistryProcessorFactory;
32
use Symfony\Component\Console\Command\Command;
33
use Symfony\Component\Console\Input\InputOption;
34
use Symfony\Component\Console\Input\InputInterface;
35
use Symfony\Component\Console\Output\OutputInterface;
36
use Symfony\Component\Console\Input\InputArgument;
37
use TechDivision\Import\Cli\Configuration\Database;
38
39
/**
40
 * The abstract import command implementation.
41
 *
42
 * @author    Tim Wagner <[email protected]>
43
 * @copyright 2016 TechDivision GmbH <[email protected]>
44
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
45
 * @link      https://github.com/techdivision/import-cli-simple
46
 * @link      http://www.techdivision.com
47
 */
48
abstract class AbstractImportCommand extends Command
49
{
50
51
    /**
52
     * Configures the current command.
53
     *
54
     * @return void
55
     * @see \Symfony\Component\Console\Command\Command::configure()
56
     */
57
    protected function configure()
58
    {
59
60
        // initialize the command with the required/optional options
61
        $this->addArgument(
62
            InputArgumentKeys::OPERATION_NAME,
63
            InputArgument::OPTIONAL,
64
            'The operation that has to be used for the import, one of "add-update", "replace" or "delete"',
65
            InputArgumentKeys::OPERATION_NAME_ARG_REPLACE
66
        )
67
        ->addOption(
68
            InputOptionKeys::CONFIGURATION,
69
            null,
70
            InputOption::VALUE_REQUIRED,
71
            'Specify the pathname to the configuration file to use',
72
            sprintf('%s/techdivision-import.json', getcwd())
73
        )
74
        ->addOption(
75
            InputOptionKeys::INSTALLATION_DIR,
76
            null,
77
            InputOption::VALUE_REQUIRED,
78
            'The Magento installation directory to which the files has to be imported'
79
        )
80
        ->addOption(
81
            InputOptionKeys::SOURCE_DIR,
82
            null,
83
            InputOption::VALUE_REQUIRED,
84
            'The directory that has to be watched for new files'
85
        )
86
        ->addOption(
87
            InputOptionKeys::TARGET_DIR,
88
            null,
89
            InputOption::VALUE_REQUIRED,
90
            'The target directory with the files that has been imported'
91
        )
92
        ->addOption(
93
            InputOptionKeys::UTILITY_CLASS_NAME,
94
            null,
95
            InputOption::VALUE_REQUIRED,
96
            'The utility class name with the SQL statements'
97
        )
98
        ->addOption(
99
            InputOptionKeys::PREFIX,
100
            null,
101
            InputOption::VALUE_REQUIRED,
102
            'The prefix of the CSV source file(s) that has/have to be imported'
103
        )
104
        ->addOption(
105
            InputOptionKeys::MAGENTO_EDITION,
106
            null,
107
            InputOption::VALUE_REQUIRED,
108
            'The Magento edition to be used, either one of CE or EE'
109
        )
110
        ->addOption(
111
            InputOptionKeys::MAGENTO_VERSION,
112
            null,
113
            InputOption::VALUE_REQUIRED,
114
            'The Magento version to be used, e. g. 2.1.2'
115
        )
116
        ->addOption(
117
            InputOptionKeys::SOURCE_DATE_FORMAT,
118
            null,
119
            InputOption::VALUE_REQUIRED,
120
            'The date format used in the CSV file(s)'
121
        )
122
        ->addOption(
123
            InputOptionKeys::USE_DB_ID,
124
            null,
125
            InputOption::VALUE_REQUIRED,
126
            'The explicit database ID used for the actual import process'
127
        )
128
        ->addOption(
129
            InputOptionKeys::DB_PDO_DSN,
130
            null,
131
            InputOption::VALUE_REQUIRED,
132
            'The DSN used to connect to the Magento database where the data has to be imported, e. g. mysql:host=127.0.0.1;dbname=magento'
133
        )
134
        ->addOption(
135
            InputOptionKeys::DB_USERNAME,
136
            null,
137
            InputOption::VALUE_REQUIRED,
138
            'The username used to connect to the Magento database'
139
        )
140
        ->addOption(
141
            InputOptionKeys::DB_PASSWORD,
142
            null,
143
            InputOption::VALUE_REQUIRED,
144
            'The password used to connect to the Magento database'
145
        )
146
        ->addOption(
147
            InputOptionKeys::LOG_LEVEL,
148
            null,
149
            InputOption::VALUE_REQUIRED,
150
            'The log level to use'
151
        )
152
        ->addOption(
153
            InputOptionKeys::IGNORE_PID,
154
            null,
155
            InputOption::VALUE_REQUIRED,
156
            'Whether or not an existing PID should be ignored or not'
157
        )
158
        ->addOption(
159
            InputOptionKeys::DEBUG_MODE,
160
            null,
161
            InputOption::VALUE_REQUIRED,
162
            'Whether use the debug mode or not'
163
        )
164
        ->addOption(
165
            InputOptionKeys::PID_FILENAME,
166
            null,
167
            InputOption::VALUE_REQUIRED,
168
            'The explicit PID filename to use',
169
            sprintf('%s/%s', sys_get_temp_dir(), Configuration::PID_FILENAME)
170
        );
171
    }
172
173
    /**
174
     * Factory implementation to create a new initialized configuration instance.
175
     *
176
     * If command line options are specified, they will always override the
177
     * values found in the configuration file.
178
     *
179
     * @param \Symfony\Component\Console\Input\InputInterface $input The Symfony console input instance
180
     *
181
     * @return \TechDivision\Import\Cli\Configuration The configuration instance
182
     * @throws \Exception Is thrown, if the specified configuration file doesn't exist
183
     */
184
    protected function configurationFactory(InputInterface $input)
185
    {
186
187
        // load the configuration filename we want to use
188
        $filename = $input->getOption(InputOptionKeys::CONFIGURATION);
189
190
        // load the JSON data
191
        if (!$jsonData = file_get_contents($filename)) {
192
            throw new \Exception(sprintf('Can\'t load configuration file %s', $filename));
193
        }
194
195
        // initialize the JMS serializer and load the configuration
196
        $serializer = SerializerBuilder::create()->build();
197
        /** @var \TechDivision\Import\Cli\Configuration $instance */
198
        $instance = $serializer->deserialize($jsonData, 'TechDivision\Import\Cli\Configuration', 'json');
199
200
        // query whether or not an operation name has been specified as command line
201
        // option, if yes override the value from the configuration file
202
        if ($input->hasArgument(InputArgumentKeys::OPERATION_NAME)) {
203
            $instance->setOperationName($input->getArgument(InputArgumentKeys::OPERATION_NAME));
204
        }
205
206
        // query whether or not a Magento installation directory has been specified as command line
207
        // option, if yes override the value from the configuration file
208
        if ($installationDir = $input->getOption(InputOptionKeys::INSTALLATION_DIR)) {
209
            $instance->setInstallationDir($installationDir);
210
        }
211
212
        // query whether or not a directory for the source files has been specified as command line
213
        // option, if yes override the value from the configuration file
214
        if ($sourceDir = $input->getOption(InputOptionKeys::SOURCE_DIR)) {
215
            $instance->setSourceDir($sourceDir);
216
        }
217
218
        // query whether or not a directory containing the imported files has been specified as command line
219
        // option, if yes override the value from the configuration file
220
        if ($targetDir = $input->getOption(InputOptionKeys::TARGET_DIR)) {
221
            $instance->setTargetDir($targetDir);
222
        }
223
224
        // query whether or not a source date format has been specified as command
225
        // line  option, if yes override the value from the configuration file
226
        if ($sourceDateFormat = $input->getOption(InputOptionKeys::SOURCE_DATE_FORMAT)) {
227
            $instance->setSourceDateFormat($sourceDateFormat);
228
        }
229
230
        // query whether or not a Magento edition has been specified as command line
231
        // option, if yes override the value from the configuration file
232
        if ($magentoEdition = $input->getOption(InputOptionKeys::MAGENTO_EDITION)) {
233
            $instance->setMagentoEdition($magentoEdition);
234
        }
235
236
        // query whether or not a Magento version has been specified as command line
237
        // option, if yes override the value from the configuration file
238
        if ($magentoVersion = $input->getOption(InputOptionKeys::MAGENTO_VERSION)) {
239
            $instance->setMagentoVersion($magentoVersion);
240
        }
241
242
        // query whether or not a DB ID has been specified as command line
243
        // option, if yes override the value from the configuration file
244
        if ($useDbId = $input->getOption(InputOptionKeys::USE_DB_ID)) {
245
            $instance->setUseDbId($useDbId);
246
        } else {
247
            // query whether or not a PDO DSN has been specified as command line
248
            // option, if yes override the value from the configuration file
249
            if ($dsn = $input->getOption(InputOptionKeys::DB_PDO_DSN)) {
250
                // first REMOVE all other database configurations
251
                $instance->clearDatabases();
252
253
                // initialize a new database configuration
254
                $database = new Database();
255
                $database->setId(Uuid::uuid4()->__toString());
256
                $database->setDefault(true);
257
                $database->setDsn($dsn);
258
259
                // query whether or not a DB username has been specified as command line
260
                // option, if yes override the value from the configuration file
261
                if ($username = $input->getOption(InputOptionKeys::DB_USERNAME)) {
262
                    $database->setUsername($username);
263
                }
264
265
                // query whether or not a DB password has been specified as command line
266
                // option, if yes override the value from the configuration file
267
                if ($password = $input->getOption(InputOptionKeys::DB_PASSWORD)) {
268
                    $database->setPassword($password);
269
                }
270
271
                // add the database configuration
272
                $instance->addDatabase($database);
273
            }
274
        }
275
276
        // query whether or not the debug mode has been specified as command line
277
        // option, if yes override the value from the configuration file
278
        if ($debugMode = $input->getOption(InputOptionKeys::DEBUG_MODE)) {
279
            $instance->setDebugMode($instance->mapBoolean($debugMode));
280
        }
281
282
        // query whether or not the ignore PID flag has been specified as command line
283
        // option, if yes override the value from the configuration file
284
        if ($ignorePid = $input->getOption(InputOptionKeys::IGNORE_PID)) {
285
            $instance->setIgnorePid($instance->mapBoolean($ignorePid));
286
        }
287
288
        // query whether or not the log level has been specified as command line
289
        // option, if yes override the value from the configuration file
290
        if ($logLevel = $input->getOption(InputOptionKeys::LOG_LEVEL)) {
291
            $instance->setLogLevel($logLevel);
292
        }
293
294
        // query whether or not a PID filename has been specified as command line
295
        // option, if yes override the value from the configuration file
296
        if ($pidFilename = $input->getOption(InputOptionKeys::PID_FILENAME)) {
297
            $instance->setPidFilename($pidFilename);
298
        }
299
300
        // extend the plugins with the main configuration instance
301
        /** @var \TechDivision\Import\Cli\Configuration\Subject $subject */
302
        foreach ($instance->getPlugins() as $plugin) {
303
            // set the configuration instance on the plugin
304
            $plugin->setConfiguration($instance);
305
306
            // query whether or not the plugin has subjects configured
307
            if ($subjects = $plugin->getSubjects()) {
308
                // extend the plugin's subjects with the main configuration instance
309
                /** @var \TechDivision\Import\Cli\Configuration\Subject $subject */
310
                foreach ($subjects as $subject) {
311
                    // set the configuration instance on the subject
312
                    $subject->setConfiguration($instance);
313
                }
314
            }
315
        }
316
317
        // query whether or not the debug mode is enabled and log level
318
        // has NOT been overwritten with a commandline option
319
        if ($instance->isDebugMode() && !$input->getOption(InputOptionKeys::LOG_LEVEL)) {
320
            // set debug log level, if log level has NOT been overwritten on command line
321
            $instance->setLogLevel(LogLevel::DEBUG);
322
        }
323
324
        // return the initialized configuration instance
325
        return $instance;
326
    }
327
328
    /**
329
     * Executes the current command.
330
     *
331
     * This method is not abstract because you can use this class
332
     * as a concrete class. In this case, instead of defining the
333
     * execute() method, you set the code to execute by passing
334
     * a Closure to the setCode() method.
335
     *
336
     * @param \Symfony\Component\Console\Input\InputInterface   $input  An InputInterface instance
337
     * @param \Symfony\Component\Console\Output\OutputInterface $output An OutputInterface instance
338
     *
339
     * @return null|int null or 0 if everything went fine, or an error code
340
     * @throws \LogicException When this abstract method is not implemented
341
     * @see \Symfony\Component\Console\Command\Command::execute()
342
     */
343
    protected function execute(InputInterface $input, OutputInterface $output)
344
    {
345
346
        // register the JMS Serializer annotations
347
        \Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace(
348
            'JMS\Serializer\Annotation',
349
            dirname(__DIR__).'/../vendor/jms/serializer/src'
350
        );
351
352
        // load the specified configuration
353
        $configuration = $this->configurationFactory($input);
354
355
        // initialize the PDO connection
356
        $dsn = $configuration->getDatabase()->getDsn();
357
        $username = $configuration->getDatabase()->getUsername();
358
        $password = $configuration->getDatabase()->getPassword();
359
        $connection = new \PDO($dsn, $username, $password);
360
        $connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
361
362
        // initialize the system logger
363
        $systemLogger = new Logger('techdivision/import');
364
        $systemLogger->pushHandler(
365
            new ErrorLogHandler(
366
                ErrorLogHandler::OPERATING_SYSTEM,
367
                $configuration->getLogLevel()
368
            )
369
        );
370
371
        // initialize the registry/import processor
372
        $registryProcessor = RegistryProcessorFactory::factory($connection, $configuration);
373
        $importProcessor = ImportProcessorFactory::factory($connection, $configuration);
374
375
        // initialize the importer
376
        $importer = new Simple(
377
            $systemLogger,
378
            $registryProcessor,
379
            $importProcessor,
380
            $configuration,
381
            $input,
382
            $output
383
        );
384
385
        // start the process
386
        $importer->process();
387
    }
388
}
389