Test Setup Failed
Push — master ( e94fe5...b7ec94 )
by
unknown
02:01
created

AttributeDataSet::handleAttributes()   C

Complexity

Conditions 12
Paths 51

Size

Total Lines 70
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 39
nc 51
nop 1
dl 0
loc 70
rs 6.9666
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\DataSet;
6
7
use InvalidArgumentException;
8
use ReflectionClass;
9
use ReflectionException;
10
use Yiisoft\Validator\Attribute\HasMany;
11
use Yiisoft\Validator\Attribute\HasOne;
12
use Yiisoft\Validator\Rule\Each;
13
use Yiisoft\Validator\Rule\Nested;
14
use Yiisoft\Validator\RuleInterface;
15
use Yiisoft\Validator\RulesProviderInterface;
16
17
use function in_array;
18
19
/**
20
 * This data set makes use of attributes introduced in PHP 8. It simplifies rules configuration process, especially for
21
 * nested data and relations. Please refer to the guide for example.
22
 *
23
 * @link https://www.php.net/manual/en/language.attributes.overview.php
24
 */
25
final class AttributeDataSet implements RulesProviderInterface
26
{
27
    use ArrayDataTrait;
28
29
    private object $baseAnnotatedObject;
30
31
    public function __construct(object $baseAnnotatedObject, array $data = [])
32
    {
33
        $this->baseAnnotatedObject = $baseAnnotatedObject;
34
        $this->data = $data;
35
    }
36
37
    public function getRules(): iterable
38
    {
39
        $classMeta = new ReflectionClass($this->baseAnnotatedObject);
40
41
        return $this->handleAttributes($classMeta);
42
    }
43
44
    private function handleAttributes(ReflectionClass $classMeta): array
45
    {
46
        $rules = [];
47
        foreach ($classMeta->getProperties() as $property) {
48
            if ($property->isStatic()) {
49
                continue;
50
            }
51
52
            foreach ([HasMany::class, HasOne::class] as $className) {
53
                $attributes = $property->getAttributes($className);
54
                if (empty($attributes)) {
55
                    continue;
56
                }
57
58
                $relatedClassName = $attributes[0]->getArguments()[0];
59
60
                try {
61
                    $relatedClassMeta = new ReflectionClass($relatedClassName);
62
                } catch (ReflectionException) {
63
                    throw new InvalidArgumentException("Class \"$relatedClassName\" not found.");
64
                }
65
66
                $nestedRule = new Nested(
67
                    $this->handleAttributes($relatedClassMeta),
68
                    ...(($property->getAttributes(Nested::class)[0] ?? null)?->getArguments() ?? [])
0 ignored issues
show
Bug introduced by
$property->getAttributes...tArguments() ?? array() is expanded, but the parameter $errorWhenPropertyPathIsNotFound of Yiisoft\Validator\Rule\Nested::__construct() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

68
                    /** @scrutinizer ignore-type */ ...(($property->getAttributes(Nested::class)[0] ?? null)?->getArguments() ?? [])
Loading history...
69
                );
70
71
                if ($className !== HasMany::class) {
72
                    $rules[$property->getName()] = $nestedRule;
73
                } else {
74
                    /** @psalm-suppress UndefinedMethod */
75
                    $rules[$property->getName()][] = new Each(
76
                        [$nestedRule],
77
                        ...(($property->getAttributes(Each::class)[0] ?? null)?->getArguments() ?? [])
0 ignored issues
show
Bug introduced by
$property->getAttributes...tArguments() ?? array() is expanded, but the parameter $incorrectInputMessage of Yiisoft\Validator\Rule\Each::__construct() does not expect variable arguments. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

77
                        /** @scrutinizer ignore-type */ ...(($property->getAttributes(Each::class)[0] ?? null)?->getArguments() ?? [])
Loading history...
78
                    );
79
                }
80
            }
81
82
            $flatRules = [];
83
            $attributes = $property->getAttributes();
84
            foreach ($attributes as $attribute) {
85
                if (!is_subclass_of($attribute->getName(), RuleInterface::class)) {
86
                    continue;
87
                }
88
89
                if (in_array($attribute->getName(), [Each::class, Nested::class])) {
90
                    continue;
91
                }
92
93
                $flatRules[] = $attribute->newInstance();
94
            }
95
96
            if (!$flatRules) {
97
                continue;
98
            }
99
100
            if ((string) $property->getType() !== 'array') {
101
                $rules[$property->getName()] = $flatRules;
102
103
                continue;
104
            }
105
106
            /** @psalm-suppress UndefinedMethod */
107
            $rules[$property->getName()][] = new Each(
108
                $flatRules,
109
                ...(($property->getAttributes(Each::class)[0] ?? null)?->getArguments() ?? [])
110
            );
111
        }
112
113
        return $rules;
114
    }
115
}
116