PageRenderTime 48ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/applications/diviner/atom/DivinerAtom.php

https://github.com/navyuginfo/phabricator
PHP | 437 lines | 363 code | 69 blank | 5 comment | 17 complexity | 97028b543fbc3d757514d40030c735cb MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, LGPL-3.0, MIT, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. <?php
  2. final class DivinerAtom {
  3. const TYPE_FILE = 'file';
  4. const TYPE_ARTICLE = 'article';
  5. const TYPE_METHOD = 'method';
  6. const TYPE_CLASS = 'class';
  7. const TYPE_FUNCTION = 'function';
  8. const TYPE_INTERFACE = 'interface';
  9. private $type;
  10. private $name;
  11. private $file;
  12. private $line;
  13. private $hash;
  14. private $contentRaw;
  15. private $length;
  16. private $language;
  17. private $docblockRaw;
  18. private $docblockText;
  19. private $docblockMeta;
  20. private $warnings = array();
  21. private $parent;
  22. private $parentHash;
  23. private $children = array();
  24. private $childHashes = array();
  25. private $context;
  26. private $extends = array();
  27. private $links = array();
  28. private $book;
  29. private $properties = array();
  30. /**
  31. * Returns a sorting key which imposes an unambiguous, stable order on atoms.
  32. */
  33. public function getSortKey() {
  34. return implode(
  35. "\0",
  36. array(
  37. $this->getBook(),
  38. $this->getType(),
  39. $this->getContext(),
  40. $this->getName(),
  41. $this->getFile(),
  42. sprintf('%08', $this->getLine()),
  43. ));
  44. }
  45. public function setBook($book) {
  46. $this->book = $book;
  47. return $this;
  48. }
  49. public function getBook() {
  50. return $this->book;
  51. }
  52. public function setContext($context) {
  53. $this->context = $context;
  54. return $this;
  55. }
  56. public function getContext() {
  57. return $this->context;
  58. }
  59. public static function getAtomSerializationVersion() {
  60. return 2;
  61. }
  62. public function addWarning($warning) {
  63. $this->warnings[] = $warning;
  64. return $this;
  65. }
  66. public function getWarnings() {
  67. return $this->warnings;
  68. }
  69. public function setDocblockRaw($docblock_raw) {
  70. $this->docblockRaw = $docblock_raw;
  71. $parser = new PhutilDocblockParser();
  72. list($text, $meta) = $parser->parse($docblock_raw);
  73. $this->docblockText = $text;
  74. $this->docblockMeta = $meta;
  75. return $this;
  76. }
  77. public function getDocblockRaw() {
  78. return $this->docblockRaw;
  79. }
  80. public function getDocblockText() {
  81. if ($this->docblockText === null) {
  82. throw new Exception('Call setDocblockRaw() before getDocblockText()!');
  83. }
  84. return $this->docblockText;
  85. }
  86. public function getDocblockMeta() {
  87. if ($this->docblockMeta === null) {
  88. throw new Exception('Call setDocblockRaw() before getDocblockMeta()!');
  89. }
  90. return $this->docblockMeta;
  91. }
  92. public function getDocblockMetaValue($key, $default = null) {
  93. $meta = $this->getDocblockMeta();
  94. return idx($meta, $key, $default);
  95. }
  96. public function setDocblockMetaValue($key, $value) {
  97. $meta = $this->getDocblockMeta();
  98. $meta[$key] = $value;
  99. $this->docblockMeta = $meta;
  100. return $this;
  101. }
  102. public function setType($type) {
  103. $this->type = $type;
  104. return $this;
  105. }
  106. public function getType() {
  107. return $this->type;
  108. }
  109. public function setName($name) {
  110. $this->name = $name;
  111. return $this;
  112. }
  113. public function getName() {
  114. return $this->name;
  115. }
  116. public function setFile($file) {
  117. $this->file = $file;
  118. return $this;
  119. }
  120. public function getFile() {
  121. return $this->file;
  122. }
  123. public function setLine($line) {
  124. $this->line = $line;
  125. return $this;
  126. }
  127. public function getLine() {
  128. return $this->line;
  129. }
  130. public function setContentRaw($content_raw) {
  131. $this->contentRaw = $content_raw;
  132. return $this;
  133. }
  134. public function getContentRaw() {
  135. return $this->contentRaw;
  136. }
  137. public function setHash($hash) {
  138. $this->hash = $hash;
  139. return $this;
  140. }
  141. public function addLink(DivinerAtomRef $ref) {
  142. $this->links[] = $ref;
  143. return $this;
  144. }
  145. public function addExtends(DivinerAtomRef $ref) {
  146. $this->extends[] = $ref;
  147. return $this;
  148. }
  149. public function getLinkDictionaries() {
  150. return mpull($this->links, 'toDictionary');
  151. }
  152. public function getExtendsDictionaries() {
  153. return mpull($this->extends, 'toDictionary');
  154. }
  155. public function getExtends() {
  156. return $this->extends;
  157. }
  158. public function getHash() {
  159. if ($this->hash) {
  160. return $this->hash;
  161. }
  162. $parts = array(
  163. $this->getBook(),
  164. $this->getType(),
  165. $this->getName(),
  166. $this->getFile(),
  167. $this->getLine(),
  168. $this->getLength(),
  169. $this->getLanguage(),
  170. $this->getContentRaw(),
  171. $this->getDocblockRaw(),
  172. $this->getProperties(),
  173. $this->getChildHashes(),
  174. mpull($this->extends, 'toHash'),
  175. mpull($this->links, 'toHash'),
  176. );
  177. $this->hash = md5(serialize($parts)).'N';
  178. return $this->hash;
  179. }
  180. public function setLength($length) {
  181. $this->length = $length;
  182. return $this;
  183. }
  184. public function getLength() {
  185. return $this->length;
  186. }
  187. public function setLanguage($language) {
  188. $this->language = $language;
  189. return $this;
  190. }
  191. public function getLanguage() {
  192. return $this->language;
  193. }
  194. public function addChildHash($child_hash) {
  195. $this->childHashes[] = $child_hash;
  196. return $this;
  197. }
  198. public function getChildHashes() {
  199. if (!$this->childHashes && $this->children) {
  200. $this->childHashes = mpull($this->children, 'getHash');
  201. }
  202. return $this->childHashes;
  203. }
  204. public function setParentHash($parent_hash) {
  205. if ($this->parentHash) {
  206. throw new Exception('Atom already has a parent!');
  207. }
  208. $this->parentHash = $parent_hash;
  209. return $this;
  210. }
  211. public function hasParent() {
  212. return $this->parent || $this->parentHash;
  213. }
  214. public function setParent(DivinerAtom $atom) {
  215. if ($this->parentHash) {
  216. throw new Exception('Parent hash has already been computed!');
  217. }
  218. $this->parent = $atom;
  219. return $this;
  220. }
  221. public function getParentHash() {
  222. if ($this->parent && !$this->parentHash) {
  223. $this->parentHash = $this->parent->getHash();
  224. }
  225. return $this->parentHash;
  226. }
  227. public function addChild(DivinerAtom $atom) {
  228. if ($this->childHashes) {
  229. throw new Exception('Child hashes have already been computed!');
  230. }
  231. $atom->setParent($this);
  232. $this->children[] = $atom;
  233. return $this;
  234. }
  235. public function getURI() {
  236. $parts = array();
  237. $parts[] = phutil_escape_uri_path_component($this->getType());
  238. if ($this->getContext()) {
  239. $parts[] = phutil_escape_uri_path_component($this->getContext());
  240. }
  241. $parts[] = phutil_escape_uri_path_component($this->getName());
  242. $parts[] = null;
  243. return implode('/', $parts);
  244. }
  245. public function toDictionary() {
  246. // NOTE: If you change this format, bump the format version in
  247. // getAtomSerializationVersion().
  248. return array(
  249. 'book' => $this->getBook(),
  250. 'type' => $this->getType(),
  251. 'name' => $this->getName(),
  252. 'file' => $this->getFile(),
  253. 'line' => $this->getLine(),
  254. 'hash' => $this->getHash(),
  255. 'uri' => $this->getURI(),
  256. 'length' => $this->getLength(),
  257. 'context' => $this->getContext(),
  258. 'language' => $this->getLanguage(),
  259. 'docblockRaw' => $this->getDocblockRaw(),
  260. 'warnings' => $this->getWarnings(),
  261. 'parentHash' => $this->getParentHash(),
  262. 'childHashes' => $this->getChildHashes(),
  263. 'extends' => $this->getExtendsDictionaries(),
  264. 'links' => $this->getLinkDictionaries(),
  265. 'ref' => $this->getRef()->toDictionary(),
  266. 'properties' => $this->getProperties(),
  267. );
  268. }
  269. public function getRef() {
  270. $title = null;
  271. if ($this->docblockMeta) {
  272. $title = $this->getDocblockMetaValue('title');
  273. }
  274. return id(new DivinerAtomRef())
  275. ->setBook($this->getBook())
  276. ->setContext($this->getContext())
  277. ->setType($this->getType())
  278. ->setName($this->getName())
  279. ->setTitle($title)
  280. ->setGroup($this->getProperty('group'));
  281. }
  282. public static function newFromDictionary(array $dictionary) {
  283. $atom = id(new DivinerAtom())
  284. ->setBook(idx($dictionary, 'book'))
  285. ->setType(idx($dictionary, 'type'))
  286. ->setName(idx($dictionary, 'name'))
  287. ->setFile(idx($dictionary, 'file'))
  288. ->setLine(idx($dictionary, 'line'))
  289. ->setHash(idx($dictionary, 'hash'))
  290. ->setLength(idx($dictionary, 'length'))
  291. ->setContext(idx($dictionary, 'context'))
  292. ->setLanguage(idx($dictionary, 'language'))
  293. ->setParentHash(idx($dictionary, 'parentHash'))
  294. ->setDocblockRaw(idx($dictionary, 'docblockRaw'))
  295. ->setProperties(idx($dictionary, 'properties'));
  296. foreach (idx($dictionary, 'warnings', array()) as $warning) {
  297. $atom->addWarning($warning);
  298. }
  299. foreach (idx($dictionary, 'childHashes', array()) as $child) {
  300. $atom->addChildHash($child);
  301. }
  302. foreach (idx($dictionary, 'extends', array()) as $extends) {
  303. $atom->addExtends(DivinerAtomRef::newFromDictionary($extends));
  304. }
  305. return $atom;
  306. }
  307. public function getProperty($key, $default = null) {
  308. return idx($this->properties, $key, $default);
  309. }
  310. public function setProperty($key, $value) {
  311. $this->properties[$key] = $value;
  312. }
  313. public function getProperties() {
  314. return $this->properties;
  315. }
  316. public function setProperties(array $properties) {
  317. $this->properties = $properties;
  318. return $this;
  319. }
  320. public static function getThisAtomIsNotDocumentedString($type) {
  321. switch ($type) {
  322. case self::TYPE_FILE:
  323. return pht('This file is not documented.');
  324. case self::TYPE_FUNCTION:
  325. return pht('This function is not documented.');
  326. case self::TYPE_CLASS:
  327. return pht('This class is not documented.');
  328. case self::TYPE_ARTICLE:
  329. return pht('This article is not documented.');
  330. case self::TYPE_METHOD:
  331. return pht('This method is not documented.');
  332. case self::TYPE_INTERFACE:
  333. return pht('This interface is not documented.');
  334. default:
  335. phlog("Need translation for '{$type}'.");
  336. return pht('This %s is not documented.', $type);
  337. }
  338. }
  339. public static function getAllTypes() {
  340. return array(
  341. self::TYPE_FILE,
  342. self::TYPE_FUNCTION,
  343. self::TYPE_CLASS,
  344. self::TYPE_ARTICLE,
  345. self::TYPE_METHOD,
  346. self::TYPE_INTERFACE,
  347. );
  348. }
  349. public static function getAtomTypeNameString($type) {
  350. switch ($type) {
  351. case self::TYPE_FILE:
  352. return pht('File');
  353. case self::TYPE_FUNCTION:
  354. return pht('Function');
  355. case self::TYPE_CLASS:
  356. return pht('Class');
  357. case self::TYPE_ARTICLE:
  358. return pht('Article');
  359. case self::TYPE_METHOD:
  360. return pht('Method');
  361. case self::TYPE_INTERFACE:
  362. return pht('Interface');
  363. default:
  364. phlog("Need translation for '{$type}'.");
  365. return ucwords($type);
  366. }
  367. }
  368. }