Extbase:
authorSebastian Kurfürst <sebastian@typo3.org>
Thu, 18 Jun 2009 11:33:04 +0000 (11:33 +0000)
committerSebastian Kurfürst <sebastian@typo3.org>
Thu, 18 Jun 2009 11:33:04 +0000 (11:33 +0000)
* Added Reflection Cache patch by Niels Pardon. Thanks a lot! (fixes #3294)

typo3/sysext/extbase/Classes/Dispatcher.php
typo3/sysext/extbase/Classes/Reflection/Service.php
typo3/sysext/extbase/ext_localconf.php

index e345f1a..725c9c7 100644 (file)
  * @version $ID:$
  */
 class Tx_Extbase_Dispatcher {
+       /**
+        * @var Tx_Extbase_Reflection_Service
+        */
+       protected $reflectionService;
 
        /**
         * Creates a request an dispatches it to a controller.
@@ -65,6 +69,7 @@ class Tx_Extbase_Dispatcher {
 
                $persistenceSession->commit();
                $persistenceSession->clear();
+               $this->reflectionService->shutdown();
                if (count($response->getAdditionalHeaderData()) > 0) {
                        $GLOBALS['TSFE']->additionalHeaderData[$request->getControllerExtensionName()] = implode("\n", $response->getAdditionalHeaderData());
                }
@@ -87,11 +92,27 @@ class Tx_Extbase_Dispatcher {
                $propertyMapper = t3lib_div::makeInstance('Tx_Extbase_Property_Mapper');
                $controller->injectPropertyMapper($propertyMapper);
                $controller->injectSettings($this->getSettings($request));
-               $reflectionService = t3lib_div::makeInstance('Tx_Extbase_Reflection_Service');
+               $cacheManager = t3lib_div::makeInstance('t3lib_cache_Manager');
+               $this->reflectionService = t3lib_div::makeInstance('Tx_Extbase_Reflection_Service');
+               try {
+                       $this->reflectionService->setCache($cacheManager->getCache('Tx_Extbase_Reflection'));
+               } catch (t3lib_cache_exception_NoSuchCache $exception) {
+                       $cacheFactory = t3lib_div::makeInstance('t3lib_cache_Factory');
+                       $cacheFactory->create(
+                               'Tx_Extbase_Reflection',
+                               't3lib_cache_frontend_VariableFrontend',
+                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['Tx_Extbase_Reflection']['backend'],
+                               $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['Tx_Extbase_Reflection']['options']
+                       );
+                       $this->reflectionService->setCache($cacheManager->getCache('Tx_Extbase_Reflection'));
+               }
+               if (!$this->reflectionService->isInitialized()) {
+                       $this->reflectionService->initialize();
+               }
                $validatorResolver = t3lib_div::makeInstance('Tx_Extbase_Validation_ValidatorResolver');
-               $validatorResolver->injectReflectionService($reflectionService);
+               $validatorResolver->injectReflectionService($this->reflectionService);
                $controller->injectValidatorResolver($validatorResolver);
-               $controller->injectReflectionService($reflectionService);
+               $controller->injectReflectionService($this->reflectionService);
                return $controller;
        }
 
index be01947..d4a164d 100644 (file)
 class Tx_Extbase_Reflection_Service implements t3lib_Singleton {
 
        /**
-        * List of tags which are ignored while reflecting class and method annotations
+        * Whether this service has been initialized.
+        *
+        * @var boolean
+        */
+       protected $initialized = FALSE;
+
+       /**
+        * @var t3lib_cache_frontend_VariableFrontend
+        */
+       protected $cache;
+
+       /**
+        * Whether class alterations should be detected on each initialization.
+        *
+        * @var boolean
+        */
+       protected $detectClassChanges = FALSE;
+
+       /**
+        * All available class names to consider. Class name = key, value is the
+        * UNIX timestamp the class was reflected.
         *
         * @var array
         */
-       protected $ignoredTags = array('package', 'subpackage', 'license', 'copyright', 'author', 'version', 'const');
+       protected $reflectedClassNames = array();
 
        /**
-        * @var array Array of array of method tags values by class name and method name
+        * Array of tags and the names of classes which are tagged with them.
+        *
+        * @var array
+        */
+       protected $taggedClasses = array();
+
+       /**
+        * Array of class names and their tags and values.
+        *
+        * @var array
         */
-       protected $methodTagsValues;
+       protected $classTagsValues = array();
 
        /**
-        * @var array Array of array of method parameters by class name and method name
+        * Array of class names, method names and their tags and values.
+        *
+        * @var array
         */
-       protected $methodParameters;
-       
+       protected $methodTagsValues = array();
+
        /**
-        * Array of class names and names of their properties
+        * Array of class names, method names, their parameters and additional
+        * information about the parameters.
+        *
+        * @var array
+        */
+       protected $methodParameters = array();
+
+       /**
+        * Array of class names and names of their properties.
         *
         * @var array
         */
        protected $classPropertyNames = array();
 
+       /**
+        * Array of class names, property names and their tags and values.
+        *
+        * @var array
+        */
+       protected $propertyTagsValues = array();
+
+       /**
+        * List of tags which are ignored while reflecting class and method annotations.
+        *
+        * @var array
+        */
+       protected $ignoredTags = array('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 boolean
+        */
+       protected $cacheNeedsUpdate = FALSE;
+
+       /**
+        * Sets the cache.
+        *
+        * The cache must be set before initializing the Reflection Service.
+        *
+        * @param t3lib_cache_frontend_VariableFrontend $cache Cache for the Reflection service
+        * @return void
+        */
+       public function setCache(t3lib_cache_frontend_VariableFrontend $cache) {
+               $this->cache = $cache;
+       }
+
+       /**
+        * Initializes this service
+        *
+        * @param array $classNamesToReflect Names of available classes to consider in this reflection service
+        * @return void
+        * @internal
+        */
+       public function initialize() {
+               if ($this->initialized) throw new Tx_Extbase_Reflection_Exception('The Reflection Service can only be initialized once.', 1232044696);
+
+               $this->loadFromCache();
+
+               $this->initialized = TRUE;
+       }
+
+       /**
+        * Returns whether the Reflection Service is initialized.
+        *
+        * @return boolean true if the Reflection Service is initialized, otherwise false
+        * @internal
+        */
+       public function isInitialized() {
+               return $this->initialized;
+       }
+
+       /**
+        * Shuts the Reflection Service down.
+        *
+        * @return void
+        * @internal
+        */
+       public function shutdown() {
+               if ($this->cacheNeedsUpdate) {
+                       $this->saveToCache();
+               }
+       }
 
        /**
         * Returns the names of all properties of the specified class
@@ -162,8 +276,10 @@ class Tx_Extbase_Reflection_Service implements t3lib_Singleton {
                        }
                }
                ksort($this->reflectedClassNames);
+
+               $this->cacheNeedsUpdate = TRUE;
        }
-       
+
        /**
         * Converts the given parameter reflection into an information array
         *
@@ -201,18 +317,64 @@ class Tx_Extbase_Reflection_Service implements t3lib_Singleton {
                return $parameterInformation;
        }
 
-       protected function getClassReflection($className) {
-               if (!isset($this->classReflections[$className])) {
-                       $this->classReflections[$className] = new Tx_Extbase_Reflection_ClassReflection($className);
-               }
-               return $this->classReflections[$className];
-       }
-
+       /**
+        * 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 Tx_Extbase_Reflection_MethodReflection the method Reflection object
+        */
        protected function getMethodReflection($className, $methodName) {
                if (!isset($this->methodReflections[$className][$methodName])) {
                        $this->methodReflections[$className][$methodName] = new Tx_Extbase_Reflection_MethodReflection($className, $methodName);
+                       $this->cacheNeedsUpdate = TRUE;
                }
                return $this->methodReflections[$className][$methodName];
        }
+
+       /**
+        * Tries to load the reflection data from this service's cache.
+        *
+        * @return void
+        * @internal
+        */
+       protected function loadFromCache() {
+               if ($this->cache->has('ReflectionData')) {
+                       $data = $this->cache->get('ReflectionData');
+                       foreach ($data as $propertyName => $propertyValue) {
+                               $this->$propertyName = $propertyValue;
+                       }
+               }
+       }
+
+       /**
+        * Exports the internal reflection data into the ReflectionData cache.
+        *
+        * @return void
+        * @internal
+        */
+       protected function saveToCache() {
+               if (!is_object($this->cache)) {
+                       throw new Tx_Extbase_Reflection_Exception(
+                               'A cache must be injected before initializing the Reflection Service.',
+                               1232044697
+                       );
+               }
+
+               $data = array();
+               $propertyNames = array(
+                       'reflectedClassNames',
+                       'classPropertyNames',
+                       'classTagsValues',
+                       'methodTagsValues',
+                       'methodParameters',
+                       'propertyTagsValues',
+                       'taggedClasses'
+               );
+               foreach ($propertyNames as $propertyName) {
+                       $data[$propertyName] = $this->$propertyName;
+               }
+               $this->cache->set('ReflectionData', $data);
+       }
 }
 ?>
\ No newline at end of file
index b6dc1ca..b009a46 100644 (file)
@@ -4,5 +4,12 @@ if (!defined ('TYPO3_MODE'))   die ('Access denied.');
 require_once(t3lib_extMgm::extPath('extbase') . 'Classes/Dispatcher.php');
 spl_autoload_register(array('Tx_Extbase_Dispatcher', 'autoloadClass'));
 
+$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['Tx_Extbase_Reflection'] = array(
+       'backend' => 't3lib_cache_backend_FileBackend',
+       'options' => array(
+               'cacheDirectory' => 'typo3temp/cache/Tx_Extbase_Reflection/'
+       ),
+);
+
 # $GLOBALS ['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = 'EXT:extbase/Classes/Persistence/Hook/TCEMainValueObjectUpdater.php:tx_Extbase_Persistence_Hook_TCEMainValueObjectUpdater';
 ?>
\ No newline at end of file