painter = $painter;
$this->base_dir = $base_dir;
}
function paintHeader($test_name, $charset="UTF-8")
{
$this->sendNoCacheHeaders();
header('Content-Type: text/html; Charset='.$charset);
print "\n
\n$test_name\n";
print "";
print "\n";
print "\n\n";
print "$test_name
\n";
flush();
if (extension_loaded('xdebug'))
xdebug_start_code_coverage(XDEBUG_CC_UNUSED);
}
/**
*
*/
function _getCss()
{
$contents = parent::_getCss()."\n ";
$contents .= '
.bar { float: left; display: inline; border: 1px solid #eee; width: 300px; white-space: nowrap;}
.percentage { float: left; background-color: #eef; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 0.65em; padding: 5px; margin-right: }
.coverage {margin: 0.4em; }
.coverage a {
padding-left: 0.5em;
}
.coverage:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.coverage {display: inline-block;}
/* Hides from IE-mac \*/
* html .coverage {height: 1%;}
.coverage {display: block;}
/* End hide from IE-mac */
';
Return $contents;
}
function paintFooter($test_name)
{
if (extension_loaded('xdebug'))
{
$this->coverage = xdebug_get_code_coverage();
xdebug_stop_code_coverage();
}
$colour = ($this->getFailCount() + $this->getExceptionCount() > 0 ? "red" : "green");
print "";
print $this->getTestCaseProgress() . "/" . $this->getTestCaseCount();
print " test cases complete:\n";
print "" . $this->getPassCount() . " passes, ";
print "" . $this->getFailCount() . " fails and ";
print "" . $this->getExceptionCount() . " exceptions.";
print "
\n";
$this->paintCoverage();
print "\n\n";
}
function paintCoverage()
{
$dir = dirname(__FILE__);
if(count($this->coverage) > 0)
print 'Code Coverage
';
ksort($this->coverage);
$details = array();
foreach($this->coverage as $file => $coverage)
{
if(is_int(strpos($file, $dir)) == false
&& is_int(strpos($file, 'simpletest')) == false
&& is_int(strpos($file, $this->base_dir)))
{
$total = HTMLCoverageReport::codelines($file);
$executed = count($coverage);
$percentage = sprintf('%01d',$executed/$total*100);
$width = $percentage * 3;
$filename = str_replace($this->base_dir, '',$file);
$link = $this->constructURL($filename, $coverage);
$detail['total'] = $total;
$detail['executed'] = $executed;
$detail['width'] = $width;
$detail['filename'] = $filename;
$detail['link'] = $link;
$details[$percentage][] = $detail;
}
}
krsort($details);
foreach($details as $percentage => $files)
{
foreach($files as $detail)
{
$total = $detail['total'];
$executed = $detail['executed'];
$width = $detail['width'];
$filename = $detail['filename'];
$link = $detail['link'];
print "";
print "
";
print "";
print "$executed/$total\n";
print "$percentage%\n";
print "
{$filename}\n";
print "
\n";
}
}
}
function constructURL($file, $coverage)
{
$file = rawurlencode($file);
$lines = implode(',', array_keys($coverage));
return $this->painter.'?file='.$file.'&lines='.$lines;
}
}
class HTMLCoverageReport extends HtmlReporter
{
protected $file;
protected $lines;
protected $name;
function __construct($file, $name, $lines)
{
$this->file = $file;
$this->lines = $lines;
$this->name = $name;
}
function show()
{
$this->paintHeader($this->name);
$contents = file($this->file);
foreach($contents as $count => $line)
{
$num = ($count+1);
$line = preg_replace("/\\n|\\r/",'',$line);
$line = htmlspecialchars($line);
$line = str_replace(' ',' ',$line);
$line = str_replace("\t",' ',$line);
if(in_array($count+1, $this->lines))
echo "$num $line
\n";
else
echo "$num $line
\n";
}
$this->paintFooter();
}
function paintHeader($file, $charset="UTF-8")
{
$total = $this->codelines($this->file);
$executed = count($this->lines);
$percentage = sprintf('%01.2f',$executed/$total*100);
$this->sendNoCacheHeaders();
header('Content-Type: text/html Charset='.$charset);
print "\n\nCode Coverage: $file\n";
print "";
print "\n";
print "\n\n";
print "Code Coverage
\n";
print "$file
";
print " Total code lines: {$total}
Total lines executed: {$executed} ({$percentage}%)
";
flush();
}
function paintFooter($test_name)
{
print "\n\n";
}
static function codelines($file)
{
$source = file_get_contents($file);
$tokens = @token_get_all($source);
$lines = '';
foreach ($tokens as $token)
{
if (is_string($token))
{
// simple 1-character token
$lines .= $token;
}
else
{
// token array
list($id, $text) = $token;
switch ($id)
{
case T_COMMENT:
case T_ML_COMMENT: // we've defined this
case T_DOC_COMMENT: // and this
// no action on comments
break;
default:
// anything else -> output "as is"
//echo $text;
$lines .= $text;
break;
}
}
}
$lines = preg_replace('/\\n\s*$/m',"",$lines);
$codelines = explode("\n",$lines);
$count = 0;
$patterns[] = '^\s*{\s*$';
$patterns[] = '<\?';
$patterns[] = '^\s*(private|protected|public)\s+\$';
$pattern = '/'.implode('|', $patterns).'/';
foreach($codelines as $line)
{
if(!preg_match($pattern, $line))
$count++;
}
return $count;
//var_dump($codelines);
//return count($codelines);
}
}