PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/applications/diviner/atom/DivinerAtomRef.php

https://github.com/navyuginfo/phabricator
PHP | 210 lines | 170 code | 30 blank | 10 comment | 6 complexity | 2499d2100457398db1bd637e8aeb3279 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 DivinerAtomRef {
  3. private $book;
  4. private $context;
  5. private $type;
  6. private $name;
  7. private $group;
  8. private $summary;
  9. private $index;
  10. private $title;
  11. public function getSortKey() {
  12. return implode(
  13. "\0",
  14. array(
  15. $this->getName(),
  16. $this->getType(),
  17. $this->getContext(),
  18. $this->getBook(),
  19. $this->getIndex(),
  20. ));
  21. }
  22. public function setIndex($index) {
  23. $this->index = $index;
  24. return $this;
  25. }
  26. public function getIndex() {
  27. return $this->index;
  28. }
  29. public function setSummary($summary) {
  30. $this->summary = $summary;
  31. return $this;
  32. }
  33. public function getSummary() {
  34. return $this->summary;
  35. }
  36. public function setName($name) {
  37. $normal_name = self::normalizeString($name);
  38. if (preg_match('/^@[0-9]+\z/', $normal_name)) {
  39. throw new Exception(
  40. "Atom names must not be in the form '/@\d+/'. This pattern is ".
  41. "reserved for disambiguating atoms with similar names.");
  42. }
  43. $this->name = $normal_name;
  44. return $this;
  45. }
  46. public function getName() {
  47. return $this->name;
  48. }
  49. public function setType($type) {
  50. $this->type = self::normalizeString($type);
  51. return $this;
  52. }
  53. public function getType() {
  54. return $this->type;
  55. }
  56. public function setContext($context) {
  57. if ($context === null) {
  58. $this->context = $context;
  59. } else {
  60. $this->context = self::normalizeString($context);
  61. }
  62. return $this;
  63. }
  64. public function getContext() {
  65. return $this->context;
  66. }
  67. public function setBook($book) {
  68. if ($book === null) {
  69. $this->book = $book;
  70. } else {
  71. $this->book = self::normalizeString($book);
  72. }
  73. return $this;
  74. }
  75. public function getBook() {
  76. return $this->book;
  77. }
  78. public function setGroup($group) {
  79. $this->group = $group;
  80. return $this;
  81. }
  82. public function getGroup() {
  83. return $this->group;
  84. }
  85. public function setTitle($title) {
  86. $this->title = $title;
  87. return $this;
  88. }
  89. public function getTitle() {
  90. return $this->title;
  91. }
  92. public function getTitleSlug() {
  93. return self::normalizeTitleString($this->getTitle());
  94. }
  95. public function toDictionary() {
  96. return array(
  97. 'book' => $this->getBook(),
  98. 'context' => $this->getContext(),
  99. 'type' => $this->getType(),
  100. 'name' => $this->getName(),
  101. 'group' => $this->getGroup(),
  102. 'index' => $this->getIndex(),
  103. 'summary' => $this->getSummary(),
  104. 'title' => $this->getTitle(),
  105. );
  106. }
  107. public function toHash() {
  108. $dict = $this->toDictionary();
  109. unset($dict['group']);
  110. unset($dict['index']);
  111. unset($dict['summary']);
  112. unset($dict['title']);
  113. ksort($dict);
  114. return md5(serialize($dict)).'S';
  115. }
  116. public static function newFromDictionary(array $dict) {
  117. $obj = new DivinerAtomRef();
  118. $obj->setBook(idx($dict, 'book'));
  119. $obj->setContext(idx($dict, 'context'));
  120. $obj->setType(idx($dict, 'type'));
  121. $obj->setName(idx($dict, 'name'));
  122. $obj->group = idx($dict, 'group');
  123. $obj->index = idx($dict, 'index');
  124. $obj->summary = idx($dict, 'summary');
  125. $obj->title = idx($dict, 'title');
  126. return $obj;
  127. }
  128. public static function normalizeString($str) {
  129. // These characters create problems on the filesystem or in URIs. Replace
  130. // them with non-problematic appoximations (instead of simply removing them)
  131. // to keep the URIs fairly useful and avoid unnecessary collisions. These
  132. // approximations are selected based on some domain knowledge of common
  133. // languages: where a character is used as a delimiter, it is more helpful
  134. // to replace it with a "." or a ":" or similar, while it's better if
  135. // operator overloads read as, e.g., "operator_div".
  136. $map = array(
  137. // Hopefully not used anywhere by anything.
  138. '#' => '.',
  139. // Used in Ruby methods.
  140. '?' => 'Q',
  141. // Used in PHP namespaces.
  142. '\\' => '.',
  143. // Used in "operator +" in C++.
  144. '+' => 'plus',
  145. // Used in "operator %" in C++.
  146. '%' => 'mod',
  147. // Used in "operator /" in C++.
  148. '/' => 'div',
  149. );
  150. $str = str_replace(array_keys($map), array_values($map), $str);
  151. // Replace all spaces with underscores.
  152. $str = preg_replace('/ +/', '_', $str);
  153. // Replace control characters with "X".
  154. $str = preg_replace('/[\x00-\x19]/', 'X', $str);
  155. // Replace specific problematic names with alternative names.
  156. $alternates = array(
  157. '.' => 'dot',
  158. '..' => 'dotdot',
  159. '' => 'null',
  160. );
  161. return idx($alternates, $str, $str);
  162. }
  163. public static function normalizeTitleString($str) {
  164. // Remove colons from titles. This is mostly to accommodate legacy rules
  165. // from the old Diviner, which generated a significant number of article
  166. // URIs without colons present in the titles.
  167. $str = str_replace(':', '', $str);
  168. $str = self::normalizeString($str);
  169. return phutil_utf8_strtolower($str);
  170. }
  171. }