Overview

Namespaces

  • Budovy
  • Kdyby
    • BootstrapFormRenderer
      • DI
      • Latte
  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Diagnostics
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
      • Diagnostics
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • PhpGenerator
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
  • NetteModule
  • Nextras
    • Datagrid
  • None
  • PHP
  • Tester
    • CodeCoverage
    • Runner
      • Output
  • Vodacek
    • Forms
      • Controls
  • WebLoader
    • Filter
    • Nette

Classes

  • Collector
  • ReportGenerator
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Tester.
  5:  * Copyright (c) 2009 David Grudl (http://davidgrudl.com)
  6:  */
  7: 
  8: namespace Tester\CodeCoverage;
  9: 
 10: 
 11: /**
 12:  * Code coverage report generator.
 13:  *
 14:  * @author     David Grudl
 15:  * @author     Patrik Votoček
 16:  * @package    Nette\Test
 17:  */
 18: class ReportGenerator
 19: {
 20:     /** @var array */
 21:     public $acceptFiles = array('php', 'phpc', 'phpt', 'phtml');
 22: 
 23:     /** @var array */
 24:     private $data;
 25: 
 26:     /** @var string */
 27:     private $sourceDir;
 28: 
 29:     /** @var string */
 30:     private $title;
 31: 
 32:     /** @var array */
 33:     private $files = array();
 34: 
 35:     /** @var int */
 36:     private $totalSum = 0;
 37: 
 38:     /** @var int */
 39:     private $coveredSum = 0;
 40: 
 41:     /** @var array */
 42:     public static $classes = array(
 43:         1 => 't', // tested
 44:         -1 => 'u', // untested
 45:         -2 => 'dead', // dead code
 46:     );
 47: 
 48: 
 49:     /**
 50:      * @param string  path to coverage.dat file
 51:      * @param string  path to source files
 52:      */
 53:     public function __construct($file, $sourceDir, $title = NULL)
 54:     {
 55:         if (!is_file($file)) {
 56:             throw new \Exception("File '$file' is missing.");
 57:         }
 58: 
 59:         $this->data = @unserialize(file_get_contents($file));
 60:         if (!is_array($this->data)) {
 61:             throw new \Exception("Content of file '$file' is invalid.");
 62:         }
 63: 
 64:         if (!$sourceDir) {
 65:             $sourceDir = key($this->data);
 66:             for ($i = 0; $i < strlen($sourceDir); $i++) {
 67:                 foreach ($this->data as $s => $foo) {
 68:                     if (!isset($s[$i]) || $sourceDir[$i] !== $s[$i]) {
 69:                         $sourceDir = substr($sourceDir, 0, $i);
 70:                         break 2;
 71:                     }
 72:                 }
 73:             }
 74:             $sourceDir = dirname($sourceDir . 'x');
 75: 
 76:         } elseif (!is_dir($sourceDir)) {
 77:             throw new \Exception("Directory '$sourceDir' is missing.");
 78:         }
 79: 
 80:         $this->sourceDir = realpath($sourceDir) . DIRECTORY_SEPARATOR;
 81:         $this->title = $title;
 82:     }
 83: 
 84: 
 85:     public function render($file = NULL)
 86:     {
 87:         $this->setupHighlight();
 88:         $this->parse();
 89: 
 90:         $title = $this->title;
 91:         $classes = self::$classes;
 92:         $files = $this->files;
 93:         $totalSum = $this->totalSum;
 94:         $coveredSum = $this->coveredSum;
 95: 
 96:         $handle = $file ? @fopen($file, 'w') : STDOUT;
 97:         if (!$handle) {
 98:             throw new \Exception("Unable to write to file '$file'.");
 99:         }
100:         ob_start(function($buffer) use ($handle) { fwrite($handle, $buffer); }, 4096);
101:         include __DIR__ . '/template.phtml';
102:         ob_end_flush();
103:     }
104: 
105: 
106:     private function setupHighlight()
107:     {
108:         ini_set('highlight.comment', '#999; font-style: italic');
109:         ini_set('highlight.default', '#000');
110:         ini_set('highlight.html', '#06B');
111:         ini_set('highlight.keyword', '#D24; font-weight: bold');
112:         ini_set('highlight.string', '#080');
113:     }
114: 
115: 
116:     private function parse()
117:     {
118:         if (count($this->files) > 0) {
119:             return;
120:         }
121: 
122:         $this->files = array();
123:         foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->sourceDir)) as $entry) {
124:             if (substr($entry->getBasename(), 0, 1) === '.'  // . or .. or .gitignore
125:                 || !in_array(pathinfo($entry, PATHINFO_EXTENSION), $this->acceptFiles))
126:             {
127:                 continue;
128:             }
129:             $entry = (string) $entry;
130: 
131:             $coverage = $covered = $total = 0;
132:             $loaded = isset($this->data[$entry]);
133:             $lines = array();
134:             if ($loaded) {
135:                 $lines = $this->data[$entry];
136:                 foreach ($lines as $flag) {
137:                     if ($flag >= -1) {
138:                         $total++;
139:                     }
140:                     if ($flag >= 1) {
141:                         $covered++;
142:                     }
143:                 }
144:                 $coverage = round($covered * 100 / $total);
145:                 $this->totalSum += $total;
146:                 $this->coveredSum += $covered;
147:             }
148: 
149:             $light = $total ? $total < 5 : count(file($entry)) < 50;
150:             $this->files[] = (object) array(
151:                 'name' => str_replace($this->sourceDir, '', $entry),
152:                 'file' => $entry,
153:                 'lines' => $lines,
154:                 'coverage' => $coverage,
155:                 'total' => $total,
156:                 'class' => $light ? 'light' : ($loaded ? NULL : 'not-loaded'),
157:             );
158:         }
159:     }
160: }
161: 
API documentation generated by ApiGen 2.8.0