Passed
Pull Request — master (#446)
by Sergei
03:27
created

Each::getHandlerClassName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 1
cts 1
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use Attribute;
8
use Closure;
9
use JetBrains\PhpStorm\ArrayShape;
10
use Yiisoft\Validator\AfterInitAttributeEventInterface;
11
use Yiisoft\Validator\PropagateOptionsInterface;
12
use Yiisoft\Validator\Rule\Trait\SkipOnEmptyTrait;
13
use Yiisoft\Validator\Rule\Trait\SkipOnErrorTrait;
14
use Yiisoft\Validator\Rule\Trait\WhenTrait;
15
use Yiisoft\Validator\RuleInterface;
16
use Yiisoft\Validator\RulesDumper;
17
use Yiisoft\Validator\RuleWithOptionsInterface;
18
use Yiisoft\Validator\SkipOnEmptyInterface;
19
use Yiisoft\Validator\SkipOnErrorInterface;
20
use Yiisoft\Validator\WhenInterface;
21
22
/**
23
 * Validates an array by checking each of its elements against a set of rules.
24
 *
25
 * @psalm-import-type WhenType from WhenInterface
26
 */
27
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
28
final class Each implements
29
    RuleWithOptionsInterface,
30
    SkipOnErrorInterface,
31
    WhenInterface,
32
    SkipOnEmptyInterface,
33
    PropagateOptionsInterface,
34
    AfterInitAttributeEventInterface
35
{
36
    use SkipOnEmptyTrait;
37
    use SkipOnErrorTrait;
38
    use WhenTrait;
39 6
40
    private ?RulesDumper $rulesDumper = null;
41
42
    public function __construct(
43
        /**
44
         * @var iterable<RuleInterface>
45
         */
46
        private iterable $rules = [],
47
        private string $incorrectInputMessage = 'Value must be array or iterable.',
48
        private string $incorrectInputKeyMessage = 'Every iterable key must have an integer or a string type.',
49
0 ignored issues
show
Coding Style introduced by
Blank lines are not allowed in a multi-line function declaration
Loading history...
50
        /**
51
         * @var bool|callable|null
52
         */
53
        private $skipOnEmpty = null,
54
        private bool $skipOnError = false,
55
        /**
56
         * @var WhenType
57 6
         */
58
        private Closure|null $when = null,
59
    ) {
60 2
    }
61
62 2
    public function getName(): string
63
    {
64
        return 'each';
65 1
    }
66
67 1
    public function propagateOptions(): void
68 1
    {
69 1
        $rules = [];
70 1
        foreach ($this->rules as $rule) {
71
            if ($rule instanceof SkipOnEmptyInterface) {
72 1
                $rule = $rule->skipOnEmpty($this->skipOnEmpty);
73 1
            }
74
            if ($rule instanceof SkipOnErrorInterface) {
75 1
                $rule = $rule->skipOnError($this->skipOnError);
76 1
            }
77
            if ($rule instanceof WhenInterface) {
78
                $rule = $rule->when($this->when);
79 1
            }
80
81 1
            $rules[] = $rule;
82 1
83
            if ($rule instanceof PropagateOptionsInterface) {
84
                $rule->propagateOptions();
85
            }
86 1
        }
87
88
        $this->rules = $rules;
89
    }
90
91
    /**
92 18
     * @return iterable<Closure|Closure[]|RuleInterface|RuleInterface[]>
93
     */
94 18
    public function getRules(): iterable
95
    {
96
        return $this->rules;
97 5
    }
98
99 5
    public function getIncorrectInputMessage(): string
100
    {
101
        return $this->incorrectInputMessage;
102 3
    }
103
104 3
    public function getIncorrectInputKeyMessage(): string
105
    {
106
        return $this->incorrectInputKeyMessage;
107 3
    }
108
109
    #[ArrayShape([
110
        'incorrectInputMessage' => 'array',
111
        'incorrectInputKeyMessage' => 'array',
112
        'skipOnEmpty' => 'bool',
113
        'skipOnError' => 'bool',
114
        'rules' => 'array',
115
    ])]
116
    public function getOptions(): array
117
    {
118 3
        return [
119
            'incorrectInputMessage' => [
120
                'template' => $this->incorrectInputMessage,
121
                'parameters' => [],
122 3
            ],
123
            'incorrectInputKeyMessage' => [
124
                'template' => $this->incorrectInputKeyMessage,
125 3
                'parameters' => [],
126 3
            ],
127 3
            'skipOnEmpty' => $this->getSkipOnEmptyOption(),
128
            'skipOnError' => $this->skipOnError,
129
            'rules' => $this->getRulesDumper()->asArray($this->rules),
130
        ];
131 18
    }
132
133 18
    public function getHandlerClassName(): string
134
    {
135
        return EachHandler::class;
136
    }
137
138
    public function afterInitAttribute(object $object, int $target): void
139
    {
140
        foreach ($this->rules as $rule) {
141
            if ($rule instanceof AfterInitAttributeEventInterface) {
142
                $rule->afterInitAttribute(
143
                    $object,
144
                    $target === Attribute::TARGET_CLASS ? Attribute::TARGET_PROPERTY : $target
145
                );
146
            }
147
        }
148
    }
149
150
    private function getRulesDumper(): RulesDumper
151
    {
152
        if ($this->rulesDumper === null) {
153
            $this->rulesDumper = new RulesDumper();
154
        }
155
156
        return $this->rulesDumper;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->rulesDumper could return the type null which is incompatible with the type-hinted return Yiisoft\Validator\RulesDumper. Consider adding an additional type-check to rule them out.
Loading history...
157
    }
158
}
159