<commit_before><?php
/**
 * Humbug
 *
 * @category   Humbug
 * @package    Humbug
 * @copyright  Copyright (c) 2015 <NAME> (http://blog.astrumfutura.com)
 * @license    https://github.com/padraic/humbug/blob/master/LICENSE New BSD License
 */

namespace Humbug\Adapter\Phpunit;

use Humbug\Adapter\Phpunit\XmlConfiguration\AcceleratorListener;
use Humbug\Adapter\Phpunit\XmlConfiguration\FastestFirstFilter;
use Humbug\Adapter\Phpunit\XmlConfiguration\FilterListener;
use Humbug\Adapter\Phpunit\XmlConfiguration\IncludeOnlyFilter;
use Humbug\Adapter\Phpunit\XmlConfiguration\TimeCollectorListener;
use Humbug\Adapter\Phpunit\XmlConfiguration\Visitor;
use Humbug\Container;
use Humbug\Exception\RuntimeException;
use Humbug\Exception\InvalidArgumentException;

class XmlConfiguration
{
    private static $hasBootstrap;

    /**
     *
     * @var \DOMDocument
     */
    private $dom;

    /**
     * @var \DOMXPath
     */
    private $xpath;

    /**
     * @var \DOMElement
     */
    private $rootElement;

    public function __construct(\DOMDocument $dom)
    {
        if (!$dom->documentElement) {
            throw new \LogicException('No document element present. Document should not be empty!');
        }

        $this->dom = $dom;
        $this->xpath = new \DOMXPath($this->dom);
        $this->rootElement = $this->dom->documentElement;
    }

    /**
     * Wrangle XML to create a PHPUnit configuration, based on the original, that
     * allows for more control over what tests are run, allows JUnit logging,
     * and ensures that Code Coverage (for Humbug use) whitelists all of the
     * relevant source code.
     *
     *
     * @return string
     */
    public static function assemble(Container $container, $firstRun = false, array $testSuites = [])
    {
        self::$hasBootstrap = false;

        $configurationDir = self::resolveConfigurationDir($container);

        $configurationFile = (new ConfigurationLocator())->locate($configurationDir);

        if (!empty($configurationDir)) {
            $configurationDir .= '/';
        }

        $dom = (new ConfigurationLoader())->load($configurationFile);

        $xmlConfiguration = new XmlConfiguration($dom);

        if ($xmlConfiguration->hasBootstrap()) {
            self::$hasBootstrap = true;
            $bootstrap = $xmlConfiguration->getBootstrap();
            $path = self::makeAbsolutePath($bootstrap, $configurationDir);

            //@todo Get rid off this side effect...
            $container->setBootstrap($path);
        }

        $xmlConfiguration->setBootstrap(self::getNewBootstrapPath());
        $xmlConfiguration->turnOffCacheTokens();

        $xmlConfiguration->cleanupLoggers();
        $xmlConfiguration->cleanupFilters();
        $xmlConfiguration->cleanupListeners();

        $xmlConfiguration->addListener(new AcceleratorListener());

        /**
         * On first runs collect a test log and also generate code coverage
         */
        if ($firstRun === true) {
            $xmlConfiguration->addLogger('coverage-php', $container->getCacheDirectory() . '/coverage.humbug.php');
            $xmlConfiguration->addLogger('coverage-text', $container->getCacheDirectory() . '/coverage.humbug.txt');

            $srcList = $container->getSourceList();

            $whiteListSrc = isset($srcList->directories) ? self::getRealPathList($srcList->directories) : [];
            $excludeDirs = isset($srcList->excludes) ? self::getRealPathList($srcList->excludes) : [];

            $xmlConfiguration->addWhiteListFilter($whiteListSrc, $excludeDirs);

            $xmlConfiguration->addListener(new TimeCollectorListener(self::getPathToTimeCollectorFile($container)));
        } else {
            $filterListener = new FilterListener([
                new IncludeOnlyFilter($testSuites),
                new FastestFirstFilter(self::getPathToTimeCollectorFile($container))
            ]);
            $xmlConfiguration->addListener($filterListener);
        }

        $xpath = new \DOMXPath($dom);

        $suites = $xpath->query('/phpunit/testsuites/testsuite');
        foreach ($suites as $suite) {
            // DOMNodeList's Traversable implementation is a bit unpredictable.
            // Iterate over the child nodes using a for loop rather than a
            // foreach so that we can append new children without these being
            // iterated over again.
            $length = $suite->childNodes->length;
            for ($i = 0; $i < $length; $i++) {
                $node = $suite->childNodes->item($i);
                if ($node instanceof \DOMElement && $node->tagName == 'exclude') {
                    $node->nodeValue = self::makeAbsolutePath($node->nodeValue, $configurationDir);
                }
            }
        }

        /**
         * Set any remaining file & directory references to realpaths
         */
        $directories = $xpath->query('//directory');
        foreach ($directories as $directory) {
            $directory->nodeValue = self::makeAbsolutePath($directory->nodeValue, $configurationDir);
        }
        $files = $xpath->query('//file');
        foreach ($files as $file) {
            $file->nodeValue = self::makeAbsolutePath($file->nodeValue, $configurationDir);
        }

        $suite1 = $xpath->query('/phpunit/testsuites/testsuite')->item(0);
        if (is_a($suite1, 'DOMElement')) {
            self::handleSuite($suite1, $configurationFile, $container, $dom);
        }
        
        $saveFile = $container->getCacheDirectory() . '/phpunit.humbug.xml';
        $dom->save($saveFile);

        return $saveFile;
    }

