Passed
Push — master ( c9351b...a8a6df )
by Smoren
02:20
created

ContainerRule::getHasAttributeCheck()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 7
ccs 6
cts 6
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Smoren\Validator\Rules;
6
7
use Smoren\Validator\Checks\Check;
8
use Smoren\Validator\Exceptions\ValidationError;
9
use Smoren\Validator\Helpers\ContainerAccessHelper;
10
use Smoren\Validator\Interfaces\RuleInterface;
11
use Smoren\Validator\Interfaces\CheckInterface;
12
use Smoren\Validator\Interfaces\ContainerRuleInterface;
13
use Smoren\Validator\Interfaces\IntegerRuleInterface;
14
use Smoren\Validator\Structs\CheckErrorName;
15
use Smoren\Validator\Structs\CheckName;
16
use Smoren\Validator\Structs\Param;
17
18
class ContainerRule extends Rule implements ContainerRuleInterface
19
{
20
    /**
21
     * ContainerRule constructor.
22
     */
23 19
    public function __construct(string $name)
24
    {
25 19
        parent::__construct($name);
26 19
        $this->check(new Check(
27 19
            CheckName::CONTAINER,
28 19
            CheckErrorName::NOT_CONTAINER,
29 19
            fn ($value) => \is_array($value) || \is_object($value),
30 19
            []
31 19
        ), true);
32
    }
33
34
    /**
35
     * {@inheritDoc}
36
     *
37
     * @return static
38
     */
39 3
    public function array(): self
40
    {
41 3
        return $this->check($this->getArrayCheck());
42
    }
43
44
    /**
45
     * {@inheritDoc}
46
     *
47
     * @return static
48
     */
49 2
    public function indexedArray(): self
50
    {
51 2
        return $this->check(new Check(
52 2
            CheckName::INDEXED_ARRAY,
53 2
            CheckErrorName::NOT_INDEXED_ARRAY,
54 2
            fn ($value) => (\array_values($value) === $value),
55 2
            [],
56 2
            [$this->getArrayCheck()]
57 2
        ));
58
    }
59
60
    /**
61
     * {@inheritDoc}
62
     *
63
     * @return static
64
     */
65 1
    public function associativeArray(): self
66
    {
67 1
        return $this->check(new Check(
68 1
            CheckName::ASSOCIATIVE_ARRAY,
69 1
            CheckErrorName::NOT_ASSOCIATIVE_ARRAY,
70 1
            fn ($value) => \array_values($value) !== $value,
71 1
            [],
72 1
            [$this->getArrayCheck()]
73 1
        ));
74
    }
75
76
    /**
77
     * {@inheritDoc}
78
     *
79
     * @return static
80
     */
81
    public function arrayAccessible(): self
82
    {
83
        return $this->check(new Check(
84
            CheckName::ARRAY_ACCESSIBLE,
85
            CheckErrorName::NOT_ARRAY_ACCESSIBLE,
86
            fn ($value) => \is_array($value) || $value instanceof \ArrayAccess
87
        ));
88
    }
89
90
    /**
91
     * {@inheritDoc}
92
     *
93
     * @return static
94
     */
95
    public function iterable(): self
96
    {
97
        return $this->check($this->getIterableCheck());
98
    }
99
100
    /**
101
     * {@inheritDoc}
102
     *
103
     * @return static
104
     */
105
    public function countable(): self
106
    {
107
        return $this->check($this->getCountableCheck());
108
    }
109
110
    /**
111
     * {@inheritDoc}
112
     *
113
     * @return static
114
     */
115
    public function empty(): self
116
    {
117
        return $this->check(new Check(
118
            CheckName::EMPTY,
119
            CheckErrorName::NOT_EMPTY,
120
            fn ($value) => \count($value) === 0,
121
            [],
122
            [$this->getCountableCheck()]
123
        ));
124
    }
125
126
    /**
127
     * {@inheritDoc}
128
     *
129
     * @return static
130
     */
131
    public function notEmpty(): self
132
    {
133
        return $this->check(new Check(
134
            CheckName::NOT_EMPTY,
135
            CheckErrorName::EMPTY,
136
            fn ($value) => \count($value) > 0,
137
            [],
138
            [$this->getCountableCheck()]
139
        ));
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     *
145
     * @return static
146
     */
147 2
    public function object(): self
148
    {
149 2
        return $this->check(new Check(
150 2
            CheckName::OBJECT,
151 2
            CheckErrorName::NOT_OBJECT,
152 2
            fn ($value) => \is_object($value)
153 2
        ));
154
    }
155
156
    /**
157
     * {@inheritDoc}
158
     *
159
     * @return static
160
     */
161
    public function stdObject(): self
162
    {
163
        return $this->check(new Check(
164
            CheckName::STD_OBJECT,
165
            CheckErrorName::NOT_STD_OBJECT,
166
            fn ($value) => $value instanceof \stdClass
167
        ));
168
    }
169
170
    /**
171
     * {@inheritDoc}
172
     *
173
     * @return static
174
     */
175
    public function instanceOf(string $class): self
176
    {
177
        return $this->check(new Check(
178
            CheckName::INSTANCE_OF,
179
            CheckErrorName::NOT_INSTANCE_OF,
180
            fn ($value) => $value instanceof $class
181
        ));
182
    }
183
184
    /**
185
     * {@inheritDoc}
186
     *
187
     * @return static
188
     */
189 3
    public function lengthIs(IntegerRuleInterface $rule): self
190
    {
191 3
        return $this->check(new Check(
192 3
            CheckName::LENGTH_IS,
193 3
            CheckErrorName::BAD_LENGTH,
194 3
            static function ($value) use ($rule) {
195
                /** @var \Countable $value */
196 3
                $rule->validate(\count($value));
197 2
                return true;
198 3
            },
199 3
            [],
200 3
            [$this->getCountableCheck()]
201 3
        ));
202
    }
203
204
    /**
205
     * {@inheritDoc}
206
     *
207
     * @return static
208
     */
209 6
    public function hasAttribute(string $name, ?RuleInterface $rule = null): self
210
    {
211 6
        if ($rule === null) {
212 2
            return $this->check($this->getHasAttributeCheck($name));
213
        }
214
215 4
        return $this->check(new Check(
216 4
            CheckName::HAS_ATTRIBUTE,
217 4
            CheckErrorName::BAD_ATTRIBUTE,
218 4
            static function ($value, string $name) use ($rule) {
219 3
                $rule->validate(ContainerAccessHelper::getAttributeValue($value, $name));
220 2
                return true;
221 4
            },
222 4
            [Param::ATTRIBUTE => $name],
223 4
            [$this->getHasAttributeCheck($name)]
224 4
        ));
225
    }
226
227
    /**
228
     * {@inheritDoc}
229
     *
230
     * @return static
231
     */
232
    public function hasOptionalAttribute(string $name, RuleInterface $rule): self
233
    {
234
        return $this->check(new Check(
235
            CheckName::HAS_ATTRIBUTE,
236
            CheckErrorName::BAD_ATTRIBUTE,
237
            static function ($value) use ($name, $rule) {
238
                if (!ContainerAccessHelper::hasAccessibleAttribute($value, $name)) {
239
                    return true;
240
                }
241
                $rule->validate(ContainerAccessHelper::getAttributeValue($value, $name));
242
                return true;
243
            },
244
            [Param::ATTRIBUTE => $name],
245
        ));
246
    }
247
248
    /**
249
     * {@inheritDoc}
250
     *
251
     * @return static
252
     */
253
    public function allKeysAre(RuleInterface $rule): self
254
    {
255
        return $this->check(
256
            new Check(
257
                CheckName::ALL_KEYS_ARE,
258
                CheckErrorName::SOME_KEYS_BAD,
259
                static function ($value) use ($rule) {
260
                    foreach ($value as $k => $v) {
261
                        $rule->validate($k);
262
                    }
263
                    return true;
264
                },
265
                [],
266
                [$this->getIterableCheck()]
267
            )
268
        );
269
    }
270
271
    /**
272
     * {@inheritDoc}
273
     *
274
     * @return static
275
     */
276 3
    public function allValuesAre(RuleInterface $rule): self
277
    {
278 3
        return $this->check(
279 3
            new Check(
280 3
                CheckName::ALL_VALUES_ARE,
281 3
                CheckErrorName::SOME_VALUES_BAD,
282 3
                static function ($value) use ($rule) {
283 3
                    foreach ($value as $v) {
284 3
                        $rule->validate($v);
285
                    }
286 2
                    return true;
287 3
                },
288 3
                [],
289 3
                [$this->getIterableCheck()]
290 3
            )
291 3
        );
292
    }
293
294 6
    protected function getArrayCheck(): CheckInterface
295
    {
296 6
        return new Check(
297 6
            CheckName::ARRAY,
298 6
            CheckErrorName::NOT_ARRAY,
299 6
            fn ($value) => \is_array($value)
300 6
        );
301
    }
302
303 3
    protected function getCountableCheck(): CheckInterface
304
    {
305 3
        return new Check(
306 3
            CheckName::COUNTABLE,
307 3
            CheckErrorName::NOT_COUNTABLE,
308 3
            fn ($value) => \is_countable($value)
309 3
        );
310
    }
311
312 3
    protected function getIterableCheck(): CheckInterface
313
    {
314 3
        return new Check(
315 3
            CheckName::ITERABLE,
316 3
            CheckErrorName::NOT_ITERABLE,
317 3
            fn ($value) => \is_iterable($value)
318 3
        );
319
    }
320
321 6
    protected function getHasAttributeCheck(string $name): CheckInterface
322
    {
323 6
        return new Check(
324 6
            CheckName::HAS_ATTRIBUTE,
325 6
            CheckErrorName::ATTRIBUTE_NOT_EXIST,
326 6
            fn ($value) => ContainerAccessHelper::hasAccessibleAttribute($value, $name),
327 6
            [Param::ATTRIBUTE => $name]
328 6
        );
329
    }
330
}
331