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

AttributesRulesProvider::createAttributes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 2
nc 2
nop 1
crap 2
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 ReflectionObject;
11
use ReflectionProperty;
12
use Yiisoft\Validator\RuleInterface;
13
use Yiisoft\Validator\RulesProviderInterface;
14
15
final class AttributesRulesProvider implements RulesProviderInterface
16
{
17
    /**
18
     * @var array<RuleInterface[]>|null
19
     */
20
    private Generator|null $rules = null;
21
22 13
    public function __construct(
23
        /**
24
         * @param class-string|object $class
25
         */
26
        private string|object $source,
27
        private int $propertyVisibility = ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PUBLIC
28
    ) {
29
    }
30
31
    /**
32
     * @return array<RuleInterface[]>
33
     */
34 13
    public function getRules(): iterable
35
    {
36 13
        if ($this->rules === null) {
37 13
            $this->rules = $this->parseRules();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->parseRules() of type Generator is incompatible with the declared type array<mixed,Yiisoft\Vali...r\RuleInterface[]>|null of property $rules.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
38
        }
39
40 13
        yield from $this->rules;
0 ignored issues
show
Bug Best Practice introduced by
The expression YieldFromNode returns the type Generator which is incompatible with the documented return type array<mixed,Yiisoft\Validator\RuleInterface[]>.
Loading history...
41
    }
42
43
    /**
44
     * @return Generator<RuleInterface[]>
45
     */
46 13
    private function parseRules(): iterable
47
    {
48 13
        $reflection = is_object($this->source)
49 5
            ? new ReflectionObject($this->source)
50 8
            : new ReflectionClass($this->source);
51
52 13
        $reflectionProperties = $reflection->getProperties();
53 13
        if ($reflectionProperties === []) {
54
            return [];
55
        }
56 13
        foreach ($reflectionProperties as $property) {
57 13
            if (!$this->isUseProperty($property)) {
58 7
                continue;
59
            }
60
61 13
            $attributes = $property->getAttributes(RuleInterface::class, ReflectionAttribute::IS_INSTANCEOF);
62 13
            if ($attributes === []) {
63
                continue;
64
            }
65
66 13
            yield $property->getName() => $this->createAttributes($attributes);
67
        }
68
    }
69
70
    /**
71
     * @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...
72
     *
73
     * @return iterable
74
     */
75 13
    private function createAttributes(array $attributes): iterable
76
    {
77 13
        foreach ($attributes as $attribute) {
78 13
            yield $attribute->newInstance();
79
        }
80
    }
81
82 13
    private function isUseProperty(ReflectionProperty $property): bool
83
    {
84 13
        return ($property->isPublic() && ($this->propertyVisibility & ReflectionProperty::IS_PUBLIC))
85 12
            || ($property->isPrivate() && ($this->propertyVisibility & ReflectionProperty::IS_PRIVATE))
86 13
            || ($property->isProtected() && ($this->propertyVisibility & ReflectionProperty::IS_PROTECTED));
87
    }
88
}
89