Passed
Push — master ( bf98f6...b66066 )
by Smoren
02:12
created

ContainerRule::isAttribute()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3.2098

Importance

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