/** * Filter found entities if needed * * @param array $output * @return array */ protected function _filterEntities(array $output) { $entitySuffix = '\\' . ucfirst(ProxyGenerator::ENTITY_TYPE); $filteredEntities = []; foreach ($output as $className) { $entityName = substr($className, -strlen($entitySuffix)) === $entitySuffix ? substr($className, 0, -strlen($entitySuffix)) : $className; $isClassExists = false; try { $isClassExists = class_exists($className); } catch (\RuntimeException $e) { } if (false === $isClassExists) { if (class_exists($entityName) || interface_exists($entityName)) { array_push($filteredEntities, $className); } else { $this->_log->add( \Magento\Setup\Module\Di\Compiler\Log\Log::CONFIGURATION_ERROR, $className, 'Invalid proxy class for ' . substr($className, 0, -5) ); } } } return $filteredEntities; }
/** * Retrieves list of classes for given path * * @param string $path path to dir with files * * @return array */ public function getList($path) { $nameList = []; foreach ($this->classesScanner->getList($path) as $className) { try { if (!strpos($path, 'generation')) { // validate all classes except classes in var/generation dir $this->validator->validate($className); } $nameList[] = $className; } catch (\Magento\Framework\Exception\ValidatorException $exception) { $this->log->add(Log::COMPILATION_ERROR, $className, $exception->getMessage()); } catch (\ReflectionException $e) { $this->log->add(Log::COMPILATION_ERROR, $className, $e->getMessage()); } } $this->log->report(); return $nameList; }
/** * Fetch factories from class constructor * * @param \ReflectionClass $reflectionClass * @param string $file * @return string[] */ protected function _fetchFactories($reflectionClass, $file) { $factorySuffix = '\\' . ucfirst(FactoryGenerator::ENTITY_TYPE); $absentFactories = $this->_findMissingClasses($file, $reflectionClass, '__construct', ucfirst(FactoryGenerator::ENTITY_TYPE)); foreach ($absentFactories as $key => $absentFactory) { if (substr($absentFactory, -strlen($factorySuffix)) == $factorySuffix) { $entityName = rtrim(substr($absentFactory, 0, -strlen($factorySuffix)), '\\'); $this->_log->add(Log::CONFIGURATION_ERROR, $absentFactory, 'Invalid Factory declaration for class ' . $entityName . ' in file ' . $file); unset($absentFactories[$key]); } } return $absentFactories; }
/** * Retrieves list of classes for given path * * @param string $path path to dir with files * * @return array */ public function getList($path) { foreach ($this->classesScanner->getList($path) as $className) { $this->current = $className; // for errorHandler function try { if ($path != $this->generationDir) { // validate all classes except classes in generation dir $this->validator->validate($className); } $this->relations[$className] = $this->classReader->getParents($className); } catch (\Magento\Framework\Exception\ValidatorException $exception) { $this->log->add(Log::COMPILATION_ERROR, $className, $exception->getMessage()); } catch (\ReflectionException $e) { $this->log->add(Log::COMPILATION_ERROR, $className, $e->getMessage()); } } return $this->relations; }
/** * Compile Code * * @param string $generationDir * @param array $fileExcludePatterns * @param InputInterface $input * @return void * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ private function compileCode($generationDir, $fileExcludePatterns, $input) { $diDir = $input->getOption(self::INPUT_KEY_DI) ? $input->getOption(self::INPUT_KEY_DI) : $this->directoryList->getPath(DirectoryList::DI); $relationsFile = $diDir . '/relations.ser'; $pluginDefFile = $diDir . '/plugins.ser'; $compilationDirs = [$this->directoryList->getPath(DirectoryList::SETUP) . '/Magento/Setup/Module', $this->directoryList->getRoot() . '/dev/tools/Magento/Tools']; $compilationDirs = array_merge($compilationDirs, $this->componentRegistrar->getPaths(ComponentRegistrar::MODULE), $this->componentRegistrar->getPaths(ComponentRegistrar::LIBRARY)); $serializer = $input->getOption(self::INPUT_KEY_SERIALIZER) == Igbinary::NAME ? new Igbinary() : new Standard(); // 2.1 Code scan $validator = new \Magento\Framework\Code\Validator(); $validator->add(new \Magento\Framework\Code\Validator\ConstructorIntegrity()); $validator->add(new \Magento\Framework\Code\Validator\ContextAggregation()); $classesScanner = new \Magento\Setup\Module\Di\Code\Reader\ClassesScanner(); $classesScanner->addExcludePatterns($fileExcludePatterns); $directoryInstancesNamesList = new \Magento\Setup\Module\Di\Code\Reader\Decorator\Directory($this->log, new \Magento\Framework\Code\Reader\ClassReader(), $classesScanner, $validator, $generationDir); foreach ($compilationDirs as $path) { if (is_readable($path)) { $directoryInstancesNamesList->getList($path); } } $inheritanceScanner = new Scanner\InheritanceInterceptorScanner(); $this->entities['interceptors'] = $inheritanceScanner->collectEntities(get_declared_classes(), $this->entities['interceptors']); // 2.1.1 Generation of Proxy and Interceptor Classes foreach (['interceptors', 'di'] as $type) { foreach ($this->entities[$type] as $entityName) { switch ($this->generator->generateClass($entityName)) { case \Magento\Framework\Code\Generator::GENERATION_SUCCESS: $this->log->add(Log::GENERATION_SUCCESS, $entityName); break; case \Magento\Framework\Code\Generator::GENERATION_ERROR: $this->log->add(Log::GENERATION_ERROR, $entityName); break; case \Magento\Framework\Code\Generator::GENERATION_SKIP: default: //no log break; } } } //2.1.2 Compile relations for Proxy/Interceptor classes $directoryInstancesNamesList->getList($generationDir); $relations = $directoryInstancesNamesList->getRelations(); // 2.2 Compression $relationsFileDir = dirname($relationsFile); if (!file_exists($relationsFileDir)) { mkdir($relationsFileDir, DriverInterface::WRITEABLE_DIRECTORY_MODE, true); } $relations = array_filter($relations); file_put_contents($relationsFile, $serializer->serialize($relations)); // 3. Plugin Definition Compilation $pluginScanner = new Scanner\CompositeScanner(); $pluginScanner->addChild(new Scanner\PluginScanner(), 'di'); $pluginDefinitions = []; $pluginList = $pluginScanner->collectEntities($this->files); $pluginDefinitionList = new \Magento\Framework\Interception\Definition\Runtime(); foreach ($pluginList as $type => $entityList) { foreach ($entityList as $entity) { $pluginDefinitions[ltrim($entity, '\\')] = $pluginDefinitionList->getMethodList($entity); } } $outputContent = $serializer->serialize($pluginDefinitions); $pluginDefFileDir = dirname($pluginDefFile); if (!file_exists($pluginDefFileDir)) { mkdir($pluginDefFileDir, DriverInterface::WRITEABLE_DIRECTORY_MODE, true); } file_put_contents($pluginDefFile, $outputContent); }