api.ubcodeinspector.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /**
  3. * UBCodeInspector is responsible for inspecting and analyzing code base.
  4. */
  5. class UBCodeInspector {
  6. /**
  7. * Default Ubilling libs path
  8. *
  9. * @var string
  10. */
  11. protected $libsPath = 'api/libs/';
  12. /**
  13. * Contains full code environment
  14. *
  15. * @var array
  16. */
  17. protected $result = array();
  18. public function __construct() {
  19. $this->loadLibraries();
  20. $this->processClasses();
  21. $this->processFunctions();
  22. }
  23. /**
  24. * Preloads all available libs to inspect defined classess and function
  25. *
  26. * @return void
  27. */
  28. protected function loadLibraries() {
  29. $allLibs = rcms_scandir($this->libsPath, '*.php');
  30. $loadedRaw = get_included_files();
  31. $loadedLibs = array();
  32. if (!empty($loadedRaw)) {
  33. foreach ($loadedRaw as $each) {
  34. $fileName = basename($each);
  35. $loadedLibs[$fileName] = $each;
  36. }
  37. }
  38. if (!empty($allLibs)) {
  39. foreach ($allLibs as $eachLib) {
  40. if (!isset($loadedLibs[$eachLib]) and !ispos($eachLib, 'maps') and !ispos($eachLib, 'oll') and ($eachLib != 'api.ic.php')) {
  41. require_once($this->libsPath . $eachLib);
  42. }
  43. }
  44. }
  45. }
  46. /**
  47. * Preprocesses available classes and methods data
  48. *
  49. * @return void
  50. */
  51. protected function processClasses() {
  52. $allClasses = get_declared_classes();
  53. if (!empty($allClasses)) {
  54. foreach ($allClasses as $eachClass) {
  55. $classRef = new ReflectionClass($eachClass);
  56. $classLibName = $classRef->getFileName();
  57. $defineStartLine = $classRef->getStartLine();
  58. if (!empty($classLibName)) {
  59. $classLibName = $this->cleanFilePath($classLibName);
  60. }
  61. $classMethods = get_class_methods($eachClass);
  62. $methodParams = array();
  63. if (!empty($classMethods)) {
  64. foreach ($classMethods as $eachMethod) {
  65. $methodRef = new ReflectionMethod($eachClass, $eachMethod);
  66. $params = $methodRef->getParameters();
  67. $methodDefineLine = $methodRef->getStartLine();
  68. $methodComment = $methodRef->getDocComment();
  69. if (!empty($params)) {
  70. foreach ($params as $eachParam) {
  71. $paramName = $eachParam->getName();
  72. $paramOptional = $eachParam->isOptional();
  73. $methodParams[$eachMethod]['params'][$paramName] = $paramOptional;
  74. }
  75. $methodParams[$eachMethod]['line'] = $methodDefineLine;
  76. $methodParams[$eachMethod]['comment'] = $methodComment;
  77. } else {
  78. $methodParams[$eachMethod]['params'] = array();
  79. $methodParams[$eachMethod]['line'] = $methodDefineLine;
  80. $methodParams[$eachMethod]['comment'] = $methodComment;
  81. }
  82. }
  83. }
  84. $classComment = $classRef->getDocComment();
  85. $this->result['classes'][$eachClass]['comment'] = $classComment;
  86. $this->result['classes'][$eachClass]['file'] = $classLibName;
  87. $this->result['classes'][$eachClass]['line'] = $defineStartLine;
  88. $this->result['classes'][$eachClass]['methods'] = $methodParams;
  89. }
  90. }
  91. }
  92. /**
  93. * Preprocesses available functions
  94. *
  95. * @return void
  96. */
  97. protected function processFunctions() {
  98. $allFunctions = get_defined_functions();
  99. if (!empty($allFunctions)) {
  100. $funcParams = array();
  101. $allDefinedFuncs = $allFunctions['user'];
  102. if (!empty($allDefinedFuncs)) {
  103. foreach ($allDefinedFuncs as $eachFuncName) {
  104. $ref = new ReflectionFunction($eachFuncName);
  105. $originalFuncName = $ref->getName();
  106. $params = $ref->getParameters();
  107. $fileName = $ref->getFileName();
  108. $defineStartLine = $ref->getStartLine();
  109. $funcComment = $ref->getDocComment();
  110. if (!empty($fileName)) {
  111. $fileName = $this->cleanFilePath($fileName);
  112. }
  113. if (!empty($params)) {
  114. foreach ($params as $eachParam) {
  115. $paramName = $eachParam->getName();
  116. $paramOptional = $eachParam->isOptional();
  117. $funcParams[$originalFuncName]['params'][$paramName] = $paramOptional;
  118. }
  119. }
  120. $funcParams[$originalFuncName]['comment'] = $funcComment;
  121. $funcParams[$originalFuncName]['file'] = $fileName;
  122. $funcParams[$originalFuncName]['line'] = $defineStartLine;
  123. }
  124. }
  125. $this->result['functions'] = $funcParams;
  126. $internalParams = array();
  127. $allInternalFuncs = $allFunctions['internal'];
  128. if (!empty($allInternalFuncs)) {
  129. foreach ($allInternalFuncs as $eachFuncName) {
  130. $ref = new ReflectionFunction($eachFuncName);
  131. $params = $ref->getParameters();
  132. if (!empty($params)) {
  133. foreach ($params as $eachParam) {
  134. $paramName = $eachParam->getName();
  135. $paramOptional = $eachParam->isOptional();
  136. $internalParams[$eachFuncName][$paramName] = $paramOptional;
  137. }
  138. }
  139. }
  140. }
  141. $this->result['internal'] = $internalParams;
  142. }
  143. }
  144. /**
  145. * Parses docBlock data into human-readable text
  146. *
  147. * @param string $docComment
  148. * @param bool $extensive
  149. *
  150. * @return string
  151. */
  152. public function parseDocBlock($docComment, $extensive = true) {
  153. $result = '';
  154. if ($docComment) {
  155. $docComment = preg_replace('/^\/\*\*|\*\/$/', '', $docComment);
  156. $lines = preg_split('/\R/', $docComment);
  157. $cleanedLines = array_map(function ($line) {
  158. return preg_replace('/^\s*\*\s?/', '', $line);
  159. }, $lines);
  160. $cleanedComment = trim(implode("\n", $cleanedLines));
  161. preg_match_all('/@(\w+)\s+([^\n]+)/', $cleanedComment, $matches, PREG_SET_ORDER);
  162. if ($extensive) {
  163. $result .= __('Description') . ':' . PHP_EOL;
  164. }
  165. $result .= strtok($cleanedComment, '@') . "\n\n";
  166. if ($extensive) {
  167. $result .= __('Details') . ':' . PHP_EOL;
  168. foreach ($matches as $match) {
  169. $result .= ucfirst($match[1]) . ": " . trim($match[2]) . "\n";
  170. }
  171. }
  172. }
  173. return ($result);
  174. }
  175. /**
  176. * Cleans lib file-path and transforms it to relative
  177. *
  178. * @param string $path
  179. *
  180. * @return string
  181. */
  182. protected function cleanFilePath($path = '') {
  183. $result = '';
  184. if (!empty($path)) {
  185. $path = str_replace('/usr/local/www/apache24/data/', '', $path);
  186. $path = str_replace('/var/www/html/', '', $path);
  187. $path = str_replace('dev/ubilling/', '', $path);
  188. $path = str_replace('billing/', '', $path);
  189. $result = $path;
  190. }
  191. return ($result);
  192. }
  193. /**
  194. * Returns full code environment data
  195. *
  196. * @return void
  197. */
  198. public function getCodeEnv() {
  199. return ($this->result);
  200. }
  201. }