/ext/doc/generate_doc_common.php

https://github.com/datastax/php-driver · PHP · 207 lines · 166 code · 29 blank · 12 comment · 26 complexity · b1ff6ea013e49320bdca7b48274c095c MD5 · raw file

  1. <?php
  2. define("INPUT_NAMESPACE", "Cassandra");
  3. function logWarning($message) {
  4. fwrite(STDERR, "Warning: $message" . PHP_EOL);
  5. }
  6. function doesParentHaveMethod($class, $method) {
  7. $parent = $class->getParentClass();
  8. if ($parent) {
  9. if ($parent->hasMethod($method->getName())) {
  10. return true;
  11. }
  12. return doesParentHaveMethod($parent, $method);
  13. }
  14. return false;
  15. }
  16. function getClassNameWithNoCoreNamespace($className) {
  17. return preg_replace("/" . INPUT_NAMESPACE . "\\\\/", "", $className);
  18. }
  19. class YamlClassDoc {
  20. private $class;
  21. private $fileName;
  22. private $yamlFileName;
  23. private $doc;
  24. private static $classDocs = array();
  25. private function __construct($class, $fileName, $yamlFileName, $doc) {
  26. $this->class = $class;
  27. $this->fileName = $fileName;
  28. $this->yamlFileName = $yamlFileName;
  29. $this->doc = $doc;
  30. }
  31. public function getClass() {
  32. return $this->class;
  33. }
  34. public function getClassNameWithNoCoreNamespace() {
  35. return getClassNameWithNoCoreNamespace($this->class->getName());
  36. }
  37. public function getFileName() {
  38. return $this->fileName;
  39. }
  40. public function getYamlFileName() {
  41. return $this->yamlFileName;
  42. }
  43. public function getDoc() {
  44. return $this->doc;
  45. }
  46. public static function getClassDocs() {
  47. return self::$classDocs;
  48. }
  49. /**
  50. * Get the first non-empty class comment
  51. */
  52. public function getParentClassComment() {
  53. $classDocs = self::$classDocs;
  54. return self::getParentDocInternal($this->class, function($className) use($classDocs) {
  55. if ($className &&
  56. isset(self::$classDocs[$className]) &&
  57. !empty(trim(self::$classDocs[$className]->getDoc()["comment"]))) {
  58. return self::$classDocs[$className]->getDoc()["comment"];
  59. }
  60. return null;
  61. });
  62. }
  63. /**
  64. * Get the first non-empty method comment
  65. */
  66. public function getParentMethodComment($methodName) {
  67. $classDocs = self::$classDocs;
  68. return self::getParentDocInternal($this->class, function($className) use($classDocs, $methodName) {
  69. if ($className &&
  70. isset(self::$classDocs[$className]) &&
  71. isset(self::$classDocs[$className]->getDoc()["methods"][$methodName])) {
  72. $methodDoc = self::$classDocs[$className]->getDoc()["methods"][$methodName];
  73. if (!empty(trim($methodDoc["comment"]))) {
  74. return $methodDoc["comment"];
  75. }
  76. return null;
  77. }
  78. });
  79. }
  80. /**
  81. * Get the first non-empty param doc
  82. */
  83. public function getParentParamDoc($methodName, $paramName) {
  84. $classDocs = self::$classDocs;
  85. return self::getParentDocInternal($this->class, function($className) use($classDocs, $methodName, $paramName) {
  86. if ($className &&
  87. isset(self::$classDocs[$className]) &&
  88. isset(self::$classDocs[$className]->getDoc()["methods"][$methodName]) &&
  89. isset(self::$classDocs[$className]->getDoc()["methods"][$methodName]['params'][$paramName])) {
  90. $paramDoc = self::$classDocs[$className]->getDoc()["methods"][$methodName]['params'][$paramName];
  91. if ($paramDoc["type"] != "mixed" && !empty(trim($paramDoc["comment"]))) {
  92. return $paramDoc;
  93. }
  94. }
  95. return null;
  96. });
  97. }
  98. /**
  99. * Get the first non-empty return doc
  100. */
  101. public function getParentReturnDoc($methodName) {
  102. $classDocs = self::$classDocs;
  103. return self::getParentDocInternal($this->class, function($className) use($classDocs, $methodName) {
  104. if ($className &&
  105. isset(self::$classDocs[$className]) &&
  106. isset(self::$classDocs[$className]->getDoc()["methods"][$methodName])) {
  107. $methodDoc = self::$classDocs[$className]->getDoc()["methods"][$methodName];
  108. if ($methodDoc["return"]["type"] != "mixed" && !empty(trim($methodDoc["return"]["comment"]))) {
  109. return $methodDoc["return"];
  110. }
  111. }
  112. return null;
  113. });
  114. }
  115. private static function getParentDocInternal($current, $getDoc) {
  116. $parent = $current->getParentClass();
  117. if ($parent) {
  118. $result = $getDoc($parent->getName());
  119. if ($result) {
  120. return $result;
  121. }
  122. }
  123. foreach ($current->getInterfaces() as $interface) {
  124. $result = $getDoc($interface->getName());
  125. if ($result) {
  126. return $result;
  127. }
  128. }
  129. if ($parent) {
  130. return self::getParentDocInternal($parent, $getDoc);
  131. }
  132. return null;
  133. }
  134. private static function loadYaml($class, $yamlFileName) {
  135. $doc = yaml_parse_file($yamlFileName);
  136. $classNameNoCoreNamespace = getClassNameWithNoCoreNamespace($class->getName());
  137. if ($doc === false) {
  138. $fullClassName = $class->getName();
  139. logWarning("Unable to load '$yamlFileName' for class '$fullClassName'");
  140. return array();
  141. } else if (isset($doc[$classNameNoCoreNamespace])){
  142. return $doc[$classNameNoCoreNamespace];
  143. } else {
  144. logWarning( "Unable to find top level class in '$yamlFileName'");
  145. return false;
  146. }
  147. return $doc;
  148. }
  149. private static function load($fileName, $dirName) {
  150. $yamlFileName = preg_replace("/(.+)\.c$/", "$1.yaml", $fileName);
  151. $fileName = substr($fileName, strlen($dirName));
  152. $fileName = preg_replace("/(.+)\.c$/", "$1", $fileName);
  153. if ($fileName == "/Core") {
  154. $fileName = "/" . INPUT_NAMESPACE;
  155. $fullClassName = str_replace("/", "\\", $fileName);
  156. } else {
  157. $fullClassName = INPUT_NAMESPACE . str_replace("/", "\\", $fileName);
  158. }
  159. try {
  160. $class = new ReflectionClass($fullClassName);
  161. $doc = self::loadYaml($class, $yamlFileName);
  162. if ($doc !== false) {
  163. self::$classDocs[$class->getName()] =
  164. new YamlClassDoc($class, $fileName, $yamlFileName, $doc);
  165. }
  166. } catch(Exception $e) {
  167. logWarning("Ignoring '$fullClassName': $e");
  168. }
  169. }
  170. public static function loadAll($dirName) {
  171. $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirName));
  172. $regex = new RegexIterator($iterator, '/^.+\.c$/i', RecursiveRegexIterator::GET_MATCH);
  173. foreach ($regex as $fileName => $notused) {
  174. echo "Loading... $fileName" . PHP_EOL;
  175. self::load($fileName, $dirName);
  176. }
  177. }
  178. }