Passed
Push — master ( 39136d...c199ca )
by Smoren
02:15
created

Rule::stopOnViolation()   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 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Smoren\Validator\Rules;
6
7
use Smoren\Validator\Checks\Check;
8
use Smoren\Validator\Checks\RetrospectiveCheck;
9
use Smoren\Validator\Exceptions\CheckError;
10
use Smoren\Validator\Exceptions\ValidationError;
11
use Smoren\Validator\Interfaces\CheckInterface;
12
use Smoren\Validator\Interfaces\CheckWrapperInterface;
13
use Smoren\Validator\Interfaces\RuleInterface;
14
use Smoren\Validator\Interfaces\ValidationResultInterface;
15
use Smoren\Validator\Structs\CheckWrapper;
16
use Smoren\Validator\Structs\ValidationSuccessResult;
17
18
class Rule extends BaseRule implements RuleInterface
19
{
20
    public const ERROR_NULL = 'null';
21
    public const ERROR_NOT_TRUTHY = 'not_truthy';
22
    public const ERROR_NOT_FALSY = 'not_falsy';
23
24
    /**
25
     * @var array<CheckWrapperInterface>
26
     */
27
    protected array $checks = [];
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->check(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->check(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 check(CheckInterface $check, bool $isInterrupting = false): self
76
    {
77
        $this->checks[] = new CheckWrapper($check, $isInterrupting);
78
        return $this;
79
    }
80
81
    /**
82
     * {@inheritDoc}
83
     *
84
     * @return static
85
     */
86
    public function stopOnViolation(): self
87
    {
88
        return $this->check(new RetrospectiveCheck());
89
    }
90
91
    /**
92
     * {@inheritDoc}
93
     *
94
     * @return static
95
     */
96
    public function stopOnAnyPriorViolation(): self
97
    {
98
        foreach ($this->checks as $check) {
99
            $check->setInterrupting();
100
        }
101
        return $this;
102
    }
103
104
    /**
105
     * {@inheritDoc}
106
     */
107 68
    protected function execute($value): ValidationResultInterface
108
    {
109 68
        $result = parent::execute($value);
110 68
        if ($result->preventNextChecks()) {
111
            return $result;
112
        }
113
114 68
        if ($value === null) {
115 8
            if ($this->isNullable) {
116 5
                return new ValidationSuccessResult(true);
117
            }
118
119 3
            throw new ValidationError($value, [[self::ERROR_NULL, []]]);
120
        }
121
122 65
        $errors = [];
123
124 65
        foreach ($this->checks as $check) {
125
            try {
126 64
                $check->getCheck()->execute($value, $errors);
127 39
            } catch (CheckError $e) {
128 39
                $errors[] = $e;
129 39
                if ($check->isInterrupting()) {
130 12
                    throw ValidationError::fromCheckErrors($value, $errors);
131
                }
132
            }
133
        }
134
135 57
        if (\count($errors) > 0) {
136 27
            throw ValidationError::fromCheckErrors($value, $errors);
137
        }
138
139 33
        return new ValidationSuccessResult(false);
140
    }
141
}
142