Passed
Pull Request — master (#312)
by Dmitriy
02:17
created

ObjectDataSet::isUseProperty()   A

Complexity

Conditions 6
Paths 11

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.2222
cc 6
nc 11
nop 1
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\DataSet;
6
7
use ReflectionAttribute;
8
use ReflectionObject;
9
use ReflectionProperty;
10
use Yiisoft\Validator\DataSetInterface;
11
use Yiisoft\Validator\RuleInterface;
12
use Yiisoft\Validator\RulesProviderInterface;
13
14
/**
15
 * This data set makes use of attributes introduced in PHP 8. It simplifies rules configuration process, especially for
16
 * nested data and relations. Please refer to the guide for example.
17
 *
18
 * @link https://www.php.net/manual/en/language.attributes.overview.php
19
 */
20
final class ObjectDataSet implements RulesProviderInterface, DataSetInterface
21
{
22
    private object $object;
23
24
    private bool $dataSetProvided;
25
26
    private int $propertyVisibility;
27
28
    /**
29
     * @var ReflectionProperty[]
30
     */
31
    private array $reflectionProperties = [];
32
33
    private iterable $rules;
34
35 38
    public function __construct(
36
        object $object,
37
        int $propertyVisibility = ReflectionProperty::IS_PRIVATE|ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PUBLIC
38
    ) {
39 38
        $this->object = $object;
40 38
        $this->propertyVisibility = $propertyVisibility;
41 38
        $this->parseObject();
42
    }
43
44 33
    public function getRules(): iterable
45
    {
46 33
        return $this->rules;
47
    }
48
49 28
    public function getAttributeValue(string $attribute): mixed
50
    {
51 28
        if ($this->dataSetProvided) {
52 2
            return $this->object->getAttributeValue($attribute);
53
        }
54
55 26
        return isset($this->reflectionProperties[$attribute])
56 26
            ? $this->reflectionProperties[$attribute]->getValue($this->object)
57 26
            : null;
58
    }
59
60 7
    public function getData(): array
61
    {
62 7
        if ($this->dataSetProvided) {
63 2
            return $this->object->getData();
64
        }
65
66 5
        $data = [];
67 5
        foreach ($this->reflectionProperties as $name => $property) {
68 5
            $data[$name] = $property->getValue($this->object);
69
        }
70 5
        return $data;
71
    }
72
73
    // TODO: use Generator to collect attributes
74 38
    private function parseObject(): void
75
    {
76 38
        $objectProvidedRules = $this->object instanceof RulesProviderInterface;
77 38
        $this->dataSetProvided = $this->object instanceof DataSetInterface;
78
79 38
        $this->rules = $objectProvidedRules ? $this->object->getRules() : [];
80
81 38
        if ($this->dataSetProvided) {
82 2
            return;
83
        }
84
85 36
        $reflection = new ReflectionObject($this->object);
86 36
        foreach ($reflection->getProperties($this->propertyVisibility) as $property) {
87 35
            if (PHP_VERSION_ID < 80100) {
88 35
                $property->setAccessible(true);
89
            }
90 35
            $this->reflectionProperties[$property->getName()] = $property;
91
92 35
            if (!$objectProvidedRules) {
93 30
                $attributes = $property->getAttributes(RuleInterface::class, ReflectionAttribute::IS_INSTANCEOF);
94 30
                foreach ($attributes as $attribute) {
95 27
                    $this->rules[$property->getName()][] = $attribute->newInstance();
96
                }
97
            }
98
        }
99
    }
100
}
101