Completed
Push — 15.x ( 66d904...a48227 )
by Tim
01:30
created

ConsoleOptionLoader   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 117
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 4
dl 0
loc 117
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
C load() 0 61 13
1
<?php
2
3
/**
4
 * TechDivision\Import\Configuration\Jms\ConsoleOptionLoader
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 2019 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-configuration-jms
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Configuration\Jms;
22
23
use JMS\Serializer\Annotation\Accessor;
24
use JMS\Serializer\Annotation\SerializedName;
25
use TechDivision\Import\ConfigurationInterface;
26
use Doctrine\Common\Annotations\AnnotationReader;
27
use Symfony\Component\Console\Input\InputInterface;
28
use TechDivision\Import\ConsoleOptionLoaderInterface;
29
use TechDivision\Import\Utils\InputOptionKeysInterface;
30
31
/**
32
 * A dynamic console option loader implementation.
33
 *
34
 * @author    Tim Wagner <[email protected]>
35
 * @copyright 2019 TechDivision GmbH <[email protected]>
36
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
37
 * @link      https://github.com/techdivision/import-configuration-jms
38
 * @link      http://www.techdivision.com
39
 */
40
class ConsoleOptionLoader implements ConsoleOptionLoaderInterface
41
{
42
43
    /**
44
     * Array with options values that should NOT override the one from the configuration, if they already have values.
45
     *
46
     * @var array
47
     */
48
    protected $overrideIfEmpty = array();
49
50
    /**
51
     * The array with the blacklisted options that should be ignored.
52
     *
53
     * @var array
54
     */
55
    protected $blacklist = array();
56
57
    /**
58
     * The input interface.
59
     *
60
     * @var \Symfony\Component\Console\Input\InputInterface
61
     */
62
    protected $input;
63
64
    /**
65
     * The input option keys.
66
     *
67
     * @var \TechDivision\Import\Utils\InputOptionKeysInterface
68
     */
69
    protected $inputOptionKeys;
70
71
    /**
72
     * Initializes the console options loader.
73
     *
74
     * @param array $overrideIfEmpty The input options to parse
75
     */
76
    public function __construct(
77
        InputInterface $input,
78
        InputOptionKeysInterface $inputOptionKeys,
79
        array $overrideIfEmpty = array(),
80
        array $blacklist = array()
81
    ) {
82
        $this->input = $input;
83
        $this->blacklist = $blacklist;
84
        $this->inputOptionKeys = $inputOptionKeys;
85
        $this->overrideIfEmpty = $overrideIfEmpty;
86
    }
87
88
    /**
89
     * Load's the input options ans try's to initialize the configuration with the values found.
90
     *
91
     * @param \TechDivision\Import\ConfigurationInterface $instance The configuration instance to load the values for
92
     *
93
     * @returnf void
94
     */
95
    public function load(ConfigurationInterface $instance)
96
    {
97
98
        // we need the reflection properties of the configuration
99
        $reflectionClass = new \ReflectionClass($instance);
100
        $reflectionProperties = $reflectionClass->getProperties();
101
102
        // load the annoation reader
103
        $reader = new AnnotationReader();
104
105
        // iterate over the properties to initialize the configuration
106
        /** @var \ReflectionProperty $reflectionProperty */
107
        foreach ($reflectionProperties as $reflectionProperty) {
108
            // try to load the annotations of the properties
109
            /** @var \JMS\Serializer\Annotation\SerializedName $serializedName */
110
            $serializedName = $reader->getPropertyAnnotation($reflectionProperty, SerializedName::class);
111
            /** @var \JMS\Serializer\Annotation\SerializedName $accessors */
112
            $accessor = $reader->getPropertyAnnotation($reflectionProperty, Accessor::class);
113
114
            // intialize the option value (which equals the property name by default)
115
            $name = $reflectionProperty->getName();
116
117
            // if we've an JMS serializer annotation, we use the configured name instead
118
            if ($serializedName instanceof SerializedName) {
119
                $name = $serializedName->name;
120
            }
121
122
            // query whether or not the name matches an input option and is NOT on the blacklist
123
            if ($this->inputOptionKeys->isInputOption($name) && in_array($name, $this->blacklist) === false) {
124
                // query whether or not the @Accessor annotion with a setter has been specified
125
                if ($accessor instanceof Accessor && isset($accessor->getter) && isset($accessor->setter)) {
126
                    // initialize the value
127
                    $newValue = null;
128
129
                    // try to load the new value from the command line
130
                    if ($this->input->hasOption($name)) {
131
                        $newValue = $this->input->getOption($name);
132
                    }
133
134
                    // query whether or not we've a new value
135
                    if ($newValue === null) {
136
                        continue;
137
                    }
138
139
                    // this is the case where we may have a value from the configuration
140
                    // which may collate with the default value one from the command line
141
                    if (in_array($name, $this->overrideIfEmpty)) {
142
                        // first we try load the existing value from the configuration
143
                        $val = call_user_func(array($instance, $accessor->getter));
144
                        // query whether or not the command line option has REALLY been specified otherwise it'll
145
                        // be the default value and in that case the one from the configuration has precedence
146
                        if ($val === null || $this->input->hasOptionSpecified($name)) {
0 ignored issues
show
Bug introduced by
The method hasOptionSpecified() does not exist on Symfony\Component\Console\Input\InputInterface. Did you maybe mean hasOption()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
147
                            call_user_func(array($instance, $accessor->setter), $newValue);
148
                        }
149
                    } else {
150
                        call_user_func(array($instance, $accessor->setter), $newValue);
151
                    }
152
                }
153
            }
154
        }
155
    }
156
}
157