Laravel version update

Laravel version update
This commit is contained in:
Manish Verma
2018-08-06 18:48:58 +05:30
parent d143048413
commit 126fbb0255
13678 changed files with 1031482 additions and 778530 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,97 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Driver for Xdebug's code coverage functionality.
*
* @since Class available since Release 1.0.0
* @codeCoverageIgnore
*/
class PHP_CodeCoverage_Driver_Xdebug implements PHP_CodeCoverage_Driver
{
/**
* Constructor.
*/
public function __construct()
{
if (!extension_loaded('xdebug')) {
throw new PHP_CodeCoverage_Exception('This driver requires Xdebug');
}
if (version_compare(phpversion('xdebug'), '2.2.0-dev', '>=') &&
!ini_get('xdebug.coverage_enable')) {
throw new PHP_CodeCoverage_Exception(
'xdebug.coverage_enable=On has to be set in php.ini'
);
}
}
/**
* Start collection of code coverage information.
*/
public function start()
{
xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
}
/**
* Stop collection of code coverage information.
*
* @return array
*/
public function stop()
{
$data = xdebug_get_code_coverage();
xdebug_stop_code_coverage();
return $this->cleanup($data);
}
/**
* @param array $data
* @return array
* @since Method available since Release 2.0.0
*/
private function cleanup(array $data)
{
foreach (array_keys($data) as $file) {
unset($data[$file][0]);
if ($file != 'xdebug://debug-eval' && file_exists($file)) {
$numLines = $this->getNumberOfLinesInFile($file);
foreach (array_keys($data[$file]) as $line) {
if (isset($data[$file][$line]) && $line > $numLines) {
unset($data[$file][$line]);
}
}
}
}
return $data;
}
/**
* @param string $file
* @return int
* @since Method available since Release 2.0.0
*/
private function getNumberOfLinesInFile($file)
{
$buffer = file_get_contents($file);
$lines = substr_count($buffer, "\n");
if (substr($buffer, -1) !== "\n") {
$lines++;
}
return $lines;
}
}

View File

@@ -1,18 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Exception class for PHP_CodeCoverage component.
*
* @since Class available since Release 1.1.0
*/
class PHP_CodeCoverage_Exception extends RuntimeException
{
}

View File

@@ -1,18 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Exception that is raised when code is unintentionally covered.
*
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Exception_UnintentionallyCoveredCode extends PHP_CodeCoverage_Exception
{
}

View File

@@ -1,293 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Filter for blacklisting and whitelisting of code coverage information.
*
* @since Class available since Release 1.0.0
*/
class PHP_CodeCoverage_Filter
{
/**
* Source files that are blacklisted.
*
* @var array
*/
private $blacklistedFiles = array();
/**
* Source files that are whitelisted.
*
* @var array
*/
private $whitelistedFiles = array();
/**
* Adds a directory to the blacklist (recursively).
*
* @param string $directory
* @param string $suffix
* @param string $prefix
*/
public function addDirectoryToBlacklist($directory, $suffix = '.php', $prefix = '')
{
$facade = new File_Iterator_Facade;
$files = $facade->getFilesAsArray($directory, $suffix, $prefix);
foreach ($files as $file) {
$this->addFileToBlacklist($file);
}
}
/**
* Adds a file to the blacklist.
*
* @param string $filename
*/
public function addFileToBlacklist($filename)
{
$this->blacklistedFiles[realpath($filename)] = true;
}
/**
* Adds files to the blacklist.
*
* @param array $files
*/
public function addFilesToBlacklist(array $files)
{
foreach ($files as $file) {
$this->addFileToBlacklist($file);
}
}
/**
* Removes a directory from the blacklist (recursively).
*
* @param string $directory
* @param string $suffix
* @param string $prefix
*/
public function removeDirectoryFromBlacklist($directory, $suffix = '.php', $prefix = '')
{
$facade = new File_Iterator_Facade;
$files = $facade->getFilesAsArray($directory, $suffix, $prefix);
foreach ($files as $file) {
$this->removeFileFromBlacklist($file);
}
}
/**
* Removes a file from the blacklist.
*
* @param string $filename
*/
public function removeFileFromBlacklist($filename)
{
$filename = realpath($filename);
if (isset($this->blacklistedFiles[$filename])) {
unset($this->blacklistedFiles[$filename]);
}
}
/**
* Adds a directory to the whitelist (recursively).
*
* @param string $directory
* @param string $suffix
* @param string $prefix
*/
public function addDirectoryToWhitelist($directory, $suffix = '.php', $prefix = '')
{
$facade = new File_Iterator_Facade;
$files = $facade->getFilesAsArray($directory, $suffix, $prefix);
foreach ($files as $file) {
$this->addFileToWhitelist($file);
}
}
/**
* Adds a file to the whitelist.
*
* @param string $filename
*/
public function addFileToWhitelist($filename)
{
$this->whitelistedFiles[realpath($filename)] = true;
}
/**
* Adds files to the whitelist.
*
* @param array $files
*/
public function addFilesToWhitelist(array $files)
{
foreach ($files as $file) {
$this->addFileToWhitelist($file);
}
}
/**
* Removes a directory from the whitelist (recursively).
*
* @param string $directory
* @param string $suffix
* @param string $prefix
*/
public function removeDirectoryFromWhitelist($directory, $suffix = '.php', $prefix = '')
{
$facade = new File_Iterator_Facade;
$files = $facade->getFilesAsArray($directory, $suffix, $prefix);
foreach ($files as $file) {
$this->removeFileFromWhitelist($file);
}
}
/**
* Removes a file from the whitelist.
*
* @param string $filename
*/
public function removeFileFromWhitelist($filename)
{
$filename = realpath($filename);
if (isset($this->whitelistedFiles[$filename])) {
unset($this->whitelistedFiles[$filename]);
}
}
/**
* Checks whether a filename is a real filename.
*
* @param string $filename
* @return bool
*/
public function isFile($filename)
{
if ($filename == '-' ||
strpos($filename, 'vfs://') === 0 ||
strpos($filename, 'xdebug://debug-eval') !== false ||
strpos($filename, 'eval()\'d code') !== false ||
strpos($filename, 'runtime-created function') !== false ||
strpos($filename, 'runkit created function') !== false ||
strpos($filename, 'assert code') !== false ||
strpos($filename, 'regexp code') !== false) {
return false;
}
return file_exists($filename);
}
/**
* Checks whether or not a file is filtered.
*
* When the whitelist is empty (default), blacklisting is used.
* When the whitelist is not empty, whitelisting is used.
*
* @param string $filename
* @return bool
* @throws PHP_CodeCoverage_Exception
*/
public function isFiltered($filename)
{
if (!$this->isFile($filename)) {
return true;
}
$filename = realpath($filename);
if (!empty($this->whitelistedFiles)) {
return !isset($this->whitelistedFiles[$filename]);
}
return isset($this->blacklistedFiles[$filename]);
}
/**
* Returns the list of blacklisted files.
*
* @return array
*/
public function getBlacklist()
{
return array_keys($this->blacklistedFiles);
}
/**
* Returns the list of whitelisted files.
*
* @return array
*/
public function getWhitelist()
{
return array_keys($this->whitelistedFiles);
}
/**
* Returns whether this filter has a whitelist.
*
* @return bool
* @since Method available since Release 1.1.0
*/
public function hasWhitelist()
{
return !empty($this->whitelistedFiles);
}
/**
* Returns the blacklisted files.
*
* @return array
* @since Method available since Release 2.0.0
*/
public function getBlacklistedFiles()
{
return $this->blacklistedFiles;
}
/**
* Sets the blacklisted files.
*
* @param array $blacklistedFiles
* @since Method available since Release 2.0.0
*/
public function setBlacklistedFiles($blacklistedFiles)
{
$this->blacklistedFiles = $blacklistedFiles;
}
/**
* Returns the whitelisted files.
*
* @return array
* @since Method available since Release 2.0.0
*/
public function getWhitelistedFiles()
{
return $this->whitelistedFiles;
}
/**
* Sets the whitelisted files.
*
* @param array $whitelistedFiles
* @since Method available since Release 2.0.0
*/
public function setWhitelistedFiles($whitelistedFiles)
{
$this->whitelistedFiles = $whitelistedFiles;
}
}

View File

@@ -1,182 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Generates an HTML report from an PHP_CodeCoverage object.
*
* @since Class available since Release 1.0.0
*/
class PHP_CodeCoverage_Report_HTML
{
/**
* @var string
*/
private $templatePath;
/**
* @var string
*/
private $generator;
/**
* @var int
*/
private $lowUpperBound;
/**
* @var int
*/
private $highLowerBound;
/**
* Constructor.
*
* @param int $lowUpperBound
* @param int $highLowerBound
* @param string $generator
*/
public function __construct($lowUpperBound = 50, $highLowerBound = 90, $generator = '')
{
$this->generator = $generator;
$this->highLowerBound = $highLowerBound;
$this->lowUpperBound = $lowUpperBound;
$this->templatePath = sprintf(
'%s%sHTML%sRenderer%sTemplate%s',
dirname(__FILE__),
DIRECTORY_SEPARATOR,
DIRECTORY_SEPARATOR,
DIRECTORY_SEPARATOR,
DIRECTORY_SEPARATOR
);
}
/**
* @param PHP_CodeCoverage $coverage
* @param string $target
*/
public function process(PHP_CodeCoverage $coverage, $target)
{
$target = $this->getDirectory($target);
$report = $coverage->getReport();
unset($coverage);
if (!isset($_SERVER['REQUEST_TIME'])) {
$_SERVER['REQUEST_TIME'] = time();
}
$date = date('D M j G:i:s T Y', $_SERVER['REQUEST_TIME']);
$dashboard = new PHP_CodeCoverage_Report_HTML_Renderer_Dashboard(
$this->templatePath,
$this->generator,
$date,
$this->lowUpperBound,
$this->highLowerBound
);
$directory = new PHP_CodeCoverage_Report_HTML_Renderer_Directory(
$this->templatePath,
$this->generator,
$date,
$this->lowUpperBound,
$this->highLowerBound
);
$file = new PHP_CodeCoverage_Report_HTML_Renderer_File(
$this->templatePath,
$this->generator,
$date,
$this->lowUpperBound,
$this->highLowerBound
);
$directory->render($report, $target . 'index.html');
$dashboard->render($report, $target . 'dashboard.html');
foreach ($report as $node) {
$id = $node->getId();
if ($node instanceof PHP_CodeCoverage_Report_Node_Directory) {
if (!file_exists($target . $id)) {
mkdir($target . $id, 0777, true);
}
$directory->render($node, $target . $id . '/index.html');
$dashboard->render($node, $target . $id . '/dashboard.html');
} else {
$dir = dirname($target . $id);
if (!file_exists($dir)) {
mkdir($dir, 0777, true);
}
$file->render($node, $target . $id . '.html');
}
}
$this->copyFiles($target);
}
/**
* @param string $target
*/
private function copyFiles($target)
{
$dir = $this->getDirectory($target . 'css');
copy($this->templatePath . 'css/bootstrap.min.css', $dir . 'bootstrap.min.css');
copy($this->templatePath . 'css/nv.d3.min.css', $dir . 'nv.d3.min.css');
copy($this->templatePath . 'css/style.css', $dir . 'style.css');
$dir = $this->getDirectory($target . 'fonts');
copy($this->templatePath . 'fonts/glyphicons-halflings-regular.eot', $dir . 'glyphicons-halflings-regular.eot');
copy($this->templatePath . 'fonts/glyphicons-halflings-regular.svg', $dir . 'glyphicons-halflings-regular.svg');
copy($this->templatePath . 'fonts/glyphicons-halflings-regular.ttf', $dir . 'glyphicons-halflings-regular.ttf');
copy($this->templatePath . 'fonts/glyphicons-halflings-regular.woff', $dir . 'glyphicons-halflings-regular.woff');
copy($this->templatePath . 'fonts/glyphicons-halflings-regular.woff2', $dir . 'glyphicons-halflings-regular.woff2');
$dir = $this->getDirectory($target . 'js');
copy($this->templatePath . 'js/bootstrap.min.js', $dir . 'bootstrap.min.js');
copy($this->templatePath . 'js/d3.min.js', $dir . 'd3.min.js');
copy($this->templatePath . 'js/holder.min.js', $dir . 'holder.min.js');
copy($this->templatePath . 'js/html5shiv.min.js', $dir . 'html5shiv.min.js');
copy($this->templatePath . 'js/jquery.min.js', $dir . 'jquery.min.js');
copy($this->templatePath . 'js/nv.d3.min.js', $dir . 'nv.d3.min.js');
copy($this->templatePath . 'js/respond.min.js', $dir . 'respond.min.js');
}
/**
* @param string $directory
* @return string
* @throws PHP_CodeCoverage_Exception
* @since Method available since Release 1.2.0
*/
private function getDirectory($directory)
{
if (substr($directory, -1, 1) != DIRECTORY_SEPARATOR) {
$directory .= DIRECTORY_SEPARATOR;
}
if (is_dir($directory)) {
return $directory;
}
if (@mkdir($directory, 0777, true)) {
return $directory;
}
throw new PHP_CodeCoverage_Exception(
sprintf(
'Directory "%s" does not exist.',
$directory
)
);
}
}

View File

