Passed
Push — master ( c4ff45...acf216 )
by Smoren
02:28
created

MixedRule   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 176
Duplicated Lines 0 %

Test Coverage

Coverage 84%

Importance

Changes 0
Metric Value
eloc 43
dl 0
loc 176
ccs 42
cts 50
cp 0.84
rs 10
c 0
b 0
f 0
wmc 23

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A nullable() 0 4 1
A equal() 0 3 1
A falsy() 0 3 1
A stopOnViolation() 0 3 1
A stopOnAnyPriorViolation() 0 6 2
A getName() 0 3 1
A validate() 0 3 1
A same() 0 3 1
B execute() 0 36 9
A truthy() 0 3 1
A isValid() 0 7 2
A check() 0 4 1
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\CheckBuilder;
11
use Smoren\Validator\Factories\Checks\MixedCheckFactory;
12
use Smoren\Validator\Interfaces\CheckInterface;
13
use Smoren\Validator\Interfaces\CheckWrapperInterface;
14
use Smoren\Validator\Interfaces\MixedRuleInterface;
15
use Smoren\Validator\Interfaces\UtilityCheckInterface;
16
use Smoren\Validator\Interfaces\ValidationResultInterface;
17
use Smoren\Validator\Structs\CheckName;
18
use Smoren\Validator\Structs\CheckWrapper;
19
use Smoren\Validator\Structs\ValidationSuccessResult;
20
21
class MixedRule extends BaseRule implements MixedRuleInterface
22
{
23
    /**
24
     * @var string
25
     */
26
    protected string $name;
27
    /**
28
     * @var array<CheckWrapperInterface>
29
     */
30
    protected array $checks = [];
31
    /**
32
     * @var bool
33
     */
34
    protected bool $isNullable = false;
35
36
    /**
37
     * @param string $name
38
     */
39 277
    public function __construct(string $name)
40
    {
41 277
        $this->name = $name;
42
    }
43
44
    /**
45
     * {@inheritDoc}
46
     *
47
     * @return static
48
     */
49 28
    public function nullable(): self
50
    {
51 28
        $this->isNullable = true;
52 28
        return $this;
53
    }
54
55
    /**
56
     * {@inheritDoc}
57
     *
58
     * @return static
59
     */
60 7
    public function truthy(): self
61
    {
62 7
        return $this->check(MixedCheckFactory::getTruthyCheck());
63
    }
64
65
    /**
66
     * {@inheritDoc}
67
     *
68
     * @return static
69
     */
70 7
    public function falsy(): self
71
    {
72 7
        return $this->check(MixedCheckFactory::getFalsyCheck());
73
    }
74
75
    /**
76
     * {@inheritDoc}
77
     *
78
     * @return static
79
     */
80 19
    public function equal($value): self
81
    {
82 19
        return $this->check(MixedCheckFactory::getEqualCheck($value));
83
    }
84
85
    /**
86
     * {@inheritDoc}
87
     *
88
     * @return static
89
     */
90 12
    public function same($value): self
91
    {
92 12
        return $this->check(MixedCheckFactory::getSameCheck($value));
93
    }
94
95
    /**
96
     * {@inheritDoc}
97
     *
98
     * @return static
99
     */
100 270
    public function check(CheckInterface $check, bool $stopOnViolation = false): self
101
    {
102 270
        $this->checks[] = new CheckWrapper($check, $stopOnViolation);
103 270
        return $this;
104
    }
105
106
    /**
107
     * {@inheritDoc}
108
     *
109
     * @return static
110
     */
111 6
    public function stopOnViolation(): self
112
    {
113 6
        return $this->check(new RetrospectiveCheck(), true);
114
    }
115
116
    /**
117
     * {@inheritDoc}
118
     *
119
     * @return static
120
     */
121 4
    public function stopOnAnyPriorViolation(): self
122
    {
123 4
        foreach ($this->checks as $check) {
124 4
            $check->setInterrupting();
125
        }
126 4
        return $this;
127
    }
128
129
    /**
130
     * {@inheritDoc}
131
     */
132 277
    public function validate($value): void
133
    {
134 277
        $this->execute($value);
135
    }
136
137
    /**
138
     * {@inheritDoc}
139
     */
140
    public function getName(): string
141
    {
142
        return $this->name;
143
    }
144
145
    /**
146
     * {@inheritDoc}
147
     */
148
    public function isValid($value): bool
149
    {
150
        try {
151
            $this->validate($value);
152
            return true;
153
        } catch (ValidationError $e) {
154
            return false;
155
        }
156
    }
157
158
    /**
159
     * {@inheritDoc}
160
     */
161 277
    protected function execute($value): ValidationResultInterface
162
    {
163 277
        $result = parent::execute($value);
164 277
        if ($result->preventNextChecks()) {
165
            return $result;
166
        }
167
168 277
        if ($value === null) {
169 26
            if ($this->isNullable) {
170 17
                return new ValidationSuccessResult(true);
171
            }
172
173 9
            throw new ValidationError($this->name, $value, [[CheckName::NOT_NULL, []]]);
174
        }
175
176 268
        $errors = [];
177
178 268
        foreach ($this->checks as $check) {
179
            try {
180 264
                $check->getCheck()->execute($value, $errors);
181 145
            } catch (CheckError $e) {
182 145
                if (!($check->getCheck() instanceof UtilityCheckInterface)) {
183 145
                    $errors[] = $e;
184
                }
185
186 145
                if ($check->isInterrupting()) {
187 46
                    throw ValidationError::fromCheckErrors($this->name, $value, $errors);
188
                }
189
            }
190
        }
191
192 234
        if (\count($errors) > 0) {
193 107
            throw ValidationError::fromCheckErrors($this->name, $value, $errors);
194
        }
195
196 139
        return new ValidationSuccessResult(false);
197
    }
198
}
199