/** * @param SplFileInfo[] $files */ public function parse($files) { foreach ($files as $file) { $content = $this->charsetConvertor->convertFileToUtf($file->getPathname()); try { $this->broker->processString($content, $file->getPathname()); } catch (FileProcessingException $exception) { $this->errors[] = $exception; } } $this->extractBrokerDataForParserResult($this->broker); }
/** * This method may transform the supplied source and return a new replacement for it * * @param StreamMetaData $metadata Metadata for source * @return void|bool Return false if transformation should be stopped */ public function transform(StreamMetaData $metadata) { $totalTransformations = 0; $fileName = $metadata->uri; try { CleanableMemory::enterProcessing(); $parsedSource = $this->broker->processString($metadata->source, $fileName, true); } catch (FileProcessingException $e) { CleanableMemory::leaveProcessing(); return false; } // Check if we have some new aspects that weren't loaded yet $unloadedAspects = $this->aspectLoader->getUnloadedAspects(); if ($unloadedAspects) { $this->loadAndRegisterAspects($unloadedAspects); } $advisors = $this->container->getByTag('advisor'); /** @var $namespaces ParsedFileNamespace[] */ $namespaces = $parsedSource->getNamespaces(); $lineOffset = 0; foreach ($namespaces as $namespace) { /** @var $classes ParsedClass[] */ $classes = $namespace->getClasses(); foreach ($classes as $class) { $parentClassNames = array_merge($class->getParentClassNameList(), $class->getInterfaceNames(), $class->getTraitNames()); foreach ($parentClassNames as $parentClassName) { class_exists($parentClassName); // trigger autoloading of class/interface/trait } // Skip interfaces and aspects if ($class->isInterface() || in_array('Go\\Aop\\Aspect', $class->getInterfaceNames())) { continue; } $wasClassProcessed = $this->processSingleClass($advisors, $metadata, $class, $lineOffset); $totalTransformations += (int) $wasClassProcessed; } $wasFunctionsProcessed = $this->processFunctions($advisors, $metadata, $namespace); $totalTransformations += (int) $wasFunctionsProcessed; } CleanableMemory::leaveProcessing(); // If we return false this will indicate no more transformation for following transformers return $totalTransformations > 0; }
/** * This method may transform the supplied source and return a new replacement for it * * @param StreamMetaData $metadata Metadata for source * @return void */ public function transform(StreamMetaData $metadata) { $fileName = $metadata->uri; if (!$this->isAllowedToTransform($fileName)) { return; } try { CleanableMemory::enterProcessing(); $parsedSource = $this->broker->processString($metadata->source, $fileName, true); } catch (FileProcessingException $e) { // TODO: collect this exception and make a record in the modified source // TODO: Maybe just ask a developer to add this file into exclude list? CleanableMemory::leaveProcessing(); return; } /** @var $namespaces ParsedFileNamespace[] */ $namespaces = $parsedSource->getNamespaces(); $lineOffset = 0; foreach ($namespaces as $namespace) { /** @var $classes ParsedClass[] */ $classes = $namespace->getClasses(); foreach ($classes as $class) { $parentClassNames = array_merge($class->getParentClassNameList(), $class->getInterfaceNames(), $class->getTraitNames()); foreach ($parentClassNames as $parentClassName) { class_exists($parentClassName); // trigger autoloading of class/interface/trait } // Skip interfaces and aspects if ($class->isInterface() || in_array('Go\\Aop\\Aspect', $class->getInterfaceNames())) { continue; } $this->processSingleClass($metadata, $class, $lineOffset); } $this->processFunctions($metadata, $namespace); } CleanableMemory::leaveProcessing(); }
/** * You can modify the container here before it is dumped to PHP code. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { /** @var \SplFileInfo[] $files */ $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS)); foreach ($files as $file) { if ($file->getExtension() !== 'php') { continue; } $content = file_get_contents($file->getPathname()); if (strpos($content, '@Component') === false) { continue; } $reflectionFile = $this->broker->processString($content, $file->getPathname(), true); /** @var ReflectionFileNamespace[] $namespaces */ $namespaces = $reflectionFile->getNamespaces(); foreach ($namespaces as $namespace) { $classes = $namespace->getClasses(); foreach ($classes as $class) { $this->checkAndRegisterComponent($class, $container); } } } $container->addResource(new DirectoryResource($this->directory)); }
/** * Scans and parses PHP files. * * @return array * @throws \RuntimeException If no PHP files have been found. */ public function parse() { $files = array(); $flags = \RecursiveDirectoryIterator::CURRENT_AS_FILEINFO | \RecursiveDirectoryIterator::SKIP_DOTS; if (defined('\\RecursiveDirectoryIterator::FOLLOW_SYMLINKS')) { // Available from PHP 5.3.1 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; } foreach ($this->config->source as $source) { $entries = array(); if (is_dir($source)) { foreach (new \RecursiveIteratorIterator(new SourceFilesFilterIterator(new \RecursiveDirectoryIterator($source, $flags), $this->config->exclude)) as $entry) { if (!$entry->isFile()) { continue; } $entries[] = $entry; } } elseif ($this->isPhar($source)) { if (!extension_loaded('phar')) { throw new RuntimeException('Phar extension is not loaded'); } foreach (new \RecursiveIteratorIterator(new \Phar($source, $flags)) as $entry) { if (!$entry->isFile()) { continue; } $entries[] = $entry; } } else { $entries[] = new \SplFileInfo($source); } $regexp = '~\\.' . implode('|', $this->config->extensions->toArray()) . '$~i'; foreach ($entries as $entry) { if (!preg_match($regexp, $entry->getFilename())) { continue; } $pathName = $this->normalizePath($entry->getPathName()); $files[$pathName] = $entry->getSize(); if (false !== $entry->getRealPath() && $pathName !== $entry->getRealPath()) { $this->symlinks[$entry->getRealPath()] = $pathName; } } } if (empty($files)) { throw new RuntimeException('No PHP files found'); } $this->fireEvent('parseStart', array_sum($files)); $broker = new Broker(new Backend($this, !empty($this->config->report)), Broker::OPTION_DEFAULT & ~(Broker::OPTION_PARSE_FUNCTION_BODY | Broker::OPTION_SAVE_TOKEN_STREAM)); $errors = array(); foreach ($files as $filePath => $size) { $content = $this->charsetConvertor->convertFile($filePath); try { $broker->processString($content, $filePath); } catch (\Exception $e) { $errors[] = $e; } $this->fireEvent('parseProgress', $size); } // Classes $this->parsedClasses->exchangeArray($broker->getClasses(Backend::TOKENIZED_CLASSES | Backend::INTERNAL_CLASSES | Backend::NONEXISTENT_CLASSES)); $this->parsedClasses->uksort('strcasecmp'); // Constants $this->parsedConstants->exchangeArray($broker->getConstants()); $this->parsedConstants->uksort('strcasecmp'); // Functions $this->parsedFunctions->exchangeArray($broker->getFunctions()); $this->parsedFunctions->uksort('strcasecmp'); $documentedCounter = function ($count, $element) { return $count += (int) $element->isDocumented(); }; return (object) array('classes' => count($broker->getClasses(Backend::TOKENIZED_CLASSES)), 'constants' => count($this->parsedConstants), 'functions' => count($this->parsedFunctions), 'internalClasses' => count($broker->getClasses(Backend::INTERNAL_CLASSES)), 'documentedClasses' => array_reduce($broker->getClasses(Backend::TOKENIZED_CLASSES), $documentedCounter), 'documentedConstants' => array_reduce($this->parsedConstants->getArrayCopy(), $documentedCounter), 'documentedFunctions' => array_reduce($this->parsedFunctions->getArrayCopy(), $documentedCounter), 'documentedInternalClasses' => array_reduce($broker->getClasses(Backend::INTERNAL_CLASSES), $documentedCounter), 'errors' => $errors); }