@@ -1,97 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Renders a PHP_CodeCoverage_Report_Node_Directory node.
*
* @since Class available since Release 1.1.0
*/
class PHP_CodeCoverage_Report_HTML_Renderer_Directory extends PHP_CodeCoverage_Report_HTML_Renderer
{
/**
* @param PHP_CodeCoverage_Report_Node_Directory $node
* @param string $file
*/
public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file)
{
$template = new Text_Template($this->templatePath . 'directory.html', '{{', '}}');
$this->setCommonTemplateVariables($template, $node);
$items = $this->renderItem($node, true);
foreach ($node->getDirectories() as $item) {
$items .= $this->renderItem($item);
}
foreach ($node->getFiles() as $item) {
$items .= $this->renderItem($item);
}
$template->setVar(
array(
'id' => $node->getId(),
'items' => $items
)
);
$template->renderTo($file);
}
/**
* @param PHP_CodeCoverage_Report_Node $item
* @param bool $total
* @return string
*/
protected function renderItem(PHP_CodeCoverage_Report_Node $item, $total = false)
{
$data = array(
'numClasses' => $item->getNumClassesAndTraits(),
'numTestedClasses' => $item->getNumTestedClassesAndTraits(),
'numMethods' => $item->getNumMethods(),
'numTestedMethods' => $item->getNumTestedMethods(),
'linesExecutedPercent' => $item->getLineExecutedPercent(false),
'linesExecutedPercentAsString' => $item->getLineExecutedPercent(),
'numExecutedLines' => $item->getNumExecutedLines(),
'numExecutableLines' => $item->getNumExecutableLines(),
'testedMethodsPercent' => $item->getTestedMethodsPercent(false),
'testedMethodsPercentAsString' => $item->getTestedMethodsPercent(),
'testedClassesPercent' => $item->getTestedClassesAndTraitsPercent(false),
'testedClassesPercentAsString' => $item->getTestedClassesAndTraitsPercent()
);
if ($total) {
$data['name'] = 'Total';
} else {
if ($item instanceof PHP_CodeCoverage_Report_Node_Directory) {
$data['name'] = sprintf(
'<a href="%s/index.html">%s</a>',
$item->getName(),
$item->getName()
);
$data['icon'] = '<span class="glyphicon glyphicon-folder-open"></span> ';
} else {
$data['name'] = sprintf(
'<a href="%s.html">%s</a>',
$item->getName(),
$item->getName()
);
$data['icon'] = '<span class="glyphicon glyphicon-file"></span> ';
}
}
return $this->renderItemTemplate(
new Text_Template($this->templatePath . 'directory_item.html', '{{', '}}'),
$data
);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +0,0 @@
/**
* @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document);

File diff suppressed because one or more lines are too long

View File

@@ -1,50 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Uses var_export() to write a PHP_CodeCoverage object to a file.
*
* @since Class available since Release 1.1.0
*/
class PHP_CodeCoverage_Report_PHP
{
/**
* @param PHP_CodeCoverage $coverage
* @param string $target
* @return string
*/
public function process(PHP_CodeCoverage $coverage, $target = null)
{
$filter = $coverage->filter();
$output = sprintf(
'<?php
$coverage = new PHP_CodeCoverage;
$coverage->setData(%s);
$coverage->setTests(%s);
$filter = $coverage->filter();
$filter->setBlacklistedFiles(%s);
$filter->setWhitelistedFiles(%s);
return $coverage;',
var_export($coverage->getData(true), 1),
var_export($coverage->getTests(), 1),
var_export($filter->getBlacklistedFiles(), 1),
var_export($filter->getWhitelistedFiles(), 1)
);
if ($target !== null) {
return file_put_contents($target, $output);
} else {
return $output;
}
}
}

View File

@@ -1,72 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML_File_Report extends PHP_CodeCoverage_Report_XML_File
{
public function __construct($name)
{
$this->dom = new DOMDocument;
$this->dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="http://schema.phpunit.de/coverage/1.0"><file /></phpunit>');
$this->contextNode = $this->dom->getElementsByTagNameNS(
'http://schema.phpunit.de/coverage/1.0',
'file'
)->item(0);
$this->setName($name);
}
private function setName($name)
{
$this->contextNode->setAttribute('name', $name);
}
public function asDom()
{
return $this->dom;
}
public function getFunctionObject($name)
{
$node = $this->contextNode->appendChild(
$this->dom->createElementNS(
'http://schema.phpunit.de/coverage/1.0',
'function'
)
);
return new PHP_CodeCoverage_Report_XML_File_Method($node, $name);
}
public function getClassObject($name)
{
return $this->getUnitObject('class', $name);
}
public function getTraitObject($name)
{
return $this->getUnitObject('trait', $name);
}
private function getUnitObject($tagName, $name)
{
$node = $this->contextNode->appendChild(
$this->dom->createElementNS(
'http://schema.phpunit.de/coverage/1.0',
$tagName
)
);
return new PHP_CodeCoverage_Report_XML_File_Unit($node, $name);
}
}

View File

@@ -1,63 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML_Project extends PHP_CodeCoverage_Report_XML_Node
{
public function __construct($name)
{
$this->init();
$this->setProjectName($name);
}
private function init()
{
$dom = new DOMDocument;
$dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="http://schema.phpunit.de/coverage/1.0"><project/></phpunit>');
$this->setContextNode(
$dom->getElementsByTagNameNS(
'http://schema.phpunit.de/coverage/1.0',
'project'
)->item(0)
);
}
private function setProjectName($name)
{
$this->getContextNode()->setAttribute('name', $name);
}
public function getTests()
{
$testsNode = $this->getContextNode()->getElementsByTagNameNS(
'http://schema.phpunit.de/coverage/1.0',
'tests'
)->item(0);
if (!$testsNode) {
$testsNode = $this->getContextNode()->appendChild(
$this->getDom()->createElementNS(
'http://schema.phpunit.de/coverage/1.0',
'tests'
)
);
}
return new PHP_CodeCoverage_Report_XML_Tests($testsNode);
}
public function asDom()
{
return $this->getDom();
}
}

View File

@@ -1,39 +0,0 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Factory for PHP_CodeCoverage_Exception objects that are used to describe
* invalid arguments passed to a function or method.
*
* @since Class available since Release 1.2.0
*/
class PHP_CodeCoverage_Util_InvalidArgumentHelper
{
/**
* @param int $argument
* @param string $type
* @param mixed $value
*/
public static function factory($argument, $type, $value = null)
{
$stack = debug_backtrace(false);
return new PHP_CodeCoverage_Exception(
sprintf(
'Argument #%d%sof %s::%s() must be a %s',
$argument,
$value !== null ? ' (' . gettype($value) . '#' . $value . ')' : ' (No Value) ',
$stack[1]['class'],
$stack[1]['function'],
$type
)
);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,35 +8,40 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Driver;
/**
* Interface for code coverage drivers.
*
* @since Class available since Release 1.0.0
*/
interface PHP_CodeCoverage_Driver
interface Driver
{
/**
* @var int
*
* @see http://xdebug.org/docs/code_coverage
*/
const LINE_EXECUTED = 1;
/**
* @var int
*
* @see http://xdebug.org/docs/code_coverage
*/
const LINE_NOT_EXECUTED = -1;
/**
* @var int
*
* @see http://xdebug.org/docs/code_coverage
*/
const LINE_NOT_EXECUTABLE = -2;
/**
* Start collection of code coverage information.
*
* @param bool $determineUnusedAndDead
*/
public function start();
public function start($determineUnusedAndDead = true);
/**
* Stop collection of code coverage information.

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,19 +8,22 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Driver;
/**
* Driver for HHVM's code coverage functionality.
*
* @since Class available since Release 2.2.2
* @codeCoverageIgnore
*/
class PHP_CodeCoverage_Driver_HHVM extends PHP_CodeCoverage_Driver_Xdebug
class HHVM extends Xdebug
{
/**
* Start collection of code coverage information.
*
* @param bool $determineUnusedAndDead
*/
public function start()
public function start($determineUnusedAndDead = true)
{
xdebug_start_code_coverage();
\xdebug_start_code_coverage();
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,13 +8,16 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Driver;
use SebastianBergmann\CodeCoverage\RuntimeException;
/**
* Driver for PHPDBG's code coverage functionality.
*
* @since Class available since Release 2.2.0
* @codeCoverageIgnore
*/
class PHP_CodeCoverage_Driver_PHPDBG implements PHP_CodeCoverage_Driver
class PHPDBG implements Driver
{
/**
* Constructor.
@@ -22,13 +25,13 @@ class PHP_CodeCoverage_Driver_PHPDBG implements PHP_CodeCoverage_Driver
public function __construct()
{
if (PHP_SAPI !== 'phpdbg') {
throw new PHP_CodeCoverage_Exception(
throw new RuntimeException(
'This driver requires the PHPDBG SAPI'
);
}
if (!function_exists('phpdbg_start_oplog')) {
throw new PHP_CodeCoverage_Exception(
if (!\function_exists('phpdbg_start_oplog')) {
throw new RuntimeException(
'This build of PHPDBG does not support code coverage'
);
}
@@ -36,8 +39,10 @@ class PHP_CodeCoverage_Driver_PHPDBG implements PHP_CodeCoverage_Driver
/**
* Start collection of code coverage information.
*
* @param bool $determineUnusedAndDead
*/
public function start()
public function start($determineUnusedAndDead = true)
{
phpdbg_start_oplog();
}
@@ -49,24 +54,24 @@ class PHP_CodeCoverage_Driver_PHPDBG implements PHP_CodeCoverage_Driver
*/
public function stop()
{
static $fetchedLines = array();
static $fetchedLines = [];
$dbgData = phpdbg_end_oplog();
if ($fetchedLines == array()) {
if ($fetchedLines == []) {
$sourceLines = phpdbg_get_executable();
} else {
$newFiles = array_diff(
get_included_files(),
array_keys($fetchedLines)
$newFiles = \array_diff(
\get_included_files(),
\array_keys($fetchedLines)
);
if ($newFiles) {
$sourceLines = phpdbg_get_executable(
array('files' => $newFiles)
['files' => $newFiles]
);
} else {
$sourceLines = array();
$sourceLines = [];
}
}
@@ -76,7 +81,7 @@ class PHP_CodeCoverage_Driver_PHPDBG implements PHP_CodeCoverage_Driver
}
}
$fetchedLines = array_merge($fetchedLines, $sourceLines);
$fetchedLines = \array_merge($fetchedLines, $sourceLines);
return $this->detectExecutedLines($fetchedLines, $dbgData);
}
@@ -84,8 +89,9 @@ class PHP_CodeCoverage_Driver_PHPDBG implements PHP_CodeCoverage_Driver
/**
* Convert phpdbg based data into the format CodeCoverage expects
*
* @param array $sourceLines
* @param array $dbgData
* @param array $sourceLines
* @param array $dbgData
*
* @return array
*/
private function detectExecutedLines(array $sourceLines, array $dbgData)

View File

@@ -0,0 +1,117 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Driver;
use SebastianBergmann\CodeCoverage\RuntimeException;
/**
* Driver for Xdebug's code coverage functionality.
*
* @codeCoverageIgnore
*/
class Xdebug implements Driver
{
/**
* Cache the number of lines for each file
*
* @var array
*/
private $cacheNumLines = [];
/**
* Constructor.
*/
public function __construct()
{
if (!\extension_loaded('xdebug')) {
throw new RuntimeException('This driver requires Xdebug');
}
if (\version_compare(\phpversion('xdebug'), '2.2.1', '>=') &&
!\ini_get('xdebug.coverage_enable')) {
throw new RuntimeException(
'xdebug.coverage_enable=On has to be set in php.ini'
);
}
}
/**
* Start collection of code coverage information.
*
* @param bool $determineUnusedAndDead
*/
public function start($determineUnusedAndDead = true)
{
if ($determineUnusedAndDead) {
\xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
} else {
\xdebug_start_code_coverage();
}
}
/**
* Stop collection of code coverage information.
*
* @return array
*/
public function stop()
{
$data = \xdebug_get_code_coverage();
\xdebug_stop_code_coverage();
return $this->cleanup($data);
}
/**
* @param array $data
*
* @return array
*/
private function cleanup(array $data)
{
foreach (\array_keys($data) as $file) {
unset($data[$file][0]);
if (\strpos($file, 'xdebug://debug-eval') !== 0 && \file_exists($file)) {
$numLines = $this->getNumberOfLinesInFile($file);
foreach (\array_keys($data[$file]) as $line) {
if ($line > $numLines) {
unset($data[$file][$line]);
}
}
}
}
return $data;
}
/**
* @param string $file
*
* @return int
*/
private function getNumberOfLinesInFile($file)
{
if (!isset($this->cacheNumLines[$file])) {
$buffer = \file_get_contents($file);
$lines = \substr_count($buffer, "\n");
if (\substr($buffer, -1) !== "\n") {
$lines++;
}
$this->cacheNumLines[$file] = $lines;
}
return $this->cacheNumLines[$file];
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage;
/**
* Exception that is raised when covered code is not executed.
*/
class CoveredCodeNotExecutedException extends RuntimeException
{
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,9 +8,11 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage;
/**
* @since Class available since Release 2.0.0
* Exception interface for php-code-coverage component.
*/
class PHP_CodeCoverage_Report_XML_Directory extends PHP_CodeCoverage_Report_XML_Node
interface Exception
{
}

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage;
class InvalidArgumentException extends \InvalidArgumentException implements Exception
{
/**
* @param int $argument
* @param string $type
* @param mixed $value
*
* @return InvalidArgumentException
*/
public static function create($argument, $type, $value = null)
{
$stack = \debug_backtrace(0);
return new self(
\sprintf(
'Argument #%d%sof %s::%s() must be a %s',
$argument,
$value !== null ? ' (' . \gettype($value) . '#' . $value . ')' : ' (No Value) ',
$stack[1]['class'],
$stack[1]['function'],
$type
)
);
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage;
/**
* Exception that is raised when @covers must be used but is not.
*/
class MissingCoversAnnotationException extends RuntimeException
{
}

View File

@@ -0,0 +1,15 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage;
class RuntimeException extends \RuntimeException implements Exception
{
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage;
/**
* Exception that is raised when code is unintentionally covered.
*/
class UnintentionallyCoveredCodeException extends RuntimeException
{
/**
* @var array
*/
private $unintentionallyCoveredUnits = [];
/**
* @param array $unintentionallyCoveredUnits
*/
public function __construct(array $unintentionallyCoveredUnits)
{
$this->unintentionallyCoveredUnits = $unintentionallyCoveredUnits;
parent::__construct($this->toString());
}
/**
* @return array
*/
public function getUnintentionallyCoveredUnits()
{
return $this->unintentionallyCoveredUnits;
}
/**
* @return string
*/
private function toString()
{
$message = '';
foreach ($this->unintentionallyCoveredUnits as $unit) {
$message .= '- ' . $unit . "\n";
}
return $message;
}
}

View File

@@ -0,0 +1,173 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage;
/**
* Filter for whitelisting of code coverage information.
*/
class Filter
{
/**
* Source files that are whitelisted.
*
* @var array
*/
private $whitelistedFiles = [];
/**
* Adds a directory to the whitelist (recursively).
*
* @param string $directory
* @param string $suffix
* @param string $prefix
*/
public function addDirectoryToWhitelist($directory, $suffix = '.php', $prefix = '')
{
$facade = new \File_Iterator_Facade;
$files = $facade->getFilesAsArray($directory, $suffix, $prefix);
foreach ($files as $file) {
$this->addFileToWhitelist($file);
}
}
/**
* Adds a file to the whitelist.
*
* @param string $filename
*/
public function addFileToWhitelist($filename)
{
$this->whitelistedFiles[\realpath($filename)] = true;
}
/**
* Adds files to the whitelist.
*
* @param array $files
*/
public function addFilesToWhitelist(array $files)
{
foreach ($files as $file) {
$this->addFileToWhitelist($file);
}
}
/**
* Removes a directory from the whitelist (recursively).
*
* @param string $directory
* @param string $suffix
* @param string $prefix
*/
public function removeDirectoryFromWhitelist($directory, $suffix = '.php', $prefix = '')
{
$facade = new \File_Iterator_Facade;
$files = $facade->getFilesAsArray($directory, $suffix, $prefix);
foreach ($files as $file) {
$this->removeFileFromWhitelist($file);
}
}
/**
* Removes a file from the whitelist.
*
* @param string $filename
*/
public function removeFileFromWhitelist($filename)
{
$filename = \realpath($filename);
unset($this->whitelistedFiles[$filename]);
}
/**
* Checks whether a filename is a real filename.
*
* @param string $filename
*
* @return bool
*/
public function isFile($filename)
{
if ($filename == '-' ||
\strpos($filename, 'vfs://') === 0 ||
\strpos($filename, 'xdebug://debug-eval') !== false ||
\strpos($filename, 'eval()\'d code') !== false ||
\strpos($filename, 'runtime-created function') !== false ||
\strpos($filename, 'runkit created function') !== false ||
\strpos($filename, 'assert code') !== false ||
\strpos($filename, 'regexp code') !== false) {
return false;
}
return \file_exists($filename);
}
/**
* Checks whether or not a file is filtered.
*
* @param string $filename
*
* @return bool
*/
public function isFiltered($filename)
{
if (!$this->isFile($filename)) {
return true;
}
$filename = \realpath($filename);
return !isset($this->whitelistedFiles[$filename]);
}
/**
* Returns the list of whitelisted files.
*
* @return array
*/
public function getWhitelist()
{
return \array_keys($this->whitelistedFiles);
}
/**
* Returns whether this filter has a whitelist.
*
* @return bool
*/
public function hasWhitelist()
{
return !empty($this->whitelistedFiles);
}
/**
* Returns the whitelisted files.
*
* @return array
*/
public function getWhitelistedFiles()
{
return $this->whitelistedFiles;
}
/**
* Sets the whitelisted files.
*
* @param array $whitelistedFiles
*/
public function setWhitelistedFiles($whitelistedFiles)
{
$this->whitelistedFiles = $whitelistedFiles;
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,48 +8,50 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Node;
use SebastianBergmann\CodeCoverage\Util;
/**
* Base class for nodes in the code coverage information tree.
*
* @since Class available since Release 1.1.0
*/
abstract class PHP_CodeCoverage_Report_Node implements Countable
abstract class AbstractNode implements \Countable
{
/**
* @var string
*/
protected $name;
private $name;
/**
* @var string
*/
protected $path;
private $path;
/**
* @var array
*/
protected $pathArray;
private $pathArray;
/**
* @var PHP_CodeCoverage_Report_Node
* @var AbstractNode
*/
protected $parent;
private $parent;
/**
* @var string
*/
protected $id;
private $id;
/**
* Constructor.
*
* @param string $name
* @param PHP_CodeCoverage_Report_Node $parent
* @param string $name
* @param AbstractNode $parent
*/
public function __construct($name, PHP_CodeCoverage_Report_Node $parent = null)
public function __construct($name, self $parent = null)
{
if (substr($name, -1) == '/') {
$name = substr($name, 0, -1);
if (\substr($name, -1) == '/') {
$name = \substr($name, 0, -1);
}
$this->name = $name;
@@ -78,7 +80,7 @@ abstract class PHP_CodeCoverage_Report_Node implements Countable
$parentId = $parent->getId();
if ($parentId == 'index') {
$this->id = str_replace(':', '_', $this->name);
$this->id = \str_replace(':', '_', $this->name);
} else {
$this->id = $parentId . '/' . $this->name;
}
@@ -111,7 +113,7 @@ abstract class PHP_CodeCoverage_Report_Node implements Countable
{
if ($this->pathArray === null) {
if ($this->parent === null) {
$this->pathArray = array();
$this->pathArray = [];
} else {
$this->pathArray = $this->parent->getPathAsArray();
}
@@ -123,7 +125,7 @@ abstract class PHP_CodeCoverage_Report_Node implements Countable
}
/**
* @return PHP_CodeCoverage_Report_Node
* @return AbstractNode
*/
public function getParent()
{
@@ -133,12 +135,13 @@ abstract class PHP_CodeCoverage_Report_Node implements Countable
/**
* Returns the percentage of classes that has been tested.
*
* @param bool $asString
* @param bool $asString
*
* @return int
*/
public function getTestedClassesPercent($asString = true)
{
return PHP_CodeCoverage_Util::percent(
return Util::percent(
$this->getNumTestedClasses(),
$this->getNumClasses(),
$asString
@@ -148,12 +151,13 @@ abstract class PHP_CodeCoverage_Report_Node implements Countable
/**
* Returns the percentage of traits that has been tested.
*
* @param bool $asString
* @param bool $asString
*
* @return int
*/
public function getTestedTraitsPercent($asString = true)
{
return PHP_CodeCoverage_Util::percent(
return Util::percent(
$this->getNumTestedTraits(),
$this->getNumTraits(),
$asString
@@ -161,45 +165,79 @@ abstract class PHP_CodeCoverage_Report_Node implements Countable
}
/**
* Returns the percentage of traits that has been tested.
* Returns the percentage of classes and traits that has been tested.
*
* @param bool $asString
*
* @param bool $asString
* @return int
* @since Method available since Release 1.2.0
*/
public function getTestedClassesAndTraitsPercent($asString = true)
{
return PHP_CodeCoverage_Util::percent(
return Util::percent(
$this->getNumTestedClassesAndTraits(),
$this->getNumClassesAndTraits(),
$asString
);
}
/**
* Returns the percentage of functions that has been tested.
*
* @param bool $asString
*
* @return int
*/
public function getTestedFunctionsPercent($asString = true)
{
return Util::percent(
$this->getNumTestedFunctions(),
$this->getNumFunctions(),
$asString
);
}
/**
* Returns the percentage of methods that has been tested.
*
* @param bool $asString
* @param bool $asString
*
* @return int
*/
public function getTestedMethodsPercent($asString = true)
{
return PHP_CodeCoverage_Util::percent(
return Util::percent(
$this->getNumTestedMethods(),
$this->getNumMethods(),
$asString
);
}
/**
* Returns the percentage of functions and methods that has been tested.
*
* @param bool $asString
*
* @return int
*/
public function getTestedFunctionsAndMethodsPercent($asString = true)
{
return Util::percent(
$this->getNumTestedFunctionsAndMethods(),
$this->getNumFunctionsAndMethods(),
$asString
);
}
/**
* Returns the percentage of executed lines.
*
* @param bool $asString
* @param bool $asString
*
* @return int
*/
public function getLineExecutedPercent($asString = true)
{
return PHP_CodeCoverage_Util::percent(
return Util::percent(
$this->getNumExecutedLines(),
$this->getNumExecutableLines(),
$asString
@@ -210,7 +248,6 @@ abstract class PHP_CodeCoverage_Report_Node implements Countable
* Returns the number of classes and traits.
*
* @return int
* @since Method available since Release 1.2.0
*/
public function getNumClassesAndTraits()
{
@@ -221,7 +258,6 @@ abstract class PHP_CodeCoverage_Report_Node implements Countable
* Returns the number of tested classes and traits.
*
* @return int
* @since Method available since Release 1.2.0
*/
public function getNumTestedClassesAndTraits()
{
@@ -232,11 +268,40 @@ abstract class PHP_CodeCoverage_Report_Node implements Countable
* Returns the classes and traits of this node.
*
* @return array
* @since Method available since Release 1.2.0
*/
public function getClassesAndTraits()
{
return array_merge($this->getClasses(), $this->getTraits());
return \array_merge($this->getClasses(), $this->getTraits());
}
/**
* Returns the number of functions and methods.
*
* @return int
*/
public function getNumFunctionsAndMethods()
{
return $this->getNumFunctions() + $this->getNumMethods();
}
/**
* Returns the number of tested functions and methods.
*
* @return int
*/
public function getNumTestedFunctionsAndMethods()
{
return $this->getNumTestedFunctions() + $this->getNumTestedMethods();
}
/**
* Returns the functions and methods of this node.
*
* @return array
*/
public function getFunctionsAndMethods()
{
return \array_merge($this->getFunctions(), $this->getMethods());
}
/**

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,22 +8,22 @@
* file that was distributed with this source code.
*/
/**
* Factory for PHP_CodeCoverage_Report_Node_* object graphs.
*
* @since Class available since Release 1.1.0
*/
class PHP_CodeCoverage_Report_Factory
namespace SebastianBergmann\CodeCoverage\Node;
use SebastianBergmann\CodeCoverage\CodeCoverage;
class Builder
{
/**
* @param PHP_CodeCoverage $coverage
* @return PHP_CodeCoverage_Report_Node_Directory
* @param CodeCoverage $coverage
*
* @return Directory
*/
public function create(PHP_CodeCoverage $coverage)
public function build(CodeCoverage $coverage)
{
$files = $coverage->getData();
$commonPath = $this->reducePaths($files);
$root = new PHP_CodeCoverage_Report_Node_Directory(
$root = new Directory(
$commonPath,
null
);
@@ -39,18 +39,18 @@ class PHP_CodeCoverage_Report_Factory
}
/**
* @param PHP_CodeCoverage_Report_Node_Directory $root
* @param array $items
* @param array $tests
* @param bool $cacheTokens
* @param Directory $root
* @param array $items
* @param array $tests
* @param bool $cacheTokens
*/
private function addItems(PHP_CodeCoverage_Report_Node_Directory $root, array $items, array $tests, $cacheTokens)
private function addItems(Directory $root, array $items, array $tests, $cacheTokens)
{
foreach ($items as $key => $value) {
if (substr($key, -2) == '/f') {
$key = substr($key, 0, -2);
if (\substr($key, -2) == '/f') {
$key = \substr($key, 0, -2);
if (file_exists($root->getPath() . DIRECTORY_SEPARATOR . $key)) {
if (\file_exists($root->getPath() . DIRECTORY_SEPARATOR . $key)) {
$root->addFile($key, $value, $tests, $cacheTokens);
}
} else {
@@ -100,17 +100,18 @@ class PHP_CodeCoverage_Report_Factory
* )
* </code>
*
* @param array $files
* @param array $files
*
* @return array
*/
private function buildDirectoryStructure($files)
{
$result = array();
$result = [];
foreach ($files as $path => $file) {
$path = explode('/', $path);
$path = \explode('/', $path);
$pointer = &$result;
$max = count($path);
$max = \count($path);
for ($i = 0; $i < $max; $i++) {
if ($i == ($max - 1)) {
@@ -165,7 +166,8 @@ class PHP_CodeCoverage_Report_Factory
* )
* </code>
*
* @param array $files
* @param array $files
*
* @return string
*/
private function reducePaths(&$files)
@@ -175,26 +177,26 @@ class PHP_CodeCoverage_Report_Factory
}
$commonPath = '';
$paths = array_keys($files);
$paths = \array_keys($files);
if (count($files) == 1) {
$commonPath = dirname($paths[0]) . '/';
$files[basename($paths[0])] = $files[$paths[0]];
if (\count($files) == 1) {
$commonPath = \dirname($paths[0]) . '/';
$files[\basename($paths[0])] = $files[$paths[0]];
unset($files[$paths[0]]);
return $commonPath;
}
$max = count($paths);
$max = \count($paths);
for ($i = 0; $i < $max; $i++) {
// strip phar:// prefixes
if (strpos($paths[$i], 'phar://') === 0) {
$paths[$i] = substr($paths[$i], 7);
$paths[$i] = strtr($paths[$i], '/', DIRECTORY_SEPARATOR);
if (\strpos($paths[$i], 'phar://') === 0) {
$paths[$i] = \substr($paths[$i], 7);
$paths[$i] = \strtr($paths[$i], '/', DIRECTORY_SEPARATOR);
}
$paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]);
$paths[$i] = \explode(DIRECTORY_SEPARATOR, $paths[$i]);
if (empty($paths[$i][0])) {
$paths[$i][0] = DIRECTORY_SEPARATOR;
@@ -202,14 +204,15 @@ class PHP_CodeCoverage_Report_Factory
}
$done = false;
$max = count($paths);
$max = \count($paths);
while (!$done) {
for ($i = 0; $i < $max - 1; $i++) {
if (!isset($paths[$i][0]) ||
!isset($paths[$i+1][0]) ||
$paths[$i][0] != $paths[$i+1][0]) {
!isset($paths[$i + 1][0]) ||
$paths[$i][0] != $paths[$i + 1][0]) {
$done = true;
break;
}
}
@@ -222,21 +225,21 @@ class PHP_CodeCoverage_Report_Factory
}
for ($i = 0; $i < $max; $i++) {
array_shift($paths[$i]);
\array_shift($paths[$i]);
}
}
}
$original = array_keys($files);
$max = count($original);
$original = \array_keys($files);
$max = \count($original);
for ($i = 0; $i < $max; $i++) {
$files[implode('/', $paths[$i])] = $files[$original[$i]];
$files[\implode('/', $paths[$i])] = $files[$original[$i]];
unset($files[$original[$i]]);
}
ksort($files);
\ksort($files);
return substr($commonPath, 0, -1);
return \substr($commonPath, 0, -1);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,102 +8,104 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Node;
use SebastianBergmann\CodeCoverage\InvalidArgumentException;
/**
* Represents a directory in the code coverage information tree.
*
* @since Class available since Release 1.1.0
*/
class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Node implements IteratorAggregate
class Directory extends AbstractNode implements \IteratorAggregate
{
/**
* @var PHP_CodeCoverage_Report_Node[]
* @var AbstractNode[]
*/
protected $children = array();
private $children = [];
/**
* @var PHP_CodeCoverage_Report_Node_Directory[]
* @var Directory[]
*/
protected $directories = array();
private $directories = [];
/**
* @var PHP_CodeCoverage_Report_Node_File[]
* @var File[]
*/
protected $files = array();
private $files = [];
/**
* @var array
*/
protected $classes;
private $classes;
/**
* @var array
*/
protected $traits;
private $traits;
/**
* @var array
*/
protected $functions;
private $functions;
/**
* @var array
*/
protected $linesOfCode = null;
private $linesOfCode = null;
/**
* @var int
*/
protected $numFiles = -1;
private $numFiles = -1;
/**
* @var int
*/
protected $numExecutableLines = -1;
private $numExecutableLines = -1;
/**
* @var int
*/
protected $numExecutedLines = -1;
private $numExecutedLines = -1;
/**
* @var int
*/
protected $numClasses = -1;
private $numClasses = -1;
/**
* @var int
*/
protected $numTestedClasses = -1;
private $numTestedClasses = -1;
/**
* @var int
*/
protected $numTraits = -1;
private $numTraits = -1;
/**
* @var int
*/
protected $numTestedTraits = -1;
private $numTestedTraits = -1;
/**
* @var int
*/
protected $numMethods = -1;
private $numMethods = -1;
/**
* @var int
*/
protected $numTestedMethods = -1;
private $numTestedMethods = -1;
/**
* @var int
*/
protected $numFunctions = -1;
private $numFunctions = -1;
/**
* @var int
*/
protected $numTestedFunctions = -1;
private $numTestedFunctions = -1;
/**
* Returns the number of files in/under this node.
@@ -116,7 +118,7 @@ class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Nod
$this->numFiles = 0;
foreach ($this->children as $child) {
$this->numFiles += count($child);
$this->numFiles += \count($child);
}
}
@@ -126,28 +128,29 @@ class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Nod
/**
* Returns an iterator for this node.
*
* @return RecursiveIteratorIterator
* @return \RecursiveIteratorIterator
*/
public function getIterator()
{
return new RecursiveIteratorIterator(
new PHP_CodeCoverage_Report_Node_Iterator($this),
RecursiveIteratorIterator::SELF_FIRST
return new \RecursiveIteratorIterator(
new Iterator($this),
\RecursiveIteratorIterator::SELF_FIRST
);
}
/**
* Adds a new directory.
*
* @param string $name
* @return PHP_CodeCoverage_Report_Node_Directory
* @param string $name
*
* @return Directory
*/
public function addDirectory($name)
{
$directory = new self($name, $this);
$this->children[] = $directory;
$this->directories[] = &$this->children[count($this->children) - 1];
$this->directories[] = &$this->children[\count($this->children) - 1];
return $directory;
}
@@ -155,16 +158,18 @@ class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Nod
/**
* Adds a new file.
*
* @param string $name
* @param array $coverageData
* @param array $testData
* @param bool $cacheTokens
* @return PHP_CodeCoverage_Report_Node_File
* @throws PHP_CodeCoverage_Exception
* @param string $name
* @param array $coverageData
* @param array $testData
* @param bool $cacheTokens
*
* @return File
*
* @throws InvalidArgumentException
*/
public function addFile($name, array $coverageData, array $testData, $cacheTokens)
{
$file = new PHP_CodeCoverage_Report_Node_File(
$file = new File(
$name,
$this,
$coverageData,
@@ -173,7 +178,7 @@ class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Nod
);
$this->children[] = $file;
$this->files[] = &$this->children[count($this->children) - 1];
$this->files[] = &$this->children[\count($this->children) - 1];
$this->numExecutableLines = -1;
$this->numExecutedLines = -1;
@@ -219,10 +224,10 @@ class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Nod
public function getClasses()
{
if ($this->classes === null) {
$this->classes = array();
$this->classes = [];
foreach ($this->children as $child) {
$this->classes = array_merge(
$this->classes = \array_merge(
$this->classes,
$child->getClasses()
);
@@ -240,10 +245,10 @@ class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Nod
public function getTraits()
{
if ($this->traits === null) {
$this->traits = array();
$this->traits = [];
foreach ($this->children as $child) {
$this->traits = array_merge(
$this->traits = \array_merge(
$this->traits,
$child->getTraits()
);
@@ -261,10 +266,10 @@ class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Nod
public function getFunctions()
{
if ($this->functions === null) {
$this->functions = array();
$this->functions = [];
foreach ($this->children as $child) {
$this->functions = array_merge(
$this->functions = \array_merge(
$this->functions,
$child->getFunctions()
);
@@ -282,13 +287,13 @@ class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Nod
public function getLinesOfCode()
{
if ($this->linesOfCode === null) {
$this->linesOfCode = array('loc' => 0, 'cloc' => 0, 'ncloc' => 0);
$this->linesOfCode = ['loc' => 0, 'cloc' => 0, 'ncloc' => 0];
foreach ($this->children as $child) {
$linesOfCode = $child->getLinesOfCode();
$this->linesOfCode['loc'] += $linesOfCode['loc'];
$this->linesOfCode['cloc'] += $linesOfCode['cloc'];
$this->linesOfCode['loc'] += $linesOfCode['loc'];
$this->linesOfCode['cloc'] += $linesOfCode['cloc'];
$this->linesOfCode['ncloc'] += $linesOfCode['ncloc'];
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,107 +8,120 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Node;
use SebastianBergmann\CodeCoverage\InvalidArgumentException;
/**
* Represents a file in the code coverage information tree.
*
* @since Class available since Release 1.1.0
*/
class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
class File extends AbstractNode
{
/**
* @var array
*/
protected $coverageData;
private $coverageData;
/**
* @var array
*/
protected $testData;
private $testData;
/**
* @var int
*/
protected $numExecutableLines = 0;
private $numExecutableLines = 0;
/**
* @var int
*/
protected $numExecutedLines = 0;
private $numExecutedLines = 0;
/**
* @var array
*/
protected $classes = array();
private $classes = [];
/**
* @var array
*/
protected $traits = array();
private $traits = [];
/**
* @var array
*/
protected $functions = array();
private $functions = [];
/**
* @var array
*/
protected $linesOfCode = array();
private $linesOfCode = [];
/**
* @var int
*/
protected $numTestedTraits = 0;
private $numClasses = null;
/**
* @var int
*/
protected $numTestedClasses = 0;
private $numTestedClasses = 0;
/**
* @var int
*/
protected $numMethods = null;
private $numTraits = null;
/**
* @var int
*/
protected $numTestedMethods = null;
private $numTestedTraits = 0;
/**
* @var int
*/
protected $numTestedFunctions = null;
private $numMethods = null;
/**
* @var int
*/
private $numTestedMethods = null;
/**
* @var int
*/
private $numTestedFunctions = null;
/**
* @var array
*/
protected $startLines = array();
private $startLines = [];
/**
* @var array
*/
protected $endLines = array();
private $endLines = [];
/**
* @var bool
*/
protected $cacheTokens;
private $cacheTokens;
/**
* Constructor.
*
* @param string $name
* @param PHP_CodeCoverage_Report_Node $parent
* @param array $coverageData
* @param array $testData
* @param bool $cacheTokens
* @throws PHP_CodeCoverage_Exception
* @param string $name
* @param AbstractNode $parent
* @param array $coverageData
* @param array $testData
* @param bool $cacheTokens
*
* @throws InvalidArgumentException
*/
public function __construct($name, PHP_CodeCoverage_Report_Node $parent, array $coverageData, array $testData, $cacheTokens)
public function __construct($name, AbstractNode $parent, array $coverageData, array $testData, $cacheTokens)
{
if (!is_bool($cacheTokens)) {
throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
if (!\is_bool($cacheTokens)) {
throw InvalidArgumentException::create(
1,
'boolean'
);
@@ -220,7 +233,21 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
*/
public function getNumClasses()
{
return count($this->classes);
if ($this->numClasses === null) {
$this->numClasses = 0;
foreach ($this->classes as $class) {
foreach ($class['methods'] as $method) {
if ($method['executableLines'] > 0) {
$this->numClasses++;
continue 2;
}
}
}
}
return $this->numClasses;
}
/**
@@ -240,7 +267,21 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
*/
public function getNumTraits()
{
return count($this->traits);
if ($this->numTraits === null) {
$this->numTraits = 0;
foreach ($this->traits as $trait) {
foreach ($trait['methods'] as $method) {
if ($method['executableLines'] > 0) {
$this->numTraits++;
continue 2;
}
}
}
}
return $this->numTraits;
}
/**
@@ -322,7 +363,7 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
*/
public function getNumFunctions()
{
return count($this->functions);
return \count($this->functions);
}
/**
@@ -351,12 +392,12 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
*/
protected function calculateStatistics()
{
$classStack = $functionStack = array();
$classStack = $functionStack = [];
if ($this->cacheTokens) {
$tokens = PHP_Token_Stream_CachingFactory::get($this->getPath());
$tokens = \PHP_Token_Stream_CachingFactory::get($this->getPath());
} else {
$tokens = new PHP_Token_Stream($this->getPath());
$tokens = new \PHP_Token_Stream($this->getPath());
}
$this->processClasses($tokens);
@@ -409,7 +450,7 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
$this->numExecutableLines++;
if (count($this->coverageData[$lineNumber]) > 0) {
if (\count($this->coverageData[$lineNumber]) > 0) {
if (isset($currentClass)) {
$currentClass['executedLines']++;
}
@@ -436,8 +477,8 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
unset($currentClass);
if ($classStack) {
end($classStack);
$key = key($classStack);
\end($classStack);
$key = \key($classStack);
$currentClass = &$classStack[$key];
unset($classStack[$key]);
}
@@ -452,8 +493,8 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
unset($currentFunction);
if ($functionStack) {
end($functionStack);
$key = key($functionStack);
\end($functionStack);
$key = \key($functionStack);
$currentFunction = &$functionStack[$key];
unset($functionStack[$key]);
}
@@ -481,14 +522,14 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
if ($trait['executableLines'] > 0) {
$trait['coverage'] = ($trait['executedLines'] /
$trait['executableLines']) * 100;
if ($trait['coverage'] == 100) {
$this->numTestedClasses++;
}
} else {
$trait['coverage'] = 100;
}
if ($trait['coverage'] == 100) {
$this->numTestedClasses++;
}
$trait['crap'] = $this->crap(
$trait['ccn'],
$trait['coverage']
@@ -515,25 +556,43 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
if ($class['executableLines'] > 0) {
$class['coverage'] = ($class['executedLines'] /
$class['executableLines']) * 100;
if ($class['coverage'] == 100) {
$this->numTestedClasses++;
}
} else {
$class['coverage'] = 100;
}
if ($class['coverage'] == 100) {
$this->numTestedClasses++;
}
$class['crap'] = $this->crap(
$class['ccn'],
$class['coverage']
);
}
foreach ($this->functions as &$function) {
if ($function['executableLines'] > 0) {
$function['coverage'] = ($function['executedLines'] /
$function['executableLines']) * 100;
} else {
$function['coverage'] = 100;
}
if ($function['coverage'] == 100) {
$this->numTestedFunctions++;
}
$function['crap'] = $this->crap(
$function['ccn'],
$function['coverage']
);
}
}
/**
* @param PHP_Token_Stream $tokens
* @param \PHP_Token_Stream $tokens
*/
protected function processClasses(PHP_Token_Stream $tokens)
protected function processClasses(\PHP_Token_Stream $tokens)
{
$classes = $tokens->getClasses();
unset($tokens);
@@ -541,9 +600,13 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
$link = $this->getId() . '.html#';
foreach ($classes as $className => $class) {
$this->classes[$className] = array(
if (!empty($class['package']['namespace'])) {
$className = $class['package']['namespace'] . '\\' . $className;
}
$this->classes[$className] = [
'className' => $className,
'methods' => array(),
'methods' => [],
'startLine' => $class['startLine'],
'executableLines' => 0,
'executedLines' => 0,
@@ -552,24 +615,13 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
'crap' => 0,
'package' => $class['package'],
'link' => $link . $class['startLine']
);
];
$this->startLines[$class['startLine']] = &$this->classes[$className];
$this->endLines[$class['endLine']] = &$this->classes[$className];
foreach ($class['methods'] as $methodName => $method) {
$this->classes[$className]['methods'][$methodName] = array(
'methodName' => $methodName,
'signature' => $method['signature'],
'startLine' => $method['startLine'],
'endLine' => $method['endLine'],
'executableLines' => 0,
'executedLines' => 0,
'ccn' => $method['ccn'],
'coverage' => 0,
'crap' => 0,
'link' => $link . $method['startLine']
);
$this->classes[$className]['methods'][$methodName] = $this->newMethod($methodName, $method, $link);
$this->startLines[$method['startLine']] = &$this->classes[$className]['methods'][$methodName];
$this->endLines[$method['endLine']] = &$this->classes[$className]['methods'][$methodName];
@@ -578,9 +630,9 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
}
/**
* @param PHP_Token_Stream $tokens
* @param \PHP_Token_Stream $tokens
*/
protected function processTraits(PHP_Token_Stream $tokens)
protected function processTraits(\PHP_Token_Stream $tokens)
{
$traits = $tokens->getTraits();
unset($tokens);
@@ -588,9 +640,9 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
$link = $this->getId() . '.html#';
foreach ($traits as $traitName => $trait) {
$this->traits[$traitName] = array(
$this->traits[$traitName] = [
'traitName' => $traitName,
'methods' => array(),
'methods' => [],
'startLine' => $trait['startLine'],
'executableLines' => 0,
'executedLines' => 0,
@@ -599,24 +651,13 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
'crap' => 0,
'package' => $trait['package'],
'link' => $link . $trait['startLine']
);
];
$this->startLines[$trait['startLine']] = &$this->traits[$traitName];
$this->endLines[$trait['endLine']] = &$this->traits[$traitName];
foreach ($trait['methods'] as $methodName => $method) {
$this->traits[$traitName]['methods'][$methodName] = array(
'methodName' => $methodName,
'signature' => $method['signature'],
'startLine' => $method['startLine'],
'endLine' => $method['endLine'],
'executableLines' => 0,
'executedLines' => 0,
'ccn' => $method['ccn'],
'coverage' => 0,
'crap' => 0,
'link' => $link . $method['startLine']
);
$this->traits[$traitName]['methods'][$methodName] = $this->newMethod($methodName, $method, $link);
$this->startLines[$method['startLine']] = &$this->traits[$traitName]['methods'][$methodName];
$this->endLines[$method['endLine']] = &$this->traits[$traitName]['methods'][$methodName];
@@ -625,9 +666,9 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
}
/**
* @param PHP_Token_Stream $tokens
* @param \PHP_Token_Stream $tokens
*/
protected function processFunctions(PHP_Token_Stream $tokens)
protected function processFunctions(\PHP_Token_Stream $tokens)
{
$functions = $tokens->getFunctions();
unset($tokens);
@@ -635,7 +676,7 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
$link = $this->getId() . '.html#';
foreach ($functions as $functionName => $function) {
$this->functions[$functionName] = array(
$this->functions[$functionName] = [
'functionName' => $functionName,
'signature' => $function['signature'],
'startLine' => $function['startLine'],
@@ -645,7 +686,7 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
'coverage' => 0,
'crap' => 0,
'link' => $link . $function['startLine']
);
];
$this->startLines[$function['startLine']] = &$this->functions[$functionName];
$this->endLines[$function['endLine']] = &$this->functions[$functionName];
@@ -656,24 +697,48 @@ class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
* Calculates the Change Risk Anti-Patterns (CRAP) index for a unit of code
* based on its cyclomatic complexity and percentage of code coverage.
*
* @param int $ccn
* @param float $coverage
* @param int $ccn
* @param float $coverage
*
* @return string
* @since Method available since Release 1.2.0
*/
protected function crap($ccn, $coverage)
{
if ($coverage == 0) {
return (string) (pow($ccn, 2) + $ccn);
return (string) (\pow($ccn, 2) + $ccn);
}
if ($coverage >= 95) {
return (string) $ccn;
}
return sprintf(
return \sprintf(
'%01.2F',
pow($ccn, 2) * pow(1 - $coverage/100, 3) + $ccn
\pow($ccn, 2) * \pow(1 - $coverage / 100, 3) + $ccn
);
}
/**
* @param string $methodName
* @param array $method
* @param string $link
*
* @return array
*/
private function newMethod($methodName, array $method, $link)
{
return [
'methodName' => $methodName,
'visibility' => $method['visibility'],
'signature' => $method['signature'],
'startLine' => $method['startLine'],
'endLine' => $method['endLine'],
'executableLines' => 0,
'executedLines' => 0,
'ccn' => $method['ccn'],
'coverage' => 0,
'crap' => 0,
'link' => $link . $method['startLine'],
];
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,29 +8,27 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Node;
/**
* Recursive iterator for PHP_CodeCoverage_Report_Node object graphs.
*
* @since Class available since Release 1.1.0
* Recursive iterator for node object graphs.
*/
class PHP_CodeCoverage_Report_Node_Iterator implements RecursiveIterator
class Iterator implements \RecursiveIterator
{
/**
* @var int
*/
protected $position;
private $position;
/**
* @var PHP_CodeCoverage_Report_Node[]
* @var AbstractNode[]
*/
protected $nodes;
private $nodes;
/**
* Constructor.
*
* @param PHP_CodeCoverage_Report_Node_Directory $node
* @param Directory $node
*/
public function __construct(PHP_CodeCoverage_Report_Node_Directory $node)
public function __construct(Directory $node)
{
$this->nodes = $node->getChildNodes();
}
@@ -50,7 +48,7 @@ class PHP_CodeCoverage_Report_Node_Iterator implements RecursiveIterator
*/
public function valid()
{
return $this->position < count($this->nodes);
return $this->position < \count($this->nodes);
}
/**
@@ -66,7 +64,7 @@ class PHP_CodeCoverage_Report_Node_Iterator implements RecursiveIterator
/**
* Returns the current element.
*
* @return PHPUnit_Framework_Test
* @return \PHPUnit_Framework_Test
*/
public function current()
{
@@ -84,7 +82,7 @@ class PHP_CodeCoverage_Report_Node_Iterator implements RecursiveIterator
/**
* Returns the sub iterator for the current element.
*
* @return PHP_CodeCoverage_Report_Node_Iterator
* @return Iterator
*/
public function getChildren()
{
@@ -100,6 +98,6 @@ class PHP_CodeCoverage_Report_Node_Iterator implements RecursiveIterator
*/
public function hasChildren()
{
return $this->nodes[$this->position] instanceof PHP_CodeCoverage_Report_Node_Directory;
return $this->nodes[$this->position] instanceof Directory;
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,22 +8,29 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Node\File;
use SebastianBergmann\CodeCoverage\RuntimeException;
/**
* Generates a Clover XML logfile from an PHP_CodeCoverage object.
*
* @since Class available since Release 1.0.0
* Generates a Clover XML logfile from a code coverage object.
*/
class PHP_CodeCoverage_Report_Clover
class Clover
{
/**
* @param PHP_CodeCoverage $coverage
* @param string $target
* @param string $name
* @param CodeCoverage $coverage
* @param string $target
* @param string $name
*
* @return string
*
* @throws \SebastianBergmann\CodeCoverage\RuntimeException
*/
public function process(PHP_CodeCoverage $coverage, $target = null, $name = null)
public function process(CodeCoverage $coverage, $target = null, $name = null)
{
$xmlDocument = new DOMDocument('1.0', 'UTF-8');
$xmlDocument = new \DOMDocument('1.0', 'UTF-8');
$xmlDocument->formatOutput = true;
$xmlCoverage = $xmlDocument->createElement('coverage');
@@ -33,29 +40,30 @@ class PHP_CodeCoverage_Report_Clover
$xmlProject = $xmlDocument->createElement('project');
$xmlProject->setAttribute('timestamp', (int) $_SERVER['REQUEST_TIME']);
if (is_string($name)) {
if (\is_string($name)) {
$xmlProject->setAttribute('name', $name);
}
$xmlCoverage->appendChild($xmlProject);
$packages = array();
$packages = [];
$report = $coverage->getReport();
unset($coverage);
foreach ($report as $item) {
$namespace = 'global';
if (!$item instanceof PHP_CodeCoverage_Report_Node_File) {
if (!$item instanceof File) {
continue;
}
/* @var File $item */
$xmlFile = $xmlDocument->createElement('file');
$xmlFile->setAttribute('name', $item->getPath());
$classes = $item->getClassesAndTraits();
$coverage = $item->getCoverageData();
$lines = array();
$classes = $item->getClassesAndTraits();
$coverage = $item->getCoverageData();
$lines = [];
$namespace = 'global';
foreach ($classes as $className => $class) {
$classStatements = 0;
@@ -64,32 +72,34 @@ class PHP_CodeCoverage_Report_Clover
$classMethods = 0;
foreach ($class['methods'] as $methodName => $method) {
if ($method['executableLines'] == 0) {
if ($method['executableLines'] == 0) {
continue;
}
$classMethods++;
$classStatements += $method['executableLines'];
$classStatements += $method['executableLines'];
$coveredClassStatements += $method['executedLines'];
if ($method['coverage'] == 100) {
$coveredMethods++;
}
$methodCount = 0;
for ($i = $method['startLine'];
$i <= $method['endLine'];
$i++) {
if (isset($coverage[$i]) && ($coverage[$i] !== null)) {
$methodCount = max($methodCount, count($coverage[$i]));
foreach (\range($method['startLine'], $method['endLine']) as $line) {
if (isset($coverage[$line]) && ($coverage[$line] !== null)) {
$methodCount = \max($methodCount, \count($coverage[$line]));
}
}
$lines[$method['startLine']] = array(
'count' => $methodCount,
'crap' => $method['crap'],
'type' => 'method',
'name' => $methodName
);
$lines[$method['startLine']] = [
'ccn' => $method['ccn'],
'count' => $methodCount,
'crap' => $method['crap'],
'type' => 'method',
'visibility' => $method['visibility'],
'name' => $methodName
];
}
if (!empty($class['package']['namespace'])) {
@@ -131,27 +141,15 @@ class PHP_CodeCoverage_Report_Clover
$xmlFile->appendChild($xmlClass);
$xmlMetrics = $xmlDocument->createElement('metrics');
$xmlMetrics->setAttribute('complexity', $class['ccn']);
$xmlMetrics->setAttribute('methods', $classMethods);
$xmlMetrics->setAttribute('coveredmethods', $coveredMethods);
$xmlMetrics->setAttribute('conditionals', 0);
$xmlMetrics->setAttribute('coveredconditionals', 0);
$xmlMetrics->setAttribute('statements', $classStatements);
$xmlMetrics->setAttribute(
'coveredstatements',
$coveredClassStatements
);
$xmlMetrics->setAttribute(
'elements',
$classMethods +
$classStatements
/* + conditionals */
);
$xmlMetrics->setAttribute(
'coveredelements',
$coveredMethods +
$coveredClassStatements
/* + coveredconditionals */
);
$xmlMetrics->setAttribute('coveredstatements', $coveredClassStatements);
$xmlMetrics->setAttribute('elements', $classMethods + $classStatements /* + conditionals */);
$xmlMetrics->setAttribute('coveredelements', $coveredMethods + $coveredClassStatements /* + coveredconditionals */);
$xmlClass->appendChild($xmlMetrics);
}
@@ -160,12 +158,12 @@ class PHP_CodeCoverage_Report_Clover
continue;
}
$lines[$line] = array(
'count' => count($data), 'type' => 'stmt'
);
$lines[$line] = [
'count' => \count($data), 'type' => 'stmt'
];
}
ksort($lines);
\ksort($lines);
foreach ($lines as $line => $data) {
$xmlLine = $xmlDocument->createElement('line');
@@ -176,6 +174,14 @@ class PHP_CodeCoverage_Report_Clover
$xmlLine->setAttribute('name', $data['name']);
}
if (isset($data['visibility'])) {
$xmlLine->setAttribute('visibility', $data['visibility']);
}
if (isset($data['ccn'])) {
$xmlLine->setAttribute('complexity', $data['ccn']);
}
if (isset($data['crap'])) {
$xmlLine->setAttribute('crap', $data['crap']);
}
@@ -191,30 +197,13 @@ class PHP_CodeCoverage_Report_Clover
$xmlMetrics->setAttribute('ncloc', $linesOfCode['ncloc']);
$xmlMetrics->setAttribute('classes', $item->getNumClassesAndTraits());
$xmlMetrics->setAttribute('methods', $item->getNumMethods());
$xmlMetrics->setAttribute(
'coveredmethods',
$item->getNumTestedMethods()
);
$xmlMetrics->setAttribute('coveredmethods', $item->getNumTestedMethods());
$xmlMetrics->setAttribute('conditionals', 0);
$xmlMetrics->setAttribute('coveredconditionals', 0);
$xmlMetrics->setAttribute(
'statements',
$item->getNumExecutableLines()
);
$xmlMetrics->setAttribute(
'coveredstatements',
$item->getNumExecutedLines()
);
$xmlMetrics->setAttribute(
'elements',
$item->getNumMethods() + $item->getNumExecutableLines()
/* + conditionals */
);
$xmlMetrics->setAttribute(
'coveredelements',
$item->getNumTestedMethods() + $item->getNumExecutedLines()
/* + coveredconditionals */
);
$xmlMetrics->setAttribute('statements', $item->getNumExecutableLines());
$xmlMetrics->setAttribute('coveredstatements', $item->getNumExecutedLines());
$xmlMetrics->setAttribute('elements', $item->getNumMethods() + $item->getNumExecutableLines() /* + conditionals */);
$xmlMetrics->setAttribute('coveredelements', $item->getNumTestedMethods() + $item->getNumExecutedLines() /* + coveredconditionals */);
$xmlFile->appendChild($xmlMetrics);
if ($namespace == 'global') {
@@ -236,49 +225,37 @@ class PHP_CodeCoverage_Report_Clover
$linesOfCode = $report->getLinesOfCode();
$xmlMetrics = $xmlDocument->createElement('metrics');
$xmlMetrics->setAttribute('files', count($report));
$xmlMetrics->setAttribute('files', \count($report));
$xmlMetrics->setAttribute('loc', $linesOfCode['loc']);
$xmlMetrics->setAttribute('ncloc', $linesOfCode['ncloc']);
$xmlMetrics->setAttribute(
'classes',
$report->getNumClassesAndTraits()
);
$xmlMetrics->setAttribute('classes', $report->getNumClassesAndTraits());
$xmlMetrics->setAttribute('methods', $report->getNumMethods());
$xmlMetrics->setAttribute(
'coveredmethods',
$report->getNumTestedMethods()
);
$xmlMetrics->setAttribute('coveredmethods', $report->getNumTestedMethods());
$xmlMetrics->setAttribute('conditionals', 0);
$xmlMetrics->setAttribute('coveredconditionals', 0);
$xmlMetrics->setAttribute(
'statements',
$report->getNumExecutableLines()
);
$xmlMetrics->setAttribute(
'coveredstatements',
$report->getNumExecutedLines()
);
$xmlMetrics->setAttribute(
'elements',
$report->getNumMethods() + $report->getNumExecutableLines()
/* + conditionals */
);
$xmlMetrics->setAttribute(
'coveredelements',
$report->getNumTestedMethods() + $report->getNumExecutedLines()
/* + coveredconditionals */
);
$xmlMetrics->setAttribute('statements', $report->getNumExecutableLines());
$xmlMetrics->setAttribute('coveredstatements', $report->getNumExecutedLines());
$xmlMetrics->setAttribute('elements', $report->getNumMethods() + $report->getNumExecutableLines() /* + conditionals */);
$xmlMetrics->setAttribute('coveredelements', $report->getNumTestedMethods() + $report->getNumExecutedLines() /* + coveredconditionals */);
$xmlProject->appendChild($xmlMetrics);
$buffer = $xmlDocument->saveXML();
if ($target !== null) {
if (!is_dir(dirname($target))) {
mkdir(dirname($target), 0777, true);
if (!\is_dir(\dirname($target))) {
\mkdir(\dirname($target), 0777, true);
}
return $xmlDocument->save($target);
} else {
return $xmlDocument->saveXML();
if (@\file_put_contents($target, $buffer) === false) {
throw new RuntimeException(
\sprintf(
'Could not write to "%s',
$target
)
);
}
}
return $buffer;
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,10 +8,14 @@
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_Crap4j
namespace SebastianBergmann\CodeCoverage\Report;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\InvalidArgumentException;
use SebastianBergmann\CodeCoverage\Node\File;
use SebastianBergmann\CodeCoverage\RuntimeException;
class Crap4j
{
/**
* @var int
@@ -23,8 +27,8 @@ class PHP_CodeCoverage_Report_Crap4j
*/
public function __construct($threshold = 30)
{
if (!is_int($threshold)) {
throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
if (!\is_int($threshold)) {
throw InvalidArgumentException::create(
1,
'integer'
);
@@ -34,22 +38,25 @@ class PHP_CodeCoverage_Report_Crap4j
}
/**
* @param PHP_CodeCoverage $coverage
* @param string $target
* @param string $name
* @param CodeCoverage $coverage
* @param string $target
* @param string $name
*
* @return string
*
* @throws \SebastianBergmann\CodeCoverage\RuntimeException
*/
public function process(PHP_CodeCoverage $coverage, $target = null, $name = null)
public function process(CodeCoverage $coverage, $target = null, $name = null)
{
$document = new DOMDocument('1.0', 'UTF-8');
$document = new \DOMDocument('1.0', 'UTF-8');
$document->formatOutput = true;
$root = $document->createElement('crap_result');
$document->appendChild($root);
$project = $document->createElement('project', is_string($name) ? $name : '');
$project = $document->createElement('project', \is_string($name) ? $name : '');
$root->appendChild($project);
$root->appendChild($document->createElement('timestamp', date('Y-m-d H:i:s', (int) $_SERVER['REQUEST_TIME'])));
$root->appendChild($document->createElement('timestamp', \date('Y-m-d H:i:s', (int) $_SERVER['REQUEST_TIME'])));
$stats = $document->createElement('stats');
$methodsNode = $document->createElement('methods');
@@ -65,7 +72,7 @@ class PHP_CodeCoverage_Report_Crap4j
foreach ($report as $item) {
$namespace = 'global';
if (!$item instanceof PHP_CodeCoverage_Report_Node_File) {
if (!$item instanceof File) {
continue;
}
@@ -78,7 +85,7 @@ class PHP_CodeCoverage_Report_Crap4j
foreach ($class['methods'] as $methodName => $method) {
$crapLoad = $this->getCrapLoad($method['crap'], $method['ccn'], $method['coverage']);
$fullCrap += $method['crap'];
$fullCrap += $method['crap'];
$fullCrapLoad += $crapLoad;
$fullMethodCount++;
@@ -95,12 +102,12 @@ class PHP_CodeCoverage_Report_Crap4j
$methodNode->appendChild($document->createElement('package', $namespace));
$methodNode->appendChild($document->createElement('className', $className));
$methodNode->appendChild($document->createElement('methodName', $methodName));
$methodNode->appendChild($document->createElement('methodSignature', htmlspecialchars($method['signature'])));
$methodNode->appendChild($document->createElement('fullMethod', htmlspecialchars($method['signature'])));
$methodNode->appendChild($document->createElement('methodSignature', \htmlspecialchars($method['signature'])));
$methodNode->appendChild($document->createElement('fullMethod', \htmlspecialchars($method['signature'])));
$methodNode->appendChild($document->createElement('crap', $this->roundValue($method['crap'])));
$methodNode->appendChild($document->createElement('complexity', $method['ccn']));
$methodNode->appendChild($document->createElement('coverage', $this->roundValue($method['coverage'])));
$methodNode->appendChild($document->createElement('crapLoad', round($crapLoad)));
$methodNode->appendChild($document->createElement('crapLoad', \round($crapLoad)));
$methodsNode->appendChild($methodNode);
}
@@ -110,7 +117,7 @@ class PHP_CodeCoverage_Report_Crap4j
$stats->appendChild($document->createElement('name', 'Method Crap Stats'));
$stats->appendChild($document->createElement('methodCount', $fullMethodCount));
$stats->appendChild($document->createElement('crapMethodCount', $fullCrapMethodCount));
$stats->appendChild($document->createElement('crapLoad', round($fullCrapLoad)));
$stats->appendChild($document->createElement('crapLoad', \round($fullCrapLoad)));
$stats->appendChild($document->createElement('totalCrap', $fullCrap));
if ($fullMethodCount > 0) {
@@ -124,21 +131,31 @@ class PHP_CodeCoverage_Report_Crap4j
$root->appendChild($stats);
$root->appendChild($methodsNode);
$buffer = $document->saveXML();
if ($target !== null) {
if (!is_dir(dirname($target))) {
mkdir(dirname($target), 0777, true);
if (!\is_dir(\dirname($target))) {
\mkdir(\dirname($target), 0777, true);
}
return $document->save($target);
} else {
return $document->saveXML();
if (@\file_put_contents($target, $buffer) === false) {
throw new RuntimeException(
\sprintf(
'Could not write to "%s',
$target
)
);
}
}
return $buffer;
}
/**
* @param float $crapValue
* @param int $cyclomaticComplexity
* @param float $coveragePercent
* @param float $crapValue
* @param int $cyclomaticComplexity
* @param float $coveragePercent
*
* @return float
*/
private function getCrapLoad($crapValue, $cyclomaticComplexity, $coveragePercent)
@@ -154,11 +171,12 @@ class PHP_CodeCoverage_Report_Crap4j
}
/**
* @param float $value
* @param float $value
*
* @return float
*/
private function roundValue($value)
{
return round($value, 2);
return \round($value, 2);
}
}

View File

@@ -0,0 +1,190 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report\Html;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
use SebastianBergmann\CodeCoverage\RuntimeException;
/**
* Generates an HTML report from a code coverage object.
*/
class Facade
{
/**
* @var string
*/
private $templatePath;
/**
* @var string
*/
private $generator;
/**
* @var int
*/
private $lowUpperBound;
/**
* @var int
*/
private $highLowerBound;
/**
* Constructor.
*
* @param int $lowUpperBound
* @param int $highLowerBound
* @param string $generator
*/
public function __construct($lowUpperBound = 50, $highLowerBound = 90, $generator = '')
{
$this->generator = $generator;
$this->highLowerBound = $highLowerBound;
$this->lowUpperBound = $lowUpperBound;
$this->templatePath = __DIR__ . '/Renderer/Template/';
}
/**
* @param CodeCoverage $coverage
* @param string $target
*/
public function process(CodeCoverage $coverage, $target)
{
$target = $this->getDirectory($target);
$report = $coverage->getReport();
unset($coverage);
if (!isset($_SERVER['REQUEST_TIME'])) {
$_SERVER['REQUEST_TIME'] = \time();
}
$date = \date('D M j G:i:s T Y', $_SERVER['REQUEST_TIME']);
$dashboard = new Dashboard(
$this->templatePath,
$this->generator,
$date,
$this->lowUpperBound,
$this->highLowerBound
);
$directory = new Directory(
$this->templatePath,
$this->generator,
$date,
$this->lowUpperBound,
$this->highLowerBound
);
$file = new File(
$this->templatePath,
$this->generator,
$date,
$this->lowUpperBound,
$this->highLowerBound
);
$directory->render($report, $target . 'index.html');
$dashboard->render($report, $target . 'dashboard.html');
foreach ($report as $node) {
$id = $node->getId();
if ($node instanceof DirectoryNode) {
if (!\file_exists($target . $id)) {
\mkdir($target . $id, 0777, true);
}
$directory->render($node, $target . $id . '/index.html');
$dashboard->render($node, $target . $id . '/dashboard.html');
} else {
$dir = \dirname($target . $id);
if (!\file_exists($dir)) {
\mkdir($dir, 0777, true);
}
$file->render($node, $target . $id . '.html');
}
}
$this->copyFiles($target);
}
/**
* @param string $target
*/
private function copyFiles($target)
{
$dir = $this->getDirectory($target . '.css');
\file_put_contents(
$dir . 'bootstrap.min.css',
\str_replace(
'url(../fonts/',
'url(../.fonts/',
\file_get_contents($this->templatePath . 'css/bootstrap.min.css')
)
);
\copy($this->templatePath . 'css/nv.d3.min.css', $dir . 'nv.d3.min.css');
\copy($this->templatePath . 'css/style.css', $dir . 'style.css');
$dir = $this->getDirectory($target . '.fonts');
\copy($this->templatePath . 'fonts/glyphicons-halflings-regular.eot', $dir . 'glyphicons-halflings-regular.eot');
\copy($this->templatePath . 'fonts/glyphicons-halflings-regular.svg', $dir . 'glyphicons-halflings-regular.svg');
\copy($this->templatePath . 'fonts/glyphicons-halflings-regular.ttf', $dir . 'glyphicons-halflings-regular.ttf');
\copy($this->templatePath . 'fonts/glyphicons-halflings-regular.woff', $dir . 'glyphicons-halflings-regular.woff');
\copy($this->templatePath . 'fonts/glyphicons-halflings-regular.woff2', $dir . 'glyphicons-halflings-regular.woff2');
$dir = $this->getDirectory($target . '.js');
\copy($this->templatePath . 'js/bootstrap.min.js', $dir . 'bootstrap.min.js');
\copy($this->templatePath . 'js/d3.min.js', $dir . 'd3.min.js');
\copy($this->templatePath . 'js/holder.min.js', $dir . 'holder.min.js');
\copy($this->templatePath . 'js/html5shiv.min.js', $dir . 'html5shiv.min.js');
\copy($this->templatePath . 'js/jquery.min.js', $dir . 'jquery.min.js');
\copy($this->templatePath . 'js/nv.d3.min.js', $dir . 'nv.d3.min.js');
\copy($this->templatePath . 'js/respond.min.js', $dir . 'respond.min.js');
\copy($this->templatePath . 'js/file.js', $dir . 'file.js');
}
/**
* @param string $directory
*
* @return string
*
* @throws RuntimeException
*/
private function getDirectory($directory)
{
if (\substr($directory, -1, 1) != DIRECTORY_SEPARATOR) {
$directory .= DIRECTORY_SEPARATOR;
}
if (\is_dir($directory)) {
return $directory;
}
if (@\mkdir($directory, 0777, true)) {
return $directory;
}
throw new RuntimeException(
\sprintf(
'Directory "%s" does not exist.',
$directory
)
);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,14 +8,18 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report\Html;
use SebastianBergmann\CodeCoverage\Node\AbstractNode;
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
use SebastianBergmann\CodeCoverage\Node\File as FileNode;
use SebastianBergmann\CodeCoverage\Version;
use SebastianBergmann\Environment\Runtime;
/**
* Base class for PHP_CodeCoverage_Report_Node renderers.
*
* @since Class available since Release 1.1.0
* Base class for node renderers.
*/
abstract class PHP_CodeCoverage_Report_HTML_Renderer
abstract class Renderer
{
/**
* @var string
@@ -58,22 +62,21 @@ abstract class PHP_CodeCoverage_Report_HTML_Renderer
*/
public function __construct($templatePath, $generator, $date, $lowUpperBound, $highLowerBound)
{
$version = new SebastianBergmann\Version('2.2.4', dirname(dirname(dirname(dirname(__DIR__)))));
$this->templatePath = $templatePath;
$this->generator = $generator;
$this->date = $date;
$this->lowUpperBound = $lowUpperBound;
$this->highLowerBound = $highLowerBound;
$this->version = $version->getVersion();
$this->version = Version::id();
}
/**
* @param Text_Template $template
* @param array $data
* @param \Text_Template $template
* @param array $data
*
* @return string
*/
protected function renderItemTemplate(Text_Template $template, array $data)
protected function renderItemTemplate(\Text_Template $template, array $data)
{
$numSeparator = '&nbsp;/&nbsp;';
@@ -87,9 +90,10 @@ abstract class PHP_CodeCoverage_Report_HTML_Renderer
$data['testedClassesPercent']
);
} else {
$classesLevel = 'success';
$classesNumber = '0' . $numSeparator . '0';
$classesBar = $this->getCoverageBar(100);
$classesLevel = '';
$classesNumber = '0' . $numSeparator . '0';
$classesBar = '';
$data['testedClassesPercentAsString'] = 'n/a';
}
if ($data['numMethods'] > 0) {
@@ -102,10 +106,10 @@ abstract class PHP_CodeCoverage_Report_HTML_Renderer
$data['testedMethodsPercent']
);
} else {
$methodsLevel = 'success';
$methodsLevel = '';
$methodsNumber = '0' . $numSeparator . '0';
$methodsBar = $this->getCoverageBar(100);
$data['testedMethodsPercentAsString'] = '100.00%';
$methodsBar = '';
$data['testedMethodsPercentAsString'] = 'n/a';
}
if ($data['numExecutableLines'] > 0) {
@@ -118,14 +122,14 @@ abstract class PHP_CodeCoverage_Report_HTML_Renderer
$data['linesExecutedPercent']
);
} else {
$linesLevel = 'success';
$linesLevel = '';
$linesNumber = '0' . $numSeparator . '0';
$linesBar = $this->getCoverageBar(100);
$data['linesExecutedPercentAsString'] = '100.00%';
$linesBar = '';
$data['linesExecutedPercentAsString'] = 'n/a';
}
$template->setVar(
array(
[
'icon' => isset($data['icon']) ? $data['icon'] : '',
'crap' => isset($data['crap']) ? $data['crap'] : '',
'name' => $data['name'],
@@ -141,58 +145,54 @@ abstract class PHP_CodeCoverage_Report_HTML_Renderer
'classes_tested_percent' => isset($data['testedClassesPercentAsString']) ? $data['testedClassesPercentAsString'] : '',
'classes_level' => $classesLevel,
'classes_number' => $classesNumber
)
]
);
return $template->render();
}
/**
* @param Text_Template $template
* @param PHP_CodeCoverage_Report_Node $node
* @param \Text_Template $template
* @param AbstractNode $node
*/
protected function setCommonTemplateVariables(Text_Template $template, PHP_CodeCoverage_Report_Node $node)
protected function setCommonTemplateVariables(\Text_Template $template, AbstractNode $node)
{
$runtime = new Runtime;
$template->setVar(
array(
[
'id' => $node->getId(),
'full_path' => $node->getPath(),
'path_to_root' => $this->getPathToRoot($node),
'breadcrumbs' => $this->getBreadcrumbs($node),
'date' => $this->date,
'version' => $this->version,
'runtime_name' => $runtime->getName(),
'runtime_version' => $runtime->getVersion(),
'runtime_link' => $runtime->getVendorUrl(),
'runtime' => $this->getRuntimeString(),
'generator' => $this->generator,
'low_upper_bound' => $this->lowUpperBound,
'high_lower_bound' => $this->highLowerBound
)
]
);
}
protected function getBreadcrumbs(PHP_CodeCoverage_Report_Node $node)
protected function getBreadcrumbs(AbstractNode $node)
{
$breadcrumbs = '';
$path = $node->getPathAsArray();
$pathToRoot = array();
$max = count($path);
$pathToRoot = [];
$max = \count($path);
if ($node instanceof PHP_CodeCoverage_Report_Node_File) {
if ($node instanceof FileNode) {
$max--;
}
for ($i = 0; $i < $max; $i++) {
$pathToRoot[] = str_repeat('../', $i);
$pathToRoot[] = \str_repeat('../', $i);
}
foreach ($path as $step) {
if ($step !== $node) {
$breadcrumbs .= $this->getInactiveBreadcrumb(
$step,
array_pop($pathToRoot)
\array_pop($pathToRoot)
);
} else {
$breadcrumbs .= $this->getActiveBreadcrumb($step);
@@ -202,59 +202,60 @@ abstract class PHP_CodeCoverage_Report_HTML_Renderer
return $breadcrumbs;
}
protected function getActiveBreadcrumb(PHP_CodeCoverage_Report_Node $node)
protected function getActiveBreadcrumb(AbstractNode $node)
{
$buffer = sprintf(
$buffer = \sprintf(
' <li class="active">%s</li>' . "\n",
$node->getName()
);
if ($node instanceof PHP_CodeCoverage_Report_Node_Directory) {
if ($node instanceof DirectoryNode) {
$buffer .= ' <li>(<a href="dashboard.html">Dashboard</a>)</li>' . "\n";
}
return $buffer;
}
protected function getInactiveBreadcrumb(PHP_CodeCoverage_Report_Node $node, $pathToRoot)
protected function getInactiveBreadcrumb(AbstractNode $node, $pathToRoot)
{
return sprintf(
return \sprintf(
' <li><a href="%sindex.html">%s</a></li>' . "\n",
$pathToRoot,
$node->getName()
);
}
protected function getPathToRoot(PHP_CodeCoverage_Report_Node $node)
protected function getPathToRoot(AbstractNode $node)
{
$id = $node->getId();
$depth = substr_count($id, '/');
$depth = \substr_count($id, '/');
if ($id != 'index' &&
$node instanceof PHP_CodeCoverage_Report_Node_Directory) {
$node instanceof DirectoryNode) {
$depth++;
}
return str_repeat('../', $depth);
return \str_repeat('../', $depth);
}
protected function getCoverageBar($percent)
{
$level = $this->getColorLevel($percent);
$template = new Text_Template(
$template = new \Text_Template(
$this->templatePath . 'coverage_bar.html',
'{{',
'}}'
);
$template->setVar(array('level' => $level, 'percent' => sprintf('%.2F', $percent)));
$template->setVar(['level' => $level, 'percent' => \sprintf('%.2F', $percent)]);
return $template->render();
}
/**
* @param int $percent
* @param int $percent
*
* @return string
*/
protected function getColorLevel($percent)
@@ -262,10 +263,34 @@ abstract class PHP_CodeCoverage_Report_HTML_Renderer
if ($percent <= $this->lowUpperBound) {
return 'danger';
} elseif ($percent > $this->lowUpperBound &&
$percent < $this->highLowerBound) {
$percent < $this->highLowerBound) {
return 'warning';
} else {
return 'success';
}
}
/**
* @return string
*/
private function getRuntimeString()
{
$runtime = new Runtime;
$buffer = \sprintf(
'<a href="%s" target="_top">%s %s</a>',
$runtime->getVendorUrl(),
$runtime->getName(),
$runtime->getVersion()
);
if ($runtime->hasXdebug() && !$runtime->hasPHPDBGCodeCoverage()) {
$buffer .= \sprintf(
' with <a href="https://xdebug.org/">Xdebug %s</a>',
\phpversion('xdebug')
);
}
return $buffer;
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,21 +8,26 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report\Html;
use SebastianBergmann\CodeCoverage\Node\AbstractNode;
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
/**
* Renders the dashboard for a PHP_CodeCoverage_Report_Node_Directory node.
*
* @since Class available since Release 1.1.0
* Renders the dashboard for a directory node.
*/
class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_Report_HTML_Renderer
class Dashboard extends Renderer
{
/**
* @param PHP_CodeCoverage_Report_Node_Directory $node
* @param string $file
* @param DirectoryNode $node
* @param string $file
*
* @throws \InvalidArgumentException
*/
public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file)
public function render(DirectoryNode $node, $file)
{
$classes = $node->getClassesAndTraits();
$template = new Text_Template(
$template = new \Text_Template(
$this->templatePath . 'dashboard.html',
'{{',
'}}'
@@ -37,7 +42,7 @@ class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_R
$projectRisks = $this->projectRisks($classes, $baseLink);
$template->setVar(
array(
[
'insufficient_coverage_classes' => $insufficientCoverage['class'],
'insufficient_coverage_methods' => $insufficientCoverage['method'],
'project_risks_classes' => $projectRisks['class'],
@@ -46,7 +51,7 @@ class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_R
'complexity_method' => $complexity['method'],
'class_coverage_distribution' => $coverageDistribution['class'],
'method_coverage_distribution' => $coverageDistribution['method']
)
]
);
$template->renderTo($file);
@@ -55,58 +60,60 @@ class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_R
/**
* Returns the data for the Class/Method Complexity charts.
*
* @param array $classes
* @param string $baseLink
* @param array $classes
* @param string $baseLink
*
* @return array
*/
protected function complexity(array $classes, $baseLink)
{
$result = array('class' => array(), 'method' => array());
$result = ['class' => [], 'method' => []];
foreach ($classes as $className => $class) {
foreach ($class['methods'] as $methodName => $method) {
if ($className != '*') {
if ($className !== '*') {
$methodName = $className . '::' . $methodName;
}
$result['method'][] = array(
$result['method'][] = [
$method['coverage'],
$method['ccn'],
sprintf(
\sprintf(
'<a href="%s">%s</a>',
str_replace($baseLink, '', $method['link']),
\str_replace($baseLink, '', $method['link']),
$methodName
)
);
];
}
$result['class'][] = array(
$result['class'][] = [
$class['coverage'],
$class['ccn'],
sprintf(
\sprintf(
'<a href="%s">%s</a>',
str_replace($baseLink, '', $class['link']),
\str_replace($baseLink, '', $class['link']),
$className
)
);
];
}
return array(
'class' => json_encode($result['class']),
'method' => json_encode($result['method'])
);
return [
'class' => \json_encode($result['class']),
'method' => \json_encode($result['method'])
];
}
/**
* Returns the data for the Class / Method Coverage Distribution chart.
*
* @param array $classes
* @param array $classes
*
* @return array
*/
protected function coverageDistribution(array $classes)
{
$result = array(
'class' => array(
$result = [
'class' => [
'0%' => 0,
'0-10%' => 0,
'10-20%' => 0,
@@ -119,8 +126,8 @@ class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_R
'80-90%' => 0,
'90-100%' => 0,
'100%' => 0
),
'method' => array(
],
'method' => [
'0%' => 0,
'0-10%' => 0,
'10-20%' => 0,
@@ -133,59 +140,60 @@ class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_R
'80-90%' => 0,
'90-100%' => 0,
'100%' => 0
)
);
]
];
foreach ($classes as $class) {
foreach ($class['methods'] as $methodName => $method) {
if ($method['coverage'] == 0) {
if ($method['coverage'] === 0) {
$result['method']['0%']++;
} elseif ($method['coverage'] == 100) {
} elseif ($method['coverage'] === 100) {
$result['method']['100%']++;
} else {
$key = floor($method['coverage'] / 10) * 10;
$key = \floor($method['coverage'] / 10) * 10;
$key = $key . '-' . ($key + 10) . '%';
$result['method'][$key]++;
}
}
if ($class['coverage'] == 0) {
if ($class['coverage'] === 0) {
$result['class']['0%']++;
} elseif ($class['coverage'] == 100) {
} elseif ($class['coverage'] === 100) {
$result['class']['100%']++;
} else {
$key = floor($class['coverage'] / 10) * 10;
$key = \floor($class['coverage'] / 10) * 10;
$key = $key . '-' . ($key + 10) . '%';
$result['class'][$key]++;
}
}
return array(
'class' => json_encode(array_values($result['class'])),
'method' => json_encode(array_values($result['method']))
);
return [
'class' => \json_encode(\array_values($result['class'])),
'method' => \json_encode(\array_values($result['method']))
];
}
/**
* Returns the classes / methods with insufficient coverage.
*
* @param array $classes
* @param string $baseLink
* @param array $classes
* @param string $baseLink
*
* @return array
*/
protected function insufficientCoverage(array $classes, $baseLink)
{
$leastTestedClasses = array();
$leastTestedMethods = array();
$result = array('class' => '', 'method' => '');
$leastTestedClasses = [];
$leastTestedMethods = [];
$result = ['class' => '', 'method' => ''];
foreach ($classes as $className => $class) {
foreach ($class['methods'] as $methodName => $method) {
if ($method['coverage'] < $this->highLowerBound) {
if ($className != '*') {
$key = $methodName;
if ($className !== '*') {
$key = $className . '::' . $methodName;
} else {
$key = $methodName;
}
$leastTestedMethods[$key] = $method['coverage'];
@@ -197,24 +205,24 @@ class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_R
}
}
asort($leastTestedClasses);
asort($leastTestedMethods);
\asort($leastTestedClasses);
\asort($leastTestedMethods);
foreach ($leastTestedClasses as $className => $coverage) {
$result['class'] .= sprintf(
$result['class'] .= \sprintf(
' <tr><td><a href="%s">%s</a></td><td class="text-right">%d%%</td></tr>' . "\n",
str_replace($baseLink, '', $classes[$className]['link']),
\str_replace($baseLink, '', $classes[$className]['link']),
$className,
$coverage
);
}
foreach ($leastTestedMethods as $methodName => $coverage) {
list($class, $method) = explode('::', $methodName);
list($class, $method) = \explode('::', $methodName);
$result['method'] .= sprintf(
$result['method'] .= \sprintf(
' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d%%</td></tr>' . "\n",
str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']),
\str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']),
$methodName,
$method,
$coverage
@@ -227,21 +235,22 @@ class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_R
/**
* Returns the project risks according to the CRAP index.
*
* @param array $classes
* @param string $baseLink
* @param array $classes
* @param string $baseLink
*
* @return array
*/
protected function projectRisks(array $classes, $baseLink)
{
$classRisks = array();
$methodRisks = array();
$result = array('class' => '', 'method' => '');
$classRisks = [];
$methodRisks = [];
$result = ['class' => '', 'method' => ''];
foreach ($classes as $className => $class) {
foreach ($class['methods'] as $methodName => $method) {
if ($method['coverage'] < $this->highLowerBound &&
$method['ccn'] > 1) {
if ($className != '*') {
if ($className !== '*') {
$key = $className . '::' . $methodName;
} else {
$key = $methodName;
@@ -252,29 +261,29 @@ class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_R
}
if ($class['coverage'] < $this->highLowerBound &&
$class['ccn'] > count($class['methods'])) {
$class['ccn'] > \count($class['methods'])) {
$classRisks[$className] = $class['crap'];
}
}
arsort($classRisks);
arsort($methodRisks);
\arsort($classRisks);
\arsort($methodRisks);
foreach ($classRisks as $className => $crap) {
$result['class'] .= sprintf(
$result['class'] .= \sprintf(
' <tr><td><a href="%s">%s</a></td><td class="text-right">%d</td></tr>' . "\n",
str_replace($baseLink, '', $classes[$className]['link']),
\str_replace($baseLink, '', $classes[$className]['link']),
$className,
$crap
);
}
foreach ($methodRisks as $methodName => $crap) {
list($class, $method) = explode('::', $methodName);
list($class, $method) = \explode('::', $methodName);
$result['method'] .= sprintf(
$result['method'] .= \sprintf(
' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d</td></tr>' . "\n",
str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']),
\str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']),
$methodName,
$method,
$crap
@@ -284,9 +293,9 @@ class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_R
return $result;
}
protected function getActiveBreadcrumb(PHP_CodeCoverage_Report_Node $node)
protected function getActiveBreadcrumb(AbstractNode $node)
{
return sprintf(
return \sprintf(
' <li><a href="index.html">%s</a></li>' . "\n" .
' <li class="active">(Dashboard)</li>' . "\n",
$node->getName()

View File

@@ -0,0 +1,101 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report\Html;
use SebastianBergmann\CodeCoverage\Node\AbstractNode as Node;
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
/**
* Renders a directory node.
*/
class Directory extends Renderer
{
/**
* @param DirectoryNode $node
* @param string $file
*/
public function render(DirectoryNode $node, $file)
{
$template = new \Text_Template($this->templatePath . 'directory.html', '{{', '}}');
$this->setCommonTemplateVariables($template, $node);
$items = $this->renderItem($node, true);
foreach ($node->getDirectories() as $item) {
$items .= $this->renderItem($item);
}
foreach ($node->getFiles() as $item) {
$items .= $this->renderItem($item);
}
$template->setVar(
[
'id' => $node->getId(),
'items' => $items
]
);
$template->renderTo($file);
}
/**
* @param Node $node
* @param bool $total
*
* @return string
*/
protected function renderItem(Node $node, $total = false)
{
$data = [
'numClasses' => $node->getNumClassesAndTraits(),
'numTestedClasses' => $node->getNumTestedClassesAndTraits(),
'numMethods' => $node->getNumFunctionsAndMethods(),
'numTestedMethods' => $node->getNumTestedFunctionsAndMethods(),
'linesExecutedPercent' => $node->getLineExecutedPercent(false),
'linesExecutedPercentAsString' => $node->getLineExecutedPercent(),
'numExecutedLines' => $node->getNumExecutedLines(),
'numExecutableLines' => $node->getNumExecutableLines(),
'testedMethodsPercent' => $node->getTestedFunctionsAndMethodsPercent(false),
'testedMethodsPercentAsString' => $node->getTestedFunctionsAndMethodsPercent(),
'testedClassesPercent' => $node->getTestedClassesAndTraitsPercent(false),
'testedClassesPercentAsString' => $node->getTestedClassesAndTraitsPercent()
];
if ($total) {
$data['name'] = 'Total';
} else {
if ($node instanceof DirectoryNode) {
$data['name'] = \sprintf(
'<a href="%s/index.html">%s</a>',
$node->getName(),
$node->getName()
);
$data['icon'] = '<span class="glyphicon glyphicon-folder-open"></span> ';
} else {
$data['name'] = \sprintf(
'<a href="%s.html">%s</a>',
$node->getName(),
$node->getName()
);
$data['icon'] = '<span class="glyphicon glyphicon-file"></span> ';
}
}
return $this->renderItemTemplate(
new \Text_Template($this->templatePath . 'directory_item.html', '{{', '}}'),
$data
);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,34 +8,15 @@
* file that was distributed with this source code.
*/
// @codeCoverageIgnoreStart
if (!defined('T_TRAIT')) {
define('T_TRAIT', 1001);
}
namespace SebastianBergmann\CodeCoverage\Report\Html;
if (!defined('T_INSTEADOF')) {
define('T_INSTEADOF', 1002);
}
if (!defined('T_CALLABLE')) {
define('T_CALLABLE', 1003);
}
if (!defined('T_FINALLY')) {
define('T_FINALLY', 1004);
}
if (!defined('T_YIELD')) {
define('T_YIELD', 1005);
}
// @codeCoverageIgnoreEnd
use SebastianBergmann\CodeCoverage\Node\File as FileNode;
use SebastianBergmann\CodeCoverage\Util;
/**
* Renders a PHP_CodeCoverage_Report_Node_File node.
*
* @since Class available since Release 1.1.0
* Renders a file node.
*/
class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report_HTML_Renderer
class File extends Renderer
{
/**
* @var int
@@ -63,24 +44,22 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
$this->htmlspecialcharsFlags = ENT_COMPAT;
if (PHP_VERSION_ID >= 50400 && defined('ENT_SUBSTITUTE')) {
$this->htmlspecialcharsFlags = $this->htmlspecialcharsFlags | ENT_HTML401 | ENT_SUBSTITUTE;
}
$this->htmlspecialcharsFlags = $this->htmlspecialcharsFlags | ENT_HTML401 | ENT_SUBSTITUTE;
}
/**
* @param PHP_CodeCoverage_Report_Node_File $node
* @param string $file
* @param FileNode $node
* @param string $file
*/
public function render(PHP_CodeCoverage_Report_Node_File $node, $file)
public function render(FileNode $node, $file)
{
$template = new Text_Template($this->templatePath . 'file.html', '{{', '}}');
$template = new \Text_Template($this->templatePath . 'file.html', '{{', '}}');
$template->setVar(
array(
[
'items' => $this->renderItems($node),
'lines' => $this->renderSource($node)
)
]
);
$this->setCommonTemplateVariables($template, $node);
@@ -89,14 +68,15 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
}
/**
* @param PHP_CodeCoverage_Report_Node_File $node
* @param FileNode $node
*
* @return string
*/
protected function renderItems(PHP_CodeCoverage_Report_Node_File $node)
protected function renderItems(FileNode $node)
{
$template = new Text_Template($this->templatePath . 'file_item.html', '{{', '}}');
$template = new \Text_Template($this->templatePath . 'file_item.html', '{{', '}}');
$methodItemTemplate = new Text_Template(
$methodItemTemplate = new \Text_Template(
$this->templatePath . 'method_item.html',
'{{',
'}}'
@@ -104,22 +84,22 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
$items = $this->renderItemTemplate(
$template,
array(
[
'name' => 'Total',
'numClasses' => $node->getNumClassesAndTraits(),
'numTestedClasses' => $node->getNumTestedClassesAndTraits(),
'numMethods' => $node->getNumMethods(),
'numTestedMethods' => $node->getNumTestedMethods(),
'numMethods' => $node->getNumFunctionsAndMethods(),
'numTestedMethods' => $node->getNumTestedFunctionsAndMethods(),
'linesExecutedPercent' => $node->getLineExecutedPercent(false),
'linesExecutedPercentAsString' => $node->getLineExecutedPercent(),
'numExecutedLines' => $node->getNumExecutedLines(),
'numExecutableLines' => $node->getNumExecutableLines(),
'testedMethodsPercent' => $node->getTestedMethodsPercent(false),
'testedMethodsPercentAsString' => $node->getTestedMethodsPercent(),
'testedMethodsPercent' => $node->getTestedFunctionsAndMethodsPercent(false),
'testedMethodsPercentAsString' => $node->getTestedFunctionsAndMethodsPercent(),
'testedClassesPercent' => $node->getTestedClassesAndTraitsPercent(false),
'testedClassesPercentAsString' => $node->getTestedClassesAndTraitsPercent(),
'crap' => '<abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr>'
)
]
);
$items .= $this->renderFunctionItems(
@@ -143,71 +123,86 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
}
/**
* @param array $items
* @param Text_Template $template
* @param Text_Template $methodItemTemplate
* @param array $items
* @param \Text_Template $template
* @param \Text_Template $methodItemTemplate
*
* @return string
*/
protected function renderTraitOrClassItems(array $items, Text_Template $template, Text_Template $methodItemTemplate)
protected function renderTraitOrClassItems(array $items, \Text_Template $template, \Text_Template $methodItemTemplate)
{
if (empty($items)) {
return '';
}
$buffer = '';
if (empty($items)) {
return $buffer;
}
foreach ($items as $name => $item) {
$numMethods = count($item['methods']);
$numMethods = 0;
$numTestedMethods = 0;
foreach ($item['methods'] as $method) {
if ($method['executedLines'] == $method['executableLines']) {
$numTestedMethods++;
if ($method['executableLines'] > 0) {
$numMethods++;
if ($method['executedLines'] === $method['executableLines']) {
$numTestedMethods++;
}
}
}
if ($item['executableLines'] > 0) {
$numClasses = 1;
$numTestedClasses = $numTestedMethods == $numMethods ? 1 : 0;
$linesExecutedPercentAsString = Util::percent(
$item['executedLines'],
$item['executableLines'],
true
);
} else {
$numClasses = 'n/a';
$numTestedClasses = 'n/a';
$linesExecutedPercentAsString = 'n/a';
}
$buffer .= $this->renderItemTemplate(
$template,
array(
[
'name' => $name,
'numClasses' => 1,
'numTestedClasses' => $numTestedMethods == $numMethods ? 1 : 0,
'numClasses' => $numClasses,
'numTestedClasses' => $numTestedClasses,
'numMethods' => $numMethods,
'numTestedMethods' => $numTestedMethods,
'linesExecutedPercent' => PHP_CodeCoverage_Util::percent(
'linesExecutedPercent' => Util::percent(
$item['executedLines'],
$item['executableLines'],
false
),
'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent(
$item['executedLines'],
$item['executableLines'],
true
),
'linesExecutedPercentAsString' => $linesExecutedPercentAsString,
'numExecutedLines' => $item['executedLines'],
'numExecutableLines' => $item['executableLines'],
'testedMethodsPercent' => PHP_CodeCoverage_Util::percent(
'testedMethodsPercent' => Util::percent(
$numTestedMethods,
$numMethods,
false
),
'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent(
'testedMethodsPercentAsString' => Util::percent(
$numTestedMethods,
$numMethods,
true
),
'testedClassesPercent' => PHP_CodeCoverage_Util::percent(
'testedClassesPercent' => Util::percent(
$numTestedMethods == $numMethods ? 1 : 0,
1,
false
),
'testedClassesPercentAsString' => PHP_CodeCoverage_Util::percent(
'testedClassesPercentAsString' => Util::percent(
$numTestedMethods == $numMethods ? 1 : 0,
1,
true
),
'crap' => $item['crap']
)
]
);
foreach ($item['methods'] as $method) {
@@ -223,11 +218,12 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
}
/**
* @param array $functions
* @param Text_Template $template
* @param array $functions
* @param \Text_Template $template
*
* @return string
*/
protected function renderFunctionItems(array $functions, Text_Template $template)
protected function renderFunctionItems(array $functions, \Text_Template $template)
{
if (empty($functions)) {
return '';
@@ -246,57 +242,68 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
}
/**
* @param Text_Template $template
* @param \Text_Template $template
*
* @return string
*/
protected function renderFunctionOrMethodItem(Text_Template $template, array $item, $indent = '')
protected function renderFunctionOrMethodItem(\Text_Template $template, array $item, $indent = '')
{
$numTestedItems = $item['executedLines'] == $item['executableLines'] ? 1 : 0;
$numMethods = 0;
$numTestedMethods = 0;
if ($item['executableLines'] > 0) {
$numMethods = 1;
if ($item['executedLines'] === $item['executableLines']) {
$numTestedMethods = 1;
}
}
return $this->renderItemTemplate(
$template,
array(
'name' => sprintf(
[
'name' => \sprintf(
'%s<a href="#%d"><abbr title="%s">%s</abbr></a>',
$indent,
$item['startLine'],
htmlspecialchars($item['signature']),
\htmlspecialchars($item['signature']),
isset($item['functionName']) ? $item['functionName'] : $item['methodName']
),
'numMethods' => 1,
'numTestedMethods' => $numTestedItems,
'linesExecutedPercent' => PHP_CodeCoverage_Util::percent(
'numMethods' => $numMethods,
'numTestedMethods' => $numTestedMethods,
'linesExecutedPercent' => Util::percent(
$item['executedLines'],
$item['executableLines'],
false
),
'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent(
'linesExecutedPercentAsString' => Util::percent(
$item['executedLines'],
$item['executableLines'],
true
),
'numExecutedLines' => $item['executedLines'],
'numExecutableLines' => $item['executableLines'],
'testedMethodsPercent' => PHP_CodeCoverage_Util::percent(
$numTestedItems,
'testedMethodsPercent' => Util::percent(
$numTestedMethods,
1,
false
),
'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent(
$numTestedItems,
'testedMethodsPercentAsString' => Util::percent(
$numTestedMethods,
1,
true
),
'crap' => $item['crap']
)
]
);
}
/**
* @param PHP_CodeCoverage_Report_Node_File $node
* @param FileNode $node
*
* @return string
*/
protected function renderSource(PHP_CodeCoverage_Report_Node_File $node)
protected function renderSource(FileNode $node)
{
$coverageData = $node->getCoverageData();
$testData = $node->getTestData();
@@ -309,8 +316,8 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
$popoverContent = '';
$popoverTitle = '';
if (array_key_exists($i, $coverageData)) {
$numTests = count($coverageData[$i]);
if (\array_key_exists($i, $coverageData)) {
$numTests = ($coverageData[$i] ? \count($coverageData[$i]) : 0);
if ($coverageData[$i] === null) {
$trClass = ' class="warning"';
@@ -338,39 +345,46 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
switch ($testData[$test]['size']) {
case 'small':
$testCSS = ' class="covered-by-small-tests"';
break;
case 'medium':
$testCSS = ' class="covered-by-medium-tests"';
break;
default:
$testCSS = ' class="covered-by-large-tests"';
break;
}
break;
case 1:
case 2:
$testCSS = ' class="warning"';
break;
case 3:
$testCSS = ' class="danger"';
break;
case 4:
$testCSS = ' class="danger"';
break;
default:
$testCSS = '';
}
$popoverContent .= sprintf(
$popoverContent .= \sprintf(
'<li%s>%s</li>',
$testCSS,
htmlspecialchars($test)
\htmlspecialchars($test)
);
}
@@ -380,16 +394,16 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
}
if (!empty($popoverTitle)) {
$popover = sprintf(
$popover = \sprintf(
' data-title="%s" data-content="%s" data-placement="bottom" data-html="true"',
$popoverTitle,
htmlspecialchars($popoverContent)
\htmlspecialchars($popoverContent)
);
} else {
$popover = '';
}
$lines .= sprintf(
$lines .= \sprintf(
' <tr%s%s><td><div align="right"><a name="%d"></a><a href="#%d">%d</a></div></td><td class="codeLine">%s</td></tr>' . "\n",
$trClass,
$popover,
@@ -406,33 +420,34 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
}
/**
* @param string $file
* @param string $file
*
* @return array
*/
protected function loadFile($file)
{
$buffer = file_get_contents($file);
$tokens = token_get_all($buffer);
$result = array('');
$buffer = \file_get_contents($file);
$tokens = \token_get_all($buffer);
$result = [''];
$i = 0;
$stringFlag = false;
$fileEndsWithNewLine = substr($buffer, -1) == "\n";
$fileEndsWithNewLine = \substr($buffer, -1) == "\n";
unset($buffer);
foreach ($tokens as $j => $token) {
if (is_string($token)) {
if (\is_string($token)) {
if ($token === '"' && $tokens[$j - 1] !== '\\') {
$result[$i] .= sprintf(
$result[$i] .= \sprintf(
'<span class="string">%s</span>',
htmlspecialchars($token)
\htmlspecialchars($token)
);
$stringFlag = !$stringFlag;
} else {
$result[$i] .= sprintf(
$result[$i] .= \sprintf(
'<span class="keyword">%s</span>',
htmlspecialchars($token)
\htmlspecialchars($token)
);
}
@@ -441,19 +456,19 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
list($token, $value) = $token;
$value = str_replace(
array("\t", ' '),
array('&nbsp;&nbsp;&nbsp;&nbsp;', '&nbsp;'),
htmlspecialchars($value, $this->htmlspecialcharsFlags)
$value = \str_replace(
["\t", ' '],
['&nbsp;&nbsp;&nbsp;&nbsp;', '&nbsp;'],
\htmlspecialchars($value, $this->htmlspecialcharsFlags)
);
if ($value === "\n") {
$result[++$i] = '';
} else {
$lines = explode("\n", $value);
$lines = \explode("\n", $value);
foreach ($lines as $jj => $line) {
$line = trim($line);
$line = \trim($line);
if ($line !== '') {
if ($stringFlag) {
@@ -462,11 +477,13 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
switch ($token) {
case T_INLINE_HTML:
$colour = 'html';
break;
case T_COMMENT:
case T_DOC_COMMENT:
$colour = 'comment';
break;
case T_ABSTRACT:
@@ -526,6 +543,7 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
case T_WHILE:
case T_YIELD:
$colour = 'keyword';
break;
default:
@@ -533,7 +551,7 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
}
}
$result[$i] .= sprintf(
$result[$i] .= \sprintf(
'<span class="%s">%s</span>',
$colour,
$line
@@ -548,7 +566,7 @@ class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report
}
if ($fileEndsWithNewLine) {
unset($result[count($result)-1]);
unset($result[\count($result) - 1]);
}
return $result;

File diff suppressed because one or more lines are too long

View File

@@ -4,12 +4,12 @@
<meta charset="UTF-8">
<title>Dashboard for {{full_path}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{{path_to_root}}css/bootstrap.min.css" rel="stylesheet">
<link href="{{path_to_root}}css/nv.d3.min.css" rel="stylesheet">
<link href="{{path_to_root}}css/style.css" rel="stylesheet">
<link href="{{path_to_root}}.css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="{{path_to_root}}.css/nv.d3.min.css" rel="stylesheet" type="text/css">
<link href="{{path_to_root}}.css/style.css" rel="stylesheet" type="text/css">
<!--[if lt IE 9]>
<script src="{{path_to_root}}js/html5shiv.min.js"></script>
<script src="{{path_to_root}}js/respond.min.js"></script>
<script src="{{path_to_root}}.js/html5shiv.min.js"></script>
<script src="{{path_to_root}}.js/respond.min.js"></script>
<![endif]-->
</head>
<body>
@@ -134,15 +134,15 @@
<footer>
<hr/>
<p>
<small>Generated by <a href="http://github.com/sebastianbergmann/php-code-coverage" target="_top">PHP_CodeCoverage {{version}}</a> using <a href="{{runtime_link}}" target="_top">{{runtime_name}} {{runtime_version}}</a>{{generator}} at {{date}}.</small>
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
</p>
</footer>
</div>
<script src="{{path_to_root}}js/jquery.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}js/bootstrap.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}js/holder.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}js/d3.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}js/nv.d3.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/jquery.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/bootstrap.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/holder.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/d3.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/nv.d3.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
nv.addGraph(function() {
@@ -215,7 +215,7 @@ $(document).ready(function() {
.showDistY(true)
.showLegend(false)
.forceX([0, 100]);
chart.tooltipContent(function(key, y, e, graph) {
chart.tooltipContent(function(graph) {
return '<p>' + graph.point.class + '</p>';
});
@@ -239,7 +239,7 @@ $(document).ready(function() {
.showDistY(true)
.showLegend(false)
.forceX([0, 100]);
chart.tooltipContent(function(key, y, e, graph) {
chart.tooltipContent(function(graph) {
return '<p>' + graph.point.class + '</p>';
});

View File

@@ -4,11 +4,11 @@
<meta charset="UTF-8">
<title>Code Coverage for {{full_path}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{{path_to_root}}css/bootstrap.min.css" rel="stylesheet">
<link href="{{path_to_root}}css/style.css" rel="stylesheet">
<link href="{{path_to_root}}.css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="{{path_to_root}}.css/style.css" rel="stylesheet" type="text/css">
<!--[if lt IE 9]>
<script src="{{path_to_root}}js/html5shiv.min.js"></script>
<script src="{{path_to_root}}js/respond.min.js"></script>
<script src="{{path_to_root}}.js/html5shiv.min.js"></script>
<script src="{{path_to_root}}.js/respond.min.js"></script>
<![endif]-->
</head>
<body>
@@ -50,12 +50,12 @@
<span class="success"><strong>High</strong>: {{high_lower_bound}}% to 100%</span>
</p>
<p>
<small>Generated by <a href="http://github.com/sebastianbergmann/php-code-coverage" target="_top">PHP_CodeCoverage {{version}}</a> using <a href="{{runtime_link}}" target="_top">{{runtime_name}} {{runtime_version}}</a>{{generator}} at {{date}}.</small>
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
</p>
</footer>
</div>
<script src="{{path_to_root}}js/jquery.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}js/bootstrap.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}js/holder.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/jquery.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/bootstrap.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/holder.min.js" type="text/javascript"></script>
</body>
</html>

View File

@@ -4,11 +4,11 @@
<meta charset="UTF-8">
<title>Code Coverage for {{full_path}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{{path_to_root}}css/bootstrap.min.css" rel="stylesheet">
<link href="{{path_to_root}}css/style.css" rel="stylesheet">
<link href="{{path_to_root}}.css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="{{path_to_root}}.css/style.css" rel="stylesheet" type="text/css">
<!--[if lt IE 9]>
<script src="{{path_to_root}}js/html5shiv.min.js"></script>
<script src="{{path_to_root}}js/respond.min.js"></script>
<script src="{{path_to_root}}.js/html5shiv.min.js"></script>
<script src="{{path_to_root}}.js/respond.min.js"></script>
<![endif]-->
</head>
<body>
@@ -55,36 +55,14 @@
<span class="warning"><strong>Dead Code</strong></span>
</p>
<p>
<small>Generated by <a href="http://github.com/sebastianbergmann/php-code-coverage" target="_top">PHP_CodeCoverage {{version}}</a> using <a href="{{runtime_link}}" target="_top">{{runtime_name}} {{runtime_version}}</a>{{generator}} at {{date}}.</small>
<small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small>
</p>
<a title="Back to the top" id="toplink" href="#"><span class="glyphicon glyphicon-arrow-up"></span></a>
</footer>
</div>
<script src="{{path_to_root}}js/jquery.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}js/bootstrap.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}js/holder.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
var $window = $(window)
, $top_link = $('#toplink')
, $body = $('body, html')
, offset = $('#code').offset().top;
$top_link.hide().click(function(event) {
event.preventDefault();
$body.animate({scrollTop:0}, 800);
});
$window.scroll(function() {
if($window.scrollTop() > offset) {
$top_link.fadeIn();
} else {
$top_link.fadeOut();
}
}).scroll();
$('.popin').popover({trigger: 'hover'});
});
</script>
<script src="{{path_to_root}}.js/jquery.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/bootstrap.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/holder.min.js" type="text/javascript"></script>
<script src="{{path_to_root}}.js/file.js" type="text/javascript"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,61 @@
$(function() {
var $window = $(window)
, $top_link = $('#toplink')
, $body = $('body, html')
, offset = $('#code').offset().top
, hidePopover = function ($target) {
$target.data('popover-hover', false);
setTimeout(function () {
if (!$target.data('popover-hover')) {
$target.popover('hide');
}
}, 300);
};
$top_link.hide().click(function(event) {
event.preventDefault();
$body.animate({scrollTop:0}, 800);
});
$window.scroll(function() {
if($window.scrollTop() > offset) {
$top_link.fadeIn();
} else {
$top_link.fadeOut();
}
}).scroll();
$('.popin')
.popover({trigger: 'manual'})
.on({
'mouseenter.popover': function () {
var $target = $(this);
$target.data('popover-hover', true);
// popover already displayed
if ($target.next('.popover').length) {
return;
}
// show the popover
$target.popover('show');
// register mouse events on the popover
$target.next('.popover:not(.popover-initialized)')
.on({
'mouseenter': function () {
$target.data('popover-hover', true);
},
'mouseleave': function () {
hidePopover($target);
}
})
.addClass('popover-initialized');
},
'mouseleave.popover': function () {
hidePopover($(this));
}
});
});

View File

@@ -0,0 +1,326 @@
/**
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
;(function(window, document) {
/*jshint evil:true */
/** version */
var version = '3.7.3';
/** Preset options */
var options = window.html5 || {};
/** Used to skip problem elements */
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
/** Not all elements can be cloned in IE **/
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
/** Detect whether the browser supports default html5 styles */
var supportsHtml5Styles;
/** Name of the expando, to work with multiple documents or to re-shiv one document */
var expando = '_html5shiv';
/** The id for the the documents expando */
var expanID = 0;
/** Cached data for each document */
var expandoData = {};
/** Detect whether the browser supports unknown elements */
var supportsUnknownElements;
(function() {
try {
var a = document.createElement('a');
a.innerHTML = '<xyz></xyz>';
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
supportsHtml5Styles = ('hidden' in a);
supportsUnknownElements = a.childNodes.length == 1 || (function() {
// assign a false positive if unable to shiv
(document.createElement)('a');
var frag = document.createDocumentFragment();
return (
typeof frag.cloneNode == 'undefined' ||
typeof frag.createDocumentFragment == 'undefined' ||
typeof frag.createElement == 'undefined'
);
}());
} catch(e) {
// assign a false positive if detection fails => unable to shiv
supportsHtml5Styles = true;
supportsUnknownElements = true;
}
}());
/*--------------------------------------------------------------------------*/
/**
* Creates a style sheet with the given CSS text and adds it to the document.
* @private
* @param {Document} ownerDocument The document.
* @param {String} cssText The CSS text.
* @returns {StyleSheet} The style element.
*/
function addStyleSheet(ownerDocument, cssText) {
var p = ownerDocument.createElement('p'),
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
p.innerHTML = 'x<style>' + cssText + '</style>';
return parent.insertBefore(p.lastChild, parent.firstChild);
}
/**
* Returns the value of `html5.elements` as an array.
* @private
* @returns {Array} An array of shived element node names.
*/
function getElements() {
var elements = html5.elements;
return typeof elements == 'string' ? elements.split(' ') : elements;
}
/**
* Extends the built-in list of html5 elements
* @memberOf html5
* @param {String|Array} newElements whitespace separated list or array of new element names to shiv
* @param {Document} ownerDocument The context document.
*/
function addElements(newElements, ownerDocument) {
var elements = html5.elements;
if(typeof elements != 'string'){
elements = elements.join(' ');
}
if(typeof newElements != 'string'){
newElements = newElements.join(' ');
}
html5.elements = elements +' '+ newElements;
shivDocument(ownerDocument);
}
/**
* Returns the data associated to the given document
* @private
* @param {Document} ownerDocument The document.
* @returns {Object} An object of data.
*/
function getExpandoData(ownerDocument) {
var data = expandoData[ownerDocument[expando]];
if (!data) {
data = {};
expanID++;
ownerDocument[expando] = expanID;
expandoData[expanID] = data;
}
return data;
}
/**
* returns a shived element for the given nodeName and document
* @memberOf html5
* @param {String} nodeName name of the element
* @param {Document|DocumentFragment} ownerDocument The context document.
* @returns {Object} The shived element.
*/
function createElement(nodeName, ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createElement(nodeName);
}
if (!data) {
data = getExpandoData(ownerDocument);
}
var node;
if (data.cache[nodeName]) {
node = data.cache[nodeName].cloneNode();
} else if (saveClones.test(nodeName)) {
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
} else {
node = data.createElem(nodeName);
}
// Avoid adding some elements to fragments in IE < 9 because
// * Attributes like `name` or `type` cannot be set/changed once an element
// is inserted into a document/fragment
// * Link elements with `src` attributes that are inaccessible, as with
// a 403 response, will cause the tab/window to crash
// * Script elements appended to fragments will execute when their `src`
// or `text` property is set
return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
}
/**
* returns a shived DocumentFragment for the given document
* @memberOf html5
* @param {Document} ownerDocument The context document.
* @returns {Object} The shived DocumentFragment.
*/
function createDocumentFragment(ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createDocumentFragment();
}
data = data || getExpandoData(ownerDocument);
var clone = data.frag.cloneNode(),
i = 0,
elems = getElements(),
l = elems.length;
for(;i<l;i++){
clone.createElement(elems[i]);
}
return clone;
}
/**
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
* @private
* @param {Document|DocumentFragment} ownerDocument The document.
* @param {Object} data of the document.
*/
function shivMethods(ownerDocument, data) {
if (!data.cache) {
data.cache = {};
data.createElem = ownerDocument.createElement;
data.createFrag = ownerDocument.createDocumentFragment;
data.frag = data.createFrag();
}
ownerDocument.createElement = function(nodeName) {
//abort shiv
if (!html5.shivMethods) {
return data.createElem(nodeName);
}
return createElement(nodeName, ownerDocument, data);
};
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
'var n=f.cloneNode(),c=n.createElement;' +
'h.shivMethods&&(' +
// unroll the `createElement` calls
getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
data.createElem(nodeName);
data.frag.createElement(nodeName);
return 'c("' + nodeName + '")';
}) +
');return n}'
)(html5, data.frag);
}
/*--------------------------------------------------------------------------*/
/**
* Shivs the given document.
* @memberOf html5
* @param {Document} ownerDocument The document to shiv.
* @returns {Document} The shived document.
*/
function shivDocument(ownerDocument) {
if (!ownerDocument) {
ownerDocument = document;
}
var data = getExpandoData(ownerDocument);
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
data.hasCSS = !!addStyleSheet(ownerDocument,
// corrects block display not defined in IE6/7/8/9
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
// adds styling not present in IE6/7/8/9
'mark{background:#FF0;color:#000}' +
// hides non-rendered elements
'template{display:none}'
);
}
if (!supportsUnknownElements) {
shivMethods(ownerDocument, data);
}
return ownerDocument;
}
/*--------------------------------------------------------------------------*/
/**
* The `html5` object is exposed so that more elements can be shived and
* existing shiving can be detected on iframes.
* @type Object
* @example
*
* // options can be changed before the script is included
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
*/
var html5 = {
/**
* An array or space separated string of node names of the elements to shiv.
* @memberOf html5
* @type Array|String
*/
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
/**
* current version of html5shiv
*/
'version': version,
/**
* A flag to indicate that the HTML5 style sheet should be inserted.
* @memberOf html5
* @type Boolean
*/
'shivCSS': (options.shivCSS !== false),
/**
* Is equal to true if a browser supports creating unknown/HTML5 elements
* @memberOf html5
* @type boolean
*/
'supportsUnknownElements': supportsUnknownElements,
/**
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
* methods should be overwritten.
* @memberOf html5
* @type Boolean
*/
'shivMethods': (options.shivMethods !== false),
/**
* A string to describe the type of `html5` object ("default" or "default print").
* @memberOf html5
* @type String
*/
'type': 'default',
// shivs the document according to the specified `html5` object options
'shivDocument': shivDocument,
//creates a shived element
createElement: createElement,
//creates a shived documentFragment
createDocumentFragment: createDocumentFragment,
//extends list of elements
addElements: addElements
};
/*--------------------------------------------------------------------------*/
// expose html5
window.html5 = html5;
// shiv the document
shivDocument(document);
if(typeof module == 'object' && module.exports){
module.exports = html5;
}
}(typeof window !== "undefined" ? window : this, document));

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,59 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\RuntimeException;
/**
* Uses var_export() to write a SebastianBergmann\CodeCoverage\CodeCoverage object to a file.
*/
class PHP
{
/**
* @param CodeCoverage $coverage
* @param string $target
*
* @return string
*/
public function process(CodeCoverage $coverage, $target = null)
{
$filter = $coverage->filter();
$buffer = \sprintf(
'<?php
$coverage = new SebastianBergmann\CodeCoverage\CodeCoverage;
$coverage->setData(%s);
$coverage->setTests(%s);
$filter = $coverage->filter();
$filter->setWhitelistedFiles(%s);
return $coverage;',
\var_export($coverage->getData(true), 1),
\var_export($coverage->getTests(), 1),
\var_export($filter->getWhitelistedFiles(), 1)
);
if ($target !== null) {
if (@\file_put_contents($target, $buffer) === false) {
throw new RuntimeException(
\sprintf(
'Could not write to "%s',
$target
)
);
}
}
return $buffer;
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,30 +8,40 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Node\File;
use SebastianBergmann\CodeCoverage\Util;
/**
* Generates human readable output from an PHP_CodeCoverage object.
* Generates human readable output from a code coverage object.
*
* The output gets put into a text file our written to the CLI.
*
* @since Class available since Release 1.1.0
*/
class PHP_CodeCoverage_Report_Text
class Text
{
protected $lowUpperBound;
protected $highLowerBound;
protected $showUncoveredFiles;
protected $showOnlySummary;
private $lowUpperBound;
private $highLowerBound;
private $showUncoveredFiles;
private $showOnlySummary;
protected $colors = array(
private $colors = [
'green' => "\x1b[30;42m",
'yellow' => "\x1b[30;43m",
'red' => "\x1b[37;41m",
'header' => "\x1b[1;37;40m",
'reset' => "\x1b[0m",
'eol' => "\x1b[2K",
);
];
public function __construct($lowUpperBound, $highLowerBound, $showUncoveredFiles, $showOnlySummary)
/**
* @param int $lowUpperBound
* @param int $highLowerBound
* @param bool $showUncoveredFiles
* @param bool $showOnlySummary
*/
public function __construct($lowUpperBound = 50, $highLowerBound = 90, $showUncoveredFiles = false, $showOnlySummary = false)
{
$this->lowUpperBound = $lowUpperBound;
$this->highLowerBound = $highLowerBound;
@@ -40,24 +50,25 @@ class PHP_CodeCoverage_Report_Text
}
/**
* @param PHP_CodeCoverage $coverage
* @param bool $showColors
* @param CodeCoverage $coverage
* @param bool $showColors
*
* @return string
*/
public function process(PHP_CodeCoverage $coverage, $showColors = false)
public function process(CodeCoverage $coverage, $showColors = false)
{
$output = PHP_EOL . PHP_EOL;
$report = $coverage->getReport();
unset($coverage);
$colors = array(
$colors = [
'header' => '',
'classes' => '',
'methods' => '',
'lines' => '',
'reset' => '',
'eol' => ''
);
];
if ($showColors) {
$colors['classes'] = $this->getCoverageColor(
@@ -77,9 +88,9 @@ class PHP_CodeCoverage_Report_Text
$colors['eol'] = $this->colors['eol'];
}
$classes = sprintf(
$classes = \sprintf(
' Classes: %6s (%d/%d)',
PHP_CodeCoverage_Util::percent(
Util::percent(
$report->getNumTestedClassesAndTraits(),
$report->getNumClassesAndTraits(),
true
@@ -88,9 +99,9 @@ class PHP_CodeCoverage_Report_Text
$report->getNumClassesAndTraits()
);
$methods = sprintf(
$methods = \sprintf(
' Methods: %6s (%d/%d)',
PHP_CodeCoverage_Util::percent(
Util::percent(
$report->getNumTestedMethods(),
$report->getNumMethods(),
true
@@ -99,9 +110,9 @@ class PHP_CodeCoverage_Report_Text
$report->getNumMethods()
);
$lines = sprintf(
$lines = \sprintf(
' Lines: %6s (%d/%d)',
PHP_CodeCoverage_Util::percent(
Util::percent(
$report->getNumExecutedLines(),
$report->getNumExecutableLines(),
true
@@ -110,15 +121,15 @@ class PHP_CodeCoverage_Report_Text
$report->getNumExecutableLines()
);
$padding = max(array_map('strlen', array($classes, $methods, $lines)));
$padding = \max(\array_map('strlen', [$classes, $methods, $lines]));
if ($this->showOnlySummary) {
$title = 'Code Coverage Report Summary:';
$padding = max($padding, strlen($title));
$padding = \max($padding, \strlen($title));
$output .= $this->format($colors['header'], $padding, $title);
} else {
$date = date(' Y-m-d H:i:s', $_SERVER['REQUEST_TIME']);
$date = \date(' Y-m-d H:i:s', $_SERVER['REQUEST_TIME']);
$title = 'Code Coverage Report:';
$output .= $this->format($colors['header'], $padding, $title);
@@ -135,14 +146,14 @@ class PHP_CodeCoverage_Report_Text
return $output . PHP_EOL;
}
$classCoverage = array();
$classCoverage = [];
foreach ($report as $item) {
if (!$item instanceof PHP_CodeCoverage_Report_Node_File) {
if (!$item instanceof File) {
continue;
}
$classes = $item->getClassesAndTraits();
$classes = $item->getClassesAndTraits();
foreach ($classes as $className => $class) {
$classStatements = 0;
@@ -156,7 +167,7 @@ class PHP_CodeCoverage_Report_Text
}
$classMethods++;
$classStatements += $method['executableLines'];
$classStatements += $method['executableLines'];
$coveredClassStatements += $method['executedLines'];
if ($method['coverage'] == 100) {
$coveredMethods++;
@@ -171,18 +182,18 @@ class PHP_CodeCoverage_Report_Text
$namespace = '';
}
$classCoverage[$namespace . $className] = array(
$classCoverage[$namespace . $className] = [
'namespace' => $namespace,
'className ' => $className,
'methodsCovered' => $coveredMethods,
'methodCount' => $classMethods,
'statementsCovered' => $coveredClassStatements,
'statementCount' => $classStatements,
);
];
}
}
ksort($classCoverage);
\ksort($classCoverage);
$methodColor = '';
$linesColor = '';
@@ -199,7 +210,7 @@ class PHP_CodeCoverage_Report_Text
$output .= PHP_EOL . $fullQualifiedPath . PHP_EOL
. ' ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' '
. ' ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor
. ' ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor
;
}
}
@@ -209,7 +220,7 @@ class PHP_CodeCoverage_Report_Text
protected function getCoverageColor($numberOfCoveredElements, $totalNumberOfElements)
{
$coverage = PHP_CodeCoverage_Util::percent(
$coverage = Util::percent(
$numberOfCoveredElements,
$totalNumberOfElements
);
@@ -223,24 +234,24 @@ class PHP_CodeCoverage_Report_Text
return $this->colors['red'];
}
protected function printCoverageCounts($numberOfCoveredElements, $totalNumberOfElements, $presicion)
protected function printCoverageCounts($numberOfCoveredElements, $totalNumberOfElements, $precision)
{
$format = '%' . $presicion . 's';
$format = '%' . $precision . 's';
return PHP_CodeCoverage_Util::percent(
return Util::percent(
$numberOfCoveredElements,
$totalNumberOfElements,
true,
true
) .
' (' . sprintf($format, $numberOfCoveredElements) . '/' .
sprintf($format, $totalNumberOfElements) . ')';
' (' . \sprintf($format, $numberOfCoveredElements) . '/' .
\sprintf($format, $totalNumberOfElements) . ')';
}
private function format($color, $padding, $string)
{
$reset = $color ? $this->colors['reset'] : '';
return $color . str_pad($string, $padding) . $reset . PHP_EOL;
return $color . \str_pad($string, $padding) . $reset . PHP_EOL;
}
}

View File

@@ -0,0 +1,101 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report\Xml;
use SebastianBergmann\Environment\Runtime;
class BuildInformation
{
/**
* @var \DOMElement
*/
private $contextNode;
/**
* @param \DOMElement $contextNode
*/
public function __construct(\DOMElement $contextNode)
{
$this->contextNode = $contextNode;
}
/**
* @param Runtime $runtime
*/
public function setRuntimeInformation(Runtime $runtime)
{
$runtimeNode = $this->getNodeByName('runtime');
$runtimeNode->setAttribute('name', $runtime->getName());
$runtimeNode->setAttribute('version', $runtime->getVersion());
$runtimeNode->setAttribute('url', $runtime->getVendorUrl());
$driverNode = $this->getNodeByName('driver');
if ($runtime->isHHVM()) {
$driverNode->setAttribute('name', 'hhvm');
$driverNode->setAttribute('version', \constant('HHVM_VERSION'));
return;
}
if ($runtime->hasPHPDBGCodeCoverage()) {
$driverNode->setAttribute('name', 'phpdbg');
$driverNode->setAttribute('version', \constant('PHPDBG_VERSION'));
}
if ($runtime->hasXdebug()) {
$driverNode->setAttribute('name', 'xdebug');
$driverNode->setAttribute('version', \phpversion('xdebug'));
}
}
/**
* @param $name
*
* @return \DOMElement
*/
private function getNodeByName($name)
{
$node = $this->contextNode->getElementsByTagNameNS(
'http://schema.phpunit.de/coverage/1.0',
$name
)->item(0);
if (!$node) {
$node = $this->contextNode->appendChild(
$this->contextNode->ownerDocument->createElementNS(
'http://schema.phpunit.de/coverage/1.0',
$name
)
);
}
return $node;
}
/**
* @param \DateTime $date
*/
public function setBuildTime(\DateTime $date)
{
$this->contextNode->setAttribute('time', $date->format('D M j G:i:s T Y'));
}
/**
* @param string $phpUnitVersion
* @param string $coverageVersion
*/
public function setGeneratorVersions($phpUnitVersion, $coverageVersion)
{
$this->contextNode->setAttribute('phpunit', $phpUnitVersion);
$this->contextNode->setAttribute('coverage', $coverageVersion);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,18 +8,19 @@
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML_File_Coverage
namespace SebastianBergmann\CodeCoverage\Report\Xml;
use SebastianBergmann\CodeCoverage\RuntimeException;
class Coverage
{
/**
* @var XMLWriter
* @var \XMLWriter
*/
private $writer;
/**
* @var DOMElement
* @var \DOMElement
*/
private $contextNode;
@@ -28,11 +29,11 @@ class PHP_CodeCoverage_Report_XML_File_Coverage
*/
private $finalized = false;
public function __construct(DOMElement $context, $line)
public function __construct(\DOMElement $context, $line)
{
$this->contextNode = $context;
$this->writer = new XMLWriter();
$this->writer = new \XMLWriter();
$this->writer->openMemory();
$this->writer->startElementNs(null, $context->nodeName, 'http://schema.phpunit.de/coverage/1.0');
$this->writer->writeAttribute('nr', $line);
@@ -41,7 +42,7 @@ class PHP_CodeCoverage_Report_XML_File_Coverage
public function addTest($test)
{
if ($this->finalized) {
throw new PHP_CodeCoverage_Exception('Coverage Report already finalized');
throw new RuntimeException('Coverage Report already finalized');
}
$this->writer->startElement('covered');

View File

@@ -0,0 +1,15 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report\Xml;
class Directory extends Node
{
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,10 +8,17 @@
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML
namespace SebastianBergmann\CodeCoverage\Report\Xml;
use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Node\AbstractNode;
use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode;
use SebastianBergmann\CodeCoverage\Node\File as FileNode;
use SebastianBergmann\CodeCoverage\RuntimeException;
use SebastianBergmann\CodeCoverage\Version;
use SebastianBergmann\Environment\Runtime;
class Facade
{
/**
* @var string
@@ -19,13 +26,32 @@ class PHP_CodeCoverage_Report_XML
private $target;
/**
* @var PHP_CodeCoverage_Report_XML_Project
* @var Project
*/
private $project;
public function process(PHP_CodeCoverage $coverage, $target)
/**
* @var string
*/
private $phpUnitVersion;
/**
* @param string $version
*/
public function __construct($version)
{
if (substr($target, -1, 1) != DIRECTORY_SEPARATOR) {
$this->phpUnitVersion = $version;
}
/**
* @param CodeCoverage $coverage
* @param string $target
*
* @throws RuntimeException
*/
public function process(CodeCoverage $coverage, $target)
{
if (\substr($target, -1, 1) != DIRECTORY_SEPARATOR) {
$target .= DIRECTORY_SEPARATOR;
}
@@ -34,64 +60,69 @@ class PHP_CodeCoverage_Report_XML
$report = $coverage->getReport();
$this->project = new PHP_CodeCoverage_Report_XML_Project(
$this->project = new Project(
$coverage->getReport()->getName()
);
$this->setBuildInformation();
$this->processTests($coverage->getTests());
$this->processDirectory($report, $this->project);
$index = $this->project->asDom();
$index->formatOutput = true;
$index->preserveWhiteSpace = false;
$index->save($target . '/index.xml');
$this->saveDocument($this->project->asDom(), 'index');
}
private function initTargetDirectory($dir)
private function setBuildInformation()
{
if (file_exists($dir)) {
if (!is_dir($dir)) {
throw new PHP_CodeCoverage_Exception(
"'$dir' exists but is not a directory."
$buildNode = $this->project->getBuildInformation();
$buildNode->setRuntimeInformation(new Runtime());
$buildNode->setBuildTime(\DateTime::createFromFormat('U', $_SERVER['REQUEST_TIME']));
$buildNode->setGeneratorVersions($this->phpUnitVersion, Version::id());
}
/**
* @param string $directory
*/
protected function initTargetDirectory($directory)
{
if (\file_exists($directory)) {
if (!\is_dir($directory)) {
throw new RuntimeException(
"'$directory' exists but is not a directory."
);
}
if (!is_writable($dir)) {
throw new PHP_CodeCoverage_Exception(
"'$dir' exists but is not writable."
if (!\is_writable($directory)) {
throw new RuntimeException(
"'$directory' exists but is not writable."
);
}
} elseif (!@mkdir($dir, 0777, true)) {
throw new PHP_CodeCoverage_Exception(
"'$dir' could not be created."
} elseif (!@\mkdir($directory, 0777, true)) {
throw new RuntimeException(
"'$directory' could not be created."
);
}
}
private function processDirectory(PHP_CodeCoverage_Report_Node_Directory $directory, PHP_CodeCoverage_Report_XML_Node $context)
private function processDirectory(DirectoryNode $directory, Node $context)
{
$dirObject = $context->addDirectory($directory->getName());
$dirname = $directory->getName();
if ($this->project->getProjectSourceDirectory() === $dirname) {
$dirname = '/';
}
$dirObject = $context->addDirectory($dirname);
$this->setTotals($directory, $dirObject->getTotals());
foreach ($directory as $node) {
if ($node instanceof PHP_CodeCoverage_Report_Node_Directory) {
$this->processDirectory($node, $dirObject);
continue;
}
foreach ($directory->getDirectories() as $node) {
$this->processDirectory($node, $dirObject);
}
if ($node instanceof PHP_CodeCoverage_Report_Node_File) {
$this->processFile($node, $dirObject);
continue;
}
throw new PHP_CodeCoverage_Exception(
'Unknown node type for XML report'
);
foreach ($directory->getFiles() as $node) {
$this->processFile($node, $dirObject);
}
}
private function processFile(PHP_CodeCoverage_Report_Node_File $file, PHP_CodeCoverage_Report_XML_Directory $context)
private function processFile(FileNode $file, Directory $context)
{
$fileObject = $context->addFile(
$file->getName(),
@@ -100,9 +131,11 @@ class PHP_CodeCoverage_Report_XML
$this->setTotals($file, $fileObject->getTotals());
$fileReport = new PHP_CodeCoverage_Report_XML_File_Report(
$file->getName()
$path = \substr(
$file->getPath(),
\strlen($this->project->getProjectSourceDirectory())
);
$fileReport = new Report($path);
$this->setTotals($file, $fileReport->getTotals());
@@ -115,7 +148,7 @@ class PHP_CodeCoverage_Report_XML
}
foreach ($file->getCoverageData() as $line => $tests) {
if (!is_array($tests) || count($tests) == 0) {
if (!\is_array($tests) || \count($tests) === 0) {
continue;
}
@@ -128,17 +161,14 @@ class PHP_CodeCoverage_Report_XML
$coverage->finalize();
}
$this->initTargetDirectory(
$this->target . dirname($file->getId()) . '/'
$fileReport->getSource()->setSourceCode(
\file_get_contents($file->getPath())
);
$fileDom = $fileReport->asDom();
$fileDom->formatOutput = true;
$fileDom->preserveWhiteSpace = false;
$fileDom->save($this->target . $file->getId() . '.xml');
$this->saveDocument($fileReport->asDom(), $file->getId());
}
private function processUnit($unit, PHP_CodeCoverage_Report_XML_File_Report $report)
private function processUnit($unit, Report $report)
{
if (isset($unit['className'])) {
$unitObject = $report->getClassObject($unit['className']);
@@ -176,7 +206,7 @@ class PHP_CodeCoverage_Report_XML
}
}
private function processFunction($function, PHP_CodeCoverage_Report_XML_File_Report $report)
private function processFunction($function, Report $report)
{
$functionObject = $report->getFunctionObject($function['functionName']);
@@ -199,7 +229,7 @@ class PHP_CodeCoverage_Report_XML
}
}
private function setTotals(PHP_CodeCoverage_Report_Node $node, PHP_CodeCoverage_Report_XML_Totals $totals)
private function setTotals(AbstractNode $node, Totals $totals)
{
$loc = $node->getLinesOfCode();
@@ -231,4 +261,23 @@ class PHP_CodeCoverage_Report_XML
$node->getNumTestedFunctions()
);
}
/**
* @return string
*/
protected function getTargetDirectory()
{
return $this->target;
}
protected function saveDocument(\DOMDocument $document, $name)
{
$filename = \sprintf('%s/%s.xml', $this->getTargetDirectory(), $name);
$document->formatOutput = true;
$document->preserveWhiteSpace = false;
$this->initTargetDirectory(\dirname($filename));
$document->save($filename);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,27 +8,42 @@
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML_File
namespace SebastianBergmann\CodeCoverage\Report\Xml;
class File
{
/**
* @var DOMDocument
* @var \DOMDocument
*/
protected $dom;
private $dom;
/**
* @var DOMElement
* @var \DOMElement
*/
protected $contextNode;
private $contextNode;
public function __construct(DOMElement $context)
public function __construct(\DOMElement $context)
{
$this->dom = $context->ownerDocument;
$this->contextNode = $context;
}
/**
* @return \DOMElement
*/
protected function getContextNode()
{
return $this->contextNode;
}
/**
* @return \DOMDocument
*/
protected function getDomDocument()
{
return $this->dom;
}
public function getTotals()
{
$totalsContainer = $this->contextNode->firstChild;
@@ -42,7 +57,7 @@ class PHP_CodeCoverage_Report_XML_File
);
}
return new PHP_CodeCoverage_Report_XML_Totals($totalsContainer);
return new Totals($totalsContainer);
}
public function getLineCoverage($line)
@@ -68,6 +83,6 @@ class PHP_CodeCoverage_Report_XML_File
)
);
return new PHP_CodeCoverage_Report_XML_File_Coverage($lineNode, $line);
return new Coverage($lineNode, $line);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,17 +8,16 @@
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML_File_Method
namespace SebastianBergmann\CodeCoverage\Report\Xml;
class Method
{
/**
* @var DOMElement
* @var \DOMElement
*/
private $contextNode;
public function __construct(DOMElement $context, $name)
public function __construct(\DOMElement $context, $name)
{
$this->contextNode = $context;

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,27 +8,26 @@
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML_Node
namespace SebastianBergmann\CodeCoverage\Report\Xml;
class Node
{
/**
* @var DOMDocument
* @var \DOMDocument
*/
private $dom;
/**
* @var DOMElement
* @var \DOMElement
*/
private $contextNode;
public function __construct(DOMElement $context)
public function __construct(\DOMElement $context)
{
$this->setContextNode($context);
}
protected function setContextNode(DOMElement $context)
protected function setContextNode(\DOMElement $context)
{
$this->dom = $context->ownerDocument;
$this->contextNode = $context;
@@ -57,7 +56,7 @@ class PHP_CodeCoverage_Report_XML_Node
);
}
return new PHP_CodeCoverage_Report_XML_Totals($totalsContainer);
return new Totals($totalsContainer);
}
public function addDirectory($name)
@@ -70,7 +69,7 @@ class PHP_CodeCoverage_Report_XML_Node
$dirNode->setAttribute('name', $name);
$this->getContextNode()->appendChild($dirNode);
return new PHP_CodeCoverage_Report_XML_Directory($dirNode);
return new Directory($dirNode);
}
public function addFile($name, $href)
@@ -84,6 +83,6 @@ class PHP_CodeCoverage_Report_XML_Node
$fileNode->setAttribute('href', $href);
$this->getContextNode()->appendChild($fileNode);
return new PHP_CodeCoverage_Report_XML_File($fileNode);
return new File($fileNode);
}
}

View File

@@ -0,0 +1,95 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report\Xml;
class Project extends Node
{
/**
* @param string $directory
*/
public function __construct($directory)
{
$this->init();
$this->setProjectSourceDirectory($directory);
}
private function init()
{
$dom = new \DOMDocument();
$dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="http://schema.phpunit.de/coverage/1.0"><build/><project/></phpunit>');
$this->setContextNode(
$dom->getElementsByTagNameNS(
'http://schema.phpunit.de/coverage/1.0',
'project'
)->item(0)
);
}
private function setProjectSourceDirectory($name)
{
$this->getContextNode()->setAttribute('source', $name);
}
/**
* @return string
*/
public function getProjectSourceDirectory()
{
return $this->getContextNode()->getAttribute('source');
}
/**
* @return BuildInformation
*/
public function getBuildInformation()
{
$buildNode = $this->getDom()->getElementsByTagNameNS(
'http://schema.phpunit.de/coverage/1.0',
'build'
)->item(0);
if (!$buildNode) {
$buildNode = $this->getDom()->documentElement->appendChild(
$this->getDom()->createElementNS(
'http://schema.phpunit.de/coverage/1.0',
'build'
)
);
}
return new BuildInformation($buildNode);
}
public function getTests()
{
$testsNode = $this->getContextNode()->getElementsByTagNameNS(
'http://schema.phpunit.de/coverage/1.0',
'tests'
)->item(0);
if (!$testsNode) {
$testsNode = $this->getContextNode()->appendChild(
$this->getDom()->createElementNS(
'http://schema.phpunit.de/coverage/1.0',
'tests'
)
);
}
return new Tests($testsNode);
}
public function asDom()
{
return $this->getDom();
}
}

View File

@@ -0,0 +1,92 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report\Xml;
class Report extends File
{
public function __construct($name)
{
$dom = new \DOMDocument();
$dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="http://schema.phpunit.de/coverage/1.0"><file /></phpunit>');
$contextNode = $dom->getElementsByTagNameNS(
'http://schema.phpunit.de/coverage/1.0',
'file'
)->item(0);
parent::__construct($contextNode);
$this->setName($name);
}
private function setName($name)
{
$this->getContextNode()->setAttribute('name', \basename($name));
$this->getContextNode()->setAttribute('path', \dirname($name));
}
public function asDom()
{
return $this->getDomDocument();
}
public function getFunctionObject($name)
{
$node = $this->getContextNode()->appendChild(
$this->getDomDocument()->createElementNS(
'http://schema.phpunit.de/coverage/1.0',
'function'
)
);
return new Method($node, $name);
}
public function getClassObject($name)
{
return $this->getUnitObject('class', $name);
}
public function getTraitObject($name)
{
return $this->getUnitObject('trait', $name);
}
private function getUnitObject($tagName, $name)
{
$node = $this->getContextNode()->appendChild(
$this->getDomDocument()->createElementNS(
'http://schema.phpunit.de/coverage/1.0',
$tagName
)
);
return new Unit($node, $name);
}
public function getSource()
{
$source = $this->getContextNode()->getElementsByTagNameNS(
'http://schema.phpunit.de/coverage/1.0',
'source'
)->item(0);
if (!$source) {
$source = $this->getContextNode()->appendChild(
$this->getDomDocument()->createElementNS(
'http://schema.phpunit.de/coverage/1.0',
'source'
)
);
}
return new Source($source);
}
}

View File

@@ -0,0 +1,45 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage\Report\Xml;
use TheSeer\Tokenizer\NamespaceUri;
use TheSeer\Tokenizer\Tokenizer;
use TheSeer\Tokenizer\XMLSerializer;
class Source
{
/** @var \DOMElement */
private $context;
/**
* @param \DOMElement $context
*/
public function __construct(\DOMElement $context)
{
$this->context = $context;
}
/**
* @param string $source
*/
public function setSourceCode(string $source)
{
$context = $this->context;
$tokens = (new Tokenizer())->parse($source);
$srcDom = (new XMLSerializer(new NamespaceUri($context->namespaceURI)))->toDom($tokens);
$context->parentNode->replaceChild(
$context->ownerDocument->importNode($srcDom->documentElement, true),
$context
);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,23 +8,23 @@
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML_Tests
namespace SebastianBergmann\CodeCoverage\Report\Xml;
class Tests
{
private $contextNode;
private $codeMap = array(
private $codeMap = [
0 => 'PASSED', // PHPUnit_Runner_BaseTestRunner::STATUS_PASSED
1 => 'SKIPPED', // PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED
2 => 'INCOMPLETE', // PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE
3 => 'FAILURE', // PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE
4 => 'ERROR', // PHPUnit_Runner_BaseTestRunner::STATUS_ERROR
5 => 'RISKY' // PHPUnit_Runner_BaseTestRunner::STATUS_RISKY
);
5 => 'RISKY', // PHPUnit_Runner_BaseTestRunner::STATUS_RISKY
6 => 'WARNING' // PHPUnit_Runner_BaseTestRunner::STATUS_WARNING
];
public function __construct(DOMElement $context)
public function __construct(\DOMElement $context)
{
$this->contextNode = $context;
}
@@ -37,6 +37,7 @@ class PHP_CodeCoverage_Report_XML_Tests
'test'
)
);
$node->setAttribute('name', $test);
$node->setAttribute('size', $result['size']);
$node->setAttribute('result', (int) $result['status']);

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,42 +8,43 @@
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML_Totals
namespace SebastianBergmann\CodeCoverage\Report\Xml;
use SebastianBergmann\CodeCoverage\Util;
class Totals
{
/**
* @var DOMNode
* @var \DOMNode
*/
private $container;
/**
* @var DOMElement
* @var \DOMElement
*/
private $linesNode;
/**
* @var DOMElement
* @var \DOMElement
*/
private $methodsNode;
/**
* @var DOMElement
* @var \DOMElement
*/
private $functionsNode;
/**
* @var DOMElement
* @var \DOMElement
*/
private $classesNode;
/**
* @var DOMElement
* @var \DOMElement
*/
private $traitsNode;
public function __construct(DOMElement $container)
public function __construct(\DOMElement $container)
{
$this->container = $container;
$dom = $container->ownerDocument;
@@ -94,7 +95,7 @@ class PHP_CodeCoverage_Report_XML_Totals
$this->linesNode->setAttribute('executed', $executed);
$this->linesNode->setAttribute(
'percent',
PHP_CodeCoverage_Util::percent($executed, $executable, true)
$executable === 0 ? 0 : \sprintf('%01.2F', Util::percent($executed, $executable, false))
);
}
@@ -104,7 +105,7 @@ class PHP_CodeCoverage_Report_XML_Totals
$this->classesNode->setAttribute('tested', $tested);
$this->classesNode->setAttribute(
'percent',
PHP_CodeCoverage_Util::percent($tested, $count, true)
$count === 0 ? 0 : \sprintf('%01.2F', Util::percent($tested, $count, false))
);
}
@@ -114,7 +115,7 @@ class PHP_CodeCoverage_Report_XML_Totals
$this->traitsNode->setAttribute('tested', $tested);
$this->traitsNode->setAttribute(
'percent',
PHP_CodeCoverage_Util::percent($tested, $count, true)
$count === 0 ? 0 : \sprintf('%01.2F', Util::percent($tested, $count, false))
);
}
@@ -124,7 +125,7 @@ class PHP_CodeCoverage_Report_XML_Totals
$this->methodsNode->setAttribute('tested', $tested);
$this->methodsNode->setAttribute(
'percent',
PHP_CodeCoverage_Util::percent($tested, $count, true)
$count === 0 ? 0 : \sprintf('%01.2F', Util::percent($tested, $count, false))
);
}
@@ -134,7 +135,7 @@ class PHP_CodeCoverage_Report_XML_Totals
$this->functionsNode->setAttribute('tested', $tested);
$this->functionsNode->setAttribute(
'percent',
PHP_CodeCoverage_Util::percent($tested, $count, true)
$count === 0 ? 0 : \sprintf('%01.2F', Util::percent($tested, $count, false))
);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,17 +8,16 @@
* file that was distributed with this source code.
*/
/**
* @since Class available since Release 2.0.0
*/
class PHP_CodeCoverage_Report_XML_File_Unit
namespace SebastianBergmann\CodeCoverage\Report\Xml;
class Unit
{
/**
* @var DOMElement
* @var \DOMElement
*/
private $contextNode;
public function __construct(DOMElement $context, $name)
public function __construct(\DOMElement $context, $name)
{
$this->contextNode = $context;
@@ -92,6 +91,6 @@ class PHP_CodeCoverage_Report_XML_File_Unit
)
);
return new PHP_CodeCoverage_Report_XML_File_Method($node, $name);
return new Method($node, $name);
}
}

View File

@@ -1,6 +1,6 @@
<?php
/*
* This file is part of the PHP_CodeCoverage package.
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
@@ -8,17 +8,20 @@
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage;
/**
* Utility methods.
*
* @since Class available since Release 1.0.0
*/
class PHP_CodeCoverage_Util
class Util
{
/**
* @param float $a
* @param float $b
* @return float ($a / $b) * 100
* @param float $a
* @param float $b
* @param bool $asString
* @param bool $fixedWidth
*
* @return float|int|string
*/
public static function percent($a, $b, $asString = false, $fixedWidth = false)
{
@@ -26,20 +29,18 @@ class PHP_CodeCoverage_Util
return '';
}
$percent = 100;
if ($b > 0) {
$percent = ($a / $b) * 100;
} else {
$percent = 100;
}
if ($asString) {
if ($fixedWidth) {
return sprintf('%6.2F%%', $percent);
}
$format = $fixedWidth ? '%6.2F%%' : '%01.2F%%';
return sprintf('%01.2F%%', $percent);
} else {
return $percent;
return \sprintf($format, $percent);
}
return $percent;
}
}

View File

@@ -0,0 +1,31 @@
<?php
/*
* This file is part of the php-code-coverage package.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeCoverage;
use SebastianBergmann\Version as VersionId;
class Version
{
private static $version;
/**
* @return string
*/
public static function id()
{
if (self::$version === null) {
$version = new VersionId('5.3.2', \dirname(__DIR__));
self::$version = $version->getVersion();
}
return self::$version;
}
}