Passed
Pull Request — master (#284)
by Sergei
02:18
created

AttributeDataSet::getData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 8
ccs 0
cts 5
cp 0
rs 10
cc 2
nc 2
nop 0
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\Exception\MissingAttributeException;
12
use Yiisoft\Validator\RuleInterface;
13
use Yiisoft\Validator\RulesProviderInterface;
14
15
/**
16
 * This data set makes use of attributes introduced in PHP 8. It simplifies rules configuration process, especially for
17
 * nested data and relations. Please refer to the guide for example.
18
 *
19
 * @link https://www.php.net/manual/en/language.attributes.overview.php
20
 */
21
final class AttributeDataSet implements RulesProviderInterface, DataSetInterface
22
{
23
    private object $object;
24
25
    /**
26
     * @var ReflectionProperty[]
27
     */
28
    private array $reflectionProperties = [];
29
30
    private array $rules = [];
31
32 9
    public function __construct(object $object)
33
    {
34 9
        $this->object = $object;
35 9
        $this->collectRules();
36
    }
37
38 8
    public function getRules(): iterable
39
    {
40 8
        return $this->rules;
41
    }
42
43 2
    public function getAttributeValue(string $attribute)
44
    {
45 2
        if (!isset($this->reflectionProperties[$attribute])) {
46
            throw new MissingAttributeException("There is no \"$attribute\" key in the array.");
47
        }
48
49 2
        return $this->reflectionProperties[$attribute]->getValue($this->object);
50
    }
51
52
    public function getData(): array
53
    {
54
        $data = [];
55
        foreach ($this->reflectionProperties as $name => $property) {
56
            $data[$name] = $property->getValue($this->object);
57
        }
58
59
        return $data;
60
    }
61
62
    // TODO: use Generator to collect attributes
63 9
    private function collectRules(): void
64
    {
65 9
        $reflection = new ReflectionObject($this->object);
66 9
        foreach ($reflection->getProperties() as $property) {
67 8
            $attributes = $property->getAttributes(RuleInterface::class, ReflectionAttribute::IS_INSTANCEOF);
68 8
            if (!empty($attributes) || $property->isPublic()) {
69 6
                $this->reflectionProperties[$property->getName()] = $property;
70
            }
71 8
            foreach ($attributes as $attribute) {
72 5
                $this->rules[$property->getName()][] = $attribute->newInstance();
73
            }
74
        }
75
    }
76
}
77