[TASK] Streamline phpdoc annotations in EXT:extbase
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Reflection / ReflectionService.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Reflection;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Cache\CacheManager;
18 use TYPO3\CMS\Core\SingletonInterface;
19
20 /**
21 * Reflection service for acquiring reflection based information.
22 * Originally based on the TYPO3.Flow reflection service.
23 */
24 class ReflectionService implements SingletonInterface
25 {
26 const CACHE_IDENTIFIER = 'extbase_reflection';
27 const CACHE_ENTRY_IDENTIFIER = 'ClassSchematas';
28
29 /**
30 * @var \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend
31 */
32 protected $dataCache;
33
34 /**
35 * Indicates whether the Reflection cache needs to be updated.
36 *
37 * This flag needs to be set as soon as new Reflection information was
38 * created.
39 *
40 * @var bool
41 */
42 protected $dataCacheNeedsUpdate = false;
43
44 /**
45 * Local cache for Class schemata
46 *
47 * @var array
48 */
49 protected $classSchemata = [];
50
51 /**
52 * @var bool
53 */
54 private $cachingEnabled = false;
55
56 /**
57 * If not $cacheManager is injected, the reflection service does not
58 * cache any data, useful for testing this service in unit tests.
59 *
60 * @param CacheManager $cacheManager
61 */
62 public function __construct(CacheManager $cacheManager = null)
63 {
64 if ($cacheManager instanceof CacheManager && $cacheManager->hasCache(static::CACHE_IDENTIFIER)) {
65 $this->cachingEnabled = true;
66 $this->dataCache = $cacheManager->getCache(static::CACHE_IDENTIFIER);
67
68 if (($classSchemata = $this->dataCache->get(static::CACHE_ENTRY_IDENTIFIER)) !== false) {
69 $this->classSchemata = $classSchemata;
70 }
71 }
72 }
73
74 public function __destruct()
75 {
76 if ($this->dataCacheNeedsUpdate && $this->cachingEnabled) {
77 $this->dataCache->set(static::CACHE_ENTRY_IDENTIFIER, $this->classSchemata);
78 }
79 }
80
81 /**
82 * Returns all tags and their values the specified class is tagged with
83 *
84 * @param string $className Name of the class
85 * @return array An array of tags and their values or an empty array if no tags were found
86 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
87 */
88 public function getClassTagsValues($className): array
89 {
90 trigger_error(
91 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
92 E_USER_DEPRECATED
93 );
94
95 try {
96 $classSchema = $this->getClassSchema($className);
97 } catch (\Exception $e) {
98 return [];
99 }
100
101 return $classSchema->getTags();
102 }
103
104 /**
105 * Returns the values of the specified class tag
106 *
107 * @param string $className Name of the class containing the property
108 * @param string $tag Tag to return the values of
109 * @return array An array of values or an empty array if the tag was not found
110 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
111 */
112 public function getClassTagValues($className, $tag): array
113 {
114 trigger_error(
115 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
116 E_USER_DEPRECATED
117 );
118
119 try {
120 $classSchema = $this->getClassSchema($className);
121 } catch (\Exception $e) {
122 return [];
123 }
124
125 return $classSchema->getTags()[$tag] ?? [];
126 }
127
128 /**
129 * Returns the names of all properties of the specified class
130 *
131 * @param string $className Name of the class to return the property names of
132 * @return array An array of property names or an empty array if none exist
133 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
134 */
135 public function getClassPropertyNames($className): array
136 {
137 trigger_error(
138 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
139 E_USER_DEPRECATED
140 );
141
142 try {
143 $classSchema = $this->getClassSchema($className);
144 } catch (\Exception $e) {
145 return [];
146 }
147
148 return array_keys($classSchema->getProperties());
149 }
150
151 /**
152 * Returns the class schema for the given class
153 *
154 * @param mixed $classNameOrObject The class name or an object
155 * @return ClassSchema
156 * @throws \TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException
157 */
158 public function getClassSchema($classNameOrObject): ClassSchema
159 {
160 $className = is_object($classNameOrObject) ? get_class($classNameOrObject) : $classNameOrObject;
161 if (isset($this->classSchemata[$className])) {
162 return $this->classSchemata[$className];
163 }
164
165 return $this->buildClassSchema($className);
166 }
167
168 /**
169 * Wrapper for method_exists() which tells if the given method exists.
170 *
171 * @param string $className Name of the class containing the method
172 * @param string $methodName Name of the method
173 * @return bool
174 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
175 */
176 public function hasMethod($className, $methodName): bool
177 {
178 trigger_error(
179 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
180 E_USER_DEPRECATED
181 );
182
183 try {
184 $classSchema = $this->getClassSchema($className);
185 } catch (\Exception $e) {
186 return false;
187 }
188
189 return $classSchema->hasMethod($methodName);
190 }
191
192 /**
193 * Returns all tags and their values the specified method is tagged with
194 *
195 * @param string $className Name of the class containing the method
196 * @param string $methodName Name of the method to return the tags and values of
197 * @return array An array of tags and their values or an empty array of no tags were found
198 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
199 */
200 public function getMethodTagsValues($className, $methodName): array
201 {
202 trigger_error(
203 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
204 E_USER_DEPRECATED
205 );
206
207 try {
208 $classSchema = $this->getClassSchema($className);
209 } catch (\Exception $e) {
210 return [];
211 }
212
213 return $classSchema->getMethod($methodName)['tags'] ?? [];
214 }
215
216 /**
217 * Returns an array of parameters of the given method. Each entry contains
218 * additional information about the parameter position, type hint etc.
219 *
220 * @param string $className Name of the class containing the method
221 * @param string $methodName Name of the method to return parameter information of
222 * @return array An array of parameter names and additional information or an empty array of no parameters were found
223 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
224 */
225 public function getMethodParameters($className, $methodName): array
226 {
227 trigger_error(
228 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
229 E_USER_DEPRECATED
230 );
231
232 try {
233 $classSchema = $this->getClassSchema($className);
234 } catch (\Exception $e) {
235 return [];
236 }
237
238 return $classSchema->getMethod($methodName)['params'] ?? [];
239 }
240
241 /**
242 * Returns all tags and their values the specified class property is tagged with
243 *
244 * @param string $className Name of the class containing the property
245 * @param string $propertyName Name of the property to return the tags and values of
246 * @return array An array of tags and their values or an empty array of no tags were found
247 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
248 */
249 public function getPropertyTagsValues($className, $propertyName): array
250 {
251 trigger_error(
252 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
253 E_USER_DEPRECATED
254 );
255
256 try {
257 $classSchema = $this->getClassSchema($className);
258 } catch (\Exception $e) {
259 return [];
260 }
261
262 return $classSchema->getProperty($propertyName)['tags'] ?? [];
263 }
264
265 /**
266 * Returns the values of the specified class property tag
267 *
268 * @param string $className Name of the class containing the property
269 * @param string $propertyName Name of the tagged property
270 * @param string $tag Tag to return the values of
271 * @return array An array of values or an empty array if the tag was not found
272 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
273 */
274 public function getPropertyTagValues($className, $propertyName, $tag): array
275 {
276 trigger_error(
277 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
278 E_USER_DEPRECATED
279 );
280
281 try {
282 $classSchema = $this->getClassSchema($className);
283 } catch (\Exception $e) {
284 return [];
285 }
286
287 return $classSchema->getProperty($propertyName)['tags'][$tag] ?? [];
288 }
289
290 /**
291 * Tells if the specified class is tagged with the given tag
292 *
293 * @param string $className Name of the class
294 * @param string $tag Tag to check for
295 * @return bool TRUE if the class is tagged with $tag, otherwise FALSE
296 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
297 */
298 public function isClassTaggedWith($className, $tag): bool
299 {
300 trigger_error(
301 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
302 E_USER_DEPRECATED
303 );
304
305 try {
306 $classSchema = $this->getClassSchema($className);
307 } catch (\Exception $e) {
308 return false;
309 }
310
311 foreach (array_keys($classSchema->getTags()) as $tagName) {
312 if ($tagName === $tag) {
313 return true;
314 }
315 }
316
317 return false;
318 }
319
320 /**
321 * Tells if the specified class property is tagged with the given tag
322 *
323 * @param string $className Name of the class
324 * @param string $propertyName Name of the property
325 * @param string $tag Tag to check for
326 * @return bool TRUE if the class property is tagged with $tag, otherwise FALSE
327 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0.
328 */
329 public function isPropertyTaggedWith($className, $propertyName, $tag): bool
330 {
331 trigger_error(
332 'Method ' . __METHOD__ . ' is deprecated and will be removed in TYPO3 v10.0.',
333 E_USER_DEPRECATED
334 );
335
336 try {
337 $classSchema = $this->getClassSchema($className);
338 } catch (\Exception $e) {
339 return false;
340 }
341
342 $property = $classSchema->getProperty($propertyName);
343
344 if (empty($property)) {
345 return false;
346 }
347
348 return isset($property['tags'][$tag]);
349 }
350
351 /**
352 * Builds class schemata from classes annotated as entities or value objects
353 *
354 * @param string $className
355 * @throws Exception\UnknownClassException
356 * @return ClassSchema The class schema
357 */
358 protected function buildClassSchema($className): ClassSchema
359 {
360 try {
361 $classSchema = new ClassSchema($className);
362 } catch (\ReflectionException $e) {
363 throw new Exception\UnknownClassException('The classname "' . $className . '" was not found and thus can not be reflected.', 1278450972, $e);
364 }
365 $this->classSchemata[$className] = $classSchema;
366 $this->dataCacheNeedsUpdate = true;
367 return $classSchema;
368 }
369 }