BaseDoc.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\apidoc\models;
  8. use phpDocumentor\Reflection\DocBlock\Tag\DeprecatedTag;
  9. use phpDocumentor\Reflection\DocBlock\Tag\SinceTag;
  10. use yii\base\Object;
  11. use yii\helpers\StringHelper;
  12. /**
  13. * Base class for API documentation information.
  14. *
  15. * @author Carsten Brandt <mail@cebe.cc>
  16. * @since 2.0
  17. */
  18. class BaseDoc extends Object
  19. {
  20. /**
  21. * @var \phpDocumentor\Reflection\DocBlock\Context
  22. */
  23. public $phpDocContext;
  24. public $name;
  25. public $sourceFile;
  26. public $startLine;
  27. public $endLine;
  28. public $shortDescription;
  29. public $description;
  30. public $since;
  31. public $deprecatedSince;
  32. public $deprecatedReason;
  33. /**
  34. * @var \phpDocumentor\Reflection\DocBlock\Tag[]
  35. */
  36. public $tags = [];
  37. /**
  38. * Checks if doc has tag of a given name
  39. * @param string $name tag name
  40. * @return bool if doc has tag of a given name
  41. */
  42. public function hasTag($name)
  43. {
  44. foreach ($this->tags as $tag) {
  45. if (strtolower($tag->getName()) == $name) {
  46. return true;
  47. }
  48. }
  49. return false;
  50. }
  51. /**
  52. * Removes tag of a given name
  53. * @param string $name
  54. */
  55. public function removeTag($name)
  56. {
  57. foreach ($this->tags as $i => $tag) {
  58. if (strtolower($tag->getName()) == $name) {
  59. unset($this->tags[$i]);
  60. }
  61. }
  62. }
  63. /**
  64. * Get the first tag of a given name
  65. * @param string $name
  66. * @return \phpDocumentor\Reflection\DocBlock\Tag
  67. * @since 2.0.5
  68. */
  69. public function getFirstTag($name)
  70. {
  71. foreach ($this->tags as $i => $tag) {
  72. if (strtolower($tag->getName()) == $name) {
  73. return $this->tags[$i];
  74. }
  75. }
  76. }
  77. /**
  78. * @param \phpDocumentor\Reflection\BaseReflector $reflector
  79. * @param Context $context
  80. * @param array $config
  81. */
  82. public function __construct($reflector = null, $context = null, $config = [])
  83. {
  84. parent::__construct($config);
  85. if ($reflector === null) {
  86. return;
  87. }
  88. // base properties
  89. $this->name = ltrim($reflector->getName(), '\\');
  90. $this->startLine = $reflector->getNode()->getAttribute('startLine');
  91. $this->endLine = $reflector->getNode()->getAttribute('endLine');
  92. $docblock = $reflector->getDocBlock();
  93. if ($docblock !== null) {
  94. $this->shortDescription = static::mbUcFirst($docblock->getShortDescription());
  95. if (empty($this->shortDescription) && !($this instanceof PropertyDoc) && $context !== null && $docblock->getTagsByName('inheritdoc') === null) {
  96. $context->warnings[] = [
  97. 'line' => $this->startLine,
  98. 'file' => $this->sourceFile,
  99. 'message' => "No short description for " . substr(StringHelper::basename(get_class($this)), 0, -3) . " '{$this->name}'",
  100. ];
  101. }
  102. $this->description = $docblock->getLongDescription()->getContents();
  103. $this->phpDocContext = $docblock->getContext();
  104. $this->tags = $docblock->getTags();
  105. foreach ($this->tags as $i => $tag) {
  106. if ($tag instanceof SinceTag) {
  107. $this->since = $tag->getVersion();
  108. unset($this->tags[$i]);
  109. } elseif ($tag instanceof DeprecatedTag) {
  110. $this->deprecatedSince = $tag->getVersion();
  111. $this->deprecatedReason = $tag->getDescription();
  112. unset($this->tags[$i]);
  113. }
  114. }
  115. } elseif ($context !== null) {
  116. $context->warnings[] = [
  117. 'line' => $this->startLine,
  118. 'file' => $this->sourceFile,
  119. 'message' => "No docblock for element '{$this->name}'",
  120. ];
  121. }
  122. }
  123. // TODO implement
  124. // public function loadSource($reflection)
  125. // {
  126. // $this->sourceFile;
  127. // $this->startLine;
  128. // $this->endLine;
  129. // }
  130. //
  131. // public function getSourceCode()
  132. // {
  133. // $lines = file(YII2_PATH . $this->sourcePath);
  134. // return implode("", array_slice($lines, $this->startLine - 1, $this->endLine - $this->startLine + 1));
  135. // }
  136. /**
  137. * Extracts first sentence out of text
  138. * @param string $text
  139. * @return string
  140. */
  141. public static function extractFirstSentence($text)
  142. {
  143. if (mb_strlen($text, 'utf-8') > 4 && ($pos = mb_strpos($text, '.', 4, 'utf-8')) !== false) {
  144. $sentence = mb_substr($text, 0, $pos + 1, 'utf-8');
  145. if (mb_strlen($text, 'utf-8') >= $pos + 3) {
  146. $abbrev = mb_substr($text, $pos - 1, 4, 'utf-8');
  147. if ($abbrev === 'e.g.' || $abbrev === 'i.e.') { // do not break sentence after abbreviation
  148. $sentence .= static::extractFirstSentence(mb_substr($text, $pos + 1, mb_strlen($text, 'utf-8'), 'utf-8'));
  149. }
  150. }
  151. return $sentence;
  152. } else {
  153. return $text;
  154. }
  155. }
  156. /**
  157. * Multibyte version of ucfirst()
  158. * @since 2.0.6
  159. */
  160. protected static function mbUcFirst($string)
  161. {
  162. $firstChar = mb_strtoupper(mb_substr($string, 0, 1, 'utf-8'), 'utf-8');
  163. return $firstChar . mb_substr($string, 1, mb_strlen($string, 'utf-8'), 'utf-8');
  164. }
  165. }