Completed
Push — master ( 815996...dfd5cb )
by Tim
02:17
created

ReflectionUtility::isMethodTaggedWith()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 2
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
        if (self::is9orHigher()) {
46
            $reflectionClass = new \ReflectionClass($className);
47
48
            return (bool) $reflectionClass->isInstantiable();
49
        }
50
51
        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...
52
            ->isInstantiable();
53
    }
54
55
    /**
56
     * Get the name of the parent class.
57
     *
58
     * @param string $className
59
     *
60
     * @return string
61
     */
62
    public static function getParentClassName($className)
63
    {
64
        if (self::is9orHigher()) {
65
            $reflectionClass = new \ReflectionClass($className);
66
67
            return $reflectionClass->getParentClass()->getName();
68
        }
69
70
        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...
71
            ->getParentClass()
72
            ->getName();
73
    }
74
75
    /**
76
     * Get first class tag information.
77
     * The trimmed value if the tag exists and FALSE if the tag do not exists.
78
     *
79
     * @param string $className
80
     * @param string $tag
81
     *
82
     * @return string|bool
83
     */
84
    public static function getFirstTagValue(string $className, string $tag)
85
    {
86
        if (self::is9orHigher()) {
87
            $rc = new \ReflectionClass($className);
88
            if (strpos($rc->getDocComment(), '@' . $tag) === false) {
89
                return false;
90
            }
91
92
            $reflectionService = self::getReflectionService();
93
            $values = $reflectionService->getClassTagValues($className, $tag);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Reflec...ce::getClassTagValues() 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...
94
        } else {
95
            $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...
96
            if (!$classReflection->isTaggedWith($tag)) {
97
                return false;
98
            }
99
            $values = $classReflection->getTagValues($tag);
100
        }
101
102
        if (\is_array($values)) {
103
            return \trim((string) $values[0]);
104
        }
105
106
        return false;
107
    }
108
109
    /**
110
     * Get the tag configuration from this method and respect multiple line and space configuration.
111
     *
112
     * @param string $className
113
     * @param        $methodName
114
     * @param array $tagNames
115
     *
116
     * @return array
117
     */
118
    public static function getTagConfigurationForMethod($className, $methodName, array $tagNames): array
119
    {
120
        $reflectionService = self::getReflectionService();
121
        $tags = $reflectionService->getMethodTagsValues($className, $methodName);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Reflec...::getMethodTagsValues() 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...
122
123
        $configuration = [];
124
        foreach ($tagNames as $tagName) {
125
            $configuration[$tagName] = [];
126
            if (!\is_array($tags[$tagName])) {
127
                continue;
128
            }
129
            foreach ($tags[$tagName] as $c) {
130
                $configuration[$tagName] = \array_merge(
131
                    $configuration[$tagName],
132
                    GeneralUtility::trimExplode(' ', $c, true)
133
                );
134
            }
135
        }
136
137
        return $configuration;
138
    }
139
140
    /**
141
     * Get the tag configuration from this method and respect multiple line and space configuration.
142
     *
143
     * @param string $className
144
     * @param array $tagNames
145
     *
146
     * @return array
147
     */
148
    public static function getTagConfigurationForClass(string $className, array $tagNames): array
149
    {
150
        $reflectionService = self::getReflectionService();
151
        $tags = $reflectionService->getClassTagsValues($className);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Reflec...e::getClassTagsValues() 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...
152
153
        $configuration = [];
154
        foreach ($tagNames as $tagName) {
155
            $configuration[$tagName] = [];
156
            if (!\is_array($tags[$tagName])) {
157
                continue;
158
            }
159
            foreach ($tags[$tagName] as $c) {
160
                $configuration[$tagName] = \array_merge(
161
                    $configuration[$tagName],
162
                    GeneralUtility::trimExplode(' ', $c, true)
163
                );
164
            }
165
        }
166
167
        return $configuration;
168
    }
169
170
    /**
171
     * Get the tag configuration from this method and respect multiple line and space configuration.
172
     *
173
     * @param string $className
174
     * @param string $property
175
     * @param array $tagNames
176
     *
177
     * @return array
178
     */
179
    public static function getTagConfigurationForProperty(string $className, string $property, array $tagNames): array
