3 * @see https://github.com/zendframework/zend-server for the canonical source repository
4 * @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
5 * @license https://github.com/zendframework/zend-server/blob/master/LICENSE.md New BSD License
8 namespace Zend\Server\Reflection
;
13 class ReflectionMethod
extends AbstractFunction
16 * Doc block inherit tag for search
18 const INHERIT_TAG
= '{@inheritdoc}';
27 * Parent class reflection
28 * @var ReflectionClass|\ReflectionClass
30 protected $classReflection;
35 * @param ReflectionClass $class
36 * @param \ReflectionMethod $r
37 * @param string $namespace
40 public function __construct(ReflectionClass
$class, \ReflectionMethod
$r, $namespace = null, $argv = [])
42 $this->classReflection
= $class;
43 $this->reflection
= $r;
45 $classNamespace = $class->getNamespace();
47 // Determine namespace
48 if (! empty($namespace)) {
49 $this->setNamespace($namespace);
50 } elseif (! empty($classNamespace)) {
51 $this->setNamespace($classNamespace);
54 // Determine arguments
55 if (is_array($argv)) {
59 // If method call, need to store some info on the class
60 $this->class = $class->getName();
62 // Perform some introspection
67 * Return the reflection for the class that defines this method
69 * @return \Zend\Server\Reflection\ReflectionClass
71 public function getDeclaringClass()
73 return $this->classReflection
;
77 * Wakeup from serialization
79 * Reflection needs explicit instantiation to work correctly. Re-instantiate
80 * reflection object on wakeup.
84 public function __wakeup()
86 $this->classReflection
= new ReflectionClass(
87 new \
ReflectionClass($this->class),
88 $this->getNamespace(),
89 $this->getInvokeArguments()
91 $this->reflection
= new \
ReflectionMethod($this->classReflection
->getName(), $this->getName());
97 protected function reflect()
99 $docComment = $this->reflection
->getDocComment();
100 if (strpos($docComment, self
::INHERIT_TAG
) !== false) {
101 $this->docComment
= $this->fetchRecursiveDocComment();
108 * Fetch all doc comments for inherit values
112 private function fetchRecursiveDocComment()
114 $currentMethodName = $this->reflection
->getName();
115 $docCommentList[] = $this->reflection
->getDocComment();
117 // fetch all doc blocks for method from parent classes
118 $docCommentFetched = $this->fetchRecursiveDocBlockFromParent($this->classReflection
, $currentMethodName);
119 if ($docCommentFetched) {
120 $docCommentList = array_merge($docCommentList, $docCommentFetched);
124 // fetch doc blocks from interfaces
125 $interfaceReflectionList = $this->classReflection
->getInterfaces();
126 foreach ($interfaceReflectionList as $interfaceReflection) {
127 if (! $interfaceReflection->hasMethod($currentMethodName)) {
131 $docCommentList[] = $interfaceReflection->getMethod($currentMethodName)->getDocComment();
134 $normalizedDocCommentList = array_map(
135 function ($docComment) {
136 $docComment = str_replace('/**', '', $docComment);
137 $docComment = str_replace('*/', '', $docComment);
144 $docComment = '/**' . implode(PHP_EOL
, $normalizedDocCommentList) . '*/';
150 * Fetch recursive doc blocks from parent classes
152 * @param \ReflectionClass $reflectionClass
153 * @param string $methodName
157 private function fetchRecursiveDocBlockFromParent($reflectionClass, $methodName)
160 $parentReflectionClass = $reflectionClass->getParentClass();
161 if (! $parentReflectionClass) {
165 if (! $parentReflectionClass->hasMethod($methodName)) {
169 $methodReflection = $parentReflectionClass->getMethod($methodName);
170 $docCommentLast = $methodReflection->getDocComment();
171 $docComment[] = $docCommentLast;
172 if ($this->isInherit($docCommentLast)) {
173 if ($docCommentFetched = $this->fetchRecursiveDocBlockFromParent($parentReflectionClass, $methodName)) {
174 $docComment = array_merge($docComment, $docCommentFetched);
182 * Return true if doc block inherit from parent or interface
184 * @param string $docComment
188 private function isInherit($docComment)
190 $isInherit = strpos($docComment, self
::INHERIT_TAG
) !== false;