Completed
Pull Request — master (#32)
by
unknown
05:04 queued 02:17
created

BaseNode::setDefaults()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Linio\Component\Input\Node;
6
7
use Linio\Component\Input\Constraint\ConstraintInterface;
8
use Linio\Component\Input\Exception\InvalidConstraintException;
9
use Linio\Component\Input\Exception\RequiredFieldException;
10
use Linio\Component\Input\InputHandler;
11
use Linio\Component\Input\Instantiator\InstantiatorInterface;
12
use Linio\Component\Input\Transformer\TransformerInterface;
13
use Linio\Component\Input\TypeHandler;
14
15
class BaseNode
16
{
17
    /**
18
     * @var ConstraintInterface[]
19
     */
20
    protected $constraints = [];
21
22
    /**
23
     * @var TransformerInterface
24
     */
25
    protected $transformer;
26
27
    /**
28
     * @var InstantiatorInterface
29
     */
30
    protected $instantiator;
31
32
    /**
33
     * @var string
34
     */
35
    protected $type = 'array';
36
37
    /**
38
     * @var string
39
     */
40
    protected $typeAlias = 'array';
41
42
    /**
43
     * @var bool
44
     */
45
    protected $required = true;
46
47
    /**
48
     * @var mixed
49
     */
50
    protected $default;
51
52
    /**
53
     * @var BaseNode[]
54
     */
55
    protected $children = [];
56
57
    /**
58
     * @var TypeHandler
59
     */
60
    protected $typeHandler;
61
62
    /**
63
     * @var bool
64
     */
65
    protected $allowNull = false;
66
67
    /**
68
     * @var array
69
     */
70
    protected $defaults = [];
71
72
    public function setConstraints(array $constraints)
73
    {
74
        $this->constraints = $constraints;
75
    }
76
77
    public function addConstraint(ConstraintInterface $constraint)
78
    {
79
        $this->constraints[] = $constraint;
80
    }
81
82
    public function addConstraints(array $constraints)
83
    {
84
        $this->constraints = array_merge($this->constraints, $constraints);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($this->constraints, $constraints) of type array is incompatible with the declared type array<integer,object<Lin...t\ConstraintInterface>> of property $constraints.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
85
    }
86
87
    public function setTransformer(TransformerInterface $transformer)
88
    {
89
        $this->transformer = $transformer;
90
    }
91
92
    public function setInstantiator(InstantiatorInterface $instantiator)
93
    {
94
        $this->instantiator = $instantiator;
95
    }
96
97
    public function setTypeHandler(TypeHandler $typeHandler)
98
    {
99
        $this->typeHandler = $typeHandler;
100
    }
101
102
    public function setType(string $type)
103
    {
104
        $this->type = $type;
105
    }
106
107
    public function setTypeAlias(string $typeAlias)
108
    {
109
        $this->typeAlias = $typeAlias;
110
    }
111
112
    public function getTypeAlias(): string
113
    {
114
        return $this->typeAlias;
115
    }
116
117
    public function setRequired(bool $required)
118
    {
119
        $this->required = $required;
120
    }
121
122
    public function setDefault($default)
123
    {
124
        $this->default = $default;
125
    }
126
127
    public function setAllowNull(bool $allowNull)
128
    {
129
        $this->allowNull = $allowNull;
130
    }
131
132
    public function getDefault()
133
    {
134
        return $this->default;
135
    }
136
137
    public function hasDefault(): bool
138
    {
139
        return (bool) $this->default;
140
    }
141
142
    /**
143
     * Gets the value of defaults.
144
     *
145
     * @return array
146
     */
147
    public function getDefaults(): array
148
    {
149
        return $this->defaults;
150
    }
151
152
    /**
153
     * Sets the value of defaults.
154
     *
155
     * @param array $defaults the defaults
156
     *
157
     * @return self
158
     */
159
    public function setDefaults(array $defaults): self
160
    {
161
        $this->defaults = $defaults;
162
163
        return $this;
164
    }
165
166
    public function add(string $key, string $type, array $options = []): BaseNode
167
    {
168
        $child = $this->typeHandler->getType($type);
169
170
        if (isset($options['handler'])) {
171
            /** @var InputHandler $handler */
172
            $handler = $options['handler'];
173
            $handler->setRootType($type);
174
            $handler->define();
175
176
            $child = $handler->getRoot();
177
        }
178
179
        if (isset($options['required'])) {
180
            $child->setRequired($options['required']);
181
        }
182
183
        if (isset($options['default'])) {
184
            $child->setDefault($options['default']);
185
        }
186
187
        if (isset($options['instantiator'])) {
188
            $child->setInstantiator($options['instantiator']);
189
        }
190
191
        if (isset($options['transformer'])) {
192
            $child->setTransformer($options['transformer']);
193
        }
194
195
        if (isset($options['constraints'])) {
196
            $child->addConstraints($options['constraints']);
197
        }
198
199
        if (isset($options['allow_null'])) {
200
            $child->setAllowNull($options['allow_null']);
201
        }
202
203
        if (array_key_exists($key, $this->defaults)) {
204
            $child->setDefault($this->defaults[$key]);
205
        }
206
207
        $this->children[$key] = $child;
208
209
        return $child;
210
    }
211
212
    public function remove(string $key)
213
    {
214
        unset($this->children[$key]);
215
    }
216
217
    /**
218
     * @return BaseNode[]
219
     */
220
    public function getChildren(): array
221
    {
222
        return $this->children;
223
    }
224
225
    public function hasChildren(): bool
226
    {
227
        return !empty($this->children);
228
    }
229
230
    public function isRequired(): bool
231
    {
232
        if ($this->hasDefault()) {
233
            return false;
234
        }
235
236
        return $this->required;
237
    }
238
239
    public function allowNull(): bool
0 ignored issues
show
Coding Style introduced by
function allowNull() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
240
    {
241
        return $this->allowNull;
242
    }
243
244
    public function getValue(string $field, $value)
245
    {
246
        if ($this->allowNull() && $value === null) {
247
            return $value;
248
        }
249
250
        $this->checkConstraints($field, $value);
251
252
        if ($this->transformer) {
253
            return $this->transformer->transform($value);
254
        }
255
256
        return $value;
257
    }
258
259
    public function walk($input)
260
    {
261
        $result = [];
262
263
        if (!$this->hasChildren()) {
264
            return $input;
265
        }
266
267 View Code Duplication
        foreach ($this->getChildren() as $field => $config) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
268
            if (!array_key_exists($field, $input)) {
269
                if ($config->isRequired()) {
270
                    throw new RequiredFieldException($field);
271
                }
272
273
                if (!$config->hasDefault()) {
274
                    continue;
275
                }
276
277
                $input[$field] = $config->getDefault();
278
            }
279
280
            $result[$field] = $config->getValue($field, $config->walk($input[$field]));
281
        }
282
283
        return $result;
284
    }
285
286
    protected function checkConstraints(string $field, $value)
287
    {
288
        foreach ($this->constraints as $constraint) {
289
            if (!$constraint->validate($value)) {
290
                throw new InvalidConstraintException($constraint->getErrorMessage($field));
291
            }
292
        }
293
    }
294
}
295