]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/PHP/CodeCoverage/Report/HTML/Node.php
Release 6.2.0
[Github/sugarcrm.git] / tests / PHPUnit / PHP / CodeCoverage / Report / HTML / Node.php
1 <?php
2 /**
3  * PHP_CodeCoverage
4  *
5  * Copyright (c) 2009-2011, Sebastian Bergmann <sb@sebastian-bergmann.de>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *
15  *   * Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in
17  *     the documentation and/or other materials provided with the
18  *     distribution.
19  *
20  *   * Neither the name of Sebastian Bergmann nor the names of his
21  *     contributors may be used to endorse or promote products derived
22  *     from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * @category   PHP
38  * @package    CodeCoverage
39  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40  * @copyright  2009-2011 Sebastian Bergmann <sb@sebastian-bergmann.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42  * @link       http://github.com/sebastianbergmann/php-code-coverage
43  * @since      File available since Release 1.0.0
44  */
45
46 /**
47  * Base class for nodes in the code coverage information tree.
48  *
49  * @category   PHP
50  * @package    CodeCoverage
51  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
52  * @copyright  2009-2011 Sebastian Bergmann <sb@sebastian-bergmann.de>
53  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
54  * @version    Release: 1.0.4
55  * @link       http://github.com/sebastianbergmann/php-code-coverage
56  * @since      Class available since Release 1.0.0
57  */
58 abstract class PHP_CodeCoverage_Report_HTML_Node
59 {
60     /**
61      * @var array
62      */
63     protected $cache = array();
64
65     /**
66      * @var string
67      */
68     protected $name;
69
70     /**
71      * @var PHP_CodeCoverage_Report_HTML_Node
72      */
73     protected $parent;
74
75     /**
76      * Constructor.
77      *
78      * @param string                            $name
79      * @param PHP_CodeCoverage_Report_HTML_Node $parent
80      */
81     public function __construct($name, PHP_CodeCoverage_Report_HTML_Node $parent = NULL)
82     {
83         $this->name   = $name;
84         $this->parent = $parent;
85     }
86
87     /**
88      * Returns the percentage of classes that has been tested.
89      *
90      * @return integer
91      */
92     public function getTestedClassesPercent()
93     {
94         return PHP_CodeCoverage_Util::percent(
95           $this->getNumTestedClasses(),
96           $this->getNumClasses(),
97           TRUE
98         );
99     }
100
101     /**
102      * Returns the percentage of methods that has been tested.
103      *
104      * @return integer
105      */
106     public function getTestedMethodsPercent()
107     {
108         return PHP_CodeCoverage_Util::percent(
109           $this->getNumTestedMethods(),
110           $this->getNumMethods(),
111           TRUE
112         );
113     }
114
115     /**
116      * Returns the percentage of executed lines.
117      *
118      * @return integer
119      */
120     public function getLineExecutedPercent()
121     {
122         return PHP_CodeCoverage_Util::percent(
123           $this->getNumExecutedLines(),
124           $this->getNumExecutableLines(),
125           TRUE
126         );
127     }
128
129     /**
130      * Returns this node's ID.
131      *
132      * @return string
133      */
134     public function getId()
135     {
136         if (!isset($this->cache['id'])) {
137             if ($this->parent === NULL) {
138                 $this->cache['id'] = 'index';
139             } else {
140                 $parentId = $this->parent->getId();
141
142                 if ($parentId == 'index') {
143                     $this->cache['id'] = $this->getName();
144                 } else {
145                     $this->cache['id'] = $parentId . '_' . $this->getName();
146                 }
147             }
148         }
149
150         return $this->cache['id'];
151     }
152
153     /**
154      * Returns this node's name.
155      *
156      * @param  boolean $includeParent
157      * @return string
158      */
159     public function getName($includeParent = FALSE, $includeCommonPath = FALSE)
160     {
161         if ($includeParent && $this->parent !== NULL) {
162             if (!isset($this->cache['nameIncludingParent'])) {
163                 $parent = $this->parent->getName(TRUE);
164
165                 if (!empty($parent)) {
166                     $this->cache['nameIncludingParent'] = $parent . '/' .
167                                                           $this->name;
168                 } else {
169                     $this->cache['nameIncludingParent'] = $this->name;
170                 }
171             }
172
173             return $this->cache['nameIncludingParent'];
174         } else {
175             if ($this->parent !== NULL) {
176                 return $this->name;
177             } else {
178                 return $includeCommonPath ? $this->name : '';
179             }
180         }
181     }
182
183     /**
184      * Returns the link to this node.
185      *
186      * @param  boolean $full
187      * @return string
188      */
189     public function getLink($full)
190     {
191         if (substr($this->name, -1) == DIRECTORY_SEPARATOR) {
192             $name = substr($this->name, 0, -1);
193         } else {
194             $name = $this->name;
195         }
196
197         $cleanId = PHP_CodeCoverage_Util::getSafeFilename($this->getId());
198
199         if ($full) {
200             if ($this->parent !== NULL) {
201                 $parent = $this->parent->getLink(TRUE) . DIRECTORY_SEPARATOR;
202             } else {
203                 $parent = '';
204             }
205
206             return sprintf(
207               '%s<a href="%s.html">%s</a>',
208               $parent,
209               $cleanId,
210               $name
211             );
212         } else {
213             return sprintf(
214               '<a href="%s.html">%s</a>',
215               $cleanId,
216               $name
217             );
218         }
219     }
220
221     /**
222      * Returns this node's path.
223      *
224      * @return string
225      */
226     public function getPath()
227     {
228         if (!isset($this->cache['path'])) {
229             if ($this->parent === NULL) {
230                 $this->cache['path'] = $this->getName(FALSE, TRUE);
231             } else {
232                 $parentPath = $this->parent->getPath();
233
234                 if (substr($parentPath, -1) == DIRECTORY_SEPARATOR) {
235                     $this->cache['path'] = $parentPath .
236                                            $this->getName(FALSE, TRUE);
237                 } else {
238                     $this->cache['path'] = $parentPath .
239                                            DIRECTORY_SEPARATOR .
240                                            $this->getName(FALSE, TRUE);
241
242                     if ($parentPath === '' &&
243                         realpath($this->cache['path']) === FALSE &&
244                         realpath($this->getName(FALSE, TRUE)) !== FALSE) {
245                         $this->cache['path'] = $this->getName(FALSE, TRUE);
246                     }
247                 }
248             }
249         }
250
251         return $this->cache['path'];
252     }
253
254     protected function doRenderItemObject(PHP_CodeCoverage_Report_HTML_Node $item, $lowUpperBound, $highLowerBound, $link = NULL, $itemClass = 'coverItem')
255     {
256         return $this->doRenderItem(
257           array(
258             'name'                 => $link != NULL ? $link : $item->getLink(
259                                                                 FALSE
260                                                               ),
261             'itemClass'            => $itemClass,
262             'numClasses'           => $item->getNumClasses(),
263             'numTestedClasses'     => $item->getNumTestedClasses(),
264             'testedClassesPercent' => $item->getTestedClassesPercent(),
265             'numMethods'           => $item->getNumMethods(),
266             'numTestedMethods'     => $item->getNumTestedMethods(),
267             'testedMethodsPercent' => $item->getTestedMethodsPercent(),
268             'numExecutableLines'   => $item->getNumExecutableLines(),
269             'numExecutedLines'     => $item->getNumExecutedLines(),
270             'executedLinesPercent' => $item->getLineExecutedPercent(),
271             'crap'                 => $link == 'Total' ? '<acronym title="Change Risk Anti-Patterns (CRAP) Index">CRAP</acronym>' : ''
272           ),
273           $lowUpperBound,
274           $highLowerBound
275         );
276     }
277
278     protected function doRenderItem(array $data, $lowUpperBound, $highLowerBound, $template = NULL)
279     {
280         if ($template === NULL) {
281             if ($this instanceof PHP_CodeCoverage_Report_HTML_Node_Directory) {
282                 $template = 'directory_item.html';
283             } else {
284                 $template = 'file_item.html';
285             }
286         }
287
288         $itemTemplate = new Text_Template(
289           PHP_CodeCoverage_Report_HTML::$templatePath . $template
290         );
291
292         if ($data['numClasses'] > 0) {
293             list($classesColor, $classesLevel) = $this->getColorLevel(
294               $data['testedClassesPercent'], $lowUpperBound, $highLowerBound
295             );
296
297             $classesNumber = $data['numTestedClasses'] . ' / ' .
298                              $data['numClasses'];
299         } else {
300             $classesColor  = 'snow';
301             $classesLevel  = 'None';
302             $classesNumber = '&nbsp;';
303         }
304
305         if ($data['numMethods'] > 0) {
306             list($methodsColor, $methodsLevel) = $this->getColorLevel(
307               $data['testedMethodsPercent'], $lowUpperBound, $highLowerBound
308             );
309
310             $methodsNumber = $data['numTestedMethods'] . ' / ' .
311                              $data['numMethods'];
312         } else {
313             $methodsColor  = 'snow';
314             $methodsLevel  = 'None';
315             $methodsNumber = '&nbsp;';
316         }
317
318         list($linesColor, $linesLevel) = $this->getColorLevel(
319           $data['executedLinesPercent'], $lowUpperBound, $highLowerBound
320         );
321
322         if ($data['name'] == '<b><a href="#0">*</a></b>') {
323             $functions = TRUE;
324         } else {
325             $functions = FALSE;
326         }
327
328         $icon = '';
329
330         if (isset($data['itemClass'])) {
331             if ($data['itemClass'] == 'coverDirectory') {
332                 $icon = '<img alt="directory" src="directory.png"/> ';
333             }
334
335             else if ($data['itemClass'] == 'coverFile') {
336                 $icon = '<img alt="file" src="file.png"/> ';
337             }
338         }
339
340         $itemTemplate->setVar(
341           array(
342             'name'                     => $functions ? 'Functions' : $data['name'],
343             'icon'                     => $icon,
344             'itemClass'                => isset($data['itemClass']) ? $data['itemClass'] : 'coverItem',
345             'classes_color'            => $classesColor,
346             'classes_level'            => $functions ? 'None' : $classesLevel,
347             'classes_tested_width'     => floor($data['testedClassesPercent']),
348             'classes_tested_percent'   => !$functions && $data['numClasses'] > 0 ? $data['testedClassesPercent'] . '%' : '&nbsp;',
349             'classes_not_tested_width' => 100 - floor($data['testedClassesPercent']),
350             'classes_number'           => $functions ? '&nbsp;' : $classesNumber,
351             'methods_color'            => $methodsColor,
352             'methods_level'            => $methodsLevel,
353             'methods_tested_width'     => floor($data['testedMethodsPercent']),
354             'methods_tested_percent'   => $data['numMethods'] > 0 ? $data['testedMethodsPercent'] . '%' : '&nbsp;',
355             'methods_not_tested_width' => 100 - floor($data['testedMethodsPercent']),
356             'methods_number'           => $methodsNumber,
357             'lines_color'              => $linesColor,
358             'lines_level'              => $linesLevel,
359             'lines_executed_width'     => floor($data['executedLinesPercent']),
360             'lines_executed_percent'   => $data['executedLinesPercent'] . '%',
361             'lines_not_executed_width' => 100 - floor($data['executedLinesPercent']),
362             'num_executable_lines'     => $data['numExecutableLines'],
363             'num_executed_lines'       => $data['numExecutedLines'],
364             'crap'                     => isset($data['crap']) ? $data['crap'] : ''
365           )
366         );
367
368         return $itemTemplate->render();
369     }
370
371     protected function getColorLevel($percent, $lowUpperBound, $highLowerBound)
372     {
373         $floorPercent = floor($percent);
374
375         if ($floorPercent < $lowUpperBound) {
376             $color = 'scarlet_red';
377             $level = 'Lo';
378         }
379
380         else if ($floorPercent >= $lowUpperBound &&
381                  $floorPercent <  $highLowerBound) {
382             $color = 'butter';
383             $level = 'Med';
384         }
385
386         else {
387             $color = 'chameleon';
388             $level = 'Hi';
389         }
390
391         return array($color, $level);
392     }
393
394     protected function renderTotalItem($lowUpperBound, $highLowerBound, $directory = TRUE)
395     {
396         if ($directory &&
397             empty($this->directories) &&
398             count($this->files) == 1) {
399             return '';
400         }
401
402         return $this->doRenderItemObject(
403                  $this, $lowUpperBound, $highLowerBound, 'Total'
404                ) .
405                "        <tr>\n" .
406                '          <td class="tableHead" colspan="11">&nbsp;</td>' .
407                "\n        </tr>\n";
408     }
409
410     /**
411      * @param Text_Template $template
412      * @param string        $title
413      * @param string        $charset
414      * @param string        $generator
415      */
416     protected function setTemplateVars(Text_Template $template, $title, $charset, $generator)
417     {
418         $dashboard = '';
419
420         if ($this instanceof PHP_CodeCoverage_Report_HTML_Node_Directory) {
421             $dashboard = sprintf(
422               '<a href="%s">dashboard</a>',
423               PHP_CodeCoverage_Util::getSafeFilename(
424                 $this->getId()
425               ) . '.dashboard.html'
426             );
427         }
428
429         $template->setVar(
430           array(
431             'title'                  => $title,
432             'charset'                => $charset,
433             'link'                   => $this->getLink(TRUE),
434             'dashboard_link'         => $dashboard,
435             'num_executable_lines'   => $this->getNumExecutableLines(),
436             'num_executed_lines'     => $this->getNumExecutedLines(),
437             'lines_executed_percent' => $this->getLineExecutedPercent(),
438             'date'                   => date(
439                                           'D M j G:i:s T Y',
440                                           $_SERVER['REQUEST_TIME']
441                                         ),
442             'version'                => '1.0.4',
443             'php_version'            => PHP_VERSION,
444             'generator'              => $generator
445           )
446         );
447     }
448
449     /**
450      * Returns the classes of this node.
451      *
452      * @return array
453      */
454     abstract public function getClasses();
455
456     /**
457      * Returns the number of executable lines.
458      *
459      * @return integer
460      */
461     abstract public function getNumExecutableLines();
462
463     /**
464      * Returns the number of executed lines.
465      *
466      * @return integer
467      */
468     abstract public function getNumExecutedLines();
469
470     /**
471      * Returns the number of classes.
472      *
473      * @return integer
474      */
475     abstract public function getNumClasses();
476
477     /**
478      * Returns the number of tested classes.
479      *
480      * @return integer
481      */
482     abstract public function getNumTestedClasses();
483
484     /**
485      * Returns the number of methods.
486      *
487      * @return integer
488      */
489     abstract public function getNumMethods();
490
491     /**
492      * Returns the number of tested methods.
493      *
494      * @return integer
495      */
496     abstract public function getNumTestedMethods();
497
498     /**
499      * Renders this node.
500      *
501      * @param string  $target
502      * @param string  $title
503      * @param string  $charset
504      * @param integer $lowUpperBound
505      * @param integer $highLowerBound
506      * @param string  $generator
507      */
508     abstract public function render($target, $title, $charset = 'UTF-8', $lowUpperBound = 35, $highLowerBound = 70, $generator = '');
509 }
510
511 require_once 'PHP/CodeCoverage/Report/HTML/Node/Directory.php';
512 require_once 'PHP/CodeCoverage/Report/HTML/Node/File.php';