Completed
Push — master ( 44297e...90be80 )
by Tim
06:31 queued 03:38
created

ReflectionUtility::getPropertiesTaggedWith()   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 0
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 all properties that are tagged with the given tag.
76
     *
77
     * @param string $className
78
     * @param string $tag
79
     *
80
     * @return array
81
     */
82
    public static function getPropertyNamesTaggedWith($className, $tag): array
83
    {
84
        $properties = self::getPropertyNames($className);
85
        $return = [];
86
        foreach ($properties as $property) {
87
            $config = self::getTagConfigurationForProperty($className, $property, [$tag]);
88
            if (!empty($config[$tag])) {
89
                $return[] = $property;
90
            }
91
        }
92
93
        return $return;
94
    }
95
96
    /**
97
     * Get first class tag information.
98
     * The trimmed value if the tag exists and FALSE if the tag do not exists.
99
     *
100
     * @param string $className
101
     * @param string $tag
102
     *
103
     * @return string|bool
104
     */
105
    public static function getFirstTagValue(string $className, string $tag)
106
    {
107
        if (self::is9orHigher()) {
108
            $rc = new \ReflectionClass($className);
109
            if (strpos($rc->getDocComment(), '@' . $tag) === false) {
110
                return false;
111
            }
112
113
            $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
114
            $values = $reflectionService->getClassTagValues($className, $tag);
115
        } else {
116
            $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...
117
            if (!$classReflection->isTaggedWith($tag)) {
118
                return false;
119
            }
120
            $values = $classReflection->getTagValues($tag);
121
        }
122
123
        if (\is_array($values)) {
124
            return \trim((string) $values[0]);
125
        }
126
127
        return false;
128
    }
129
130
    /**
131
     * Get the tag configuration from this method and respect multiple line and space configuration.
132
     *
133
     * @param string $className
134
     * @param        $methodName
135
     * @param array  $tagNames
136
     *
137
     * @return array
138
     */
139
    public static function getTagConfigurationForMethod($className, $methodName, array $tagNames): array
140
    {
141
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
142
        $tags = $reflectionService->getMethodTagsValues($className, $methodName);
143
144
        $configuration = [];
145
        foreach ($tagNames as $tagName) {
146
            $configuration[$tagName] = [];
147
            if (!\is_array($tags[$tagName])) {
148
                continue;
149
            }
150
            foreach ($tags[$tagName] as $c) {
151
                $configuration[$tagName] = \array_merge(
152
                    $configuration[$tagName],
153
                    GeneralUtility::trimExplode(' ', $c, true)
154
                );
155
            }
156
        }
157
158
        return $configuration;
159
    }
160
161
    /**
162
     * Get the tag configuration from this method and respect multiple line and space configuration.
163
     *
164
     * @param string $className
165
     * @param array  $tagNames
166
     *
167
     * @return array
168
     */
169
    public static function getTagConfigurationForClass(string $className, array $tagNames): array
170
    {
171
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
172
        $tags = $reflectionService->getClassTagsValues($className);
173
174
        $configuration = [];
175
        foreach ($tagNames as $tagName) {
176
            $configuration[$tagName] = [];
177
            if (!\is_array($tags[$tagName])) {
178
                continue;
179
            }
180
            foreach ($tags[$tagName] as $c) {
181
                $configuration[$tagName] = \array_merge(
182
                    $configuration[$tagName],
183
                    GeneralUtility::trimExplode(' ', $c, true)
184
                );
185
            }
186
        }
187
188
        return $configuration;
189
    }
190
191
    /**
192
     * Get the tag configuration from this method and respect multiple line and space configuration.
193
     *
194
     * @param string $className
195
     * @param string $property
196
     * @param array  $tagNames
197
     *
198
     * @return array
199
     */
200
    public static function getTagConfigurationForProperty(string $className, string $property, array $tagNames): array
201
    {
202
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
203
        $tags = $reflectionService->getClassSchema($className)->getProperty($property)['tags'];
204
205
        $configuration = [];
206
        foreach ($tagNames as $tagName) {
207
            $configuration[$tagName] = [];
208
            if (!\is_array($tags[$tagName])) {
209
                continue;
210
            }
211
            foreach ($tags[$tagName] as $c) {
212
                $configuration[$tagName] = \array_merge(
213
                    $configuration[$tagName],
214
                    GeneralUtility::trimExplode(' ', $c, true)
215
                );
216
            }
217
        }
218
219
        return $configuration;
220
    }
221
222
    /**
223
     * Get public method names.
224
     *
225
     * @param string $className
226
     *
227
     * @return array
228
     */
229
    public static function getPropertyNames(string $className): array
230
    {
231
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
232
233
        return \array_keys($reflectionService->getClassSchema($className)->getProperties());
234
    }
235
236
    /**
237
     * @param string $className
238
     * @param string $tag
239
     *
240
     * @throws \ReflectionException
241
     * @return array
242
     */
243
    public static function getPropertiesTaggedWith(string $className, string $tag): array
244
    {
245
        $classReflection = new \ReflectionClass($className);
246
        $props = $classReflection->getProperties();
247
        $result = [];
248
        foreach ($props as $prop) {
249
            /** @var $prop \ReflectionProperty */
250
            if (strpos($prop->getDocComment(), '@' . $tag) !== false) {
251
                $result[] = $prop->getName();
252
            }
253
        }
254
        return $result;
255
    }
256
257
    /**
258
     * Get public method names.
259
     *
260
     * @param string $className
261
     *
262
     * @return array
263
     */
264
    public static function getPublicMethodNames(string $className): array
265
    {
266
        $methodNames = [];
267
268
        if (self::is9orHigher()) {
269
            $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
270
            $schema = $reflectionService->getClassSchema($className);
271
            $methods = $schema->getMethods();
272
            foreach ($methods as $key => $method) {
273
                if ($method['public']) {
274
                    $methodNames[] = $key;
275
                }
276
            }
277
278
            return $methodNames;
279
        }
280
281
        $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...
282
            ->getMethods(\ReflectionMethod::IS_PUBLIC);
283
        foreach ($methods as $method) {
284
            $methodNames[] = $method->getName();
285
        }
286
287
        return $methodNames;
288
    }
289
290
    /**
291
     * Get properties of the given class, that are als declared in the given class.
292
     *
293
     * @param string $className
294
     *
295
     * @return array
296
     */
297
    public static function getDeclaringProperties($className)
298
    {
299
        $classReflection = new \ReflectionClass($className);
300
        $own = \array_filter($classReflection->getProperties(), function ($property) use ($className) {
301
            return $property->class === $className;
302
        });
303
304
        return \array_map(function ($item) {
305
            return $item->name;
306
        }, $own);
307
    }
308
309
    /**
310
     * Is 9 or higher.
311
     *
312
     * @return bool
313
     */
314
    public static function is9orHigher(): bool
315
    {
316
        return VersionNumberUtility::convertVersionNumberToInteger(TYPO3_branch) >= VersionNumberUtility::convertVersionNumberToInteger('9.0');
317
    }
318
}
319