Completed
Push — master ( 58df20...aea7d8 )
by Théo
02:30
created

PhpunitExecutableFinder::getConfig()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
/**
3
 * Locate a Composer executable or throw a tantrum.
4
 *
5
 * @category   Humbug
6
 * @package    Humbug
7
 * @copyright  Copyright (c) 2015 Pádraic Brady (http://blog.astrumfutura.com)
8
 * @license    https://github.com/padraic/humbug/blob/master/LICENSE New BSD License
9
 */
10
11
namespace Humbug\Adapter\Phpunit\Process;
12
13
use Humbug\Process\AbstractExecutableFinder;
14
use Humbug\Process\ComposerExecutableFinder;
15
use Humbug\Exception\RuntimeException;
16
use Humbug\Config;
17
use Humbug\Config\JsonParser;
18
use Symfony\Component\Process\Process;
19
use Symfony\Component\Process\ExecutableFinder;
20
use Symfony\Component\Process\PhpExecutableFinder;
21
22
class PhpunitExecutableFinder extends AbstractExecutableFinder
23
{
24
25
    /**
26
     * @var Config
27
     */
28
    private $config;
29
30
    /**
31
     * @return string
32
     */
33
    public function find()
34
    {
35
        $this->checkVendorPath();
36
        return $this->findPhpunit();
37
    }
38
39
    /**
40
     * @return void
41
     */
42
    private function checkVendorPath()
43
    {
44
        $vendorPath = null;
45
        try {
46
            $composer = $this->findComposer();
47
            $process = new Process(sprintf('%s %s', $composer, 'config bin-dir'));
48
            $process->run();
49
            $vendorPath = trim($process->getOutput());
50
        } catch (RuntimeException $e) {
51
            $candidate = getcwd() . '/vendor/bin';
52
            if (file_exists($candidate)) {
53
                $vendorPath = $candidate;
54
            }
55
        }
56
        if (!is_null($vendorPath)) {
57
            putenv('PATH=' . $vendorPath . PATH_SEPARATOR . getenv('PATH'));
58
        }
59
    }
60
61
    /**
62
     * @return string
63
     */
64
    private function findComposer()
65
    {
66
        $finder = new ComposerExecutableFinder;
67
        return $finder->find();
68
    }
69
70
    /**
71
     * @return string
72
     */
73
    private function findPhpunit()
74
    {
75
        $probable = $this->getExecutableNames();
76
        $dir = $this->getPhpunitExecutablePath();
77
        $finder = new ExecutableFinder;
78
        foreach ($probable as $name) {
79
            if ($path = $finder->find($name, null, [$dir])) {
80
                return $this->makeExecutable($path);
81
            }
82
        }
83
        $result = $this->searchNonExecutables($probable, [$dir]);
84
        if (!is_null($result)) {
85
            return $result;
86
        }
87
        throw new RuntimeException(
88
            'Unable to locate a PHPUnit executable on local system. Ensure '
89
            . 'that PHPUnit is installed and available.'
90
        );
91
    }
92
93
    /**
94
     * Prefix commands with exec outside Windows to ensure process timeouts
95
     * are enforced and end PHP processes properly
96
     *
97
     * @param string $path
98
     * @return string
99
     */
100
    protected function makeExecutable($path)
101
    {
102
        $path = realpath($path);
103
        $phpFinder = new PhpExecutableFinder();
104
        if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
105
            return sprintf('%s %s %s', 'exec', $phpFinder->find(), $path);
106
        } else {
107
            if (false !== strpos($path, '.bat')) {
108
                return $path;
109
            }
110
            return sprintf('%s %s', $phpFinder->find(), $path);
111
        }
112
    }
113
114
    private function setConfig()
115
    {
116
        $config = (new JsonParser())->parseFile();
117
        $this->config = new Config($config);
118
    }
119
120
    /**
121
     * @return Config
122
     */
123
    private function getConfig()
124
    {
125
        if (is_null($this->config)) {
126
            $this->setConfig();
127
        }
128
        return $this->config;
129
    }
130
131
    /**
132
     * @return array
133
     */
134
    private function getExecutableNames()
135
    {
136
        if ($this->getConfig()->isPhpunitConfigured()) {
137
            return [basename($this->getConfig()->getPhpunitConfig()->phar)];
138
        }
139
        return ['phpunit', 'phpunit.phar'];
140
    }
141
142
    /**
143
     * @return string
144
     */
145
    private function getPhpunitExecutablePath()
146
    {
147
        if ($this->getConfig()->isPhpunitConfigured()) {
148
            return dirname($this->getConfig()->getPhpunitConfig()->phar);
149
        }
150
        return getcwd();
151
    }
152
}
153