Completed
Push — master ( 05a043...a79f71 )
by Tim
15:11
created

ReflectionUtility::getClassTagValues()   A

Complexity

Conditions 3
Paths 7

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
ccs 0
cts 0
cp 0
cc 3
nc 7
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\Extbase\Reflection\ClassSchema;
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
56
        try {
57
            if ($searchClass === $checked) {
58
                return true;
59
            }
60
            $reflection = new \ReflectionClass($searchClass);
61
            while ($reflection = $reflection->getParentClass()) {
62
                if ($checked === trim($reflection->getName(), '\\')) {
63
                    return true;
64
                }
65
            }
66
67
            return false;
68
        } catch (\Exception $exception) {
69
            return false;
70
        }
71
    }
72
73
    /**
74
     * Get first class tag information.
75
     * The trimmed value if the tag exists and FALSE if the tag do not exists.
76
     *
77
     * @return string|bool
78
     */
79
    public static function getFirstTagValue(string $className, string $tag)
80
    {
81
        $values = self::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
        $tags = self::getMethodTagValues($className, $methodName);
102
103
        $configuration = [];
104
        foreach ($tagNames as $tagName) {
105
            $configuration[$tagName] = [];
106
            if (!\is_array($tags[$tagName])) {
107
                continue;
108
            }
109
            foreach ($tags[$tagName] as $c) {
110
                $configuration[$tagName] = array_merge(
111
                    $configuration[$tagName],
112
                    GeneralUtility::trimExplode(' ', $c, true)
113
                );
114
            }
115
        }
116
117
        return $configuration;
118
    }
119
120
    /**
121
     * Get the tag configuration from this method and respect multiple line and space configuration.
122
     */
123
    public static function getTagConfigurationForClass(string $className, array $tagNames): array
0 ignored issues
show
Unused Code introduced by
The parameter $className is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
124
    {
125
//        $classSchema = new ClassSchema($className);
126
127
        /** @todo */
128
129
        //       $reflectionService = $objectManager->get(ReflectionService::class);
130
        $tags = []; // $reflectionService->getClassTagsValues($className);
131
132
        $configuration = [];
133
        foreach ($tagNames as $tagName) {
134
            $configuration[$tagName] = [];
135
            if (!\is_array($tags[$tagName])) {
136
                continue;
137
            }
138
            foreach ($tags[$tagName] as $c) {
139
                $configuration[$tagName] = array_merge(
140
                    $configuration[$tagName],
141
                    GeneralUtility::trimExplode(' ', $c, true)
142
                );
143
            }
144
        }
145
146
        return $configuration;
147
    }
148
149
    /**
150
     * Get the tag configuration from this method and respect multiple line and space configuration.
151
     */
152
    public static function getTagConfigurationForProperty(string $className, string $property, array $tagNames): array
153
    {
154
        $coreReflectionService = GeneralUtility::makeInstance(ReflectionService::class);
155
        $classSchema = $coreReflectionService->getClassSchema($className);
156
157
        $tags = $classSchema->getProperty($property)['tags'];
158
159
        $configuration = [];
160
        foreach ($tagNames as $tagName) {
161
            if (!\is_array($tags[$tagName])) {
162
                continue;
163
            }
164
            $configuration[$tagName] = '';
165
            foreach ($tags[$tagName] as $c) {
166
                $configuration[$tagName] = trim($configuration[$tagName] . ' ' . $c);
167
            }
168
        }
169
170
        return $configuration;
171
    }
172
173
    /**
174
     * Get the tag value
175
     * - Array (if the tag exist)
176
     * - false (if the tag do not exists).
177
     *
178
     * @return array|bool
179
     */
180
    public static function getClassTagValues(string $className, string $tag)
181
    {
182
        try {
183
            $coreReflectionService = GeneralUtility::makeInstance(ReflectionService::class);
184
            $classSchema = $coreReflectionService->getClassSchema($className);
185
            $tags = $classSchema->getTags();
186
187
            if (!\array_key_exists($tag, $tags)) {
188
                return false;
189
            }
190
191
            return $tags[$tag] ?? [];
192
        } catch (\Exception $e) {
193
            return false;
194
        }
195
    }
196
197
    /**
198
     * Get method tag values
199
     * - Array
200
     * - False (if there are any problems).
201
     *
202
     * @return array|bool
203
     */
204
    public static function getMethodTagValues(string $className, string $methodName)
205
    {
206
        try {
207
            $coreReflectionService = GeneralUtility::makeInstance(ReflectionService::class);
208
            $classSchema = $coreReflectionService->getClassSchema($className);
209
210
            return $classSchema->getMethod($methodName)['tags'] ?? [];
211
        } catch (\Exception $e) {
212
            return false;
213
        }
214
    }
215
216
    /**
217
     * Get public method names.
218
     */
219
    public static function getPropertyNames(string $className): array
220
    {
221
        $coreReflectionService = GeneralUtility::makeInstance(ReflectionService::class);
222
        $classSchema = $coreReflectionService->getClassSchema($className);
223
224
        return array_keys($classSchema->getProperties());
225
    }
226
227
    /**
228
     * @throws \ReflectionException
229
     */
230
    public static function getPropertiesTaggedWith(string $className, string $tag): array
231
    {
232
        $classReflection = new \ReflectionClass($className);
233
        $props = $classReflection->getProperties();
234
        $result = [];
235
        foreach ($props as $prop) {
236
            /** @var \ReflectionProperty $prop */
237
            if (false !== mb_strpos((string)$prop->getDocComment(), '@' . $tag)) {
238
                $result[] = $prop->getName();
239
            }
240
        }
241
242
        return $result;
243
    }
244
245
    /**
246
     * Get properties of the given class, that are als declared in the given class.
247
     *
248
     * @return array
249
     */
250
    public static function getDeclaringProperties(string $className)
251
    {
252
        $classReflection = new \ReflectionClass($className);
253
        $own = array_filter($classReflection->getProperties(), function ($property) use ($className) {
254
            return trim((string)$property->class, '\\') === trim($className, '\\');
255
        });
256
257
        return array_map(function ($item) {
258
            return (string)$item->name;
259
        }, $own);
260
    }
261
262
    /**
263
     * Check if the method is tagged with the given tag (no value checked).
264
     *
265
     * @param string $className
266
     * @param string $methodName
267
     * @param string $tagName
268
     */
269
    public static function isMethodTaggedWith($className, $methodName, $tagName): bool
270
    {
271
        $tags = self::getMethodTagValues($className, $methodName);
272
273
        return \array_key_exists($tagName, $tags);
274
    }
275
276
    /**
277
     * Check if the property is tagged with the given tag (no value checked).
278
     *
279
     * @param string $className
280
     * @param string $propertyName
281
     * @param string $tagName
282
     */
283
    public static function isPropertyTaggedWith($className, $propertyName, $tagName): bool
284
    {
285
        $properties = self::getPropertiesTaggedWith($className, $tagName);
286
287
        return \in_array($propertyName, $properties, true);
288
    }
289
}
290