5e4b77f95321a4a94e410d1fabbb8eb59590347e
[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 the class schema for the given class
83 *
84 * @param mixed $classNameOrObject The class name or an object
85 * @return ClassSchema
86 * @throws \TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException
87 */
88 public function getClassSchema($classNameOrObject): ClassSchema
89 {
90 $className = is_object($classNameOrObject) ? get_class($classNameOrObject) : $classNameOrObject;
91 if (isset($this->classSchemata[$className])) {
92 return $this->classSchemata[$className];
93 }
94
95 return $this->buildClassSchema($className);
96 }
97
98 /**
99 * Builds class schemata from classes annotated as entities or value objects
100 *
101 * @param string $className
102 * @throws Exception\UnknownClassException
103 * @return ClassSchema The class schema
104 */
105 protected function buildClassSchema($className): ClassSchema
106 {
107 try {
108 $classSchema = new ClassSchema($className);
109 } catch (\ReflectionException $e) {
110 throw new Exception\UnknownClassException($e->getMessage() . '. Reflection failed.', 1278450972, $e);
111 }
112 $this->classSchemata[$className] = $classSchema;
113 $this->dataCacheNeedsUpdate = true;
114 return $classSchema;
115 }
116 }