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