Completed
Pull Request — master (#86)
by Alessandro
06:05
created

PHPUnitConfig::isRelativePath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Paraunit\Configuration;
4
5
/**
6
 * Class PHPUnitConfig
7
 * @package Paraunit\Configuration
8
 */
9
class PHPUnitConfig
10
{
11
    const DEFAULT_FILE_NAME = 'phpunit.xml.dist';
12
13
    /** @var  TempFilenameFactory */
14
    private $tempFilenameFactory;
15
16
    /** @var string */
17
    private $configFile;
18
19
    /** @var string */
20
    private $originalFilename;
21
22
    /** @var  PHPUnitOption[] */
23 30
    private $phpunitOptions;
24
25 30
    /**
26
     * @param TempFilenameFactory $tempFilenameFactory
27 30
     * @param string $inputPathOrFileName
28 1
     * @throws \InvalidArgumentException
29
     */
30
    public function __construct(TempFilenameFactory $tempFilenameFactory, $inputPathOrFileName)
31 29
    {
32 18
        $this->tempFilenameFactory = $tempFilenameFactory;
33 29
        $this->originalFilename = $inputPathOrFileName;
34
        $this->phpunitOptions = array();
35 29
    }
36 1
37
    /**
38
     * Get the full path for this configuration file
39 28
     * @return string
40 28
     */
41 28
    public function getFileFullPath()
42
    {
43
        if (null === $this->configFile) {
44
            $this->loadAndCopyConfigFile();
45
        }
46
47 20
        return $this->configFile;
48
    }
49 20
50
    /**
51
     * The relative path from where the configuration defines the testsuites
52
     * @return string
53
     */
54
    public function getBaseDirectory()
55
    {
56 8
        return dirname($this->originalFilename);
57
    }
58 8
59
    /**
60
     * @param PHPUnitOption $option
61
     */
62
    public function addPhpunitOption(PHPUnitOption $option)
63
    {
64 2
        $this->phpunitOptions[] = $option;
65
    }
66 2
67 2
    /**
68
     * @return PHPUnitOption[]
69
     */
70
    public function getPhpunitOptions()
71
    {
72 11
        return $this->phpunitOptions;
73
    }
74 11
75
    private function loadAndCopyConfigFile()
76
    {
77
        $originalConfigFilename = $this->getConfigFileRealpath($this->originalFilename);
78
        $this->configFile = $this->copyAndAlterConfig($originalConfigFilename);
79
    }
80
81
    /**
82
     * @param string $inputPathOrFileName
83
     * @return string
84
     * @throws \InvalidArgumentException
85
     */
86
    private function getConfigFileRealpath($inputPathOrFileName)
87
    {
88
        $inputPathOrFileName = realpath($inputPathOrFileName);
89
90
        if (false === $inputPathOrFileName) {
91
            throw new \InvalidArgumentException('Config path/file provided is not valid (does it exist?)');
92
        }
93
94
        $configFile = $inputPathOrFileName;
95
96
        if (is_dir($configFile)) {
97
            $this->baseDirectory = dirname($configFile);
0 ignored issues
show
Bug introduced by
The property baseDirectory does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
98
            $configFile .= DIRECTORY_SEPARATOR . self::DEFAULT_FILE_NAME;
99
        }
100
101
        if (! is_file($configFile) || ! is_readable($configFile)) {
102
            throw new \InvalidArgumentException('Config file ' . $configFile . ' does not exist or is not readable');
103
        }
104
105
        return $configFile;
106
    }
107
108
    private function copyAndAlterConfig($originalConfigFilename)
109
    {
110
        $originalConfig = file_get_contents($originalConfigFilename);
111
        $document = new \DOMDocument;
112
        $document->preserveWhiteSpace = false;
113
114
        $document->loadXML($originalConfig);
115
        $this->alterBoostrap($document);
116
        $this->appendLogListener($document);
117
        
118
        $newFilename = $this->tempFilenameFactory->getFilenameForConfiguration();
119
120
        if (false === file_put_contents($newFilename, $document->saveXML())) {
121
            throw new \RuntimeException('Error while saving temporary config');
122
        }
123
124
        return $newFilename;
125
    }
126
127
    /**
128
     * @param string $originalBoostrap
129
     * @return bool
130
     */
131
    private function isRelativePath($originalBoostrap)
132
    {
133
        return 0 === preg_match('~(^[A-Z]:)|(^/)~', $originalBoostrap);
134
    }
135
136
    private function alterBoostrap(\DOMDocument $document)
137
    {
138
        $rootNode = $document->documentElement;
139
140
        $originalBoostrap = $rootNode->getAttribute('bootstrap');
141
        if ($originalBoostrap && $this->isRelativePath($originalBoostrap)) {
142
            $newBootstrapPath = $this->getBaseDirectory() . DIRECTORY_SEPARATOR . $originalBoostrap;
143
            $rootNode->setAttribute('bootstrap', $newBootstrapPath);
144
        }
145
    }
146
147
    private function appendLogListener(\DOMDocument $document)
148
    {
149
        $rootNode = $document->documentElement;
150
151
        $textNode = $document->createTextNode($this->tempFilenameFactory->getPathForLog());
152
        $logDirNode = $document->createElement('string');
153
        $logDirNode->appendChild($textNode);
154
        $argumentsNode = $document->createElement('arguments');
155
        $argumentsNode->appendChild($logDirNode);
156
        $logListenerNode = $document->createElement('listener');
157
        $logListenerNode->setAttribute('class', 'Paraunit\Parser\JSON\LogPrinter');
158
        $logListenerNode->appendChild($argumentsNode);
159
160
        $listenersNode = $rootNode->getElementsByTagName('listeners')->item(0);
161
        if (! $listenersNode) {
162
            $listenersNode = $document->createElement('listeners');
163
            $rootNode->appendChild($listenersNode);
164
        }
165
166
        $listenersNode->appendChild($logListenerNode);
167
    }
168
}
169