/vendor/zendframework/zend-code/src/Reflection/FunctionReflection.php

https://gitlab.com/yousafsyed/easternglamor · PHP · 269 lines · 170 code · 37 blank · 62 comment · 25 complexity · c565f31258356e56509b5beff2debe56 MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Code\Reflection;
  10. use ReflectionFunction;
  11. class FunctionReflection extends ReflectionFunction implements ReflectionInterface
  12. {
  13. /**
  14. * Constant use in @MethodReflection to display prototype as an array
  15. */
  16. const PROTOTYPE_AS_ARRAY = 'prototype_as_array';
  17. /**
  18. * Constant use in @MethodReflection to display prototype as a string
  19. */
  20. const PROTOTYPE_AS_STRING = 'prototype_as_string';
  21. /**
  22. * Get function DocBlock
  23. *
  24. * @throws Exception\InvalidArgumentException
  25. * @return DocBlockReflection
  26. */
  27. public function getDocBlock()
  28. {
  29. if ('' == ($comment = $this->getDocComment())) {
  30. throw new Exception\InvalidArgumentException(sprintf(
  31. '%s does not have a DocBlock',
  32. $this->getName()
  33. ));
  34. }
  35. $instance = new DocBlockReflection($comment);
  36. return $instance;
  37. }
  38. /**
  39. * Get start line (position) of function
  40. *
  41. * @param bool $includeDocComment
  42. * @return int
  43. */
  44. public function getStartLine($includeDocComment = false)
  45. {
  46. if ($includeDocComment) {
  47. if ($this->getDocComment() != '') {
  48. return $this->getDocBlock()->getStartLine();
  49. }
  50. }
  51. return parent::getStartLine();
  52. }
  53. /**
  54. * Get contents of function
  55. *
  56. * @param bool $includeDocBlock
  57. * @return string
  58. */
  59. public function getContents($includeDocBlock = true)
  60. {
  61. $fileName = $this->getFileName();
  62. if (false === $fileName) {
  63. return '';
  64. }
  65. $startLine = $this->getStartLine();
  66. $endLine = $this->getEndLine();
  67. // eval'd protect
  68. if (preg_match('#\((\d+)\) : eval\(\)\'d code$#', $fileName, $matches)) {
  69. $fileName = preg_replace('#\(\d+\) : eval\(\)\'d code$#', '', $fileName);
  70. $startLine = $endLine = $matches[1];
  71. }
  72. $lines = array_slice(
  73. file($fileName, FILE_IGNORE_NEW_LINES),
  74. $startLine - 1,
  75. ($endLine - ($startLine - 1)),
  76. true
  77. );
  78. $functionLine = implode("\n", $lines);
  79. $content = '';
  80. if ($this->isClosure()) {
  81. preg_match('#function\s*\([^\)]*\)\s*(use\s*\([^\)]+\))?\s*\{(.*\;)?\s*\}#s', $functionLine, $matches);
  82. if (isset($matches[0])) {
  83. $content = $matches[0];
  84. }
  85. } else {
  86. $name = substr($this->getName(), strrpos($this->getName(), '\\')+1);
  87. preg_match('#function\s+' . preg_quote($name) . '\s*\([^\)]*\)\s*{([^{}]+({[^}]+})*[^}]+)?}#', $functionLine, $matches);
  88. if (isset($matches[0])) {
  89. $content = $matches[0];
  90. }
  91. }
  92. $docComment = $this->getDocComment();
  93. return $includeDocBlock && $docComment ? $docComment . "\n" . $content : $content;
  94. }
  95. /**
  96. * Get method prototype
  97. *
  98. * @return array
  99. */
  100. public function getPrototype($format = FunctionReflection::PROTOTYPE_AS_ARRAY)
  101. {
  102. $returnType = 'mixed';
  103. $docBlock = $this->getDocBlock();
  104. if ($docBlock) {
  105. $return = $docBlock->getTag('return');
  106. $returnTypes = $return->getTypes();
  107. $returnType = count($returnTypes) > 1 ? implode('|', $returnTypes) : $returnTypes[0];
  108. }
  109. $prototype = array(
  110. 'namespace' => $this->getNamespaceName(),
  111. 'name' => substr($this->getName(), strlen($this->getNamespaceName()) + 1),
  112. 'return' => $returnType,
  113. 'arguments' => array(),
  114. );
  115. $parameters = $this->getParameters();
  116. foreach ($parameters as $parameter) {
  117. $prototype['arguments'][$parameter->getName()] = array(
  118. 'type' => $parameter->getType(),
  119. 'required' => !$parameter->isOptional(),
  120. 'by_ref' => $parameter->isPassedByReference(),
  121. 'default' => $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null,
  122. );
  123. }
  124. if ($format == FunctionReflection::PROTOTYPE_AS_STRING) {
  125. $line = $prototype['return'] . ' ' . $prototype['name'] . '(';
  126. $args = array();
  127. foreach ($prototype['arguments'] as $name => $argument) {
  128. $argsLine = ($argument['type'] ? $argument['type'] . ' ' : '') . ($argument['by_ref'] ? '&' : '') . '$' . $name;
  129. if (!$argument['required']) {
  130. $argsLine .= ' = ' . var_export($argument['default'], true);
  131. }
  132. $args[] = $argsLine;
  133. }
  134. $line .= implode(', ', $args);
  135. $line .= ')';
  136. return $line;
  137. }
  138. return $prototype;
  139. }
  140. /**
  141. * Get function parameters
  142. *
  143. * @return ParameterReflection[]
  144. */
  145. public function getParameters()
  146. {
  147. $phpReflections = parent::getParameters();
  148. $zendReflections = array();
  149. while ($phpReflections && ($phpReflection = array_shift($phpReflections))) {
  150. $instance = new ParameterReflection($this->getName(), $phpReflection->getName());
  151. $zendReflections[] = $instance;
  152. unset($phpReflection);
  153. }
  154. unset($phpReflections);
  155. return $zendReflections;
  156. }
  157. /**
  158. * Get return type tag
  159. *
  160. * @throws Exception\InvalidArgumentException
  161. * @return DocBlockReflection
  162. */
  163. public function getReturn()
  164. {
  165. $docBlock = $this->getDocBlock();
  166. if (!$docBlock->hasTag('return')) {
  167. throw new Exception\InvalidArgumentException(
  168. 'Function does not specify an @return annotation tag; cannot determine return type'
  169. );
  170. }
  171. $tag = $docBlock->getTag('return');
  172. return new DocBlockReflection('@return ' . $tag->getDescription());
  173. }
  174. /**
  175. * Get method body
  176. *
  177. * @return string|false
  178. */
  179. public function getBody()
  180. {
  181. $fileName = $this->getFileName();
  182. if (false === $fileName) {
  183. throw new Exception\InvalidArgumentException(
  184. 'Cannot determine internals functions body'
  185. );
  186. }
  187. $startLine = $this->getStartLine();
  188. $endLine = $this->getEndLine();
  189. // eval'd protect
  190. if (preg_match('#\((\d+)\) : eval\(\)\'d code$#', $fileName, $matches)) {
  191. $fileName = preg_replace('#\(\d+\) : eval\(\)\'d code$#', '', $fileName);
  192. $startLine = $endLine = $matches[1];
  193. }
  194. $lines = array_slice(
  195. file($fileName, FILE_IGNORE_NEW_LINES),
  196. $startLine - 1,
  197. ($endLine - ($startLine - 1)),
  198. true
  199. );
  200. $functionLine = implode("\n", $lines);
  201. $body = false;
  202. if ($this->isClosure()) {
  203. preg_match('#function\s*\([^\)]*\)\s*(use\s*\([^\)]+\))?\s*\{(.*\;)\s*\}#s', $functionLine, $matches);
  204. if (isset($matches[2])) {
  205. $body = $matches[2];
  206. }
  207. } else {
  208. $name = substr($this->getName(), strrpos($this->getName(), '\\')+1);
  209. preg_match('#function\s+' . $name . '\s*\([^\)]*\)\s*{([^{}]+({[^}]+})*[^}]+)}#', $functionLine, $matches);
  210. if (isset($matches[1])) {
  211. $body = $matches[1];
  212. }
  213. }
  214. return $body;
  215. }
  216. /**
  217. * @return string
  218. */
  219. public function toString()
  220. {
  221. return $this->__toString();
  222. }
  223. /**
  224. * Required due to bug in php
  225. *
  226. * @return string
  227. */
  228. public function __toString()
  229. {
  230. return parent::__toString();
  231. }
  232. }