180
    {
181
        $reflectionService = self::getReflectionService();
182
        if (self::is9orHigher()) {
183
            $tags = $reflectionService->getClassSchema($className)->getProperty($property)['tags'];
184
        } else {
185
            $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...
186
        }
187
188
        $configuration = [];
189
        foreach ($tagNames as $tagName) {
190
            if (!\is_array($tags[$tagName])) {
191
                continue;
192
            }
193
            $configuration[$tagName] = '';
194
            foreach ($tags[$tagName] as $c) {
195
                $configuration[$tagName] = trim($configuration[$tagName] . ' ' . $c);
196
            }
197
        }
198
199
        return $configuration;
200
    }
201
202
    /**
203
     * Get public method names.
204
     *
205
     * @param string $className
206
     *
207
     * @return array
208
     */
209
    public static function getPropertyNames(string $className): array
210
    {
211
        $reflectionService = self::getReflectionService();
212
213
        return \array_keys($reflectionService->getClassSchema($className)->getProperties());
214
    }
215
216
    /**
217
     * @param string $className
218
     * @param string $tag
219
     *
220
     * @throws \ReflectionException
221
     * @return array
222
     */
223
    public static function getPropertiesTaggedWith(string $className, string $tag): array
224
    {
225
        $classReflection = new \ReflectionClass($className);
226
        $props = $classReflection->getProperties();
227
        $result = [];
228
        foreach ($props as $prop) {
229
            /** @var $prop \ReflectionProperty */
230
            if (strpos($prop->getDocComment(), '@' . $tag) !== false) {
231
                $result[] = $prop->getName();
232
            }
233
        }
234
        return $result;
235
    }
236
237
    /**
238
     * Get public method names.
239
     *
240
     * @param string $className
241
     *
242
     * @return array
243
     */
244
    public static function getPublicMethodNames(string $className): array
245
    {
246
        $methodNames = [];
247
248
        if (self::is9orHigher()) {
249
            $reflectionService = self::getReflectionService();
250
            $schema = $reflectionService->getClassSchema($className);
251
            $methods = $schema->getMethods();
252
            foreach ($methods as $key => $method) {
253
                if ($method['public']) {
254
                    $methodNames[] = $key;
255
                }
256
            }
257
258
            return $methodNames;
259
        }
260
261
        $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...
262
            ->getMethods(\ReflectionMethod::IS_PUBLIC);
263
        foreach ($methods as $method) {
264
            $methodNames[] = $method->getName();
265
        }
266
267
        return $methodNames;
268
    }
269
270
    /**
271
     * Get properties of the given class, that are als declared in the given class.
272
     *
273
     * @param string $className
274
     *
275
     * @return array
276
     */
277
    public static function getDeclaringProperties(string $className)
278
    {
279
        $classReflection = new \ReflectionClass($className);
280
        $own = \array_filter($classReflection->getProperties(), function ($property) use ($className) {
281
            return trim((string) $property->class, '\\') === trim($className, '\\');
282
        });
283
284
        return \array_map(function ($item) {
285
            return (string) $item->name;
286
        }, $own);
287
    }
288
289
    /**
290
     * Is 9 or higher.
291
     *
292
     * @return bool
293
     */
294
    public static function is9orHigher(): bool
295
    {
296
        return VersionNumberUtility::convertVersionNumberToInteger(TYPO3_branch) >= VersionNumberUtility::convertVersionNumberToInteger('9.0');
297
    }
298
299
    /**
300
     * Create reflection service
301
     *
302
     * @return ReflectionService
303
     */
304
    protected static function getReflectionService()
305
    {
306
        $objectManager = new ObjectManager();
307
        return $objectManager->get(ReflectionService::class);
308
    }
309
310
    /**
311
     * Check if the method is tagged with the given tag (no value checked)
312
     *
313
     * @param string $controllerName
0 ignored issues
show
Bug introduced by
There is no parameter named $controllerName. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
314
     * @param string $methodName
315
     * @param string $tagName
316
     * @return bool
317
     */
318
    public static function isMethodTaggedWith($className, $methodName, $tagName): bool
319
    {
320
        $reflectionService = self::getReflectionService();
321
        $tags = $reflectionService->getMethodTagsValues($className, $methodName);
0 ignored issues
show
Deprecated Code introduced by
The method TYPO3\CMS\Extbase\Reflec...::getMethodTagsValues() 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...
322
        return array_key_exists($tagName, $tags);
323
    }
324
}
325