1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* Composer plugin for bower/npm assets |
5
|
|
|
* |
6
|
|
|
* @link https://github.com/hiqdev/composer-asset-plugin |
7
|
|
|
* @package composer-asset-plugin |
8
|
|
|
* @license BSD-3-Clause |
9
|
|
|
* @copyright Copyright (c) 2015, HiQDev (http://hiqdev.com/) |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace hiqdev\composerassetplugin; |
13
|
|
|
|
14
|
|
|
use Composer\Json\JsonFile; |
15
|
|
|
use Composer\Package\CompletePackage; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Abstract package manager class. |
19
|
|
|
* |
20
|
|
|
* @author Andrii Vasyliev <[email protected]> |
21
|
|
|
*/ |
22
|
|
|
abstract class PackageManager |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* The plugin. |
26
|
|
|
* @var Plugin |
27
|
|
|
*/ |
28
|
|
|
protected $plugin; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Package manager name: bower or npm. |
32
|
|
|
* @var string |
33
|
|
|
*/ |
34
|
|
|
protected $name; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* Package config file: bower.json or package.json |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
public $file; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Path to package manager binary. |
44
|
|
|
* @var string |
45
|
|
|
*/ |
46
|
|
|
public $bin; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Package name of PHP version of package manager. |
50
|
|
|
* @var string |
51
|
|
|
*/ |
52
|
|
|
public $phpPackage; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Binary name of PHP version of package manager. |
56
|
|
|
* @var string |
57
|
|
|
*/ |
58
|
|
|
protected $phpBin; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Package config. Initially holds default config. |
62
|
|
|
*/ |
63
|
|
|
protected $config = []; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Conversion table. |
67
|
|
|
* @var string |
68
|
|
|
*/ |
69
|
|
|
protected $keyTable = [ |
70
|
|
|
'require' => 'dependencies', |
71
|
|
|
'require-dev' => 'devDependencies', |
72
|
|
|
]; |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Reads config file or dist config if exists, merges with default config. |
76
|
|
|
*/ |
77
|
|
|
public function __construct(Plugin $plugin) |
78
|
|
|
{ |
79
|
|
|
$this->plugin = $plugin; |
80
|
|
|
//$dist = $this->file . '.dist'; |
|
|
|
|
81
|
|
|
$this->config = array_merge( |
82
|
|
|
$this->config, |
83
|
|
|
$this->readConfig($this->file) |
84
|
|
|
//$this->readConfig(file_exists($dist) ? $dist : $this->file) |
|
|
|
|
85
|
|
|
); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
public function readConfig($file) |
89
|
|
|
{ |
90
|
|
|
$jsonFile = new JsonFile($file); |
91
|
|
|
$config = $jsonFile->exists() ? $jsonFile->read() : []; |
92
|
|
|
foreach ($this->keyTable as $key) { |
|
|
|
|
93
|
|
|
if (!isset($config[$key])) { |
94
|
|
|
$config[$key] = []; |
95
|
|
|
} |
96
|
|
|
} |
97
|
|
|
return $config; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
public function writeConfig($file, $config) |
101
|
|
|
{ |
102
|
|
|
foreach ($this->keyTable as $key) { |
|
|
|
|
103
|
|
|
if (isset($config[$key]) && !$config[$key]) { |
104
|
|
|
unset($config[$key]); |
105
|
|
|
} |
106
|
|
|
} |
107
|
|
|
$jsonFile = new JsonFile($file); |
108
|
|
|
$jsonFile->write($config); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
public function scanPackage(CompletePackage $package) |
112
|
|
|
{ |
113
|
|
|
$extra = $package->getExtra(); |
114
|
|
|
$config = []; |
115
|
|
|
foreach (['require', 'require-dev'] as $key) { |
116
|
|
|
$name = $this->name . '-' . $key; |
117
|
|
|
if (isset($extra[$name])) { |
118
|
|
|
$config[$key] = $extra[$name]; |
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
if ($config) { |
|
|
|
|
122
|
|
|
$this->mergeConfig($config); |
123
|
|
|
} |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
protected function mergeConfig($config) |
127
|
|
|
{ |
128
|
|
|
foreach ($config as $key => $packages) { |
129
|
|
|
$key = $this->keyTable[$key]; |
130
|
|
|
foreach ($packages as $name => $version) { |
131
|
|
|
$this->config[$key][$name] = isset($this->config[$key][$name]) |
132
|
|
|
? $this->mergeVersions($this->config[$key][$name], $version) |
133
|
|
|
: $version; |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
protected function mergeVersions($a, $b) |
139
|
|
|
{ |
140
|
|
|
$a = trim($a); |
141
|
|
|
$b = trim($b); |
142
|
|
|
if ($a === $b || $this->isMoreVersion($b, $a)) { |
143
|
|
|
return $a; |
144
|
|
|
} elseif ($this->isMoreVersion($a, $b)) { |
145
|
|
|
return $b; |
146
|
|
|
} else { |
147
|
|
|
return $a . ' ' . $b; |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* Check if $a is more then $b, like: a="1.1 || 2.2" b="1.1" |
153
|
|
|
* Possible optimization. |
154
|
|
|
*/ |
155
|
|
|
public function isMoreVersion($a, $b) |
|
|
|
|
156
|
|
|
{ |
157
|
|
|
return $this->isAnyVersion($a); |
158
|
|
|
// WRONG: return strpos($b, $a) !== false; |
|
|
|
|
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
public function isAnyVersion($version) |
162
|
|
|
{ |
163
|
|
|
return !$version || $version === '*' || $version === '>=0.0.0'; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Set config. |
168
|
|
|
* @param array $config |
169
|
|
|
*/ |
170
|
|
|
public function setConfig(array $config) |
171
|
|
|
{ |
172
|
|
|
$this->config = $config; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Run given action: show notice, write config and run `perform`. |
177
|
|
|
* @param string $action |
178
|
|
|
*/ |
179
|
|
|
public function runAction($action) |
180
|
|
|
{ |
181
|
|
|
$doing = trim($action, 'e') . 'ing'; |
182
|
|
|
$this->plugin->io->write($doing . ' ' . $this->name . ' dependencies...'); |
183
|
|
|
$this->writeConfig($this->file, $this->config); |
184
|
|
|
$this->perform($action); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Run installation. Specific for every package manager. |
189
|
|
|
* @param string $action |
190
|
|
|
*/ |
191
|
|
|
protected function perform($action) |
192
|
|
|
{ |
193
|
|
|
if ($this->passthru($action)) { |
|
|
|
|
194
|
|
|
$this->plugin->io->write('failed ' . $name . ' ' . $action); |
|
|
|
|
195
|
|
|
} |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Prepares arguments and runs it with passthru. |
200
|
|
|
* @param string $args |
201
|
|
|
* @return int exit code |
202
|
|
|
*/ |
203
|
|
|
public function passthru($args = '') |
204
|
|
|
{ |
205
|
|
|
passthru($this->getBin() . $this->prepareCommand($args), $exitcode); |
206
|
|
|
return $exitcode; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Prepares given command arguments. |
211
|
|
|
* @param string|array $args |
212
|
|
|
* @return string |
213
|
|
|
*/ |
214
|
|
|
public function prepareCommand($args = '') |
215
|
|
|
{ |
216
|
|
|
if (is_string($args)) { |
217
|
|
|
$res = ' ' . trim($args); |
218
|
|
|
} else { |
219
|
|
|
$res = ''; |
220
|
|
|
foreach ($args as $a) { |
221
|
|
|
$res .= ' ' . escapeshellarg($a); |
222
|
|
|
} |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
return $res; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* Set path to binary. |
230
|
|
|
* @param string $value |
231
|
|
|
*/ |
232
|
|
|
public function setBin($value) |
233
|
|
|
{ |
234
|
|
|
$this->bin = $value; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* Get path to binary. |
239
|
|
|
* @return string |
240
|
|
|
*/ |
241
|
|
|
public function getBin() |
242
|
|
|
{ |
243
|
|
|
if ($this->bin === null) { |
244
|
|
|
$this->bin = $this->detectBin(); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
return $this->bin; |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
/** |
251
|
|
|
* Find path binary. |
252
|
|
|
* @return string |
253
|
|
|
*/ |
254
|
|
|
public function detectBin() |
255
|
|
|
{ |
256
|
|
|
if (isset($this->plugin->getPackages()[$this->phpPackage])) { |
257
|
|
|
return $this->plugin->getVendorDir() . '/bin/' . $this->phpBin; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
return $this->name; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
} |
264
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.