Ejemplo n.º 1
0
 /**
  * Traverses through the given class and interface names and builds a base object configuration
  * for all of them. Then parses the provided extra configuration and merges the result
  * into the overall configuration. Finally autowires dependencies of arguments and properties
  * which can be resolved automatically.
  *
  * @param array $availableClassNamesByPackage An array of available class names, grouped by package key
  * @param array $rawObjectConfigurationsByPackages An array of package keys and their raw (ie. unparsed) object configurations
  * @return array<TYPO3\FLOW3\Object\Configuration\Configuration> Object configurations
  * @throws \TYPO3\FLOW3\Object\Exception\InvalidObjectConfigurationException
  */
 public function buildObjectConfigurations(array $availableClassNamesByPackage, array $rawObjectConfigurationsByPackages)
 {
     $objectConfigurations = array();
     foreach ($availableClassNamesByPackage as $packageKey => $classNames) {
         foreach ($classNames as $className) {
             $objectName = $className;
             if ($this->reflectionService->isClassFinal($className)) {
                 continue;
             }
             if (interface_exists($className)) {
                 $interfaceName = $className;
                 $className = $this->reflectionService->getDefaultImplementationClassNameForInterface($interfaceName);
                 if ($className === FALSE) {
                     continue;
                 }
                 if ($this->reflectionService->isClassAnnotatedWith($interfaceName, 'TYPO3\\FLOW3\\Annotations\\Scope')) {
                     throw new \TYPO3\FLOW3\Object\Exception\InvalidObjectConfigurationException(sprintf('Scope annotations in interfaces don\'t have any effect, therefore you better remove it from %s in order to avoid confusion.', $interfaceName), 1299095595);
                 }
             }
             $rawObjectConfiguration = array('className' => $className);
             $rawObjectConfiguration = $this->enhanceRawConfigurationWithAnnotationOptions($className, $rawObjectConfiguration);
             $objectConfigurations[$objectName] = $this->parseConfigurationArray($objectName, $rawObjectConfiguration, 'automatically registered class');
             $objectConfigurations[$objectName]->setPackageKey($packageKey);
         }
     }
     foreach ($rawObjectConfigurationsByPackages as $packageKey => $rawObjectConfigurations) {
         foreach ($rawObjectConfigurations as $objectName => $rawObjectConfiguration) {
             $objectName = str_replace('_', '\\', $objectName);
             if (!is_array($rawObjectConfiguration)) {
                 throw new \TYPO3\FLOW3\Object\Exception\InvalidObjectConfigurationException('Configuration of object "' . $objectName . '" in package "' . $packageKey . '" is not an array, please check your Objects.yaml for syntax errors.', 1295954338);
             }
             $existingObjectConfiguration = isset($objectConfigurations[$objectName]) ? $objectConfigurations[$objectName] : NULL;
             if (isset($rawObjectConfiguration['className'])) {
                 $rawObjectConfiguration = $this->enhanceRawConfigurationWithAnnotationOptions($rawObjectConfiguration['className'], $rawObjectConfiguration);
             }
             $newObjectConfiguration = $this->parseConfigurationArray($objectName, $rawObjectConfiguration, 'configuration of package ' . $packageKey . ', definition for object "' . $objectName . '"', $existingObjectConfiguration);
             if (!isset($objectConfigurations[$objectName]) && !interface_exists($objectName, TRUE) && !class_exists($objectName, FALSE)) {
                 throw new \TYPO3\FLOW3\Object\Exception\InvalidObjectConfigurationException('Tried to configure unknown object "' . $objectName . '" in package "' . $packageKey . '". Please check your Objects.yaml.', 1184926175);
             }
             if ($objectName !== $newObjectConfiguration->getClassName() && !interface_exists($objectName, TRUE)) {
                 throw new \TYPO3\FLOW3\Object\Exception\InvalidObjectConfigurationException('Tried to set a differing class name for class "' . $objectName . '" in the object configuration of package "' . $packageKey . '". Setting "className" is only allowed for interfaces, please check your Objects.yaml."', 1295954589);
             }
             $objectConfigurations[$objectName] = $newObjectConfiguration;
             if ($objectConfigurations[$objectName]->getPackageKey() === NULL) {
                 $objectConfigurations[$objectName]->setPackageKey($packageKey);
             }
         }
     }
     $this->autowireArguments($objectConfigurations);
     $this->autowireProperties($objectConfigurations);
     return $objectConfigurations;
 }
Ejemplo n.º 2
0
 /**
  * Determines which of the given classes are potentially proxyable
  * and returns their names in an array.
  *
  * @param array $classNamesByPackage Names of the classes to check
  * @return array Names of classes which can be proxied
  */
 protected function getProxyableClasses(array $classNamesByPackage)
 {
     $proxyableClasses = array();
     foreach ($classNamesByPackage as $classNames) {
         foreach ($classNames as $className) {
             if (!in_array(substr($className, 0, 15), $this->blacklistedSubPackages)) {
                 if (!$this->reflectionService->isClassAnnotatedWith($className, 'TYPO3\\FLOW3\\Annotations\\Aspect') && !$this->reflectionService->isClassFinal($className)) {
                     $proxyableClasses[] = $className;
                 }
             }
         }
     }
     return $proxyableClasses;
 }
Ejemplo n.º 3
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);
     }
 }