diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php index 7bb1f4c0346ca9906d0d5e1d9f79d62eaea0cc8a..526a7059b8a2ade1a9a5bb5765eebc1056eee4eb 100644 --- a/typo3/sysext/core/Configuration/DefaultConfiguration.php +++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php @@ -183,17 +183,9 @@ return [ 'frontend' => \TYPO3\CMS\Fluid\Core\Cache\FluidTemplateCache::class, 'groups' => ['system'], ], - 'extbase_object' => [ - 'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, - 'backend' => \TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend::class, - 'options' => [ - 'defaultLifetime' => 0, - ], - 'groups' => ['system'] - ], 'extbase_reflection' => [ 'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, - 'backend' => \TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend::class, + 'backend' => \TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend::class, 'options' => [ 'defaultLifetime' => 0, ], diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-57594-OptimizeReflectionServiceCacheHandling.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-57594-OptimizeReflectionServiceCacheHandling.rst new file mode 100644 index 0000000000000000000000000000000000000000..6d3b893570571be689f0a26f4efbbf4c4aba295a --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-57594-OptimizeReflectionServiceCacheHandling.rst @@ -0,0 +1,63 @@ +.. include:: ../../Includes.txt + +============================================================ +Breaking: #57594 - Optimize ReflectionService Cache handling +============================================================ + +See :issue:`57594` + +Description +=========== + +The `extbase_object` cache has been removed completely and all necessary information about objects, +mainly @inject information, is now fetched from the ReflectionService as well. + +The ReflectionService does still create `ClassSchema` instances but these were improved a lot. All +necessary information is now gathered during the instantiation of `ClassSchema` instances. That means +that all necessary data is fetched once and then it can be used everywhere making any further +reflection superfluous. + +As runtime reflection has been removed completely, along with it several reflection classes, that +analyzed doc blocks, have been removed as well. These are no longer necessary. + +The `extbase_reflection` cache is no longer plugin based and will no longer be stored in the database +in the first place. Serialized ClassSchema instances will be stored in `typo3temp/var/Cache`. + +The following classes for internal use only and have been removed: + +* :php:`ClassInfo` +* :php:`ClassInfoCache` +* :php:`ClassInfoFactory` +* :php:`ClassReflection` +* :php:`MethodReflection` +* :php:`ParameterReflection` +* :php:`PropertyReflection` + +The following methods of the PHP class :php:`ReflectionService` have been removed: + +* :php:`injectConfigurationManager` +* :php:`setDataCache` +* :php:`initialize` +* :php:`isInitialized` +* :php:`shutdown` + + +Impact +====== + +Installations using the above classes or methods will throw a fatal error. + + +Affected Installations +====================== + +Installations using one of the mentioned classes or methods instead of the ReflectionService API. + + +Migration +========= + +Use the class :php:`ReflectionService` as API which will be automatically initialized on +instantiation. + +.. index:: PHP-API, FullyScanned diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst new file mode 100644 index 0000000000000000000000000000000000000000..f2b5d1992d420e45db19eb3bad41c40d01632bbd --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst @@ -0,0 +1,42 @@ +.. include:: ../../Includes.txt + +=============================================================== +Deprecation: #57594 - Optimize ReflectionService Cache handling +=============================================================== + +See :issue:`57594` + +Description +=========== + +In the process of streamlining the internal reflection / docparser cache handling, the following +methods of the PHP class :php:`ClassSchema` have been deprecated: + +* :php:`addProperty()` +* :php:`setModelType()` +* :php:`getModelType()` +* :php:`setUuidPropertyName()` +* :php:`getUuidPropertyName()` +* :php:`markAsIdentityProperty()` +* :php:`getIdentityProperties()` + + +Impact +====== + +Installations using the above methods will trigger a :php:`E_USER_DEPRECATED` warning. + + +Affected Installations +====================== + +Installations using one of the mentioned methods instead of the ReflectionService API. + + +Migration +========= + +Use the class :php:`ReflectionService` as API which will be automatically initialized on +nstantiation. + +.. index:: PHP-API, FullyScanned diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-57594-OptimizeReflectionServiceCacheHandling.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-57594-OptimizeReflectionServiceCacheHandling.rst new file mode 100644 index 0000000000000000000000000000000000000000..32cc9ac230e17e57e234a2899b369a3ff7cdcf70 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-57594-OptimizeReflectionServiceCacheHandling.rst @@ -0,0 +1,54 @@ +.. include:: ../../Includes.txt + +=========================================================== +Feature: #57594 - Optimize ReflectionService Cache handling +=========================================================== + +See :issue:`57594` + +Description +=========== + +Since its beginnings, Extbase came along with two main caches for reflection data, +`extbase_reflection` and `extbase_object`. The latter mostly stored information that were relevant +to the dependency injection, like inject methods, inject properties and constructor parameters. The +information was gathered by actual reflection and by analysing doc blocks of properties and methods. + +`extbase_reflection` stored similar reflection and doc block data about objects but mainly for the +parts outside dependency injection. + +For example, the validation resolver used it to identify `@validate` tags, the ActionController used +it to identity which properties not to validate. The ORM also used it a lot to find annotated types +via `@var`. + +There were a few issues with these two approaches: + +* A lot of redundant data was fetched + +* Data was fetched multiple times at different locations + +* The `extbase_reflection` cache was stored each plugin separately, resulting in a lot of redundant +cache data for each plugin cache + +* At a lot of places, the reflection service was used to reflect objects, but the data wasn't cached +or taken from a cache resulting in performance drawbacks + + +Impact +====== + +* The `extbase_object` cache has been removed completely and all necessary information about objects, +mainly `@inject` functionality, is now fetched from the `ReflectionService` as well. + +* The `ReflectionService` does still create `ClassSchema` instances but these were improved a lot. +All necessary information is now gathered during the instantiation of ClassSchema instances. This +means that all necessary data is fetched once and then it can be used everywhere making any further +reflection superfluous. + +* As runtime reflection has been removed completely, along with it several reflection classes, that +analyzed doc blocks, have been removed as well. These are no longer necessary. + +* The `extbase_reflection` cache is no longer plugin based and will no longer be stored in the +database in the first place. Serialized `ClassSchema` instances will be stored in `typo3temp/var/Cache`. + +.. index:: PHP-API diff --git a/typo3/sysext/extbase/Classes/Core/Bootstrap.php b/typo3/sysext/extbase/Classes/Core/Bootstrap.php index 39c84f587e31417a8205e2eecd4bd0b86cd39855..6b9d9427a193768394a4419b5ef5035ec86d5ecf 100644 --- a/typo3/sysext/extbase/Classes/Core/Bootstrap.php +++ b/typo3/sysext/extbase/Classes/Core/Bootstrap.php @@ -30,13 +30,6 @@ class Bootstrap implements \TYPO3\CMS\Extbase\Core\BootstrapInterface */ public $cObj; - /** - * The application context - * - * @var string - */ - protected $context; - /** * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManager */ @@ -47,16 +40,6 @@ class Bootstrap implements \TYPO3\CMS\Extbase\Core\BootstrapInterface */ protected $objectManager; - /** - * @var \TYPO3\CMS\Core\Cache\CacheManager - */ - protected $cacheManager; - - /** - * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService - */ - protected $reflectionService; - /** * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager */ @@ -86,8 +69,6 @@ class Bootstrap implements \TYPO3\CMS\Extbase\Core\BootstrapInterface $this->initializeObjectManager(); $this->initializeConfiguration($configuration); $this->configureObjectManager(); - $this->initializeCache(); - $this->initializeReflection(); $this->initializePersistence(); } @@ -137,30 +118,6 @@ class Bootstrap implements \TYPO3\CMS\Extbase\Core\BootstrapInterface } } - /** - * Initializes the cache framework - * - * @see initialize() - */ - protected function initializeCache() - { - $this->cacheManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class); - } - - /** - * Initializes the Reflection Service - * - * @see initialize() - */ - protected function initializeReflection() - { - $this->reflectionService = $this->objectManager->get(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class); - $this->reflectionService->setDataCache($this->cacheManager->getCache('extbase_reflection')); - if (!$this->reflectionService->isInitialized()) { - $this->reflectionService->initialize(); - } - } - /** * Initializes the persistence framework * @@ -201,7 +158,6 @@ class Bootstrap implements \TYPO3\CMS\Extbase\Core\BootstrapInterface // This happens for instance, when a USER object was converted to a USER_INT // @see TYPO3\CMS\Extbase\Mvc\Web\FrontendRequestHandler::handleRequest() if ($response === null) { - $this->reflectionService->shutdown(); $content = ''; } else { $content = $response->shutdown(); @@ -221,7 +177,6 @@ class Bootstrap implements \TYPO3\CMS\Extbase\Core\BootstrapInterface protected function resetSingletons() { $this->persistenceManager->persistAll(); - $this->reflectionService->shutdown(); } /** diff --git a/typo3/sysext/extbase/Classes/Mvc/Cli/Command.php b/typo3/sysext/extbase/Classes/Mvc/Cli/Command.php index 7653a2e2efc5f66815bd14614c7476e1f821e051..aa3a51e61fee7cc96a8c90883343e5051276493a 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Cli/Command.php +++ b/typo3/sysext/extbase/Classes/Mvc/Cli/Command.php @@ -14,6 +14,8 @@ namespace TYPO3\CMS\Extbase\Mvc\Cli; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Extbase\Reflection\ClassSchema; + /** * Represents a Command * @@ -41,11 +43,6 @@ class Command */ protected $commandIdentifier; - /** - * @var \TYPO3\CMS\Extbase\Reflection\MethodReflection - */ - protected $commandMethodReflection; - /** * Name of the extension to which this command belongs * @@ -58,6 +55,16 @@ class Command */ protected $reflectionService; + /** + * @var ClassSchema + */ + protected $classSchema; + + /** + * @var string + */ + protected $controllerCommandMethod; + /** * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager */ @@ -85,6 +92,7 @@ class Command { $this->controllerClassName = $controllerClassName; $this->controllerCommandName = $controllerCommandName; + $this->controllerCommandMethod = $this->controllerCommandName . 'Command'; $delimiter = strpos($controllerClassName, '\\') !== false ? '\\' : '_'; $classNameParts = explode($delimiter, $controllerClassName); if (isset($classNameParts[0]) && $classNameParts[0] === 'TYPO3' && isset($classNameParts[1]) && $classNameParts[1] === 'CMS') { @@ -111,6 +119,11 @@ class Command $this->commandIdentifier = strtolower($extensionKey . ':' . substr($classNameParts[$numberOfClassNameParts - 1], 0, -17) . ':' . $controllerCommandName); } + public function initializeObject() + { + $this->classSchema = $this->reflectionService->getClassSchema($this->controllerClassName); + } + /** * @return string */ @@ -154,7 +167,7 @@ class Command */ public function getShortDescription() { - $lines = explode(LF, $this->getCommandMethodReflection()->getDescription()); + $lines = explode(LF, $this->classSchema->getMethod($this->controllerCommandMethod)['description']); return !empty($lines) ? trim($lines[0]) : '<no description available>'; } @@ -167,7 +180,7 @@ class Command */ public function getDescription() { - $lines = explode(LF, $this->getCommandMethodReflection()->getDescription()); + $lines = explode(LF, $this->classSchema->getMethod($this->controllerCommandMethod)['description']); array_shift($lines); $descriptionLines = []; foreach ($lines as $line) { @@ -186,7 +199,7 @@ class Command */ public function hasArguments() { - return !empty($this->getCommandMethodReflection()->getParameters()); + return !empty($this->classSchema->getMethod($this->controllerCommandMethod)['params']); } /** @@ -202,12 +215,11 @@ class Command return []; } $commandArgumentDefinitions = []; - $commandMethodReflection = $this->getCommandMethodReflection(); - $annotations = $commandMethodReflection->getTagsValues(); - $commandParameters = $this->reflectionService->getMethodParameters($this->controllerClassName, $this->controllerCommandName . 'Command'); + $commandParameters = $this->classSchema->getMethod($this->controllerCommandMethod)['params']; + $commandParameterTags = $this->classSchema->getMethod($this->controllerCommandMethod)['tags']['param']; $i = 0; foreach ($commandParameters as $commandParameterName => $commandParameterDefinition) { - $explodedAnnotation = preg_split('/\s+/', $annotations['param'][$i], 3); + $explodedAnnotation = preg_split('/\s+/', $commandParameterTags[$i], 3); $description = !empty($explodedAnnotation[2]) ? $explodedAnnotation[2] : ''; $required = $commandParameterDefinition['optional'] !== true; $commandArgumentDefinitions[] = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition::class, $commandParameterName, $required, $description); @@ -225,7 +237,7 @@ class Command */ public function isInternal() { - return $this->getCommandMethodReflection()->isTaggedWith('internal'); + return isset($this->classSchema->getMethod($this->controllerCommandMethod)['tags']['internal']); } /** @@ -235,7 +247,7 @@ class Command */ public function isCliOnly() { - return $this->getCommandMethodReflection()->isTaggedWith('cli'); + return isset($this->classSchema->getMethod($this->controllerCommandMethod)['tags']['cli']); } /** @@ -247,7 +259,7 @@ class Command */ public function isFlushingCaches() { - return $this->getCommandMethodReflection()->isTaggedWith('flushesCaches'); + return isset($this->classSchema->getMethod($this->controllerCommandMethod)['tags']['flushesCaches']); } /** @@ -258,27 +270,15 @@ class Command */ public function getRelatedCommandIdentifiers() { - $commandMethodReflection = $this->getCommandMethodReflection(); - if (!$commandMethodReflection->isTaggedWith('see')) { + if (!isset($this->classSchema->getMethod($this->controllerCommandMethod)['tags']['see'])) { return []; } $relatedCommandIdentifiers = []; - foreach ($commandMethodReflection->getTagValues('see') as $tagValue) { + foreach ($this->classSchema->getMethod($this->controllerCommandMethod)['tags']['see'] as $tagValue) { if (preg_match('/^[\\w\\d\\.]+:[\\w\\d]+:[\\w\\d]+$/', $tagValue) === 1) { $relatedCommandIdentifiers[] = $tagValue; } } return $relatedCommandIdentifiers; } - - /** - * @return \TYPO3\CMS\Extbase\Reflection\MethodReflection - */ - protected function getCommandMethodReflection() - { - if ($this->commandMethodReflection === null) { - $this->commandMethodReflection = $this->objectManager->get(\TYPO3\CMS\Extbase\Reflection\MethodReflection::class, $this->controllerClassName, $this->controllerCommandName . 'Command'); - } - return $this->commandMethodReflection; - } } diff --git a/typo3/sysext/extbase/Classes/Mvc/Controller/ActionController.php b/typo3/sysext/extbase/Classes/Mvc/Controller/ActionController.php index c97960da0bcbc72617cd43a712a2f5862d7a5219..ebc0bba86111a788c3be848634a540b482776f25 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Controller/ActionController.php +++ b/typo3/sysext/extbase/Classes/Mvc/Controller/ActionController.php @@ -235,7 +235,7 @@ class ActionController extends AbstractController if ($dataType === null) { throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException('The argument type for parameter $' . $parameterName . ' of method ' . static::class . '->' . $this->actionMethodName . '() could not be detected.', 1253175643); } - $defaultValue = isset($parameterInfo['defaultValue']) ? $parameterInfo['defaultValue'] : null; + $defaultValue = $parameterInfo['hasDefaultValue'] === true ? $parameterInfo['defaultValue'] : null; $this->arguments->addNewArgument($parameterName, $dataType, $parameterInfo['optional'] === false, $defaultValue); } } diff --git a/typo3/sysext/extbase/Classes/Mvc/Dispatcher.php b/typo3/sysext/extbase/Classes/Mvc/Dispatcher.php index c02e80ea1254199926b0b23a4443be5a27ea6b84..6d82759185e690bfce5482609402118374d70993 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Dispatcher.php +++ b/typo3/sysext/extbase/Classes/Mvc/Dispatcher.php @@ -25,11 +25,6 @@ class Dispatcher implements \TYPO3\CMS\Core\SingletonInterface */ protected $objectManager; - /** - * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService - */ - protected $reflectionService; - /** * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher */ @@ -40,14 +35,6 @@ class Dispatcher implements \TYPO3\CMS\Core\SingletonInterface */ protected $settings = []; - /** - * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService - */ - public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService) - { - $this->reflectionService = $reflectionService; - } - /** * @param \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher */ diff --git a/typo3/sysext/extbase/Classes/Mvc/RequestHandlerResolver.php b/typo3/sysext/extbase/Classes/Mvc/RequestHandlerResolver.php index e85148f773ec6cdf837526138b1fcb23af8a0aae..7a8f8e627f1a5ded9865a1ee3f4e4943ea7dbe27 100644 --- a/typo3/sysext/extbase/Classes/Mvc/RequestHandlerResolver.php +++ b/typo3/sysext/extbase/Classes/Mvc/RequestHandlerResolver.php @@ -24,11 +24,6 @@ class RequestHandlerResolver */ protected $objectManager; - /** - * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService - */ - protected $reflectionService; - /** * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface */ @@ -42,14 +37,6 @@ class RequestHandlerResolver $this->objectManager = $objectManager; } - /** - * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService - */ - public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService) - { - $this->reflectionService = $reflectionService; - } - /** * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager */ diff --git a/typo3/sysext/extbase/Classes/Object/Container/ClassInfo.php b/typo3/sysext/extbase/Classes/Object/Container/ClassInfo.php deleted file mode 100644 index 40cbe8d1d77bc07c724b22229949594c7a268237..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Classes/Object/Container/ClassInfo.php +++ /dev/null @@ -1,170 +0,0 @@ -<?php -namespace TYPO3\CMS\Extbase\Object\Container; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Value object containing the relevant informations for a class, - * this object is build by the classInfoFactory - or could also be restored from a cache - */ -class ClassInfo -{ - /** - * The classname of the class where the infos belong to - * - * @var string - */ - private $className; - - /** - * The constructor Dependencies for the class in the format: - * array( - * 0 => array( <-- parameters for argument 1 - * 'name' => <arg name>, <-- name of argument - * 'dependency' => <classname>, <-- if the argument is a class, the type of the argument - * 'defaultvalue' => <mixed>) <-- if the argument is optional, its default value - * ), - * 1 => ... - * ) - * - * @var array - */ - private $constructorArguments; - - /** - * All setter injections in the format - * array (<nameOfMethod> => <classNameToInject> ) - * - * @var array - */ - private $injectMethods; - - /** - * All setter injections in the format - * array (<nameOfProperty> => <classNameToInject> ) - * - * @var array - */ - private $injectProperties; - - /** - * Indicates if the class is a singleton or not. - * - * @var bool - */ - private $isSingleton = false; - - /** - * Indicates if the class has the method initializeObject - * - * @var bool - */ - private $isInitializeable = false; - - /** - * @param string $className - * @param array $constructorArguments - * @param array $injectMethods - * @param bool $isSingleton - * @param bool $isInitializeable - * @param array $injectProperties - */ - public function __construct($className, array $constructorArguments, array $injectMethods, $isSingleton = false, $isInitializeable = false, array $injectProperties = []) - { - $this->className = $className; - $this->constructorArguments = $constructorArguments; - $this->injectMethods = $injectMethods; - $this->injectProperties = $injectProperties; - $this->isSingleton = $isSingleton; - $this->isInitializeable = $isInitializeable; - } - - /** - * Gets the class name passed to constructor - * - * @return string - */ - public function getClassName() - { - return $this->className; - } - - /** - * Get arguments passed to constructor - * - * @return array - */ - public function getConstructorArguments() - { - return $this->constructorArguments; - } - - /** - * Returns an array with the inject methods. - * - * @return array - */ - public function getInjectMethods() - { - return $this->injectMethods; - } - - /** - * Returns an array with the inject properties - * - * @return array - */ - public function getInjectProperties() - { - return $this->injectProperties; - } - - /** - * Asserts if the class is a singleton or not. - * - * @return bool - */ - public function getIsSingleton() - { - return $this->isSingleton; - } - - /** - * Asserts if the class is initializeable with initializeObject. - * - * @return bool - */ - public function getIsInitializeable() - { - return $this->isInitializeable; - } - - /** - * Asserts if the class has Dependency Injection methods - * - * @return bool - */ - public function hasInjectMethods() - { - return !empty($this->injectMethods); - } - - /** - * @return bool - */ - public function hasInjectProperties() - { - return !empty($this->injectProperties); - } -} diff --git a/typo3/sysext/extbase/Classes/Object/Container/ClassInfoCache.php b/typo3/sysext/extbase/Classes/Object/Container/ClassInfoCache.php deleted file mode 100644 index 3dd2920ee0ed24ec30549f7df3b859d61e658c57..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Classes/Object/Container/ClassInfoCache.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php -namespace TYPO3\CMS\Extbase\Object\Container; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Simple Cache for classInfos - */ -class ClassInfoCache -{ - /** - * @var array - */ - private $level1Cache = []; - - /** - * @var \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend - */ - private $level2Cache; - - /** - * constructor - */ - public function __construct() - { - $this->initializeLevel2Cache(); - } - - /** - * checks if cacheentry exists for id - * - * @param string $id - * @return bool - */ - public function has($id) - { - return isset($this->level1Cache[$id]) || $this->level2Cache->has($id); - } - - /** - * Gets the cache for the id - * - * @param string $id - * @return mixed - */ - public function get($id) - { - if (!isset($this->level1Cache[$id])) { - $this->level1Cache[$id] = $this->level2Cache->get($id); - } - return $this->level1Cache[$id]; - } - - /** - * sets the cache for the id - * - * @param string $id - * @param mixed $value - */ - public function set($id, $value) - { - $this->level1Cache[$id] = $value; - $this->level2Cache->set($id, $value); - } - - /** - * Initialize the TYPO3 second level cache - */ - private function initializeLevel2Cache() - { - $this->level2Cache = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('extbase_object'); - } -} diff --git a/typo3/sysext/extbase/Classes/Object/Container/ClassInfoFactory.php b/typo3/sysext/extbase/Classes/Object/Container/ClassInfoFactory.php deleted file mode 100644 index 26980ea12c8a1d8f1d4cdf4ef40f2029f09bb435..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Classes/Object/Container/ClassInfoFactory.php +++ /dev/null @@ -1,172 +0,0 @@ -<?php -namespace TYPO3\CMS\Extbase\Object\Container; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * TYPO3 Dependency Injection container - */ -class ClassInfoFactory -{ - /** - * Factory metod that builds a ClassInfo Object for the given classname - using reflection - * - * @param string $className The class name to build the class info for - * @throws Exception\UnknownObjectException - * @return \TYPO3\CMS\Extbase\Object\Container\ClassInfo the class info - */ - public function buildClassInfoFromClassName($className) - { - if ($className === 'DateTime') { - return new \TYPO3\CMS\Extbase\Object\Container\ClassInfo($className, [], [], false, false, []); - } - try { - $reflectedClass = new \ReflectionClass($className); - } catch (\Exception $e) { - throw new \TYPO3\CMS\Extbase\Object\Container\Exception\UnknownObjectException('Could not analyse class: "' . $className . '" maybe not loaded or no autoloader? ' . $e->getMessage(), 1289386765, $e); - } - $constructorArguments = $this->getConstructorArguments($reflectedClass); - $injectMethods = $this->getInjectMethods($reflectedClass); - $injectProperties = $this->getInjectProperties($reflectedClass); - $isSingleton = $this->getIsSingleton($className); - $isInitializeable = $this->getIsInitializeable($className); - return new \TYPO3\CMS\Extbase\Object\Container\ClassInfo($className, $constructorArguments, $injectMethods, $isSingleton, $isInitializeable, $injectProperties); - } - - /** - * Build a list of constructor arguments - * - * @param \ReflectionClass $reflectedClass - * @return array of parameter infos for constructor - */ - private function getConstructorArguments(\ReflectionClass $reflectedClass) - { - $reflectionMethod = $reflectedClass->getConstructor(); - if (!is_object($reflectionMethod)) { - return []; - } - $result = []; - foreach ($reflectionMethod->getParameters() as $reflectionParameter) { - /* @var $reflectionParameter \ReflectionParameter */ - $info = []; - $info['name'] = $reflectionParameter->getName(); - if ($reflectionParameter->getClass()) { - $info['dependency'] = $reflectionParameter->getClass()->getName(); - } - - try { - $info['defaultValue'] = $reflectionParameter->getDefaultValue(); - } catch (\ReflectionException $e) { - } - - $result[] = $info; - } - return $result; - } - - /** - * Build a list of inject methods for the given class. - * - * @param \ReflectionClass $reflectedClass - * @throws \Exception - * @return array (nameOfInjectMethod => nameOfClassToBeInjected) - */ - private function getInjectMethods(\ReflectionClass $reflectedClass) - { - $result = []; - $reflectionMethods = $reflectedClass->getMethods(); - if (is_array($reflectionMethods)) { - foreach ($reflectionMethods as $reflectionMethod) { - if ($reflectionMethod->isPublic() && $this->isNameOfInjectMethod($reflectionMethod->getName())) { - $reflectionParameter = $reflectionMethod->getParameters(); - if (isset($reflectionParameter[0])) { - if (!$reflectionParameter[0]->getClass()) { - throw new \Exception( - 'Method "' . $reflectionMethod->getName() . '" of class "' . $reflectedClass->getName() . '" is marked as setter for Dependency Injection, but does not have a type annotation', - 1476108030 - ); - } - $result[$reflectionMethod->getName()] = $reflectionParameter[0]->getClass()->getName(); - } - } - } - } - return $result; - } - - /** - * Build a list of properties to be injected for the given class. - * - * @param \ReflectionClass $reflectedClass - * @return array (nameOfInjectProperty => nameOfClassToBeInjected) - */ - private function getInjectProperties(\ReflectionClass $reflectedClass) - { - $result = []; - $reflectionProperties = $reflectedClass->getProperties(); - if (is_array($reflectionProperties)) { - foreach ($reflectionProperties as $reflectionProperty) { - $reflectedProperty = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Reflection\PropertyReflection::class, $reflectedClass->getName(), $reflectionProperty->getName()); - if ($reflectedProperty->isTaggedWith('inject') && $reflectedProperty->getName() !== 'settings') { - $varValues = $reflectedProperty->getTagValues('var'); - if (count($varValues) === 1) { - $result[$reflectedProperty->getName()] = ltrim($varValues[0], '\\'); - } - } - } - } - return $result; - } - - /** - * This method checks if given method can be used for injection - * - * @param string $methodName - * @return bool - */ - private function isNameOfInjectMethod($methodName) - { - if ( - substr($methodName, 0, 6) === 'inject' - && $methodName[6] === strtoupper($methodName[6]) - && $methodName !== 'injectSettings' - ) { - return true; - } - return false; - } - - /** - * This method is used to determine if a class is a singleton or not. - * - * @param string $classname - * @return bool - */ - private function getIsSingleton($classname) - { - return in_array(\TYPO3\CMS\Core\SingletonInterface::class, class_implements($classname)); - } - - /** - * This method is used to determine of the object is initializeable with the - * method initializeObject. - * - * @param string $classname - * @return bool - */ - private function getIsInitializeable($classname) - { - return method_exists($classname, 'initializeObject'); - } -} diff --git a/typo3/sysext/extbase/Classes/Object/Container/Container.php b/typo3/sysext/extbase/Classes/Object/Container/Container.php index 179b78a07d24e496ba51c7f57d86965f42e6a62d..4d7682525385b70041f80cee88e964b739df42f8 100644 --- a/typo3/sysext/extbase/Classes/Object/Container/Container.php +++ b/typo3/sysext/extbase/Classes/Object/Container/Container.php @@ -15,8 +15,11 @@ namespace TYPO3\CMS\Extbase\Object\Container; */ use Psr\Log\LoggerInterface; +use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Reflection\ClassSchema; +use TYPO3\CMS\Extbase\Reflection\ReflectionService; /** * Internal TYPO3 Dependency Injection container @@ -26,13 +29,6 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface const SCOPE_PROTOTYPE = 1; const SCOPE_SINGLETON = 2; - /** - * internal cache for classinfos - * - * @var \TYPO3\CMS\Extbase\Object\Container\ClassInfoCache - */ - private $cache = null; - /** * registered alternative implementations of a class * e.g. used to know the class for an AbstractClass or a Dependency @@ -41,13 +37,6 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface */ private $alternativeImplementation; - /** - * reference to the classinfofactory, that analyses dependencys - * - * @var \TYPO3\CMS\Extbase\Object\Container\ClassInfoFactory - */ - private $classInfoFactory = null; - /** * @var \Doctrine\Instantiator\InstantiatorInterface */ @@ -67,6 +56,11 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface */ private $prototypeObjectsWhichAreCurrentlyInstanciated; + /** + * @var ReflectionService + */ + private $reflectionService; + /** * Constructor is protected since container should * be a singleton. @@ -75,32 +69,7 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface */ public function __construct() { - } - - /** - * Internal method to create the classInfoFactory, extracted to be mockable. - * - * @return \TYPO3\CMS\Extbase\Object\Container\ClassInfoFactory - */ - protected function getClassInfoFactory() - { - if ($this->classInfoFactory == null) { - $this->classInfoFactory = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\Container\ClassInfoFactory::class); - } - return $this->classInfoFactory; - } - - /** - * Internal method to create the classInfoCache, extracted to be mockable. - * - * @return \TYPO3\CMS\Extbase\Object\Container\ClassInfoCache - */ - protected function getClassInfoCache() - { - if ($this->cache == null) { - $this->cache = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\Container\ClassInfoCache::class); - } - return $this->cache; + $this->reflectionService = GeneralUtility::makeInstance(ReflectionService::class, GeneralUtility::makeInstance(CacheManager::class)); } /** @@ -139,10 +108,10 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface public function getEmptyObject($className) { $className = $this->getImplementationClassName($className); - $classInfo = $this->getClassInfo($className); + $classSchema = $this->reflectionService->getClassSchema($className); $object = $this->getInstantiator()->instantiate($className); - $this->injectDependencies($object, $classInfo); - $this->initializeObject($object, $classInfo); + $this->injectDependencies($object, $classSchema); + $this->initializeObject($object); return $object; } @@ -174,17 +143,18 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface } return $this->singletonInstances[$className]; } - $classInfo = $this->getClassInfo($className); - $classIsSingleton = $classInfo->getIsSingleton(); + + $classSchema = $this->reflectionService->getClassSchema($className); + $classIsSingleton = $classSchema->isSingleton(); if (!$classIsSingleton) { if (array_key_exists($className, $this->prototypeObjectsWhichAreCurrentlyInstanciated) !== false) { throw new \TYPO3\CMS\Extbase\Object\Exception\CannotBuildObjectException('Cyclic dependency in prototype object, for class "' . $className . '".', 1295611406); } $this->prototypeObjectsWhichAreCurrentlyInstanciated[$className] = true; } - $instance = $this->instanciateObject($classInfo, $givenConstructorArguments); - $this->injectDependencies($instance, $classInfo); - $this->initializeObject($instance, $classInfo); + $instance = $this->instanciateObject($classSchema, $givenConstructorArguments); + $this->injectDependencies($instance, $classSchema); + $this->initializeObject($instance); if (!$classIsSingleton) { unset($this->prototypeObjectsWhichAreCurrentlyInstanciated[$className]); } @@ -196,19 +166,19 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface * Additionally, directly registers all singletons in the singleton registry, * such that circular references of singletons are correctly instanciated. * - * @param \TYPO3\CMS\Extbase\Object\Container\ClassInfo $classInfo + * @param ClassSchema $classSchema * @param array $givenConstructorArguments * @throws \TYPO3\CMS\Extbase\Object\Exception * @return object the new instance */ - protected function instanciateObject(\TYPO3\CMS\Extbase\Object\Container\ClassInfo $classInfo, array $givenConstructorArguments) + protected function instanciateObject(ClassSchema $classSchema, array $givenConstructorArguments) { - $className = $classInfo->getClassName(); - $classIsSingleton = $classInfo->getIsSingleton(); + $className = $classSchema->getClassName(); + $classIsSingleton = $classSchema->isSingleton(); if ($classIsSingleton && !empty($givenConstructorArguments)) { throw new \TYPO3\CMS\Extbase\Object\Exception('Object "' . $className . '" has explicit constructor arguments but is a singleton; this is not allowed.', 1292858051); } - $constructorArguments = $this->getConstructorArguments($className, $classInfo, $givenConstructorArguments); + $constructorArguments = $this->getConstructorArguments($className, $classSchema, $givenConstructorArguments); array_unshift($constructorArguments, $className); $instance = call_user_func_array([GeneralUtility::class, 'makeInstance'], $constructorArguments); if ($classIsSingleton) { @@ -221,28 +191,28 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface * Inject setter-dependencies into $instance * * @param object $instance - * @param \TYPO3\CMS\Extbase\Object\Container\ClassInfo $classInfo + * @param ClassSchema $classSchema */ - protected function injectDependencies($instance, \TYPO3\CMS\Extbase\Object\Container\ClassInfo $classInfo) + protected function injectDependencies($instance, ClassSchema $classSchema) { - if (!$classInfo->hasInjectMethods() && !$classInfo->hasInjectProperties()) { + if (!$classSchema->hasInjectMethods() && !$classSchema->hasInjectProperties()) { return; } - foreach ($classInfo->getInjectMethods() as $injectMethodName => $classNameToInject) { + foreach ($classSchema->getInjectMethods() as $injectMethodName => $classNameToInject) { $instanceToInject = $this->getInstanceInternal($classNameToInject); - if ($classInfo->getIsSingleton() && !$instanceToInject instanceof \TYPO3\CMS\Core\SingletonInterface) { - $this->getLogger()->notice('The singleton "' . $classInfo->getClassName() . '" needs a prototype in "' . $injectMethodName . '". This is often a bad code smell; often you rather want to inject a singleton.'); + if ($classSchema->isSingleton() && !$instanceToInject instanceof \TYPO3\CMS\Core\SingletonInterface) { + $this->getLogger()->notice('The singleton "' . $classSchema->getClassName() . '" needs a prototype in "' . $injectMethodName . '". This is often a bad code smell; often you rather want to inject a singleton.'); } if (is_callable([$instance, $injectMethodName])) { $instance->{$injectMethodName}($instanceToInject); } } - foreach ($classInfo->getInjectProperties() as $injectPropertyName => $classNameToInject) { + foreach ($classSchema->getInjectProperties() as $injectPropertyName => $classNameToInject) { $instanceToInject = $this->getInstanceInternal($classNameToInject); - if ($classInfo->getIsSingleton() && !$instanceToInject instanceof \TYPO3\CMS\Core\SingletonInterface) { - $this->getLogger()->notice('The singleton "' . $classInfo->getClassName() . '" needs a prototype in "' . $injectPropertyName . '". This is often a bad code smell; often you rather want to inject a singleton.'); + if ($classSchema->isSingleton() && !$instanceToInject instanceof \TYPO3\CMS\Core\SingletonInterface) { + $this->getLogger()->notice('The singleton "' . $classSchema->getClassName() . '" needs a prototype in "' . $injectPropertyName . '". This is often a bad code smell; often you rather want to inject a singleton.'); } - $propertyReflection = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Reflection\PropertyReflection::class, $instance, $injectPropertyName); + $propertyReflection = new \ReflectionProperty($instance, $injectPropertyName); $propertyReflection->setAccessible(true); $propertyReflection->setValue($instance, $instanceToInject); @@ -253,11 +223,10 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface * Call object initializer if present in object * * @param object $instance - * @param \TYPO3\CMS\Extbase\Object\Container\ClassInfo $classInfo */ - protected function initializeObject($instance, \TYPO3\CMS\Extbase\Object\Container\ClassInfo $classInfo) + protected function initializeObject($instance) { - if ($classInfo->getIsInitializeable() && is_callable([$instance, 'initializeObject'])) { + if (method_exists($instance, 'initializeObject') && is_callable([$instance, 'initializeObject'])) { $instance->initializeObject(); } } @@ -278,26 +247,28 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface * gets array of parameter that can be used to call a constructor * * @param string $className - * @param \TYPO3\CMS\Extbase\Object\Container\ClassInfo $classInfo + * @param ClassSchema $classSchema * @param array $givenConstructorArguments * @throws \InvalidArgumentException * @return array */ - private function getConstructorArguments($className, \TYPO3\CMS\Extbase\Object\Container\ClassInfo $classInfo, array $givenConstructorArguments) + private function getConstructorArguments($className, ClassSchema $classSchema, array $givenConstructorArguments) { $parameters = []; - $constructorArgumentInformation = $classInfo->getConstructorArguments(); - foreach ($constructorArgumentInformation as $index => $argumentInformation) { + $constructorArgumentInformation = $classSchema->getConstructorArguments(); + foreach ($constructorArgumentInformation as $constructorArgumentName => $argumentInformation) { + $index = $argumentInformation['position']; + // Constructor argument given AND argument is a simple type OR instance of argument type if (array_key_exists($index, $givenConstructorArguments) && (!isset($argumentInformation['dependency']) || is_a($givenConstructorArguments[$index], $argumentInformation['dependency']))) { $parameter = $givenConstructorArguments[$index]; } else { - if (isset($argumentInformation['dependency']) && !array_key_exists('defaultValue', $argumentInformation)) { + if (isset($argumentInformation['dependency']) && $argumentInformation['hasDefaultValue'] === false) { $parameter = $this->getInstanceInternal($argumentInformation['dependency']); - if ($classInfo->getIsSingleton() && !$parameter instanceof \TYPO3\CMS\Core\SingletonInterface) { + if ($classSchema->isSingleton() && !$parameter instanceof \TYPO3\CMS\Core\SingletonInterface) { $this->getLogger()->notice('The singleton "' . $className . '" needs a prototype in the constructor. This is often a bad code smell; often you rather want to inject a singleton.'); } - } elseif (array_key_exists('defaultValue', $argumentInformation)) { + } elseif ($argumentInformation['hasDefaultValue'] === true) { $parameter = $argumentInformation['defaultValue']; } else { throw new \InvalidArgumentException('not a correct info array of constructor dependencies was passed!', 1476107941); @@ -326,23 +297,6 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface return $className; } - /** - * Gets Classinfos for the className - using the cache and the factory - * - * @param string $className - * @return \TYPO3\CMS\Extbase\Object\Container\ClassInfo - */ - private function getClassInfo($className) - { - $classNameHash = md5($className); - $classInfo = $this->getClassInfoCache()->get($classNameHash); - if (!$classInfo instanceof \TYPO3\CMS\Extbase\Object\Container\ClassInfo) { - $classInfo = $this->getClassInfoFactory()->buildClassInfoFromClassName($className); - $this->getClassInfoCache()->set($classNameHash, $classInfo); - } - return $classInfo; - } - /** * @param string $className * @@ -350,7 +304,7 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface */ public function isSingleton($className) { - return $this->getClassInfo($className)->getIsSingleton(); + return $this->reflectionService->getClassSchema($className)->isSingleton(); } /** diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php index c70360260de2da9368be6ae1e15296262b0a613a..cd9a39312675ed112fd083f8edce49b69fd9cd5a 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php @@ -454,7 +454,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface $propertyMetaData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName); foreach ($this->getRemovedChildObjects($parentObject, $propertyName) as $removedObject) { $this->detachObjectFromParentObject($removedObject, $parentObject, $propertyName); - if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY && $propertyMetaData['cascade'] === 'remove') { + if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY && $propertyMetaData['annotations']['cascade'] === 'remove') { $this->removeEntity($removedObject); } } @@ -1077,7 +1077,7 @@ class Backend implements \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface continue; } $propertyMetaData = $classSchema->getProperty($propertyName); - if ($propertyMetaData['cascade'] === 'remove') { + if ($propertyMetaData['annotations']['cascade'] === 'remove') { if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) { foreach ($propertyValue as $containedObject) { $this->removeEntity($containedObject); diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapper.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapper.php index 4adb5bedad8eac2c4c46cbc05644fa0d5350d17a..2e55f63235c65863c5cb427d0757c03304f97843 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapper.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/DataMapper.php @@ -349,7 +349,7 @@ class DataMapper implements \TYPO3\CMS\Core\SingletonInterface public function fetchRelated(DomainObjectInterface $parentObject, $propertyName, $fieldValue = '', $enableLazyLoading = true) { $propertyMetaData = $this->reflectionService->getClassSchema(get_class($parentObject))->getProperty($propertyName); - if ($enableLazyLoading === true && $propertyMetaData['lazy']) { + if ($enableLazyLoading === true && $propertyMetaData['annotations']['lazy']) { if ($propertyMetaData['type'] === \TYPO3\CMS\Extbase\Persistence\ObjectStorage::class) { $result = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\LazyObjectStorage::class, $parentObject, $propertyName, $fieldValue); } else { diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Session.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Session.php index 2b56c98722327e8d7e54bcfc6b02e180c83db0a9..ab0351bc7ba0d477c4bec7e09c8c2e9ce8d8ef1a 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Session.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Session.php @@ -47,19 +47,6 @@ class Session implements \TYPO3\CMS\Core\SingletonInterface */ protected $identifierMap = []; - /** - * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService - */ - protected $reflectionService; - - /** - * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService - */ - public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService) - { - $this->reflectionService = $reflectionService; - } - /** * Constructs a new Session */ diff --git a/typo3/sysext/extbase/Classes/Reflection/ClassReflection.php b/typo3/sysext/extbase/Classes/Reflection/ClassReflection.php deleted file mode 100644 index 8adc6ebb91fa321759148bdef4f4031d88a2db54..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Classes/Reflection/ClassReflection.php +++ /dev/null @@ -1,187 +0,0 @@ -<?php -namespace TYPO3\CMS\Extbase\Reflection; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Extended version of the ReflectionClass - */ -class ClassReflection extends \ReflectionClass -{ - /** - * @var DocCommentParser Holds an instance of the doc comment parser for this class - */ - protected $docCommentParser; - - /** - * Replacement for the original getMethods() method which makes sure - * that \TYPO3\CMS\Extbase\Reflection\MethodReflection objects are returned instead of the - * original ReflectionMethod instances. - * - * @param int|NULL $filter A filter mask - * @return MethodReflection[] Method reflection objects of the methods in this class - */ - public function getMethods($filter = null) - { - $extendedMethods = []; - $methods = $filter === null ? parent::getMethods() : parent::getMethods($filter); - foreach ($methods as $method) { - $extendedMethods[] = new MethodReflection($this->getName(), $method->getName()); - } - return $extendedMethods; - } - - /** - * Replacement for the original getMethod() method which makes sure - * that \TYPO3\CMS\Extbase\Reflection\MethodReflection objects are returned instead of the - * original ReflectionMethod instances. - * - * @param string $name - * @return MethodReflection Method reflection object of the named method - */ - public function getMethod($name) - { - $parentMethod = parent::getMethod($name); - if (!is_object($parentMethod)) { - return $parentMethod; - } - return new MethodReflection($this->getName(), $parentMethod->getName()); - } - - /** - * Replacement for the original getConstructor() method which makes sure - * that \TYPO3\CMS\Extbase\Reflection\MethodReflection objects are returned instead of the - * original ReflectionMethod instances. - * - * @return MethodReflection Method reflection object of the constructor method - */ - public function getConstructor() - { - $parentConstructor = parent::getConstructor(); - if (!is_object($parentConstructor)) { - return $parentConstructor; - } - return new MethodReflection($this->getName(), $parentConstructor->getName()); - } - - /** - * Replacement for the original getProperties() method which makes sure - * that \TYPO3\CMS\Extbase\Reflection\PropertyReflection objects are returned instead of the - * original ReflectionProperty instances. - * - * @param int|NULL $filter A filter mask - * @return PropertyReflection[] Property reflection objects of the properties in this class - */ - public function getProperties($filter = null) - { - $extendedProperties = []; - $properties = $filter === null ? parent::getProperties() : parent::getProperties($filter); - foreach ($properties as $property) { - $extendedProperties[] = new PropertyReflection($this->getName(), $property->getName()); - } - return $extendedProperties; - } - - /** - * Replacement for the original getProperty() method which makes sure - * that a \TYPO3\CMS\Extbase\Reflection\PropertyReflection object is returned instead of the - * original ReflectionProperty instance. - * - * @param string $name Name of the property - * @return PropertyReflection Property reflection object of the specified property in this class - */ - public function getProperty($name) - { - return new PropertyReflection($this->getName(), $name); - } - - /** - * Replacement for the original getInterfaces() method which makes sure - * that \TYPO3\CMS\Extbase\Reflection\ClassReflection objects are returned instead of the - * original ReflectionClass instances. - * - * @return ClassReflection[] Class reflection objects of the properties in this class - */ - public function getInterfaces() - { - $extendedInterfaces = []; - $interfaces = parent::getInterfaces(); - foreach ($interfaces as $interface) { - $extendedInterfaces[] = new self($interface->getName()); - } - return $extendedInterfaces; - } - - /** - * Replacement for the original getParentClass() method which makes sure - * that a \TYPO3\CMS\Extbase\Reflection\ClassReflection object is returned instead of the - * original ReflectionClass instance. - * - * @return ClassReflection Reflection of the parent class - if any - */ - public function getParentClass() - { - $parentClass = parent::getParentClass(); - return $parentClass === false ? false : new self($parentClass->getName()); - } - - /** - * Checks if the doc comment of this method is tagged with - * the specified tag - * - * @param string $tag Tag name to check for - * @return bool TRUE if such a tag has been defined, otherwise FALSE - */ - public function isTaggedWith($tag) - { - $result = $this->getDocCommentParser()->isTaggedWith($tag); - return $result; - } - - /** - * Returns an array of tags and their values - * - * @return array Tags and values - */ - public function getTagsValues() - { - return $this->getDocCommentParser()->getTagsValues(); - } - - /** - * Returns the values of the specified tag - * - * @param string $tag - * @return array Values of the given tag - */ - public function getTagValues($tag) - { - return $this->getDocCommentParser()->getTagValues($tag); - } - - /** - * Returns an instance of the doc comment parser and - * runs the parse() method. - * - * @return DocCommentParser - */ - protected function getDocCommentParser() - { - if (!is_object($this->docCommentParser)) { - $this->docCommentParser = new DocCommentParser(); - $this->docCommentParser->parseDocComment($this->getDocComment()); - } - return $this->docCommentParser; - } -} diff --git a/typo3/sysext/extbase/Classes/Reflection/ClassSchema.php b/typo3/sysext/extbase/Classes/Reflection/ClassSchema.php index 5f8b37d5db0173fe02193b9512490940af4af999..e7ca5a3581bb499cbb61fda250cbed4c134dffed 100644 --- a/typo3/sysext/extbase/Classes/Reflection/ClassSchema.php +++ b/typo3/sysext/extbase/Classes/Reflection/ClassSchema.php @@ -14,11 +14,16 @@ namespace TYPO3\CMS\Extbase\Reflection; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\SingletonInterface; +use TYPO3\CMS\Core\Utility\ClassNamingUtility; +use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; +use TYPO3\CMS\Extbase\DomainObject\AbstractValueObject; use TYPO3\CMS\Extbase\Utility\TypeHandlingUtility; /** * A class schema * + * @internal * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later */ class ClassSchema @@ -71,14 +76,256 @@ class ClassSchema */ protected $identityProperties = []; + /** + * Indicates if the class is a singleton or not. + * + * @var bool + */ + private $isSingleton; + + /** + * @var array + */ + private $methods; + + /** + * @var array + */ + protected static $ignoredTags = ['package', 'subpackage', 'license', 'copyright', 'author', 'version', 'const']; + + /** + * @var array + */ + private $tags; + + /** + * @var array + */ + private $injectProperties = []; + + /** + * @var array + */ + private $injectMethods = []; + /** * Constructs this class schema * * @param string $className Name of the class this schema is referring to + * @throws \TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException + * @throws \ReflectionException */ public function __construct($className) { $this->className = $className; + + $reflectionClass = new \ReflectionClass($className); + + $this->isSingleton = $reflectionClass->implementsInterface(SingletonInterface::class); + + if ($reflectionClass->isSubclassOf(AbstractEntity::class)) { + $this->modelType = static::MODELTYPE_ENTITY; + + $possibleRepositoryClassName = ClassNamingUtility::translateModelNameToRepositoryName($className); + if (class_exists($possibleRepositoryClassName)) { + $this->setAggregateRoot(true); + } + } + + if ($reflectionClass->isSubclassOf(AbstractValueObject::class)) { + $this->modelType = static::MODELTYPE_VALUEOBJECT; + } + + $docCommentParser = new DocCommentParser(); + $docCommentParser->parseDocComment($reflectionClass->getDocComment()); + foreach ($docCommentParser->getTagsValues() as $tag => $values) { + if (in_array($tag, static::$ignoredTags, true)) { + continue; + } + + $this->tags[$tag] = $values; + } + + $this->reflectProperties($reflectionClass); + $this->reflectMethods($reflectionClass); + } + + /** + * @param \ReflectionClass $reflectionClass + */ + protected function reflectProperties(\ReflectionClass $reflectionClass) + { + foreach ($reflectionClass->getProperties() as $reflectionProperty) { + $propertyName = $reflectionProperty->getName(); + + $this->properties[$propertyName] = [ + 'default' => $reflectionProperty->isDefault(), + 'private' => $reflectionProperty->isPrivate(), + 'protected' => $reflectionProperty->isProtected(), + 'public' => $reflectionProperty->isPublic(), + 'static' => $reflectionProperty->isStatic(), + 'type' => null, // Extbase + 'elementType' => null, // Extbase + 'annotations' => [], + 'tags' => [] + ]; + + $docCommentParser = new DocCommentParser(); + $docCommentParser->parseDocComment($reflectionProperty->getDocComment()); + foreach ($docCommentParser->getTagsValues() as $tag => $values) { + if (in_array($tag, static::$ignoredTags, true)) { + continue; + } + + $this->properties[$propertyName]['tags'][$tag] = $values; + } + + $this->properties[$propertyName]['annotations']['inject'] = false; + $this->properties[$propertyName]['annotations']['lazy'] = $docCommentParser->isTaggedWith('lazy'); + $this->properties[$propertyName]['annotations']['transient'] = $docCommentParser->isTaggedWith('transient'); + $this->properties[$propertyName]['annotations']['type'] = null; + $this->properties[$propertyName]['annotations']['cascade'] = null; + $this->properties[$propertyName]['annotations']['dependency'] = null; + + if ($propertyName !== 'settings' && $docCommentParser->isTaggedWith('inject')) { + try { + $varValues = $docCommentParser->getTagValues('var'); + $this->properties[$propertyName]['annotations']['inject'] = true; + $this->properties[$propertyName]['annotations']['type'] = ltrim($varValues[0], '\\'); + $this->properties[$propertyName]['annotations']['dependency'] = ltrim($varValues[0], '\\'); + + $this->injectProperties[] = $propertyName; + } catch (\Exception $e) { + } + } + + if ($docCommentParser->isTaggedWith('var') && !$docCommentParser->isTaggedWith('transient')) { + try { + $cascadeAnnotationValues = $docCommentParser->getTagValues('cascade'); + $this->properties[$propertyName]['annotations']['cascade'] = $cascadeAnnotationValues[0]; + } catch (\Exception $e) { + } + + try { + $type = TypeHandlingUtility::parseType(implode(' ', $docCommentParser->getTagValues('var'))); + } catch (\Exception $e) { + $type = [ + 'type' => null, + 'elementType' => null + ]; + } + + $this->properties[$propertyName]['type'] = $type['type'] ? ltrim($type['type'], '\\') : null; + $this->properties[$propertyName]['elementType'] = $type['elementType'] ? ltrim($type['elementType'], '\\') : null; + } + + if ($docCommentParser->isTaggedWith('uuid')) { + $this->setUuidPropertyName($propertyName); + } + + if ($docCommentParser->isTaggedWith('identity')) { + $this->markAsIdentityProperty($propertyName); + } + } + } + + /** + * @param \ReflectionClass $reflectionClass + */ + protected function reflectMethods(\ReflectionClass $reflectionClass) + { + foreach ($reflectionClass->getMethods() as $reflectionMethod) { + $methodName = $reflectionMethod->getName(); + + $this->methods[$methodName] = []; + $this->methods[$methodName]['private'] = $reflectionMethod->isPrivate(); + $this->methods[$methodName]['protected'] = $reflectionMethod->isProtected(); + $this->methods[$methodName]['public'] = $reflectionMethod->isPublic(); + $this->methods[$methodName]['static'] = $reflectionMethod->isStatic(); + $this->methods[$methodName]['abstract'] = $reflectionMethod->isAbstract(); + $this->methods[$methodName]['params'] = []; + $this->methods[$methodName]['tags'] = []; + + $docCommentParser = new DocCommentParser(); + $docCommentParser->parseDocComment($reflectionMethod->getDocComment()); + foreach ($docCommentParser->getTagsValues() as $tag => $values) { + if (in_array($tag, static::$ignoredTags, true)) { + continue; + } + + $this->methods[$methodName]['tags'][$tag] = $values; + } + + $this->methods[$methodName]['description'] = $docCommentParser->getDescription(); + + foreach ($reflectionMethod->getParameters() as $parameterPosition => $reflectionParameter) { + /* @var $reflectionParameter \ReflectionParameter */ + + $parameterName = $reflectionParameter->getName(); + + $this->methods[$methodName]['params'][$parameterName] = []; + $this->methods[$methodName]['params'][$parameterName]['position'] = $parameterPosition; // compat + $this->methods[$methodName]['params'][$parameterName]['byReference'] = $reflectionParameter->isPassedByReference(); // compat + $this->methods[$methodName]['params'][$parameterName]['array'] = $reflectionParameter->isArray(); // compat + $this->methods[$methodName]['params'][$parameterName]['optional'] = $reflectionParameter->isOptional(); + $this->methods[$methodName]['params'][$parameterName]['allowsNull'] = $reflectionParameter->allowsNull(); // compat + $this->methods[$methodName]['params'][$parameterName]['class'] = null; // compat + $this->methods[$methodName]['params'][$parameterName]['type'] = null; + $this->methods[$methodName]['params'][$parameterName]['nullable'] = $reflectionParameter->allowsNull(); + $this->methods[$methodName]['params'][$parameterName]['default'] = null; + $this->methods[$methodName]['params'][$parameterName]['hasDefaultValue'] = $reflectionParameter->isDefaultValueAvailable(); + $this->methods[$methodName]['params'][$parameterName]['defaultValue'] = null; // compat + $this->methods[$methodName]['params'][$parameterName]['dependency'] = null; // Extbase DI + + if ($reflectionParameter->isDefaultValueAvailable()) { + $this->methods[$methodName]['params'][$parameterName]['default'] = $reflectionParameter->getDefaultValue(); + $this->methods[$methodName]['params'][$parameterName]['defaultValue'] = $reflectionParameter->getDefaultValue(); // compat + } + + if (($reflectionType = $reflectionParameter->getType()) instanceof \ReflectionType) { + $this->methods[$methodName]['params'][$parameterName]['type'] = (string)$reflectionType; + $this->methods[$methodName]['params'][$parameterName]['nullable'] = $reflectionType->allowsNull(); + } + + if (($parameterClass = $reflectionParameter->getClass()) instanceof \ReflectionClass) { + $this->methods[$methodName]['params'][$parameterName]['class'] = $parameterClass->getName(); + $this->methods[$methodName]['params'][$parameterName]['type'] = ltrim($parameterClass->getName(), '\\'); + } else { + $methodTagsAndValues = $this->methods[$methodName]['tags']; + if (isset($methodTagsAndValues['param'], $methodTagsAndValues['param'][$parameterPosition])) { + $explodedParameters = explode(' ', $methodTagsAndValues['param'][$parameterPosition]); + if (count($explodedParameters) >= 2) { + if (TypeHandlingUtility::isSimpleType($explodedParameters[0])) { + // ensure that short names of simple types are resolved correctly to the long form + // this is important for all kinds of type checks later on + $typeInfo = TypeHandlingUtility::parseType($explodedParameters[0]); + + $this->methods[$methodName]['params'][$parameterName]['type'] = ltrim($typeInfo['type'], '\\'); + } else { + $this->methods[$methodName]['params'][$parameterName]['type'] = ltrim($explodedParameters[0], '\\'); + } + } + } + } + + // Extbase DI + if ($reflectionParameter->getClass() instanceof \ReflectionClass + && ($reflectionMethod->isConstructor() || $this->hasInjectMethodName($reflectionMethod)) + ) { + $this->methods[$methodName]['params'][$parameterName]['dependency'] = $reflectionParameter->getClass()->getName(); + } + } + + // Extbase + $this->methods[$methodName]['injectMethod'] = false; + if ($this->hasInjectMethodName($reflectionMethod) + && count($this->methods[$methodName]['params']) === 1 + && reset($this->methods[$methodName]['params'])['dependency'] !== null + ) { + $this->methods[$methodName]['injectMethod'] = true; + $this->injectMethods[] = $methodName; + } + } } /** @@ -86,7 +333,7 @@ class ClassSchema * * @return string The class name */ - public function getClassName() + public function getClassName(): string { return $this->className; } @@ -98,9 +345,14 @@ class ClassSchema * @param string $type Type of the property * @param bool $lazy Whether the property should be lazy-loaded when reconstituting * @param string $cascade Strategy to cascade the object graph. + * @deprecated */ public function addProperty($name, $type, $lazy = false, $cascade = '') { + trigger_error( + 'This method will be removed in TYPO3 v10.0, properties will be automatically added on ClassSchema construction.', + E_USER_DEPRECATED + ); $type = TypeHandlingUtility::parseType($type); $this->properties[$name] = [ 'type' => $type['type'], @@ -137,9 +389,14 @@ class ClassSchema * * @param int $modelType The model type, one of the MODELTYPE_* constants. * @throws \InvalidArgumentException + * @deprecated */ public function setModelType($modelType) { + trigger_error( + 'This method will be removed in TYPO3 v10.0, modelType will be automatically set on ClassSchema construction.', + E_USER_DEPRECATED + ); if ($modelType < self::MODELTYPE_ENTITY || $modelType > self::MODELTYPE_VALUEOBJECT) { throw new \InvalidArgumentException('"' . $modelType . '" is an invalid model type.', 1212519195); } @@ -150,9 +407,14 @@ class ClassSchema * Returns the model type of the class this schema is referring to. * * @return int The model type, one of the MODELTYPE_* constants. + * @deprecated */ public function getModelType() { + trigger_error( + 'This method will be removed in TYPO3 v10.0.', + E_USER_DEPRECATED + ); return $this->modelType; } @@ -173,7 +435,7 @@ class ClassSchema * * @return bool TRUE if it is managed */ - public function isAggregateRoot() + public function isAggregateRoot(): bool { return $this->aggregateRoot; } @@ -184,7 +446,7 @@ class ClassSchema * @param string $propertyName Name of the property * @return bool */ - public function hasProperty($propertyName) + public function hasProperty($propertyName): bool { return array_key_exists($propertyName, $this->properties); } @@ -194,9 +456,14 @@ class ClassSchema * * @param string $propertyName * @throws \InvalidArgumentException + * @deprecated */ public function setUuidPropertyName($propertyName) { + trigger_error( + 'Tagging properties with @uuid is deprecated and will be removed in TYPO3 v10.0.', + E_USER_DEPRECATED + ); if (!array_key_exists($propertyName, $this->properties)) { throw new \InvalidArgumentException('Property "' . $propertyName . '" must be added to the class schema before it can be marked as UUID property.', 1233863842); } @@ -207,9 +474,14 @@ class ClassSchema * Gets the name of the property marked as uuid of an object * * @return string + * @deprecated */ public function getUuidPropertyName() { + trigger_error( + 'Tagging properties with @uuid is deprecated and will be removed in TYPO3 v10.0.', + E_USER_DEPRECATED + ); return $this->uuidPropertyName; } @@ -220,13 +492,18 @@ class ClassSchema * * @param string $propertyName * @throws \InvalidArgumentException + * @deprecated */ public function markAsIdentityProperty($propertyName) { + trigger_error( + 'Tagging properties with @identity is deprecated and will be removed in TYPO3 v10.0.', + E_USER_DEPRECATED + ); if (!array_key_exists($propertyName, $this->properties)) { throw new \InvalidArgumentException('Property "' . $propertyName . '" must be added to the class schema before it can be marked as identity property.', 1233775407); } - if ($this->properties[$propertyName]['lazy'] === true) { + if ($this->properties[$propertyName]['annotations']['lazy'] === true) { throw new \InvalidArgumentException('Property "' . $propertyName . '" must not be makred for lazy loading to be marked as identity property.', 1239896904); } $this->identityProperties[$propertyName] = $this->properties[$propertyName]['type']; @@ -237,9 +514,165 @@ class ClassSchema * * @return array * @see markAsIdentityProperty() + * @deprecated */ public function getIdentityProperties() { + trigger_error( + 'Tagging properties with @identity is deprecated and will be removed in TYPO3 v10.0.', + E_USER_DEPRECATED + ); return $this->identityProperties; } + + /** + * @return bool + */ + public function hasConstructor(): bool + { + return isset($this->methods['__construct']); + } + + /** + * @param string $name + * @return array + */ + public function getMethod(string $name): array + { + return $this->methods[$name] ?? []; + } + + /** + * @return array + */ + public function getMethods(): array + { + return $this->methods; + } + + /** + * @param \ReflectionMethod $reflectionMethod + * @return bool + */ + protected function hasInjectMethodName(\ReflectionMethod $reflectionMethod): bool + { + $methodName = $reflectionMethod->getName(); + if ($methodName === 'injectSettings' || !$reflectionMethod->isPublic()) { + return false; + } + + if ( + strpos($reflectionMethod->getName(), 'inject') === 0 + ) { + return true; + } + + return false; + } + + /** + * @return bool + * @internal + */ + public function isModel(): bool + { + return $this->isEntity() || $this->isValueObject(); + } + + /** + * @return bool + * @internal + */ + public function isEntity(): bool + { + return $this->modelType === static::MODELTYPE_ENTITY; + } + + /** + * @return bool + * @internal + */ + public function isValueObject(): bool + { + return $this->modelType === static::MODELTYPE_VALUEOBJECT; + } + + /** + * @return bool + */ + public function isSingleton(): bool + { + return $this->isSingleton; + } + + /** + * @param string $methodName + * @return bool + */ + public function hasMethod(string $methodName): bool + { + return isset($this->methods[$methodName]); + } + + /** + * @return array + */ + public function getTags(): array + { + return $this->tags; + } + + /** + * @return bool + */ + public function hasInjectProperties(): bool + { + return count($this->injectProperties) > 0; + } + + /** + * @return bool + */ + public function hasInjectMethods(): bool + { + return count($this->injectMethods) > 0; + } + + /** + * @return array + */ + public function getInjectMethods(): array + { + $injectMethods = []; + foreach ($this->injectMethods as $injectMethodName) { + $injectMethods[$injectMethodName] = reset($this->methods[$injectMethodName]['params'])['dependency']; + } + + return $injectMethods; + } + + /** + * @return array + */ + public function getInjectProperties(): array + { + $injectProperties = []; + foreach ($this->injectProperties as $injectPropertyName) { + $injectProperties[$injectPropertyName] = $this->properties[$injectPropertyName]['annotations']['dependency']; + } + + return $injectProperties; + } + + /** + * @return array + */ + public function getConstructorArguments(): array + { + if (!$this->hasConstructor()) { + return []; + } + + return $this->methods['__construct']['params']; + } } diff --git a/typo3/sysext/extbase/Classes/Reflection/MethodReflection.php b/typo3/sysext/extbase/Classes/Reflection/MethodReflection.php deleted file mode 100644 index fbd00f50614861b511a11020d18b2e0e8233a0b7..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Classes/Reflection/MethodReflection.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php -namespace TYPO3\CMS\Extbase\Reflection; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Extended version of the ReflectionMethod - */ -class MethodReflection extends \ReflectionMethod -{ - /** - * @var DocCommentParser An instance of the doc comment parser - */ - protected $docCommentParser; - - /** - * Returns the declaring class - * - * @return ClassReflection The declaring class - */ - public function getDeclaringClass() - { - return new ClassReflection(parent::getDeclaringClass()->getName()); - } - - /** - * Replacement for the original getParameters() method which makes sure - * that \TYPO3\CMS\Extbase\Reflection\ParameterReflection objects are returned instead of the - * original ReflectionParameter instances. - * - * @return ParameterReflection[] Parameter reflection objects of the parameters of this method - */ - public function getParameters() - { - $extendedParameters = []; - foreach (parent::getParameters() as $parameter) { - $extendedParameters[] = new ParameterReflection([$this->getDeclaringClass()->getName(), $this->getName()], $parameter->getName()); - } - return $extendedParameters; - } - - /** - * Checks if the doc comment of this method is tagged with - * the specified tag - * - * @param string $tag Tag name to check for - * @return bool TRUE if such a tag has been defined, otherwise FALSE - */ - public function isTaggedWith($tag) - { - $result = $this->getDocCommentParser()->isTaggedWith($tag); - return $result; - } - - /** - * Returns an array of tags and their values - * - * @return array Tags and values - */ - public function getTagsValues() - { - return $this->getDocCommentParser()->getTagsValues(); - } - - /** - * Returns the values of the specified tag - * - * @param string $tag Tag name to check for - * @return array Values of the given tag - */ - public function getTagValues($tag) - { - return $this->getDocCommentParser()->getTagValues($tag); - } - - /** - * Returns the description part of the doc comment - * - * @return string Doc comment description - */ - public function getDescription() - { - return $this->getDocCommentParser()->getDescription(); - } - - /** - * Returns an instance of the doc comment parser and - * runs the parse() method. - * - * @return DocCommentParser - */ - protected function getDocCommentParser() - { - if (!is_object($this->docCommentParser)) { - $this->docCommentParser = new DocCommentParser(); - $this->docCommentParser->parseDocComment($this->getDocComment()); - } - return $this->docCommentParser; - } -} diff --git a/typo3/sysext/extbase/Classes/Reflection/ObjectAccess.php b/typo3/sysext/extbase/Classes/Reflection/ObjectAccess.php index 3152ff5c4b577f6c664e479cfad43340221e58fd..1d9c5008275839a83b8626c5919600842b78faff 100644 --- a/typo3/sysext/extbase/Classes/Reflection/ObjectAccess.php +++ b/typo3/sysext/extbase/Classes/Reflection/ObjectAccess.php @@ -96,7 +96,11 @@ class ObjectAccess } elseif (is_object($subject)) { if ($forceDirectAccess) { if (property_exists($subject, $propertyName)) { - $propertyReflection = new PropertyReflection($subject, $propertyName); + $propertyReflection = new \ReflectionProperty($subject, $propertyName); + if ($propertyReflection->isPublic()) { + return $propertyReflection->getValue($subject); + } + $propertyReflection->setAccessible(true); return $propertyReflection->getValue($subject); } throw new Exception\PropertyNotAccessibleException('The property "' . $propertyName . '" on the subject does not exist.', 1302855001); @@ -183,7 +187,7 @@ class ObjectAccess $result = true; if ($forceDirectAccess) { if (property_exists($subject, $propertyName)) { - $propertyReflection = new PropertyReflection($subject, $propertyName); + $propertyReflection = new \ReflectionProperty($subject, $propertyName); $propertyReflection->setAccessible(true); $propertyReflection->setValue($subject, $propertyValue); } else { @@ -195,7 +199,7 @@ class ObjectAccess if (is_callable([$subject, $setterMethodName])) { $subject->{$setterMethodName}($propertyValue); } elseif (property_exists($subject, $propertyName)) { - $reflection = new PropertyReflection($subject, $propertyName); + $reflection = new \ReflectionProperty($subject, $propertyName); if ($reflection->isPublic()) { $subject->{$propertyName} = $propertyValue; } else { @@ -348,7 +352,7 @@ class ObjectAccess return true; } if (property_exists($object, $propertyName)) { - $propertyReflection = new PropertyReflection($object, $propertyName); + $propertyReflection = new \ReflectionProperty($object, $propertyName); return $propertyReflection->isPublic(); } return false; diff --git a/typo3/sysext/extbase/Classes/Reflection/ParameterReflection.php b/typo3/sysext/extbase/Classes/Reflection/ParameterReflection.php deleted file mode 100644 index 7dc7fd41c4eff22ab7ce75f0a44d6d3cef9593e5..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Classes/Reflection/ParameterReflection.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -namespace TYPO3\CMS\Extbase\Reflection; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Extended version of the ReflectionParameter - */ -class ParameterReflection extends \ReflectionParameter -{ - /** - * Returns the declaring class - * - * @return ClassReflection The declaring class - */ - public function getDeclaringClass() - { - return new ClassReflection(parent::getDeclaringClass()->getName()); - } - - /** - * Returns the parameter class - * - * @return ClassReflection The parameter class - */ - public function getClass() - { - try { - $class = parent::getClass(); - } catch (\Exception $e) { - return null; - } - return is_object($class) ? new ClassReflection($class->getName()) : null; - } -} diff --git a/typo3/sysext/extbase/Classes/Reflection/PropertyReflection.php b/typo3/sysext/extbase/Classes/Reflection/PropertyReflection.php deleted file mode 100644 index d107dbb16d060f0a571587ee5c86979853194bb4..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Classes/Reflection/PropertyReflection.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php -namespace TYPO3\CMS\Extbase\Reflection; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Extended version of the ReflectionProperty - */ -class PropertyReflection extends \ReflectionProperty -{ - /** - * @var DocCommentParser An instance of the doc comment parser - */ - protected $docCommentParser; - - /** - * Checks if the doc comment of this property is tagged with - * the specified tag - * - * @param string $tag Tag name to check for - * @return bool TRUE if such a tag has been defined, otherwise FALSE - */ - public function isTaggedWith($tag) - { - $result = $this->getDocCommentParser()->isTaggedWith($tag); - return $result; - } - - /** - * Returns an array of tags and their values - * - * @return array Tags and values - */ - public function getTagsValues() - { - return $this->getDocCommentParser()->getTagsValues(); - } - - /** - * Returns the values of the specified tag - * - * @param string $tag - * @return array Values of the given tag - */ - public function getTagValues($tag) - { - return $this->getDocCommentParser()->getTagValues($tag); - } - - /** - * Returns the value of the reflected property - even if it is protected. - * - * @param object $object Instance of the declaring class \TYPO3\CMS\Extbase\Reflection to read the value from - * @return mixed Value of the property - * @throws Exception - * @todo Maybe support private properties as well, as of PHP 5.3.0 we can do - */ - public function getValue($object = null) - { - if (!is_object($object)) { - throw new Exception('$object is of type ' . gettype($object) . ', instance of class ' . $this->class . ' expected.', 1210859212); - } - if ($this->isPublic()) { - return parent::getValue($object); - } - if ($this->isPrivate()) { - throw new Exception('Cannot return value of private property "' . $this->name . '.', 1210859206); - } - parent::setAccessible(true); - return parent::getValue($object); - } - - /** - * Returns an instance of the doc comment parser and - * runs the parse() method. - * - * @return DocCommentParser - */ - protected function getDocCommentParser() - { - if (!is_object($this->docCommentParser)) { - $this->docCommentParser = new DocCommentParser(); - $this->docCommentParser->parseDocComment($this->getDocComment()); - } - return $this->docCommentParser; - } -} diff --git a/typo3/sysext/extbase/Classes/Reflection/ReflectionService.php b/typo3/sysext/extbase/Classes/Reflection/ReflectionService.php index 06a284282f0497d5b5a59bdb62ce49f189d92814..14957f4f2d131a9f9aec92814ef56dd6a62e5150 100644 --- a/typo3/sysext/extbase/Classes/Reflection/ReflectionService.php +++ b/typo3/sysext/extbase/Classes/Reflection/ReflectionService.php @@ -14,114 +14,31 @@ namespace TYPO3\CMS\Extbase\Reflection; * The TYPO3 project - inspiring people to share! */ -use TYPO3\CMS\Core\Utility\ClassNamingUtility; -use TYPO3\CMS\Extbase\Utility\TypeHandlingUtility; +use TYPO3\CMS\Core\Cache\CacheManager; +use TYPO3\CMS\Core\SingletonInterface; /** - * A backport of the TYPO3.Flow reflection service for acquiring reflection based information. - * Most of the code is based on the TYPO3.Flow reflection service. + * Reflection service for acquiring reflection based information. + * Originally based on the TYPO3.Flow reflection service. * * @api */ -class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface +class ReflectionService implements SingletonInterface { - /** - * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface - */ - protected $objectManager; - - /** - * Whether this service has been initialized. - * - * @var bool - */ - protected $initialized = false; + const CACHE_IDENTIFIER = 'extbase_reflection'; + const CACHE_ENTRY_IDENTIFIER = 'ClassSchematas'; /** * @var \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend */ protected $dataCache; - /** - * Whether class alterations should be detected on each initialization. - * - * @var bool - */ - protected $detectClassChanges = false; - - /** - * All available class names to consider. Class name = key, value is the - * UNIX timestamp the class was reflected. - * - * @var array - */ - protected $reflectedClassNames = []; - - /** - * Array of tags and the names of classes which are tagged with them. - * - * @var array - */ - protected $taggedClasses = []; - - /** - * Array of class names and their tags and values. - * - * @var array - */ - protected $classTagsValues = []; - - /** - * Array of class names, method names and their tags and values. - * - * @var array - */ - protected $methodTagsValues = []; - - /** - * Array of class names, method names, their parameters and additional - * information about the parameters. - * - * @var array - */ - protected $methodParameters = []; - - /** - * Array of class names and names of their properties. - * - * @var array - */ - protected $classPropertyNames = []; - - /** - * Array of class names and names of their methods. - * - * @var array - */ - protected $classMethodNames = []; - - /** - * Array of class names, property names and their tags and values. - * - * @var array - */ - protected $propertyTagsValues = []; - - /** - * List of tags which are ignored while reflecting class and method annotations. - * - * @var array - */ - protected $ignoredTags = ['package', 'subpackage', 'license', 'copyright', 'author', 'version', 'const']; - /** * Indicates whether the Reflection cache needs to be updated. * * This flag needs to be set as soon as new Reflection information was * created. * - * @see reflectClass() - * @see getMethodReflection() * @var bool */ protected $dataCacheNeedsUpdate = false; @@ -134,85 +51,33 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface protected $classSchemata = []; /** - * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface - */ - protected $configurationManager; - - /** - * @var string - */ - protected $cacheIdentifier; - - /** - * Internal runtime cache of method reflection objects - * - * @var array - */ - protected $methodReflections = []; - - /** - * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager + * @var bool */ - public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) - { - $this->objectManager = $objectManager; - } + private $cachingEnabled = false; /** - * @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager - */ - public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager) - { - $this->configurationManager = $configurationManager; - } - - /** - * Sets the data cache. - * - * The cache must be set before initializing the Reflection Service. + * If not $cacheManager is injected, the reflection service does not + * cache any data, useful for testing this service in unit tests. * - * @param \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend $dataCache Cache for the Reflection service + * @param CacheManager $cacheManager */ - public function setDataCache(\TYPO3\CMS\Core\Cache\Frontend\VariableFrontend $dataCache) + public function __construct(\TYPO3\CMS\Core\Cache\CacheManager $cacheManager = null) { - $this->dataCache = $dataCache; - } + if ($cacheManager instanceof CacheManager && $cacheManager->hasCache(static::CACHE_IDENTIFIER)) { + $this->cachingEnabled = true; + $this->dataCache = $cacheManager->getCache(static::CACHE_IDENTIFIER); - /** - * Initializes this service - * - * @throws Exception - */ - public function initialize() - { - if ($this->initialized) { - throw new Exception('The Reflection Service can only be initialized once.', 1232044696); + if (($classSchemata = $this->dataCache->has(static::CACHE_ENTRY_IDENTIFIER)) !== false) { + $this->classSchemata = $this->dataCache->get(static::CACHE_ENTRY_IDENTIFIER); + } } - $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); - $this->cacheIdentifier = 'ReflectionData_' . $frameworkConfiguration['extensionName']; - $this->loadFromCache(); - $this->initialized = true; } - /** - * Returns whether the Reflection Service is initialized. - * - * @return bool true if the Reflection Service is initialized, otherwise false - */ - public function isInitialized() - { - return $this->initialized; - } - - /** - * Shuts the Reflection Service down. - */ - public function shutdown() + public function __destruct() { - if ($this->dataCacheNeedsUpdate) { - $this->saveToCache(); + if ($this->dataCacheNeedsUpdate && $this->cachingEnabled) { + $this->dataCache->set(static::CACHE_ENTRY_IDENTIFIER, $this->classSchemata); } - $this->initialized = false; } /** @@ -221,15 +86,9 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $className Name of the class * @return array An array of tags and their values or an empty array if no tags were found */ - public function getClassTagsValues($className) + public function getClassTagsValues($className): array { - if (!isset($this->reflectedClassNames[$className])) { - $this->reflectClass($className); - } - if (!isset($this->classTagsValues[$className])) { - return []; - } - return isset($this->classTagsValues[$className]) ? $this->classTagsValues[$className] : []; + return $this->getClassSchema($className)->getTags(); } /** @@ -239,15 +98,9 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $tag Tag to return the values of * @return array An array of values or an empty array if the tag was not found */ - public function getClassTagValues($className, $tag) + public function getClassTagValues($className, $tag): array { - if (!isset($this->reflectedClassNames[$className])) { - $this->reflectClass($className); - } - if (!isset($this->classTagsValues[$className])) { - return []; - } - return isset($this->classTagsValues[$className][$tag]) ? $this->classTagsValues[$className][$tag] : []; + return $this->getClassSchema($className)->getTags()[$tag]; } /** @@ -256,12 +109,9 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $className Name of the class to return the property names of * @return array An array of property names or an empty array if none exist */ - public function getClassPropertyNames($className) + public function getClassPropertyNames($className): array { - if (!isset($this->reflectedClassNames[$className])) { - $this->reflectClass($className); - } - return isset($this->classPropertyNames[$className]) ? $this->classPropertyNames[$className] : []; + return array_keys($this->getClassSchema($className)->getProperties()); } /** @@ -269,13 +119,16 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * * @param mixed $classNameOrObject The class name or an object * @return ClassSchema + * @throws \TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException + * @throws \ReflectionException */ - public function getClassSchema($classNameOrObject) + public function getClassSchema($classNameOrObject): ClassSchema { $className = is_object($classNameOrObject) ? get_class($classNameOrObject) : $classNameOrObject; if (isset($this->classSchemata[$className])) { return $this->classSchemata[$className]; } + return $this->buildClassSchema($className); } @@ -286,18 +139,9 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $methodName Name of the method * @return bool */ - public function hasMethod($className, $methodName) + public function hasMethod($className, $methodName): bool { - try { - if (!array_key_exists($className, $this->classMethodNames) || !array_key_exists($methodName, $this->classMethodNames[$className])) { - $this->getMethodReflection($className, $methodName); - $this->classMethodNames[$className][$methodName] = true; - } - } catch (\ReflectionException $e) { - // Method does not exist. Store this information in cache. - $this->classMethodNames[$className][$methodName] = null; - } - return isset($this->classMethodNames[$className][$methodName]); + return $this->getClassSchema($className)->hasMethod($methodName); } /** @@ -307,18 +151,9 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $methodName Name of the method to return the tags and values of * @return array An array of tags and their values or an empty array of no tags were found */ - public function getMethodTagsValues($className, $methodName) + public function getMethodTagsValues($className, $methodName): array { - if (!isset($this->methodTagsValues[$className][$methodName])) { - $method = $this->getMethodReflection($className, $methodName); - $this->methodTagsValues[$className][$methodName] = []; - foreach ($method->getTagsValues() as $tag => $values) { - if (array_search($tag, $this->ignoredTags) === false) { - $this->methodTagsValues[$className][$methodName][$tag] = $values; - } - } - } - return $this->methodTagsValues[$className][$methodName]; + return $this->getClassSchema($className)->getMethod($methodName)['tags']; } /** @@ -329,16 +164,9 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $methodName Name of the method to return parameter information of * @return array An array of parameter names and additional information or an empty array of no parameters were found */ - public function getMethodParameters($className, $methodName) + public function getMethodParameters($className, $methodName): array { - if (!isset($this->methodParameters[$className][$methodName])) { - $method = $this->getMethodReflection($className, $methodName); - $this->methodParameters[$className][$methodName] = []; - foreach ($method->getParameters() as $parameterPosition => $parameter) { - $this->methodParameters[$className][$methodName][$parameter->getName()] = $this->convertParameterReflectionToArray($parameter, $parameterPosition, $method); - } - } - return $this->methodParameters[$className][$methodName]; + return $this->getClassSchema($className)->getMethod($methodName)['params']; } /** @@ -348,15 +176,9 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $propertyName Name of the property to return the tags and values of * @return array An array of tags and their values or an empty array of no tags were found */ - public function getPropertyTagsValues($className, $propertyName) + public function getPropertyTagsValues($className, $propertyName): array { - if (!isset($this->reflectedClassNames[$className])) { - $this->reflectClass($className); - } - if (!isset($this->propertyTagsValues[$className])) { - return []; - } - return isset($this->propertyTagsValues[$className][$propertyName]) ? $this->propertyTagsValues[$className][$propertyName] : []; + return $this->getClassSchema($className)->getProperty($propertyName)['tags']; } /** @@ -367,27 +189,13 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $tag Tag to return the values of * @return array An array of values or an empty array if the tag was not found */ - public function getPropertyTagValues($className, $propertyName, $tag) + public function getPropertyTagValues($className, $propertyName, $tag): array { - if (!isset($this->reflectedClassNames[$className])) { - $this->reflectClass($className); - } - if (!isset($this->propertyTagsValues[$className][$propertyName])) { + if (!$this->isPropertyTaggedWith($className, $propertyName, $tag)) { return []; } - return isset($this->propertyTagsValues[$className][$propertyName][$tag]) ? $this->propertyTagsValues[$className][$propertyName][$tag] : []; - } - /** - * Tells if the specified class is known to this reflection service and - * reflection information is available. - * - * @param string $className Name of the class - * @return bool If the class is reflected by this service - */ - public function isClassReflected($className) - { - return isset($this->reflectedClassNames[$className]); + return $this->getClassSchema($className)->getProperty($propertyName)['tags'][$tag]; } /** @@ -397,18 +205,15 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $tag Tag to check for * @return bool TRUE if the class is tagged with $tag, otherwise FALSE */ - public function isClassTaggedWith($className, $tag) + public function isClassTaggedWith($className, $tag): bool { - if ($this->initialized === false) { - return false; - } - if (!isset($this->reflectedClassNames[$className])) { - $this->reflectClass($className); - } - if (!isset($this->classTagsValues[$className])) { - return false; + foreach (array_keys($this->getClassSchema($className)->getTags()) as $tagName) { + if ($tagName === $tag) { + return true; + } } - return isset($this->classTagsValues[$className][$tag]); + + return false; } /** @@ -419,57 +224,21 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $tag Tag to check for * @return bool TRUE if the class property is tagged with $tag, otherwise FALSE */ - public function isPropertyTaggedWith($className, $propertyName, $tag) + public function isPropertyTaggedWith($className, $propertyName, $tag): bool { - if (!isset($this->reflectedClassNames[$className])) { - $this->reflectClass($className); - } - if (!isset($this->propertyTagsValues[$className])) { + try { + $classSchema = $this->getClassSchema($className); + } catch (\Exception $e) { return false; } - if (!isset($this->propertyTagsValues[$className][$propertyName])) { + + $property = $classSchema->getProperty($propertyName); + + if (empty($property)) { return false; } - return isset($this->propertyTagsValues[$className][$propertyName][$tag]); - } - /** - * Reflects the given class and stores the results in this service's properties. - * - * @param string $className Full qualified name of the class to reflect - */ - protected function reflectClass($className) - { - $class = new ClassReflection($className); - $this->reflectedClassNames[$className] = time(); - foreach ($class->getTagsValues() as $tag => $values) { - if (array_search($tag, $this->ignoredTags) === false) { - $this->taggedClasses[$tag][] = $className; - $this->classTagsValues[$className][$tag] = $values; - } - } - foreach ($class->getProperties() as $property) { - $propertyName = $property->getName(); - $this->classPropertyNames[$className][] = $propertyName; - foreach ($property->getTagsValues() as $tag => $values) { - if (array_search($tag, $this->ignoredTags) === false) { - $this->propertyTagsValues[$className][$propertyName][$tag] = $values; - } - } - } - foreach ($class->getMethods() as $method) { - $methodName = $method->getName(); - foreach ($method->getTagsValues() as $tag => $values) { - if (array_search($tag, $this->ignoredTags) === false) { - $this->methodTagsValues[$className][$methodName][$tag] = $values; - } - } - foreach ($method->getParameters() as $parameterPosition => $parameter) { - $this->methodParameters[$className][$methodName][$parameter->getName()] = $this->convertParameterReflectionToArray($parameter, $parameterPosition, $method); - } - } - ksort($this->reflectedClassNames); - $this->dataCacheNeedsUpdate = true; + return isset($property['tags'][$tag]); } /** @@ -478,140 +247,17 @@ class ReflectionService implements \TYPO3\CMS\Core\SingletonInterface * @param string $className * @throws Exception\UnknownClassException * @return ClassSchema The class schema + * @throws \ReflectionException */ - protected function buildClassSchema($className) + protected function buildClassSchema($className): ClassSchema { if (!class_exists($className)) { throw new Exception\UnknownClassException('The classname "' . $className . '" was not found and thus can not be reflected.', 1278450972); } - $classSchema = $this->objectManager->get(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class, $className); - if (is_subclass_of($className, \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class)) { - $classSchema->setModelType(ClassSchema::MODELTYPE_ENTITY); - $possibleRepositoryClassName = ClassNamingUtility::translateModelNameToRepositoryName($className); - if (class_exists($possibleRepositoryClassName)) { - $classSchema->setAggregateRoot(true); - } - } elseif (is_subclass_of($className, \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject::class)) { - $classSchema->setModelType(ClassSchema::MODELTYPE_VALUEOBJECT); - } - foreach ($this->getClassPropertyNames($className) as $propertyName) { - if (!$this->isPropertyTaggedWith($className, $propertyName, 'transient') && $this->isPropertyTaggedWith($className, $propertyName, 'var')) { - $cascadeTagValues = $this->getPropertyTagValues($className, $propertyName, 'cascade'); - $classSchema->addProperty($propertyName, implode(' ', $this->getPropertyTagValues($className, $propertyName, 'var')), $this->isPropertyTaggedWith($className, $propertyName, 'lazy'), $cascadeTagValues[0]); - } - if ($this->isPropertyTaggedWith($className, $propertyName, 'uuid')) { - $classSchema->setUuidPropertyName($propertyName); - } - if ($this->isPropertyTaggedWith($className, $propertyName, 'identity')) { - $classSchema->markAsIdentityProperty($propertyName); - } - } + + $classSchema = new ClassSchema($className); $this->classSchemata[$className] = $classSchema; $this->dataCacheNeedsUpdate = true; return $classSchema; } - - /** - * Converts the given parameter reflection into an information array - * - * @param ParameterReflection $parameter The parameter to reflect - * @param int $parameterPosition - * @param MethodReflection|NULL $method - * @return array Parameter information array - */ - protected function convertParameterReflectionToArray(ParameterReflection $parameter, $parameterPosition, MethodReflection $method = null) - { - $parameterInformation = [ - 'position' => $parameterPosition, - 'byReference' => $parameter->isPassedByReference(), - 'array' => $parameter->isArray(), - 'optional' => $parameter->isOptional(), - 'allowsNull' => $parameter->allowsNull() - ]; - $parameterClass = $parameter->getClass(); - $parameterInformation['class'] = $parameterClass !== null ? $parameterClass->getName() : null; - if ($parameter->isDefaultValueAvailable()) { - $parameterInformation['defaultValue'] = $parameter->getDefaultValue(); - } - if ($parameterClass !== null) { - $parameterInformation['type'] = $parameterClass->getName(); - } elseif ($method !== null) { - $methodTagsAndValues = $this->getMethodTagsValues($method->getDeclaringClass()->getName(), $method->getName()); - if (isset($methodTagsAndValues['param']) && isset($methodTagsAndValues['param'][$parameterPosition])) { - $explodedParameters = explode(' ', $methodTagsAndValues['param'][$parameterPosition]); - if (count($explodedParameters) >= 2) { - if (TypeHandlingUtility::isSimpleType($explodedParameters[0])) { - // ensure that short names of simple types are resolved correctly to the long form - // this is important for all kinds of type checks later on - $typeInfo = TypeHandlingUtility::parseType($explodedParameters[0]); - $parameterInformation['type'] = $typeInfo['type']; - } else { - $parameterInformation['type'] = $explodedParameters[0]; - } - } - } - } - if (isset($parameterInformation['type']) && $parameterInformation['type'][0] === '\\') { - $parameterInformation['type'] = substr($parameterInformation['type'], 1); - } - return $parameterInformation; - } - - /** - * Returns the Reflection of a method. - * - * @param string $className Name of the class containing the method - * @param string $methodName Name of the method to return the Reflection for - * @return MethodReflection the method Reflection object - */ - protected function getMethodReflection($className, $methodName) - { - $this->dataCacheNeedsUpdate = true; - if (!isset($this->methodReflections[$className][$methodName])) { - $this->methodReflections[$className][$methodName] = new MethodReflection($className, $methodName); - } - return $this->methodReflections[$className][$methodName]; - } - - /** - * Tries to load the reflection data from this service's cache. - */ - protected function loadFromCache() - { - $data = $this->dataCache->get($this->cacheIdentifier); - if ($data !== false) { - foreach ($data as $propertyName => $propertyValue) { - $this->{$propertyName} = $propertyValue; - } - } - } - - /** - * Exports the internal reflection data into the ReflectionData cache. - * - * @throws Exception - */ - protected function saveToCache() - { - if (!is_object($this->dataCache)) { - throw new Exception('A cache must be injected before initializing the Reflection Service.', 1232044697); - } - $data = []; - $propertyNames = [ - 'reflectedClassNames', - 'classPropertyNames', - 'classMethodNames', - 'classTagsValues', - 'methodTagsValues', - 'methodParameters', - 'propertyTagsValues', - 'taggedClasses', - 'classSchemata' - ]; - foreach ($propertyNames as $propertyName) { - $data[$propertyName] = $this->{$propertyName}; - } - $this->dataCache->set($this->cacheIdentifier, $data); - $this->dataCacheNeedsUpdate = false; - } } diff --git a/typo3/sysext/extbase/Classes/Scheduler/TaskExecutor.php b/typo3/sysext/extbase/Classes/Scheduler/TaskExecutor.php index cace8572034586c8b90f623b3e2e7f02e533f7bf..85d38be9403907abcbd319720fa1e55ffb325d74 100644 --- a/typo3/sysext/extbase/Classes/Scheduler/TaskExecutor.php +++ b/typo3/sysext/extbase/Classes/Scheduler/TaskExecutor.php @@ -108,12 +108,6 @@ class TaskExecutor implements \TYPO3\CMS\Core\SingletonInterface } } } - // initialize reflection - $reflectionService = $this->objectManager->get(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class); - $reflectionService->setDataCache(\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('extbase_reflection')); - if (!$reflectionService->isInitialized()) { - $reflectionService->initialize(); - } } /** @@ -144,10 +138,7 @@ class TaskExecutor implements \TYPO3\CMS\Core\SingletonInterface */ protected function shutdown() { - // shutdown $persistenceManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class); $persistenceManager->persistAll(); - $reflectionService = $this->objectManager->get(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class); - $reflectionService->shutdown(); } } diff --git a/typo3/sysext/extbase/Tests/Unit/Mvc/Cli/CommandTest.php b/typo3/sysext/extbase/Tests/Unit/Mvc/Cli/CommandTest.php index c6bb34dcf4d482099fcc67c438b53076275c1669..eb047169078672afb54d8fad7e2111a0e7f0a71f 100644 --- a/typo3/sysext/extbase/Tests/Unit/Mvc/Cli/CommandTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Mvc/Cli/CommandTest.php @@ -21,35 +21,32 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Mvc\Cli; * The TYPO3 project - inspiring people to share! * * */ +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Mvc\Cli\Command; +use TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Tests\Unit\Mvc\Cli\Fixture\Command\MockCCommandController; + /** * Test case */ class CommandTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase { /** - * @var \TYPO3\CMS\Extbase\Mvc\Cli\Command|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface - */ - protected $command; - - /** - * @var \TYPO3\CMS\Extbase\Reflection\MethodReflection + * @var array */ - protected $mockMethodReflection; + protected $singletonInstances; - /** - * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface - */ - protected $mockObjectManager; - - /** - */ protected function setUp() { - $this->command = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Mvc\Cli\Command::class, ['getCommandMethodReflection'], [], '', false); - $this->mockMethodReflection = $this->createMock(\TYPO3\CMS\Extbase\Reflection\MethodReflection::class); - $this->command->expects($this->any())->method('getCommandMethodReflection')->will($this->returnValue($this->mockMethodReflection)); - $this->mockObjectManager = $this->createMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class); - $this->command->_set('objectManager', $this->mockObjectManager); + $this->singletonInstances = GeneralUtility::getSingletonInstances(); + GeneralUtility::purgeInstances(); + } + + protected function tearDown() + { + GeneralUtility::resetSingletonInstances($this->singletonInstances); + parent::tearDown(); } /** @@ -101,52 +98,167 @@ class CommandTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase new \TYPO3\CMS\Extbase\Mvc\Cli\Command($controllerClassName, 'foo'); } - /** - * @test - */ - public function hasArgumentsReturnsFalseIfCommandExpectsNoArguments() + public function testIsInternal() { - $this->mockMethodReflection->expects($this->atLeastOnce())->method('getParameters')->will($this->returnValue([])); - $this->assertFalse($this->command->hasArguments()); + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'empty' + ); + + static::assertFalse($commandController->isInternal()); + + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'internal' + ); + + static::assertTrue($commandController->isInternal()); } - /** - * @test - */ - public function hasArgumentsReturnsTrueIfCommandExpectsArguments() + public function testIsCliOnly() { - $mockParameterReflection = $this->createMock(\TYPO3\CMS\Extbase\Reflection\ParameterReflection::class); - $this->mockMethodReflection->expects($this->atLeastOnce())->method('getParameters')->will($this->returnValue([$mockParameterReflection])); - $this->assertTrue($this->command->hasArguments()); + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'empty' + ); + + static::assertFalse($commandController->isCliOnly()); + + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'cliOnly' + ); + + static::assertTrue($commandController->isCliOnly()); } - /** - * @test - */ - public function getArgumentDefinitionsReturnsEmptyArrayIfCommandExpectsNoArguments() + public function testIsFlushinCaches() { - $this->mockMethodReflection->expects($this->atLeastOnce())->method('getParameters')->will($this->returnValue([])); - $this->assertSame([], $this->command->getArgumentDefinitions()); + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'empty' + ); + + static::assertFalse($commandController->isFlushingCaches()); + + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'flushingCaches' + ); + + static::assertTrue($commandController->isFlushingCaches()); } - /** - * @test - */ - public function getArgumentDefinitionsReturnsArrayOfArgumentDefinitionIfCommandExpectsArguments() + public function testHasArguments() + { + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'empty' + ); + + static::assertFalse($commandController->hasArguments()); + + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'withArguments' + ); + + static::assertTrue($commandController->hasArguments()); + } + + public function testGetArgumentDefinitions() + { + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'empty' + ); + + static::assertSame([], $commandController->getArgumentDefinitions()); + + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'withArguments' + ); + + $expected = [ + new CommandArgumentDefinition('foo', true, 'FooParamDescription'), + new CommandArgumentDefinition('bar', false, 'BarParamDescription'), + ]; + + static::assertEquals($expected, $commandController->getArgumentDefinitions()); + } + + public function testGetDescription() + { + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'empty' + ); + + static::assertSame('', $commandController->getDescription()); + + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'withDescription' + ); + + $expected = 'Longer Description' . PHP_EOL . + 'Multine' . PHP_EOL . PHP_EOL . + 'Much Multiline'; + + static::assertEquals($expected, $commandController->getDescription()); + } + + public function testGetShortDescription() + { + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'empty' + ); + + static::assertSame('', $commandController->getShortDescription()); + + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'withDescription' + ); + + $expected = 'Short Description'; + + static::assertEquals($expected, $commandController->getShortDescription()); + } + + public function testGetRelatedCommandIdentifiers() { - $mockParameterReflection = $this->createMock(\TYPO3\CMS\Extbase\Reflection\ParameterReflection::class); - $mockReflectionService = $this->createMock(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class); - $mockMethodParameters = ['argument1' => ['optional' => false], 'argument2' => ['optional' => true]]; - $mockReflectionService->expects($this->atLeastOnce())->method('getMethodParameters')->will($this->returnValue($mockMethodParameters)); - $this->command->_set('reflectionService', $mockReflectionService); - $this->mockMethodReflection->expects($this->atLeastOnce())->method('getParameters')->will($this->returnValue([$mockParameterReflection])); - $this->mockMethodReflection->expects($this->atLeastOnce())->method('getTagsValues')->will($this->returnValue(['param' => ['@param $argument1 argument1 description', '@param $argument2 argument2 description']])); - $mockCommandArgumentDefinition1 = $this->createMock(\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition::class); - $mockCommandArgumentDefinition2 = $this->createMock(\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition::class); - $this->mockObjectManager->expects($this->at(0))->method('get')->with(\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition::class, 'argument1', true, 'argument1 description')->will($this->returnValue($mockCommandArgumentDefinition1)); - $this->mockObjectManager->expects($this->at(1))->method('get')->with(\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition::class, 'argument2', false, 'argument2 description')->will($this->returnValue($mockCommandArgumentDefinition2)); - $expectedResult = [$mockCommandArgumentDefinition1, $mockCommandArgumentDefinition2]; - $actualResult = $this->command->getArgumentDefinitions(); - $this->assertSame($expectedResult, $actualResult); + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'empty' + ); + + static::assertSame([], $commandController->getRelatedCommandIdentifiers()); + + $commandController = GeneralUtility::makeInstance(ObjectManager::class)->get( + Command::class, + MockCCommandController::class, + 'relatedCommandIdentifiers' + ); + + $expected = ['Foo:Bar:Baz']; + static::assertEquals($expected, $commandController->getRelatedCommandIdentifiers()); } } diff --git a/typo3/sysext/extbase/Tests/Unit/Mvc/Cli/Fixture/Command/MockCCommandController.php b/typo3/sysext/extbase/Tests/Unit/Mvc/Cli/Fixture/Command/MockCCommandController.php new file mode 100644 index 0000000000000000000000000000000000000000..463c0b416c80de7d6c84ede4ddbf952c60c24d0c --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Mvc/Cli/Fixture/Command/MockCCommandController.php @@ -0,0 +1,60 @@ +<?php +namespace TYPO3\CMS\Extbase\Tests\Unit\Mvc\Cli\Fixture\Command; + +/** + * Another mock CLI Command + */ +class MockCCommandController extends \TYPO3\CMS\Extbase\Mvc\Cli\Command +{ + public function emptyCommand() + { + } + + /** + * @internal + */ + public function internalCommand() + { + } + + /** + * @cli + */ + public function cliOnlyCommand() + { + } + + /** + * @flushesCaches + */ + public function flushingCachesCommand() + { + } + + /** + * @param string $foo FooParamDescription + * @param string $bar BarParamDescription + */ + public function withArgumentsCommand($foo, $bar = 'baz') + { + } + + /** + * Short Description + * + * Longer Description + * Multine + * + * Much Multiline + */ + public function withDescriptionCommand() + { + } + + /** + * @see Foo:Bar:Baz + */ + public function relatedCommandIdentifiersCommand() + { + } +} diff --git a/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/ActionControllerTest.php b/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/ActionControllerTest.php index 6c8de904e19b27ddd5a56f4d3883925c3a553f4c..783b31365c6df8c26f292765fe6fa7e603db96ea 100644 --- a/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/ActionControllerTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Mvc/Controller/ActionControllerTest.php @@ -256,7 +256,8 @@ class ActionControllerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas 'array' => false, 'optional' => false, 'allowsNull' => false, - 'type' => 'string' + 'type' => 'string', + 'hasDefaultValue' => false ], 'arg2' => [ 'position' => 1, @@ -264,7 +265,8 @@ class ActionControllerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas 'array' => true, 'optional' => true, 'defaultValue' => [21], - 'allowsNull' => false + 'allowsNull' => false, + 'hasDefaultValue' => true ], 'arg3' => [ 'position' => 2, @@ -273,7 +275,8 @@ class ActionControllerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas 'optional' => true, 'defaultValue' => 42, 'allowsNull' => false, - 'type' => 'string' + 'type' => 'string', + 'hasDefaultValue' => true ] ]; $mockReflectionService = $this->createMock(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class); diff --git a/typo3/sysext/extbase/Tests/Unit/Object/Container/ClassInfoFactoryTest.php b/typo3/sysext/extbase/Tests/Unit/Object/Container/ClassInfoFactoryTest.php deleted file mode 100644 index d5582594fc42148287b2c0f86f46bd20814afeac..0000000000000000000000000000000000000000 --- a/typo3/sysext/extbase/Tests/Unit/Object/Container/ClassInfoFactoryTest.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -namespace TYPO3\CMS\Extbase\Tests\Unit\Object\Container; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -use TYPO3\CMS\Extbase\Object\Container\Exception\UnknownObjectException; - -/** - * Test case - */ -class ClassInfoFactoryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Extbase\Object\Container\ClassInfoFactory - */ - protected $classInfoFactory; - - /** - * Set up - */ - protected function setUp() - { - $this->classInfoFactory = new \TYPO3\CMS\Extbase\Object\Container\ClassInfoFactory(); - } - - /** - * @test - */ - public function buildClassInfoFromClassNameThrowsExceptionIfGivenClassNameCantBeReflected() - { - $this->expectException(UnknownObjectException::class); - $this->expectExceptionCode(1289386765); - $this->classInfoFactory->buildClassInfoFromClassName('SomeNonExistingClass'); - } - - /** - * @test - */ - public function buildClassInfoDoesNotIncludeInjectSettingsMethodInListOfInjectMethods() - { - $classInfo = $this->classInfoFactory->buildClassInfoFromClassName('t3lib_object_tests_class_with_injectsettings'); - $this->assertEquals(['injectFoo' => 't3lib_object_tests_resolveablecyclic1'], $classInfo->getInjectMethods()); - } - - /** - * @test - */ - public function buildClassInfoDetectsPropertiesToInjectByAnnotation() - { - $classInfo = $this->classInfoFactory->buildClassInfoFromClassName(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithInjectProperties::class); - $this->assertEquals(['secondDummyClass' => \TYPO3\CMS\Extbase\Tests\Fixture\SecondDummyClass::class], $classInfo->getInjectProperties()); - } - - /** - * @test - */ - public function buildClassInfoReturnsCustomClassInfoForDateTime() - { - /** @var \PHPUnit_Framework_MockObject_MockObject | \TYPO3\CMS\Extbase\Object\Container\ClassInfoFactory $classInfoFactory */ - $classInfoFactory = $this->getMockBuilder(\TYPO3\CMS\Extbase\Object\Container\ClassInfoFactory::class) - ->setMethods(['getConstructorArguments']) - ->getMock(); - $classInfoFactory->expects($this->never())->method('getConstructorArguments'); - - $classInfo = $classInfoFactory->buildClassInfoFromClassName('DateTime'); - $this->assertEquals( - new \TYPO3\CMS\Extbase\Object\Container\ClassInfo('DateTime', [], [], false, false, []), - $classInfo - ); - } -} diff --git a/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php b/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php index 144a761d608034d7223b4cc68ac5a98a2e2c2f17..91ef94bb8a036be69509d5758b688c091783b9e9 100644 --- a/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php @@ -17,6 +17,7 @@ use Psr\Log\LoggerInterface; use TYPO3\CMS\Core\Log\Logger; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\Object\Exception\CannotBuildObjectException; +use TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException; /** * Test case @@ -194,33 +195,11 @@ class ContainerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase */ public function getInstanceThrowsExceptionIfClassWasNotFound() { - $this->expectException(Exception::class); - $this->expectExceptionCode(1289386765); + $this->expectException(UnknownClassException::class); + $this->expectExceptionCode(1278450972); $this->container->getInstance('nonextistingclass_bla'); } - /** - * @test - */ - public function getInstanceUsesClassNameMd5AsCacheKey() - { - $className = \TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\NamespacedClass::class; - $classNameHash = md5($className); - $mockedCache = $this->getMockBuilder(\TYPO3\CMS\Extbase\Object\Container\ClassInfoCache::class) - ->setMethods(['has', 'set', 'get']) - ->getMock(); - $container = $this->getMockBuilder(\TYPO3\CMS\Extbase\Object\Container\Container::class) - ->setMethods(['log', 'getClassInfoCache']) - ->getMock(); - $container->expects($this->any())->method('getClassInfoCache')->will($this->returnValue($mockedCache)); - $mockedCache->expects($this->never())->method('has'); - $mockedCache->expects($this->once())->method('get')->with($classNameHash)->will($this->returnValue(false)); - $mockedCache->expects($this->once())->method('set')->with($classNameHash, $this->anything())->will($this->returnCallback([$this, 'setClassInfoCacheCallback'])); - $container->getInstance($className); - $this->assertInstanceOf(\TYPO3\CMS\Extbase\Object\Container\ClassInfo::class, $this->cachedClassInfo); - $this->assertEquals($className, $this->cachedClassInfo->getClassName()); - } - /** * @test */ @@ -230,17 +209,6 @@ class ContainerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $this->assertTrue($instance->isInitialized()); } - /** - * Callback for getInstanceUsesClassNameSha1AsCacheKey - * - * @param string $id - * @param \TYPO3\CMS\Extbase\Object\Container\ClassInfo $value - */ - public function setClassInfoCacheCallback($id, \TYPO3\CMS\Extbase\Object\Container\ClassInfo $value) - { - $this->cachedClassInfo = $value; - } - /** * @test */ diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php index 88e3fb4166c0073a59d6707c5e500bdc6373f8a7..d8041a2fea386442dd5f9e0d019201a487a2a239 100644 --- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapperTest.php @@ -18,6 +18,7 @@ use TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface; use TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnexpectedTypeException; use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap; use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper; +use TYPO3\CMS\Extbase\Reflection\ClassSchema; use TYPO3\TestingFramework\Core\AccessibleObjectInterface; /** @@ -64,7 +65,26 @@ class DataMapperTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $className = $this->getUniqueId('Class'); $classNameWithNS = __NAMESPACE__ . '\\' . $className; eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\' . \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class . ' { - public $firstProperty; public $secondProperty; public $thirdProperty; public $fourthProperty; + + /** + * @var string + */ + public $firstProperty; + + /** + * @var int + */ + public $secondProperty; + + /** + * @var float + */ + public $thirdProperty; + + /** + * @var bool + */ + public $fourthProperty; }' ); $object = new $classNameWithNS(); @@ -88,13 +108,7 @@ class DataMapperTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $classNameWithNS => $dataMap ]; /** @var AccessibleObjectInterface|\TYPO3\CMS\Extbase\Reflection\ClassSchema $classSchema */ - $classSchema = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class, ['dummy'], [$classNameWithNS]); - $classSchema->addProperty('pid', 'integer'); - $classSchema->addProperty('uid', 'integer'); - $classSchema->addProperty('firstProperty', 'string'); - $classSchema->addProperty('secondProperty', 'integer'); - $classSchema->addProperty('thirdProperty', 'float'); - $classSchema->addProperty('fourthProperty', 'boolean'); + $classSchema = new ClassSchema($classNameWithNS); $mockReflectionService = $this->getMockBuilder(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class) ->setMethods(['getClassSchema']) ->getMock(); @@ -189,17 +203,21 @@ class DataMapperTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $className = $this->getUniqueId('Class1'); $classNameWithNS = __NAMESPACE__ . '\\' . $className; - eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\' . \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class . ' { public $relationProperty; }'); - $object = new $classNameWithNS(); $className2 = $this->getUniqueId('Class2'); $className2WithNS = __NAMESPACE__ . '\\' . $className2; eval('namespace ' . __NAMESPACE__ . '; class ' . $className2 . ' extends \\' . \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class . ' { }'); + eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\' . \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class . ' { + /** + * @var ' . $className2WithNS . ' + */ + public $relationProperty; + }'); + $object = new $classNameWithNS(); $child = new $className2WithNS(); /** @var \TYPO3\CMS\Extbase\Reflection\ClassSchema|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject $classSchema1 */ - $classSchema1 = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class, ['dummy'], [$classNameWithNS]); - $classSchema1->addProperty('relationProperty', $className2WithNS); + $classSchema1 = new ClassSchema($classNameWithNS); $identifier = 1; $session = new \TYPO3\CMS\Extbase\Persistence\Generic\Session(); diff --git a/typo3/sysext/extbase/Tests/Unit/Property/TypeConverter/Fixtures/Query.php b/typo3/sysext/extbase/Tests/Unit/Property/TypeConverter/Fixtures/Query.php new file mode 100644 index 0000000000000000000000000000000000000000..7b893c229bb8cba2a8eccde262ac57d2a894bf0f --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Property/TypeConverter/Fixtures/Query.php @@ -0,0 +1,22 @@ +<?php +namespace TYPO3\CMS\Extbase\Tests\Unit\Property\TypeConverter\Fixtures; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Fixture Query + */ +class Query +{ +} diff --git a/typo3/sysext/extbase/Tests/Unit/Property/TypeConverter/PersistentObjectConverterTest.php b/typo3/sysext/extbase/Tests/Unit/Property/TypeConverter/PersistentObjectConverterTest.php index 689f4417ededac8957904f6ea537f7871a4b9400..a2890570c6860f5adc7eb9a54f67066b4aa9764a 100644 --- a/typo3/sysext/extbase/Tests/Unit/Property/TypeConverter/PersistentObjectConverterTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Property/TypeConverter/PersistentObjectConverterTest.php @@ -255,7 +255,7 @@ class PersistentObjectConverterTest extends \TYPO3\TestingFramework\Core\Unit\Un public function setupMockQuery($numberOfResults, $howOftenIsGetFirstCalled) { $mockClassSchema = $this->getMockBuilder(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class) - ->setConstructorArgs(['Dummy']) + ->setConstructorArgs([\TYPO3\CMS\Extbase\Tests\Unit\Property\TypeConverter\Fixtures\Query::class]) ->getMock(); $mockClassSchema->expects($this->any())->method('getIdentityProperties')->will($this->returnValue(['key1' => 'someType'])); $this->mockReflectionService->expects($this->any())->method('getClassSchema')->with('SomeType')->will($this->returnValue($mockClassSchema)); diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchemaTest.php b/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchemaTest.php index eb93ceb1cbe721159c1c7550bf310bad37e51dbd..7a2f97c9d03e17e3e2c8a60a490e12a1ed3ff745 100644 --- a/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchemaTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchemaTest.php @@ -14,6 +14,11 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Persistence\ObjectStorage; +use TYPO3\CMS\Extbase\Reflection\ClassSchema; +use TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyModel; + /** * Test case */ @@ -24,49 +29,173 @@ class ClassSchemaTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase */ public function classSchemaForModelIsSetAggregateRootIfRepositoryClassIsFoundForNamespacedClasses() { - $className = $this->getUniqueId('BazFixture'); - eval(' - namespace Foo\\Bar\\Domain\\Model; - class ' . $className . ' extends \\' . \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class . ' {} - '); - eval(' - namespace Foo\\Bar\\Domain\\Repository; - class ' . $className . 'Repository {} - '); - - /** @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject $objectManager */ - $objectManager = $this->createMock(\TYPO3\CMS\Extbase\Object\ObjectManager::class); - $mockClassSchema = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class, ['dummy'], ['Foo\\Bar\\Domain\\Model\\' . $className]); - $objectManager->expects($this->once())->method('get')->will($this->returnValue($mockClassSchema)); - /** @var \TYPO3\CMS\Extbase\Reflection\ReflectionService $service */ - $service = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class, ['dummy']); - $service->_set('objectManager', $objectManager); - $classSchema = $service->getClassSchema('Foo\\Bar\\Domain\\Model\\' . $className); + $service = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class); + $classSchema = $service->getClassSchema(DummyModel::class); $this->assertTrue($classSchema->isAggregateRoot()); } - /** - * @test - */ - public function classSchemaForModelIsSetAggregateRootIfRepositoryClassIsFoundForNotNamespacedClasses() - { - $className = $this->getUniqueId('BazFixture'); - eval(' - class Foo_Bar_Domain_Model_' . $className . ' extends \\' . \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class . ' {} - '); - eval(' - class Foo_Bar_Domain_Repository_' . $className . 'Repository {} - '); - - /** @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject $objectManager */ - $objectManager = $this->createMock(\TYPO3\CMS\Extbase\Object\ObjectManager::class); - $mockClassSchema = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class, ['dummy'], ['Foo_Bar_Domain_Model_' . $className]); - $objectManager->expects($this->once())->method('get')->will($this->returnValue($mockClassSchema)); - - $service = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class, ['dummy']); - $service->_set('objectManager', $objectManager); - $classSchema = $service->getClassSchema('Foo_Bar_Domain_Model_' . $className); - $this->assertTrue($classSchema->isAggregateRoot()); + public function testClassSchemaHasConstructor() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithConstructorAndConstructorArguments::class); + static::assertTrue($classSchema->hasConstructor()); + } + + public function testClassSchemaDetectsConstructorArguments() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithConstructorAndConstructorArguments::class); + static::assertTrue($classSchema->hasConstructor()); + + $methodDefinition = $classSchema->getMethod('__construct'); + static::assertArrayHasKey('foo', $methodDefinition['params']); + static::assertArrayHasKey('bar', $methodDefinition['params']); + } + + public function testClassSchemaDetectsConstructorArgumentsWithDependencies() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithConstructorAndConstructorArgumentsWithDependencies::class); + static::assertTrue($classSchema->hasConstructor()); + + $methodDefinition = $classSchema->getMethod('__construct'); + static::assertArrayHasKey('foo', $methodDefinition['params']); + static::assertSame(Fixture\DummyClassWithGettersAndSetters::class, $methodDefinition['params']['foo']['dependency']); + } + + public function testClassSchemaDetectsMethodVisibility() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class); + + $methodDefinition = $classSchema->getMethod('publicMethod'); + static::assertTrue($methodDefinition['public']); + static::assertFalse($methodDefinition['protected']); + static::assertFalse($methodDefinition['private']); + + $methodDefinition = $classSchema->getMethod('protectedMethod'); + static::assertFalse($methodDefinition['public']); + static::assertTrue($methodDefinition['protected']); + static::assertFalse($methodDefinition['private']); + + $methodDefinition = $classSchema->getMethod('privateMethod'); + static::assertFalse($methodDefinition['public']); + static::assertFalse($methodDefinition['protected']); + static::assertTrue($methodDefinition['private']); + } + + public function testClassSchemaDetectsInjectMethods() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class); + + $methodDefinition = $classSchema->getMethod('injectSettings'); + static::assertFalse($methodDefinition['injectMethod']); + + $methodDefinition = $classSchema->getMethod('injectMethodWithoutParam'); + static::assertFalse($methodDefinition['injectMethod']); + + $methodDefinition = $classSchema->getMethod('injectMethodThatIsProtected'); + static::assertFalse($methodDefinition['injectMethod']); + + $methodDefinition = $classSchema->getMethod('injectFoo'); + static::assertTrue($methodDefinition['injectMethod']); + } + + public function testClassSchemaDetectsStaticMethods() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class); + + $methodDefinition = $classSchema->getMethod('staticMethod'); + static::assertTrue($methodDefinition['static']); + } + + public function testClassSchemaDetectsMandatoryParams() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class); + + $methodDefinition = $classSchema->getMethod('methodWithMandatoryParam'); + static::assertFalse($methodDefinition['params']['param']['optional']); + } + + public function testClassSchemaDetectsNullableParams() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class); + + $methodDefinition = $classSchema->getMethod('methodWithNullableParam'); + static::assertTrue($methodDefinition['params']['param']['nullable']); + } + + public function testClassSchemaDetectsDefaultValueParams() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class); + + $methodDefinition = $classSchema->getMethod('methodWithDefaultValueParam'); + static::assertSame('foo', $methodDefinition['params']['param']['default']); + } + + public function testClassSchemaDetectsParamTypeFromTypeHint() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfMethods::class); + + $methodDefinition = $classSchema->getMethod('methodWithTypeHintedParam'); + static::assertSame('string', $methodDefinition['params']['param']['type']); + } + + public function testClassSchemaDetectsPropertyVisibility() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class); + + $propertyDefinition = $classSchema->getProperty('publicProperty'); + static::assertTrue($propertyDefinition['public']); + static::assertFalse($propertyDefinition['protected']); + static::assertFalse($propertyDefinition['private']); + + $propertyDefinition = $classSchema->getProperty('protectedProperty'); + static::assertFalse($propertyDefinition['public']); + static::assertTrue($propertyDefinition['protected']); + static::assertFalse($propertyDefinition['private']); + + $propertyDefinition = $classSchema->getProperty('privateProperty'); + static::assertFalse($propertyDefinition['public']); + static::assertFalse($propertyDefinition['protected']); + static::assertTrue($propertyDefinition['private']); + } + + public function testClassSchemaDetectsInjectProperty() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class); + + $propertyDefinition = $classSchema->getProperty('propertyWithInjectAnnotation'); + static::assertTrue($propertyDefinition['annotations']['inject']); + } + + public function testClassSchemaDetectsTransientProperty() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class); + + $propertyDefinition = $classSchema->getProperty('propertyWithTransientAnnotation'); + static::assertTrue($propertyDefinition['annotations']['transient']); + } + + public function testClassSchemaDetectsCascadeProperty() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class); + + $propertyDefinition = $classSchema->getProperty('propertyWithCascadeAnnotation'); + static::assertSame('remove', $propertyDefinition['annotations']['cascade']); + } + + public function testClassSchemaDetectsCascadePropertyOnlyWithVarAnnotation() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class); + + $propertyDefinition = $classSchema->getProperty('propertyWithCascadeAnnotationWithoutVarAnnotation'); + static::assertNull($propertyDefinition['annotations']['cascade']); + } + + public function testClassSchemaDetectsTypeAndElementType() + { + $classSchema = new ClassSchema(Fixture\DummyClassWithAllTypesOfProperties::class); + + $propertyDefinition = $classSchema->getProperty('propertyWithObjectStorageAnnotation'); + static::assertSame(ObjectStorage::class, $propertyDefinition['type']); + static::assertSame(Fixture\DummyClassWithAllTypesOfProperties::class, $propertyDefinition['elementType']); } } diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfMethods.php b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfMethods.php new file mode 100644 index 0000000000000000000000000000000000000000..e34f09b4a74cbfc3e228a286552a8348151c4a3b --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfMethods.php @@ -0,0 +1,75 @@ +<?php +namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Fixture class with getters and setters + * + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later + */ +class DummyClassWithAllTypesOfMethods +{ + public function publicMethod() + { + } + + protected function protectedMethod() + { + } + + private function privateMethod() + { + } + + public function injectSettings() + { + // Will fail, as injectSettings is blacklisted + } + + public function injectMethodWithoutParam() + { + // Will fail, as there is no param + } + + protected function injectMethodThatIsProtected() + { + // Will fail, as method is protected + } + + public function injectFoo(DummyClassWithAllTypesOfMethods $foo) + { + // Will succeed + } + + public static function staticMethod() + { + } + + public static function methodWithMandatoryParam($param) + { + } + + public static function methodWithNullableParam($param = null) + { + } + + public static function methodWithDefaultValueParam($param = 'foo') + { + } + + public static function methodWithTypeHintedParam(string $param) + { + } +} diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php new file mode 100644 index 0000000000000000000000000000000000000000..6f336c282ed2aa5e7d3437a85b80d9ee2daaf823 --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php @@ -0,0 +1,56 @@ +<?php +namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Fixture class with getters and setters + * + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later + */ +class DummyClassWithAllTypesOfProperties +{ + public $publicProperty; + + protected $protectedProperty; + + private $privateProperty; + + /** + * @inject + * @var DummyClassWithAllTypesOfProperties + */ + public $propertyWithInjectAnnotation; + + /** + * @transient + */ + public $propertyWithTransientAnnotation; + + /** + * @var DummyClassWithAllTypesOfProperties + * @cascade remove + */ + public $propertyWithCascadeAnnotation; + + /** + * @cascade remove + */ + public $propertyWithCascadeAnnotationWithoutVarAnnotation; + + /** + * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyClassWithAllTypesOfProperties> + */ + public $propertyWithObjectStorageAnnotation; +} diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithConstructorAndConstructorArguments.php b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithConstructorAndConstructorArguments.php new file mode 100644 index 0000000000000000000000000000000000000000..5b835f77438f81fa3695e298b0d266d71311d2b2 --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithConstructorAndConstructorArguments.php @@ -0,0 +1,27 @@ +<?php +namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Fixture class with getters and setters + * + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later + */ +class DummyClassWithConstructorAndConstructorArguments +{ + public function __construct(int $foo, $bar = 'baz') + { + } +} diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithConstructorAndConstructorArgumentsWithDependencies.php b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithConstructorAndConstructorArgumentsWithDependencies.php new file mode 100644 index 0000000000000000000000000000000000000000..db405c9c377729db2f2b594d005a29b339c8ffe1 --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithConstructorAndConstructorArgumentsWithDependencies.php @@ -0,0 +1,27 @@ +<?php +namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Fixture class with getters and setters + * + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later + */ +class DummyClassWithConstructorAndConstructorArgumentsWithDependencies +{ + public function __construct(DummyClassWithGettersAndSetters $foo) + { + } +} diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyModel.php b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyModel.php new file mode 100644 index 0000000000000000000000000000000000000000..bb933c412649bb181ae06c3e47acbff826d85923 --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyModel.php @@ -0,0 +1,24 @@ +<?php +namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; + +/** + * Fixture model + */ +class DummyModel extends AbstractEntity +{ +} diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyModelRepository.php b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyModelRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..5acd0117e099d4594a0b5dd0dd5e29de0da481b8 --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyModelRepository.php @@ -0,0 +1,24 @@ +<?php +namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Persistence\Repository; + +/** + * Fixture repository + */ +class DummyModelRepository extends Repository +{ +} diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/ReflectionServiceTest.php b/typo3/sysext/extbase/Tests/Unit/Reflection/ReflectionServiceTest.php index 830700eaa5db43c3e8b0f6cf063b0595f1013cbb..9f12e29cc81e08f7fe212a0eeab28c093fe136f4 100644 --- a/typo3/sysext/extbase/Tests/Unit/Reflection/ReflectionServiceTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Reflection/ReflectionServiceTest.php @@ -14,6 +14,7 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Reflection\ReflectionService; /** @@ -45,7 +46,7 @@ class ReflectionServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa */ public function getClassTagsValues() { - $service = new ReflectionService(); + $service = GeneralUtility::makeInstance(ReflectionService::class); $classValues = $service->getClassTagsValues(static::class); $this->assertEquals([ 'firsttest' => ['test for reflection'], @@ -58,7 +59,7 @@ class ReflectionServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa */ public function getClassTagValues() { - $service = new ReflectionService(); + $service = GeneralUtility::makeInstance(ReflectionService::class); $classValues = $service->getClassTagValues(static::class, 'firsttest'); $this->assertEquals([ 'test for reflection', @@ -70,7 +71,7 @@ class ReflectionServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa */ public function hasMethod() { - $service = new ReflectionService(); + $service = GeneralUtility::makeInstance(ReflectionService::class); $this->assertTrue($service->hasMethod(static::class, 'fixtureMethodForMethodTagsValues')); $this->assertFalse($service->hasMethod(static::class, 'notExistentMethod')); } @@ -80,7 +81,7 @@ class ReflectionServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa */ public function getMethodTagsValues() { - $service = new ReflectionService(); + $service = GeneralUtility::makeInstance(ReflectionService::class); $tagsValues = $service->getMethodTagsValues(static::class, 'fixtureMethodForMethodTagsValues'); $this->assertEquals([ 'param' => ['array $foo The foo parameter'], @@ -93,7 +94,7 @@ class ReflectionServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa */ public function getMethodParameters() { - $service = new ReflectionService(); + $service = GeneralUtility::makeInstance(ReflectionService::class); $parameters = $service->getMethodParameters(static::class, 'fixtureMethodForMethodTagsValues'); $this->assertSame([ 'foo' => [ @@ -103,7 +104,12 @@ class ReflectionServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa 'optional' => false, 'allowsNull' => false, 'class' => null, - 'type' => 'array' + 'type' => 'array', + 'nullable' => false, + 'default' => null, + 'hasDefaultValue' => false, + 'defaultValue' => null, + 'dependency' => null, ] ], $parameters); } @@ -113,7 +119,7 @@ class ReflectionServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa */ public function getMethodParametersWithShortTypeNames() { - $service = new ReflectionService(); + $service = GeneralUtility::makeInstance(ReflectionService::class); $parameters = $service->getMethodParameters(static::class, 'fixtureMethodForMethodTagsValuesWithShortTypes'); $this->assertSame([ 'dummy' => [ @@ -123,7 +129,12 @@ class ReflectionServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa 'optional' => false, 'allowsNull' => true, 'class' => null, - 'type' => 'boolean' + 'type' => 'boolean', + 'nullable' => true, + 'default' => null, + 'hasDefaultValue' => false, + 'defaultValue' => null, + 'dependency' => null, ], 'foo' => [ 'position' => 1, @@ -132,7 +143,12 @@ class ReflectionServiceTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCa 'optional' => false, 'allowsNull' => true, 'class' => null, - 'type' => 'integer' + 'type' => 'integer', + 'nullable' => true, + 'default' => null, + 'hasDefaultValue' => false, + 'defaultValue' => null, + 'dependency' => null, ] ], $parameters); } diff --git a/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php b/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php index fddd525f236847970297f255b63fbde1211b140f..6fa42c1895c20553cc433f184c85958d70fffff5 100644 --- a/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php +++ b/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php @@ -26,7 +26,6 @@ use TYPO3\CMS\Extbase\Mvc\Web\Request; use TYPO3\CMS\Extbase\Mvc\Web\Response; use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; use TYPO3\CMS\Extbase\Property\Exception as PropertyException; -use TYPO3\CMS\Extbase\Reflection\PropertyReflection; use TYPO3\CMS\Form\Domain\Exception\RenderingException; use TYPO3\CMS\Form\Domain\Finishers\FinisherContext; use TYPO3\CMS\Form\Domain\Model\FormDefinition; @@ -700,7 +699,7 @@ class FormRuntime implements RootRenderableInterface, \ArrayAccess return true; } if (property_exists($this, $identifier)) { - $propertyReflection = new PropertyReflection($this, $identifier); + $propertyReflection = new \ReflectionProperty($this, $identifier); return $propertyReflection->isPublic(); } diff --git a/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/ApcPreset.php b/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/ApcPreset.php deleted file mode 100644 index e2eba039387cb29c627c38aa9a3d38f21c80862c..0000000000000000000000000000000000000000 --- a/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/ApcPreset.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php -namespace TYPO3\CMS\Install\Configuration\ExtbaseObjectCache; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Install\Configuration; - -/** - * APC preset - */ -class ApcPreset extends Configuration\AbstractPreset -{ - /** - * @var string Name of preset - */ - protected $name = 'Apc'; - - /** - * @var int Priority of preset - */ - protected $priority = 80; - - /** - * @var array Configuration values handled by this preset - */ - protected $configurationValues = [ - 'SYS/caching/cacheConfigurations/extbase_object' => [ - 'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, - 'backend' => \TYPO3\CMS\Core\Cache\Backend\ApcBackend::class, - 'options' => [ - 'defaultLifetime' => 0, - ], - 'groups' => ['system'] - ] - ]; - - /** - * APC preset is available if extension is loaded and at least ~5MB are free. - * - * @return bool TRUE - */ - public function isAvailable() - { - $result = false; - if (extension_loaded('apc')) { - $memoryInfo = @apc_sma_info(); - $availableMemory = $memoryInfo['avail_mem']; - - // If more than 5MB free - if ($availableMemory > (5 * 1024 * 1024)) { - $result = true; - } - } - return $result; - } -} diff --git a/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/ApcuPreset.php b/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/ApcuPreset.php deleted file mode 100644 index d595059e9f9d6a75546f19f8cf9f6635fceecadb..0000000000000000000000000000000000000000 --- a/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/ApcuPreset.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php -namespace TYPO3\CMS\Install\Configuration\ExtbaseObjectCache; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Install\Configuration; - -/** - * APCu preset - */ -class ApcuPreset extends Configuration\AbstractPreset -{ - /** - * @var string Name of preset - */ - protected $name = 'Apcu'; - - /** - * @var int Priority of preset - */ - protected $priority = 90; - - /** - * @var array Configuration values handled by this preset - */ - protected $configurationValues = [ - 'SYS/caching/cacheConfigurations/extbase_object' => [ - 'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, - 'backend' => \TYPO3\CMS\Core\Cache\Backend\ApcuBackend::class, - 'options' => [ - 'defaultLifetime' => 0, - ], - 'groups' => ['system'] - ] - ]; - - /** - * APC preset is available if extension is loaded and at least ~5MB are free. - * - * @return bool TRUE - */ - public function isAvailable() - { - $result = false; - if (extension_loaded('apcu')) { - $memoryInfo = @apcu_sma_info(); - $availableMemory = $memoryInfo['avail_mem']; - - // If more than 5MB free - if ($availableMemory > (5 * 1024 * 1024)) { - $result = true; - } - } - return $result; - } -} diff --git a/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/DatabasePreset.php b/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/DatabasePreset.php deleted file mode 100644 index 5c3aa1c1fb762cfe2ba4f778a3e9f2aefadd1f69..0000000000000000000000000000000000000000 --- a/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/DatabasePreset.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -namespace TYPO3\CMS\Install\Configuration\ExtbaseObjectCache; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Install\Configuration; - -/** - * Database preset - */ -class DatabasePreset extends Configuration\AbstractPreset -{ - /** - * @var string Name of preset - */ - protected $name = 'Database'; - - /** - * @var int Priority of preset - */ - protected $priority = 50; - - /** - * @var array Configuration values handled by this preset - */ - protected $configurationValues = [ - 'SYS/caching/cacheConfigurations/extbase_object' => [ - 'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, - 'backend' => \TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend::class, - 'options' => [ - 'defaultLifetime' => 0, - ], - 'groups' => ['system'] - ] - ]; - - /** - * Database preset is always available - * - * @return bool TRUE - */ - public function isAvailable() - { - return true; - } -} diff --git a/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/ExtbaseObjectCacheFeature.php b/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/ExtbaseObjectCacheFeature.php deleted file mode 100644 index fcc8c813e79ae3a71482d455a82af84a2ec1c994..0000000000000000000000000000000000000000 --- a/typo3/sysext/install/Classes/Configuration/ExtbaseObjectCache/ExtbaseObjectCacheFeature.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -namespace TYPO3\CMS\Install\Configuration\ExtbaseObjectCache; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Install\Configuration; - -/** - * Extbase object cache configuration - */ -class ExtbaseObjectCacheFeature extends Configuration\AbstractFeature implements Configuration\FeatureInterface -{ - /** - * @var string Name of feature - */ - protected $name = 'ExtbaseObjectCache'; - - /** - * @var array List of preset classes - */ - protected $presetRegistry = [ - DatabasePreset::class, - ApcPreset::class, - ApcuPreset::class, - ]; -} diff --git a/typo3/sysext/install/Classes/Configuration/FeatureManager.php b/typo3/sysext/install/Classes/Configuration/FeatureManager.php index 7698305953a43c8feb3ca48c3f209af5d7b2af33..567b883e065f61e591857c2a7107cc1b3c7bf542 100644 --- a/typo3/sysext/install/Classes/Configuration/FeatureManager.php +++ b/typo3/sysext/install/Classes/Configuration/FeatureManager.php @@ -16,7 +16,6 @@ namespace TYPO3\CMS\Install\Configuration; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Install\Configuration\Context\ContextFeature; -use TYPO3\CMS\Install\Configuration\ExtbaseObjectCache\ExtbaseObjectCacheFeature; use TYPO3\CMS\Install\Configuration\Image\ImageFeature; use TYPO3\CMS\Install\Configuration\Mail\MailFeature; @@ -31,7 +30,6 @@ class FeatureManager protected $featureRegistry = [ ContextFeature::class, ImageFeature::class, - ExtbaseObjectCacheFeature::class, MailFeature::class, ]; diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php index a2028be9f7aea1a8f855a1221b447d6f317aac5f..414ee5298b94e9aecd820995f2bace7373b7409d 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php @@ -404,6 +404,39 @@ return [ 'Deprecation-82744-RenameExtlowlevelViewToLowlevelController.rst', ], ], + 'TYPO3\CMS\Extbase\Object\Container\ClassInfo' => [ + 'restFiles' => [ + 'Breaking-57594-OptimizeReflectionServiceCacheHandling.rst', + 'Feature-57594-OptimizeReflectionServiceCacheHandling.rst' + ], + ], + 'TYPO3\CMS\Extbase\Object\Container\ClassInfoCache' => [ + 'restFiles' => [ + 'Breaking-57594-OptimizeReflectionServiceCacheHandling.rst', + 'Feature-57594-OptimizeReflectionServiceCacheHandling.rst' + ], + ], + 'TYPO3\CMS\Extbase\Object\Container\ClassInfoFactory' => [ + 'restFiles' => [ + 'Breaking-57594-OptimizeReflectionServiceCacheHandling.rst', + 'Feature-57594-OptimizeReflectionServiceCacheHandling.rst' + ], + ], + 'TYPO3\CMS\Extbase\Reflection\ClassReflection' => [ + 'restFiles' => [ + 'Breaking-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\MethodReflection' => [ + 'restFiles' => [ + 'Breaking-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\ParameterReflection' => [ + 'restFiles' => [ + 'Breaking-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], // Removed interfaces 'TYPO3\CMS\Backend\Form\DatabaseFileIconsHookInterface' => [ diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php index eac2fdafcc95d6ccbb0d06128e0579917faf0bf1..ee98199074f21ead870a9dc55256f82bb2f3dd30 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php @@ -1289,4 +1289,74 @@ return [ 'Deprecation-81217-TSFE-relatedLanguageMethods.rst', ], ], + 'TYPO3\CMS\Extbase\Reflection\PropertyReflection->isTaggedWith' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Breaking-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\PropertyReflection->getTagsValues' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Breaking-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\PropertyReflection->getTagValues' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Breaking-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\ClassSchema->addProperty' => [ + 'numberOfMandatoryArguments' => 2, + 'maximumNumberOfArguments' => 4, + 'restFiles' => [ + 'Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\ClassSchema->setModelType' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\ClassSchema->getModelType' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\ClassSchema->setUuidPropertyName' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\ClassSchema->getUuidPropertyName' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\ClassSchema->markAsIdentityProperty' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], + 'TYPO3\CMS\Extbase\Reflection\ClassSchema->getIdentityProperties' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-57594-OptimizeReflectionServiceCacheHandling.rst', + ], + ], ]; diff --git a/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache.html b/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache.html deleted file mode 100644 index fd3b8269ac2cb285670394e668029bdac00de484..0000000000000000000000000000000000000000 --- a/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache.html +++ /dev/null @@ -1,27 +0,0 @@ -<div class="panel panel-default"> - <div class="panel-heading" role="tab" id="headingThree"> - <h4 class="panel-title"> - <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="true" aria-controls="collapseThree" class="collapsed"> - <span class="caret"></span> - Extbase object cache - </a> - </h4> - </div> - <div id="collapseThree" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree"> - <div class="panel-body"> - <p> - To speed up object instantiation, Extbase stores some cache data. This can lead - to lots of SELECT database queries on each page hit if the cache is configured - to use the default database cache backend. - </p> - <p> - This cache is limited in size, uses no tagging, and is used multiple times - for one request. These characteristics make it well suited to be used in - combination with a APC cache backend. - </p> - <f:for each="{feature.presetsOrderedByPriority}" as="preset"> - <f:render partial="Settings/Presets/{feature.name}/{preset.name}" arguments="{_all}" /> - </f:for> - </div> - </div> -</div> \ No newline at end of file diff --git a/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache/Apc.html b/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache/Apc.html deleted file mode 100644 index c2ce156928807b4149e00c8614ad8d3646b0d9f6..0000000000000000000000000000000000000000 --- a/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache/Apc.html +++ /dev/null @@ -1,37 +0,0 @@ -<div class="alert {f:if(condition:'{preset.isAvailable}', then:'alert-success', else:'alert-warning')}"> - <div class="header-container"> - <div class="message-header"> - <input - type="radio" - class="t3-install-tool-configuration-radio" - id="t3-install-tool-configuration-extbaseobjectcache-apc" - name="install[values][{feature.name}][enable]" - value="{preset.name}" - {f:if(condition:'{preset.isAvailable}', then:'', else:'disabled="disabled"')} - {f:if(condition: preset.isActive, then:'checked="checked"')} - /> - <label - for="t3-install-tool-configuration-extbaseobjectcache-apc" - class="t3-install-tool-configuration-radio-label" - > - <strong> - APC cache backend - </strong> - {f:if(condition: preset.isActive, then:' [Active]')} - </label> - </div> - </div> - <div class="message-body>"> - <f:if condition="{preset.isAvailable}"> - <f:then> - Use APC cache backend. This reduces your MySQL load and - speeds up lots of TYPO3 CMS requests. Use if available. - </f:then> - <f:else> - APCu 4.x is not loaded or not enough memory is left. APC should - have at least 5MB free memory. - </f:else> - </f:if> - </div> -</div> -<p></p> diff --git a/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache/Apcu.html b/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache/Apcu.html deleted file mode 100644 index c59e654a4a98f7200cdb474fcf274e2631ffa37d..0000000000000000000000000000000000000000 --- a/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache/Apcu.html +++ /dev/null @@ -1,37 +0,0 @@ -<div class="alert {f:if(condition:'{preset.isAvailable}', then:'alert-success', else:'alert-warning')}"> - <div class="header-container"> - <div class="message-header"> - <input - type="radio" - class="t3-install-tool-configuration-radio" - id="t3-install-tool-configuration-extbaseobjectcache-apc" - name="install[values][{feature.name}][enable]" - value="{preset.name}" - {f:if(condition:'{preset.isAvailable}', then:'', else:'disabled="disabled"')} - {f:if(condition: preset.isActive, then:'checked="checked"')} - /> - <label - for="t3-install-tool-configuration-extbaseobjectcache-apc" - class="t3-install-tool-configuration-radio-label" - > - <strong> - APCu cache backend - </strong> - {f:if(condition: preset.isActive, then:' [Active]')} - </label> - </div> - </div> - <div class="message-body>"> - <f:if condition="{preset.isAvailable}"> - <f:then> - Use APCu (APC Userland) cache backend. This reduces your MySQL load and - speeds up lots of TYPO3 CMS requests. Use if available. - </f:then> - <f:else> - APCu 5+ is not loaded or not enough memory is left. APCu should - have at least 5MB free memory. - </f:else> - </f:if> - </div> -</div> -<p></p> diff --git a/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache/Database.html b/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache/Database.html deleted file mode 100644 index ed764522ee2313dff87c8ea519fceb9435b6f3d1..0000000000000000000000000000000000000000 --- a/typo3/sysext/install/Resources/Private/Partials/Settings/Presets/ExtbaseObjectCache/Database.html +++ /dev/null @@ -1,28 +0,0 @@ -<div class="alert alert-success"> - <div class="header-container"> - <div class="message-header"> - <input - type="radio" - class="t3-install-tool-configuration-radio" - id="t3-install-tool-configuration-extbaseobjectcache-database" - name="install[values][{feature.name}][enable]" - value="{preset.name}" - {f:if(condition: preset.isActive, then:'checked="checked"')} - /> - <label - for="t3-install-tool-configuration-extbaseobjectcache-database" - class="t3-install-tool-configuration-radio-label" - > - <strong> - Database cache backend - </strong> - {f:if(condition: preset.isActive, then:' [Active]')} - </label> - </div> - </div> - <div class="message-body>"> - This default cache backend is always available as a - fallback if APC is not available. - </div> -</div> -<p></p>