3 * This file is part of the PHP_CodeCoverage package.
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
12 * Factory for PHP_CodeCoverage_Report_Node_* object graphs.
14 * @since Class available since Release 1.1.0
16 class PHP_CodeCoverage_Report_Factory
19 * @param PHP_CodeCoverage $coverage
20 * @return PHP_CodeCoverage_Report_Node_Directory
22 public function create(PHP_CodeCoverage $coverage)
24 $files = $coverage->getData();
25 $commonPath = $this->reducePaths($files);
26 $root = new PHP_CodeCoverage_Report_Node_Directory(
33 $this->buildDirectoryStructure($files),
34 $coverage->getTests(),
35 $coverage->getCacheTokens()
42 * @param PHP_CodeCoverage_Report_Node_Directory $root
45 * @param bool $cacheTokens
47 private function addItems(PHP_CodeCoverage_Report_Node_Directory $root, array $items, array $tests, $cacheTokens)
49 foreach ($items as $key => $value) {
50 if (substr($key, -2) == '/f') {
51 $key = substr($key, 0, -2);
53 if (file_exists($root->getPath() . DIRECTORY_SEPARATOR . $key)) {
54 $root->addFile($key, $value, $tests, $cacheTokens);
57 $child = $root->addDirectory($key);
58 $this->addItems($child, $value, $tests, $cacheTokens);
64 * Builds an array representation of the directory structure.
71 * [Money.php] => Array
76 * [MoneyBag.php] => Array
90 * [Money.php] => Array
95 * [MoneyBag.php] => Array
103 * @param array $files
106 private function buildDirectoryStructure($files)
110 foreach ($files as $path => $file) {
111 $path = explode('/', $path);
115 for ($i = 0; $i < $max; $i++) {
116 if ($i == ($max - 1)) {
122 $pointer = &$pointer[$path[$i] . $type];
132 * Reduces the paths by cutting the longest common start path.
139 * [/home/sb/Money/Money.php] => Array
144 * [/home/sb/Money/MoneyBag.php] => Array
156 * [Money.php] => Array
161 * [MoneyBag.php] => Array
168 * @param array $files
171 private function reducePaths(&$files)
178 $paths = array_keys($files);
180 if (count($files) == 1) {
181 $commonPath = dirname($paths[0]) . '/';
182 $files[basename($paths[0])] = $files[$paths[0]];
184 unset($files[$paths[0]]);
189 $max = count($paths);
191 for ($i = 0; $i < $max; $i++) {
192 // strip phar:// prefixes
193 if (strpos($paths[$i], 'phar://') === 0) {
194 $paths[$i] = substr($paths[$i], 7);
195 $paths[$i] = strtr($paths[$i], '/', DIRECTORY_SEPARATOR);
197 $paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]);
199 if (empty($paths[$i][0])) {
200 $paths[$i][0] = DIRECTORY_SEPARATOR;
205 $max = count($paths);
208 for ($i = 0; $i < $max - 1; $i++) {
209 if (!isset($paths[$i][0]) ||
210 !isset($paths[$i+1][0]) ||
211 $paths[$i][0] != $paths[$i+1][0]) {
218 $commonPath .= $paths[0][0];
220 if ($paths[0][0] != DIRECTORY_SEPARATOR) {
221 $commonPath .= DIRECTORY_SEPARATOR;
224 for ($i = 0; $i < $max; $i++) {
225 array_shift($paths[$i]);
230 $original = array_keys($files);
231 $max = count($original);
233 for ($i = 0; $i < $max; $i++) {
234 $files[implode('/', $paths[$i])] = $files[$original[$i]];
235 unset($files[$original[$i]]);
240 return substr($commonPath, 0, -1);