/classes/scripts/treemap.php

https://github.com/tharkun/atoum · PHP · 453 lines · 379 code · 74 blank · 0 comment · 34 complexity · 5aadbffd95f13a04f19c5956ff927311 MD5 · raw file

  1. <?php
  2. namespace mageekguy\atoum\scripts;
  3. use
  4. mageekguy\atoum,
  5. mageekguy\atoum\exceptions,
  6. mageekguy\atoum\scripts\treemap\analyzers
  7. ;
  8. class treemap extends atoum\script\configurable
  9. {
  10. const defaultConfigFile = '.treemap.php';
  11. const dataFile = 'data.json';
  12. protected $projectName = null;
  13. protected $projectUrl = null;
  14. protected $codeUrl = null;
  15. protected $directories = array();
  16. protected $htmlDirectory = null;
  17. protected $outputDirectory = null;
  18. protected $onlyJsonFile = false;
  19. protected $analyzers = array();
  20. protected $categorizers = array();
  21. public function __construct($name, atoum\adapter $adapter = null)
  22. {
  23. parent::__construct($name, $adapter);
  24. $this->setIncluder();
  25. }
  26. public function getProjectName()
  27. {
  28. return $this->projectName;
  29. }
  30. public function setProjectName($projectName)
  31. {
  32. $this->projectName = $projectName;
  33. return $this;
  34. }
  35. public function getProjectUrl()
  36. {
  37. return $this->projectUrl;
  38. }
  39. public function setProjectUrl($projectUrl)
  40. {
  41. $this->projectUrl = $projectUrl;
  42. return $this;
  43. }
  44. public function getCodeUrl()
  45. {
  46. return $this->codeUrl;
  47. }
  48. public function setCodeUrl($codeUrl)
  49. {
  50. $this->codeUrl = $codeUrl;
  51. return $this;
  52. }
  53. public function addDirectory($directory)
  54. {
  55. if (in_array($directory, $this->directories) === false)
  56. {
  57. $this->directories[] = $directory;
  58. }
  59. return $this;
  60. }
  61. public function getDirectories()
  62. {
  63. return $this->directories;
  64. }
  65. public function setHtmlDirectory($path = null)
  66. {
  67. $this->htmlDirectory = $path;
  68. return $this;
  69. }
  70. public function getHtmlDirectory()
  71. {
  72. return $this->htmlDirectory;
  73. }
  74. public function setOutputDirectory($directory)
  75. {
  76. $this->outputDirectory = $directory;
  77. return $this;
  78. }
  79. public function getOutputDirectory()
  80. {
  81. return $this->outputDirectory;
  82. }
  83. public function getOnlyJsonFile($boolean = null)
  84. {
  85. if ($boolean !== null)
  86. {
  87. $this->onlyJsonFile = ($boolean == true);
  88. }
  89. return $this->onlyJsonFile;
  90. }
  91. public function getAnalyzers()
  92. {
  93. return $this->analyzers;
  94. }
  95. public function addAnalyzer(treemap\analyzer $analyzer)
  96. {
  97. $this->analyzers[] = $analyzer;
  98. return $this;
  99. }
  100. public function getCategorizers()
  101. {
  102. return $this->categorizers;
  103. }
  104. public function addCategorizer(treemap\categorizer $categorizer)
  105. {
  106. $this->categorizers[] = $categorizer;
  107. return $this;
  108. }
  109. public function useConfigFile($path)
  110. {
  111. $script = $this;
  112. return $this->includeConfigFile($path, function($path) use ($script) { include_once($path); });
  113. }
  114. protected function setArgumentHandlers()
  115. {
  116. return parent::setArgumentHandlers()
  117. ->addArgumentHandler(
  118. function($script, $argument, $projectName) {
  119. if (sizeof($projectName) != 1)
  120. {
  121. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getName()));
  122. }
  123. $script->setProjectName(current($projectName));
  124. },
  125. array('-pn', '--project-name'),
  126. '<string>',
  127. $this->locale->_('Set project name <string>')
  128. )
  129. ->addArgumentHandler(
  130. function($script, $argument, $projectUrl) {
  131. if (sizeof($projectUrl) != 1)
  132. {
  133. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getUrl()));
  134. }
  135. $script->setProjectUrl(current($projectUrl));
  136. },
  137. array('-pu', '--project-url'),
  138. '<string>',
  139. $this->locale->_('Set project url <string>')
  140. )
  141. ->addArgumentHandler(
  142. function($script, $argument, $codeUrl) {
  143. if (sizeof($codeUrl) != 1)
  144. {
  145. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getUrl()));
  146. }
  147. $script->setCodeUrl(current($codeUrl));
  148. },
  149. array('-cu', '--code-url'),
  150. '<string>',
  151. $this->locale->_('Set code url <string>')
  152. )
  153. ->addArgumentHandler(
  154. function($script, $argument, $directories) {
  155. if (sizeof($directories) <= 0)
  156. {
  157. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getName()));
  158. }
  159. foreach ($directories as $directory)
  160. {
  161. $script->addDirectory($directory);
  162. }
  163. },
  164. array('-d', '--directories'),
  165. '<directory>...',
  166. $this->locale->_('Scan all directories <directory>')
  167. )
  168. ->addArgumentHandler(
  169. function($script, $argument, $outputDirectory) {
  170. if (sizeof($outputDirectory) != 1)
  171. {
  172. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getName()));
  173. }
  174. $script->setOutputDirectory(current($outputDirectory));
  175. },
  176. array('-od', '--output-directory'),
  177. '<directory>',
  178. $this->locale->_('Generate treemap in directory <directory>')
  179. )
  180. ->addArgumentHandler(
  181. function($script, $argument, $value) {
  182. if (sizeof($value) != 0)
  183. {
  184. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getName()));
  185. }
  186. $script->getOnlyJsonFile(true);
  187. },
  188. array('-ojf', '--only-json-file'),
  189. null,
  190. $this->locale->_('Generate only JSON file')
  191. )
  192. ->addArgumentHandler(
  193. function($script, $argument, $value) {
  194. if (sizeof($value) != 0)
  195. {
  196. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getName()));
  197. }
  198. $script->addAnalyzer(new analyzers\sloc());
  199. },
  200. array('--sloc'),
  201. null,
  202. $this->locale->_('Count source line of code (SLOC)')
  203. )
  204. ->addArgumentHandler(
  205. function($script, $argument, $value) {
  206. if (sizeof($value) != 0)
  207. {
  208. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getName()));
  209. }
  210. $script->addAnalyzer(new analyzers\token());
  211. },
  212. array('--php-token'),
  213. null,
  214. $this->locale->_('Count PHP tokens')
  215. )
  216. ->addArgumentHandler(
  217. function($script, $argument, $value) {
  218. if (sizeof($value) != 0)
  219. {
  220. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getName()));
  221. }
  222. $script->addAnalyzer(new analyzers\size());
  223. },
  224. array('--file-size'),
  225. null,
  226. $this->locale->_('Get file size')
  227. )
  228. ->addArgumentHandler(
  229. function($script, $argument, $htmlDirectory) {
  230. if (sizeof($htmlDirectory) != 1)
  231. {
  232. throw new exceptions\logic\invalidArgument(sprintf($script->getLocale()->_('Bad usage of %s, do php %s --help for more informations'), $argument, $script->getName()));
  233. }
  234. $script->setHtmlDirectory(current($htmlDirectory));
  235. },
  236. array('-hd', '--html-directory'),
  237. '<directory>',
  238. $this->locale->_('Use html files in <directory> to generate treemap')
  239. )
  240. ;
  241. }
  242. protected function doRun()
  243. {
  244. if ($this->projectName === null)
  245. {
  246. throw new exceptions\runtime($this->locale->_('Project name is undefined'));
  247. }
  248. if (sizeof($this->directories) <= 0)
  249. {
  250. throw new exceptions\runtime($this->locale->_('Directories are undefined'));
  251. }
  252. if ($this->outputDirectory === null)
  253. {
  254. throw new exceptions\runtime($this->locale->_('Output directory is undefined'));
  255. }
  256. if ($this->htmlDirectory === null)
  257. {
  258. throw new exceptions\runtime($this->locale->_('Html directory is undefined'));
  259. }
  260. $maxDepth = 1;
  261. $nodes = array(
  262. 'name' => $this->projectName,
  263. 'url' => $this->projectUrl,
  264. 'path' => '',
  265. 'children' => array()
  266. );
  267. foreach ($this->directories as $rootDirectory)
  268. {
  269. try
  270. {
  271. $directoryIterator = new \recursiveIteratorIterator(new atoum\iterators\filters\recursives\dot($rootDirectory));
  272. }
  273. catch (\exception $exception)
  274. {
  275. throw new exceptions\runtime($this->locale->_('Directory \'' . $rootDirectory . '\' does not exist'));
  276. }
  277. foreach ($directoryIterator as $file)
  278. {
  279. $node = & $nodes;
  280. $directories = ltrim(substr(dirname($file->getPathname()), strlen($rootDirectory)), DIRECTORY_SEPARATOR);
  281. if ($directories !== '')
  282. {
  283. $directories = explode(DIRECTORY_SEPARATOR, $directories);
  284. $depth = sizeof($directories);
  285. if ($depth > $maxDepth)
  286. {
  287. $maxDepth = $depth;
  288. }
  289. foreach ($directories as $directory)
  290. {
  291. $childFound = false;
  292. foreach ($node['children'] as $key => $child)
  293. {
  294. $childFound = ($child['name'] === $directory);
  295. if ($childFound === true)
  296. {
  297. break;
  298. }
  299. }
  300. if ($childFound === false)
  301. {
  302. $key = sizeof($node['children']);
  303. $node['children'][] = array(
  304. 'name' => $directory,
  305. 'path' => $node['path'] . DIRECTORY_SEPARATOR . $directory,
  306. 'children' => array()
  307. );
  308. }
  309. $node = & $node['children'][$key];
  310. }
  311. }
  312. $child = array(
  313. 'name' => $file->getFilename(),
  314. 'path' => $node['path'] . DIRECTORY_SEPARATOR . $file->getFilename(),
  315. 'metrics' => array(),
  316. 'type' => ''
  317. );
  318. foreach ($this->analyzers as $analyzer)
  319. {
  320. $child['metrics'][$analyzer->getMetricName()] = $analyzer->getMetricFromFile($file);
  321. }
  322. foreach ($this->categorizers as $categorizer)
  323. {
  324. if ($categorizer->categorize($file) === true)
  325. {
  326. $child['type'] = $categorizer->getName();
  327. break;
  328. }
  329. }
  330. $node['children'][] = $child;
  331. }
  332. }
  333. $data = array(
  334. 'codeUrl' => $this->codeUrl,
  335. 'metrics' => array(),
  336. 'categorizers' => array(),
  337. 'maxDepth' => $maxDepth,
  338. 'nodes' => $nodes
  339. );
  340. foreach ($this->analyzers as $analyzer)
  341. {
  342. $data['metrics'][] = array(
  343. 'name' => $analyzer->getMetricName(),
  344. 'label' => $analyzer->getMetricLabel()
  345. );
  346. }
  347. foreach ($this->categorizers as $categorizer)
  348. {
  349. $data['categorizers'][] = array(
  350. 'name' => $categorizer->getName(),
  351. 'minDepthColor' => $categorizer->getMinDepthColor(),
  352. 'maxDepthColor' => $categorizer->getMaxDepthColor()
  353. );
  354. }
  355. if (@file_put_contents($this->outputDirectory . DIRECTORY_SEPARATOR . self::dataFile, json_encode($data)) === false)
  356. {
  357. throw new exceptions\runtime($this->locale->_('Unable to write in \'' . $this->outputDirectory . '\''));
  358. }
  359. if ($this->onlyJsonFile === false)
  360. {
  361. try
  362. {
  363. $htmlDirectoryIterator = new \recursiveIteratorIterator(new atoum\iterators\filters\recursives\dot($this->htmlDirectory));
  364. }
  365. catch (\exception $exception)
  366. {
  367. throw new exceptions\runtime($this->locale->_('Directory \'' . $this->htmlDirectory . '\' does not exist'));
  368. }
  369. foreach ($htmlDirectoryIterator as $file)
  370. {
  371. if (@copy($file, $this->outputDirectory . DIRECTORY_SEPARATOR . basename($file)) === false)
  372. {
  373. throw new exceptions\runtime($this->locale->_('Unable to write in \'' . $this->outputDirectory . '\''));
  374. }
  375. }
  376. }
  377. return $this;
  378. }
  379. }