Completed
Push — master ( d3c055...25d723 )
by Tim
13:13
created

Classes/Utility/ReflectionUtility.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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\Object\ObjectManager;
13
use TYPO3\CMS\Extbase\Reflection\ClassReflection;
14
use TYPO3\CMS\Extbase\Reflection\ReflectionService;
15
16
/**
17
 * Reflection helper.
18
 */
19
class ReflectionUtility
20
{
21
    /**
22
     * Create a new class reflection. Do not use the makeInstance or objectManager
23
     * because the reflection API is also used in front of the caching framework.
24
     *
25
     * @param string $className
26
     *
27
     * @return ClassReflection
28
     *
29
     * @deprecated
30
     */
31
    public static function createReflectionClass($className)
32
    {
33
        return new ClassReflection($className);
34
    }
35
36
    /**
37
     * Check if the given class is instantiable.
38
     *
39
     * @param string $className
40
     *
41
     * @return bool
42
     */
43
    public static function isInstantiable($className): bool
44
    {
45
        $reflectionClass = new \ReflectionClass($className);
46
47
        return (bool) $reflectionClass->isInstantiable();
48
    }
49
50
    /**
51
     * Get the name of the parent class.
52
     *
53
     * @param string $className
54
     *
55
     * @return string
56
     */
57
    public static function getParentClassName($className)
58
    {
59
        if (self::is9orHigher()) {
60
            $reflectionClass = new \ReflectionClass($className);
61
62
            return $reflectionClass->getParentClass()->getName();
63
        }
64
65
        return self::createReflectionClass($className)
66
            ->getParentClass()
67
            ->getName();
68
    }
69
70
    /**
71
     * Get first class tag information.
72
     * The trimmed value if the tag exists and FALSE if the tag do not exists.
73
     *
74
     * @param string $className
75
     * @param string $tag
76
     *
77
     * @return string|bool
78
     */
79
    public static function getFirstTagValue(string $className, string $tag)
80
    {
81
        if (self::is9orHigher()) {
82
            $reflectionService = GeneralUtility::makeInstance(\HDNET\Autoloader\Service\ReflectionService::class);
83
            $values = $reflectionService->getClassTagValues($className, $tag);
84
            if (false === $values) {
85
                return false;
86
            }
87
        } else {
88
            $classReflection = self::createReflectionClass($className);
89
            if (!$classReflection->isTaggedWith($tag)) {
90
                return false;
91
            }
92
            $values = $classReflection->getTagValues($tag);
93
        }
94
95
        if (\is_array($values)) {
96
            return \trim((string) $values[0]);
97
        }
98
99
        return false;
100
    }
101
102
    /**
103
     * Get the tag configuration from this method and respect multiple line and space configuration.
104
     *
105
     * @param string $className
106
     * @param        $methodName
107
     * @param array  $tagNames
108
     *
109
     * @return array
110
     */
111
    public static function getTagConfigurationForMethod($className, $methodName, array $tagNames): array
112
    {
113
        $reflectionService = GeneralUtility::makeInstance(\HDNET\Autoloader\Service\ReflectionService::class);
114
        $tags = $reflectionService->getMethodTagValues($className, $methodName);
115
116
        $configuration = [];
117
        foreach ($tagNames as $tagName) {
118
            $configuration[$tagName] = [];
119
            if (!\is_array($tags[$tagName])) {
120
                continue;
121
            }
122
            foreach ($tags[$tagName] as $c) {
123
                $configuration[$tagName] = \array_merge(
124
                    $configuration[$tagName],
125
                    GeneralUtility::trimExplode(' ', $c, true)
126
                );
127
            }
128
        }
129
130
        return $configuration;
131
    }
132
133
    /**
134
     * Get the tag configuration from this method and respect multiple line and space configuration.
135
     *
136
     * @param string $className
137
     * @param array  $tagNames
138
     *
139
     * @return array
140
     */
141
    public static function getTagConfigurationForClass(string $className, array $tagNames): array
142
    {
143
        $reflectionService = self::getReflectionService();
144
        $tags = $reflectionService->getClassTagsValues($className);
145
146
        $configuration = [];
147
        foreach ($tagNames as $tagName) {
148
            $configuration[$tagName] = [];
149
            if (!\is_array($tags[$tagName])) {
150
                continue;
151
            }
152
            foreach ($tags[$tagName] as $c) {
153
                $configuration[$tagName] = \array_merge(
154
                    $configuration[$tagName],
155
                    GeneralUtility::trimExplode(' ', $c, true)
156
                );
157
            }
158
        }
159
160
        return $configuration;
161
    }
162
163
    /**
164
     * Get the tag configuration from this method and respect multiple line and space configuration.
165
     *
166
     * @param string $className
167
     * @param string $property
168
     * @param array  $tagNames
169
     *
170
     * @return array
171
     */
172
    public static function getTagConfigurationForProperty(string $className, string $property, array $tagNames): array
173
    {
174
        $reflectionService = self::getReflectionService();
175
        if (self::is9orHigher()) {
176
            $tags = $reflectionService->getClassSchema($className)->getProperty($property)['tags'];
177
        } else {
178
            $tags = $reflectionService->getPropertyTagsValues($className, $property);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Reflec...getPropertyTagsValues() has been deprecated with message: since TYPO3 v9, will be removed in TYPO3 v10.0.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
179
        }
180
181
        $configuration = [];
182
        foreach ($tagNames as $tagName) {
183
            if (!\is_array($tags[$tagName])) {
184
                continue;
185
            }
186
            $configuration[$tagName] = '';
187
            foreach ($tags[$tagName] as $c) {
188
                $configuration[$tagName] = \trim($configuration[$tagName] . ' ' . $c);
189
            }
190
        }
191
192
        return $configuration;
193
    }
194
195
    /**
196
     * Get public method names.
197
     *
198
     * @param string $className
199
     *
200
     * @return array
201
     */
202
    public static function getPropertyNames(string $className): array
203
    {
204
        $reflectionService = self::getReflectionService();
205
206
        return \array_keys($reflectionService->getClassSchema($className)->getProperties());
207
    }
208
209
    /**
210
     * @param string $className
211
     * @param string $tag
212
     *
213
     * @throws \ReflectionException
214
     *
215
     * @return array
216
     */
217
    public static function getPropertiesTaggedWith(string $className, string $tag): array
218
    {
219
        $classReflection = new \ReflectionClass($className);
220
        $props = $classReflection->getProperties();
221
        $result = [];
222
        foreach ($props as $prop) {
223
            /** @var $prop \ReflectionProperty */
224
            if (false !== \mb_strpos($prop->getDocComment(), '@' . $tag)) {
225
                $result[] = $prop->getName();
226
            }
227
        }
228
229
        return $result;
230
    }
231
232
    /**
233
     * Get public method names.
234
     *
235
     * @param string $className
236
     *
237
     * @return array
238
     */
239
    public static function getPublicMethodNames(string $className): array
240
    {
241
        $methodNames = [];
242
243
        if (self::is9orHigher()) {
244
            $reflectionService = self::getReflectionService();
245
            $schema = $reflectionService->getClassSchema($className);
246
            $methods = $schema->getMethods();
247
            foreach ($methods as $key => $method) {
248
                if ($method['public']) {
249
                    $methodNames[] = $key;
250
                }
251
            }
252
253
            return $methodNames;
254
        }
255
256
        $methods = self::createReflectionClass($className)
257
            ->getMethods(\ReflectionMethod::IS_PUBLIC);
258
        foreach ($methods as $method) {
259
            $methodNames[] = $method->getName();
260
        }
261
262
        return $methodNames;
263
    }
264
265
    /**
266
     * Get properties of the given class, that are als declared in the given class.
267
     *
268
     * @param string $className
269
     *
270
     * @return array
271
     */
272
    public static function getDeclaringProperties(string $className)
273
    {
274
        $classReflection = new \ReflectionClass($className);
275
        $own = \array_filter($classReflection->getProperties(), function ($property) use ($className) {
276
            return \trim((string) $property->class, '\\') === \trim($className, '\\');
277
        });
278
279
        return \array_map(function ($item) {
280
            return (string) $item->name;
281
        }, $own);
282
    }
283
284
    /**
285
     * Is 9 or higher.
286
     *
287
     * @return bool
288
     */
289
    public static function is9orHigher(): bool
290
    {
291
        return VersionNumberUtility::convertVersionNumberToInteger(TYPO3_branch) >= VersionNumberUtility::convertVersionNumberToInteger('9.0');
292
    }
293
294
    /**
295
     * Check if the method is tagged with the given tag (no value checked).
296
     *
297
     * @param string $className
298
     * @param string $methodName
299
     * @param string $tagName
300
     *
301
     * @return bool
302
     */
303
    public static function isMethodTaggedWith($className, $methodName, $tagName): bool
304
    {
305
        $reflectionService = GeneralUtility::makeInstance(\HDNET\Autoloader\Service\ReflectionService::class);
306
        $tags = $reflectionService->getMethodTagValues($className, $methodName);
307
308
        return \array_key_exists($tagName, $tags);
309
    }
310
311
    /**
312
     * Check if the property is tagged with the given tag (no value checked).
313
     *
314
     * @param string $className
315
     * @param string $propertyName
316
     * @param string $tagName
317
     *
318
     * @return bool
319
     */
320
    public static function isPropertyTaggedWith($className, $propertyName, $tagName): bool
321
    {
322
        $properties = self::getPropertiesTaggedWith($className, $tagName);
323
324
        return \in_array($propertyName, $properties, true);
325
    }
326
327
    /**
328
     * Create reflection service.
329
     *
330
     * @return ReflectionService
331
     */
332
    protected static function getReflectionService()
333
    {
334
        $objectManager = new ObjectManager();
335
336
        return $objectManager->get(ReflectionService::class);
337
    }
338
}
339