Passed
Push — master ( b66066...5b471b )
by Smoren
02:41
created

ContainerRule::getCountableCheck()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Smoren\Validator\Rules;
6
7
use ArrayAccess;
8
use Smoren\Validator\Exceptions\ValidationError;
9
use Smoren\Validator\Helpers\ContainerAccessHelper;
10
use Smoren\Validator\Interfaces\BaseRuleInterface;
11
use Smoren\Validator\Interfaces\CheckInterface;
12
use Smoren\Validator\Interfaces\ContainerRuleInterface;
13
use Smoren\Validator\Interfaces\IntegerRuleInterface;
14
use Smoren\Validator\Structs\Check;
15
16
class ContainerRule extends Rule implements ContainerRuleInterface
17
{
18
    public const ERROR_NOT_CONTAINER = 'not_container';
19
    public const ERROR_NOT_ARRAY = 'not_array';
20
    public const ERROR_NOT_INDEXED_ARRAY = 'not_array';
21
    public const ERROR_NOT_ASSOCIATIVE_ARRAY = 'not_array';
22
    public const ERROR_NOT_ITERABLE = 'not_iterable';
23
    public const ERROR_NOT_COUNTABLE = 'not_countable';
24
    public const ERROR_NOT_EMPTY = 'not_empty';
25
    public const ERROR_EMPTY = 'not_empty';
26
    public const ERROR_NOT_ARRAY_ACCESSIBLE = 'not_array_accessible';
27
    public const ERROR_NOT_OBJECT = 'not_object';
28
    public const ERROR_NOT_STD_OBJECT = 'not_std_object';
29
    public const ERROR_NOT_INSTANCE_OF = 'not_instance_of';
30
    public const ERROR_LENGTH_IS_NOT = 'length_is_not';
31
    public const ERROR_ATTRIBUTE_NOT_EXIST = 'attribute_not_exist';
32
    public const ERROR_BAD_ATTRIBUTE = 'bad_attribute';
33
34
    /**
35
     * ContainerRule constructor.
36
     */
37 16
    public function __construct()
38
    {
39 16
        $this->addCheck(new Check(
40 16
            self::ERROR_NOT_CONTAINER,
41 16
            fn ($value) => is_array($value) || is_object($value),
42 16
            [],
43 16
            true
44 16
        ));
45
    }
46
47
    /**
48
     * {@inheritDoc}
49
     *
50
     * @return static
51
     */
52 2
    public function array(): self
53
    {
54 2
        return $this->addCheck(new Check(
55 2
            self::ERROR_NOT_ARRAY,
56 2
            fn ($value) => is_array($value)
57 2
        ));
58
    }
59
60
    /**
61
     * {@inheritDoc}
62
     *
63
     * @return static
64
     */
65 2
    public function indexedArray(): self
66
    {
67 2
        return $this->addCheck(new Check(
68 2
            self::ERROR_NOT_INDEXED_ARRAY,
69 2
            fn ($value) => is_array($value) && (array_values($value) === $value)
70 2
        ));
71
    }
72
73
    /**
74
     * {@inheritDoc}
75
     *
76
     * @return static
77
     */
78 1
    public function associativeArray(): self
79
    {
80 1
        return $this->addCheck(new Check(
81 1
            self::ERROR_NOT_ASSOCIATIVE_ARRAY,
82 1
            fn ($value) => is_array($value) && (array_values($value) !== $value)
83 1
        ));
84
    }
85
86
    /**
87
     * {@inheritDoc}
88
     *
89
     * @return static
90
     */
91
    public function arrayAccessible(): self
92
    {
93
        return $this->addCheck(new Check(
94
            self::ERROR_NOT_ARRAY_ACCESSIBLE,
95
            fn ($value) => is_array($value) || $value instanceof ArrayAccess
96
        ));
97
    }
98
99
    /**
100
     * {@inheritDoc}
101
     *
102
     * @return static
103
     */
104
    public function iterable(): self
105
    {
106
        return $this->addCheck(new Check(
107
            self::ERROR_NOT_ITERABLE,
108
            fn ($value) => is_iterable($value)
109
        ));
110
    }
111
112
    /**
113
     * {@inheritDoc}
114
     *
115
     * @return static
116
     */
117
    public function countable(): self
118
    {
119
        return $this->addCheck($this->getCountableCheck());
120
    }
121
122
    /**
123
     * {@inheritDoc}
124
     *
125
     * @return static
126
     */
127
    public function empty(): self
128
    {
129
        return $this->addCheck(new Check(
130
            self::ERROR_NOT_EMPTY,
131
            fn ($value) => count($value) === 0,
132
            [],
133
            false,
134
            [$this->getCountableCheck()]
135
        ));
136
    }
137
138
    /**
139
     * {@inheritDoc}
140
     *
141
     * @return static
142
     */
143
    public function notEmpty(): self
144
    {
145
        return $this->addCheck(new Check(
146
            self::ERROR_EMPTY,
147
            fn ($value) => count($value) > 0,
148
            [],
149
            false,
150
            [$this->getCountableCheck()]
151
        ));
152
    }
153
154
    /**
155
     * {@inheritDoc}
156
     *
157
     * @return static
158
     */
159 2
    public function object(): self
160
    {
161 2
        return $this->addCheck(new Check(
162 2
            self::ERROR_NOT_OBJECT,
163 2
            fn ($value) => is_object($value)
164 2
        ));
165
    }
166
167
    /**
168
     * {@inheritDoc}
169
     *
170
     * @return static
171
     */
172
    public function stdObject(): self
173
    {
174
        return $this->addCheck(new Check(
175
            self::ERROR_NOT_STD_OBJECT,
176
            fn ($value) => $value instanceof \stdClass
177
        ));
178
    }
179
180
    /**
181
     * {@inheritDoc}
182
     *
183
     * @return static
184
     */
185
    public function instanceOf(string $class): self
186
    {
187
        return $this->addCheck(new Check(
188
            self::ERROR_NOT_INSTANCE_OF,
189
            fn ($value) => $value instanceof $class
190
        ));
191
    }
192
193
194
    /**
195
     * {@inheritDoc}
196
     *
197
     * @return static
198
     */
199 2
    public function lengthIs(IntegerRuleInterface $rule): self
200
    {
201
        $violations = [];
202 2
        return $this->addCheck(new Check(
203 2
            self::ERROR_LENGTH_IS_NOT,
204 2
            static function ($value) use ($rule, &$violations) {
205
                try {
206
                    /** @var \Countable $value */
207 2
                    $rule->validate(count($value));
208 1
                    return true;
209 1
                } catch (ValidationError $e) {
210 1
                    $violations = $e->getSummary();
211 1
                    return false;
212
                }
213 2
            },
214 2
            ['violations' => &$violations],
215 2
            false,
216 2
            [$this->getCountableCheck()]
217 2
        ));
218
    }
219
220
    /**
221
     * {@inheritDoc}
222
     *
223
     * @return static
224
     */
225
    public function hasAttribute(string $name): self
226
    {
227
        return $this->addCheck($this->getHasAttributeCheck($name));
228
    }
229
230
    /**
231
     * {@inheritDoc}
232
     *
233
     * @return static
234
     */
235 1
    public function isAttribute(string $name, BaseRuleInterface $rule): self
236
    {
237
        $violations = [];
238 1
        return $this->addCheck(new Check(
239 1
            self::ERROR_BAD_ATTRIBUTE,
240 1
            function ($value) use ($name, $rule, &$violations) {
241
                try {
242 1
                    $rule->validate(ContainerAccessHelper::getAttributeValue($value, $name));
243
                    return true;
244 1
                } catch (ValidationError $e) {
245 1
                    $violations = $e->getSummary();
246 1
                    return false;
247
                }
248 1
            },
249 1
            ['name' => $name, 'violations' => &$violations],
250 1
            false,
251 1
            [$this->getHasAttributeCheck($name)]
252 1
        ));
253
    }
254
255
    /**
256
     * {@inheritDoc}
257
     *
258
     * @return static
259
     */
260
    public function everyKeyIs(BaseRuleInterface $rule): self
261
    {
262
        // TODO: Implement everyKeyIs() method.
263
        return $this;
264
    }
265
266
    /**
267
     * {@inheritDoc}
268
     *
269
     * @return static
270
     */
271
    public function everyValueIs(BaseRuleInterface $rule): self
272
    {
273
        // TODO: Implement everyValueIs() method.
274
        return $this;
275
    }
276
277 2
    protected function getCountableCheck(): CheckInterface
278
    {
279 2
        return new Check(
280 2
            self::ERROR_NOT_COUNTABLE,
281 2
            fn ($value) => is_countable($value)
282 2
        );
283
    }
284
285 5
    protected function getHasAttributeCheck(string $name): CheckInterface
286
    {
287 5
        return new Check(
288 5
            self::ERROR_ATTRIBUTE_NOT_EXIST,
289 5
            fn ($value) => ContainerAccessHelper::hasAccessibleAttribute($value, $name),
290 5
            ['name' => $name]
291 5
        );
292
    }
293
}
294