Passed
Push — main ( a6da94...0d356a )
by Breno
01:59
created

AttributesFactory::reflectionClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace BrenoRoosevelt\PhpAttributes;
5
6
use FlexFqcnFinder\FqcnFinderInterface;
7
use ReflectionClass;
8
use ReflectionClassConstant;
9
use ReflectionMethod;
10
use ReflectionParameter;
11
use ReflectionProperty;
12
use Attribute;
13
14
class AttributesFactory
15
{
16
    /**
17
     * @param object|string|object[]|string[]|array $objectOrClass
18
     * @param int $target
19
     * @param string|null $attribute
20
     * @param int $flags
21
     * @return Attributes
22
     */
23
    public function from(
24
        object|string|array $objectOrClass,
25
        int $target = Attribute::TARGET_ALL,
26
        string $attribute = null,
27
        int $flags = 0,
28
    ): Attributes {
29
        $collection = new Attributes();
30
31
        if (is_string($objectOrClass) || is_object($objectOrClass)) {
0 ignored issues
show
introduced by
The condition is_object($objectOrClass) is always false.
Loading history...
32
            $objectOrClass = $this->reflectionClass($objectOrClass);
33
        }
34
35
        $classes =
36
            is_array($objectOrClass) ?
0 ignored issues
show
introduced by
The condition is_array($objectOrClass) is always true.
Loading history...
37
                array_map(fn($class) => $this->reflectionClass($class), $objectOrClass) :
38
                [$objectOrClass];
39
40
        foreach ($classes as $objectOrClass) {
41
            if (Attribute::TARGET_CLASS & $target) {
42
                $collection = $collection->merge($this->fromClass($objectOrClass, $attribute, $flags));
43
            }
44
45
            if (Attribute::TARGET_PROPERTY & $target) {
46
                $collection = $collection->merge($this->fromProperties($objectOrClass, $attribute, $flags));
47
            }
48
49
            if (Attribute::TARGET_METHOD & $target) {
50
                $collection = $collection->merge($this->fromMethods($objectOrClass, $attribute, $flags));
51
            }
52
53
            if (Attribute::TARGET_PARAMETER & $target) {
54
                $collection =
55
                    $collection->merge($this->fromParameters($objectOrClass, null, $attribute, $flags));
56
            }
57
58
            if (Attribute::TARGET_CLASS_CONSTANT & $target) {
59
                $collection = $collection->merge($this->fromConstants($objectOrClass, $attribute, $flags));
60
            }
61
        }
62
63
        return $collection;
64
    }
65
66
    /**
67
     * @param object|object[] $reflectionObject
68
     * @param string|null $attribute
69
     * @param int $flags
70
     * @return Attributes
71
     */
72
    public function fromReflection(object|array $reflectionObject, string $attribute = null, int $flags = 0): Attributes
73
    {
74
        $attributes = [];
75
        $reflectionObject = is_array($reflectionObject) ? $reflectionObject : [$reflectionObject];
0 ignored issues
show
introduced by
The condition is_array($reflectionObject) is always true.
Loading history...
76
        foreach ($reflectionObject as $object) {
77
            if ($object instanceof ReflectionClass ||
78
                $object instanceof ReflectionMethod ||
79
                $object instanceof ReflectionProperty ||
80
                $object instanceof ReflectionParameter ||
81
                $object instanceof ReflectionClassConstant
82
            ) {
83
                foreach ($object->getAttributes($attribute, $flags) as $reflectionAttribute) {
84
                    $attributes[] = new ParsedAttribute($reflectionAttribute, $object);
85
                }
86
            }
87
        }
88
89
        return new Attributes(...$attributes);
90
    }
91
92
    public function fromClass(
93
        object|string $objectOrClass,
94
        string $attribute = null,
95
        int $flags = 0,
96
    ): Attributes {
97
        $objectOrClass = $this->reflectionClass($objectOrClass);
98
        return $this->fromReflection($objectOrClass, $attribute, $flags);
99
    }
100
101
    public function fromProperties(
102
        object|string $objectOrClass,
103
        string $attribute = null,
104
        int $flags = 0,
105
        int $filter = null
106
    ): Attributes {
107
        $collection = new Attributes();
108
        $objectOrClass = $this->reflectionClass($objectOrClass);
109
        foreach ($objectOrClass->getProperties($filter) as $property) {
110
            $collection = $collection->merge($this->fromReflection($property, $attribute, $flags));
111
        }
112
113
        return $collection;
114
    }
115
116
    public function fromMethods(
117
        object|string $objectOrClass,
118
        string $attribute = null,
119
        int $flags = 0,
120
        int $filter = null
121
    ): Attributes {
122
        $collection = new Attributes();
123
        $objectOrClass = $this->reflectionClass($objectOrClass);
124
        foreach ($objectOrClass->getMethods($filter) as $method) {
125
            $collection = $collection->merge($this->fromReflection($method, $attribute, $flags));
126
        }
127
128
        return $collection;
129
    }
130
131
    public function fromParameters(
132
        object|string $objectOrClass,
133
        string $method = null,
134
        string $attribute = null,
135
        int $flags = 0,
136
        int $filter = null
137
    ): Attributes {
138
        $collection = new Attributes();
139
        $objectOrClass = $this->reflectionClass($objectOrClass);
140
        $methods = is_null($method) ? $objectOrClass->getMethods($filter) : [$objectOrClass->getMethod($method)];
141
        foreach ($methods as $method) {
142
            foreach ($method->getParameters() as $parameter) {
143
                $collection = $collection->merge($this->fromReflection($parameter, $attribute, $flags));
144
            }
145
        }
146
147
        return $collection;
148
    }
149
150
    public function fromConstants(
151
        object|string $objectOrClass,
152
        string $attribute = null,
153
        int $flags = 0,
154
        int $filter = null
155
    ): Attributes {
156
        $collection = new Attributes();
157
        $objectOrClass = $this->reflectionClass($objectOrClass);
158
        foreach ($objectOrClass->getReflectionConstants($filter) as $constant) {
159
            $collection = $collection->merge($this->fromReflection($constant, $attribute, $flags));
160
        }
161
162
        return $collection;
163
    }
164
165
    public function fromFqcnFinder(
166
        FqcnFinderInterface $finder,
167
        int $target = Attribute::TARGET_ALL,
168
        string $attribute = null,
169
        int $flags = 0
170
    ): Attributes {
171
        return $this->from($finder->find(), $target, $attribute, $flags);
172
    }
173
174
    protected function reflectionClass(object|string $objectOrClass): ReflectionClass
175
    {
176
        if ($objectOrClass instanceof ReflectionClass) {
177
            return $objectOrClass;
178
        }
179
180
        return new ReflectionClass($objectOrClass);
181
    }
182
}
183