Passed
Push — main ( f7f95e...c4cb1e )
by Breno
02:19
created

RuleSet::rules()   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 (null === $input && $this->hasAllowsNull()) {
55
            return $errorReporting;
56
        }
57
58
        if ((new IsEmpty)->isValid($input) && $this->hasAllowsEmpty()) {
59
            return $errorReporting;
60
        }
61
62
        foreach ($this->rules as $rule) {
63
            if ($rule instanceof BelongsToField) {
64
                $rule = $rule->setField($this->getField());
65
            }
66
67
            $errorReporting = $errorReporting->add($rule->validate($input, $context));
68
        }
69
70
        return $errorReporting;
71
    }
72
73
    public function hasRequired(): bool
74
    {
75
        return $this->someRule(fn(Rule $rule) => $rule instanceof Required);
76
    }
77
78
    public function hasAllowsNull(): bool
79
    {
80
        return $this->someRule(fn(Rule $rule) => $rule instanceof AllowsNull);
81
    }
82
83
    public function hasAllowsEmpty(): bool
84
    {
85
        return $this->someRule(fn(Rule $rule) => $rule instanceof AllowsEmpty);
86
    }
87
88
    public function isEmpty(): bool
89
    {
90
        return empty($this->rules);
91
    }
92
93
    /** @return Rule[] */
94
    public function rules(): array
95
    {
96
        return $this->rules;
97
    }
98
99
    private function someRule(callable $callback): bool
100
    {
101
        foreach ($this->rules as $rule) {
102
            if (true === call_user_func_array($callback, [$rule])) {
103
                return true;
104
            }
105
        }
106
107
        return false;
108
    }
109
}
110