Passed
Push — main ( e4d7a2...ff0dd8 )
by Breno
01:45
created

Validator::except()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 6
rs 10
c 1
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace BrenoRoosevelt\Validation;
5
6
use ReflectionClass;
7
use ReflectionException;
8
9
final class Validator
10
{
11
    /** @var ValidationSet[] */
12
    private array $ruleSets;
13
14
    public static function new(): self
15
    {
16
        return new self;
17
    }
18
19
    public function ruleSet(string $field): ValidationSet
20
    {
21
        foreach ($this->ruleSets as $ruleSet) {
22
            if ($ruleSet->getField() === $field) {
23
                return $ruleSet;
24
            }
25
        }
26
27
        return $this->ruleSets[] = ValidationSet::forField($field);
28
    }
29
30
    public function field(string $field, Validation|ValidationSet ...$rules): self
31
    {
32
        $ruleset = $this->ruleSet($field);
33
        foreach ($rules as $rule) {
34
            if ($rule instanceof Validation) {
35
                $ruleset->add($rule);
36
            }
37
38
            if ($rule instanceof ValidationSet) {
39
                $ruleset->add(...$rule->rules());
40
            }
41
        }
42
43
        return $this;
44
    }
45
46
    public function validate(array $data = []): ValidationResultSet
47
    {
48
        $validationResultSet = new ValidationResultSet;
49
        foreach ($this->ruleSets as $ruleSet) {
50
            $field = $ruleSet->getField();
51
            if (!$ruleSet->isRequired() && !array_key_exists($field, $data)) {
52
                continue;
53
            }
54
55
            $value = $data[$field] ?? null;
56
            if ($ruleSet->allowsEmpty() && empty($value)) {
57
                continue;
58
            }
59
60
            $result = $ruleSet->validate($value, $data);
61
            if (!$result->isOk()) {
62
                $validationResultSet = $validationResultSet->add($result);
63
            }
64
        }
65
66
        return $validationResultSet;
67
    }
68
69
    public function only(string ...$fields): self
70
    {
71
        $instance = clone $this;
72
        $instance->ruleSets =
73
            array_filter($instance->ruleSets, fn(ValidationSet $ruleSet) => in_array($ruleSet->getField(), $fields));
74
        return $instance;
75
    }
76
77
    public function except(string ...$fields): self
78
    {
79
        $instance = clone $this;
80
        $instance->ruleSets =
81
            array_filter($instance->ruleSets, fn(ValidationSet $ruleSet) => !in_array($ruleSet->getField(), $fields));
82
        return $instance;
83
    }
84
85
    /**
86
     * @throws ReflectionException
87
     */
88
    public function validateObject(object $object): ValidationResultSet
89
    {
90
        $data = [];
91
        $class = new ReflectionClass($object);
92
        foreach ($class->getProperties() as $property) {
93
            $data[$property->getName()] = $property->getValue($object);
94
        }
95
96
        $result = Validator::fromProperties($object)->validate($data);
97
98
        foreach ($class->getMethods() as $method) {
99
            $ruleSet = ValidationSet::fromReflectionMethod($method);
100
            $value = $method->invoke($method->isStatic() ? null : $object);
101
            $methodResult = $ruleSet->validate($value);
102
            if (!$methodResult->isOk()) {
103
                $result = $result->add($methodResult);
104
            }
105
        }
106
107
        return $result;
108
    }
109
110
    /**
111
     * @param array $data
112
     * @param ?string $message
113
     * @return void
114
     * @throws ValidationException
115
     */
116
    public function validateOrFail(array $data = [], ?string $message = null)
117
    {
118
        $result = $this->validate($data);
119
        if (!$result->isOk()) {
120
            throw new ValidationException($result, $message);
121
        }
122
    }
123
124
    /**
125
     * @param string|object $objectOrClass
126
     * @param int|null $filter filter properties, ex: ReflectionProperty::IS_PUBLIC|ReflectionProperty::IS_PRIVATE
127
     * @return static
128
     * @throws ReflectionException if the class does not exist
129
     */
130
    public static function fromProperties(string|object $objectOrClass, ?int $filter = null): self
131
    {
132
        $instance = new self;
133
        $instance->ruleSets = ValidationSet::fromProperties($objectOrClass, $filter);
134
        return $instance;
135
    }
136
}
137