Version 1
[yaffs-website] / vendor / phpunit / php-code-coverage / src / CodeCoverage / Report / Factory.php
diff --git a/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/Factory.php b/vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/Factory.php
new file mode 100644 (file)
index 0000000..b28964e
--- /dev/null
@@ -0,0 +1,242 @@
+<?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_Report_Node_* object graphs.
+ *
+ * @since Class available since Release 1.1.0
+ */
+class PHP_CodeCoverage_Report_Factory
+{
+    /**
+     * @param  PHP_CodeCoverage                       $coverage
+     * @return PHP_CodeCoverage_Report_Node_Directory
+     */
+    public function create(PHP_CodeCoverage $coverage)
+    {
+        $files      = $coverage->getData();
+        $commonPath = $this->reducePaths($files);
+        $root       = new PHP_CodeCoverage_Report_Node_Directory(
+            $commonPath,
+            null
+        );
+
+        $this->addItems(
+            $root,
+            $this->buildDirectoryStructure($files),
+            $coverage->getTests(),
+            $coverage->getCacheTokens()
+        );
+
+        return $root;
+    }
+
+    /**
+     * @param PHP_CodeCoverage_Report_Node_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)
+    {
+        foreach ($items as $key => $value) {
+            if (substr($key, -2) == '/f') {
+                $key = substr($key, 0, -2);
+
+                if (file_exists($root->getPath() . DIRECTORY_SEPARATOR . $key)) {
+                    $root->addFile($key, $value, $tests, $cacheTokens);
+                }
+            } else {
+                $child = $root->addDirectory($key);
+                $this->addItems($child, $value, $tests, $cacheTokens);
+            }
+        }
+    }
+
+    /**
+     * Builds an array representation of the directory structure.
+     *
+     * For instance,
+     *
+     * <code>
+     * Array
+     * (
+     *     [Money.php] => Array
+     *         (
+     *             ...
+     *         )
+     *
+     *     [MoneyBag.php] => Array
+     *         (
+     *             ...
+     *         )
+     * )
+     * </code>
+     *
+     * is transformed into
+     *
+     * <code>
+     * Array
+     * (
+     *     [.] => Array
+     *         (
+     *             [Money.php] => Array
+     *                 (
+     *                     ...
+     *                 )
+     *
+     *             [MoneyBag.php] => Array
+     *                 (
+     *                     ...
+     *                 )
+     *         )
+     * )
+     * </code>
+     *
+     * @param  array $files
+     * @return array
+     */
+    private function buildDirectoryStructure($files)
+    {
+        $result = array();
+
+        foreach ($files as $path => $file) {
+            $path    = explode('/', $path);
+            $pointer = &$result;
+            $max     = count($path);
+
+            for ($i = 0; $i < $max; $i++) {
+                if ($i == ($max - 1)) {
+                    $type = '/f';
+                } else {
+                    $type = '';
+                }
+
+                $pointer = &$pointer[$path[$i] . $type];
+            }
+
+            $pointer = $file;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Reduces the paths by cutting the longest common start path.
+     *
+     * For instance,
+     *
+     * <code>
+     * Array
+     * (
+     *     [/home/sb/Money/Money.php] => Array
+     *         (
+     *             ...
+     *         )
+     *
+     *     [/home/sb/Money/MoneyBag.php] => Array
+     *         (
+     *             ...
+     *         )
+     * )
+     * </code>
+     *
+     * is reduced to
+     *
+     * <code>
+     * Array
+     * (
+     *     [Money.php] => Array
+     *         (
+     *             ...
+     *         )
+     *
+     *     [MoneyBag.php] => Array
+     *         (
+     *             ...
+     *         )
+     * )
+     * </code>
+     *
+     * @param  array  $files
+     * @return string
+     */
+    private function reducePaths(&$files)
+    {
+        if (empty($files)) {
+            return '.';
+        }
+
+        $commonPath = '';
+        $paths      = array_keys($files);
+
+        if (count($files) == 1) {
+            $commonPath                 = dirname($paths[0]) . '/';
+            $files[basename($paths[0])] = $files[$paths[0]];
+
+            unset($files[$paths[0]]);
+
+            return $commonPath;
+        }
+
+        $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);
+            }
+            $paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]);
+
+            if (empty($paths[$i][0])) {
+                $paths[$i][0] = DIRECTORY_SEPARATOR;
+            }
+        }
+
+        $done = false;
+        $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]) {
+                    $done = true;
+                    break;
+                }
+            }
+
+            if (!$done) {
+                $commonPath .= $paths[0][0];
+
+                if ($paths[0][0] != DIRECTORY_SEPARATOR) {
+                    $commonPath .= DIRECTORY_SEPARATOR;
+                }
+
+                for ($i = 0; $i < $max; $i++) {
+                    array_shift($paths[$i]);
+                }
+            }
+        }
+
+        $original = array_keys($files);
+        $max      = count($original);
+
+        for ($i = 0; $i < $max; $i++) {
+            $files[implode('/', $paths[$i])] = $files[$original[$i]];
+            unset($files[$original[$i]]);
+        }
+
+        ksort($files);
+
+        return substr($commonPath, 0, -1);
+    }
+}