Completed
Push — master ( 90be80...4028a0 )
by Tim
02:24
created

ReflectionUtility::getPropertyNamesTaggedWith()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 0
cts 3
cp 0
rs 9.8333
c 0
b 0
f 0
cc 3
nc 3
nop 2
crap 12
1
<?php
2
3
/**
4
 * Reflection helper.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Autoloader\Utility;
9
10
use TYPO3\CMS\Core\Utility\GeneralUtility;
11
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
12
use TYPO3\CMS\Extbase\Reflection\ClassReflection;
13
use TYPO3\CMS\Extbase\Reflection\ReflectionService;
14
15
/**
16
 * Reflection helper.
17
 */
18
class ReflectionUtility
19
{
20
    /**
21
     * Create a new class reflection. Do not use the makeInstance or objectManager
22
     * because the reflection API is also used in front of the caching framework.
23
     *
24
     * @param string $className
25
     *
26
     * @return ClassReflection
27
     *
28
     * @deprecated
29
     */
30
    public static function createReflectionClass($className)
31
    {
32
        return new ClassReflection($className);
33
    }
34
35
    /**
36
     * Check if the given class is instantiable.
37
     *
38
     * @param string $className
39
     *
40
     * @return bool
41
     */
42
    public static function isInstantiable($className): bool
43
    {
44
        if (self::is9orHigher()) {
45
            $reflectionClass = new \ReflectionClass($className);
46
47
            return (bool) $reflectionClass->isInstantiable();
48
        }
49
50
        return (bool) self::createReflectionClass($className)
0 ignored issues
show
Deprecated Code introduced by
The method HDNET\Autoloader\Utility...createReflectionClass() has been deprecated.

This method has been deprecated.

Loading history...
51
            ->isInstantiable();
52
    }
53
54
    /**
55
     * Get the name of the parent class.
56
     *
57
     * @param string $className
58
     *
59
     * @return string
60
     */
61
    public static function getParentClassName($className)
62
    {
63
        if (self::is9orHigher()) {
64
            $reflectionClass = new \ReflectionClass($className);
65
66
            return $reflectionClass->getParentClass()->getName();
67
        }
68
69
        return self::createReflectionClass($className)
0 ignored issues
show
Deprecated Code introduced by
The method HDNET\Autoloader\Utility...createReflectionClass() has been deprecated.

This method has been deprecated.

Loading history...
70
            ->getParentClass()
71
            ->getName();
72
    }
73
74
    /**
75
     * Get first class tag information.
76
     * The trimmed value if the tag exists and FALSE if the tag do not exists.
77
     *
78
     * @param string $className
79
     * @param string $tag
80
     *
81
     * @return string|bool
82
     */
83
    public static function getFirstTagValue(string $className, string $tag)
84
    {
85
        if (self::is9orHigher()) {
86
            $rc = new \ReflectionClass($className);
87
            if (strpos($rc->getDocComment(), '@' . $tag) === false) {
88
                return false;
89
            }
90
91
            $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
92
            $values = $reflectionService->getClassTagValues($className, $tag);
93
        } else {
94
            $classReflection = self::createReflectionClass($className);
0 ignored issues
show
Deprecated Code introduced by
The method HDNET\Autoloader\Utility...createReflectionClass() has been deprecated.

This method has been deprecated.

Loading history...
95
            if (!$classReflection->isTaggedWith($tag)) {
96
                return false;
97
            }
98
            $values = $classReflection->getTagValues($tag);
99
        }
100
101
        if (\is_array($values)) {
102
            return \trim((string) $values[0]);
103
        }
104
105
        return false;
106
    }
107
108
    /**
109
     * Get the tag configuration from this method and respect multiple line and space configuration.
110
     *
111
     * @param string $className
112
     * @param        $methodName
113
     * @param array  $tagNames
114
     *
115
     * @return array
116
     */
117
    public static function getTagConfigurationForMethod($className, $methodName, array $tagNames): array
118
    {
119
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
120
        $tags = $reflectionService->getMethodTagsValues($className, $methodName);
121
122
        $configuration = [];
123
        foreach ($tagNames as $tagName) {
124
            $configuration[$tagName] = [];
125
            if (!\is_array($tags[$tagName])) {
126
                continue;
127
            }
128
            foreach ($tags[$tagName] as $c) {
129
                $configuration[$tagName] = \array_merge(
130
                    $configuration[$tagName],
131
                    GeneralUtility::trimExplode(' ', $c, true)
132
                );
133
            }
134
        }
135
136
        return $configuration;
137
    }
138
139
    /**
140
     * Get the tag configuration from this method and respect multiple line and space configuration.
141
     *
142
     * @param string $className
143
     * @param array  $tagNames
144
     *
145
     * @return array
146
     */
147
    public static function getTagConfigurationForClass(string $className, array $tagNames): array
148
    {
149
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
150
        $tags = $reflectionService->getClassTagsValues($className);
151
152
        $configuration = [];
153
        foreach ($tagNames as $tagName) {
154
            $configuration[$tagName] = [];
155
            if (!\is_array($tags[$tagName])) {
156
                continue;
157
            }
158
            foreach ($tags[$tagName] as $c) {
159
                $configuration[$tagName] = \array_merge(
160
                    $configuration[$tagName],
161
                    GeneralUtility::trimExplode(' ', $c, true)
162
                );
163
            }
164
        }
165
166
        return $configuration;
167
    }
168
169
    /**
170
     * Get the tag configuration from this method and respect multiple line and space configuration.
171
     *
172
     * @param string $className
173
     * @param string $property
174
     * @param array  $tagNames
175
     *
176
     * @return array
177
     */
178
    public static function getTagConfigurationForProperty(string $className, string $property, array $tagNames): array
179
    {
180
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
181
        $tags = $reflectionService->getClassSchema($className)->getProperty($property)['tags'];
182
183
        $configuration = [];
184
        foreach ($tagNames as $tagName) {
185
            $configuration[$tagName] = [];
186
            if (!\is_array($tags[$tagName])) {
187
                continue;
188
            }
189
            foreach ($tags[$tagName] as $c) {
190
                $configuration[$tagName] = \array_merge(
191
                    $configuration[$tagName],
192
                    GeneralUtility::trimExplode(' ', $c, true)
193
                );
194
            }
195
        }
196
197
        return $configuration;
198
    }
199
200
    /**
201
     * Get public method names.
202
     *
203
     * @param string $className
204
     *
205
     * @return array
206
     */
207
    public static function getPropertyNames(string $className): array
208
    {
209
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
210
211
        return \array_keys($reflectionService->getClassSchema($className)->getProperties());
212
    }
213
214
    /**
215
     * @param string $className
216
     * @param string $tag
217
     *
218
     * @throws \ReflectionException
219
     * @return array
220
     */
221
    public static function getPropertiesTaggedWith(string $className, string $tag): array
222
    {
223
        $classReflection = new \ReflectionClass($className);
224
        $props = $classReflection->getProperties();
225
        $result = [];
226
        foreach ($props as $prop) {
227
            /** @var $prop \ReflectionProperty */
228
            if (strpos($prop->getDocComment(), '@' . $tag) !== false) {
229
                $result[] = $prop->getName();
230
            }
231
        }
232
        return $result;
233
    }
234
235
    /**
236
     * Get public method names.
237
     *
238
     * @param string $className
239
     *
240
     * @return array
241
     */
242
    public static function getPublicMethodNames(string $className): array
243
    {
244
        $methodNames = [];
245
246
        if (self::is9orHigher()) {
247
            $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
248
            $schema = $reflectionService->getClassSchema($className);
249
            $methods = $schema->getMethods();
250
            foreach ($methods as $key => $method) {
251
                if ($method['public']) {
252
                    $methodNames[] = $key;
253
                }
254
            }
255
256
            return $methodNames;
257
        }
258
259
        $methods = self::createReflectionClass($className)
0 ignored issues
show
Deprecated Code introduced by
The method HDNET\Autoloader\Utility...createReflectionClass() has been deprecated.

This method has been deprecated.

Loading history...
260
            ->getMethods(\ReflectionMethod::IS_PUBLIC);
261
        foreach ($methods as $method) {
262
            $methodNames[] = $method->getName();
263
        }
264
265
        return $methodNames;
266
    }
267
268
    /**
269
     * Get properties of the given class, that are als declared in the given class.
270
     *
271
     * @param string $className
272
     *
273
     * @return array
274
     */
275
    public static function getDeclaringProperties(string $className)
276
    {
277
        $classReflection = new \ReflectionClass($className);
278
        $own = \array_filter($classReflection->getProperties(), function ($property) use ($className) {
279
            return trim((string)$property->class, '\\') === trim($className, '\\');
280
        });
281
282
        return \array_map(function ($item) {
283
            return (string)$item->name;
284
        }, $own);
285
    }
286
287
    /**
288
     * Is 9 or higher.
289
     *
290
     * @return bool
291
     */
292
    public static function is9orHigher(): bool
293
    {
294
        return VersionNumberUtility::convertVersionNumberToInteger(TYPO3_branch) >= VersionNumberUtility::convertVersionNumberToInteger('9.0');
295
    }
296
}
297