Passed
Push — master ( d3853d...011878 )
by Smoren
02:21
created

Rule::nullable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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