1<?php 2/* 3 * This file is part of the php-code-coverage package. 4 * 5 * (c) Sebastian Bergmann <sebastian@phpunit.de> 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11namespace SebastianBergmann\CodeCoverage\Report\Html; 12 13use SebastianBergmann\CodeCoverage\CodeCoverage; 14use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; 15use SebastianBergmann\CodeCoverage\RuntimeException; 16 17/** 18 * Generates an HTML report from a code coverage object. 19 */ 20class Facade 21{ 22 /** 23 * @var string 24 */ 25 private $templatePath; 26 27 /** 28 * @var string 29 */ 30 private $generator; 31 32 /** 33 * @var int 34 */ 35 private $lowUpperBound; 36 37 /** 38 * @var int 39 */ 40 private $highLowerBound; 41 42 /** 43 * Constructor. 44 * 45 * @param int $lowUpperBound 46 * @param int $highLowerBound 47 * @param string $generator 48 */ 49 public function __construct($lowUpperBound = 50, $highLowerBound = 90, $generator = '') 50 { 51 $this->generator = $generator; 52 $this->highLowerBound = $highLowerBound; 53 $this->lowUpperBound = $lowUpperBound; 54 $this->templatePath = __DIR__ . '/Renderer/Template/'; 55 } 56 57 /** 58 * @param CodeCoverage $coverage 59 * @param string $target 60 */ 61 public function process(CodeCoverage $coverage, $target) 62 { 63 $target = $this->getDirectory($target); 64 $report = $coverage->getReport(); 65 unset($coverage); 66 67 if (!isset($_SERVER['REQUEST_TIME'])) { 68 $_SERVER['REQUEST_TIME'] = time(); 69 } 70 71 $date = date('D M j G:i:s T Y', $_SERVER['REQUEST_TIME']); 72 73 $dashboard = new Dashboard( 74 $this->templatePath, 75 $this->generator, 76 $date, 77 $this->lowUpperBound, 78 $this->highLowerBound 79 ); 80 81 $directory = new Directory( 82 $this->templatePath, 83 $this->generator, 84 $date, 85 $this->lowUpperBound, 86 $this->highLowerBound 87 ); 88 89 $file = new File( 90 $this->templatePath, 91 $this->generator, 92 $date, 93 $this->lowUpperBound, 94 $this->highLowerBound 95 ); 96 97 $directory->render($report, $target . 'index.html'); 98 $dashboard->render($report, $target . 'dashboard.html'); 99 100 foreach ($report as $node) { 101 $id = $node->getId(); 102 103 if ($node instanceof DirectoryNode) { 104 if (!file_exists($target . $id)) { 105 mkdir($target . $id, 0777, true); 106 } 107 108 $directory->render($node, $target . $id . '/index.html'); 109 $dashboard->render($node, $target . $id . '/dashboard.html'); 110 } else { 111 $dir = dirname($target . $id); 112 113 if (!file_exists($dir)) { 114 mkdir($dir, 0777, true); 115 } 116 117 $file->render($node, $target . $id . '.html'); 118 } 119 } 120 121 $this->copyFiles($target); 122 } 123 124 /** 125 * @param string $target 126 */ 127 private function copyFiles($target) 128 { 129 $dir = $this->getDirectory($target . 'css'); 130 copy($this->templatePath . 'css/bootstrap.min.css', $dir . 'bootstrap.min.css'); 131 copy($this->templatePath . 'css/nv.d3.min.css', $dir . 'nv.d3.min.css'); 132 copy($this->templatePath . 'css/style.css', $dir . 'style.css'); 133 134 $dir = $this->getDirectory($target . 'fonts'); 135 copy($this->templatePath . 'fonts/glyphicons-halflings-regular.eot', $dir . 'glyphicons-halflings-regular.eot'); 136 copy($this->templatePath . 'fonts/glyphicons-halflings-regular.svg', $dir . 'glyphicons-halflings-regular.svg'); 137 copy($this->templatePath . 'fonts/glyphicons-halflings-regular.ttf', $dir . 'glyphicons-halflings-regular.ttf'); 138 copy($this->templatePath . 'fonts/glyphicons-halflings-regular.woff', $dir . 'glyphicons-halflings-regular.woff'); 139 copy($this->templatePath . 'fonts/glyphicons-halflings-regular.woff2', $dir . 'glyphicons-halflings-regular.woff2'); 140 141 $dir = $this->getDirectory($target . 'js'); 142 copy($this->templatePath . 'js/bootstrap.min.js', $dir . 'bootstrap.min.js'); 143 copy($this->templatePath . 'js/d3.min.js', $dir . 'd3.min.js'); 144 copy($this->templatePath . 'js/holder.min.js', $dir . 'holder.min.js'); 145 copy($this->templatePath . 'js/html5shiv.min.js', $dir . 'html5shiv.min.js'); 146 copy($this->templatePath . 'js/jquery.min.js', $dir . 'jquery.min.js'); 147 copy($this->templatePath . 'js/nv.d3.min.js', $dir . 'nv.d3.min.js'); 148 copy($this->templatePath . 'js/respond.min.js', $dir . 'respond.min.js'); 149 } 150 151 /** 152 * @param string $directory 153 * 154 * @return string 155 * 156 * @throws RuntimeException 157 */ 158 private function getDirectory($directory) 159 { 160 if (substr($directory, -1, 1) != DIRECTORY_SEPARATOR) { 161 $directory .= DIRECTORY_SEPARATOR; 162 } 163 164 if (is_dir($directory)) { 165 return $directory; 166 } 167 168 if (@mkdir($directory, 0777, true)) { 169 return $directory; 170 } 171 172 throw new RuntimeException( 173 sprintf( 174 'Directory "%s" does not exist.', 175 $directory 176 ) 177 ); 178 } 179} 180