Skip to content
This repository has been archived by the owner on Jan 31, 2020. It is now read-only.

Commit

Permalink
Merge develop to master in preparation for 2.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
weierophinney committed Dec 17, 2015
2 parents 8d885b0 + ee97319 commit 784ae10
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 4 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 2.5.2 - TBD
## 2.6.0 - 2015-12-17

### Added

- Nothing.
- [#3](https://github.com/zendframework/zend-server/pull/3) adds support for
resolving `{@inheritdoc}` annotations to the original parent during
reflection.

### Deprecated

Expand Down
13 changes: 12 additions & 1 deletion src/Reflection/AbstractFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ abstract class AbstractFunction
*/
protected $prototypes = [];

/**
* Phpdoc comment
* @var string
*/
protected $docComment = '';

private $return;
private $returnDesc;
private $paramDesc;
Expand Down Expand Up @@ -231,7 +237,12 @@ protected function reflect()
$function = $this->reflection;
$paramCount = $function->getNumberOfParameters();
$parameters = $function->getParameters();
$scanner = new DocBlockReflection(($function->getDocComment()) ? : '/***/');

if (!$this->docComment) {
$this->docComment = $function->getDocComment();
}

$scanner = new DocBlockReflection(($this->docComment) ? : '/***/');
$helpText = $scanner->getLongDescription();
/* @var \Zend\Code\Reflection\DocBlock\Tag\ParamTag[] $paramTags */
$paramTags = $scanner->getTags('param');
Expand Down
108 changes: 107 additions & 1 deletion src/Reflection/ReflectionMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
*/
class ReflectionMethod extends AbstractFunction
{
/**
* Doc block inherit tag for search
*/
const INHERIT_TAG = '{@inheritdoc}';

/**
* Parent class name
* @var string
Expand All @@ -22,7 +27,7 @@ class ReflectionMethod extends AbstractFunction

/**
* Parent class reflection
* @var ReflectionClass
* @var ReflectionClass|\ReflectionClass
*/
protected $classReflection;

Expand Down Expand Up @@ -83,4 +88,105 @@ public function __wakeup()
$this->classReflection = new ReflectionClass(new \ReflectionClass($this->class), $this->getNamespace(), $this->getInvokeArguments());
$this->reflection = new \ReflectionMethod($this->classReflection->getName(), $this->getName());
}

/**
* {@inheritdoc}
*/
protected function reflect()
{
$docComment = $this->reflection->getDocComment();
if (strpos($docComment, self::INHERIT_TAG) !== false) {
$this->docComment = $this->fetchRecursiveDocComment();
}

parent::reflect();
}

/**
* Fetch all doc comments for inherit values
*
* @return string
*/
private function fetchRecursiveDocComment()
{
$currentMethodName = $this->reflection->getName();
$docCommentList[] = $this->reflection->getDocComment();

// fetch all doc blocks for method from parent classes
$docCommentFetched = $this->fetchRecursiveDocBlockFromParent($this->classReflection, $currentMethodName);
if ($docCommentFetched) {
$docCommentList = array_merge($docCommentList, $docCommentFetched);
}


// fetch doc blocks from interfaces
$interfaceReflectionList = $this->classReflection->getInterfaces();
foreach ($interfaceReflectionList as $interfaceReflection) {
if (!$interfaceReflection->hasMethod($currentMethodName)) {
continue;
}

$docCommentList[] = $interfaceReflection->getMethod($currentMethodName)->getDocComment();
}

$normalizedDocCommentList = array_map(
function ($docComment) {
$docComment = str_replace('/**', '', $docComment);
$docComment = str_replace('*/', '', $docComment);

return $docComment;
},
$docCommentList
);

$docComment = '/**' . implode(PHP_EOL, $normalizedDocCommentList) . '*/';

return $docComment;
}

/**
* Fetch recursive doc blocks from parent classes
*
* @param \ReflectionClass $reflectionClass
* @param string $methodName
*
* @return array|void
*/
private function fetchRecursiveDocBlockFromParent($reflectionClass, $methodName)
{
$docComment = [];
$parentReflectionClass = $reflectionClass->getParentClass();
if (!$parentReflectionClass) {
return;
}

if (!$parentReflectionClass->hasMethod($methodName)) {
return;
}

$methodReflection = $parentReflectionClass->getMethod($methodName);
$docCommentLast = $methodReflection->getDocComment();
$docComment[] = $docCommentLast;
if ($this->isInherit($docCommentLast)) {
if ($docCommentFetched = $this->fetchRecursiveDocBlockFromParent($parentReflectionClass, $methodName)) {
$docComment = array_merge($docComment, $docCommentFetched);
}
}

return $docComment;
}

/**
* Return true if doc block inherit from parent or interface
*
* @param string $docComment
*
* @return bool
*/
private function isInherit($docComment)
{
$isInherit = strpos($docComment, self::INHERIT_TAG) !== false;

return $isInherit;
}
}
77 changes: 77 additions & 0 deletions test/Reflection/ReflectionMethodTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,51 @@

use Zend\Server\Reflection;

/**
* Interface ReflectionMethodInterface
*/
interface ReflectionMethodInterface
{
/**
* Test method
*
* @param ReflectionMethodTest $reflectionMethodTest Reflection method
* @param array $anything Some array information
*/
public function testMethod(ReflectionMethodTest $reflectionMethodTest, array $anything);
}

/**
* Class ReflectionMethodTestInstance
* for testing only
*/
class ReflectionMethodTestInstance implements ReflectionMethodInterface
{

/**
* {@inheritdoc}
*/
public function testMethod(ReflectionMethodTest $reflectionMethodTest, array $anything)
{
// it doesn`t matter
}
}

/**
* Class ReflectionMethodNode
* for testing only
*/
class ReflectionMethodNode extends Reflection\Node
{
/**
* {@inheritdoc}
*/
public function setParent(Reflection\Node $node, $new = false)
{
// it doesn`t matter
}
}

/**
* Test case for \Zend\Server\Reflection\ReflectionMethod
*
Expand Down Expand Up @@ -87,4 +132,36 @@ public function test__wakeup()
$this->assertEquals($r->getName(), $u->getName());
$this->assertEquals($r->getDeclaringClass()->getName(), $u->getDeclaringClass()->getName());
}

/**
* Test fetch method doc block from interface
*/
public function testMethodDocBlockFromInterface()
{
$reflectionClass = new \ReflectionClass('ZendTest\Server\Reflection\ReflectionMethodTestInstance');
$reflectionMethod = $reflectionClass->getMethod('testMethod');

$zendReflectionMethod = new Reflection\ReflectionMethod(new Reflection\ReflectionClass($reflectionClass), $reflectionMethod);
list($prototype) = $zendReflectionMethod->getPrototypes();
list($first, $second) = $prototype->getParameters();

self::assertEquals('ReflectionMethodTest', $first->getType());
self::assertEquals('array', $second->getType());
}

/**
* Test fetch method doc block from parent class
*/
public function testMethodDocBlockFromParent()
{
$reflectionClass = new \ReflectionClass('ZendTest\Server\Reflection\ReflectionMethodNode');
$reflectionMethod = $reflectionClass->getMethod('setParent');

$zendReflectionMethod = new Reflection\ReflectionMethod(new Reflection\ReflectionClass($reflectionClass), $reflectionMethod);
$prototypes = $zendReflectionMethod->getPrototypes();
list($first, $second) = $prototypes[1]->getParameters();

self::assertEquals('\Zend\Server\Reflection\Node', $first->getType());
self::assertEquals('bool', $second->getType());
}
}

0 comments on commit 784ae10

Please sign in to comment.