--- /dev/null
+<?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
+ )
+ );
+ }
+}