/** * @param \ReflectionMethod $method * @param string $alias * @param \ReflectionClass $class * @param string|null $methodName * @param array $interfaces */ public function __construct(\ReflectionMethod $method, $alias, $class, $methodName = null, $interfaces = array()) { $this->method = $method; $this->interfaces = $interfaces; $this->name = $methodName ?: $method->name; $this->namespace = $method->getDeclaringClass()->getNamespaceName(); //Create a DocBlock and serializer instance $this->phpdoc = new DocBlock($method, new Context($this->namespace)); //Normalize the description and inherit the docs from parents/interfaces try { $this->normalizeParams($this->phpdoc); $this->normalizeReturn($this->phpdoc); $this->normalizeDescription($this->phpdoc); } catch (\Exception $e) { } //Get the parameters, including formatted default values $this->getParameters($method); //Make the method static $this->phpdoc->appendTag(Tag::createInstance('@static', $this->phpdoc)); //Reference the 'real' function in the declaringclass $declaringClass = $method->getDeclaringClass(); $this->declaringClassName = '\\' . ltrim($declaringClass->name, '\\'); $this->root = '\\' . ltrim($class->getName(), '\\'); }
/** * @param string $class * @return string */ protected function createPhpDocs($class) { $reflection = new \ReflectionClass($class); $namespace = $reflection->getNamespaceName(); $classname = $reflection->getShortName(); $originalDoc = $reflection->getDocComment(); if ($this->reset) { $phpdoc = new DocBlock('', new Context($namespace)); } else { $phpdoc = new DocBlock($reflection, new Context($namespace)); } if (!$phpdoc->getText()) { $phpdoc->setText($class); } $properties = array(); $methods = array(); foreach ($phpdoc->getTags() as $tag) { $name = $tag->getName(); if ($name == "property" || $name == "property-read" || $name == "property-write") { $properties[] = $tag->getVariableName(); } elseif ($name == "method") { $methods[] = $tag->getMethodName(); } } foreach ($this->properties as $name => $property) { $name = "\${$name}"; if (in_array($name, $properties)) { continue; } if ($property['read'] && $property['write']) { $attr = 'property'; } elseif ($property['write']) { $attr = 'property-write'; } else { $attr = 'property-read'; } if ($this->hasCamelCaseModelProperties()) { $name = Str::camel($name); } $tagLine = trim("@{$attr} {$property['type']} {$name} {$property['comment']}"); $tag = Tag::createInstance($tagLine, $phpdoc); $phpdoc->appendTag($tag); } foreach ($this->methods as $name => $method) { if (in_array($name, $methods)) { continue; } $arguments = implode(', ', $method['arguments']); $tag = Tag::createInstance("@method static {$method['type']} {$name}({$arguments})", $phpdoc); $phpdoc->appendTag($tag); } if ($this->write && !$phpdoc->getTagsByName('mixin')) { $phpdoc->appendTag(Tag::createInstance("@mixin \\Eloquent", $phpdoc)); } $serializer = new DocBlockSerializer(); $serializer->getDocComment($phpdoc); $docComment = $serializer->getDocComment($phpdoc); if ($this->write) { $filename = $reflection->getFileName(); $contents = $this->files->get($filename); if ($originalDoc) { $contents = str_replace($originalDoc, $docComment, $contents); } else { $needle = "class {$classname}"; $replace = "{$docComment}\nclass {$classname}"; $pos = strpos($contents, $needle); if ($pos !== false) { $contents = substr_replace($contents, $replace, $pos, strlen($needle)); } } if ($this->files->put($filename, $contents)) { $this->info('Written new phpDocBlock to ' . $filename); } } $output = "namespace {$namespace}{\n{$docComment}\n\tclass {$classname} extends \\Eloquent {}\n}\n\n"; return $output; }
/** * Creates the tag objects. * * @param string $tags Tag block to parse. * * @return void */ protected function parseTags($tags) { $result = array(); $tags = trim($tags); if ('' !== $tags) { if ('@' !== $tags[0]) { throw new \LogicException('A tag block started with text instead of an actual tag,' . ' this makes the tag block invalid: ' . $tags); } foreach (explode("\n", $tags) as $tag_line) { if (isset($tag_line[0]) && $tag_line[0] === '@') { $result[] = $tag_line; } else { $result[count($result) - 1] .= "\n" . $tag_line; } } // create proper Tag objects foreach ($result as $key => $tag_line) { $result[$key] = Tag::createInstance(trim($tag_line), $this); } } $this->tags = $result; }
/** * @covers \Barryvdh\Reflection\DocBlock\Tag::registerTagHandler * * @return void */ public function testIncompatibleTagHandlerRegistration() { $currentHandler = __NAMESPACE__ . '\\Tag\\VarTag'; $tagPreReg = Tag::createInstance('@var mixed'); $this->assertInstanceOf($currentHandler, $tagPreReg); $this->assertInstanceOf(__NAMESPACE__ . '\\Tag', $tagPreReg); $this->assertFalse(Tag::registerTagHandler('var', __NAMESPACE__ . '\\TagTest')); $tagPostReg = Tag::createInstance('@var mixed'); $this->assertInstanceOf($currentHandler, $tagPostReg); $this->assertInstanceOf(__NAMESPACE__ . '\\Tag', $tagPostReg); }
/** * Returns the parsed text of this description. * * @return array An array of strings and tag objects, in the order they * occur within the description. */ public function getParsedContents() { if (null === $this->parsedContents) { $this->parsedContents = preg_split('/\\{ # "{@}" is not a valid inline tag. This ensures that # we do not treat it as one, but treat it literally. (?!@\\}) # We want to capture the whole tag line, but without the # inline tag delimiters. (\\@ # Match everything up to the next delimiter. [^{}]* # Nested inline tag content should not be captured, or # it will appear in the result separately. (?: # Match nested inline tags. (?: # Because we did not catch the tag delimiters # earlier, we must be explicit with them here. # Notice that this also matches "{}", as a way # to later introduce it as an escape sequence. \\{(?1)?\\} | # Make sure we match hanging "{". \\{ ) # Match content after the nested inline tag. [^{}]* )* # If there are more inline tags, match them as well. # We use "*" since there may not be any nested inline # tags. ) \\}/Sux', $this->contents, null, PREG_SPLIT_DELIM_CAPTURE); $count = count($this->parsedContents); for ($i = 1; $i < $count; $i += 2) { $this->parsedContents[$i] = Tag::createInstance($this->parsedContents[$i], $this->docblock); } //In order to allow "literal" inline tags, the otherwise invalid //sequence "{@}" is changed to "@", and "{}" is changed to "}". //See unit tests for examples. for ($i = 0; $i < $count; $i += 2) { $this->parsedContents[$i] = str_replace(array('{@}', '{}'), array('@', '}'), $this->parsedContents[$i]); } } return $this->parsedContents; }