Completed
Push — master ( 6f6c2f...93dd0d )
by Tim
02:28
created

ReflectionUtility::is9orHigher()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * Reflection helper.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Autoloader\Utility;
9
10
use HDNET\Autoloader\Hooks\ClearCache;
11
use TYPO3\CMS\Core\Utility\GeneralUtility;
12
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
13
use TYPO3\CMS\Extbase\Reflection\ClassReflection;
14
use TYPO3\CMS\Extbase\Reflection\MethodReflection;
15
use TYPO3\CMS\Extbase\Reflection\ReflectionService;
16
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
17
18
/**
19
 * Reflection helper.
20
 */
21
class ReflectionUtility
22
{
23
    /**
24
     * Create a new class reflection. Do not use the makeInstance or objectManager
25
     * because the reflection API is also used in front of the caching framework.
26
     *
27
     * @param string $className
28
     *
29
     * @return ClassReflection
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
            return (bool)$reflectionClass->isInstantiable();
48
        }
49
50
        return (bool)self::createReflectionClass($className)
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
        return self::createReflectionClass($className)
64
            ->getParentClass()
65
            ->getName();
66
    }
67
68
    /**
69
     * Get all properties that are tagged with the given tag.
70
     *
71
     * @param string $className
72
     * @param string $tag
73
     *
74
     * @return array
75
     */
76
    public static function getPropertiesTaggedWith($className, $tag)
77
    {
78
        $classReflection = self::createReflectionClass($className);
79
        $properties = [];
80
        foreach ($classReflection->getProperties() as $property) {
81
            /** @var \TYPO3\CMS\Extbase\Reflection\PropertyReflection $property */
82
            if ($property->isTaggedWith($tag)) {
83
                $properties[] = $property;
84
            }
85
        }
86
87
        return $properties;
88
    }
89
90
    /**
91
     * Get all properties that are tagged with the given tag.
92
     *
93
     * @param string $className
94
     * @param string $tag
95
     *
96
     * @return array
97
     */
98
    public static function getPropertyNamesTaggedWith($className, $tag):array
99
    {
100
        $classReflection = self::createReflectionClass($className);
101
        $properties = [];
102
        foreach ($classReflection->getProperties() as $property) {
103
            /** @var \TYPO3\CMS\Extbase\Reflection\PropertyReflection $property */
104
            if ($property->isTaggedWith($tag)) {
105
                $properties[] = $property->getName();
106
            }
107
        }
108
109
        return $properties;
110
    }
111
112
    /**
113
     * Get all public methods of the given class.
114
     *
115
     * @param string $className
116
     *
117
     * @return MethodReflection[]
118
     */
119
    public static function getPublicMethods($className)
120
    {
121
        return self::createReflectionClass($className)
122
            ->getMethods(\ReflectionMethod::IS_PUBLIC);
123
    }
124
125
    /**
126
     * Get first class tag information.
127
     * The trimmed value if the tag exists and FALSE if the tag do not exists.
128
     *
129
     * @param string $className
130
     * @param string $tag
131
     *
132
     * @return string|bool
133
     */
134
    public static function getFirstTagValue(string $className, string $tag)
135
    {
136
        $classReflection = self::createReflectionClass($className);
137
        if (!$classReflection->isTaggedWith($tag)) {
138
            return false;
139
        }
140
        $values = $classReflection->getTagValues($tag);
141
        if (\is_array($values)) {
142
            return \trim((string) $values[0]);
143
        }
144
145
        return false;
146
    }
147
148
    /**
149
     * Get the tag configuration from this method and respect multiple line and space configuration.
150
     *
151
     * @param MethodReflection|ClassReflection $reflectionObject
152
     * @param array                            $tagNames
153
     *
154
     * @return array
155
     */
156
    public static function getTagConfiguration($reflectionObject, array $tagNames): array
157
    {
158
        $tags = $reflectionObject->getTagsValues();
159
        $configuration = [];
160
        foreach ($tagNames as $tagName) {
161
            $configuration[$tagName] = [];
162
            if (!\is_array($tags[$tagName])) {
163
                continue;
164
            }
165
            foreach ($tags[$tagName] as $c) {
166
                $configuration[$tagName] = \array_merge(
167
                    $configuration[$tagName],
168
                    GeneralUtility::trimExplode(' ', $c, true)
169
                );
170
            }
171
        }
172
173
        return $configuration;
174
    }
175
176
177
    /**
178
     * Get the tag configuration from this method and respect multiple line and space configuration.
179
     *
180
     * @param MethodReflection|ClassReflection $reflectionObject
0 ignored issues
show
Bug introduced by
There is no parameter named $reflectionObject. 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...
181
     * @param array                            $tagNames
182
     *
183
     * @return array
184
     */
185
    public static function getTagConfigurationForMethod($className, $methodName, array $tagNames): array
186
    {
187
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
188
        $tags = $reflectionService->getMethodTagsValues($className, $methodName);
189
        $configuration = [];
190
        foreach ($tagNames as $tagName) {
191
            $configuration[$tagName] = [];
192
            if (!\is_array($tags[$tagName])) {
193
                continue;
194
            }
195
            foreach ($tags[$tagName] as $c) {
196
                $configuration[$tagName] = \array_merge(
197
                    $configuration[$tagName],
198
                    GeneralUtility::trimExplode(' ', $c, true)
199
                );
200
            }
201
        }
202
203
        return $configuration;
204
    }
205
206
207
    /**
208
     * Get the tag configuration from this method and respect multiple line and space configuration.
209
     *
210
     * @param MethodReflection|ClassReflection $reflectionObject
0 ignored issues
show
Bug introduced by
There is no parameter named $reflectionObject. 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...
211
     * @param array                            $tagNames
212
     *
213
     * @return array
214
     */
215
    public static function getTagConfigurationForClass($className, array $tagNames): array
216
    {
217
        $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
218
        $tags = $reflectionService->getClassTagsValues($className);
219
220
        $configuration = [];
221
        foreach ($tagNames as $tagName) {
222
            $configuration[$tagName] = [];
223
            if (!\is_array($tags[$tagName])) {
224
                continue;
225
            }
226
            foreach ($tags[$tagName] as $c) {
227
                $configuration[$tagName] = \array_merge(
228
                    $configuration[$tagName],
229
                    GeneralUtility::trimExplode(' ', $c, true)
230
                );
231
            }
232
        }
233
234
        return $configuration;
235
    }
236
237
238
239
    /**
240
     * Get public method names
241
     *
242
     * @param string $className
243
     * @return array
244
     */
245
    public static function getPublicMethodNames(string $className): array
246
    {
247
        $methodNames = [];
248
249
        if (self::is9orHigher()) {
250
            $reflectionService = GeneralUtility::makeInstance(ReflectionService::class);
251
            $schema = $reflectionService->getClassSchema($className);
252
            $methods = $schema->getMethods();
253
            foreach ($methods as $key => $method) {
254
                if ($method['public']) {
255
                    $methodNames[] = $key;
256
                }
257
            }
258
        } else {
259
            $methods = self::getPublicMethods($className);
260
            foreach ($methods as $method) {
261
                $methodNames[] = $method->getName();
262
            }
263
        }
264
        return $methodNames;
265
    }
266
267
    /**
268
     * Get properties of the given class, that are als declared in the given class.
269
     *
270
     * @param string $className
271
     *
272
     * @return array
273
     */
274
    public static function getDeclaringProperties($className)
275
    {
276
        $properties = [];
277
        $classReflection = self::createReflectionClass($className);
278
        foreach ($classReflection->getProperties() as $property) {
279
            /** @var \TYPO3\CMS\Extbase\Reflection\PropertyReflection $property */
280
            if ($property->getDeclaringClass()
281
                    ->getName() === $classReflection->getName()
282
            ) {
283
                $properties[] = $property->getName();
284
            }
285
        }
286
287
        return $properties;
288
    }
289
290
    /**
291
     * Is 9 or higher
292
     *
293
     * @return bool
294
     */
295
    public static function is9orHigher(): bool
296
    {
297
        return VersionNumberUtility::convertVersionNumberToInteger(TYPO3_branch) >= VersionNumberUtility::convertVersionNumberToInteger('9.0');
298
    }
299
}
300