/** * Adds the short description of $docblock to the given node as description * field. * * @param \DOMElement $node * @param DocBlock $docblock * * @return void */ protected function addDescription(\DOMElement $node, DocBlock $docblock) { $cdata = $node->ownerDocument->createCDATASection($docblock->getShortDescription()); $description = new \DOMElement('description'); $node->appendChild($description); $description->appendChild($cdata); }
protected function configure() { $reflection = new \ReflectionClass(get_called_class()); $baseNamespaceChunks = []; foreach (explode('\\', $reflection->getNamespaceName()) as $namespaceChunk) { $baseNamespaceChunks[] = $namespaceChunk; if ($namespaceChunk == consoleBase::COMMANDS_DIRECTORY) { break; } } $namespace = str_replace(implode('\\', $baseNamespaceChunks), '', get_called_class()); $namespace = trim($namespace, '\\'); $commandNameData = explode('\\', $namespace); $phpdoc = new DocBlock($reflection); /** @var DocBlock\Tag $tag */ $tag = reset($phpdoc->getTagsByName('consoleNs')); $commandNameValues = []; if ($tag) { $consoleNs = trim($tag->getDescription()); if (!empty($consoleNs)) { $commandNameValues[] = $consoleNs; } } foreach ($commandNameData as $commandNameValue) { $commandNameValues[] = $commandNameValue; } $this->setName(implode(':', $commandNameValues))->setDescription($phpdoc->getShortDescription())->setHelp($phpdoc->getLongDescription()); $this->defineArguments(); }
protected function addDescription(\DOMElement $child, \phpDocumentor\Reflection\DocBlock $docblock) { $node = $child->ownerDocument->createCDATASection($docblock->getShortDescription()); $description = new \DOMElement('description'); $child->appendChild($description); $description->appendChild($node); }
/** * Parse the docBlock comment for this command, and set the * fields of this class with the data thereby obtained. */ public function parse() { $docblockComment = $this->reflection->getDocComment(); $phpdoc = new DocBlock($docblockComment); // First set the description (synopsis) and help. $this->commandInfo->setDescription((string) $phpdoc->getShortDescription()); $this->commandInfo->setHelp((string) $phpdoc->getLongDescription()); $this->processAllTags($phpdoc); }
public function getMethodDesc($methodName) { if (!$this->reflection->hasMethod($methodName)) { return null; } $docComment = $this->reflection->getMethod($methodName)->getDocComment(); if ($docComment) { $docBlock = new DocBlock($docComment); return join(' ', [$docBlock->getShortDescription(), $docBlock->getLongDescription()]); } return null; }
/** * * @param ReflectionProperty $reflector * @return ParsePropertyBlockResult */ public function parsePropertyDocBlock(ReflectionProperty $reflector) { $phpdoc = new DocBlock($reflector->getDocComment()); /* @var $varTags VarTag[] */ $varTags = $phpdoc->getTagsByName("var"); /* @var $varTag VarTag */ $varTag = $varTags[0]; $result = new ParsePropertyBlockResult(); $result->description = $phpdoc->getShortDescription(); $result->type = (string) $varTag->getType(); return $result; }
public function getMethodsDetails() { $methods = []; foreach ($this->reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { $docblock = new DocBlock($method); $data = ['shortDescription' => $docblock->getShortDescription(), 'longDescription' => $docblock->getLongDescription(), 'argumentsList' => $this->retriveParams($docblock->getTagsByName('param')), 'argumentsDescription' => $this->retriveParamsDescription($docblock->getTagsByName('param')), 'returnValue' => $this->retriveReturnValue($docblock->getTagsByName('return')), 'visibility' => join('', [$method->isFinal() ? 'final ' : '', 'public', $method->isStatic() ? ' static' : ''])]; if (strlen($data['shortDescription'])) { $methods[$method->getName()] = (object) $data; } } return $methods; }
/** * @param $doc * @return bool */ public function parseClass(ControllerDoc $doc) { if (!($docBlock = new DocBlock($this->reflection))) { return false; } $doc->longDescription = $docBlock->getLongDescription()->getContents(); $doc->shortDescription = $docBlock->getShortDescription(); $doc->populateTags($docBlock); if (DocBlockHelper::isInherit($docBlock)) { $parentParser = $this->getParentParser(); $parentParser->parseClass($doc); } }
/** * {@inheritDoc} */ public function extractAction(ActionInterface $action) { $callable = $this->callableResolver->resolve($action); if ($this->parameterExtractor) { $parameters = $this->parameterExtractor->extract($action, $callable); } else { $parameters = []; } $reflection = $callable->getReflection(); $docBlock = new DocBlock($reflection); $description = $docBlock->getShortDescription(); $actionDoc = new Action($action->getName(), $description, $parameters); return $actionDoc; }
/** * Assemble DocBlock. * * @param DocBlock|null $docBlock * @param DescriptorAbstract $target * * @return void */ protected function assembleDocBlock($docBlock, $target) { if (!$docBlock) { return; } $target->setSummary($docBlock->getShortDescription()); $target->setDescription($docBlock->getLongDescription()->getContents()); /** @var DocBlock\Tag $tag */ foreach ($docBlock->getTags() as $tag) { $tagDescriptor = $this->builder->buildDescriptor($tag); // allow filtering of tags if (!$tagDescriptor) { continue; } $target->getTags()->get($tag->getName(), new Collection())->add($tagDescriptor); } }
/** * Returns an array of endpoints * * @return array */ protected function getEndpoints() { $endpoints = []; foreach ($this->routes as $route) { $array = explode("@", $route['action']); $class = $array[0]; if ($class == "Closure") { // check for api/v1/docs if (strpos($route['uri'], $this->prefix . '/docs') !== false) { continue; } } $reflector = new ReflectionClass($class); $docBlock = new DocBlock($reflector); // remove Controller $class = str_replace('Controller', '', $class); $endpoints["{$class}"]['methods'] = []; $endpoints["{$class}"]['description'] = $docBlock->getShortDescription(); } return $this->getEndpointMethods($endpoints); }
public function parse($comment, ParserContext $context) { $docBlock = null; $errorMessage = ''; try { $docBlockContext = new DocBlock\Context($context->getNamespace(), $context->getAliases() ?: array()); $docBlock = new DocBlock((string) $comment, $docBlockContext); } catch (\Exception $e) { $errorMessage = $e->getMessage(); } $result = new DocBlockNode(); if ($errorMessage) { $result->addError($errorMessage); return $result; } $result->setShortDesc($docBlock->getShortDescription()); $result->setLongDesc((string) $docBlock->getLongDescription()); foreach ($docBlock->getTags() as $tag) { $result->addTag($tag->getName(), $this->parseTag($tag)); } return $result; }
public function fetchMethod($className, $method) { $phpdoc = new DocBlock($method->getDocComment()); $call = array(); $params = array(); $return = null; // build the call example string foreach ($method->getParameters() as $param) { if ($param->isOptional()) { try { $value = var_export($param->getDefaultValue(), true); $value = str_replace(PHP_EOL, '', $value); $value = str_replace('NULL', 'null', $value); $value = str_replace('array ()', 'array()', $value); $call[] = '$' . $param->getName() . ' = ' . $value; } catch (Exception $e) { $call[] = '$' . $param->getName(); } } else { $call[] = '$' . $param->getName(); } } // get all parameter docs foreach ($phpdoc->getTags() as $tag) { switch ($tag->getName()) { case 'param': $params[] = array('name' => $tag->getVariableName(), 'type' => $tag->getType(), 'text' => $tag->getDescription()); break; case 'return': $return = array('type' => $tag->getType(), 'text' => $tag->getDescription()); break; } } // a::first $methodName = strtolower($className) . '::' . $method->getName(); $methodSlug = str::slug($method->getName()); // build the full method array return array('name' => $methodName, 'slug' => $methodSlug, 'excerpt' => str_replace(PHP_EOL, ' ', $phpdoc->getShortDescription()), 'call' => $methodName . '(' . implode(', ', $call) . ')', 'return' => $return, 'params' => $params); }
protected function findSummary(\ReflectionClass $scopeClass, \ReflectionMethod $scopeMethod, Language $lang = null, &$alreadyScopedClasses = array()) { foreach ($alreadyScopedClasses as $sc) { /* @var \ReflectionClass $sc */ if ($sc->getName() === $scopeClass->getName()) { return null; } } $alreadyScopedClasses[] = $scopeClass; $doc = new DocBlock($scopeMethod); $result = $doc->getShortDescription(); if ('{@inheritdoc}' === \trim(\strtolower($result))) { $result = null; $typesToCheck = \array_merge($scopeClass->getTraits(), [$scopeClass->getParentClass()], $scopeClass->getInterfaces()); foreach ($typesToCheck as $type) { if (!$type instanceof \ReflectionClass) { continue; } $matchingMethod = null; foreach ($type->getMethods() as $otherMethod) { if ($otherMethod->getName() !== $scopeMethod->getName()) { continue; } $matchingMethod = $otherMethod; } if (!$matchingMethod instanceof \ReflectionMethod) { continue; } $summary = \trim($this->findSummary($type, $matchingMethod, $lang, $alreadyScopedClasses)); if ('' !== $summary) { $result = $summary; } } } $result = \trim($result); return '' !== $result ? $result : null; }
/** * @param string $class * @param array $processed * * @return array */ private function extractParameters($class, $processed = []) { if (isset($processed[$class])) { return []; } $processed[$class] = true; $reflectionClass = new \ReflectionClass($class); $parameters = []; foreach ($reflectionClass->getProperties() as $reflectionProperty) { $type = $this->determinePropertyType($reflectionProperty); $isCollection = false; if ($extractedType = $this->typeResolver->extractTypeFromCollectionType($type)) { $isCollection = true; $type = $extractedType; } $docBlock = new DocBlock($reflectionProperty); $parameter = ['name' => $reflectionProperty->getName(), 'description' => $docBlock->getShortDescription(), 'type' => $type . ($isCollection ? '[]' : '')]; if (class_exists($type)) { $parameter = array_merge($parameter, ['type' => 'object' . ($isCollection ? '[]' : ''), 'properties' => $this->extractParameters($type, $processed)]); } $parameters[] = $parameter; } return $parameters; }
/** * @param DocBlock $docBlock * @param \SimpleXMLElement $xmlElement */ protected function setDescriptions($docBlock, $xmlElement) { if ($docBlock->getShortDescription()) { $shortDesc = $xmlElement->addChild('shortdesc', $docBlock->getShortDescription()); $shortDesc->addAttribute('lang', $this->language); } if ($docBlock->getLongDescription()->getContents()) { $longDesc = $xmlElement->addChild('longdesc', $docBlock->getLongDescription()->getContents()); $longDesc->addAttribute('lang', $this->language); } }
/** * Create options and arguments from the public properties on your command * * @param \ReflectionClass $class * @param $argsAdded * * @return null */ protected function createOptionsFromPublic(\ReflectionClass $class, $argsAdded) { $properties = $class->getProperties(\ReflectionProperty::IS_PUBLIC); if (empty($properties)) { return null; } foreach ($properties as $property) { $propBlock = new DocBlock($property); $short = null; $description = $propBlock->getShortDescription(); $mode = InputOption::VALUE_OPTIONAL; if ($propBlock->hasTag('short')) { $short = head($propBlock->getTagsByName('short'))->getDescription(); } if ($propBlock->hasTag('description')) { $description = head($propBlock->getTagsByName('description'))->getDescription(); } if ($propBlock->hasTag('valuerequired')) { $mode = InputOption::VALUE_REQUIRED; } if ($propBlock->hasTag('flag')) { $mode = InputOption::VALUE_NONE; } $this->addOption($property->getName(), $short, $mode, $description, $property->getValue($this)); } }
private function getMethodDetails($method) { $docblock = new DocBlock($method); $data = ['shortDescription' => $docblock->getShortDescription(), 'longDescription' => $docblock->getLongDescription(), 'argumentsList' => $this->retriveParams($docblock->getTagsByName('param')), 'argumentsDescription' => $this->retriveParamsDescription($docblock->getTagsByName('param')), 'returnValue' => $this->retriveReturnValue($docblock->getTagsByName('return')), 'visibility' => join('', [$method->isFinal() ? 'final ' : '', 'public', $method->isStatic() ? ' static' : ''])]; return (object) $data; }
/** * Process an individual file * * @param string $file File path * @return array Processed endpoints */ private function processFile($file) { // var to hold output $output = array(); require_once $file; $className = $this->parseClassFromFile($file); $component = $this->parseClassFromFile($file, true)['component']; $version = $this->parseClassFromFile($file, true)['version']; // Push file to files array $this->output['files'][] = $file; // Push version to versions array $this->output['versions']['available'][] = $version; if (!class_exists($className)) { return $output; } $classReflector = new ReflectionClass($className); foreach ($classReflector->getMethods() as $method) { // Create docblock object & make sure we have something $phpdoc = new DocBlock($method); // Skip methods we don't want processed if (substr($method->getName(), -4) != 'Task' || in_array($method->getName(), array('registerTask', 'unregisterTask', 'indexTask'))) { continue; } // Skip method in the parent class (already processed), if ($className != $method->getDeclaringClass()->getName()) { //continue; } // Skip if we dont have a short desc // but put in error if (!$phpdoc->getShortDescription()) { $this->output['errors'][] = sprintf('Missing docblock for method "%s" in "%s"', $method->getName(), $file); continue; } // Create endpoint data array $endpoint = array('name' => $phpdoc->getShortDescription(), 'description' => $phpdoc->getLongDescription()->getContents(), 'method' => '', 'uri' => '', 'parameters' => array(), '_metadata' => array('component' => $component, 'version' => $version, 'method' => $method->getName())); // Loop through each tag foreach ($phpdoc->getTags() as $tag) { $name = strtolower(str_replace('api', '', $tag->getName())); $content = $tag->getContent(); // Handle parameters separately // json decode param input if ($name == 'parameter') { $parameter = json_decode($content); if (json_last_error() != JSON_ERROR_NONE) { $this->output['errors'][] = sprintf('Unable to parse parameter info for method "%s" in "%s"', $method->getName(), $file); continue; } $endpoint['parameters'][] = (array) $parameter; continue; } if ($name == 'uri' && $method->getName() == 'indexTask') { $content .= $component; } // Add data to endpoint data $endpoint[$name] = $content; } // Add endpoint to output // We always want indexTask to be first in the list if ($method->getName() == 'indexTask') { array_unshift($output, $endpoint); } else { $output[] = $endpoint; } } return $output; }
public static function resolve($reflected) { $is_method = false; $is_property = false; // Are we working with a property or a method? if ($reflected instanceof ReflectionMethod) { $is_method = true; } elseif ($reflected instanceof ReflectionProperty) { $is_property = true; } else { throw new Exception('Only methods and properties can be reflected with ' . get_called_class()); } // Parse the docblock $docblock = new DocBlock($reflected->getDocComment()); $found_description = false; $return = $reflected; // Save these for messaging $__class = $reflected->getDeclaringClass()->getName(); $__kind = $reflected->getName(); // Can we just do a straight-up inherit? // @todo: Do a better job of handling {@inheritdoc} according to the spec. try { while (!$found_description && strpos($docblock->getShortDescription(), '{@inheritdoc}') !== false) { // Start over... $found_description = false; // Log that we're starting... Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Starting resolution:', array(sprintf("{$__class}%s{$__kind}%s", $is_method ? '::' : '::$', $is_method ? '()' : ''))); // Grab a reference to the class containing the entity with the {@inheritdoc} tag $klass = $reflected->getDeclaringClass(); // Is this an Interface? if ($klass->isInterface()) { throw new InheritdocInInterfaceException('The {@inheritdoc} tag is not resolvable from within Interfaces. Methods and properties should ' . 'be fully-documented.'); } elseif (SystemStore::get('_.php54') && $klass->isTrait()) { throw new InheritdocInTraitException('The {@inheritdoc} tag is not resolvable from within Traits. Methods and properties should ' . 'be fully-documented.'); } // Are we using Interfaces? if (!$found_description && ($interface_count = count($klass->getInterfaces())) > 0) { $count = 1; foreach ($klass->getInterfaces() as $rinterface) { Logger::get()->{ConfigStore::get('log.info')}("{@inheritdoc} Checking Interface {$count}/{$interface_count}:", array($rinterface->getName())); try { $return = $rinterface->getMethod($reflected->getName()); Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($rinterface->getName(), $reflected->getName(), 'Method')); $found_description = true; break 2; } catch (Exception $e) { try { $return = $rinterface->getProperty($reflected->getName()); Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($rinterface->getName(), $reflected->getName(), 'Property')); $found_description = true; break 2; } catch (Exception $e) { Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} No match. Will keep looking...', array($rinterface->getName(), $reflected->getName())); } } $count++; } } // Are we using Traits? if (!$found_description && SystemStore::get('_.php54') && ($trait_count = count($klass->getTraits())) > 0) { $count = 1; foreach ($klass->getTraits() as $rtrait) { Logger::get()->{ConfigStore::get('log.info')}("{@inheritdoc} Checking Trait {$count}/{$trait_count}:", array($rtrait->getName())); try { $return = $rtrait->getMethod($reflected->getName()); Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($rtrait->getName(), $reflected->getName(), 'Method')); $found_description = true; break 2; } catch (Exception $e) { try { $return = $rtrait->getProperty($reflected->getName()); Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($rtrait->getName(), $reflected->getName(), 'Property')); $found_description = true; break 2; } catch (Exception $e) { Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} No match. Will keep looking...', array($rtrait->getName(), $reflected->getName())); } } $count++; } } // Are we extending a class? if ($klass->getParentClass()) { // Continue climbing up the ancestry as necessary while (!$found_description && $klass->getParentClass()) { // Rewrite the reference to $klass $klass = $klass->getParentClass(); Logger::get()->{ConfigStore::get('log.info')}("{@inheritdoc} Checking the parent class:", array($klass->getName())); try { $return = $klass->getMethod($reflected->getName()); Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($klass->getName(), $reflected->getName(), 'Method')); $found_description = true; break 2; } catch (Exception $e) { try { $return = $klass->getProperty($reflected->getName()); Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} Match!', array($klass->getName(), $reflected->getName(), 'Property')); $found_description = true; break 2; } catch (Exception $e) { Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} No match. Will keep looking...', array($klass->getName(), $reflected->getName())); } } } } // We couldn't find anything throw new CouldNotResolveInheritdocException('Leaving as-is. The tag will be viewable in the ' . 'resulting documentation.'); } } catch (InheritdocInInterfaceException $e) { $message = sprintf("{$__class}%s{$__kind}%s", $is_method ? '::' : '::$', $is_method ? '()' : ''); // Log that we're starting... Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} ' . $e->getMessage(), array($message)); $formatter = ConsoleUtil::formatters(); Inconsistency::add($message . $formatter->gold->apply(' => Could not resolve {@inheritdoc}. ' . $e->getMessage())); } catch (InheritdocInTraitException $e) { $message = sprintf("{$__class}%s{$__kind}%s", $is_method ? '::' : '::$', $is_method ? '()' : ''); // Log that we're starting... Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} ' . $e->getMessage(), array($message)); $formatter = ConsoleUtil::formatters(); Inconsistency::add($message . $formatter->gold->apply(' => Could not resolve {@inheritdoc}. ' . $e->getMessage())); } catch (CouldNotResolveInheritdocException $e) { $message = sprintf("{$__class}%s{$__kind}%s", $is_method ? '::' : '::$', $is_method ? '()' : ''); // Log that we're starting... Logger::get()->{ConfigStore::get('log.info')}('{@inheritdoc} ' . $e->getMessage(), array($message)); $formatter = ConsoleUtil::formatters(); Inconsistency::add($message . $formatter->gold->apply(' => Could not resolve {@inheritdoc}. ' . $e->getMessage())); } catch (VanityException $e) { } catch (Exception $e) { } return $return; }
public function store_class_constant(Node\Stmt\Class_ $class, Node\Stmt\ClassConst $constant) { if ($comments = $constant->getAttribute('comments')) { $phpdoc = new DocBlock($comments[0]->getText()); $description = $phpdoc->getShortDescription(); // short circuit @ignore functions if ($phpdoc->hasTag('ignore')) { return; } } else { $description = ''; } $this->store_model('class_constants', array('constant' => $constant->consts[0]->name, 'class' => $class->name, 'namespace' => !empty($class->namespacedName) ? implode('\\', array_slice($class->namespacedName->parts, 0, -1)) : '', 'file' => $this->_current_file, 'line' => $constant->getLine(), 'type' => $this->get_type_for_node($constant->consts[0]->value), 'description' => $description)); }
function __construct($reflector) { $phpdoc = new \phpDocumentor\Reflection\DocBlock($reflector); $this->tags = array(); $this->docblock = $reflector->getDocComment(); $this->desc = new stdClass(); $this->desc->long = $phpdoc->getLongDescription()->getFormattedContents(); $this->desc->short = $phpdoc->getShortDescription(); $this->desc->full = strip_tags($this->desc->short . "\n" . $this->desc->long); foreach ($phpdoc->getTags() as $tag) { $rslt = self::get_tag(); switch (true) { case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\AuthorName: $rslt->name = $tag->getAuthorName(); $rslt->email = $tag->getAuthorEmail(); break; case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\SeeTag: case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\UsesTag: $rslt->ref = $tag->getReference(); break; case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\ExampleTag: $rslt->file_path = $tag->getFilePath(); break; case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\LinkTag: $rslt->link = $tag->getLink(); break; case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\MethodTag: $rslt->name = $tag->getMethodName(); $rslt->args = $tag->getArguments(); break; case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\VarTag: case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\ParamTag: case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\PropertyTag: case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\PropertyReadTag: case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\PropertyWriteTag: $rslt->name = $tag->getVariableName(); $rslt->type = str_replace('\\', '', $tag->getType()); break; case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\ReturnTag: case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag: $rslt->type = str_replace('\\', '', $tag->getType()); break; case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\SinceTag: case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\VersionTag: case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\DeprecatedTag: $rslt->version = $tag->getVersion(); break; case $tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\SourceTag: $rslt->line = new stdClass(); $rslt->line->count = $tag->getLineCount(); $rslt->line->starting = $tag->getStartingLine(); break; default: break; } $rslt->desc = $tag->getDescription(); $name = $tag->getName(); if (@isset($rslt->name)) { $rslt->name = rtrim($rslt->name, ':'); } if ($tag instanceof \phpDocumentor\Reflection\DocBlock\Tag\ParamTag) { if (!@isset($this->tags[$name])) { $this->tags[$name] = array(); } $this->tags[$name][] = $rslt; } else { $this->tags[$name] = $rslt; } } }
/** * Generate the docs for all facades in the AliasLoader * * @return string */ protected function generateDocs() { $aliasLoader = AliasLoader::getInstance(); //Get all aliases $aliases = $aliasLoader->getAliases(); foreach ($aliases as $alias => $facade) { $root = $this->getRoot($facade); if (!$root) { continue; } try { $this->mapping[$alias] = array('root' => $root, 'facade' => $facade, 'methods' => array()); $usedMethods = array(); $this->getMethods($root, $alias, $usedMethods); $driver = $this->getDriver($alias); if ($driver) { $this->getMethods($driver, $alias, $usedMethods); } //Add extra methods, from other classes (magic static calls) if (array_key_exists($alias, $this->extra)) { $this->mapping[$alias]['root'] = $this->extra[$alias][0]; $this->getMethods($this->extra[$alias], $alias, $usedMethods); } //Add extra methods, from other classes (magic static calls) if (array_key_exists($alias, $this->magic)) { $this->addMagicMethods($this->magic[$alias], $alias, $usedMethods); } } catch (\Exception $e) { $this->error("Exception: " . $e->getMessage() . "\nCould not analyze {$root}."); } } if (!empty($this->helpers)) { foreach ($this->helpers as $helper) { if (file_exists($helper)) { $helper_raw = str_replace(array('<?php', '?>'), '', \File::get($helper)); if (preg_match_all("/function_exists\\('(.*)'\\)/", $helper_raw, $helper_names, PREG_SET_ORDER)) { foreach ($helper_names as $h) { $reflection = new \ReflectionFunction($h[1]); list($params, $paramsWithDefault) = $this->getParameters($reflection); $phpdoc = new DocBlock($reflection); $info = array('name' => $h[1], 'params' => implode($paramsWithDefault, ", "), 'desc' => $phpdoc->getShortDescription()); $this->mapping['_helpers'][$h[1]] = $info; } } } } } }
/** * Парсит описание метода из phpdoc в стандартизованный вид для дальнейшей обработки * @param string $text * @return string */ protected function parseMdMethodFromPHPDoc($text) { $lines = $this->getTextLines($text); $link = ''; $code = trim(array_pop($lines)); if (strpos($code, 'link:') === 0) { $link = substr($code, 5); $code = trim(array_pop($lines)); } $code_out_params = trim(substr($code, 0, strpos($code, '('))); $comment = implode("\n", $lines); $args = []; preg_match_all('/(\\$[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)\\s*\\=\\s*(.+?)(\\,|\\))/', $code, $matches, PREG_SET_ORDER); foreach ($matches as $matche) { $args[$matche[1]] = $matche[2]; } $code_params = []; $desc_params = []; $PHPDoc = new DocBlock($comment); $doc_result = $PHPDoc->getTagsByName('return'); $code_return_type = empty($doc_result) ? 'void' : $this->getDocDefaultType($doc_result[0]->getType()); $doc_params = $PHPDoc->getTagsByName('param'); $doc_callbacks = $PHPDoc->getTagsByName('callback'); $callbacks = []; foreach ($doc_callbacks as $cb) { list($cb_name, $cb_code) = explode(' ', $cb->getDescription(), 2); $callbacks[$cb_name] = $cb_code; } foreach ($doc_params as $tag) { $name = $tag->getVariableName(); $type = $tag->getType(); $desc = $tag->getDescription(); $deftype = $this->getDocDefaultType($type); if ($name === '' && $desc !== '' && $desc[0] === '&' && $desc[1] === '$') { if (strpos($desc, ' ') === false) { $name = $desc; $desc = ''; } else { list($name, $desc) = explode(' ', $desc, 2); } } $code_params[] = $deftype . ' ' . $name . (isset($args[$name]) ? ' = ' . $args[$name] : ''); $extra = ''; if ($deftype === 'callable') { if (isset($callbacks[$name])) { $extra = "callback {$callbacks[$name]}\n"; } } $desc_params[] = $name . "\n" . $extra . $desc; } $result = ''; if ($link) { $result .= 'link:' . $link . "\n"; } // $desc_text_arr = preg_split('/[ \t]*\n[ \t]*/', trim($PHPDoc->getShortDescription() ."\n". $PHPDoc->getLongDescription()), -1, PREG_SPLIT_NO_EMPTY); // $desc_text = ' ' . implode(" \n ", $desc_text_arr); $desc_text = $this->convertTextToHTML(trim($PHPDoc->getShortDescription() . "\n\n" . $PHPDoc->getLongDescription())); $doc_methods = $PHPDoc->getTagsByName('call'); if (empty($doc_methods)) { $result .= $this->showReturnType($code_return_type) . ' ' . $code_out_params . ' ( ' . implode(', ', $code_params) . " )\n\n"; } else { foreach ($doc_methods as $tag) { $result .= $tag->getDescription() . "<i class='dn'>;</i>\n"; } $result .= "\n"; } $result .= $desc_text . "\n\n"; $result .= implode("\n\n", $desc_params); return $result; }
/** * {@inheritDoc} */ public function extract(ActionInterface $action, CallableInterface $callable) { /** @var \ReflectionClass $requestClass */ $requestClass = null; $inputParameters = $callable->getReflection()->getParameters(); foreach ($inputParameters as $parameter) { if ($class = $parameter->getClass()) { if ($class->implementsInterface('FiveLab\\Component\\Api\\Request\\RequestInterface')) { $requestClass = $class; break; } } } if (!$requestClass) { return []; } $requestParameters = []; $requestObject = $requestClass->newInstance(); $objectMetadata = $this->objectMapper->getMetadataFactory()->load($requestObject, ObjectMetadata::DEFAULT_GROUP); if (!$objectMetadata) { // Can not load metadata for object return []; } foreach ($objectMetadata->getProperties() as $property) { if (!$property->reflection) { $property->reflection = new \ReflectionProperty($requestClass->getName(), $property->getPropertyName()); } $docBlock = new DocBlock($property->reflection); $content = $docBlock->getShortDescription(); $typeTags = $docBlock->getTagsByName('var'); $type = null; if ($typeTags) { /** @var \phpDocumentor\Reflection\DocBlock\Tag\VarTag $typeTag */ $typeTag = array_pop($typeTags); $type = $typeTag->getType(); //$type = $this->formatPHPType($type); } $defaultValue = null; if ($property->reflection->isDefault()) { if (!$property->reflection->isPublic()) { $property->reflection->setAccessible(true); } $defaultValue = $property->reflection->getValue($requestObject); } $parameter = new Parameter($property->getFieldName(), $type, $this->isPropertyRequired($property->reflection), $content, $defaultValue); $requestParameters[$property->getFieldName()] = $parameter; } return $requestParameters; }
public function testTagCaseSensitivity() { $fixture = <<<DOCBLOCK /** * This is a short description. * * This is a long description. * * @method null something() * @Method({"GET", "POST"}) */ DOCBLOCK; $object = new DocBlock($fixture); $this->assertEquals('This is a short description.', $object->getShortDescription()); $this->assertEquals('This is a long description.', $object->getLongDescription()->getContents()); $tags = $object->getTags(); $this->assertCount(2, $tags); $this->assertTrue($object->hasTag('method')); $this->assertTrue($object->hasTag('Method')); $this->assertInstanceOf(__NAMESPACE__ . '\\DocBlock\\Tag\\MethodTag', $tags[0]); $this->assertInstanceOf(__NAMESPACE__ . '\\DocBlock\\Tag', $tags[1]); $this->assertNotInstanceOf(__NAMESPACE__ . '\\DocBlock\\Tag\\MethodTag', $tags[1]); }
/** * Extract response property * * @param ActionInterface $action * @param CallableInterface $callable * @param \ReflectionProperty $property * * @return ResponseProperty */ protected function extractResponseProperty(ActionInterface $action, CallableInterface $callable, \ReflectionProperty $property) { $docBlock = new DocBlock($property); $description = $docBlock->getShortDescription(); $type = 'mixed'; $child = null; $varTags = $docBlock->getTagsByName('var'); if (count($varTags)) { /** @var \phpDocumentor\Reflection\DocBlock\Tag\VarTag $varTag */ $varTag = $varTags[0]; $varTypes = $varTag->getTypes(); $varType = null; if (count($varTypes)) { $varType = array_pop($varTypes); } switch (true) { case 'int' == $varType: case 'integer' == $varType: $type = 'int'; break; case 'string' == $varType: $type = 'string'; break; case 'float' == $varType: case 'double' == $varType: $type = 'float'; break; case 'boolean' == $varType: case 'bool' == $varType: $type = 'bool'; break; case 'DateTime' == ltrim($varType, '\\'): $type = 'datetime'; break; default: if ($varType && class_exists($varType)) { $type = 'object'; $childProperties = $this->getPropertiesForClass($action, $callable, $varType); $child = []; foreach ($childProperties as $childProperty) { $child[$childProperty->getName()] = $this->extractResponseProperty($action, $callable, $childProperty); } break; } else { if ($varType && substr($varType, strlen($varType) - 2) == '[]') { $childClass = substr($varType, 0, strlen($varType) - 2); $type = 'collection'; $childProperties = $this->getPropertiesForClass($action, $callable, $childClass); $child = []; foreach ($childProperties as $childProperty) { $child[$childProperty->getName()] = $this->extractResponseProperty($action, $callable, $childProperty); } break; } } $this->tryFormatPhpType($varTag, $varType); } } $responseProperty = new ResponseProperty($property->getName(), $type, $description, $child); return $responseProperty; }
/** * Adds the short description of $docblock to the given node as description * field. * * @param \DOMElement $node * @param DocBlock $docblock * * @return void */ protected function addDescription(\DOMElement $node, DocBlock $docblock) { $node->appendChild(new \DOMElement('description'))->appendChild(new \DOMText($docblock->getShortDescription())); }