Example #1
0
 /**
  * Analyzes the Object Configuration provided by the compiler and builds the necessary PHP code for the proxy classes
  * to realize dependency injection.
  *
  * @return void
  */
 public function build()
 {
     $this->objectConfigurations = $this->objectManager->getObjectConfigurations();
     foreach ($this->objectConfigurations as $objectName => $objectConfiguration) {
         $className = $objectConfiguration->getClassName();
         if ($this->compiler->hasCacheEntryForClass($className) === TRUE) {
             continue;
         }
         if ($objectName !== $className || $this->reflectionService->isClassAbstract($className) || $this->reflectionService->isClassFinal($className)) {
             continue;
         }
         $proxyClass = $this->compiler->getProxyClass($className);
         if ($proxyClass === FALSE) {
             continue;
         }
         $this->systemLogger->log('Building DI proxy for "' . $className . '".', LOG_DEBUG);
         $constructorPreCode = '';
         $constructorPostCode = '';
         $constructorPreCode .= $this->buildSetInstanceCode($objectConfiguration);
         $constructorPreCode .= $this->buildConstructorInjectionCode($objectConfiguration);
         $wakeupMethod = $proxyClass->getMethod('__wakeup');
         $wakeupMethod->addPreParentCallCode($this->buildSetInstanceCode($objectConfiguration));
         $wakeupMethod->addPreParentCallCode($this->buildSetRelatedEntitiesCode());
         $wakeupMethod->addPostParentCallCode($this->buildLifecycleInitializationCode($objectConfiguration, \TYPO3\FLOW3\Object\ObjectManagerInterface::INITIALIZATIONCAUSE_RECREATED));
         $wakeupMethod->addPostParentCallCode($this->buildLifecycleShutdownCode($objectConfiguration));
         $sleepMethod = $proxyClass->getMethod('__sleep');
         $sleepMethod->addPostParentCallCode($this->buildSerializeRelatedEntitiesCode($objectConfiguration));
         $searchForEntitiesAndStoreIdentifierArrayMethod = $proxyClass->getMethod('searchForEntitiesAndStoreIdentifierArray');
         $searchForEntitiesAndStoreIdentifierArrayMethod->setMethodParametersCode('$path, $propertyValue, $originalPropertyName');
         $searchForEntitiesAndStoreIdentifierArrayMethod->overrideMethodVisibility('private');
         $searchForEntitiesAndStoreIdentifierArrayMethod->addPreParentCallCode($this->buildSearchForEntitiesAndStoreIdentifierArrayCode());
         $injectPropertiesCode = $this->buildPropertyInjectionCode($objectConfiguration);
         if ($injectPropertiesCode !== '') {
             $proxyClass->getMethod('FLOW3_Proxy_injectProperties')->addPreParentCallCode($injectPropertiesCode);
             $proxyClass->getMethod('FLOW3_Proxy_injectProperties')->overrideMethodVisibility('private');
             $wakeupMethod->addPreParentCallCode("\t\t\$this->FLOW3_Proxy_injectProperties();\n");
             $constructorPostCode .= '		if (\'' . $className . '\' === get_class($this)) {' . "\n";
             $constructorPostCode .= '			$this->FLOW3_Proxy_injectProperties();' . "\n";
             $constructorPostCode .= '		}' . "\n";
         }
         $constructorPostCode .= $this->buildLifecycleInitializationCode($objectConfiguration, \TYPO3\FLOW3\Object\ObjectManagerInterface::INITIALIZATIONCAUSE_CREATED);
         $constructorPostCode .= $this->buildLifecycleShutdownCode($objectConfiguration);
         $constructor = $proxyClass->getConstructor();
         $constructor->addPreParentCallCode($constructorPreCode);
         $constructor->addPostParentCallCode($constructorPostCode);
     }
 }
