1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* PackagesManager.php |
4
|
|
|
* |
5
|
|
|
* @copyright More in license.md |
6
|
|
|
* @license http://www.ipublikuj.eu |
7
|
|
|
* @author Adam Kadlec http://www.ipublikuj.eu |
8
|
|
|
* @package iPublikuj:Packages! |
9
|
|
|
* @subpackage common |
10
|
|
|
* @since 1.0.0 |
11
|
|
|
* |
12
|
|
|
* @date 30.05.15 |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
declare(strict_types = 1); |
16
|
|
|
|
17
|
|
|
namespace IPub\Packages; |
18
|
|
|
|
19
|
|
|
use Nette; |
20
|
|
|
use Nette\Utils; |
21
|
|
|
|
22
|
|
|
use IPub; |
23
|
|
|
use IPub\Packages; |
24
|
|
|
use IPub\Packages\DependencyResolver; |
25
|
|
|
use IPub\Packages\Entities; |
26
|
|
|
use IPub\Packages\Exceptions; |
27
|
|
|
use IPub\Packages\Installers; |
28
|
|
|
use IPub\Packages\Repository; |
29
|
|
|
use IPub\Packages\Scripts; |
30
|
|
|
use Tracy\Debugger; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Packages manager |
34
|
|
|
* |
35
|
|
|
* @package iPublikuj:Packages! |
36
|
|
|
* @subpackage common |
37
|
|
|
* |
38
|
|
|
* @author Adam Kadlec <[email protected]> |
39
|
|
|
* |
40
|
|
|
* @method onEnable(PackagesManager $manager, Entities\IPackage $package) |
41
|
|
|
* @method onDisable(PackagesManager $manager, Entities\IPackage $package) |
42
|
|
|
* @method onUpgrade(PackagesManager $manager, Entities\IPackage $package) |
43
|
|
|
* @method onInstall(PackagesManager $manager, Entities\IPackage $package) |
44
|
|
|
* @method onUninstall(PackagesManager $manager, Entities\IPackage $package) |
45
|
|
|
* @method onRegister(PackagesManager $manager, Entities\IPackage $package) |
46
|
|
|
* @method onUnregister(PackagesManager $manager, Entities\IPackage $package) |
47
|
|
|
*/ |
48
|
|
|
final class PackagesManager extends Nette\Object implements IPackagesManager |
49
|
|
|
{ |
50
|
|
|
/** |
51
|
|
|
* Define class name |
52
|
|
|
*/ |
53
|
|
|
const CLASS_NAME = __CLASS__; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Define package metadata keys |
57
|
|
|
*/ |
58
|
|
|
const PACKAGE_STATUS = 'status'; |
59
|
|
|
const PACKAGE_METADATA = 'metadata'; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Define actions |
63
|
|
|
*/ |
64
|
|
|
const ACTION_ENABLE = 'enable'; |
65
|
|
|
const ACTION_DISABLE = 'disable'; |
66
|
|
|
const ACTION_REGISTER = 'register'; |
67
|
|
|
const ACTION_UNREGISTER = 'unregister'; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @var callable[] |
71
|
|
|
*/ |
72
|
|
|
public $onEnable = []; |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* @var callable[] |
76
|
|
|
*/ |
77
|
|
|
public $onDisable = []; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* @var callable[] |
81
|
|
|
*/ |
82
|
|
|
public $onUpgrade = []; |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @var callable[] |
86
|
|
|
*/ |
87
|
|
|
public $onInstall = []; |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* @var callable[] |
91
|
|
|
*/ |
92
|
|
|
public $onUninstall = []; |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* @var callable[] |
96
|
|
|
*/ |
97
|
|
|
public $onRegister = []; |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* @var callable[] |
101
|
|
|
*/ |
102
|
|
|
public $onUnregister = []; |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* @var string |
106
|
|
|
*/ |
107
|
|
|
private $vendorDir; |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* @var string |
111
|
|
|
*/ |
112
|
|
|
private $configDir; |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @var Repository\IRepository |
116
|
|
|
*/ |
117
|
|
|
private $repository; |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @var Installers\IInstaller|NULL |
121
|
|
|
*/ |
122
|
|
|
private $installer; |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* @var Nette\DI\Container |
126
|
|
|
*/ |
127
|
|
|
private $container; |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* @var DependencyResolver\Solver |
131
|
|
|
*/ |
132
|
|
|
private $dependencySolver; |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* @var Utils\ArrayHash |
136
|
|
|
*/ |
137
|
|
|
private $packagesConfig; |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* @var Scripts\IScript[] |
141
|
|
|
*/ |
142
|
|
|
private $scripts = []; |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* @param string $vendorDir |
146
|
|
|
* @param string $configDir |
147
|
|
|
* @param Repository\IRepository $repository |
148
|
|
|
* @param Installers\IInstaller|NULL $installer |
149
|
|
|
*/ |
150
|
|
|
public function __construct( |
151
|
|
|
string $vendorDir, |
152
|
|
|
string $configDir, |
153
|
|
|
Repository\IRepository $repository, |
154
|
|
|
Installers\IInstaller $installer = NULL |
155
|
|
|
) { |
156
|
|
|
$this->vendorDir = $vendorDir; |
157
|
|
|
$this->configDir = $configDir; |
158
|
|
|
|
159
|
|
|
$this->repository = $repository; |
160
|
|
|
$this->installer = $installer; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* {@inheritdoc} |
165
|
|
|
*/ |
166
|
|
|
public function getStatus(Entities\IPackage $package) : string |
167
|
|
|
{ |
168
|
|
|
$packageConfig = $this->getPackagesConfig(); |
169
|
|
|
|
170
|
|
|
if (!$packageConfig->offsetExists($package->getName()) || !isset($packageConfig[$package->getName()][self::PACKAGE_STATUS])) { |
171
|
|
|
return Entities\IPackage::STATE_UNREGISTERED; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
return $packageConfig[$package->getName()][self::PACKAGE_STATUS]; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* {@inheritdoc} |
179
|
|
|
*/ |
180
|
|
|
public function getVersion(Entities\IPackage $package) : string |
181
|
|
|
{ |
182
|
|
|
if (!$path = $package->getPath()) { |
183
|
|
|
throw new \RuntimeException('Package path is missing.'); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
if (!file_exists($file = $path . DIRECTORY_SEPARATOR . 'composer.json')) { |
187
|
|
|
throw new \RuntimeException('\'composer.json\' is missing.'); |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
$packageData = Utils\Json::decode(file_get_contents($file), Utils\Json::FORCE_ARRAY); |
191
|
|
|
|
192
|
|
|
if (isset($packageData['version'])) { |
193
|
|
|
return $packageData['version']; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
if (file_exists($file = $this->vendorDir . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'installed.json')) { |
197
|
|
|
$installed = Utils\Json::decode(file_get_contents($file), Utils\Json::FORCE_ARRAY); |
198
|
|
|
|
199
|
|
|
foreach ($installed as $packageData) { |
200
|
|
|
if ($packageData['name'] === $package->getName()) { |
201
|
|
|
return $packageData['version']; |
202
|
|
|
} |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
return '0.0.0'; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* {@inheritdoc} |
211
|
|
|
*/ |
212
|
|
|
public function comparePackages(Entities\IPackage $first, Entities\IPackage $second, string $operator = '==') : bool |
213
|
|
|
{ |
214
|
|
|
return strtolower($first->getName()) === strtolower($second->getName()) && |
215
|
|
|
version_compare(strtolower($this->getVersion($first)), strtolower($this->getVersion($second)), $operator); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* {@inheritdoc} |
220
|
|
|
*/ |
221
|
|
|
public function addScript(string $name, Scripts\IScript $service) |
222
|
|
|
{ |
223
|
|
|
$this->scripts[$name] = $service; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* {@inheritdoc} |
228
|
|
|
*/ |
229
|
|
|
public function registerAvailable() : array |
230
|
|
|
{ |
231
|
|
|
$actions = []; |
232
|
|
|
|
233
|
|
|
$installedPackages = array_keys($this->repository->getPackages()); |
234
|
|
|
$registeredPackages = array_keys((array) $this->getPackagesConfig()); |
235
|
|
|
|
236
|
|
|
foreach (array_diff($installedPackages, $registeredPackages) as $name) { |
237
|
|
|
$this->register($this->repository->findPackage($name)); |
|
|
|
|
238
|
|
|
$actions[] = [$name => self::ACTION_REGISTER]; |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
return $actions; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* {@inheritdoc} |
246
|
|
|
*/ |
247
|
|
|
public function enableAvailable() : array |
248
|
|
|
{ |
249
|
|
|
$actions = []; |
250
|
|
|
|
251
|
|
|
while (TRUE) { |
252
|
|
|
/** @var Entities\IPackage[] $packages */ |
253
|
|
|
$packages = $this->repository->filterPackages(function (Entities\IPackage $package) { |
254
|
|
|
return $this->getStatus($package) === Entities\IPackage::STATE_DISABLED; |
255
|
|
|
}); |
256
|
|
|
|
257
|
|
|
if (!count($packages)) { |
258
|
|
|
break; |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** @var Entities\IPackage $package */ |
262
|
|
|
$package = reset($packages); |
263
|
|
|
|
264
|
|
|
foreach ($this->testEnable($package)->getSolutions() as $job) { |
265
|
|
|
if ($job->getAction() === DependencyResolver\Job::ACTION_ENABLE) { |
266
|
|
|
$this->enable($job->getPackage()); |
267
|
|
|
$actions[] = [$job->getPackage()->getName() => self::ACTION_ENABLE]; |
268
|
|
|
|
269
|
|
|
} elseif ($job->getAction() === DependencyResolver\Job::ACTION_DISABLE) { |
270
|
|
|
$this->disable($job->getPackage()); |
271
|
|
|
$actions[] = [$job->getPackage()->getName() => self::ACTION_DISABLE]; |
272
|
|
|
} |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
$this->enable($package); |
276
|
|
|
|
277
|
|
|
$this->dependencySolver = NULL; |
278
|
|
|
|
279
|
|
|
$actions[] = [$package->getName() => self::ACTION_ENABLE]; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
return $actions; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* {@inheritdoc} |
287
|
|
|
*/ |
288
|
|
|
public function disableAbsent() : array |
289
|
|
|
{ |
290
|
|
|
$actions = []; |
291
|
|
|
|
292
|
|
|
$installedPackages = array_keys($this->repository->getPackages()); |
293
|
|
|
$registeredPackages = array_keys((array) $this->getPackagesConfig()); |
294
|
|
|
|
295
|
|
|
foreach (array_diff($registeredPackages, $installedPackages) as $name) { |
296
|
|
|
/** @var Entities\IPackage $package */ |
297
|
|
|
$package = $this->repository->findPackage($name); |
298
|
|
|
|
299
|
|
|
if ($this->getStatus($package) === Entities\IPackage::STATE_ENABLED) { |
300
|
|
|
$this->disable($package); |
301
|
|
|
$actions[] = [$name => self::ACTION_DISABLE]; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
$this->disable($package); |
305
|
|
|
|
306
|
|
|
$actions[] = [$package->getName() => self::ACTION_DISABLE]; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
return $actions; |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
/** |
313
|
|
|
* {@inheritdoc} |
314
|
|
|
*/ |
315
|
|
|
public function install(string $name, bool $packagist = FALSE, bool $preferSource = TRUE) |
316
|
|
|
{ |
317
|
|
|
// Check if installer service is created |
318
|
|
|
if ($this->installer === NULL) { |
319
|
|
|
new Exceptions\InvalidStateException('Packages installer service is not created.'); |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
// Check if package is not already installed |
323
|
|
|
if ($this->repository->findPackage($name)) { |
324
|
|
|
throw new Exceptions\InvalidArgumentException(sprintf('Package "%s" is already installed', $name)); |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
$this->installer->install($name, $packagist, $preferSource); |
|
|
|
|
328
|
|
|
|
329
|
|
|
// Reload repository after installation |
330
|
|
|
$this->repository->reload(); |
331
|
|
|
|
332
|
|
|
// Get newly installed package |
333
|
|
|
$package = $this->repository->findPackage($name); |
334
|
|
|
|
335
|
|
|
// Process all package scripts |
336
|
|
|
foreach ($package->getScripts() as $class) { |
|
|
|
|
337
|
|
|
try { |
338
|
|
|
$script = $this->getScript($class); |
339
|
|
|
$script->install($package); |
|
|
|
|
340
|
|
|
|
341
|
|
|
} catch (\Exception $e) { |
342
|
|
|
foreach ($package->getScripts() as $class2) { |
|
|
|
|
343
|
|
|
if ($class === $class2) { |
344
|
|
|
break; |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
$script = $this->getScript($class2); |
348
|
|
|
$script->uninstall($package); |
|
|
|
|
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
throw new Exceptions\InvalidStateException($e->getMessage()); |
352
|
|
|
} |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
$this->register($package); |
|
|
|
|
356
|
|
|
|
357
|
|
|
$this->onInstall($this, $package); |
|
|
|
|
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* {@inheritdoc} |
362
|
|
|
*/ |
363
|
|
|
public function uninstall(string $name) |
364
|
|
|
{ |
365
|
|
|
// Check if installer service is created |
366
|
|
|
if ($this->installer === NULL) { |
367
|
|
|
new Exceptions\InvalidStateException('Packages installer service is not created.'); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
// Check if package is installed |
371
|
|
|
if (!$package = $this->repository->findPackage($name)) { |
372
|
|
|
throw new Exceptions\InvalidArgumentException(sprintf('Package "%s" is already uninstalled', $name)); |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
// If package is still enabled, disable it first |
376
|
|
|
if ($this->getStatus($package) === Entities\IPackage::STATE_ENABLED) { |
|
|
|
|
377
|
|
|
$this->disable($package); |
|
|
|
|
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
// Process all package scripts |
381
|
|
|
foreach ($package->getScripts() as $class) { |
382
|
|
|
try { |
383
|
|
|
$script = $this->getScript($class); |
384
|
|
|
$script->uninstall($package); |
|
|
|
|
385
|
|
|
|
386
|
|
|
} catch (\Exception $e) { |
387
|
|
|
foreach ($package->getScripts() as $class2) { |
388
|
|
|
if ($class === $class2) { |
389
|
|
|
break; |
390
|
|
|
} |
391
|
|
|
|
392
|
|
|
$script = $this->getScript($class2); |
393
|
|
|
$script->install($package); |
|
|
|
|
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
throw new Exceptions\InvalidStateException($e->getMessage()); |
397
|
|
|
} |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
$this->unregister($package); |
|
|
|
|
401
|
|
|
|
402
|
|
|
if ($this->installer->isInstalled($package->getName())) { |
403
|
|
|
$this->installer->uninstall($package->getName()); |
404
|
|
|
|
405
|
|
|
} else { |
406
|
|
|
if (!$path = $package->getPath()) { |
407
|
|
|
throw new Exceptions\InvalidStateException('Package path is missing.'); |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
$this->output->writeln("Removing package folder."); |
|
|
|
|
411
|
|
|
|
412
|
|
|
Utils\FileSystem::delete($path); |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
// Reload repository after uninstallation |
416
|
|
|
$this->repository->reload(); |
417
|
|
|
|
418
|
|
|
$this->onUninstall($this, $package); |
|
|
|
|
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
/** |
422
|
|
|
* {@inheritdoc} |
423
|
|
|
*/ |
424
|
|
View Code Duplication |
public function enable(Entities\IPackage $package) |
|
|
|
|
425
|
|
|
{ |
426
|
|
|
if ($this->getStatus($package) === Entities\IPackage::STATE_ENABLED) { |
427
|
|
|
throw new Exceptions\InvalidArgumentException(sprintf('Package \'%s\' is already enabled', $package->getName())); |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
$dependencyResolver = $this->getDependencySolver(); |
431
|
|
|
$dependencyResolver->testEnable($package); |
432
|
|
|
|
433
|
|
|
foreach ($package->getScripts() as $class) { |
434
|
|
|
try { |
435
|
|
|
$installer = $this->getScript($class); |
436
|
|
|
$installer->enable($package); |
437
|
|
|
|
438
|
|
|
} catch (\Exception $e) { |
439
|
|
|
foreach ($package->getScripts() as $class2) { |
440
|
|
|
if ($class === $class2) { |
441
|
|
|
break; |
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
$installer = $this->getScript($class2); |
445
|
|
|
$installer->disable($package); |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
throw new Exceptions\InvalidStateException($e->getMessage()); |
449
|
|
|
} |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
$this->setStatus($package, Entities\IPackage::STATE_ENABLED); |
453
|
|
|
|
454
|
|
|
$this->onEnable($this, $package); |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
/** |
458
|
|
|
* {@inheritdoc} |
459
|
|
|
*/ |
460
|
|
View Code Duplication |
public function disable(Entities\IPackage $package) |
|
|
|
|
461
|
|
|
{ |
462
|
|
|
if ($this->getStatus($package) === Entities\IPackage::STATE_DISABLED) { |
463
|
|
|
throw new Exceptions\InvalidArgumentException(sprintf('Package \'%s\' is already disabled', $package->getName())); |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
$dependencyResolver = $this->getDependencySolver(); |
467
|
|
|
$dependencyResolver->testDisable($package); |
468
|
|
|
|
469
|
|
|
foreach ($package->getScripts() as $class) { |
470
|
|
|
try { |
471
|
|
|
$installer = $this->getScript($class); |
472
|
|
|
$installer->disable($package); |
473
|
|
|
|
474
|
|
|
} catch (\Exception $e) { |
475
|
|
|
foreach ($package->getScripts() as $class2) { |
476
|
|
|
if ($class === $class2) { |
477
|
|
|
break; |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
$installer = $this->getScript($class2); |
481
|
|
|
$installer->enable($package); |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
throw new Exceptions\InvalidStateException($e->getMessage()); |
485
|
|
|
} |
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
$this->setStatus($package, Entities\IPackage::STATE_DISABLED); |
489
|
|
|
|
490
|
|
|
$this->onDisable($this, $package); |
491
|
|
|
} |
492
|
|
|
|
493
|
|
|
/** |
494
|
|
|
* {@inheritdoc} |
495
|
|
|
*/ |
496
|
|
View Code Duplication |
public function testEnable(Entities\IPackage $package) : DependencyResolver\Problem |
|
|
|
|
497
|
|
|
{ |
498
|
|
|
$problem = new DependencyResolver\Problem; |
499
|
|
|
|
500
|
|
|
$dependencyResolver = $this->getDependencySolver(); |
501
|
|
|
$dependencyResolver->testEnable($package, $problem); |
502
|
|
|
|
503
|
|
|
return $problem; |
504
|
|
|
} |
505
|
|
|
|
506
|
|
|
/** |
507
|
|
|
* {@inheritdoc} |
508
|
|
|
*/ |
509
|
|
View Code Duplication |
public function testDisable(Entities\IPackage $package) : DependencyResolver\Problem |
|
|
|
|
510
|
|
|
{ |
511
|
|
|
$problem = new DependencyResolver\Problem; |
512
|
|
|
|
513
|
|
|
$dependencyResolver = $this->getDependencySolver(); |
514
|
|
|
$dependencyResolver->testDisable($package, $problem); |
515
|
|
|
|
516
|
|
|
return $problem; |
517
|
|
|
} |
518
|
|
|
|
519
|
|
|
/** |
520
|
|
|
* @param Entities\IPackage $package |
521
|
|
|
* @param string $state |
522
|
|
|
*/ |
523
|
|
|
private function register(Entities\IPackage $package, string $state = Entities\IPackage::STATE_DISABLED) |
524
|
|
|
{ |
525
|
|
|
$packagesConfig = $this->getPackagesConfig(); |
526
|
|
|
|
527
|
|
|
if (!$packagesConfig->offsetExists($package->getName())) { |
528
|
|
|
// Create package config metadata |
529
|
|
|
$packagesConfig[$package->getName()] = [ |
530
|
|
|
self::PACKAGE_STATUS => $state, |
531
|
|
|
self::PACKAGE_METADATA => [ |
532
|
|
|
'authors' => array_merge((array) $package->getAuthors()), |
533
|
|
|
'description' => $package->getDescription(), |
534
|
|
|
'keywords' => array_merge((array) $package->getKeywords()), |
535
|
|
|
'license' => array_merge((array) $package->getLicense()), |
536
|
|
|
'require' => $package->getRequire(), |
537
|
|
|
'extra' => [ |
538
|
|
|
'ipub' => [ |
539
|
|
|
'configuration' => array_merge((array) $package->getConfiguration()), |
540
|
|
|
'scripts' => $package->getScripts(), |
541
|
|
|
], |
542
|
|
|
], |
543
|
|
|
], |
544
|
|
|
]; |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
$this->savePackagesConfig($packagesConfig); |
548
|
|
|
|
549
|
|
|
$this->onRegister($this, $package); |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
/** |
553
|
|
|
* @param Entities\IPackage $package |
554
|
|
|
*/ |
555
|
|
|
private function unregister(Entities\IPackage $package) |
556
|
|
|
{ |
557
|
|
|
$packagesConfig = $this->getPackagesConfig(); |
558
|
|
|
|
559
|
|
|
// Remove package info from configuration file |
560
|
|
|
unset($packagesConfig[$package->getName()]); |
561
|
|
|
|
562
|
|
|
$this->savePackagesConfig($packagesConfig); |
563
|
|
|
|
564
|
|
|
$this->onUnregister($this, $package); |
565
|
|
|
} |
566
|
|
|
|
567
|
|
|
/** |
568
|
|
|
* @param Entities\IPackage $package |
569
|
|
|
* @param string $status |
570
|
|
|
*/ |
571
|
|
|
private function setStatus(Entities\IPackage $package, string $status) |
572
|
|
|
{ |
573
|
|
|
if (!in_array($status, Entities\IPackage::STATUSES, TRUE)) { |
574
|
|
|
throw new Exceptions\InvalidArgumentException(sprintf('Status \'%s\' not exists.', $status)); |
575
|
|
|
} |
576
|
|
|
|
577
|
|
|
$packagesConfig = $this->getPackagesConfig(); |
578
|
|
|
|
579
|
|
|
// Check if package is registered |
580
|
|
|
if (!$packagesConfig->offsetExists($package->getName())) { |
581
|
|
|
throw new Exceptions\InvalidStateException(sprintf('Package "%s" is not registered. Please call ' . get_called_class() . '::registerAvailable first.', $package->getName())); |
582
|
|
|
} |
583
|
|
|
|
584
|
|
|
$packagesConfig[$package->getName()][self::PACKAGE_STATUS] = $status; |
585
|
|
|
|
586
|
|
|
$this->savePackagesConfig($packagesConfig); |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
/** |
590
|
|
|
* @param string $class |
591
|
|
|
* |
592
|
|
|
* @return Scripts\IScript |
593
|
|
|
* |
594
|
|
|
* @throws Exceptions\InvalidStateException |
595
|
|
|
*/ |
596
|
|
|
private function getScript(string $class) : Scripts\IScript |
597
|
|
|
{ |
598
|
|
|
if (isset($this->scripts[$class])) { |
599
|
|
|
return $this->scripts[$class]; |
600
|
|
|
} |
601
|
|
|
|
602
|
|
|
throw new Exceptions\InvalidStateException(sprintf('Package script "%s" was not found.', $class)); |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
/** |
606
|
|
|
* @return DependencyResolver\Solver |
607
|
|
|
*/ |
608
|
|
|
private function getDependencySolver() : DependencyResolver\Solver |
609
|
|
|
{ |
610
|
|
|
if ($this->dependencySolver === NULL) { |
611
|
|
|
$this->createSolver(); |
612
|
|
|
} |
613
|
|
|
|
614
|
|
|
return $this->dependencySolver; |
615
|
|
|
} |
616
|
|
|
|
617
|
|
|
/** |
618
|
|
|
* @return void |
619
|
|
|
*/ |
620
|
|
|
private function createSolver() |
621
|
|
|
{ |
622
|
|
|
$this->dependencySolver = new DependencyResolver\Solver($this->repository, $this); |
623
|
|
|
} |
624
|
|
|
|
625
|
|
|
/** |
626
|
|
|
* @return Utils\ArrayHash |
627
|
|
|
*/ |
628
|
|
|
private function getPackagesConfig() : Utils\ArrayHash |
629
|
|
|
{ |
630
|
|
|
if ($this->packagesConfig === NULL) { |
631
|
|
|
$config = new Nette\DI\Config\Adapters\PhpAdapter; |
632
|
|
|
|
633
|
|
|
if (!is_file($this->getPackageConfigPath())) { |
634
|
|
|
file_put_contents($this->getPackageConfigPath(), $config->dump([])); |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
$this->packagesConfig = Utils\ArrayHash::from($config->load($this->getPackageConfigPath())); |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
return $this->packagesConfig; |
641
|
|
|
} |
642
|
|
|
|
643
|
|
|
/** |
644
|
|
|
* @param Utils\ArrayHash $packagesConfig |
645
|
|
|
* |
646
|
|
|
* @throws Exceptions\NotWritableException |
647
|
|
|
*/ |
648
|
|
|
private function savePackagesConfig(Utils\ArrayHash $packagesConfig) |
649
|
|
|
{ |
650
|
|
|
$config = new Nette\DI\Config\Adapters\PhpAdapter; |
651
|
|
|
|
652
|
|
|
if (file_put_contents($this->getPackageConfigPath(), $config->dump(array_merge((array) $packagesConfig))) === FALSE) { |
653
|
|
|
throw new Exceptions\NotWritableException(sprintf('Packages configuration file "%s" is not writable.', $this->getPackageConfigPath())); |
654
|
|
|
}; |
655
|
|
|
|
656
|
|
|
// Refresh packages config data |
657
|
|
|
$this->packagesConfig = $packagesConfig; |
658
|
|
|
} |
659
|
|
|
|
660
|
|
|
/** |
661
|
|
|
* @return string |
662
|
|
|
*/ |
663
|
|
|
private function getPackageConfigPath() : string |
664
|
|
|
{ |
665
|
|
|
return $this->configDir . DIRECTORY_SEPARATOR . 'packages.php'; |
666
|
|
|
} |
667
|
|
|
} |
668
|
|
|
|
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.