Passed
Push — master ( 8f2b33...1f21d2 )
by Alexander
02:58
created

AttributeDataSet::handleAttributes()   C

Complexity

Conditions 14
Paths 51

Size

Total Lines 74
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 37
CRAP Score 14.0826

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 14
eloc 42
c 1
b 0
f 0
nc 51
nop 1
dl 0
loc 74
ccs 37
cts 40
cp 0.925
crap 14.0826
rs 6.2666

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
/**
18
 * This data set makes use of attributes introduced in PHP 8. It simplifies rules configuration process, especially for
19
 * nested data and relations. Please refer to the guide for example.
20
 *
21
 * @link https://www.php.net/manual/en/language.attributes.overview.php
22
 */
23
final class AttributeDataSet implements RulesProviderInterface
24
{
25
    use ArrayDataTrait;
26
27
    private object $baseAnnotatedObject;
28
29 2
    public function __construct(object $baseAnnotatedObject, array $data = [])
30
    {
31 2
        $this->baseAnnotatedObject = $baseAnnotatedObject;
32 2
        $this->data = $data;
33
    }
34
35 2
    public function getRules(): iterable
36
    {
37 2
        $classMeta = new ReflectionClass($this->baseAnnotatedObject);
38
39 2
        return $this->handleAttributes($classMeta);
40
    }
41
42 2
    private function handleAttributes(ReflectionClass $classMeta): array
43
    {
44 2
        $rules = [];
45 2
        foreach ($classMeta->getProperties() as $property) {
46 2
            if ($property->isStatic()) {
47
                continue;
48
            }
49
50 2
            foreach ([HasMany::class, HasOne::class] as $className) {
51 2
                $attributes = $property->getAttributes($className);
52 2
                if (empty($attributes)) {
53 2
                    continue;
54
                }
55
56 1
                $relatedClassName = $attributes[0]->getArguments()[0];
57
58
                try {
59 1
                    $relatedClassMeta = new ReflectionClass($relatedClassName);
60
                } catch (ReflectionException) {
61
                    throw new InvalidArgumentException("Class \"$relatedClassName\" not found.");
62
                }
63
64 1
                $nestedRule = new Nested(
65 1
                    $this->handleAttributes($relatedClassMeta),
66 1
                    ...(($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

66
                    /** @scrutinizer ignore-type */ ...(($property->getAttributes(Nested::class)[0] ?? null)?->getArguments() ?? [])
Loading history...
67
                );
68
69 1
                if ($className !== HasMany::class) {
70 1
                    $rules[$property->getName()] = $nestedRule;
71
                } else {
72
                    /** @psalm-suppress UndefinedMethod */
73 1
                    $rules[$property->getName()][] = new Each(
74 1
                        [$nestedRule],
75 1
                        ...(($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

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