Completed
Push — master ( 2029c7...31b598 )
by Tim
9s
created

Configuration::mapBoolean()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
ccs 0
cts 7
cp 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
crap 6
1
<?php
2
3
/**
4
 * TechDivision\Import\Cli\Configuration
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 JMS\Serializer\Annotation\Type;
25
use JMS\Serializer\SerializerBuilder;
26
use JMS\Serializer\Annotation\SerializedName;
27
use TechDivision\Import\ConfigurationInterface;
28
use Symfony\Component\Console\Input\InputInterface;
29
use TechDivision\Import\Cli\Command\InputOptionKeys;
30
use TechDivision\Import\Cli\Command\InputArgumentKeys;
31
use TechDivision\Import\Cli\Configuration\Operation;
32
33
/**
34
 * A simple configuration implementation.
35
 *
36
 * @author    Tim Wagner <[email protected]>
37
 * @copyright 2016 TechDivision GmbH <[email protected]>
38
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
39
 * @link      https://github.com/techdivision/import-cli-simple
40
 * @link      http://www.techdivision.com
41
 */
42
class Configuration implements ConfigurationInterface
43
{
44
45
    /**
46
     * Mapping for boolean values passed on the console.
47
     *
48
     * @var array
49
     */
50
    protected $booleanMapping = array(
51
        'true'  => true,
52
        'false' => false,
53
        '1'     => true,
54
        '0'     => false,
55
        'on'    => true,
56
        'off'   => false
57
    );
58
59
    /**
60
     * The operation name to use.
61
     *
62
     * @var string
63
     * @Type("string")
64
     * @SerializedName("operation-name")
65
     */
66
    protected $operationName;
67
68
    /**
69
     * The Magento edition, EE or CE.
70
     *
71
     * @var string
72
     * @Type("string")
73
     * @SerializedName("magento-edition")
74
     */
75
    protected $magentoEdition = 'CE';
76
77
    /**
78
     * The Magento version, e. g. 2.1.0.
79
     *
80
     * @var string
81
     * @Type("string")
82
     * @SerializedName("magento-version")
83
     */
84
    protected $magentoVersion = '2.1.2';
85
86
    /**
87
     * The Magento installation directory.
88
     *
89
     * @var string
90
     * @Type("string")
91
     * @SerializedName("installation-dir")
92
     */
93
    protected $installationDir;
94
95
    /**
96
     * The source directory that has to be watched for new files.
97
     *
98
     * @var string
99
     * @Type("string")
100
     * @SerializedName("source-dir")
101
     */
102
    protected $sourceDir;
103
104
    /**
105
     * The target directory with the files that has been imported.
106
     *
107
     * @var string
108
     * @Type("string")
109
     * @SerializedName("target-dir")
110
     */
111
    protected $targetDir;
112
113
    /**
114
     * The database configuration.
115
     *
116
     * @var TechDivision\Import\Configuration\Database
117
     * @Type("TechDivision\Import\Cli\Configuration\Database")
118
     */
119
    protected $database;
120
121
    /**
122
     * ArrayCollection with the information of the configured operations.
123
     *
124
     * @var \Doctrine\Common\Collections\ArrayCollection
125
     * @Type("ArrayCollection<TechDivision\Import\Cli\Configuration\Operation>")
126
     */
127
    protected $operations;
128
129
    /**
130
     * The subject's utility class with the SQL statements to use.
131
     *
132
     * @var string
133
     * @Type("string")
134
     * @SerializedName("utility-class-name")
135
     */
136
    protected $utilityClassName;
137
138
    /**
139
     * The source date format to use in the subject.
140
     *
141
     * @var string
142
     * @Type("string")
143
     * @SerializedName("source-date-format")
144
     */
145
    protected $sourceDateFormat = 'n/d/y, g:i A';
146
147
    /**
148
     * The subject's multiple field delimiter character for fields with multiple values, defaults to (,).
149
     *
150
     * @var string
151
     * @Type("string")
152
     * @SerializedName("multiple-field-delimiter")
153
     */
154
    protected $multipleFieldDelimiter = ',';
155
156
    /**
157
     * The subject's delimiter character for CSV files.
158
     *
159
     * @var string
160
     * @Type("string")
161
     */
162
    protected $delimiter;
163
164
    /**
165
     * The subject's enclosure character for CSV files.
166
     *
167
     * @var string
168
     * @Type("string")
169
     */
170
    protected $enclosure;
171
172
    /**
173
     * The subject's escape character for CSV files.
174
     *
175
     * @var string
176
     * @Type("string")
177
     */
178
    protected $escape;
179
180
    /**
181
     * The subject's source charset for the CSV file.
182
     *
183
     * @var string
184
     * @Type("string")
185
     * @SerializedName("from-charset")
186
     */
187
    protected $fromCharset;
188
189
    /**
190
     * The subject's target charset for a CSV file.
191
     *
192
     * @var string
193
     * @Type("string")
194
     * @SerializedName("to-charset")
195
     */
196
    protected $toCharset;
197
198
    /**
199
     * The subject's file mode for a CSV target file.
200
     *
201
     * @var string
202
     * @Type("string")
203
     * @SerializedName("file-mode")
204
     */
205
    protected $fileMode;
206
207
    /**
208
     * The flag to signal that the subject has to use the strict mode or not.
209
     *
210
     * @var boolean
211
     * @Type("boolean")
212
     * @SerializedName("strict-mode")
213
     */
214
    protected $strictMode;
215
216
    /**
217
     * The flag whether or not the import artefacts have to be archived.
218
     *
219
     * @var boolean
220
     * @Type("boolean")
221
     * @SerializedName("archive-artefacts")
222
     */
223
    protected $archiveArtefacts;
224
225
    /**
226
     * The directory where the archives will be stored.
227
     *
228
     * @var string
229
     * @Type("string")
230
     * @SerializedName("archive-dir")
231
     */
232
    protected $archiveDir;
233
234
    /**
235
     * The flag to signal that the subject has to use the debug mode or not.
236
     *
237
     * @var boolean
238
     * @Type("boolean")
239
     * @SerializedName("debug-mode")
240
     */
241
    protected $debugMode = false;
242
243
    /**
244
     * The log level to use (see Monolog documentation).
245
     *
246
     * @var string
247
     * @Type("string")
248
     * @SerializedName("log-level")
249
     */
250
    protected $logLevel = LogLevel::INFO;
251
252
    /**
253
     * Factory implementation to create a new initialized configuration instance.
254
     *
255
     * If command line options are specified, they will always override the
256
     * values found in the configuration file.
257
     *
258
     * @param \Symfony\Component\Console\Input\InputInterface $input The Symfony console input instance
259
     *
260
     * @return \TechDivision\Import\Cli\Configuration The configuration instance
261
     * @throws \Exception Is thrown, if the specified configuration file doesn't exist
262
     */
263
    public static function factory(InputInterface $input)
264
    {
265
266
        // load the configuration filename we want to use
267
        $filename = $input->getOption(InputOptionKeys::CONFIGURATION);
268
269
        // load the JSON data
270
        if (!$jsonData = file_get_contents($filename)) {
271
            throw new \Exception(sprintf('Can\'t load configuration file %s', $filename));
272
        }
273
274
        // initialize the JMS serializer and load the configuration
275
        $serializer = SerializerBuilder::create()->build();
276
        /** @var \TechDivision\Import\Cli\Configuration $instance */
277
        $instance = $serializer->deserialize($jsonData, 'TechDivision\Import\Cli\Configuration', 'json');
278
279
        // query whether or not an operation name has been specified as command line
280
        // option, if yes override the value from the configuration file
281
        if ($operationName = $input->getArgument(InputArgumentKeys::OPERATION_NAME)) {
282
            $instance->setOperationName($operationName);
283
        }
284
285
        // query whether or not a Magento installation directory has been specified as command line
286
        // option, if yes override the value from the configuration file
287
        if ($installationDir = $input->getOption(InputOptionKeys::INSTALLATION_DIR)) {
288
            $instance->setInstallationDir($installationDir);
289
        }
290
291
        // query whether or not a directory for the source files has been specified as command line
292
        // option, if yes override the value from the configuration file
293
        if ($sourceDir = $input->getOption(InputOptionKeys::SOURCE_DIR)) {
294
            $instance->setSourceDir($sourceDir);
295
        }
296
297
        // query whether or not a directory containing the imported files has been specified as command line
298
        // option, if yes override the value from the configuration file
299
        if ($targetDir = $input->getOption(InputOptionKeys::TARGET_DIR)) {
300
            $instance->setTargetDir($targetDir);
301
        }
302
303
        // query whether or not a source date format has been specified as command
304
        // line  option, if yes override the value from the configuration file
305
        if ($sourceDateFormat = $input->getOption(InputOptionKeys::SOURCE_DATE_FORMAT)) {
306
            $instance->setSourceDateFormat($sourceDateFormat);
307
        }
308
309
        // query whether or not a Magento edition has been specified as command line
310
        // option, if yes override the value from the configuration file
311
        if ($magentoEdition = $input->getOption(InputOptionKeys::MAGENTO_EDITION)) {
312
            $instance->setMagentoEdition($magentoEdition);
313
        }
314
315
        // query whether or not a Magento version has been specified as command line
316
        // option, if yes override the value from the configuration file
317
        if ($magentoVersion = $input->getOption(InputOptionKeys::MAGENTO_VERSION)) {
318
            $instance->setMagentoVersion($magentoVersion);
319
        }
320
321
        // query whether or not a PDO DSN has been specified as command line
322
        // option, if yes override the value from the configuration file
323
        if ($dsn = $input->getOption(InputOptionKeys::DB_PDO_DSN)) {
324
            $instance->getDatabase()->setDsn($dsn);
325
        }
326
327
        // query whether or not a DB username has been specified as command line
328
        // option, if yes override the value from the configuration file
329
        if ($username = $input->getOption(InputOptionKeys::DB_USERNAME)) {
330
            $instance->getDatabase()->setUsername($username);
331
        }
332
333
        // query whether or not a DB password has been specified as command line
334
        // option, if yes override the value from the configuration file
335
        if ($password = $input->getOption(InputOptionKeys::DB_PASSWORD)) {
336
            $instance->getDatabase()->setPassword($password);
337
        }
338
339
        // query whether or not the debug mode has been specified as command line
340
        // option, if yes override the value from the configuration file
341
        if ($debugMode = $input->getOption(InputOptionKeys::DEBUG_MODE)) {
342
            $instance->setDebugMode($instance->mapBoolean($debugMode));
343
        }
344
345
        // query whether or not the log level has been specified as command line
346
        // option, if yes override the value from the configuration file
347
        if ($logLevel = $input->getOption(InputOptionKeys::LOG_LEVEL)) {
348
            $instance->setLogLevel($logLevel);
349
        }
350
351
        // extend the subjects with the parent configuration instance
352
        /** @var \TechDivision\Import\Cli\Configuration\Subject $subject */
353
        foreach ($instance->getSubjects() as $subject) {
354
            // set the configuration instance on the subject
355
            $subject->setConfiguration($instance);
356
        }
357
358
        // return the initialized configuration instance
359
        return $instance;
360
    }
361
362
    /**
363
     * Return's the array with the subjects of the operation to use.
364
     *
365
     * @return \Doctrine\Common\Collections\ArrayCollection The ArrayCollection with the subjects
366
     * @throws \Exception Is thrown, if no subjects are available for the actual operation
367
     */
368
    public function getSubjects()
369
    {
370
371
        // iterate over the operations and return the subjects of the actual one
372
        /** @var TechDivision\Import\Configuration\OperationInterface $operation */
373
        foreach ($this->getOperations() as $operation) {
374
            if ($this->getOperation()->equals($operation)) {
375
                return $operation->getSubjects();
376
            }
377
        }
378
379
        // throw an exception if no subjects are available
380
        throw new \Exception(sprintf('Can\'t find any subjects for operation %s', $this->getOperation()));
381
    }
382
383
    /**
384
     * Map's the passed value to a boolean.
385
     *
386
     * @param string $value The value to map
387
     *
388
     * @return boolean The mapped value
389
     * @throws \Exception Is thrown, if the value can't be mapped
390
     */
391
    public function mapBoolean($value)
392
    {
393
394
        // try to map the passed value to a boolean
395
        if (isset($this->booleanMapping[$value])) {
396
            return $this->booleanMapping[$value];
397
        }
398
399
        // throw an exception if we can't convert the passed value
400
        throw new \Exception(sprintf('Can\'t convert %s to boolean', $value));
401
    }
402
403
    /**
404
     * Return's the operation, initialize from the actual operation name.
405
     *
406
     * @return \TechDivision\Import\Configuration\OperationInterface The operation instance
407
     */
408
    protected function getOperation()
409
    {
410
        return new Operation($this->getOperationName());
411
    }
412
413
    /**
414
     * Return's the operation name that has to be used.
415
     *
416
     * @param string $operationName The operation name that has to be used
417
     *
418
     * @return void
419
     */
420
    public function setOperationName($operationName)
421
    {
422
        return $this->operationName = $operationName;
423
    }
424
425
    /**
426
     * Return's the operation name that has to be used.
427
     *
428
     * @return string The operation name that has to be used
429
     */
430
    public function getOperationName()
431
    {
432
        return $this->operationName;
433
    }
434
435
    /**
436
     * Set's the Magento installation directory.
437
     *
438
     * @param string $installationDir The Magento installation directory
439
     *
440
     * @return void
441
     */
442
    public function setInstallationDir($installationDir)
443
    {
444
        $this->installationDir = $installationDir;
445
    }
446
447
    /**
448
     * Return's the Magento installation directory.
449
     *
450
     * @return string The Magento installation directory
451
     */
452
    public function getInstallationDir()
453
    {
454
        return $this->installationDir;
455
    }
456
457
    /**
458
     * Set's the source directory that has to be watched for new files.
459
     *
460
     * @param string $sourceDir The source directory
461
     *
462
     * @return void
463
     */
464
    public function setSourceDir($sourceDir)
465
    {
466
        $this->sourceDir = $sourceDir;
467
    }
468
469
    /**
470
     * Return's the source directory that has to be watched for new files.
471
     *
472
     * @return string The source directory
473
     */
474
    public function getSourceDir()
475
    {
476
        return $this->sourceDir;
477
    }
478
479
    /**
480
     * Return's the target directory with the files that has been imported.
481
     *
482
     * @return string The target directory
483
     */
484
    public function getTargetDir()
485
    {
486
        return $this->targetDir;
487
    }
488
489
    /**
490
     * Set's the target directory with the files that has been imported.
491
     *
492
     * @param string $targetDir The target directory
493
     *
494
     * @return void
495
     */
496
    public function setTargetDir($targetDir)
497
    {
498
        $this->targetDir = $targetDir;
499
    }
500
501
    /**
502
     * Return's the utility class with the SQL statements to use.
503
     *
504
     * @param string $utilityClassName The utility class name
505
     *
506
     * @return void
507
     */
508
    public function setUtilityClassName($utilityClassName)
509
    {
510
        return $this->utilityClassName = $utilityClassName;
511
    }
512
513
    /**
514
     * Return's the utility class with the SQL statements to use.
515
     *
516
     * @return string The utility class name
517
     */
518
    public function getUtilityClassName()
519
    {
520
        return $this->utilityClassName;
521
    }
522
523
    /**
524
     * Set's the Magento edition, EE or CE.
525
     *
526
     * @param string $magentoEdition The Magento edition
527
     *
528
     * @return void
529
     */
530
    public function setMagentoEdition($magentoEdition)
531
    {
532
        $this->magentoEdition = $magentoEdition;
533
    }
534
535
    /**
536
     * Return's the Magento edition, EE or CE.
537
     *
538
     * @return string The Magento edition
539
     */
540
    public function getMagentoEdition()
541
    {
542
        return $this->magentoEdition;
543
    }
544
545
    /**
546
     * Return's the Magento version, e. g. 2.1.0.
547
     *
548
     * @param string $magentoVersion The Magento version
549
     *
550
     * @return void
551
     */
552
    public function setMagentoVersion($magentoVersion)
553
    {
554
        $this->magentoVersion = $magentoVersion;
555
    }
556
557
    /**
558
     * Return's the Magento version, e. g. 2.1.0.
559
     *
560
     * @return string The Magento version
561
     */
562
    public function getMagentoVersion()
563
    {
564
        return $this->magentoVersion;
565
    }
566
567
    /**
568
     * Return's the subject's source date format to use.
569
     *
570
     * @return string The source date format
571
     */
572
    public function getSourceDateFormat()
573
    {
574
        return $this->sourceDateFormat;
575
    }
576
577
    /**
578
     * Set's the subject's source date format to use.
579
     *
580
     * @param string $sourceDateFormat The source date format
581
     *
582
     * @return void
583
     */
584
    public function setSourceDateFormat($sourceDateFormat)
585
    {
586
        $this->sourceDateFormat = $sourceDateFormat;
587
    }
588
589
    /**
590
     * Return's the multiple field delimiter character to use, default value is comma (,).
591
     *
592
     * @return string The multiple field delimiter character
593
     */
594
    public function getMultipleFieldDelimiter()
595
    {
596
        return $this->multipleFieldDelimiter;
597
    }
598
599
    /**
600
     * Return's the delimiter character to use, default value is comma (,).
601
     *
602
     * @return string The delimiter character
603
     */
604
    public function getDelimiter()
605
    {
606
        return $this->delimiter;
607
    }
608
609
    /**
610
     * The enclosure character to use, default value is double quotation (").
611
     *
612
     * @return string The enclosure character
613
     */
614
    public function getEnclosure()
615
    {
616
        return $this->enclosure;
617
    }
618
619
    /**
620
     * The escape character to use, default value is backslash (\).
621
     *
622
     * @return string The escape character
623
     */
624
    public function getEscape()
625
    {
626
        return $this->escape;
627
    }
628
629
    /**
630
     * The file encoding of the CSV source file, default value is UTF-8.
631
     *
632
     * @return string The charset used by the CSV source file
633
     */
634
    public function getFromCharset()
635
    {
636
        return $this->fromCharset;
637
    }
638
639
    /**
640
     * The file encoding of the CSV targetfile, default value is UTF-8.
641
     *
642
     * @return string The charset used by the CSV target file
643
     */
644
    public function getToCharset()
645
    {
646
        return $this->toCharset;
647
    }
648
649
    /**
650
     * The file mode of the CSV target file, either one of write or append, default is write.
651
     *
652
     * @return string The file mode of the CSV target file
653
     */
654
    public function getFileMode()
655
    {
656
        return $this->fileMode;
657
    }
658
659
    /**
660
     * Queries whether or not strict mode is enabled or not, default is TRUE.
661
     *
662
     * @return boolean TRUE if strict mode is enabled, else FALSE
663
     */
664
    public function isStrictMode()
665
    {
666
        return $this->strictMode;
667
    }
668
669
    /**
670
     * Return's the database configuration.
671
     *
672
     * @return \TechDivision\Import\Cli\Configuration\Database The database configuration
673
     */
674
    public function getDatabase()
675
    {
676
        return $this->database;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->database; (TechDivision\Import\Cli\...\Configuration\Database) is incompatible with the return type declared by the interface TechDivision\Import\Conf...nInterface::getDatabase of type TechDivision\Import\Tech...\Configuration\Database.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
677
    }
678
679
    /**
680
     * Return's the ArrayCollection with the configured operations.
681
     *
682
     * @return \Doctrine\Common\Collections\ArrayCollection The ArrayCollection with the operations
683
     */
684
    public function getOperations()
685
    {
686
        return $this->operations;
687
    }
688
689
    /**
690
     * Return's the TRUE if the import artefacts have to be archived.
691
     *
692
     * @return boolean TRUE if the import artefacts have to be archived
693
     */
694
    public function haveArchiveArtefacts()
695
    {
696
        return $this->archiveArtefacts;
697
    }
698
699
    /**
700
     * The directory where the archives will be stored.
701
     *
702
     * @return string The archive directory
703
     */
704
    public function getArchiveDir()
705
    {
706
        return $this->archiveDir;
707
    }
708
709
    /**
710
     * Set's the debug mode.
711
     *
712
     * @param boolean $debugMode TRUE if debug mode is enabled, else FALSE
713
     *
714
     * @return void
715
     */
716
    public function setDebugMode($debugMode)
717
    {
718
        $this->debugMode = $debugMode;
719
    }
720
721
    /**
722
     * Queries whether or not debug mode is enabled or not, default is TRUE.
723
     *
724
     * @return boolean TRUE if debug mode is enabled, else FALSE
725
     */
726
    public function isDebugMode()
727
    {
728
        return $this->debugMode;
729
    }
730
731
    /**
732
     * Set's the log level to use.
733
     *
734
     * @param string $logLevel The log level to use
735
     *
736
     * @return void
737
     */
738
    public function setLogLevel($logLevel)
739
    {
740
        $this->logLevel = $logLevel;
741
    }
742
743
    /**
744
     * Return's the log level to use.
745
     *
746
     * @return string The log level to use
747
     */
748
    public function getLogLevel()
749
    {
750
        return $this->logLevel;
751
    }
752
}
753