1
|
|
|
<?php |
2
|
|
|
namespace Robo\Common; |
3
|
|
|
|
4
|
|
|
use Robo\Result; |
5
|
|
|
use Symfony\Component\Process\ExecutableFinder; |
6
|
|
|
use Symfony\Component\Process\Process; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* This task is supposed to be executed as shell command. |
10
|
|
|
* You can specify working directory and if output is printed. |
11
|
|
|
*/ |
12
|
|
|
trait ExecCommand |
13
|
|
|
{ |
14
|
|
|
use ExecTrait; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @var \Robo\Common\TimeKeeper |
18
|
|
|
*/ |
19
|
|
|
protected $execTimer; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @return \Robo\Common\TimeKeeper |
23
|
|
|
*/ |
24
|
|
|
protected function getExecTimer() |
25
|
|
|
{ |
26
|
|
|
if (!isset($this->execTimer)) { |
27
|
|
|
$this->execTimer = new TimeKeeper(); |
28
|
|
|
} |
29
|
|
|
return $this->execTimer; |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Look for a "{$cmd}.phar" in the current working |
34
|
|
|
* directory; return a string to exec it if it is |
35
|
|
|
* found. Otherwise, look for an executable command |
36
|
|
|
* of the same name via findExecutable. |
37
|
|
|
* |
38
|
|
|
* @param string $cmd |
39
|
|
|
* |
40
|
|
|
* @return bool|string |
41
|
|
|
*/ |
42
|
|
|
protected function findExecutablePhar($cmd) |
43
|
|
|
{ |
44
|
|
|
if (file_exists("{$cmd}.phar")) { |
45
|
|
|
return "php {$cmd}.phar"; |
46
|
|
|
} |
47
|
|
|
return $this->findExecutable($cmd); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Return the best path to the executable program |
52
|
|
|
* with the provided name. Favor vendor/bin in the |
53
|
|
|
* current project. If not found there, use |
54
|
|
|
* whatever is on the $PATH. |
55
|
|
|
* |
56
|
|
|
* @param string $cmd |
57
|
|
|
* |
58
|
|
|
* @return bool|string |
59
|
|
|
*/ |
60
|
|
|
protected function findExecutable($cmd) |
61
|
|
|
{ |
62
|
|
|
$pathToCmd = $this->searchForExecutable($cmd); |
63
|
|
|
if ($pathToCmd) { |
64
|
|
|
return $this->useCallOnWindows($pathToCmd); |
65
|
|
|
} |
66
|
|
|
return false; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @param string $cmd |
71
|
|
|
* |
72
|
|
|
* @return string |
73
|
|
|
*/ |
74
|
|
|
private function searchForExecutable($cmd) |
75
|
|
|
{ |
76
|
|
|
$projectBin = $this->findProjectBin(); |
77
|
|
|
|
78
|
|
|
$localComposerInstallation = $projectBin . DIRECTORY_SEPARATOR . $cmd; |
79
|
|
|
if (file_exists($localComposerInstallation)) { |
80
|
|
|
return $localComposerInstallation; |
81
|
|
|
} |
82
|
|
|
$finder = new ExecutableFinder(); |
83
|
|
|
return $finder->find($cmd, null, []); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @return bool|string |
88
|
|
|
*/ |
89
|
|
|
protected function findProjectBin() |
90
|
|
|
{ |
91
|
|
|
$cwd = getcwd(); |
92
|
|
|
$candidates = [ __DIR__ . '/../../vendor/bin', __DIR__ . '/../../bin', $cwd . '/vendor/bin' ]; |
93
|
|
|
|
94
|
|
|
// If this project is inside a vendor directory, give highest priority |
95
|
|
|
// to that directory. |
96
|
|
|
$vendorDirContainingUs = realpath(__DIR__ . '/../../../..'); |
97
|
|
|
if (is_dir($vendorDirContainingUs) && (basename($vendorDirContainingUs) == 'vendor')) { |
98
|
|
|
array_unshift($candidates, $vendorDirContainingUs . '/bin'); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
foreach ($candidates as $dir) { |
102
|
|
|
if (is_dir("$dir")) { |
103
|
|
|
return realpath($dir); |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
return false; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Wrap Windows executables in 'call' per 7a88757d |
111
|
|
|
* |
112
|
|
|
* @param string $cmd |
113
|
|
|
* |
114
|
|
|
* @return string |
115
|
|
|
*/ |
116
|
|
|
protected function useCallOnWindows($cmd) |
117
|
|
|
{ |
118
|
|
|
if (defined('PHP_WINDOWS_VERSION_BUILD')) { |
119
|
|
|
if (file_exists("{$cmd}.bat")) { |
120
|
|
|
$cmd = "{$cmd}.bat"; |
121
|
|
|
} |
122
|
|
|
return "call $cmd"; |
123
|
|
|
} |
124
|
|
|
return $cmd; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
protected function getCommandDescription() |
128
|
|
|
{ |
129
|
|
|
return $this->process->getCommandLine(); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @param string $command |
134
|
|
|
* |
135
|
|
|
* @return \Robo\Result |
136
|
|
|
*/ |
137
|
|
View Code Duplication |
protected function executeCommand($command) |
|
|
|
|
138
|
|
|
{ |
139
|
|
|
$result_data = $this->execute(new Process($command)); |
140
|
|
|
return new Result( |
141
|
|
|
$this, |
142
|
|
|
$result_data->getExitCode(), |
143
|
|
|
$result_data->getMessage(), |
144
|
|
|
$result_data->getData() |
145
|
|
|
); |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.