From baf02bd30262262a5e0dd68c958eca99c03623fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Sun, 4 Oct 2020 21:48:44 +0200
Subject: [PATCH 1/8] Another approach to resolve feature of #9
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
---
src/ComponentInstaller.php | 37 ++++--
test/ComponentInstallerTest.php | 222 ++++++++++++++++++++++----------
2 files changed, 180 insertions(+), 79 deletions(-)
diff --git a/src/ComponentInstaller.php b/src/ComponentInstaller.php
index 21127dd..58277fd 100644
--- a/src/ComponentInstaller.php
+++ b/src/ComponentInstaller.php
@@ -10,7 +10,8 @@
use ArrayObject;
use Composer\Composer;
-use Composer\DependencyResolver\GenericRule;
+use Composer\DependencyResolver\Operation\InstallOperation;
+use Composer\DependencyResolver\Pool;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\PackageEvent;
use Composer\IO\IOInterface;
@@ -191,9 +192,9 @@ public function onPostPackageInstall(PackageEvent $event)
return;
}
- /** @var GenericRule $genericRule */
- $genericRule = $event->getOperation()->getReason();
- $package = $event->getOperation()->getPackage();
+ $operation = $event->getOperation();
+ assert($operation instanceof InstallOperation);
+ $package = $operation->getPackage();
$name = $package->getName();
$extra = $this->getExtraMetadata($package->getExtra());
@@ -211,13 +212,11 @@ public function onPostPackageInstall(PackageEvent $event)
return;
}
- $requireDev = $this->isADevDependency($genericRule, $name);
+ $requireDev = $this->isADevDependency($event->getPool(), $package);
$dependencies = $this->loadModuleClassesDependencies($package);
$applicationModules = $this->findApplicationModules();
$this->marshalInstallableModules($extra, $options)
- ->each(function ($module) use ($name) {
- })
// Create injectors
->reduce(function ($injectors, $module) use ($options, $packageTypes, $name, $requireDev) {
// Get extra from root package
@@ -432,7 +431,7 @@ private function marshalPackageModules(array $extra, Collection $packageTypes, C
*
* @param string[] $extra
* @param Collection $options
- * @return string[] List of packages to install
+ * @return Collection List of packages to install
*/
private function marshalInstallableModules(array $extra, Collection $options)
{
@@ -859,17 +858,27 @@ private function getModuleDependencies($file)
return [];
}
- private function isADevDependency(GenericRule $genericRule, string $name): bool
+ private function isADevDependency(Pool $pool, PackageInterface $package): bool
{
- if (array_key_exists($name, $this->composer->getPackage()->getDevRequires())) {
+ $packageName = $package->getName();
+ if (array_key_exists($packageName, $this->composer->getPackage()->getDevRequires())) {
return true;
}
- $dependentFor = is_string($genericRule->getReasonData())
- ? $genericRule->getReasonData()
- : $genericRule->getReasonData()->getSource();
+ $packages = $pool->whatProvides($packageName);
+ if (empty($packages)) {
+ return false;
+ }
+
+ $requirements = $this->composer->getPackage()->getRequires();
+ foreach ($packages as $parent) {
+ // Package is required by any package which is NOT a dev-requirement
+ if (isset($requirements[$parent->getName()])) {
+ return false;
+ }
+ }
- return array_key_exists($dependentFor, $this->composer->getPackage()->getDevRequires());
+ return true;
}
public function deactivate(Composer $composer, IOInterface $io)
diff --git a/test/ComponentInstallerTest.php b/test/ComponentInstallerTest.php
index c6fd836..57d0906 100644
--- a/test/ComponentInstallerTest.php
+++ b/test/ComponentInstallerTest.php
@@ -9,8 +9,8 @@
namespace LaminasTest\ComponentInstaller;
use Composer\Composer;
-use Composer\DependencyResolver\GenericRule;
use Composer\DependencyResolver\Operation\InstallOperation;
+use Composer\DependencyResolver\Pool;
use Composer\Installer\InstallationManager;
use Composer\Installer\PackageEvent;
use Composer\IO\IOInterface;
@@ -65,6 +65,11 @@ class ComponentInstallerTest extends TestCase
*/
private $installationManager;
+ /**
+ * @var Pool|\PHPUnit\Framework\MockObject\MockObject
+ */
+ private $pool;
+
protected function setUp() : void
{
$this->projectRoot = vfsStream::setup('project');
@@ -85,6 +90,8 @@ protected function setUp() : void
$this->installationManager = $this->prophesize(InstallationManager::class);
$this->composer->getInstallationManager()->willReturn($this->installationManager->reveal());
+
+ $this->pool = $this->createMock(Pool::class);
}
public static function assertPrompt($argument, $packageName = null)
@@ -176,17 +183,25 @@ public function getModuleDependencies()
$this->installationManager->getInstallPath(Argument::exact($package->reveal()))
->willReturn(vfsStream::url('project/' . $installPath));
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
-
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->pool
+ ->expects($this->atLeastOnce())
+ ->method('whatProvides')
+ ->with('some/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
+ $this->rootPackage
+ ->getRequires()
+ ->willReturn([]);
+
$this->io->ask(Argument::that(function ($argument) {
return ComponentInstallerTest::assertPrompt($argument, 'SomeComponent');
}), 1)->willReturn(1);
@@ -528,16 +543,22 @@ public function getModuleDependencies()
$this->installationManager->getInstallPath(Argument::exact($package->reveal()))
->willReturn(vfsStream::url('project/' . $installPath));
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io->ask(Argument::that(function ($argument) use ($packageName) {
return ComponentInstallerTest::assertPrompt($argument, $packageName);
}), 1)->willReturn(1);
@@ -627,16 +648,22 @@ public function testModuleBeforeApplicationModules(array $availableModules, arra
]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/module');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/module')
+ ->willReturn($package->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io->ask(Argument::that(function ($argument) {
return ComponentInstallerTest::assertPrompt($argument, 'SomeModule');
}), 1)->willReturn(1);
@@ -679,11 +706,8 @@ public function testPostPackageInstallDoesNothingIfComposerExtraIsEmpty()
$package->getName()->willReturn('some/component');
$package->getExtra()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
@@ -702,11 +726,8 @@ public function testOnPostPackageInstallReturnsEarlyIfApplicationConfigIsMissing
'module' => 'Some\\Component',
]]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
@@ -721,11 +742,8 @@ public function testPostPackageInstallDoesNothingIfLaminasExtraSectionDoesNotCon
$package->getName()->willReturn('some/component');
$package->getExtra()->willReturn(['laminas' => []]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
@@ -747,15 +765,20 @@ public function testOnPostPackageInstallDoesNotPromptIfPackageIsAlreadyInConfigu
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
$this->io->ask(Argument::any())->shouldNotBeCalled();
@@ -775,16 +798,22 @@ public function testOnPostPackageInstallDoesNotPromptForWhitelistedPackages()
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->rootPackage->getExtra()->willReturn(['laminas' => [
'component-whitelist' => ['some/component'],
]]);
@@ -809,16 +838,22 @@ public function testOnPostPackageInstallPromptsForConfigOptions()
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
return false;
@@ -876,16 +911,22 @@ public function testOnPostPackageInstallPromptsForConfigOptionsWhenDefinedAsArra
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
return false;
@@ -978,15 +1019,13 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanPromptMultipleTi
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $event->getPool()->willReturn($this->pool);
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1038,16 +1077,22 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanPromptMultipleTi
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('other/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
return false;
@@ -1103,16 +1148,15 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanReuseOptions()
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $event->getPool()->willReturn($this->pool);
+
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
return false;
@@ -1163,16 +1207,22 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanReuseOptions()
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->withConsecutive(['other/component'], ['some/component'])
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io->write(Argument::that(function ($argument) {
return strstr($argument, 'Installing Other\Component from package other/component');
}))->shouldBeCalled();
@@ -1213,11 +1263,8 @@ public function testOnPostPackageUninstallRemovesPackageFromConfiguration()
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
@@ -1258,16 +1305,22 @@ public function testOnPostPackageUninstallCanRemovePackageArraysFromConfiguratio
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io
->write(' Removing Some\Component from package some/component')
->shouldBeCalled();
@@ -1304,16 +1357,22 @@ public function testModuleIsAppended()
]]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/module')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
return false;
@@ -1375,16 +1434,22 @@ public function testAppendModuleAndPrependComponent()
'component' => 'Some\\Component',
]]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/package')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
return false;
@@ -1474,16 +1539,22 @@ public function testPrependComponentAndAppendModule()
'module' => 'Some\\Module',
]]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/package')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
return false;
@@ -1734,6 +1805,15 @@ public function testUninstallMessageWithDifferentInjectors($configContents, arra
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->io
->write(' Removing Some\Component from package some/component')
->shouldBeCalled();
@@ -1797,16 +1877,22 @@ public function testInstallWhitelistedDevModuleWithDifferentInjectors()
]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/component');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/component')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->assertNull($this->installer->onPostPackageInstall($event->reveal()));
$config = include vfsStream::url('project/config/modules.config.php');
$modules = $config['modules'];
@@ -1852,16 +1938,22 @@ public function testInstallWhitelistedDevModuleWithUniqueInjector()
]);
$package->getAutoload()->willReturn([]);
- $genericRule = $this->prophesize(GenericRule::class);
- $genericRule->getReasonData()->willReturn('some/module');
$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());
- $operation->getReason()->willReturn($genericRule->reveal());
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->rootPackage->getRequires()->willReturn([]);
+ $this->pool
+ ->expects($this->any())
+ ->method('whatProvides')
+ ->with('some/module')
+ ->willReturn($this->rootPackage->reveal());
+
+ $event->getPool()->willReturn($this->pool);
+
$this->assertNull($this->installer->onPostPackageInstall($event->reveal()));
$config = include vfsStream::url('project/config/modules.config.php');
$modules = $config['modules'];
From 07bd7c9fbf81e7d700f9d2ec0c5056dfe848e009 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Sun, 4 Oct 2020 22:46:15 +0200
Subject: [PATCH 2/8] Forward compatibility for composer v2
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
---
src/ComponentInstaller.php | 157 ++++++++++++------
src/PackageProvider/ComposerV1.php | 25 +++
src/PackageProvider/ComposerV2.php | 25 +++
.../PackageProviderDetectionFactory.php | 61 +++++++
.../PackageProviderDetectionInterface.php | 14 ++
test/ComponentInstallerTest.php | 121 ++++++--------
6 files changed, 277 insertions(+), 126 deletions(-)
create mode 100644 src/PackageProvider/ComposerV1.php
create mode 100644 src/PackageProvider/ComposerV2.php
create mode 100644 src/PackageProvider/PackageProviderDetectionFactory.php
create mode 100644 src/PackageProvider/PackageProviderDetectionInterface.php
diff --git a/src/ComponentInstaller.php b/src/ComponentInstaller.php
index 58277fd..258b16e 100644
--- a/src/ComponentInstaller.php
+++ b/src/ComponentInstaller.php
@@ -11,7 +11,6 @@
use ArrayObject;
use Composer\Composer;
use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Pool;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\PackageEvent;
use Composer\IO\IOInterface;
@@ -21,7 +20,8 @@
use Laminas\ComponentInstaller\Injector\AbstractInjector;
use Laminas\ComponentInstaller\Injector\ConfigInjectorChain;
use Laminas\ComponentInstaller\Injector\InjectorInterface;
-
+use Laminas\ComponentInstaller\PackageProvider\PackageProviderDetectionFactory;
+use Laminas\ComponentInstaller\PackageProvider\PackageProviderDetectionInterface;
use function array_filter;
use function array_flip;
use function array_key_exists;
@@ -122,6 +122,11 @@ class ComponentInstaller implements
*/
private $projectRoot;
+ /**
+ * @var callable(Composer $composer, PackageEvent $packageEvent, string $packageName):PackageProviderDetectionFactory
+ */
+ private $packageProviderFactory;
+
/**
* Constructor
*
@@ -129,11 +134,19 @@ class ComponentInstaller implements
*
* @param string $projectRoot
*/
- public function __construct($projectRoot = '')
+ public function __construct($projectRoot = '', callable $packageProviderFactory = null)
{
if (is_string($projectRoot) && ! empty($projectRoot) && is_dir($projectRoot)) {
$this->projectRoot = $projectRoot;
}
+ $this->packageProviderFactory = $packageProviderFactory ??
+ static function (
+ Composer $composer,
+ PackageEvent $event,
+ string $packageName
+ ): PackageProviderDetectionInterface {
+ return PackageProviderDetectionFactory::create($composer)->detect($event, $packageName);
+ };
}
/**
@@ -142,14 +155,15 @@ public function __construct($projectRoot = '')
* Sets internal pointers to Composer and IOInterface instances, and resets
* cached injector map.
*
- * @param Composer $composer
+ * @param Composer $composer
* @param IOInterface $io
+ *
* @return void
*/
public function activate(Composer $composer, IOInterface $io)
{
- $this->composer = $composer;
- $this->io = $io;
+ $this->composer = $composer;
+ $this->io = $io;
$this->cachedInjectors = [];
}
@@ -161,7 +175,7 @@ public function activate(Composer $composer, IOInterface $io)
public static function getSubscribedEvents()
{
return [
- 'post-package-install' => 'onPostPackageInstall',
+ 'post-package-install' => 'onPostPackageInstall',
'post-package-uninstall' => 'onPostPackageUninstall',
];
}
@@ -183,6 +197,7 @@ public static function getSubscribedEvents()
* writing their values into the `modules` list.
*
* @param PackageEvent $event
+ *
* @return void
*/
public function onPostPackageInstall(PackageEvent $event)
@@ -195,8 +210,8 @@ public function onPostPackageInstall(PackageEvent $event)
$operation = $event->getOperation();
assert($operation instanceof InstallOperation);
$package = $operation->getPackage();
- $name = $package->getName();
- $extra = $this->getExtraMetadata($package->getExtra());
+ $name = $package->getName();
+ $extra = $this->getExtraMetadata($package->getExtra());
if (empty($extra)) {
// Package does not define anything of interest; do nothing.
@@ -212,7 +227,8 @@ public function onPostPackageInstall(PackageEvent $event)
return;
}
- $requireDev = $this->isADevDependency($event->getPool(), $package);
+ $packageProviderDetection = ($this->packageProviderFactory)($this->composer, $event, $name);
+ $requireDev = $this->isADevDependency($packageProviderDetection, $package);
$dependencies = $this->loadModuleClassesDependencies($package);
$applicationModules = $this->findApplicationModules();
@@ -231,6 +247,7 @@ public function onPostPackageInstall(PackageEvent $event)
$whitelist,
$requireDev
);
+
return $injectors;
}, new Collection([]))
// Inject modules into configuration
@@ -249,13 +266,15 @@ public function onPostPackageInstall(PackageEvent $event)
* via method `getModuleDependencies` of Module class.
*
* These dependencies are used later
+ *
+ * @param PackageInterface $package
+ *
+ * @return array
* @see \Laminas\ComponentInstaller\Injector\AbstractInjector::injectAfterDependencies
- * to add component in a correct order on the module list - after dependencies.
+ * to add component in a correct order on the module list - after dependencies.
*
* It works with PSR-0, PSR-4, 'classmap' and 'files' composer autoloading.
*
- * @param PackageInterface $package
- * @return array
*/
private function loadModuleClassesDependencies(PackageInterface $package)
{
@@ -312,6 +331,7 @@ private function findApplicationModules()
* removing their values from the `modules` list.
*
* @param PackageEvent $event
+ *
* @return void
*/
public function onPostPackageUninstall(PackageEvent $event)
@@ -333,8 +353,8 @@ public function onPostPackageUninstall(PackageEvent $event)
}
$package = $event->getOperation()->getPackage();
- $name = $package->getName();
- $extra = $this->getExtraMetadata($package->getExtra());
+ $name = $package->getName();
+ $extra = $this->getExtraMetadata($package->getExtra());
$this->removePackageFromConfig($name, $extra, $options);
}
@@ -342,6 +362,7 @@ public function onPostPackageUninstall(PackageEvent $event)
* Retrieve the metadata from the "extra" section
*
* @param array $extra
+ *
* @return array
*/
private function getExtraMetadata(array $extra)
@@ -353,8 +374,7 @@ private function getExtraMetadata(array $extra)
// supports legacy "extra.zf" configuration
return isset($extra['zf']) && is_array($extra['zf'])
? $extra['zf']
- : []
- ;
+ : [];
}
/**
@@ -362,12 +382,14 @@ private function getExtraMetadata(array $extra)
* exposes in the extra configuration.
*
* @param string[] $extra
+ *
* @return Collection Collection of Injector\InjectorInterface::TYPE_* constants.
*/
private function discoverPackageTypes(array $extra)
{
$packageTypes = array_flip($this->packageTypes);
- $knownTypes = array_keys($packageTypes);
+ $knownTypes = array_keys($packageTypes);
+
return Collection::create($extra)
->filter(function ($packages, $type) use ($knownTypes) {
return in_array($type, $knownTypes, true);
@@ -378,6 +400,7 @@ private function discoverPackageTypes(array $extra)
foreach ($packages as $package) {
$discoveredTypes[$package] = $packageTypes[$type];
}
+
return $discoveredTypes;
}, new Collection([]));
}
@@ -386,6 +409,7 @@ private function discoverPackageTypes(array $extra)
* Marshal a collection of defined package types.
*
* @param array $extra extra.laminas value
+ *
* @return Collection
*/
private function marshalPackageTypes(array $extra)
@@ -400,9 +424,10 @@ private function marshalPackageTypes(array $extra)
/**
* Marshal a collection of package modules.
*
- * @param array $extra extra.laminas value
+ * @param array $extra extra.laminas value
* @param Collection $packageTypes
* @param Collection $options ConfigOption instances
+ *
* @return Collection
*/
private function marshalPackageModules(array $extra, Collection $packageTypes, Collection $options)
@@ -420,6 +445,7 @@ private function marshalPackageModules(array $extra, Collection $packageTypes, C
if (! in_array($type, $supportedTypes, true)) {
return $modules;
}
+
return $modules->merge((array) $extra[$configKey]);
}, new Collection([]))
// Make sure the list is unique
@@ -429,8 +455,9 @@ private function marshalPackageModules(array $extra, Collection $packageTypes, C
/**
* Prepare a list of modules to install/register with configuration.
*
- * @param string[] $extra
+ * @param string[] $extra
* @param Collection $options
+ *
* @return Collection List of packages to install
*/
private function marshalInstallableModules(array $extra, Collection $options)
@@ -447,11 +474,12 @@ private function marshalInstallableModules(array $extra, Collection $options)
/**
* Prompt for the user to select a configuration location to update.
*
- * @param string $name
+ * @param string $name
* @param Collection $options
- * @param int $packageType
- * @param string $packageName
- * @param array $whitelist
+ * @param int $packageType
+ * @param string $packageName
+ * @param array $whitelist
+ *
* @return Injector\InjectorInterface
*/
private function promptForConfigOption(
@@ -483,6 +511,7 @@ private function promptForConfigOption(
$index,
$option->getPromptText()
);
+
return $ask;
}, []);
@@ -498,6 +527,7 @@ private function promptForConfigOption(
if (is_numeric($answer) && isset($options[(int) $answer])) {
$injector = $options[(int) $answer]->getInjector();
$this->promptToRememberOption($injector, $packageType);
+
return $injector;
}
@@ -508,10 +538,11 @@ private function promptForConfigOption(
/**
* Prompt the user to determine if the selection should be remembered for later packages.
*
- * @todo Will need to store selection in filesystem and remove when all packages are complete
* @param Injector\InjectorInterface $injector
- * @param int $packageType
+ * @param int $packageType
* return void
+ *
+ * @todo Will need to store selection in filesystem and remove when all packages are complete
*/
private function promptToRememberOption(Injector\InjectorInterface $injector, $packageType)
{
@@ -523,6 +554,7 @@ private function promptToRememberOption(Injector\InjectorInterface $injector, $p
switch ($answer) {
case 'y':
$this->cacheInjector($injector, $packageType);
+
return;
case 'n':
// intentionally fall-through
@@ -535,10 +567,11 @@ private function promptToRememberOption(Injector\InjectorInterface $injector, $p
/**
* Inject a module into available configuration.
*
- * @param string $package Package name
- * @param string $module Module to install in configuration
+ * @param string $package Package name
+ * @param string $module Module to install in configuration
* @param Injector\InjectorInterface $injector Injector to use.
- * @param int $packageType
+ * @param int $packageType
+ *
* @return void
*/
private function injectModuleIntoConfig($package, $module, Injector\InjectorInterface $injector, $packageType)
@@ -560,10 +593,11 @@ private function injectModuleIntoConfig($package, $module, Injector\InjectorInte
/**
* Remove a package from configuration.
*
- * @param string $package Package name
- * @param array $metadata Metadata pulled from extra.laminas
+ * @param string $package Package name
+ * @param array $metadata Metadata pulled from extra.laminas
* @param Collection $configOptions Discovered configuration options from
- * which to remove package.
+ * which to remove package.
+ *
* @return void
*/
private function removePackageFromConfig($package, array $metadata, Collection $configOptions)
@@ -594,9 +628,10 @@ private function removePackageFromConfig($package, array $metadata, Collection $
/**
* Remove an individual module defined in a package from configuration.
*
- * @param string $module Module to remove
- * @param string $package Package in which module is defined
+ * @param string $module Module to remove
+ * @param string $package Package in which module is defined
* @param Collection $injectors Injectors to use for removal
+ *
* @return void
*/
private function removeModuleFromConfig($module, $package, Collection $injectors)
@@ -615,6 +650,7 @@ private function removeModuleFromConfig($module, $package, Collection $injectors
/**
* @param InjectorInterface $injector
+ *
* @return string
* @todo remove after InjectorInterface has getConfigName defined
*/
@@ -631,6 +667,7 @@ private function getInjectorConfigFileName(InjectorInterface $injector)
/**
* @param ConfigInjectorChain $injector
+ *
* @return string
* @todo remove after InjectorInterface has getConfigName defined
*/
@@ -643,6 +680,7 @@ private function getInjectorChainConfigFileName(ConfigInjectorChain $injector)
/**
* @param AbstractInjector $injector
+ *
* @return string
* @todo remove after InjectorInterface has getConfigName defined
*/
@@ -655,6 +693,7 @@ private function getAbstractInjectorConfigFileName(AbstractInjector $injector)
* Is a given module name valid?
*
* @param string $module
+ *
* @return bool
*/
private function moduleIsValid($module)
@@ -666,7 +705,8 @@ private function moduleIsValid($module)
* Is a given metadata value (extra.laminas.*) valid?
*
* @param string $key Key to examine in metadata
- * @param array $metadata
+ * @param array $metadata
+ *
* @return bool
*/
private function metadataForKeyIsValid($key, array $metadata)
@@ -688,6 +728,7 @@ private function metadataForKeyIsValid($key, array $metadata)
if (false === $valid) {
return $valid;
}
+
return $this->moduleIsValid($value);
}, null);
}
@@ -696,6 +737,7 @@ private function metadataForKeyIsValid($key, array $metadata)
* Attempt to retrieve a cached injector for the current package type.
*
* @param int $packageType
+ *
* @return null|Injector\InjectorInterface
*/
private function getCachedInjector($packageType)
@@ -711,7 +753,8 @@ private function getCachedInjector($packageType)
* Cache an injector for later use.
*
* @param Injector\InjectorInterface $injector
- * @param int $packageType
+ * @param int $packageType
+ *
* @return void
*/
private function cacheInjector(Injector\InjectorInterface $injector, $packageType)
@@ -722,9 +765,10 @@ private function cacheInjector(Injector\InjectorInterface $injector, $packageTyp
/**
* Iterate through each autoloader type to find dependencies.
*
- * @param array $autoload List of autoloader types and associated autoloader definitions.
+ * @param array $autoload List of autoloader types and associated autoloader definitions.
* @param ArrayObject $dependencies Module dependencies defined by the module.
- * @param string $packagePath Path to the package on the filesystem.
+ * @param string $packagePath Path to the package on the filesystem.
+ *
* @return void
*/
private function mapAutoloaders(array $autoload, ArrayObject $dependencies, $packagePath)
@@ -737,10 +781,11 @@ private function mapAutoloaders(array $autoload, ArrayObject $dependencies, $pac
/**
* Iterate through a single autolaoder type to find dependencies.
*
- * @param array $map Map of namespace => path(s) pairs.
- * @param string $type Type of autoloader being iterated.
+ * @param array $map Map of namespace => path(s) pairs.
+ * @param string $type Type of autoloader being iterated.
* @param ArrayObject $dependencies Module dependencies defined by the module.
- * @param string $packagePath Path to the package on the filesystem.
+ * @param string $packagePath Path to the package on the filesystem.
+ *
* @return void
*/
private function mapType(array $map, $type, ArrayObject $dependencies, $packagePath)
@@ -754,11 +799,12 @@ private function mapType(array $map, $type, ArrayObject $dependencies, $packageP
/**
* Iterate through the paths defined for a given namespace.
*
- * @param array $paths Paths defined for the given namespace.
- * @param string $namespace PHP namespace to which the paths map.
- * @param string $type Type of autoloader being iterated.
+ * @param array $paths Paths defined for the given namespace.
+ * @param string $namespace PHP namespace to which the paths map.
+ * @param string $type Type of autoloader being iterated.
* @param ArrayObject $dependencies Module dependencies defined by the module.
- * @param string $packagePath Path to the package on the filesystem.
+ * @param string $packagePath Path to the package on the filesystem.
+ *
* @return void
*/
private function mapNamespacePaths(array $paths, $namespace, $type, ArrayObject $dependencies, $packagePath)
@@ -771,11 +817,12 @@ private function mapNamespacePaths(array $paths, $namespace, $type, ArrayObject
/**
* Find module dependencies for a given namespace for a given path.
*
- * @param string $path Path to inspect.
- * @param string $namespace PHP namespace to which the paths map.
- * @param string $type Type of autoloader being iterated.
+ * @param string $path Path to inspect.
+ * @param string $namespace PHP namespace to which the paths map.
+ * @param string $type Type of autoloader being iterated.
* @param ArrayObject $dependencies Module dependencies defined by the module.
- * @param string $packagePath Path to the package on the filesystem.
+ * @param string $packagePath Path to the package on the filesystem.
+ *
* @return void
*/
private function mapPath($path, $namespace, $type, ArrayObject $dependencies, $packagePath)
@@ -833,6 +880,7 @@ private function mapPath($path, $namespace, $type, ArrayObject $dependencies, $p
/**
* @param string $file
+ *
* @return array
*/
private function getModuleDependencies($file)
@@ -858,14 +906,17 @@ private function getModuleDependencies($file)
return [];
}
- private function isADevDependency(Pool $pool, PackageInterface $package): bool
- {
+ private function isADevDependency(
+ PackageProviderDetectionInterface $packageProviderDetection,
+ PackageInterface $package
+ ): bool {
$packageName = $package->getName();
- if (array_key_exists($packageName, $this->composer->getPackage()->getDevRequires())) {
+ $devRequirements = $this->composer->getPackage()->getDevRequires();
+ if (isset($devRequirements[$packageName])) {
return true;
}
- $packages = $pool->whatProvides($packageName);
+ $packages = $packageProviderDetection->whatProvides($packageName);
if (empty($packages)) {
return false;
}
diff --git a/src/PackageProvider/ComposerV1.php b/src/PackageProvider/ComposerV1.php
new file mode 100644
index 0000000..1ee310f
--- /dev/null
+++ b/src/PackageProvider/ComposerV1.php
@@ -0,0 +1,25 @@
+pool = $pool;
+ }
+
+ public function whatProvides(string $packageName): array
+ {
+ return $this->pool->whatProvides($packageName);
+ }
+}
diff --git a/src/PackageProvider/ComposerV2.php b/src/PackageProvider/ComposerV2.php
new file mode 100644
index 0000000..59183b4
--- /dev/null
+++ b/src/PackageProvider/ComposerV2.php
@@ -0,0 +1,25 @@
+installedRepository = $installedRepository;
+ }
+
+ public function whatProvides(string $packageName): array
+ {
+ return $this->installedRepository->findPackagesWithReplacersAndProviders($packageName);
+ }
+}
diff --git a/src/PackageProvider/PackageProviderDetectionFactory.php b/src/PackageProvider/PackageProviderDetectionFactory.php
new file mode 100644
index 0000000..f8baaae
--- /dev/null
+++ b/src/PackageProvider/PackageProviderDetectionFactory.php
@@ -0,0 +1,61 @@
+composer = $composer;
+ }
+
+ public static function create(Composer $composer): self
+ {
+ return new self($composer);
+ }
+
+ public static function isComposerV1(): bool
+ {
+ return version_compare(PluginInterface::PLUGIN_API_VERSION, '2.0.0', '<') === true;
+ }
+
+ public function detect(PackageEvent $event, string $packageName): PackageProviderDetectionInterface
+ {
+ if (self::isComposerV1()) {
+ return new ComposerV1($event->getPool());
+ }
+
+ $platformOverrides = $this->composer->getConfig()->get('platform') ?? [];
+
+ $installedRepo = new InstalledRepository([
+ new RootPackageRepository($this->composer->getPackage()),
+ $this->composer->getRepositoryManager()->getLocalRepository(),
+ new PlatformRepository([], $platformOverrides),
+ ]);
+
+ $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos());
+ if ($match = $defaultRepos->findPackage($packageName, '')) {
+ $installedRepo->addRepository(new InstalledArrayRepository([clone $match]));
+ }
+
+ return new ComposerV2($installedRepo);
+ }
+}
diff --git a/src/PackageProvider/PackageProviderDetectionInterface.php b/src/PackageProvider/PackageProviderDetectionInterface.php
new file mode 100644
index 0000000..67c9f9a
--- /dev/null
+++ b/src/PackageProvider/PackageProviderDetectionInterface.php
@@ -0,0 +1,14 @@
+projectRoot = vfsStream::setup('project');
- $this->installer = new ComponentInstaller(vfsStream::url('project'));
+ $this->packageProviderDetection = $this->createMock(PackageProviderDetectionInterface::class);
+ $this->installer = new ComponentInstaller(
+ vfsStream::url('project'),
+ function (Composer $composer, PackageEvent $event, string $packageName): PackageProviderDetectionInterface {
+ return $this->packageProviderDetection;
+ }
+ );
$this->composer = $this->prophesize(Composer::class);
$this->rootPackage = $this->prophesize(RootPackageInterface::class);
@@ -90,8 +98,6 @@ protected function setUp() : void
$this->installationManager = $this->prophesize(InstallationManager::class);
$this->composer->getInstallationManager()->willReturn($this->installationManager->reveal());
-
- $this->pool = $this->createMock(Pool::class);
}
public static function assertPrompt($argument, $packageName = null)
@@ -190,13 +196,11 @@ public function getModuleDependencies()
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
- $this->pool
+ $this->packageProviderDetection
->expects($this->atLeastOnce())
->method('whatProvides')
->with('some/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->rootPackage
->getRequires()
@@ -551,13 +555,11 @@ public function getModuleDependencies()
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io->ask(Argument::that(function ($argument) use ($packageName) {
return ComponentInstallerTest::assertPrompt($argument, $packageName);
@@ -656,13 +658,11 @@ public function testModuleBeforeApplicationModules(array $availableModules, arra
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/module')
- ->willReturn($package->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([$package->reveal()]);
$this->io->ask(Argument::that(function ($argument) {
return ComponentInstallerTest::assertPrompt($argument, 'SomeModule');
@@ -772,13 +772,11 @@ public function testOnPostPackageInstallDoesNotPromptIfPackageIsAlreadyInConfigu
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io->ask(Argument::any())->shouldNotBeCalled();
@@ -806,13 +804,11 @@ public function testOnPostPackageInstallDoesNotPromptForWhitelistedPackages()
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->rootPackage->getExtra()->willReturn(['laminas' => [
'component-whitelist' => ['some/component'],
@@ -846,13 +842,11 @@ public function testOnPostPackageInstallPromptsForConfigOptions()
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -919,13 +913,11 @@ public function testOnPostPackageInstallPromptsForConfigOptionsWhenDefinedAsArra
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1025,7 +1017,6 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanPromptMultipleTi
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
- $event->getPool()->willReturn($this->pool);
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1085,13 +1076,11 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanPromptMultipleTi
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('other/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1155,8 +1144,6 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanReuseOptions()
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
- $event->getPool()->willReturn($this->pool);
-
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
return false;
@@ -1215,13 +1202,11 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanReuseOptions()
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->withConsecutive(['other/component'], ['some/component'])
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io->write(Argument::that(function ($argument) {
return strstr($argument, 'Installing Other\Component from package other/component');
@@ -1313,13 +1298,11 @@ public function testOnPostPackageUninstallCanRemovePackageArraysFromConfiguratio
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io
->write(' Removing Some\Component from package some/component')
@@ -1365,13 +1348,11 @@ public function testModuleIsAppended()
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/module')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1442,13 +1423,11 @@ public function testAppendModuleAndPrependComponent()
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/package')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1547,13 +1526,11 @@ public function testPrependComponentAndAppendModule()
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/package')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1806,13 +1783,11 @@ public function testUninstallMessageWithDifferentInjectors($configContents, arra
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->io
->write(' Removing Some\Component from package some/component')
@@ -1857,7 +1832,7 @@ public function testInstallWhitelistedDevModuleWithDifferentInjectors()
$this->createConfigFile($configName, $configContents);
}
- $this->rootPackage->getDevRequires()->willReturn(['some/component' => null]);
+ $this->rootPackage->getDevRequires()->willReturn(['some/component' => '*']);
$this->rootPackage->getExtra()->willReturn([
'laminas' => [
"component-whitelist" => [
@@ -1885,13 +1860,11 @@ public function testInstallWhitelistedDevModuleWithDifferentInjectors()
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/component')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->assertNull($this->installer->onPostPackageInstall($event->reveal()));
$config = include vfsStream::url('project/config/modules.config.php');
@@ -1946,13 +1919,11 @@ public function testInstallWhitelistedDevModuleWithUniqueInjector()
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->pool
+ $this->packageProviderDetection
->expects($this->any())
->method('whatProvides')
->with('some/module')
- ->willReturn($this->rootPackage->reveal());
-
- $event->getPool()->willReturn($this->pool);
+ ->willReturn([]);
$this->assertNull($this->installer->onPostPackageInstall($event->reveal()));
$config = include vfsStream::url('project/config/modules.config.php');
@@ -2005,4 +1976,8 @@ private function createConfigFile($name, $contents)
->at($this->projectRoot)
->setContent($contents);
}
+
+ private function prepareEventForPackageProviderDetection(ObjectProphecy $event): ObjectProphecy
+ {
+ }
}
From 21ae20b4cd6546d0527c3685c4890c63c3d868d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Sun, 4 Oct 2020 22:54:28 +0200
Subject: [PATCH 3/8] Add `final` keyword to `PackageProviderDetectionFactory`
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
---
src/PackageProvider/PackageProviderDetectionFactory.php | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/PackageProvider/PackageProviderDetectionFactory.php b/src/PackageProvider/PackageProviderDetectionFactory.php
index f8baaae..b68a133 100644
--- a/src/PackageProvider/PackageProviderDetectionFactory.php
+++ b/src/PackageProvider/PackageProviderDetectionFactory.php
@@ -5,7 +5,6 @@
use Composer\Composer;
use Composer\Installer\PackageEvent;
-use Composer\Package\PackageInterface;
use Composer\Plugin\PluginInterface;
use Composer\Repository\CompositeRepository;
use Composer\Repository\InstalledArrayRepository;
@@ -15,7 +14,7 @@
use Composer\Repository\RootPackageRepository;
use function version_compare;
-class PackageProviderDetectionFactory
+final class PackageProviderDetectionFactory
{
/**
* @var Composer
From 1afc845d446f00fbd376e50ba5b9d0caef4ffb75 Mon Sep 17 00:00:00 2001
From: kpicaza <1093654+kpicaza@users.noreply.github.com>
Date: Mon, 12 Oct 2020 12:40:04 +0200
Subject: [PATCH 4/8] fix issues in composer2
Signed-off-by: kpicaza <1093654+kpicaza@users.noreply.github.com>
---
src/PackageProvider/PackageProviderDetectionFactory.php | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/PackageProvider/PackageProviderDetectionFactory.php b/src/PackageProvider/PackageProviderDetectionFactory.php
index b68a133..400c313 100644
--- a/src/PackageProvider/PackageProviderDetectionFactory.php
+++ b/src/PackageProvider/PackageProviderDetectionFactory.php
@@ -5,6 +5,7 @@
use Composer\Composer;
use Composer\Installer\PackageEvent;
+use Composer\IO\NullIO;
use Composer\Plugin\PluginInterface;
use Composer\Repository\CompositeRepository;
use Composer\Repository\InstalledArrayRepository;
@@ -45,13 +46,14 @@ public function detect(PackageEvent $event, string $packageName): PackageProvide
$platformOverrides = $this->composer->getConfig()->get('platform') ?? [];
$installedRepo = new InstalledRepository([
- new RootPackageRepository($this->composer->getPackage()),
$this->composer->getRepositoryManager()->getLocalRepository(),
new PlatformRepository([], $platformOverrides),
]);
- $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos());
- if ($match = $defaultRepos->findPackage($packageName, '')) {
+ $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos(new NullIO()));
+ if (($match = $defaultRepos->findPackage($packageName, '*'))
+ && false === $installedRepo->hasPackage($match)
+ ) {
$installedRepo->addRepository(new InstalledArrayRepository([clone $match]));
}
From 336476d7a7c050c24445dda455368cfe7cbc3301 Mon Sep 17 00:00:00 2001
From: kpicaza <1093654+kpicaza@users.noreply.github.com>
Date: Fri, 23 Oct 2020 21:31:40 +0200
Subject: [PATCH 5/8] Enable root package on composer2
Signed-off-by: kpicaza <1093654+kpicaza@users.noreply.github.com>
---
src/ComponentInstaller.php | 26 +++++++++++++++---
src/PackageProvider/ComposerV1.php | 7 +++++
src/PackageProvider/ComposerV2.php | 7 +++++
.../PackageProviderDetectionFactory.php | 15 +++++++++--
.../PackageProviderDetectionInterface.php | 7 +++++
test/ComponentInstallerTest.php | 27 +++++++++++++++++--
6 files changed, 82 insertions(+), 7 deletions(-)
diff --git a/src/ComponentInstaller.php b/src/ComponentInstaller.php
index 258b16e..b97ee3f 100644
--- a/src/ComponentInstaller.php
+++ b/src/ComponentInstaller.php
@@ -16,6 +16,7 @@
use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;
use Composer\Plugin\PluginInterface;
+use Composer\Repository\RootPackageRepository;
use DirectoryIterator;
use Laminas\ComponentInstaller\Injector\AbstractInjector;
use Laminas\ComponentInstaller\Injector\ConfigInjectorChain;
@@ -123,10 +124,20 @@ class ComponentInstaller implements
private $projectRoot;
/**
- * @var callable(Composer $composer, PackageEvent $packageEvent, string $packageName):PackageProviderDetectionFactory
+ * @var callable(
+ * Composer $composer,
+ * PackageEvent $packageEvent,
+ * ?RootPackageRepository $rootRepository,
+ * string $packageName
+ * ): PackageProviderDetectionFactory
*/
private $packageProviderFactory;
+ /**
+ * @var ?RootPackageRepository
+ */
+ private $rootRepository = null;
+
/**
* Constructor
*
@@ -143,9 +154,10 @@ public function __construct($projectRoot = '', callable $packageProviderFactory
static function (
Composer $composer,
PackageEvent $event,
+ ?RootPackageRepository $rootRepository,
string $packageName
): PackageProviderDetectionInterface {
- return PackageProviderDetectionFactory::create($composer)->detect($event, $packageName);
+ return PackageProviderDetectionFactory::create($composer)->detect($event, $packageName, $rootRepository);
};
}
@@ -165,6 +177,9 @@ public function activate(Composer $composer, IOInterface $io)
$this->composer = $composer;
$this->io = $io;
$this->cachedInjectors = [];
+ if (false === PackageProviderDetectionFactory::isComposerV1()) {
+ $this->rootRepository = new RootPackageRepository($this->composer->getPackage());
+ }
}
/**
@@ -227,7 +242,12 @@ public function onPostPackageInstall(PackageEvent $event)
return;
}
- $packageProviderDetection = ($this->packageProviderFactory)($this->composer, $event, $name);
+ $packageProviderDetection = ($this->packageProviderFactory)(
+ $this->composer,
+ $event,
+ $this->rootRepository,
+ $name
+ );
$requireDev = $this->isADevDependency($packageProviderDetection, $package);
$dependencies = $this->loadModuleClassesDependencies($package);
$applicationModules = $this->findApplicationModules();
diff --git a/src/PackageProvider/ComposerV1.php b/src/PackageProvider/ComposerV1.php
index 1ee310f..7b49856 100644
--- a/src/PackageProvider/ComposerV1.php
+++ b/src/PackageProvider/ComposerV1.php
@@ -1,4 +1,11 @@
getPool());
}
@@ -46,6 +56,7 @@ public function detect(PackageEvent $event, string $packageName): PackageProvide
$platformOverrides = $this->composer->getConfig()->get('platform') ?? [];
$installedRepo = new InstalledRepository([
+ $packageRepository,
$this->composer->getRepositoryManager()->getLocalRepository(),
new PlatformRepository([], $platformOverrides),
]);
diff --git a/src/PackageProvider/PackageProviderDetectionInterface.php b/src/PackageProvider/PackageProviderDetectionInterface.php
index 67c9f9a..34d6126 100644
--- a/src/PackageProvider/PackageProviderDetectionInterface.php
+++ b/src/PackageProvider/PackageProviderDetectionInterface.php
@@ -1,4 +1,11 @@
packageProviderDetection = $this->createMock(PackageProviderDetectionInterface::class);
$this->installer = new ComponentInstaller(
vfsStream::url('project'),
- function (Composer $composer, PackageEvent $event, string $packageName): PackageProviderDetectionInterface {
+ function (
+ Composer $composer,
+ PackageEvent $event,
+ ?RootPackageRepository $repository,
+ string $packageName
+ ): PackageProviderDetectionInterface {
return $this->packageProviderDetection;
}
);
@@ -88,8 +99,20 @@ function (Composer $composer, PackageEvent $event, string $packageName): Package
$this->io = $this->prophesize(IOInterface::class);
$this->composer->getPackage()->willReturn($this->rootPackage->reveal());
- $this->rootPackage->getExtra()->willReturn([]);
+ $config = $this->prophesize(Config::class);
+
$this->rootPackage->getDevRequires()->willReturn([]);
+ $this->rootPackage->getExtra()->willReturn([]);
+ if (false === PackageProviderDetectionFactory::isComposerV1()) {
+ $this->composer->getConfig()->willReturn($config->reveal());
+ $repositoryManager = $this->prophesize(RepositoryManager::class);
+ $localRepository = $this->prophesize(PlatformRepository::class);
+ $repositoryManager->getLocalRepository()->willReturn($localRepository->reveal());
+ $this->composer->getRepositoryManager()->willReturn($repositoryManager->reveal());
+ $this->rootPackage
+ ->setRepository(Argument::type(RootPackageRepository::class))
+ ->willReturn([]);
+ }
$this->installer->activate(
$this->composer->reveal(),
From 71dd7d5e125b90a2142e1db462f00a0a62de35f0 Mon Sep 17 00:00:00 2001
From: kpicaza <1093654+kpicaza@users.noreply.github.com>
Date: Sat, 24 Oct 2020 13:50:09 +0200
Subject: [PATCH 6/8] use root repository on package provider
Signed-off-by: kpicaza <1093654+kpicaza@users.noreply.github.com>
---
.travis.yml | 9 +
src/ComponentInstaller.php | 36 +---
.../PackageProviderDetectionFactory.php | 16 +-
test/ComponentInstallerTest.php | 163 +++++++-----------
4 files changed, 81 insertions(+), 143 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 4377483..db1d45e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -38,6 +38,14 @@ matrix:
- php: 7.4
env:
- DEPS=latest
+ - php: 7.4
+ env:
+ - DEPS=lowest
+ - COMPOSER_VERSION=2
+ - php: 7.4
+ env:
+ - DEPS=latest
+ - COMPOSER_VERSION=2
before_install:
- if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi
@@ -45,6 +53,7 @@ before_install:
install:
- travis_retry composer install $COMPOSER_ARGS --ignore-platform-reqs
- if [[ $LEGACY_DEPS != '' ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies $LEGACY_DEPS ; fi
+ - if [[ $COMPOSER_VERSION == '2' ]]; then travis_retry composer self-update --2 ; fi
- if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi
- if [[ $DEPS == 'lowest' ]]; then travis_retry composer update $COMPOSER_ARGS --prefer-lowest --prefer-stable ; fi
- if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi
diff --git a/src/ComponentInstaller.php b/src/ComponentInstaller.php
index b97ee3f..7c348da 100644
--- a/src/ComponentInstaller.php
+++ b/src/ComponentInstaller.php
@@ -16,7 +16,6 @@
use Composer\IO\IOInterface;
use Composer\Package\PackageInterface;
use Composer\Plugin\PluginInterface;
-use Composer\Repository\RootPackageRepository;
use DirectoryIterator;
use Laminas\ComponentInstaller\Injector\AbstractInjector;
use Laminas\ComponentInstaller\Injector\ConfigInjectorChain;
@@ -25,7 +24,6 @@
use Laminas\ComponentInstaller\PackageProvider\PackageProviderDetectionInterface;
use function array_filter;
use function array_flip;
-use function array_key_exists;
use function array_keys;
use function array_map;
use function array_unshift;
@@ -124,20 +122,10 @@ class ComponentInstaller implements
private $projectRoot;
/**
- * @var callable(
- * Composer $composer,
- * PackageEvent $packageEvent,
- * ?RootPackageRepository $rootRepository,
- * string $packageName
- * ): PackageProviderDetectionFactory
+ * @var PackageProviderDetectionFactory
*/
private $packageProviderFactory;
- /**
- * @var ?RootPackageRepository
- */
- private $rootRepository = null;
-
/**
* Constructor
*
@@ -145,20 +133,11 @@ class ComponentInstaller implements
*
* @param string $projectRoot
*/
- public function __construct($projectRoot = '', callable $packageProviderFactory = null)
+ public function __construct($projectRoot = '')
{
if (is_string($projectRoot) && ! empty($projectRoot) && is_dir($projectRoot)) {
$this->projectRoot = $projectRoot;
}
- $this->packageProviderFactory = $packageProviderFactory ??
- static function (
- Composer $composer,
- PackageEvent $event,
- ?RootPackageRepository $rootRepository,
- string $packageName
- ): PackageProviderDetectionInterface {
- return PackageProviderDetectionFactory::create($composer)->detect($event, $packageName, $rootRepository);
- };
}
/**
@@ -177,9 +156,7 @@ public function activate(Composer $composer, IOInterface $io)
$this->composer = $composer;
$this->io = $io;
$this->cachedInjectors = [];
- if (false === PackageProviderDetectionFactory::isComposerV1()) {
- $this->rootRepository = new RootPackageRepository($this->composer->getPackage());
- }
+ $this->packageProviderFactory = PackageProviderDetectionFactory::create($composer);
}
/**
@@ -242,12 +219,7 @@ public function onPostPackageInstall(PackageEvent $event)
return;
}
- $packageProviderDetection = ($this->packageProviderFactory)(
- $this->composer,
- $event,
- $this->rootRepository,
- $name
- );
+ $packageProviderDetection = $this->packageProviderFactory->detect($event, $name);
$requireDev = $this->isADevDependency($packageProviderDetection, $package);
$dependencies = $this->loadModuleClassesDependencies($package);
$applicationModules = $this->findApplicationModules();
diff --git a/src/PackageProvider/PackageProviderDetectionFactory.php b/src/PackageProvider/PackageProviderDetectionFactory.php
index d25fce1..d643459 100644
--- a/src/PackageProvider/PackageProviderDetectionFactory.php
+++ b/src/PackageProvider/PackageProviderDetectionFactory.php
@@ -28,10 +28,17 @@ final class PackageProviderDetectionFactory
* @var Composer
*/
private $composer;
+ /**
+ * @var null|RootPackageRepository
+ */
+ private $packageRepository = null;
public function __construct(Composer $composer)
{
$this->composer = $composer;
+ if (false === self::isComposerV1()) {
+ $this->packageRepository = new RootPackageRepository($composer->getPackage());
+ }
}
public static function create(Composer $composer): self
@@ -44,11 +51,8 @@ public static function isComposerV1(): bool
return version_compare(PluginInterface::PLUGIN_API_VERSION, '2.0.0', '<') === true;
}
- public function detect(
- PackageEvent $event,
- string $packageName,
- ?RootPackageRepository $packageRepository
- ): PackageProviderDetectionInterface {
+ public function detect(PackageEvent $event, string $packageName): PackageProviderDetectionInterface
+ {
if (self::isComposerV1()) {
return new ComposerV1($event->getPool());
}
@@ -56,7 +60,7 @@ public function detect(
$platformOverrides = $this->composer->getConfig()->get('platform') ?? [];
$installedRepo = new InstalledRepository([
- $packageRepository,
+ $this->packageRepository,
$this->composer->getRepositoryManager()->getLocalRepository(),
new PlatformRepository([], $platformOverrides),
]);
diff --git a/test/ComponentInstallerTest.php b/test/ComponentInstallerTest.php
index e75d631..df23695 100644
--- a/test/ComponentInstallerTest.php
+++ b/test/ComponentInstallerTest.php
@@ -18,15 +18,12 @@
use Composer\Package\PackageInterface;
use Composer\Package\RootPackageInterface;
use Composer\Repository\PlatformRepository;
-use Composer\Repository\RepositoryInterface;
use Composer\Repository\RepositoryManager;
use Composer\Repository\RootPackageRepository;
use Laminas\ComponentInstaller\ComponentInstaller;
use Laminas\ComponentInstaller\PackageProvider\PackageProviderDetectionFactory;
-use Laminas\ComponentInstaller\PackageProvider\PackageProviderDetectionInterface;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
-use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
@@ -73,47 +70,33 @@ class ComponentInstallerTest extends TestCase
*/
private $installationManager;
- /**
- * @var PackageProviderDetectionInterface|MockObject
- */
- private $packageProviderDetection;
-
protected function setUp() : void
{
$this->projectRoot = vfsStream::setup('project');
- $this->packageProviderDetection = $this->createMock(PackageProviderDetectionInterface::class);
$this->installer = new ComponentInstaller(
- vfsStream::url('project'),
- function (
- Composer $composer,
- PackageEvent $event,
- ?RootPackageRepository $repository,
- string $packageName
- ): PackageProviderDetectionInterface {
- return $this->packageProviderDetection;
- }
+ vfsStream::url('project')
);
$this->composer = $this->prophesize(Composer::class);
$this->rootPackage = $this->prophesize(RootPackageInterface::class);
$this->io = $this->prophesize(IOInterface::class);
- $this->composer->getPackage()->willReturn($this->rootPackage->reveal());
- $config = $this->prophesize(Config::class);
-
$this->rootPackage->getDevRequires()->willReturn([]);
$this->rootPackage->getExtra()->willReturn([]);
if (false === PackageProviderDetectionFactory::isComposerV1()) {
+ $config = $this->prophesize(Config::class);
$this->composer->getConfig()->willReturn($config->reveal());
$repositoryManager = $this->prophesize(RepositoryManager::class);
$localRepository = $this->prophesize(PlatformRepository::class);
+ $localRepository->getPackages()->willReturn([]);
$repositoryManager->getLocalRepository()->willReturn($localRepository->reveal());
$this->composer->getRepositoryManager()->willReturn($repositoryManager->reveal());
- $this->rootPackage
- ->setRepository(Argument::type(RootPackageRepository::class))
- ->willReturn([]);
+ $this->rootPackage->getProvides()->willReturn([]);
+ $this->rootPackage->getReplaces()->willReturn([]);
+ $this->rootPackage->setRepository(Argument::type(RootPackageRepository::class))->willReturn([]);
}
+ $this->composer->getPackage()->willReturn($this->rootPackage->reveal());
$this->installer->activate(
$this->composer->reveal(),
$this->io->reveal()
@@ -218,12 +201,11 @@ public function getModuleDependencies()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/component');
- $this->packageProviderDetection
- ->expects($this->atLeastOnce())
- ->method('whatProvides')
- ->with('some/component')
- ->willReturn([]);
+ $this->rootPackage
+ ->getName()
+ ->willReturn('some/component');
$this->rootPackage
->getRequires()
@@ -576,13 +558,12 @@ public function getModuleDependencies()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/component');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/component')
- ->willReturn([]);
+ $this->rootPackage
+ ->getName()
+ ->willReturn('some/component');
$this->io->ask(Argument::that(function ($argument) use ($packageName) {
return ComponentInstallerTest::assertPrompt($argument, $packageName);
@@ -679,13 +660,12 @@ public function testModuleBeforeApplicationModules(array $availableModules, arra
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/module');
+ $this->prepareEventForPackageProviderDetection($event, 'some/module');
+
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/module')
- ->willReturn([$package->reveal()]);
+ $this->rootPackage->getName()->willReturn('some/component');
$this->io->ask(Argument::that(function ($argument) {
return ComponentInstallerTest::assertPrompt($argument, 'SomeModule');
@@ -794,12 +774,9 @@ public function testOnPostPackageInstallDoesNotPromptIfPackageIsAlreadyInConfigu
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/component');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/component')
- ->willReturn([]);
+ $this->rootPackage->getName()->willReturn('some/component');
$this->io->ask(Argument::any())->shouldNotBeCalled();
@@ -825,13 +802,10 @@ public function testOnPostPackageInstallDoesNotPromptForWhitelistedPackages()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/component');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/component')
- ->willReturn([]);
+ $this->rootPackage->getName()->willReturn('some/component');
$this->rootPackage->getExtra()->willReturn(['laminas' => [
'component-whitelist' => ['some/component'],
@@ -863,13 +837,10 @@ public function testOnPostPackageInstallPromptsForConfigOptions()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/component');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/component')
- ->willReturn([]);
+ $this->rootPackage->getName()->willReturn('some/component');
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -934,13 +905,10 @@ public function testOnPostPackageInstallPromptsForConfigOptionsWhenDefinedAsArra
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/component');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/component')
- ->willReturn([]);
+ $this->rootPackage->getName()->willReturn('some/component');
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1040,6 +1008,7 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanPromptMultipleTi
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/component');
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1097,13 +1066,10 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanPromptMultipleTi
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'other/component');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('other/component')
- ->willReturn([]);
+ $this->rootPackage->getName()->willReturn('other/component');
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1166,6 +1132,7 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanReuseOptions()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/component');
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1223,13 +1190,10 @@ public function testMultipleInvocationsOfOnPostPackageInstallCanReuseOptions()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'other/component');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->withConsecutive(['other/component'], ['some/component'])
- ->willReturn([]);
+ $this->rootPackage->getName()->willReturn('some/component');
$this->io->write(Argument::that(function ($argument) {
return strstr($argument, 'Installing Other\Component from package other/component');
@@ -1321,11 +1285,6 @@ public function testOnPostPackageUninstallCanRemovePackageArraysFromConfiguratio
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/component')
- ->willReturn([]);
$this->io
->write(' Removing Some\Component from package some/component')
@@ -1369,13 +1328,11 @@ public function testModuleIsAppended()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/module');
+
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/module')
- ->willReturn([]);
+ $this->rootPackage->getName()->willReturn('some/module');
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1444,13 +1401,10 @@ public function testAppendModuleAndPrependComponent()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/package');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/package')
- ->willReturn([]);
+ $this->rootPackage->getName()->willReturn('some/package');
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1547,13 +1501,12 @@ public function testPrependComponentAndAppendModule()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/package');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/package')
- ->willReturn([]);
+ $this->rootPackage
+ ->getName()
+ ->willReturn('some/package');
$this->io->ask(Argument::that(function ($argument) {
if (! is_string($argument)) {
@@ -1806,11 +1759,6 @@ public function testUninstallMessageWithDifferentInjectors($configContents, arra
$event->getOperation()->willReturn($operation->reveal());
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/component')
- ->willReturn([]);
$this->io
->write(' Removing Some\Component from package some/component')
@@ -1881,13 +1829,9 @@ public function testInstallWhitelistedDevModuleWithDifferentInjectors()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/component');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/component')
- ->willReturn([]);
$this->assertNull($this->installer->onPostPackageInstall($event->reveal()));
$config = include vfsStream::url('project/config/modules.config.php');
@@ -1940,13 +1884,12 @@ public function testInstallWhitelistedDevModuleWithUniqueInjector()
$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());
+ $this->prepareEventForPackageProviderDetection($event, 'some/module');
+ $this->rootPackage
+ ->getName()
+ ->willReturn('some/module');
$this->rootPackage->getRequires()->willReturn([]);
- $this->packageProviderDetection
- ->expects($this->any())
- ->method('whatProvides')
- ->with('some/module')
- ->willReturn([]);
$this->assertNull($this->installer->onPostPackageInstall($event->reveal()));
$config = include vfsStream::url('project/config/modules.config.php');
@@ -2000,7 +1943,17 @@ private function createConfigFile($name, $contents)
->setContent($contents);
}
- private function prepareEventForPackageProviderDetection(ObjectProphecy $event): ObjectProphecy
+ /**
+ * @param ObjectProphecy|PackageEvent $event
+ * @param string $packageName
+ * @return ObjectProphecy
+ */
+ private function prepareEventForPackageProviderDetection(ObjectProphecy $event, string $packageName): void
{
+ if (method_exists(PackageEvent::class, 'getPool')) {
+ $pool = $this->prophesize(Pool::class);
+ $pool->whatProvides($packageName)->willReturn([]);
+ $event->getPool()->willReturn($pool->reveal());
+ }
}
}
From 5434f84663d0cb0eeeee2ed23e0926fe1085dbf0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Sat, 24 Oct 2020 17:41:38 +0200
Subject: [PATCH 7/8] Ensure travis will use `composer` v1 and v2 when needed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
---
.travis.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index db1d45e..429cdca 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,7 @@ env:
global:
- COMPOSER_ARGS="--no-interaction"
- COVERAGE_DEPS="php-coveralls/php-coveralls"
+ - COMPOSER_VERSION=1
matrix:
fast_finish: true
@@ -53,7 +54,7 @@ before_install:
install:
- travis_retry composer install $COMPOSER_ARGS --ignore-platform-reqs
- if [[ $LEGACY_DEPS != '' ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies $LEGACY_DEPS ; fi
- - if [[ $COMPOSER_VERSION == '2' ]]; then travis_retry composer self-update --2 ; fi
+ - travis_retry composer self-update --$COMPOSER_VERSION
- if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi
- if [[ $DEPS == 'lowest' ]]; then travis_retry composer update $COMPOSER_ARGS --prefer-lowest --prefer-stable ; fi
- if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi
From 88b4479f6a0855278e87805b52220924dd13b270 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Sat, 24 Oct 2020 20:09:49 +0200
Subject: [PATCH 8/8] Add `CHANGELOG` entry
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
---
CHANGELOG.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index db80f24..7e30b5f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,7 +22,7 @@ All notable changes to this project will be documented in this file, in reverse
### Fixed
-- Nothing.
+- [#16](https://github.com/laminas/laminas-component-installer/pull/16) Fixed issue with detection packages in composer v2 as dev dependencies.
## 2.3.0 - 2020-09-02