Passed
Pull Request — master (#222)
by Dmitriy
16:32 queued 14:10
created

Nested   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 46
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 16
c 0
b 0
f 0
dl 0
loc 46
ccs 15
cts 15
cp 1
rs 10
wmc 8

3 Methods

Rating   Name   Duplication   Size   Complexity  
A checkRules() 0 8 3
A __construct() 0 22 4
A getOptions() 0 5 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule\Nested;
6
7
use Attribute;
8
use Closure;
9
use InvalidArgumentException;
10
use Traversable;
11
use Yiisoft\Validator\Rule\RuleNameTrait;
12
use Yiisoft\Validator\Rule\HandlerClassNameTrait;
13
use Yiisoft\Validator\RuleInterface;
14
use Yiisoft\Validator\RulesDumper;
15
use function is_array;
16
17
/**
18
 * Can be used for validation of nested structures.
19
 *
20
 * For example, we have an inbound request with the following structure:
21
 *
22
 * ```php
23
 * $request = [
24
 *     'author' => [
25
 *         'name' => 'Dmitry',
26
 *         'age' => 18,
27
 *     ],
28
 * ];
29
 * ```
30
 *
31
 * So to make validation we can configure it like this:
32
 *
33
 * ```php
34
 * $rule = new Nested([
35
 *     'author' => new Nested([
36
 *         'name' => [new HasLength(min: 3)],
37
 *         'age' => [new Number(min: 18)],
38
 *     )];
39
 * ]);
40
 * ```
41
 */
42
#[Attribute(Attribute::TARGET_PROPERTY)]
43
final class Nested implements RuleInterface
44
{
45
    use HandlerClassNameTrait;
46
    use RuleNameTrait;
47
48 3
    public function __construct(
49
        /**
50
         * @var RuleInterface[][]
51
         */
52
        public iterable $rules = [],
53
        public bool $errorWhenPropertyPathIsNotFound = false,
54
        public string $propertyPathIsNotFoundMessage = 'Property path "{path}" is not found.',
55
        public bool $skipOnEmpty = false,
56
        public bool $skipOnError = false,
57
        public ?Closure $when = null,
58
    ) {
59 3
        $rules = $rules instanceof Traversable ? iterator_to_array($rules) : $rules;
60 3
        if (empty($rules)) {
61 1
            throw new InvalidArgumentException('Rules must not be empty.');
62
        }
63
64 2
        if ($this->checkRules($rules)) {
0 ignored issues
show
Bug introduced by
It seems like $rules can also be of type iterable; however, parameter $rules of Yiisoft\Validator\Rule\Nested\Nested::checkRules() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

64
        if ($this->checkRules(/** @scrutinizer ignore-type */ $rules)) {
Loading history...
65 1
            $message = sprintf('Each rule should be an instance of %s.', RuleInterface::class);
66 1
            throw new InvalidArgumentException($message);
67
        }
68
69 1
        $this->rules = $rules;
70
    }
71
72 2
    private function checkRules(array $rules): bool
73
    {
74 2
        return array_reduce(
75
            $rules,
76 2
            function (bool $carry, $rule) {
77 2
                return $carry || (is_array($rule) ? $this->checkRules($rule) : !$rule instanceof RuleInterface);
78
            },
79
            false
80
        );
81
    }
82
83 4
    public function getOptions(): array
84
    {
85 4
        $dumper = new RulesDumper();
86
87 4
        return $dumper->asArray($this->rules, false);
88
    }
89
}
90