Example #2
0
 /**
  * Compiles the configured proxy classes and methods as static PHP code and stores it in the proxy class code cache.
  * Also builds the static object container which acts as a registry for non-prototype objects during runtime.
  *
  * @return integer Number of classes which have been compiled
  */
 public function compile()
 {
     $classCount = 0;
     foreach ($this->objectManager->getRegisteredClassNames() as $fullOriginalClassNames) {
         foreach ($fullOriginalClassNames as $fullOriginalClassName) {
             if (isset($this->proxyClasses[$fullOriginalClassName])) {
                 $proxyClassCode = $this->proxyClasses[$fullOriginalClassName]->render();
                 if ($proxyClassCode !== '') {
                     $this->classesCache->set(str_replace('\\', '_', $fullOriginalClassName), $proxyClassCode);
                     $class = new \ReflectionClass($fullOriginalClassName);
                     $classPathAndFilename = $class->getFileName();
                     $this->cacheOriginalClassFile($fullOriginalClassName, $classPathAndFilename);
                     $classCount++;
                 }
             }
         }
     }
     return $classCount;
 }
Example #3
0
 /**
  * Builds proxy class code which weaves advices into the respective target classes.
  *
  * The object configurations provided by the Compiler are searched for possible aspect
  * annotations. If an aspect class is found, the poincut expressions are parsed and
  * a new aspect with one or more advisors is added to the aspect registry of the AOP framework.
  * Finally all advices are woven into their target classes by generating proxy classes.
  *
  * In general, the command typo3.flow3:core:compile is responsible for compilation
  * and calls this method to do so.
  *
  * In order to distinguish between an emerged / changed possible target class and
  * a class which has been matched previously but just didn't have to be proxied,
  * the latter are kept track of by an "unproxiedClass-*" cache entry.
  *
  * @return void
  */
 public function build()
 {
     $allAvailableClassNamesByPackage = $this->objectManager->getRegisteredClassNames();
     $possibleTargetClassNames = $this->getProxyableClasses($allAvailableClassNamesByPackage);
     $actualAspectClassNames = $this->reflectionService->getClassNamesByAnnotation('TYPO3\\FLOW3\\Annotations\\Aspect');
     sort($possibleTargetClassNames);
     sort($actualAspectClassNames);
     $this->aspectContainers = $this->buildAspectContainers($actualAspectClassNames);
     $rebuildEverything = FALSE;
     if ($this->objectConfigurationCache->has('allAspectClassesUpToDate') === FALSE) {
         $rebuildEverything = TRUE;
         $this->systemLogger->log('Aspects have been modified, therefore rebuilding all target classes.', LOG_INFO);
         $this->objectConfigurationCache->set('allAspectClassesUpToDate', TRUE);
     }
     $possibleTargetClassNameIndex = new ClassNameIndex();
     $possibleTargetClassNameIndex->setClassNames($possibleTargetClassNames);
     $targetClassNameCandidates = new ClassNameIndex();
     foreach ($this->aspectContainers as $aspectContainer) {
         $targetClassNameCandidates->applyUnion($aspectContainer->reduceTargetClassNames($possibleTargetClassNameIndex));
     }
     $targetClassNameCandidates->sort();
     foreach ($targetClassNameCandidates->getClassNames() as $targetClassName) {
         $isUnproxied = $this->objectConfigurationCache->has('unproxiedClass-' . str_replace('\\', '_', $targetClassName));
         $hasCacheEntry = $this->compiler->hasCacheEntryForClass($targetClassName) || $isUnproxied;
         if ($rebuildEverything === TRUE || $hasCacheEntry === FALSE) {
             $proxyBuildResult = $this->buildProxyClass($targetClassName, $this->aspectContainers);
             if ($proxyBuildResult !== FALSE) {
                 if ($isUnproxied) {
                     $this->objectConfigurationCache->remove('unproxiedClass-' . str_replace('\\', '_', $targetClassName));
                 }
                 $this->systemLogger->log(sprintf('Built AOP proxy for class "%s".', $targetClassName), LOG_DEBUG);
             } else {
                 $this->objectConfigurationCache->set('unproxiedClass-' . str_replace('\\', '_', $targetClassName), TRUE);
             }
         }
     }
 }