Passed
Push — main ( 23b6b9...a20a2c )
by Breno
01:30
created

RuleSet::isEmpty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace BrenoRoosevelt\Validation;
5
6
use BrenoRoosevelt\Validation\Exception\ValidateOrFailTrait;
7
use BrenoRoosevelt\Validation\Rules\AllowsEmpty;
8
use BrenoRoosevelt\Validation\Rules\AllowsNull;
9
use BrenoRoosevelt\Validation\Rules\IsEmpty;
10
use BrenoRoosevelt\Validation\Rules\Required;
11
12
class RuleSet implements Rule, BelongsToField
13
{
14
    use RuleChainTrait, BelongsToFieldTrait, ValidateOrFailTrait;
15
16
    /** @var Rule[] */
17
    private array $rules = [];
18
19
    final public function __construct(?string $field = null, Rule | RuleSet ...$rules)
20
    {
21
        $this->field = $field;
22
        foreach ($rules as $ruleOrRuleSet) {
23
            array_push(
24
                $this->rules,
25
                ...($ruleOrRuleSet instanceof Rule ? [$ruleOrRuleSet] : $ruleOrRuleSet->rules())
26
            );
27
        }
28
    }
29
30
    public static function new(): self
31
    {
32
        return new self;
33
    }
34
35
    public static function of(string $field, Rule | RuleSet ...$rules): self
36
    {
37
        return new self($field, ...$rules);
38
    }
39
40
    public static function withRules(Rule | RuleSet ...$rules): self
41
    {
42
        return new self(null, ...$rules);
43
    }
44
45
    public function add(Rule | RuleSet ...$rules): static
46
    {
47
        return new self($this->field, ...$this->rules, ...$rules);
48
    }
49
50
    /** @inheritDoc */
51
    public function validate(mixed $input, array $context = []): Result
52
    {
53
        $errorReporting = new ErrorReporting;
54
        if (!$this->shouldValidate($input)) {
55
            return $errorReporting;
56
        }
57
58
        foreach ($this->rules as $rule) {
59
            if ($rule instanceof BelongsToField) {
60
                $rule = $rule->setField($this->getField());
61
            }
62
63
            $errorReporting = $errorReporting->add($rule->validate($input, $context));
64
        }
65
66
        return $errorReporting;
67
    }
68
69
    private function shouldValidate(mixed $input): bool
70
    {
71
        if (null === $input && $this->hasAllowsNull()) {
72
            return false;
73
        }
74
75
        if ((new IsEmpty)->isValid($input) && $this->hasAllowsEmpty()) {
76
            return false;
77
        }
78
79
        return true;
80
    }
81
82
    public function hasRequired(): bool
83
    {
84
        return $this->someRule(fn(Rule $rule) => $rule instanceof Required);
85
    }
86
87
    public function hasAllowsNull(): bool
88
    {
89
        return $this->someRule(fn(Rule $rule) => $rule instanceof AllowsNull);
90
    }
91
92
    public function hasAllowsEmpty(): bool
93
    {
94
        return $this->someRule(fn(Rule $rule) => $rule instanceof AllowsEmpty);
95
    }
96
97
    public function isEmpty(): bool
98
    {
99
        return empty($this->rules);
100
    }
101
102
    /** @return Rule[] */
103
    public function rules(): array
104
    {
105
        return $this->rules;
106
    }
107
108
    private function someRule(callable $callback): bool
109
    {
110
        foreach ($this->rules as $rule) {
111
            if (true === call_user_func_array($callback, [$rule])) {
112
                return true;
113
            }
114
        }
115
116
        return false;
117
    }
118
}
119