InputGuard::success()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 30
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 15
nc 3
nop 0
dl 0
loc 30
ccs 16
cts 16
cp 1
crap 4
rs 9.7666
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace InputGuard;
5
6
use InputGuard\Guards\BoolGuard;
7
use InputGuard\Guards\ErrorMessagesBase;
8
use InputGuard\Guards\FloatGuard;
9
use InputGuard\Guards\Guard;
10
use InputGuard\Guards\GuardFactory;
11
use InputGuard\Guards\InListGuard;
12
use InputGuard\Guards\InstanceOfGuard;
13
use InputGuard\Guards\IntGuard;
14
use InputGuard\Guards\IterableFloatGuard;
15
use InputGuard\Guards\IterableGuard;
16
use InputGuard\Guards\IterableIntGuard;
17
use InputGuard\Guards\IterableStringableGuard;
18
use InputGuard\Guards\IterableStringGuard;
19
use InputGuard\Guards\StringableGuard;
20
use InputGuard\Guards\StringGuard;
21
22
/** @noinspection EfferentObjectCouplingInspection */
23
24
/**
25
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
26
 */
27
class InputGuard implements GuardChain
28
{
29
    use ErrorMessagesBase;
30
31
    /**
32
     * @var Guard[]
33
     */
34
    private $guards = [];
35
36
    /**
37
     * @var bool|null
38
     */
39
    private $validated;
40
41
    /**
42
     * @var GuardFactory
43
     */
44
    private $factory;
45
46
    /**
47
     * @param Configuration $configuration
48
     */
49 30
    public function __construct(Configuration $configuration = null)
50
    {
51 30
        $this->factory = new GuardFactory($configuration ?? new DefaultConfiguration());
52 30
    }
53
54 1
    public function __clone()
55
    {
56 1
        $this->errorMessages = [];
57 1
        $this->guards        = [];
58 1
        $this->validated     = null;
59 1
    }
60
61 2
    public function bool($input): BoolGuard
62
    {
63
        /** @noinspection PhpIncompatibleReturnTypeInspection */
64 2
        return $this->createGuard(BoolGuard::class, $input);
65
    }
66
67 7
    public function int($input): IntGuard
68
    {
69
        /** @noinspection PhpIncompatibleReturnTypeInspection */
70 7
        return $this->createGuard(IntGuard::class, $input);
71
    }
72
73 3
    public function float($input): FloatGuard
74
    {
75
        /** @noinspection PhpIncompatibleReturnTypeInspection */
76 3
        return $this->createGuard(FloatGuard::class, $input);
77
    }
78
79 2
    public function instanceOf($input, string $className): InstanceOfGuard
80
    {
81
        /** @noinspection PhpIncompatibleReturnTypeInspection */
82 2
        return $this->createGuard(InstanceOfGuard::class, $input, $className);
83
    }
84
85 3
    public function string($input): StringGuard
86
    {
87
        /** @noinspection PhpIncompatibleReturnTypeInspection */
88 3
        return $this->createGuard(StringGuard::class, $input);
89
    }
90
91 2
    public function stringable($input): StringableGuard
92
    {
93
        /** @noinspection PhpIncompatibleReturnTypeInspection */
94 2
        return $this->createGuard(StringableGuard::class, $input);
95
    }
96
97 1
    public function array($input): IterableGuard
98
    {
99 1
        return $this->iterable($input);
100
    }
101
102 3
    public function iterable($input): IterableGuard
103
    {
104
        /** @noinspection PhpIncompatibleReturnTypeInspection */
105 3
        return $this->createGuard(IterableGuard::class, $input);
106
    }
107
108 2
    public function iterableInt($input): IterableIntGuard
109
    {
110
        /** @noinspection PhpIncompatibleReturnTypeInspection */
111 2
        return $this->createGuard(IterableIntGuard::class, $input);
112
    }
113
114 1
    public function iterableFloat($input): IterableFloatGuard
115
    {
116
        /** @noinspection PhpIncompatibleReturnTypeInspection */
117 1
        return $this->createGuard(IterableFloatGuard::class, $input);
118
    }
119
120 1
    public function iterableString($input): IterableStringGuard
121
    {
122
        /** @noinspection PhpIncompatibleReturnTypeInspection */
123 1
        return $this->createGuard(IterableStringGuard::class, $input);
124
    }
125
126 1
    public function iterableStringable($input): IterableStringableGuard
127
    {
128
        /** @noinspection PhpIncompatibleReturnTypeInspection */
129 1
        return $this->createGuard(IterableStringableGuard::class, $input);
130
    }
131
132 1
    public function inList($input, iterable $list): InListGuard
133
    {
134
        /** @noinspection PhpIncompatibleReturnTypeInspection */
135 1
        return $this->createGuard(InListGuard::class, $input, $list);
136
    }
137
138 15
    public function success(): bool
139
    {
140 15
        if ($this->validated !== null) {
141 5
            return $this->validated;
142
        }
143
144
        // Pass a local error messages variable to avoid merging arrays inside a loop.
145 15
        $error_messages = [];
146 15
        $success        = array_reduce(
147 15
            $this->guards,
148
            static function (bool $success, Guard $guard) use (&$error_messages): bool {
149
                // Check for success/failure for all collected Val's.
150 12
                if ($guard->success() === false) {
151 5
                    $error_messages[] = $guard->pullErrorMessages();
152 5
                    $success          = false;
153
                }
154
155 12
                return $success;
156 15
            },
157 15
            true
158
        );
159
160 15
        if ($error_messages) {
161
            // Merge the errors, remove duplicates, and reset the keys.
162 5
            $this->errorMessages = array_values(array_unique(array_merge($this->errorMessages, ...$error_messages)));
163
        }
164
165 15
        $this->validated = $success;
166
167 15
        return $success;
168
    }
169
170 3
    public function value(): InputGuard
171
    {
172 3
        return $this;
173
    }
174
175 25
    public function add(Guard $val): Guard
176
    {
177 25
        $this->validated = null;
178 25
        $this->guards[]  = $val;
179
180 25
        return $val;
181
    }
182
183 25
    private function createGuard(string $class, $input, ...$extra): Guard
184
    {
185 25
        return $this->add($this->factory->create($class, $input, $extra));
186
    }
187
}
188