    private static function handleSuite(\DOMElement $suite, $configFile, Container $container, \DOMDocument $dom)
    {
        foreach ($suite->childNodes as $child) {
            // phpunit.xml may omit bootstrap location but grab it automatically - include explicitly
            if (self::$hasBootstrap === false && $child instanceof \DOMElement && $child->tagName == 'directory') {<commit_msg>Making absolute path from suite/exclude node refactored<commit_after><?php
/**
 * Humbug
 *
 * @category   Humbug
 * @package    Humbug
 * @copyright  Copyright (c) 2015 <NAME> (http://blog.astrumfutura.com)
 * @license    https://github.com/padraic/humbug/blob/master/LICENSE New BSD License
 */

namespace Humbug\Adapter\Phpunit;

use Humbug\Adapter\Phpunit\XmlConfiguration\AcceleratorListener;
use Humbug\Adapter\Phpunit\XmlConfiguration\FastestFirstFilter;
use Humbug\Adapter\Phpunit\XmlConfiguration\FilterListener;
use Humbug\Adapter\Phpunit\XmlConfiguration\IncludeOnlyFilter;
use Humbug\Adapter\Phpunit\XmlConfiguration\TimeCollectorListener;
use Humbug\Adapter\Phpunit\XmlConfiguration\Visitor;
use Humbug\Container;
use Humbug\Exception\RuntimeException;
use Humbug\Exception\InvalidArgumentException;

class XmlConfiguration
{
    private static $hasBootstrap;

    /**
     *
     * @var \DOMDocument
     */
    private $dom;

    /**
     * @var \DOMXPath
     */
    private $xpath;

    /**
     * @var \DOMElement
     */
    private $rootElement;

    public function __construct(\DOMDocument $dom)
    {
        if (!$dom->documentElement) {
            throw new \LogicException('No document element present. Document should not be empty!');
        }

        $this->dom = $dom;
        $this->xpath = new \DOMXPath($this->dom);
        $this->rootElement = $this->dom->documentElement;
    }

    /**
     * Wrangle XML to create a PHPUnit configuration, based on the original, that
     * allows for more control over what tests are run, allows JUnit logging,
     * and ensures that Code Coverage (for Humbug use) whitelists all of the
     * relevant source code.
     *
     *
     * @return string
     */
    public static function assemble(Container $container, $firstRun = false, array $testSuites = [])
    {
        self::$hasBootstrap = false;

        $configurationDir = self::resolveConfigurationDir($container);

        $configurationFile = (new ConfigurationLocator())->locate($configurationDir);

        if (!empty($configurationDir)) {
            $configurationDir .= '/';
        }

        $dom = (new ConfigurationLoader())->load($configurationFile);

        $xmlConfiguration = new XmlConfiguration($dom);

        if ($xmlConfiguration->hasBootstrap()) {
            self::$hasBootstrap = true;
            $bootstrap = $xmlConfiguration->getBootstrap();
            $path = self::makeAbsolutePath($bootstrap, $configurationDir);

            //@todo Get rid off this side effect...
            $container->setBootstrap($path);
        }

        $xmlConfiguration->setBootstrap(self::getNewBootstrapPath());
        $xmlConfiguration->turnOffCacheTokens();

        $xmlConfiguration->cleanupLoggers();
        $xmlConfiguration->cleanupFilters();
        $xmlConfiguration->cleanupListeners();

        $xmlConfiguration->addListener(new AcceleratorListener());

        /**
         * On first runs collect a test log and also generate code coverage
         */
        if ($firstRun === true) {
            $xmlConfiguration->addLogger('coverage-php', $container->getCacheDirectory() . '/coverage.humbug.php');
            $xmlConfiguration->addLogger('coverage-text', $container->getCacheDirectory() . '/coverage.humbug.txt');

            $srcList = $container->getSourceList();

            $whiteListSrc = isset($srcList->directories) ? self::getRealPathList($srcList->directories) : [];
            $excludeDirs = isset($srcList->excludes) ? self::getRealPathList($srcList->excludes) : [];

            $xmlConfiguration->addWhiteListFilter($whiteListSrc, $excludeDirs);

            $xmlConfiguration->addListener(new TimeCollectorListener(self::getPathToTimeCollectorFile($container)));
        } else {
            $filterListener = new FilterListener([
                new IncludeOnlyFilter($testSuites),
                new FastestFirstFilter(self::getPathToTimeCollectorFile($container))
            ]);
            $xmlConfiguration->addListener($filterListener);
        }

        $xpath = new \DOMXPath($dom);

        $suitesExcludes = $xpath->query('/phpunit/testsuites/testsuite/exclude');
        foreach ($suitesExcludes as $exclude) {
            $exclude->nodeValue = self::makeAbsolutePath($exclude->nodeValue, $configurationDir);
        }
        /**
         * Set any remaining file & directory references to realpaths
         */
        $directories = $xpath->query('//directory');
        foreach ($directories as $directory) {
            $directory->nodeValue = self::makeAbsolutePath($directory->nodeValue, $configurationDir);
        }
        $files = $xpath->query('//file');
        foreach ($files as $file) {
            $file->nodeValue = self::makeAbsolutePath($file->nodeValue, $configurationDir);
        }

        $suite1 = $xpath->query('/phpunit/testsuites/testsuite')->item(0);
        if (is_a($suite1, 'DOMElement')) {
            self::handleSuite($suite1, $configurationFile, $container, $dom);
        }
        
        $saveFile = $container->getCacheDirectory() . '/phpunit.humbug.xml';
        $dom->save($saveFile);

        return $saveFile;
    }

    private static function handleSuite(\DOMElement $suite, $configFile, Container $container, \DOMDocument $dom)
    {
        foreach ($suite->childNodes as $child) {
            // phpunit.xml may omit bootstrap location but grab it automatically - include explicitly
            if (self::$hasBootstrap === false && $child instanceof \DOMElement && $child->tagName == 'directory') {
{'fraction_non_alphanumeric': 0.12822064672315409, 'fraction_numerical': 0.0014698253501642747, 'mean_word_length': 2.7616260162601627, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 100, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 32}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6122199', 'n_tokens_mistral': 3170, 'n_tokens_neox': 3078, 'n_words': 647}