Skip to content

Commit 3f161c8

Browse files
authored
Merge pull request #54 from boesing/feature/component-excludes
Introduce `component-ignore-list`
2 parents 23d0a99 + 8d9b575 commit 3f161c8

File tree

3 files changed

+93
-10
lines changed

3 files changed

+93
-10
lines changed

docs/book/index.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,25 @@ This value should be an array of package names.
183183

184184
This setting only works in the root package.
185185

186+
## Excluding Packages from Being Auto-Installed
187+
188+
At the root package level, you can also indicate that certain packages that supply
189+
config providers and/or modules should **NOT** automatically inject configuration,
190+
instead of prompting for installation, via the `component-ignore-list` setting.
191+
This value should be an array of package names.
192+
193+
```json
194+
"extra": {
195+
"laminas": {
196+
"component-ignore-list": [
197+
"laminas/laminas-db"
198+
]
199+
}
200+
}
201+
```
202+
203+
This setting only works in the root package.
204+
186205
## Why?
187206

188207
When preparing laminas-mvc's version 3 release, we wanted to reduce the number of

src/ComponentInstaller.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@
9292
* @internal
9393
*
9494
* @psalm-type ComposerExtraComponentInstallerProjectArrayType = array{
95-
* component-auto-installs?: non-empty-list<non-empty-string>
95+
* component-auto-installs?: non-empty-list<non-empty-string>,
96+
* component-ignore-list?: non-empty-list<non-empty-string>
9697
* }
9798
* @psalm-type ComposerExtraComponentInstallerArrayType = array{
9899
* component?:non-empty-array<non-empty-string>,
@@ -491,20 +492,27 @@ private function marshalInstallableComponents(array $extra, Collection $options)
491492
/**
492493
* Prompt for the user to select a configuration location to update.
493494
*
494-
* @param non-empty-string $name
495+
* @param non-empty-string $name
495496
* @param Collection<int,ConfigOption> $options
496497
* @param InjectorInterface::TYPE_* $packageType
497-
* @param non-empty-string $packageName
498-
* @param list<non-empty-string> $autoInstallations
498+
* @param non-empty-string $packageName
499+
* @param list<non-empty-string> $autoInstallations
500+
* @param list<non-empty-string> $ignoreList
499501
*/
500502
private function promptForConfigOption(
501503
string $name,
502504
Collection $options,
503505
int $packageType,
504506
string $packageName,
505507
array $autoInstallations,
506-
bool $requireDev = false
508+
array $ignoreList,
509+
bool $requireDev
507510
): InjectorInterface {
511+
// If package is whitelisted, do not inject
512+
if (in_array($packageName, $ignoreList, true)) {
513+
return new Injector\NoopInjector();
514+
}
515+
508516
if ($cachedInjector = $this->getCachedInjector($packageType)) {
509517
return $cachedInjector;
510518
}
@@ -951,6 +959,7 @@ private function addPackageToConfig(
951959
$rootPackageExtra = $this->composer->getPackage()->getExtra();
952960
$rootExtra = $this->getExtraMetadata($rootPackageExtra, true);
953961
$autoInstallations = $rootExtra['component-auto-installs'] ?? [];
962+
$ignoreList = $rootExtra['component-ignore-list'] ?? [];
954963

955964
$this->marshalInstallableComponents($extra, $options)
956965
// Create injectors
@@ -961,7 +970,8 @@ private function addPackageToConfig(
961970
$requireDev,
962971
$dependencies,
963972
$applicationModules,
964-
$autoInstallations
973+
$autoInstallations,
974+
$ignoreList
965975
): void {
966976
$packageType = $packageTypes->get($component);
967977

@@ -971,6 +981,7 @@ private function addPackageToConfig(
971981
$packageType,
972982
$name,
973983
$autoInstallations,
984+
$ignoreList,
974985
$requireDev
975986
);
976987

@@ -1058,6 +1069,16 @@ private function filterComponentInstallerSpecificValuesFromComposerExtra(
10581069
= $maybeLaminasSpecificConfiguration['component-auto-installs'];
10591070
}
10601071

1072+
if (
1073+
isset($maybeLaminasSpecificConfiguration['component-ignore-list'])
1074+
&& $this->isNonEmptyListContainingNonEmptyStrings(
1075+
$maybeLaminasSpecificConfiguration['component-ignore-list']
1076+
)
1077+
) {
1078+
$laminasSpecificConfiguration['component-ignore-list']
1079+
= $maybeLaminasSpecificConfiguration['component-ignore-list'];
1080+
}
1081+
10611082
return $laminasSpecificConfiguration;
10621083
}
10631084

test/ComponentInstallerTest.php

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,14 @@ final class ComponentInstallerTest extends TestCase
6262
/** @var InstallationManager&MockObject */
6363
private $installationManager;
6464

65-
/** @var array{laminas?:array{component-auto-installs?:list<non-empty-string>}} */
65+
/**
66+
* @var array{
67+
* laminas?: array{
68+
* component-auto-installs?:list<non-empty-string>,
69+
* component-ignore-list?:list<non-empty-string>
70+
* }
71+
* }
72+
**/
6673
private $rootPackageExtra = [];
6774

6875
protected function setUp(): void
@@ -216,7 +223,7 @@ private function prepareEventForPackageProviderDetection($event, string $package
216223
}
217224

218225
/**
219-
* @param array<int,string> $informations
226+
* @param non-empty-list<string> $informations
220227
*/
221228
private function createOutputAssertions(array $informations): void
222229
{
@@ -1735,6 +1742,42 @@ public function testInstallAutoInstallableDevModuleWithUniqueInjector(): void
17351742
], $modules);
17361743
}
17371744

1745+
public function testOnPostPackageInstallDoesNotPromptForIgnoredPackages(): void
1746+
{
1747+
$this->createApplicationConfig();
1748+
1749+
$package = $this->createMock(PackageInterface::class);
1750+
$package->method('getName')->willReturn('some/component');
1751+
$package->method('getExtra')->willReturn([
1752+
'laminas' => [
1753+
'component' => 'Some\\Component',
1754+
],
1755+
]);
1756+
1757+
$operation = $this->createMock(InstallOperation::class);
1758+
$operation->method('getPackage')->willReturn($package);
1759+
1760+
$event = $this->createMock(PackageEvent::class);
1761+
$event->method('isDevMode')->willReturn(true);
1762+
$event->method('getOperation')->willReturn($operation);
1763+
$this->prepareEventForPackageProviderDetection($event, 'some/component');
1764+
1765+
$this->rootPackage->method('getName')->willReturn('some/component');
1766+
$this->rootPackageExtra = [
1767+
'laminas' => [
1768+
'component-ignore-list' => ['some/component'],
1769+
],
1770+
];
1771+
1772+
$this->io
1773+
->expects(self::never())
1774+
->method('ask');
1775+
1776+
$this->installer->onPostPackageInstall($event);
1777+
$config = file_get_contents(vfsStream::url('project/config/application.config.php'));
1778+
self::assertStringNotContainsString("'Some\Component'", $config);
1779+
}
1780+
17381781
/**
17391782
* @return array<non-empty-string,array{
17401783
* non-empty-string,
@@ -1861,7 +1904,7 @@ public function testOnPostPackageUpdateRemovesPackageWhenNewerVersionDoesNotCont
18611904
* @psalm-param ComposerExtraLaminasConfiguration $previousExtra
18621905
* @psalm-param ComposerExtraLaminasConfiguration $newExtra
18631906
* @psalm-param list<AbstractQuestionAssertion> $inputAssertions
1864-
* @psalm-param list<non-empty-string> $outputAssertions
1907+
* @psalm-param non-empty-list<non-empty-string> $outputAssertions
18651908
* @psalm-param list<non-empty-string> $expectedInstalledModules
18661909
* @dataProvider packageUpdateScenarios
18671910
*/
@@ -1913,7 +1956,7 @@ public function testOnPostPackageUpdateAddsPackageWhenNewerVersionContainsDiffer
19131956
* 1:ComposerExtraLaminasConfiguration,
19141957
* 2:ComposerExtraLaminasConfiguration,
19151958
* 3:list<AbstractQuestionAssertion>,
1916-
* 4:list<non-empty-string>,
1959+
* 4:non-empty-list<non-empty-string>,
19171960
* 5:list<non-empty-string>
19181961
* }>
19191962
*/

0 commit comments

Comments
 (0)