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

AttributeDataSet   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 52
Duplicated Lines 0 %

Test Coverage

Coverage 72.72%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 11
eloc 21
c 1
b 0
f 0
dl 0
loc 52
ccs 16
cts 22
cp 0.7272
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getAttributeValue() 0 7 2
A __construct() 0 4 1
A collectRules() 0 10 5
A getRules() 0 3 1
A getData() 0 8 2
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