Completed
Push — master ( 1d0993...a92c21 )
by Klaus
03:01
created

BaseNode::isRequired()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
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 bool
38
     */
39
    protected $required = true;
40
41
    /**
42
     * @var mixed
43
     */
44
    protected $default;
45
46
    /**
47
     * @var BaseNode[]
48
     */
49
    protected $children = [];
50
51
    /**
52
     * @var TypeHandler
53
     */
54
    protected $typeHandler;
55
56
    public function setConstraints(array $constraints)
57
    {
58
        $this->constraints = $constraints;
59
    }
60
61
    public function addConstraint(ConstraintInterface $constraint)
62
    {
63
        $this->constraints[] = $constraint;
64
    }
65
66
    public function setTransformer(TransformerInterface $transformer)
67
    {
68
        $this->transformer = $transformer;
69
    }
70
71
    public function setInstantiator(InstantiatorInterface $instantiator)
72
    {
73
        $this->instantiator = $instantiator;
74
    }
75
76
    public function setTypeHandler(TypeHandler $typeHandler)
77
    {
78
        $this->typeHandler = $typeHandler;
79
    }
80
81
    public function setType(string $type)
82
    {
83
        $this->type = $type;
84
    }
85
86
    public function setRequired(bool $required)
87
    {
88
        $this->required = $required;
89
    }
90
91
    public function setDefault($default)
92
    {
93
        $this->default = $default;
94
    }
95
96
    public function getDefault()
97
    {
98
        return $this->default;
99
    }
100
101
    public function hasDefault(): bool
102
    {
103
        return (bool) $this->default;
104
    }
105
106
    public function add(string $key, string $type, array $options = []): BaseNode
107
    {
108
        $child = $this->typeHandler->getType($type);
109
110
        if (isset($options['handler'])) {
111
            /** @var InputHandler $handler */
112
            $handler = $options['handler'];
113
            $handler->setRootType($type);
114
            $handler->define();
115
116
            $child = $handler->getRoot();
117
        }
118
119
        if (isset($options['required'])) {
120
            $child->setRequired($options['required']);
121
        }
122
123
        if (isset($options['default'])) {
124
            $child->setDefault($options['default']);
125
        }
126
127
        if (isset($options['instantiator'])) {
128
            $child->setInstantiator($options['instantiator']);
129
        }
130
131
        if (isset($options['transformer'])) {
132
            $child->setTransformer($options['transformer']);
133
        }
134
135
        if (isset($options['constraints'])) {
136
            $child->setConstraints($options['constraints']);
137
        }
138
139
        $this->children[$key] = $child;
140
141
        return $child;
142
    }
143
144
    public function remove(string $key)
145
    {
146
        unset($this->children[$key]);
147
    }
148
149
    /**
150
     * @return BaseNode[]
151
     */
152
    public function getChildren(): array
153
    {
154
        return $this->children;
155
    }
156
157
    public function hasChildren(): bool
158
    {
159
        return !empty($this->children);
160
    }
161
162
    public function isRequired(): bool
163
    {
164
        if ($this->hasDefault()) {
165
            return false;
166
        }
167
168
        return $this->required;
169
    }
170
171
    public function getValue(string $field, $value)
172
    {
173
        $this->checkConstraints($field, $value);
174
175
        if ($this->transformer) {
176
            return $this->transformer->transform($value);
177
        }
178
179
        return $value;
180
    }
181
182
    public function walk($input)
183
    {
184
        $result = [];
185
186
        if (!$this->hasChildren()) {
187
            return $input;
188
        }
189
190 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...
191
            if (!array_key_exists($field, $input)) {
192
                if ($config->isRequired()) {
193
                    throw new RequiredFieldException($field);
194
                }
195
196
                if (!$config->hasDefault()) {
197
                    continue;
198
                }
199
200
                $input[$field] = $config->getDefault();
201
            }
202
203
            $result[$field] = $config->getValue($field, $config->walk($input[$field]));
204
        }
205
206
        return $result;
207
    }
208
209
    protected function checkConstraints(string $field, $value)
210
    {
211
        foreach ($this->constraints as $constraint) {
212
            if (!$constraint->validate($value)) {
213
                throw new InvalidConstraintException($constraint->getErrorMessage($field));
214
            }
215
        }
216
    }
217
}
218