Passed
Push — master ( 454f94...1d446e )
by Smoren
11:59
created

MixedRule::dontStopOnAllPriorViolations()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 6
ccs 0
cts 4
cp 0
crap 6
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Smoren\Validator\Rules;
6
7
use Smoren\Validator\Checks\RetrospectiveCheck;
8
use Smoren\Validator\Exceptions\CheckError;
9
use Smoren\Validator\Exceptions\ValidationError;
10
use Smoren\Validator\Factories\Checks\MixedCheckFactory;
11
use Smoren\Validator\Interfaces\CheckInterface;
12
use Smoren\Validator\Interfaces\CheckWrapperInterface;
13
use Smoren\Validator\Interfaces\MixedRuleInterface;
14
use Smoren\Validator\Interfaces\UtilityCheckInterface;
15
use Smoren\Validator\Interfaces\ValidationResultInterface;
16
use Smoren\Validator\Structs\CheckName;
17
use Smoren\Validator\Structs\CheckWrapper;
18
use Smoren\Validator\Structs\ValidationSuccessResult;
19
20
class MixedRule extends BaseRule implements MixedRuleInterface
21
{
22
    /**
23
     * @var string
24
     */
25
    protected string $name;
26
    /**
27
     * @var array<CheckWrapperInterface>
28
     */
29
    protected array $checks = [];
30
    /**
31
     * @var bool
32
     */
33
    protected bool $isNullable = false;
34
35
    /**
36
     * @param string $name
37
     */
38 290
    public function __construct(string $name)
39
    {
40 290
        $this->name = $name;
41
    }
42
43
    /**
44
     * {@inheritDoc}
45
     *
46
     * @return static
47
     */
48 28
    public function nullable(): self
49
    {
50 28
        $this->isNullable = true;
51 28
        return $this;
52
    }
53
54
    /**
55
     * {@inheritDoc}
56
     *
57
     * @return static
58
     */
59 7
    public function truthy(): self
60
    {
61 7
        return $this->check(MixedCheckFactory::getTruthyCheck());
62
    }
63
64
    /**
65
     * {@inheritDoc}
66
     *
67
     * @return static
68
     */
69 7
    public function falsy(): self
70
    {
71 7
        return $this->check(MixedCheckFactory::getFalsyCheck());
72
    }
73
74
    /**
75
     * {@inheritDoc}
76
     *
77
     * @return static
78
     */
79 19
    public function equal($value): self
80
    {
81 19
        return $this->check(MixedCheckFactory::getEqualCheck($value));
82
    }
83
84
    /**
85
     * {@inheritDoc}
86
     *
87
     * @return static
88
     */
89 12
    public function same($value): self
90
    {
91 12
        return $this->check(MixedCheckFactory::getSameCheck($value));
92
    }
93
94
    /**
95
     * {@inheritDoc}
96
     *
97
     * @return static
98
     */
99 283
    public function check(CheckInterface $check, bool $stopOnViolation = false): self
100
    {
101 283
        $this->checks[] = new CheckWrapper($check, $stopOnViolation);
102 283
        return $this;
103
    }
104
105
    /**
106
     * {@inheritDoc}
107
     *
108
     * @return static
109
     */
110 6
    public function stopOnViolation(): self
111
    {
112 6
        return $this->check(new RetrospectiveCheck(), true);
113
    }
114
115
    /**
116
     * {@inheritDoc}
117
     *
118
     * @return static
119
     */
120
    public function dontStopOnViolation(): self
121
    {
122
        if (\count($this->checks) > 0) {
123
            $this->checks[\count($this->checks) - 1]->setInterrupting(false);
124
        }
125
126
        return $this;
127
    }
128
129
    /**
130
     * {@inheritDoc}
131
     *
132
     * @return static
133
     */
134 4
    public function stopOnAnyPriorViolation(): self
135
    {
136 4
        foreach ($this->checks as $check) {
137 4
            $check->setInterrupting();
138
        }
139 4
        return $this;
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     *
145
     * @return static
146
     */
147
    public function dontStopOnAllPriorViolations(): self
148
    {
149
        foreach ($this->checks as $check) {
150
            $check->setInterrupting(false);
151
        }
152
        return $this;
153
    }
154
155
    /**
156
     * {@inheritDoc}
157
     */
158 290
    public function validate($value): void
159
    {
160 290
        $this->execute($value);
161
    }
162
163
    /**
164
     * {@inheritDoc}
165
     */
166
    public function getName(): string
167
    {
168
        return $this->name;
169
    }
170
171
    /**
172
     * {@inheritDoc}
173
     */
174
    public function isValid($value): bool
175
    {
176
        try {
177
            $this->validate($value);
178
            return true;
179
        } catch (ValidationError $e) {
180
            return false;
181
        }
182
    }
183
184
    /**
185
     * {@inheritDoc}
186
     */
187 290
    protected function execute($value): ValidationResultInterface
188
    {
189 290
        $result = parent::execute($value);
190 290
        if ($result->preventNextChecks()) {
191
            return $result;
192
        }
193
194 290
        if ($value === null) {
195 26
            if ($this->isNullable) {
196 17
                return new ValidationSuccessResult(true);
197
            }
198
199 9
            throw new ValidationError($this->name, $value, [[CheckName::NOT_NULL, []]]);
200
        }
201
202 281
        $errors = [];
203
204 281
        foreach ($this->checks as $check) {
205
            try {
206 277
                $check->getCheck()->execute($value, $errors);
207 152
            } catch (CheckError $e) {
208 152
                if (!($check->getCheck() instanceof UtilityCheckInterface)) {
209 152
                    $errors[] = $e;
210
                }
211
212 152
                if ($check->isInterrupting()) {
213 47
                    throw ValidationError::fromCheckErrors($this->name, $value, $errors);
214
                }
215
            }
216
        }
217
218 247
        if (\count($errors) > 0) {
219 114
            throw ValidationError::fromCheckErrors($this->name, $value, $errors);
220
        }
221
222 145
        return new ValidationSuccessResult(false);
223
    }
224
}
225