Passed
Push — main ( aa2ba1...352c83 )
by Breno
01:51
created

Validator::field()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 3
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
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 RuleSet[] */
12
    private array $ruleSets;
13
14
    public static function new(): self
15
    {
16
        return new self;
17
    }
18
19
    public function ruleSet(string $field, Rule|RuleSet ...$rules): RuleSet
20
    {
21
        $ruleSet = $this->ruleSets[$field] ?? $this->ruleSets[$field] = RuleSet::forField($field);
22
        return $ruleSet->add(...$rules);
23
    }
24
25
    public function validate(array $data = []): ValidationResultSet
26
    {
27
        $validationResultSet = new ValidationResultSet;
28
        foreach ($this->ruleSets as $field => $fieldRuleSet) {
29
            if (!$fieldRuleSet->isRequired() && !array_key_exists($field, $data)) {
30
                continue;
31
            }
32
33
            $result = $fieldRuleSet->validate($data[$field] ?? null, $data);
34
            if (!$result->isOk()) {
35
                $validationResultSet = $validationResultSet->add($result);
36
            }
37
        }
38
39
        return $validationResultSet;
40
    }
41
42
    public function only(string ...$fields): self
43
    {
44
        $instance = clone $this;
45
        $instance->ruleSets =
46
            array_filter($instance->ruleSets, fn(RuleSet $ruleSet) => in_array($ruleSet->getField(), $fields));
47
        return $instance;
48
    }
49
50
    public function except(string ...$fields): self
51
    {
52
        $instance = clone $this;
53
        $instance->ruleSets =
54
            array_filter($instance->ruleSets, fn(RuleSet $ruleSet) => !in_array($ruleSet->getField(), $fields));
55
        return $instance;
56
    }
57
58
    /**
59
     * @throws ReflectionException
60
     */
61
    public function validateObject(object $object): ValidationResultSet
62
    {
63
        $data = [];
64
        $class = new ReflectionClass($object);
65
        foreach ($class->getProperties() as $property) {
66
            $data[$property->getName()] = $property->getValue($object);
67
        }
68
69
        $result = Validator::fromProperties($object)->validate($data);
70
71
        foreach ($class->getMethods() as $method) {
72
            $ruleSet = RuleSetFactory::fromReflectionMethod($method);
73
            $value = $method->invoke($method->isStatic() ? null : $object);
74
            $methodResult = $ruleSet->validate($value);
75
            if (!$methodResult->isOk()) {
76
                $result = $result->add($methodResult);
77
            }
78
        }
79
80
        return $result;
81
    }
82
83
    /**
84
     * @param array $data
85
     * @param ?string $message
86
     * @return void
87
     * @throws ValidationException
88
     */
89
    public function validateOrFail(array $data = [], ?string $message = null)
90
    {
91
        $result = $this->validate($data);
92
        if (!$result->isOk()) {
93
            throw new ValidationException($result, $message);
94
        }
95
    }
96
97
    /**
98
     * @param string|object $objectOrClass
99
     * @param int|null $filter filter properties, ex: ReflectionProperty::IS_PUBLIC|ReflectionProperty::IS_PRIVATE
100
     * @return static
101
     * @throws ReflectionException if the class does not exist
102
     */
103
    public static function fromProperties(string|object $objectOrClass, ?int $filter = null): self
104
    {
105
        $instance = new self;
106
        $instance->ruleSets = RuleSetFactory::fromProperties($objectOrClass, $filter);
107
        return $instance;
108
    }
109
}
110