Passed
Push — master ( b66066...5b471b )
by Smoren
02:41
created

Rule::isCheckNameUsed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Smoren\Validator\Rules;
6
7
use Smoren\Validator\Exceptions\CheckError;
8
use Smoren\Validator\Exceptions\ValidationError;
9
use Smoren\Validator\Interfaces\CheckInterface;
10
use Smoren\Validator\Interfaces\RuleInterface;
11
use Smoren\Validator\Interfaces\ExecutionResultInterface;
12
use Smoren\Validator\Structs\Check;
13
use Smoren\Validator\Structs\ExecutionResult;
14
use Smoren\Validator\Structs\RetrospectiveCheck;
15
16
class Rule extends BaseRule implements RuleInterface
17
{
18
    public const ERROR_NULL = 'null';
19
    public const ERROR_NOT_TRUTHY = 'not_truthy';
20
    public const ERROR_NOT_FALSY = 'not_falsy';
21
22
    /**
23
     * @var array<CheckInterface>
24
     */
25
    protected array $checks = [];
26
    /**
27
     * @var bool
28
     */
29
    protected bool $isNullable = false;
30
31
    /**
32
     * {@inheritDoc}
33
     *
34
     * @return static
35
     */
36
    public function nullable(): self
37
    {
38
        $this->isNullable = true;
39
        return $this;
40
    }
41
42
    /**
43
     * {@inheritDoc}
44
     *
45
     * @return static
46
     */
47
    public function truthy(): self
48
    {
49
        return $this->addCheck(new Check(
50
            self::ERROR_NOT_TRUTHY,
51
            fn ($value) => boolval($value),
52
        ));
53
    }
54
55
    /**
56
     * {@inheritDoc}
57
     *
58
     * @return static
59
     */
60
    public function falsy(): self
61
    {
62
        return $this->addCheck(new Check(
63
            self::ERROR_NOT_FALSY,
64
            fn ($value) => !boolval($value),
65
        ));
66
    }
67
68
    /**
69
     * {@inheritDoc}
70
     *
71
     * @return static
72
     */
73
    public function addCheck(CheckInterface $check): self
74
    {
75
        $this->checks[] = $check;
76
        return $this;
77
    }
78
79
    /**
80
     * {@inheritDoc}
81
     *
82
     * @return static
83
     */
84
    public function check(string $name, callable $predicate, array $params = [], bool $isInterrupting = false): self
85
    {
86
        return $this->addCheck(new Check($name, $predicate, $params, $isInterrupting));
87
    }
88
89
    /**
90
     * {@inheritDoc}
91
     *
92
     * @return static
93
     */
94
    public function stopOnViolation(): self
95
    {
96
        return $this->addCheck(new RetrospectiveCheck());
97
    }
98
99
    /**
100
     * {@inheritDoc}
101
     *
102
     * @return static
103
     */
104
    public function stopOnAnyPriorViolation(): self
105
    {
106
        foreach ($this->checks as $check) {
107
            $check->setInterrupting();
108
        }
109
        return $this;
110
    }
111
112
    /**
113
     * {@inheritDoc}
114
     */
115 66
    protected function execute($value): ExecutionResultInterface
116
    {
117 66
        $result = parent::execute($value);
118 66
        if ($result->areChecksSufficient()) {
119
            return $result;
120
        }
121
122 66
        if ($value === null) {
123 8
            if ($this->isNullable) {
124 5
                return new ExecutionResult(true);
125
            }
126
127 3
            throw new ValidationError($value, [[self::ERROR_NULL, []]]);
128
        }
129
130 63
        $errors = [];
131
132 63
        foreach ($this->checks as $check) {
133
            try {
134 62
                $check->execute($value, $errors);
135 38
            } catch (CheckError $e) {
136 38
                $errors[] = $e;
137 38
                if ($check->isInterrupting()) {
138 12
                    throw ValidationError::fromCheckErrors($value, $errors);
139
                }
140
            }
141
        }
142
143 55
        if (\count($errors) > 0) {
144 26
            throw ValidationError::fromCheckErrors($value, $errors);
145
        }
146
147 31
        return new ExecutionResult(false);
148
    }
149
}
150