PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/phplinter/Report/Html.php

http://github.com/robotis/PHPLinter
PHP | 311 lines | 213 code | 10 blank | 88 comment | 31 complexity | 1f5646f383e537f4e02238bb500b723d MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. ----------------------------------------------------------------------+
  4. * @desc HTML Reporter
  5. * @file Html.php
  6. * @author Jóhann T. Maríusson <jtm@robot.is>
  7. * @since Feb 6, 2012
  8. * @package PHPLinter
  9. * @copyright
  10. * phplinter is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. ----------------------------------------------------------------------+
  23. */
  24. namespace phplinter\Report;
  25. class Html extends Base {
  26. /**
  27. ----------------------------------------------------------------------+
  28. * @desc Prepare report.
  29. ----------------------------------------------------------------------+
  30. */
  31. public function prepare() {
  32. $this->html = $this->config->check('report');
  33. if(empty($this->html['out'])) {
  34. return 'No output directory selected...';
  35. }
  36. if($this->html['out'] == $this->config->check('target')) {
  37. return 'Output directory same as target, aborting...';
  38. }
  39. if(file_exists($this->html['out'])) {
  40. if(!$this->html['overwrite']) {
  41. $files = @scandir($this->html['out']);
  42. if(count($files) > 2)
  43. return 'Output directory not empty, will not overwrite...';
  44. }
  45. }
  46. if(isset($this->html['dry_run']))
  47. $this->dry_run = $this->html['dry_run'];
  48. return true;
  49. }
  50. /**
  51. ----------------------------------------------------------------------+
  52. * @desc Create HTML report
  53. * @param Array Lint report
  54. * @param Array Lint scores
  55. * @param String Target
  56. ----------------------------------------------------------------------+
  57. */
  58. public function create($report, $penaltys=null, $root=null) {
  59. $this->root = realpath($root);
  60. $output_dir = realpath($this->html['out']);
  61. if(!$output_dir) $output_dir = $this->html['out'];
  62. if($this->config->check(OPT_VERBOSE))
  63. echo "Generating HTML Report to '$output_dir'\n";
  64. if(file_exists($output_dir) && $this->html['overwrite']) {
  65. if($this->config->check(OPT_VERBOSE))
  66. echo "Emptying `$output_dir`\n";
  67. if(!$this->dry_run)
  68. \phplinter\Path::del_recursive($output_dir);
  69. }
  70. if(!file_exists($output_dir)) {
  71. $this->mkdir($output_dir, 0775);
  72. }
  73. $this->write($output_dir . '/html_report.css', $this->css());
  74. foreach($report as $file => $rep) {
  75. $out = '<div class="wrapper"><table border="1" cellpadding="0" cellspacing="0">';
  76. $content = '';
  77. foreach($rep as $_) {
  78. $content .= $this->_fmessage($_);
  79. }
  80. $out .= '<tr>';
  81. $score = (SCORE_FULL + $penaltys[$file]);
  82. $class = $this->get_score_class($score);
  83. $out .= '<td colspan="2" align="center" class="'.$class.'">';
  84. $out .= sprintf('Score: %.2f', $score);
  85. $out .= '</td>';
  86. $parts = explode('/', $file);
  87. $rfile = array_pop($parts);
  88. $depth = count($parts);
  89. $path = $depth > 1
  90. ? implode('/', $parts)
  91. : '';
  92. $path = substr(realpath($path), strlen($this->root));
  93. $out .= '<td class="filename">';
  94. $out .= "$path/$rfile";
  95. $out .= '<td class="line">';
  96. $out .= 'Line</td></tr>';
  97. $out .= '</td></tr>';
  98. $out .= $content;
  99. $out .= '</table></div>';
  100. $dir = $output_dir . $path;
  101. if(!file_exists($dir)) {
  102. $this->mkdir($dir, 0775, true);
  103. }
  104. $pp = explode('/', substr(realpath(implode('/', $parts)), mb_strlen($this->root)));
  105. $ofile = $dir . '/' . strtr($rfile, './', '__').'.html';
  106. $this->write($ofile, $this->_html($out, count($pp)));
  107. $url['phplinter___file'] = $file;
  108. $url['phplinter___url'] = strtr($rfile, './', '__').'.html';
  109. $url['phplinter___sort'] = strtolower($url['phplinter___url']);
  110. $this->parts($pp, $url, $urls);
  111. }
  112. $urls = $this->sort($urls);
  113. $this->output_indexes($urls, $penaltys);
  114. }
  115. /**
  116. ----------------------------------------------------------------------+
  117. * @desc Format message
  118. * @param Array
  119. * @return HTML
  120. ----------------------------------------------------------------------+
  121. */
  122. protected function _fmessage($arr) {
  123. return sprintf('<tr><td align="center" class="fl_%s">%s</td>'
  124. . '<td class="message">%s</td>'
  125. . '<td class="where">%s</td>'
  126. . '<td class="line">%d</td></tr>'
  127. ,$arr['flag'][0]
  128. ,$arr['flag']
  129. ,$arr['message']
  130. ,$arr['where']
  131. ,$arr['line']
  132. );
  133. }
  134. /**
  135. ----------------------------------------------------------------------+
  136. * @desc Fills in the correct directorys
  137. * @param $parts Array
  138. * @param $url Array
  139. * @param $urls Reference (Array)
  140. ----------------------------------------------------------------------+
  141. */
  142. protected function parts($parts, $url, &$urls) {
  143. if(empty($parts)) return;
  144. $part = array_shift($parts);
  145. if(!isset($urls[$part])) {
  146. $urls[$part] = array();
  147. }
  148. if(empty($parts)) {
  149. $urls[$part][] = $url;
  150. } else $this->parts($parts, $url, $urls[$part]);
  151. }
  152. /**
  153. ----------------------------------------------------------------------+
  154. * @desc Create index files for report
  155. * @return String
  156. ----------------------------------------------------------------------+
  157. */
  158. protected function css() {
  159. return file_get_contents(dirname(__FILE__) . '/html_report.css');
  160. }
  161. /**
  162. ----------------------------------------------------------------------+
  163. * @desc Create index files for report
  164. * @param $urls Array
  165. * @param $penaltys Array
  166. * @param $path String
  167. * @param $depth int
  168. * @return Array
  169. ----------------------------------------------------------------------+
  170. */
  171. protected function output_indexes($urls, $penaltys, $path='', $depth=0) {
  172. $out = '<div class="wrapper"><table border="1" cellpadding="0" cellspacing="0">';
  173. $out .= '<tr><td align="center">'.date("d / M / Y").'</td>';
  174. $out .= '<td colspan="2" align="center">'.$this->root.'</td></tr>';
  175. $content = '';
  176. $total = 0; $num = 0;
  177. foreach($urls as $k => $_) {
  178. $content .= '<tr>';
  179. if(isset($_['phplinter___file'])) {
  180. $score = (SCORE_FULL + $penaltys[$_['phplinter___file']]);
  181. $total += $score;
  182. $num++;
  183. $class = $this->get_score_class($score);
  184. $content .= '<td class="'.$class.'">'.sprintf('%.2f', $score).'</td>';
  185. $limit = $score == 10 ? 'perfect' : 'limit';
  186. $content .= '<td class="'.$limit.'">'.sprintf('%.2f', SCORE_FULL).'</td>';
  187. $content .= '<td><a href="'
  188. . $_['phplinter___url'] . '">'
  189. . mb_substr(realpath($_['phplinter___file']), mb_strlen($this->root . $path))
  190. . '</a></td>';
  191. } else {
  192. list($ototal, $onum) = $this->output_indexes($urls[$k], $penaltys,
  193. $path . $k.'/', $depth+1);
  194. $avarage = ($ototal / $onum);
  195. $class = $this->get_score_class($avarage);
  196. $content .= sprintf('<td colspan="2" class="%s">Average: %.2f</td>',
  197. $class, $avarage);
  198. $content .= '<td class="folder"><a href="'.$k.'">'.$k.'</a></td>';
  199. $total += $ototal;
  200. $num += $onum;
  201. }
  202. $content .= '</tr>';
  203. }
  204. $out .= '<tr>';
  205. $avarage = ($total / $num);
  206. $class = $this->get_score_class($avarage);
  207. $out .= sprintf('<td colspan="2" align="center" class="%s">Average: %.2f</td>'
  208. ,$class
  209. ,$avarage);
  210. $out .= '<td>'.$path.'</td>';
  211. $out .= '</tr>';
  212. $out .= $content;
  213. $out .= '</table></div>';
  214. $path = ($path == '/')
  215. ? $this->html['out']
  216. : $path;
  217. $dir = ($path == $this->html['out'])
  218. ? $path
  219. : rtrim($this->html['out'], '/') . $path;
  220. $dir = rtrim($dir, '/') . '/';
  221. if(!empty($path)) {
  222. $file = $dir . 'index.html';
  223. $this->write($file, $this->_html($out, $depth));
  224. }
  225. $this->dirs[] = $dir;
  226. return array($total, $num);
  227. }
  228. /**
  229. ----------------------------------------------------------------------+
  230. * @desc Create HTML report
  231. * @param $content HTML
  232. * @param $depth int
  233. * @return HTML
  234. ----------------------------------------------------------------------+
  235. */
  236. protected function _html($content, $depth=0) {
  237. $r = str_pad('', ($depth-1)*3, '../');
  238. $out = "<!DOCTYPE html>\n";
  239. $out .= "<html>\n";
  240. $out .= "<head>\n";
  241. $out .= '<link rel="stylesheet" type="text/css" href="'.$r.'html_report.css"/>';
  242. $out .= "</head>\n";
  243. $out .= "<body>\n";
  244. $out .= $content;
  245. $out .= "</body>\n";
  246. $out .= '</html>';
  247. return $out;
  248. }
  249. /**
  250. ----------------------------------------------------------------------+
  251. * @desc CSS Class for score
  252. * @param $score float
  253. * @return String
  254. ----------------------------------------------------------------------+
  255. */
  256. protected function get_score_class($score) {
  257. if($score < 0)
  258. return 'terrible';
  259. elseif($score < 5)
  260. return 'bad';
  261. elseif($score < 7)
  262. return 'average';
  263. elseif($score < 9)
  264. return 'good';
  265. elseif($score < 10)
  266. return 'vgood';
  267. return 'perfect';
  268. }
  269. /**
  270. ----------------------------------------------------------------------+
  271. * @desc Sort the result array
  272. * @param Array
  273. * @return Array
  274. ----------------------------------------------------------------------+
  275. */
  276. protected function sort($urls) {
  277. $files = array();
  278. $dirs = array();
  279. foreach($urls as $k => $_) {
  280. if(isset($_['phplinter___sort']))
  281. $files[] = $_;
  282. else $dirs[$k] = $_;
  283. }
  284. if(!empty($dirs)) {
  285. uksort($dirs, function($a, $b) {
  286. return mb_strtolower($a) > mb_strtolower($b);
  287. });
  288. }
  289. if(!empty($files)) {
  290. foreach($files as $_) $arr[] = $_['phplinter___sort'];
  291. array_multisort($files, SORT_ASC, $arr);
  292. }
  293. $urls = array_merge($dirs, $files);
  294. foreach($urls as $k => $_) {
  295. if(!is_numeric($k)) {
  296. $urls[$k] = $this->sort($urls[$k]);
  297. }
  298. }
  299. return $urls;
  300. }
  301. }