/** * Creates a reflection instance. * * @param \ReflectionClass $internalReflection Internal reflection instance * @param \TokenReflection\Broker $broker Reflection broker instance * * @return \TokenReflection\Php\ReflectionFunction * @throws \TokenReflection\Exception\RuntimeException If an invalid internal reflection object was provided. */ public static function create(Reflector $internalReflection, Broker $broker) { if (!$internalReflection instanceof InternalReflectionFunction) { throw new Exception\RuntimeException('Invalid reflection instance provided, ReflectionFunction expected.', Exception\RuntimeException::INVALID_ARGUMENT); } return $broker->getFunction($internalReflection->getName()); }
/** * @param string $method * @throws InvalidArgumentException * @return MethodElement */ public function getInstance($method = null) { if (!$method) { throw new InvalidArgumentException('Bad method'); } $class = $this->broker->getClass(__CLASS__); return parent::getInstance($class->getMethod($method)); }
public function getNamespaces($requestedNamespace, $inputFolder, $exclude) { $broker = new Broker($backend = new Broker\Backend\Memory()); $broker->processDirectory($inputFolder); $namespaces = $backend->getNamespaces(); ksort($namespaces); $excludedNamespaces = $this->getExcludedNamespaces($exclude); $filteredNamespaces = $this->getFilteredNamespaces($requestedNamespace, $namespaces, $excludedNamespaces); return $filteredNamespaces; }
protected function setUp() { $container = $this->getMock('Go\\Core\\AspectContainer'); $reader = $this->getMock('Doctrine\\Common\\Annotations\\Reader'); $loader = $this->getMock('Go\\Core\\AspectLoader', array(), array($container, $reader)); $this->adviceMatcher = new AdviceMatcher($loader, $container); $brokerInstance = new Broker(new Broker\Backend\Memory()); $brokerInstance->processFile(__FILE__); $this->reflectionClass = $brokerInstance->getClass(__CLASS__); }
/** * Exports a reflected object. * * @param \TokenReflection\Broker $broker Broker instance * @param string $function Function name * @param boolean $return Return the export instead of outputting it * * @return string|null * @throws \TokenReflection\Exception\RuntimeException If requested parameter doesn't exist. */ public static function export(Broker $broker, $function, $return = false) { $functionName = $function; $function = $broker->getFunction($functionName); if (null === $function) { throw new Exception\RuntimeException(sprintf('Function %s() does not exist.', $functionName), Exception\RuntimeException::DOES_NOT_EXIST); } if ($return) { return $function->__toString(); } echo $function->__toString(); }
/** * Exports a reflected object. * * @param \TokenReflection\Broker $broker Broker instance * @param string $namespace Namespace name * @param boolean $return Return the export instead of outputting it * * @return string|null * @throws \TokenReflection\Exception\RuntimeException If requested parameter doesn't exist. */ public static function export(Broker $broker, $namespace, $return = false) { $namespaceName = $namespace; $namespace = $broker->getNamespace($namespaceName); if (null === $namespace) { throw new Exception\RuntimeException(sprintf('Namespace %s does not exist.', $namespaceName), Exception\RuntimeException::DOES_NOT_EXIST); } if ($return) { return $namespace->__toString(); } echo $namespace->__toString(); }
/** * 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; }
/** * Constructor. * * Creates a token substream from a file. * * @param string $fileName File name * @throws \TokenReflection\Exception\StreamException If the file does not exist or is not readable. */ public function __construct($fileName) { parent::__construct(); $this->fileName = Broker::getRealPath($fileName); if (false === $this->fileName) { throw new Exception\StreamException($this, 'File does not exist.', Exception\StreamException::DOES_NOT_EXIST); } $contents = @file_get_contents($this->fileName); if (false === $contents) { throw new Exception\StreamException($this, 'File is not readable.', Exception\StreamException::NOT_READABLE); } $this->processSource($contents); }
/** * Exports a reflected object. * * @param \TokenReflection\Broker $broker Broker instance * @param string|object|null $class Class name, class instance or null * @param string $constant Constant name * @param boolean $return Return the export instead of outputting it * * @return string|null * @throws \TokenReflection\Exception\RuntimeException If requested parameter doesn't exist. */ public static function export(Broker $broker, $class, $constant, $return = false) { $className = is_object($class) ? get_class($class) : $class; $constantName = $constant; if (null === $className) { $constant = $broker->getConstant($constantName); if (null === $constant) { throw new Exception\RuntimeException('Constant does not exist.', Exception\RuntimeException::DOES_NOT_EXIST); } } else { $class = $broker->getClass($className); if ($class instanceof Invalid\ReflectionClass) { throw new Exception\RuntimeException('Class is invalid.', Exception\RuntimeException::UNSUPPORTED); } elseif ($class instanceof Dummy\ReflectionClass) { throw new Exception\RuntimeException('Class does not exist.', Exception\RuntimeException::DOES_NOT_EXIST, $class); } $constant = $class->getConstantReflection($constantName); } if ($return) { return $constant->__toString(); } echo $constant->__toString(); }
/** * 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(); }
/** * Runs the documentation generator * * @access public * @param string $input_path A relative or absolute directory to scan * @return void */ public function run($input_path) { $this->setInputPath($input_path); for ($config_path = realpath($this->inputPath); $config_path != realpath($config_path . DIRECTORY_SEPARATOR . '..') && !is_readable($config_path . DIRECTORY_SEPARATOR . 'sage.config'); $config_path = realpath($config_path . DIRECTORY_SEPARATOR . '..')) { } $this->options = file_exists($config_path . DIRECTORY_SEPARATOR . 'sage.config') ? include $config_path . DIRECTORY_SEPARATOR . 'sage.config' : array(); $reflections = $this->broker->processDirectory($this->inputPath, [], TRUE); $sort_by_type = !empty($this->options['sort_by_type']); $token_parsers = !empty($this->options['token_parsers']) ? $this->options['token_parsers'] : array(); $this->configTokenParsers($token_parsers); $this->makeDocumentCollection($reflections, $sort_by_type); foreach ($reflections as $reflection) { foreach ($reflection->getNamespaces() as $namespace) { // // Add our class type structures // foreach ($namespace->getClasses() as $structure) { $root =& $this->documents; if ($sort_by_type) { if ($structure->isTrait()) { $root =& $this->documents['traits']; } elseif ($structure->isInterface()) { $root =& $this->documents['interfaces']; } else { $root =& $this->documents['classes']; } } foreach (explode('\\', $namespace->getName()) as $segment) { $root =& $root[$segment]; } $root[] = new Document($structure, $this, $namespace); } // // Add our function type structures // foreach ($namespace->getFunctions() as $function) { $root =& $this->documents; if ($sort_by_type) { $root =& $this->documents['functions']; } foreach (explode('\\', $namespace->getName()) as $segment) { $root =& $root[$segment]; } $root[] = new Document($function, $this, $namespace); } } } return $this->documents; }
/** * 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)); }
private function extractBrokerDataForParserResult(Broker $broker) { $allFoundClasses = $broker->getClasses(Backend::TOKENIZED_CLASSES | Backend::INTERNAL_CLASSES | Backend::NONEXISTENT_CLASSES); $classes = new ArrayObject($allFoundClasses); $constants = new ArrayObject($broker->getConstants()); $functions = new ArrayObject($broker->getFunctions()); $internalClasses = new ArrayObject($broker->getClasses(Backend::INTERNAL_CLASSES)); $tokenizedClasses = new ArrayObject($broker->getClasses(Backend::TOKENIZED_CLASSES)); $classes->uksort('strcasecmp'); $constants->uksort('strcasecmp'); $functions->uksort('strcasecmp'); $this->loadToParserResult($classes, $constants, $functions, $internalClasses, $tokenizedClasses); }
/** * Exports a reflected object. * * @param \TokenReflection\Broker $broker Broker instance * @param string|object $class Class name or class instance * @param string $method Method name * @param boolean $return Return the export instead of outputting it * * @return string|null * @throws \TokenReflection\Exception\RuntimeException If requested parameter doesn't exist. */ public static function export(Broker $broker, $class, $method, $return = false) { $className = is_object($class) ? get_class($class) : $class; $methodName = $method; $class = $broker->getClass($className); if ($class instanceof Invalid\ReflectionClass) { throw new Exception\RuntimeException('Class is invalid.', Exception\RuntimeException::UNSUPPORTED); } elseif ($class instanceof Dummy\ReflectionClass) { throw new Exception\RuntimeException(sprintf('Class %s does not exist.', $className), Exception\RuntimeException::DOES_NOT_EXIST); } $method = $class->getMethod($methodName); if ($return) { return $method->__toString(); } echo $method->__toString(); }
/** * Returns an array of tokens for a particular file. * * @param string $fileName File name * @return \TokenReflection\Stream * @throws \RuntimeException If the token stream could not be returned. */ public function getFileTokens($fileName) { try { if (!$this->isFileProcessed($fileName)) { throw new InvalidArgumentException('File was not processed'); } $realName = Broker::getRealPath($fileName); if (!isset($this->fileCache[$realName])) { throw new InvalidArgumentException('File is not in the cache'); } $data = @file_get_contents($this->fileCache[$realName]); if (false === $data) { throw new RuntimeException('Cached file is not readable'); } $file = @unserialize($data); if (false === $file) { throw new RuntimeException('Stream could not be loaded from cache'); } return $file; } catch (\Exception $e) { throw new RuntimeException(sprintf('Could not return token stream for file %s', $fileName), 0, $e); } }
/** * Loads template-specific macro and helper libraries. * * @param \ApiGen\Template $template Template instance */ private function registerCustomTemplateMacros(Template $template) { $latte = new Nette\Latte\Engine(); if (!empty($this->config->template['options']['extensions'])) { $this->output("Loading custom template macro and helper libraries\n"); $broker = new Broker(new Broker\Backend\Memory(), 0); $baseDir = dirname($this->config->template['config']); foreach ((array) $this->config->template['options']['extensions'] as $fileName) { $pathName = $baseDir . DIRECTORY_SEPARATOR . $fileName; if (is_file($pathName)) { try { $reflectionFile = $broker->processFile($pathName, true); foreach ($reflectionFile->getNamespaces() as $namespace) { foreach ($namespace->getClasses() as $class) { if ($class->isSubclassOf('ApiGen\\MacroSet')) { // Macro set include $pathName; call_user_func(array($class->getName(), 'install'), $latte->compiler); $this->output(sprintf(" %s (macro set)\n", $class->getName())); } elseif ($class->implementsInterface('ApiGen\\IHelperSet')) { // Helpers set include $pathName; $className = $class->getName(); $template->registerHelperLoader(callback(new $className($template), 'loader')); $this->output(sprintf(" %s (helper set)\n", $class->getName())); } } } } catch (\Exception $e) { throw new \Exception(sprintf('Could not load macros and helpers from file "%s"', $pathName), 0, $e); } } else { throw new \Exception(sprintf('Helper file "%s" does not exist.', $pathName)); } } } $template->registerFilter($latte); }
/** * Exports a reflected object. * * @param \TokenReflection\Broker $broker Broker instance * @param string|object $className Class name or class instance * @param boolean $return Return the export instead of outputting it * @return string|null * @throws \TokenReflection\Exception\RuntimeException If requested parameter doesn't exist. */ public static function export(Broker $broker, $className, $return = false) { if (is_object($className)) { $className = get_class($className); } $class = $broker->getClass($className); if ($class instanceof Invalid\ReflectionClass) { throw new Exception\RuntimeException('Class is invalid.', Exception\RuntimeException::UNSUPPORTED); } elseif ($class instanceof Dummy\ReflectionClass) { throw new Exception\RuntimeException('Class does not exist.', Exception\RuntimeException::DOES_NOT_EXIST); } if ($return) { return $class->__toString(); } echo $class->__toString(); }
/** * Parse and display the Pocco documentation for the given directory and * all contained PHP files. You may also specify the default file to show * if none has been requested. * * @param string $directory * @param string $file * @return boolean */ public function saveHTML($directory, $default = NULL, $requested = NULL) { $this->broker = $broker = new Broker(new Broker\Backend\Memory()); //Reflection File $rDir = $broker->processDirectory($directory, "*.php", true); $files = array_keys($rDir); array_walk($files, function (&$value, $key) use($directory) { //echo $directory; $value = substr($value, strlen($directory)); }); //sort files into namespaces $this->saveMode = true; $this->savePath = dirname($directory) . "/docs"; foreach ($files as $file) { //Wee need this to fix links if (!$this->isIndex) { $_segments = explode("/", $file); $_levels = count($_segments); //if not saving index for ($_i = 0; $_i < $_levels - 1; $_i++) { $this->saveHierarchy .= "../"; } } //$source = file_get_contents($directory . $file); $sections = $this->parseSource($rDir[$directory . $file], $file, $directory); $this->renderSave($sections, $file, $files, dirname($directory) . "/docs"); //reset this heierarchy $this->saveHierarchy = ""; } //create the index file which should be the first in files; $this->isIndex = true; $this->renderSave($this->parseSource($rDir[$directory . $files[0]], $files[0], $directory), $file, $files, $this->savePath, "index.html"); //copy assets into docs directory; $this->xcopy(BUDKIT_DOCS_PATH . "/assets", $this->savePath . "/assets", 0777); return true; }
private function getTokenizedReflectionClass(\ReflectionClass $class) { $this->broker->processFile($class->getFileName()); return $this->broker->getClass($class->name); }
/** * Data preparer. * * Returns pairs of TokenReflection\Broker where one parses a directory of given type * and the second one parses a PHAR archive that was created from the same directory. * * @param integer $format Archive format * @param integer $compression Archive compression * @param boolean $wholeArchive Use compression for the whole archive * @return array */ private function prepareData($format = Phar::PHAR, $compression = Phar::NONE, $wholeArchive = true) { $dirName = $this->prepareTemporaryStorage(); $directory = realpath(__DIR__ . '/../data/'); $iterator = new \DirectoryIterator($directory); static $skip = array('broker' => true, 'parseerror' => true, 'duplicities' => true); $data = array(); foreach ($iterator as $item) { if (isset($skip[$item->getFileName()])) { continue; } if ($item->isDir() && !$item->isDot()) { $ext = '.phar'; $fileName = $dirName . DIRECTORY_SEPARATOR . uniqid($format . $compression); $phar = new Phar($fileName . $ext); $phar->buildFromDirectory($item->getPathName()); if ($format !== Phar::PHAR) { if ($format === Phar::TAR) { $ext .= '.tar'; } elseif ($format === Phar::ZIP) { $ext .= '.zip'; } $phar->convertToExecutable($format, $wholeArchive ? $compression : Phar::NONE, $ext); } if ($compression !== Phar::NONE && !$wholeArchive) { $phar->compressFiles($compression); } unset($phar); $dataItem = array(array('format' => $format, 'compression' => $compression, 'wholeArchive' => $wholeArchive)); $broker = new Broker(new Broker\Backend\Memory(), 0); $broker->processDirectory($item->getPathName()); $dataItem[] = $broker; $broker2 = new Broker(new Broker\Backend\Memory(), 0); $broker2->process($fileName . $ext); $dataItem[] = $broker2; $data[] = $dataItem; } } $this->cleanUpTemporaryStorage($dirName); return $data; }
/** * @see Symfony\Component\Console\Command.Command::execute() */ protected function execute(InputInterface $input, OutputInterface $output) { $namespace = $input->getArgument('namespace'); $path = $input->getArgument('path'); $out = realpath($input->getOption('output')); $output->writeln(sprintf('<comment>Processing code from namespace %s</comment>', $namespace)); $output->writeln(sprintf('<comment>Processing files from %s</comment>', $path)); $output->writeln(sprintf('<comment>Outputting to %s</comment>', $out)); $output_files = array(); $filters = array(); if ($filtersArgument = trim($input->getOption('filters'))) { $filters = explode(';', $filtersArgument); foreach ($filters as $filter) { $output->writeln(sprintf('<comment>Applying filter %s</comment>', $filter)); } } $broker = new Broker($backend = new Memory()); $broker->processDirectory($path, $filters); $namespaces = $backend->getNamespaces(); ksort($namespaces); $excludes = array(); if ($exclude = trim($input->getOption('exclude'))) { $excludes = explode(';', $exclude); foreach ($excludes as $exclude) { $output->writeln(sprintf('<comment>Excluding code from %s</comment>', $exclude)); } } $filtered = array(); foreach ($namespaces as $n => $reflection) { if (substr($n, 0, strlen($namespace)) != $namespace) { continue; } foreach ($excludes as $exclude) { if (strncmp($n, $exclude, strlen($exclude)) == 0) { continue 2; } } $filtered[$n] = $reflection; } unset($namespaces); $elements = array(); foreach ($filtered as $n => $reflection) { $output->writeln(sprintf('<info>Processing %s</info>', $n)); $element = new NamespaceElement($reflection); $element->buildClasses($out, $output); $elements[$n] = $element; } unset($filtered); foreach ($elements as $n => $element) { $output->writeln(sprintf('<info>Building index for %s</info>', $n)); $options = array(); if ($n == $namespace && $input->getOption('title')) { $options = array('title' => $input->getOption('title')); } $element->buildIndex($out, $output, $options); } }
/** * Will run an inspection for a certain file/directory and will return a version instance * resulting from the changes compared to former inspections * * @param string $srcPath Path to the file/directory to inspect * * @return \Herrera\Version\Builder * * @throws \Exception */ public function runInspection($srcPath) { // check if we got something we can work with if (!is_readable($srcPath)) { throw new \Exception(sprintf('Cannot read from source path %s', $srcPath)); } $broker = new Broker(new Memory()); if (is_dir($srcPath)) { $broker->processDirectory($srcPath); } else { $broker->processFile($srcPath); } // iterate all php files and check for an API annotation $inspector = $this->getInspector(); foreach ($broker->getClasses() as $classReflection) { // we can continue iteration if we did not get any valuable information from this file if (!$classReflection instanceof \TokenReflection\ReflectionClass) { continue; } // if we got the API annotation we have to work with it if ($classReflection->hasAnnotation(ApiAnnotation::ANNOTATION)) { $formerReflection = $this->cache->load($classReflection->getName()); // check for possible changes $inspector->inspect($classReflection, $formerReflection); // save the current reflection object as a base for later comparison $this->cache->store($classReflection); } } // get the result and increment the version accordingly $result = $inspector->getResult(); $incrementationMethod = 'increment' . ucfirst(strtolower($result->getIncrementVersion())); $version = $this->getBaseVersion(); if (method_exists($version, $incrementationMethod)) { $version->{$incrementationMethod}(); } return $version; }
/** * Tests getting of static variables. */ public function testStaticVariables() { static $testName = 'staticVariables'; $rfl = $this->getMethodReflection($testName); $this->assertSame($rfl->internal->getStaticVariables(), $rfl->token->getStaticVariables()); $this->assertSame(array('string' => 'string', 'integer' => 1, 'float' => 1.1, 'boolean' => true, 'null' => null, 'array' => array(1 => 1), 'array2' => array(1 => 1, 2 => 2), 'constants' => array('self constant', 'parent constant')), $rfl->token->getStaticVariables()); // The same test with parsing method bodies turned off $broker = new Broker(new Broker\Backend\Memory(), Broker::OPTION_DEFAULT & ~Broker::OPTION_PARSE_FUNCTION_BODY); $broker->processFile($this->getFilePath($testName)); $reflection = $broker->getClass($this->getClassName($testName))->getMethod($this->getMethodName($testName)); $this->assertSame(array(), $reflection->getStaticVariables()); }
/** * Returns an array of tokens for a particular file. * * @param string $fileName File name * * @return \TokenReflection\Stream\StreamBase * @throws \TokenReflection\Exception\BrokerException If the requested file was not processed. */ public function getFileTokens($fileName) { $realName = Broker::getRealPath($fileName); if (!isset($this->tokenStreams[$realName])) { throw new Exception\BrokerException($this->getBroker(), sprintf('File "%s" was not processed yet.', $fileName), Exception\BrokerException::DOES_NOT_EXIST); } return true === $this->tokenStreams[$realName] ? new FileStream($realName) : $this->tokenStreams[$realName]; }