Completed
Push — master ( 3c9696...0f22ff )
by Bernhard
05:55
created

PuliRunner::getPuliCommand()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the puli/composer-plugin package.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Puli\ComposerPlugin;
13
14
use RuntimeException;
15
use Symfony\Component\Process\ExecutableFinder;
16
use Symfony\Component\Process\PhpExecutableFinder;
17
use Symfony\Component\Process\Process;
18
use Symfony\Component\Process\ProcessUtils;
19
20
/**
21
 * Executes the "puli" command.
22
 *
23
 * @since  1.0
24
 *
25
 * @author Bernhard Schussek <[email protected]>
26
 */
27
class PuliRunner
28
{
29
    /**
30
     * @var string
31
     */
32
    private $puli;
33
34
    /**
35
     * Creates a new runner.
36
     *
37
     * @param string|null $binDir The path to Composer's "bin-dir".
38
     */
39 3
    public function __construct($binDir = null)
40
    {
41 3
        $phpFinder = new PhpExecutableFinder();
42
43 3
        if (!($php = $phpFinder->find())) {
44
            throw new RuntimeException('The "php" command could not be found.');
45
        }
46
47 3
        $finder = new ExecutableFinder();
48
49
        // Search:
50
        // 1. in the current working directory
51
        // 2. in Composer's "bin-dir"
52
        // 3. in the system path
53 3
        $searchPath = array_merge(array(getcwd()), (array) $binDir);
54
55
        // Search "puli.phar" in the PATH and the current directory
56 3
        if (!($puli = $this->find('puli.phar', $searchPath, $finder))) {
57
            // Search "puli" in the PATH and Composer's "bin-dir"
58 3
            if (!($puli = $this->find('puli', $searchPath, $finder))) {
59
                throw new RuntimeException('The "puli"/"puli.phar" command could not be found.');
60
            }
61 3
        }
62
63
        // Fix slashes
64 3
        $php = strtr($php, '\\', '/');
65 3
        $puli = strtr($puli, '\\', '/');
66
67 3
        $content = file_get_contents($puli, null, null, -1, 18);
68
69 3
        if ($content === '#!/usr/bin/env php' || 0 === strpos($content, '<?php')) {
70 2
            $this->puli = ProcessUtils::escapeArgument($php).' '.ProcessUtils::escapeArgument($puli);
71 2
        } else {
72 1
            $this->puli = ProcessUtils::escapeArgument($puli);
73
        }
74 3
    }
75
76
    /**
77
     * Returns the command used to execute Puli.
78
     *
79
     * @return string The "puli" command.
80
     */
81 3
    public function getPuliCommand()
82
    {
83 3
        return $this->puli;
84
    }
85
86
    /**
87
     * Runs a Puli command.
88
     *
89
     * @param string   $command The Puli command to run.
90
     * @param string[] $args    Arguments to quote and insert into the command.
91
     *                          For each key "key" in this array, the placeholder
92
     *                          "%key%" should be present in the command string.
93
     *
94
     * @return string The lines of the output.
95
     */
96
    public function run($command, array $args = array())
97
    {
98
        $replacements = array();
99
100
        foreach ($args as $key => $arg) {
101
            $replacements['%'.$key.'%'] = ProcessUtils::escapeArgument($arg);
102
        }
103
104
        // Disable colorization so that we can process the output
105
        // Enable exception traces by using the "-vv" switch
106
        $fullCommand = sprintf('%s %s --no-ansi -vv', $this->puli, strtr($command, $replacements));
107
108
        $process = new Process($fullCommand);
109
        $process->run();
110
111
        if (!$process->isSuccessful()) {
112
            throw PuliRunnerException::forProcess($process);
113
        }
114
115
        // Normalize line endings across systems
116
        return str_replace("\r\n", "\n", $process->getOutput());
117
    }
118
119 3
    private function find($name, array $dirs, ExecutableFinder $finder)
120
    {
121 3
        $suffixes = array('');
122
123 3
        if ('\\' === DIRECTORY_SEPARATOR) {
124
            $suffixes[] = '.bat';
125
        }
126
127
        // The finder first looks in the system directories and then in the
128
        // user-defined ones. We want to check the user-defined ones first.
129 3
        foreach ($dirs as $dir) {
130 3
            foreach ($suffixes as $suffix) {
131 3
                $file = $dir.DIRECTORY_SEPARATOR.$name.$suffix;
132
133 3
                if (is_file($file) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) {
134 3
                    return $file;
135
                }
136 3
            }
137 3
        }
138
139 3
        return $finder->find($name);
140
    }
141
}
142