Completed
Push — master ( d82c34...7d95c1 )
by Tim
20:17 queued 05:19
created

ReflectionUtility::isClassInOtherClassHierarchy()   B

Complexity

Conditions 6
Paths 11

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 0
cts 6
cp 0
rs 8.9297
c 0
b 0
f 0
cc 6
nc 11
nop 2
crap 42
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\Extbase\Object\ObjectManager;
12
use TYPO3\CMS\Extbase\Reflection\ReflectionService;
13
14
/**
15
 * Reflection helper.
16
 */
17
class ReflectionUtility
18
{
19
    /**
20
     * Check if the given class is instantiable.
21
     *
22
     * @param string $className
23
     */
24
    public static function isInstantiable($className): bool
25
    {
26
        $reflectionClass = new \ReflectionClass($className);
27
28
        return (bool) $reflectionClass->isInstantiable();
29
    }
30
31
    /**
32
     * Get the name of the parent class.
33
     *
34
     * @param string $className
35
     *
36
     * @return string
37
     */
38
    public static function getParentClassName($className)
39
    {
40
        $reflectionClass = new \ReflectionClass($className);
41
42
        return $reflectionClass->getParentClass()->getName();
43
    }
44
45
    /**
46
     * Check if the first class is found in the Hierarchy of the second.
47
     */
48
    public static function isClassInOtherClassHierarchy(string $searchClass, string $checkedClass): bool
49
    {
50
        $searchClass = \trim($searchClass, '\\');
51
        if (!\class_exists($searchClass)) {
52
            return false;
53
        }
54
        $checked = \trim($checkedClass, '\\');
55
        try {
56
            if ($searchClass === $checked) {
57
                return true;
58
            }
59
            $reflection = new \ReflectionClass($searchClass);
60
            while ($reflection = $reflection->getParentClass()) {
61
                if ($checked === \trim($reflection->getName(), '\\')) {
62
                    return true;
63
                }
64
            }
65
66
            return false;
67
        } catch (\Exception $exception) {
68
            return false;
69
        }
70
    }
71
72
    /**
73
     * Get first class tag information.
74
     * The trimmed value if the tag exists and FALSE if the tag do not exists.
75
     *
76
     * @return string|bool
77
     */
78
    public static function getFirstTagValue(string $className, string $tag)
79
    {
80
        $reflectionService = GeneralUtility::makeInstance(\HDNET\Autoloader\Service\ReflectionService::class);
81
        $values = $reflectionService->getClassTagValues($className, $tag);
82
        if (false === $values) {
83
            return false;
84
        }
85
86
        if (\is_array($values)) {
87
            return \trim((string) $values[0]);
88
        }
89
90
        return false;
91
    }
92
93
    /**
94
     * Get the tag configuration from this method and respect multiple line and space configuration.
95
     *
96
     * @param string $className
97
     * @param        $methodName
98
     */
99
    public static function getTagConfigurationForMethod($className, $methodName, array $tagNames): array
100
    {
101
        $reflectionService = GeneralUtility::makeInstance(\HDNET\Autoloader\Service\ReflectionService::class);
102
        $tags = $reflectionService->getMethodTagValues($className, $methodName);
103
104
        $configuration = [];
105
        foreach ($tagNames as $tagName) {
106
            $configuration[$tagName] = [];
107
            if (!\is_array($tags[$tagName])) {
108
                continue;
109
            }
110
            foreach ($tags[$tagName] as $c) {
111
                $configuration[$tagName] = \array_merge(
112
                    $configuration[$tagName],
113
                    GeneralUtility::trimExplode(' ', $c, true)
114
                );
115
            }
116
        }
117
118
        return $configuration;
119
    }
120
121
    /**
122
     * Get the tag configuration from this method and respect multiple line and space configuration.
123
     */
124
    public static function getTagConfigurationForClass(string $className, array $tagNames): array
125
    {
126
        $reflectionService = self::getReflectionService();
127
        $tags = $reflectionService->getClassTagsValues($className);
128
129
        $configuration = [];
130
        foreach ($tagNames as $tagName) {
131
            $configuration[$tagName] = [];
132
            if (!\is_array($tags[$tagName])) {
133
                continue;
134
            }
135
            foreach ($tags[$tagName] as $c) {
136
                $configuration[$tagName] = \array_merge(
137
                    $configuration[$tagName],
138
                    GeneralUtility::trimExplode(' ', $c, true)
139
                );
140
            }
141
        }
142
143
        return $configuration;
144
    }
145
146
    /**
147
     * Get the tag configuration from this method and respect multiple line and space configuration.
148
     */
149
    public static function getTagConfigurationForProperty(string $className, string $property, array $tagNames): array
150
    {
151
        $reflectionService = self::getReflectionService();
152
153
        $tags = $reflectionService->getClassSchema($className)->getProperty($property)['tags'];
154
155
        $configuration = [];
156
        foreach ($tagNames as $tagName) {
157
            if (!\is_array($tags[$tagName])) {
158
                continue;
159
            }
160
            $configuration[$tagName] = '';
161
            foreach ($tags[$tagName] as $c) {
162
                $configuration[$tagName] = \trim($configuration[$tagName] . ' ' . $c);
163
            }
164
        }
165
166
        return $configuration;
167
    }
168
169
    /**
170
     * Get public method names.
171
     */
172
    public static function getPropertyNames(string $className): array
173
    {
174
        $reflectionService = self::getReflectionService();
175
176
        return \array_keys($reflectionService->getClassSchema($className)->getProperties());
177
    }
178
179
    /**
180
     * @throws \ReflectionException
181
     */
182
    public static function getPropertiesTaggedWith(string $className, string $tag): array
183
    {
184
        $classReflection = new \ReflectionClass($className);
185
        $props = $classReflection->getProperties();
186
        $result = [];
187
        foreach ($props as $prop) {
188
            /** @var $prop \ReflectionProperty */
189
            if (false !== \mb_strpos($prop->getDocComment(), '@' . $tag)) {
190
                $result[] = $prop->getName();
191
            }
192
        }
193
194
        return $result;
195
    }
196
197
    /**
198
     * Get public method names.
199
     */
200
    public static function getPublicMethodNames(string $className): array
201
    {
202
        $methodNames = [];
203
204
        $reflectionService = self::getReflectionService();
205
        $schema = $reflectionService->getClassSchema($className);
206
        $methods = $schema->getMethods();
207
        foreach ($methods as $key => $method) {
208
            if ($method['public']) {
209
                $methodNames[] = $key;
210
            }
211
        }
212
213
        return $methodNames;
214
    }
215
216
    /**
217
     * Get properties of the given class, that are als declared in the given class.
218
     *
219
     * @return array
220
     */
221
    public static function getDeclaringProperties(string $className)
222
    {
223
        $classReflection = new \ReflectionClass($className);
224
        $own = \array_filter($classReflection->getProperties(), function ($property) use ($className) {
225
            return \trim((string) $property->class, '\\') === \trim($className, '\\');
226
        });
227
228
        return \array_map(function ($item) {
229
            return (string) $item->name;
230
        }, $own);
231
    }
232
233
    /**
234
     * Check if the method is tagged with the given tag (no value checked).
235
     *
236
     * @param string $className
237
     * @param string $methodName
238
     * @param string $tagName
239
     */
240
    public static function isMethodTaggedWith($className, $methodName, $tagName): bool
241
    {
242
        $reflectionService = GeneralUtility::makeInstance(\HDNET\Autoloader\Service\ReflectionService::class);
243
        $tags = $reflectionService->getMethodTagValues($className, $methodName);
244
245
        return \array_key_exists($tagName, $tags);
246
    }
247
248
    /**
249
     * Check if the property is tagged with the given tag (no value checked).
250
     *
251
     * @param string $className
252
     * @param string $propertyName
253
     * @param string $tagName
254
     */
255
    public static function isPropertyTaggedWith($className, $propertyName, $tagName): bool
256
    {
257
        $properties = self::getPropertiesTaggedWith($className, $tagName);
258
259
        return \in_array($propertyName, $properties, true);
260
    }
261
262
    /**
263
     * Create reflection service.
264
     *
265
     * @return ReflectionService
266
     */
267
    protected static function getReflectionService()
268
    {
269
        $objectManager = new ObjectManager();
270
271
        return $objectManager->get(ReflectionService::class);
272
    }
273
}
274