Do you wish to register an account?
A Query Builder and Database abstraction layer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

306 lines
5.7KB

  1. <?php declare(strict_types=1);
  2. use Robo\Tasks;
  3. if ( ! function_exists('glob_recursive'))
  4. {
  5. // Does not support flag GLOB_BRACE
  6. function glob_recursive($pattern, $flags = 0)
  7. {
  8. $files = glob($pattern, $flags);
  9. foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir)
  10. {
  11. $files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags));
  12. }
  13. return $files;
  14. }
  15. }
  16. /**
  17. * This is project's console commands configuration for Robo task runner.
  18. *
  19. * @see http://robo.li/
  20. */
  21. class RoboFile extends Tasks {
  22. /**
  23. * Directories used by analysis tools
  24. *
  25. * @var array
  26. */
  27. protected $taskDirs = [
  28. 'build/logs',
  29. 'build/pdepend',
  30. 'build/phpdox',
  31. ];
  32. /**
  33. * Directories to remove with the clean task
  34. *
  35. * @var array
  36. */
  37. protected $cleanDirs = [
  38. 'coverage',
  39. 'apiDocumentation',
  40. 'phpdoc',
  41. 'build/logs',
  42. 'build/phpdox',
  43. 'build/pdepend'
  44. ];
  45. /**
  46. * Do static analysis tasks
  47. */
  48. public function analyze(): void
  49. {
  50. $this->prepare();
  51. $this->lint();
  52. $this->phploc(TRUE);
  53. $this->phpcs(TRUE);
  54. $this->phpmd(TRUE);
  55. $this->phpcpdReport();
  56. }
  57. /**
  58. * Run all tests, generate coverage, generate docs, generate code statistics
  59. */
  60. public function build(): void
  61. {
  62. $this->analyze();
  63. $this->coverage();
  64. $this->docs();
  65. }
  66. /**
  67. * Cleanup temporary files
  68. */
  69. public function clean(): void
  70. {
  71. // So the task doesn't complain,
  72. // make any 'missing' dirs to cleanup
  73. array_map(static function ($dir) {
  74. if ( ! is_dir($dir))
  75. {
  76. `mkdir -p {$dir}`;
  77. }
  78. }, $this->cleanDirs);
  79. $this->_cleanDir($this->cleanDirs);
  80. $this->_deleteDir($this->cleanDirs);
  81. }
  82. /**
  83. * Run unit tests and generate coverage reports
  84. */
  85. public function coverage(): void
  86. {
  87. $this->_run(['phpdbg -qrr -- vendor/bin/phpunit -c build']);
  88. }
  89. /**
  90. * Generate documentation with phpdox
  91. */
  92. public function docs(): void
  93. {
  94. $this->_run(['vendor/bin/phpdox']);
  95. }
  96. /**
  97. * Verify that source files are valid
  98. */
  99. public function lint(): void
  100. {
  101. $files = $this->getAllSourceFiles();
  102. $chunks = array_chunk($files, (int)shell_exec('getconf _NPROCESSORS_ONLN'));
  103. foreach($chunks as $chunk)
  104. {
  105. $this->parallelLint($chunk);
  106. }
  107. }
  108. /**
  109. * Run the phpcs tool
  110. *
  111. * @param bool $report - if true, generates reports instead of direct output
  112. */
  113. public function phpcs($report = FALSE): void
  114. {
  115. $dir = __DIR__;
  116. $report_cmd_parts = [
  117. 'vendor/bin/phpcs',
  118. "--standard=./build/CodeIgniter",
  119. "--report-checkstyle=./build/logs/phpcs.xml",
  120. ];
  121. $normal_cmd_parts = [
  122. 'vendor/bin/phpcs',
  123. "--standard=./build/CodeIgniter",
  124. ];
  125. $cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
  126. $this->_run($cmd_parts);
  127. }
  128. public function phpmd($report = FALSE): void
  129. {
  130. $report_cmd_parts = [
  131. 'vendor/bin/phpmd',
  132. './src',
  133. 'xml',
  134. 'cleancode,codesize,controversial,design,naming,unusedcode',
  135. '--exclude ParallelAPIRequest',
  136. '--reportfile ./build/logs/phpmd.xml'
  137. ];
  138. $normal_cmd_parts = [
  139. 'vendor/bin/phpmd',
  140. './src',
  141. 'ansi',
  142. 'cleancode,codesize,controversial,design,naming,unusedcode',
  143. '--exclude ParallelAPIRequest'
  144. ];
  145. $cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
  146. $this->_run($cmd_parts);
  147. }
  148. /**
  149. * Run the phploc tool
  150. *
  151. * @param bool $report - if true, generates reports instead of direct output
  152. */
  153. public function phploc($report = FALSE): void
  154. {
  155. // Command for generating reports
  156. $report_cmd_parts = [
  157. 'vendor/bin/phploc',
  158. '--count-tests',
  159. '--log-csv=build/logs/phploc.csv',
  160. '--log-xml=build/logs/phploc.xml',
  161. 'src',
  162. 'tests'
  163. ];
  164. // Command for generating direct output
  165. $normal_cmd_parts = [
  166. 'vendor/bin/phploc',
  167. '--count-tests',
  168. 'src',
  169. 'tests'
  170. ];
  171. $cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
  172. $this->_run($cmd_parts);
  173. }
  174. /**
  175. * Create temporary directories
  176. */
  177. public function prepare(): void
  178. {
  179. array_map([$this, '_mkdir'], $this->taskDirs);
  180. }
  181. /**
  182. * Lint php files and run unit tests
  183. */
  184. public function test(): void
  185. {
  186. $this->lint();
  187. $this->taskPhpUnit()
  188. ->configFile('build/phpunit.xml')
  189. ->run();
  190. $this->_run(["php tests/index.php"]);
  191. }
  192. /**
  193. * Watches for file updates, and automatically runs appropriate actions
  194. */
  195. public function watch(): void
  196. {
  197. $this->taskWatch()
  198. ->monitor('composer.json', function() {
  199. $this->taskComposerUpdate()->run();
  200. })
  201. ->monitor('src', function () {
  202. $this->taskExec('test')->run();
  203. })
  204. ->monitor('tests', function () {
  205. $this->taskExec('test')->run();
  206. })
  207. ->run();
  208. }
  209. /**
  210. * Get the total list of source files, including tests
  211. *
  212. * @return array
  213. */
  214. protected function getAllSourceFiles(): array
  215. {
  216. $files = array_merge(
  217. glob_recursive('build/*.php'),
  218. glob_recursive('src/*.php'),
  219. glob_recursive('tests/*.php'),
  220. glob('*.php')
  221. );
  222. sort($files);
  223. return $files;
  224. }
  225. /**
  226. * Run php's linter in one parallel task for the passed chunk
  227. *
  228. * @param array $chunk
  229. */
  230. protected function parallelLint(array $chunk): void
  231. {
  232. $task = $this->taskParallelExec()
  233. ->timeout(5)
  234. ->printed(FALSE);
  235. foreach($chunk as $file)
  236. {
  237. $task = $task->process("php -l {$file}");
  238. }
  239. $task->run();
  240. }
  241. /**
  242. * Generate copy paste detector report
  243. */
  244. protected function phpcpdReport(): void
  245. {
  246. $cmd_parts = [
  247. 'vendor/bin/phpcpd',
  248. '--log-pmd build/logs/pmd-cpd.xml',
  249. 'src'
  250. ];
  251. $this->_run($cmd_parts);
  252. }
  253. /**
  254. * Shortcut for joining an array of command arguments
  255. * and then running it
  256. *
  257. * @param array $cmd_parts - command arguments
  258. * @param string $join_on - what to join the command arguments with
  259. */
  260. protected function _run(array $cmd_parts, $join_on = ' '): void
  261. {
  262. $this->taskExec(implode($join_on, $cmd_parts))->run();
  263. }
  264. }