Passed
Pull Request — master (#265)
by Dmitriy
02:42
created

AttributesRulesProvider::parseRules()   A

Complexity

Conditions 6
Paths 10

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 6.105

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 13
c 2
b 0
f 0
dl 0
loc 21
ccs 12
cts 14
cp 0.8571
rs 9.2222
cc 6
nc 10
nop 0
crap 6.105
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\RulesProvider;
6
7
use Generator;
8
use ReflectionAttribute;
9
use ReflectionClass;
10
use ReflectionException;
11
use ReflectionObject;
12
use ReflectionProperty;
13
use Yiisoft\Validator\RuleInterface;
14
use Yiisoft\Validator\RulesProviderInterface;
15
16
final class AttributesRulesProvider implements RulesProviderInterface
17
{
18
    private Generator|iterable|null $rules = null;
19
20 13
    public function __construct(
21
        /**
22
         * @param class-string|object $class
23
         */
24
        private string|object $source,
25
        private int $propertyVisibility = ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PUBLIC
26
    ) {
27
    }
28
29
    /**
30
     * @throws ReflectionException
31
     *
32
     * @return iterable
33
     */
34 13
    public function getRules(): iterable
35
    {
36 13
        if ($this->rules === null) {
37 13
            $this->rules = $this->parseRules();
38
        }
39
40 13
        yield from $this->rules;
41
    }
42
43
    /**
44
     * @throws ReflectionException
45
     *
46
     * @return Generator
47
     */
48 13
    private function parseRules(): iterable
49
    {
50 13
        $reflection = is_object($this->source)
51 5
            ? new ReflectionObject($this->source)
52 8
            : new ReflectionClass($this->source);
53
54 13
        $reflectionProperties = $reflection->getProperties();
55 13
        if ($reflectionProperties === []) {
56
            return [];
57
        }
58 13
        foreach ($reflectionProperties as $property) {
59 13
            if (!$this->isUseProperty($property)) {
60 7
                continue;
61
            }
62
63 13
            $attributes = $property->getAttributes(RuleInterface::class, ReflectionAttribute::IS_INSTANCEOF);
64 13
            if ($attributes === []) {
65
                continue;
66
            }
67
68 13
            yield $property->getName() => $this->createAttributes($attributes);
69
        }
70
    }
71
72
    /**
73
     * @param array<array-key, ReflectionAttribute<RuleInterface>> $attributes
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, Reflect...tribute<RuleInterface>> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, ReflectionAttribute<RuleInterface>>.
Loading history...
74
     *
75
     * @return iterable
76
     */
77 13
    private function createAttributes(array $attributes): iterable
78
    {
79 13
        foreach ($attributes as $attribute) {
80 13
            yield $attribute->newInstance();
81
        }
82
    }
83
84 13
    private function isUseProperty(ReflectionProperty $property): bool
85
    {
86 13
        return ($property->isPublic() && ($this->propertyVisibility & ReflectionProperty::IS_PUBLIC))
87 12
            || ($property->isPrivate() && ($this->propertyVisibility & ReflectionProperty::IS_PRIVATE))
88 13
            || ($property->isProtected() && ($this->propertyVisibility & ReflectionProperty::IS_PROTECTED));
89
    }
90
}
91