Completed
Push — master ( 13238d...60cc44 )
by Klaus
02:13
created

BaseNode::remove()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Linio\Component\Input\Node;
5
6
use Linio\Component\Input\Constraint\ConstraintInterface;
7
use Linio\Component\Input\Exception\InvalidConstraintException;
8
use Linio\Component\Input\Exception\RequiredFieldException;
9
use Linio\Component\Input\InputHandler;
10
use Linio\Component\Input\Instantiator\InstantiatorInterface;
11
use Linio\Component\Input\Transformer\TransformerInterface;
12
use Linio\Component\Input\TypeHandler;
13
14
class BaseNode
15
{
16
    /**
17
     * @var ConstraintInterface[]
18
     */
19
    protected $constraints = [];
20
21
    /**
22
     * @var TransformerInterface
23
     */
24
    protected $transformer;
25
26
    /**
27
     * @var InstantiatorInterface
28
     */
29
    protected $instantiator;
30
31
    /**
32
     * @var string
33
     */
34
    protected $type = 'array';
35
36
    /**
37
     * @var string
38
     */
39
    protected $typeAlias = 'array';
40
41
    /**
42
     * @var bool
43
     */
44
    protected $required = true;
45
46
    /**
47
     * @var mixed
48
     */
49
    protected $default;
50
51
    /**
52
     * @var BaseNode[]
53
     */
54
    protected $children = [];
55
56
    /**
57
     * @var TypeHandler
58
     */
59
    protected $typeHandler;
60
61
    /**
62
     * @var bool
63
     */
64
    protected $allowNull = false;
65
66
    public function setConstraints(array $constraints)
67
    {
68
        $this->constraints = $constraints;
69
    }
70
71
    public function addConstraint(ConstraintInterface $constraint)
72
    {
73
        $this->constraints[] = $constraint;
74
    }
75
76
    public function setTransformer(TransformerInterface $transformer)
77
    {
78
        $this->transformer = $transformer;
79
    }
80
81
    public function setInstantiator(InstantiatorInterface $instantiator)
82
    {
83
        $this->instantiator = $instantiator;
84
    }
85
86
    public function setTypeHandler(TypeHandler $typeHandler)
87
    {
88
        $this->typeHandler = $typeHandler;
89
    }
90
91
    public function setType(string $type)
92
    {
93
        $this->type = $type;
94
    }
95
96
    public function setTypeAlias(string $typeAlias)
97
    {
98
        $this->typeAlias = $typeAlias;
99
    }
100
101
    public function getTypeAlias(): string
102
    {
103
        return $this->typeAlias;
104
    }
105
106
    public function setRequired(bool $required)
107
    {
108
        $this->required = $required;
109
    }
110
111
    public function setDefault($default)
112
    {
113
        $this->default = $default;
114
    }
115
116
    public function setAllowNull(bool $allowNull)
117
    {
118
        $this->allowNull = $allowNull;
119
    }
120
121
    public function getDefault()
122
    {
123
        return $this->default;
124
    }
125
126
    public function hasDefault(): bool
127
    {
128
        return (bool) $this->default;
129
    }
130
131
    public function add(string $key, string $type, array $options = []): BaseNode
132
    {
133
        $child = $this->typeHandler->getType($type);
134
135
        if (isset($options['handler'])) {
136
            /** @var InputHandler $handler */
137
            $handler = $options['handler'];
138
            $handler->setRootType($type);
139
            $handler->define();
140
141
            $child = $handler->getRoot();
142
        }
143
144
        if (isset($options['required'])) {
145
            $child->setRequired($options['required']);
146
        }
147
148
        if (isset($options['default'])) {
149
            $child->setDefault($options['default']);
150
        }
151
152
        if (isset($options['instantiator'])) {
153
            $child->setInstantiator($options['instantiator']);
154
        }
155
156
        if (isset($options['transformer'])) {
157
            $child->setTransformer($options['transformer']);
158
        }
159
160
        if (isset($options['constraints'])) {
161
            $child->setConstraints($options['constraints']);
162
        }
163
164
        if (isset($options['allow_null'])) {
165
            $child->setAllowNull($options['allow_null']);
166
        }
167
168
        $this->children[$key] = $child;
169
170
        return $child;
171
    }
172
173
    public function remove(string $key)
174
    {
175
        unset($this->children[$key]);
176
    }
177
178
    /**
179
     * @return BaseNode[]
180
     */
181
    public function getChildren(): array
182
    {
183
        return $this->children;
184
    }
185
186
    public function hasChildren(): bool
187
    {
188
        return !empty($this->children);
189
    }
190
191
    public function isRequired(): bool
192
    {
193
        if ($this->hasDefault()) {
194
            return false;
195
        }
196
197
        return $this->required;
198
    }
199
200
    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...
201
    {
202
        return $this->allowNull;
203
    }
204
205
    public function getValue(string $field, $value)
206
    {
207
        if ($this->allowNull() && $value === null) {
208
            return $value;
209
        }
210
211
        $this->checkConstraints($field, $value);
212
213
        if ($this->transformer) {
214
            return $this->transformer->transform($value);
215
        }
216
217
        return $value;
218
    }
219
220
    public function walk($input)
221
    {
222
        $result = [];
223
224
        if (!$this->hasChildren()) {
225
            return $input;
226
        }
227
228 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...
229
            if (!array_key_exists($field, $input)) {
230
                if ($config->isRequired()) {
231
                    throw new RequiredFieldException($field);
232
                }
233
234
                if (!$config->hasDefault()) {
235
                    continue;
236
                }
237
238
                $input[$field] = $config->getDefault();
239
            }
240
241
            $result[$field] = $config->getValue($field, $config->walk($input[$field]));
242
        }
243
244
        return $result;
245
    }
246
247
    protected function checkConstraints(string $field, $value)
248
    {
249
        foreach ($this->constraints as $constraint) {
250
            if (!$constraint->validate($value)) {
251
                throw new InvalidConstraintException($constraint->getErrorMessage($field));
252
            }
253
        }
254
    }
255
}
256