/library/Zend/Reflection/ReflectionDocblock.php

https://github.com/sidealice/zf2 · PHP · 292 lines · 130 code · 40 blank · 122 comment · 22 complexity · 80618f14195725234b43805e9adcae6e MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Reflection
  17. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. */
  20. /**
  21. * @namespace
  22. */
  23. namespace Zend\Reflection;
  24. /**
  25. * @uses Reflector
  26. * @uses \Zend\Reflection\ReflectionDocblockTag
  27. * @category Zend
  28. * @package Zend_Reflection
  29. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  30. * @license http://framework.zend.com/license/new-bsd New BSD License
  31. */
  32. class ReflectionDocblock implements \Reflector
  33. {
  34. /**
  35. * @var Reflector
  36. */
  37. protected $_reflector = null;
  38. /**#@+
  39. * @var int
  40. */
  41. protected $_startLine = null;
  42. protected $_endLine = null;
  43. /**#@-*/
  44. /**
  45. * @var string
  46. */
  47. protected $_docComment = null;
  48. /**
  49. * @var string
  50. */
  51. protected $_cleanDocComment = null;
  52. /**
  53. * @var string
  54. */
  55. protected $_longDescription = null;
  56. /**
  57. * @var string
  58. */
  59. protected $_shortDescription = null;
  60. /**
  61. * @var array
  62. */
  63. protected $_tags = array();
  64. /**
  65. * Export reflection
  66. *
  67. * Reqired by the Reflector interface.
  68. *
  69. * @todo What should this do?
  70. * @return void
  71. */
  72. public static function export()
  73. {
  74. }
  75. /**
  76. * Serialize to string
  77. *
  78. * Required by the Reflector interface
  79. *
  80. * @todo What should this return?
  81. * @return string
  82. */
  83. public function __toString()
  84. {
  85. $str = "Docblock [ /* Docblock */ ] {".PHP_EOL.PHP_EOL;
  86. $str .= " - Tags [".count($this->_tags)."] {".PHP_EOL;
  87. foreach($this->_tags AS $tag) {
  88. $str .= " ".$tag;
  89. }
  90. $str .= " }".PHP_EOL;
  91. $str .= "}".PHP_EOL;
  92. return $str;
  93. }
  94. /**
  95. * Constructor
  96. *
  97. * @param Reflector|string $commentOrReflector
  98. */
  99. public function __construct($commentOrReflector)
  100. {
  101. if ($commentOrReflector instanceof \Reflector) {
  102. $this->_reflector = $commentOrReflector;
  103. if (!method_exists($commentOrReflector, 'getDocComment')) {
  104. throw new Exception\InvalidArgumentException('Reflector must contain method "getDocComment"');
  105. }
  106. $docComment = $commentOrReflector->getDocComment();
  107. $lineCount = substr_count($docComment, "\n");
  108. $this->_startLine = $this->_reflector->getStartLine() - $lineCount - 1;
  109. $this->_endLine = $this->_reflector->getStartLine() - 1;
  110. } elseif (is_string($commentOrReflector)) {
  111. $docComment = $commentOrReflector;
  112. } else {
  113. throw new Exception\InvalidArgumentException(get_class($this) . ' must have a (string) DocComment or a Reflector in the constructor');
  114. }
  115. if ($docComment == '') {
  116. throw new Exception\InvalidArgumentException('DocComment cannot be empty');
  117. }
  118. $this->_docComment = $docComment;
  119. $this->_parse();
  120. }
  121. /**
  122. * Retrieve contents of docblock
  123. *
  124. * @return string
  125. */
  126. public function getContents()
  127. {
  128. return $this->_cleanDocComment;
  129. }
  130. /**
  131. * Get start line (position) of docblock
  132. *
  133. * @return int
  134. */
  135. public function getStartLine()
  136. {
  137. return $this->_startLine;
  138. }
  139. /**
  140. * Get last line (position) of docblock
  141. *
  142. * @return int
  143. */
  144. public function getEndLine()
  145. {
  146. return $this->_endLine;
  147. }
  148. /**
  149. * Get docblock short description
  150. *
  151. * @return string
  152. */
  153. public function getShortDescription()
  154. {
  155. return $this->_shortDescription;
  156. }
  157. /**
  158. * Get docblock long description
  159. *
  160. * @return string
  161. */
  162. public function getLongDescription()
  163. {
  164. return $this->_longDescription;
  165. }
  166. /**
  167. * Does the docblock contain the given annotation tag?
  168. *
  169. * @param string $name
  170. * @return bool
  171. */
  172. public function hasTag($name)
  173. {
  174. foreach ($this->_tags as $tag) {
  175. if ($tag->getName() == $name) {
  176. return true;
  177. }
  178. }
  179. return false;
  180. }
  181. /**
  182. * Retrieve the given docblock tag
  183. *
  184. * @param string $name
  185. * @return \Zend\Reflection\ReflectionDocblockTag|false
  186. */
  187. public function getTag($name)
  188. {
  189. foreach ($this->_tags as $tag) {
  190. if ($tag->getName() == $name) {
  191. return $tag;
  192. }
  193. }
  194. return false;
  195. }
  196. /**
  197. * Get all docblock annotation tags
  198. *
  199. * @param string $filter
  200. * @return array Array of \Zend\Reflection\ReflectionDocblockTag
  201. */
  202. public function getTags($filter = null)
  203. {
  204. if ($filter === null || !is_string($filter)) {
  205. return $this->_tags;
  206. }
  207. $returnTags = array();
  208. foreach ($this->_tags as $tag) {
  209. if ($tag->getName() == $filter) {
  210. $returnTags[] = $tag;
  211. }
  212. }
  213. return $returnTags;
  214. }
  215. /**
  216. * Parse the docblock
  217. *
  218. * @return void
  219. */
  220. protected function _parse()
  221. {
  222. $docComment = $this->_docComment;
  223. // First remove doc block line starters
  224. $docComment = preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ ]{0,1}(.*)?#', '$1', $docComment);
  225. $docComment = ltrim($docComment, "\r\n"); // @todo should be changed to remove first and last empty line
  226. $this->_cleanDocComment = $docComment;
  227. // Next parse out the tags and descriptions
  228. $parsedDocComment = $docComment;
  229. $lineNumber = $firstBlandLineEncountered = 0;
  230. while (($newlinePos = strpos($parsedDocComment, "\n")) !== false) {
  231. $lineNumber++;
  232. $line = substr($parsedDocComment, 0, $newlinePos);
  233. $matches = array();
  234. if ((strpos($line, '@') === 0) && (preg_match('#^(@\w+.*?)(\n)(?:@|\r?\n|$)#s', $parsedDocComment, $matches))) {
  235. $this->_tags[] = new ReflectionDocblockTag($matches[1]);
  236. $parsedDocComment = str_replace($matches[1] . $matches[2], '', $parsedDocComment);
  237. } else {
  238. if ($lineNumber < 3 && !$firstBlandLineEncountered) {
  239. $this->_shortDescription .= $line . "\n";
  240. } else {
  241. $this->_longDescription .= $line . "\n";
  242. }
  243. if ($line == '') {
  244. $firstBlandLineEncountered = true;
  245. }
  246. $parsedDocComment = substr($parsedDocComment, $newlinePos + 1);
  247. }
  248. }
  249. $this->_shortDescription = rtrim($this->_shortDescription);
  250. $this->_longDescription = rtrim($this->_longDescription);
  251. }
  252. }