Skip to content

Commit 879e0be

Browse files
authored
feat: Provide a non optimized requirement list (#1328)
This is a preparatory step for #1273. The goal is to be able to provide _all_ the requirements. The idea being that one may be interested in seeing this full list for debugging purpose, rather than the strict final one where the provided extensions removed the required extensions from the calculated requirements.
1 parent 4ae6b07 commit 879e0be

File tree

6 files changed

+314
-71
lines changed

6 files changed

+314
-71
lines changed

src/RequirementChecker/AppRequirementsFactory.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,47 @@ final class AppRequirementsFactory
2828
{
2929
private const SELF_PACKAGE = null;
3030

31+
public function createUnfiltered(
32+
ComposerJson $composerJson,
33+
ComposerLock $composerLock,
34+
CompressionAlgorithm $compressionAlgorithm,
35+
): Requirements {
36+
return $this
37+
->createBuilder(
38+
$composerJson,
39+
$composerLock,
40+
$compressionAlgorithm,
41+
)
42+
->all();
43+
}
44+
3145
public function create(
3246
ComposerJson $composerJson,
3347
ComposerLock $composerLock,
3448
CompressionAlgorithm $compressionAlgorithm,
3549
): Requirements {
50+
return $this
51+
->createBuilder(
52+
$composerJson,
53+
$composerLock,
54+
$compressionAlgorithm,
55+
)
56+
->build();
57+
}
58+
59+
private function createBuilder(
60+
ComposerJson $composerJson,
61+
ComposerLock $composerLock,
62+
CompressionAlgorithm $compressionAlgorithm,
63+
): RequirementsBuilder {
3664
$requirementsBuilder = new RequirementsBuilder();
3765

3866
self::retrievePhpVersionRequirements($requirementsBuilder, $composerJson, $composerLock);
3967
self::collectExtensionRequirementsFromCompressionAlgorithm($requirementsBuilder, $compressionAlgorithm);
4068
self::collectComposerLockExtensionRequirements($composerLock, $requirementsBuilder);
4169
self::collectComposerJsonExtensionRequirements($composerJson, $requirementsBuilder);
4270

43-
return $requirementsBuilder->build();
71+
return $requirementsBuilder;
4472
}
4573

4674
private static function retrievePhpVersionRequirements(

src/RequirementChecker/Requirement.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,35 @@ public static function forRequiredExtension(string $extension, ?string $packageN
8686
);
8787
}
8888

89+
public static function forProvidedExtension(string $extension, ?string $packageName): self
90+
{
91+
return new self(
92+
RequirementType::PROVIDED_EXTENSION,
93+
$extension,
94+
$packageName,
95+
null === $packageName
96+
? sprintf(
97+
'This application provides the extension "%s".',
98+
$extension,
99+
)
100+
: sprintf(
101+
'The package "%s" provides the extension "%s".',
102+
$packageName,
103+
$extension,
104+
),
105+
null === $packageName
106+
? sprintf(
107+
'This application does not require the extension "%s", it is provided by the application itself.',
108+
$extension,
109+
)
110+
: sprintf(
111+
'This application does not require the extension "%s", it is provided by the package "%s".',
112+
$packageName,
113+
$extension,
114+
),
115+
);
116+
}
117+
89118
public static function forConflictingExtension(string $extension, ?string $packageName): self
90119
{
91120
return new self(

src/RequirementChecker/RequirementType.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ enum RequirementType: string
1818
{
1919
case PHP = 'php';
2020
case EXTENSION = 'extension';
21+
case PROVIDED_EXTENSION = 'provided-extension';
2122
case EXTENSION_CONFLICT = 'extension-conflict';
2223
}

src/RequirementChecker/RequirementsBuilder.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,40 @@ public function addConflictingExtension(Extension $extension, ?string $source):
4949
$this->conflictingExtensions[$extension->name][] = $source;
5050
}
5151

52+
public function all(): Requirements
53+
{
54+
$requirements = $this->predefinedRequirements;
55+
56+
foreach ($this->getUnfilteredSortedRequiredExtensions() as $extensionName => $sources) {
57+
foreach ($sources as $source) {
58+
$requirements[] = Requirement::forRequiredExtension(
59+
$extensionName,
60+
$source,
61+
);
62+
}
63+
}
64+
65+
foreach ($this->getSortedProvidedExtensions() as $extensionName => $sources) {
66+
foreach ($sources as $source) {
67+
$requirements[] = Requirement::forProvidedExtension(
68+
$extensionName,
69+
$source,
70+
);
71+
}
72+
}
73+
74+
foreach ($this->getSortedConflictedExtensions() as $extensionName => $sources) {
75+
foreach ($sources as $source) {
76+
$requirements[] = Requirement::forConflictingExtension(
77+
$extensionName,
78+
$source,
79+
);
80+
}
81+
}
82+
83+
return new Requirements($requirements);
84+
}
85+
5286
public function build(): Requirements
5387
{
5488
$requirements = $this->predefinedRequirements;
@@ -74,6 +108,32 @@ public function build(): Requirements
74108
return new Requirements($requirements);
75109
}
76110

111+
/**
112+
* @return array<string, list<string>>
113+
*/
114+
private function getUnfilteredSortedRequiredExtensions(): array
115+
{
116+
return array_map(
117+
self::createSortedDistinctList(...),
118+
self::sortByExtensionName(
119+
$this->requiredExtensions,
120+
),
121+
);
122+
}
123+
124+
/**
125+
* @return array<string, list<string>>
126+
*/
127+
private function getSortedProvidedExtensions(): array
128+
{
129+
return array_map(
130+
self::createSortedDistinctList(...),
131+
self::sortByExtensionName(
132+
$this->providedExtensions,
133+
),
134+
);
135+
}
136+
77137
/**
78138
* @return array<string, list<string>>
79139
*/

tests/RequirementChecker/RequirementTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,42 @@ public function test_it_can_be_created_for_an_extension_constraint_for_a_package
9595
self::assertItCanBeCreatedFromItsArrayForm($requirement, $actual);
9696
}
9797

98+
public function test_it_can_be_created_for_a_provided_extension_constraint(): void
99+
{
100+
$requirement = Requirement::forProvidedExtension('mbstring', null);
101+
102+
$expected = [
103+
'type' => 'provided-extension',
104+
'condition' => 'mbstring',
105+
'source' => null,
106+
'message' => 'This application provides the extension "mbstring".',
107+
'helpMessage' => 'This application does not require the extension "mbstring", it is provided by the application itself.',
108+
];
109+
110+
$actual = $requirement->toArray();
111+
112+
self::assertSame($expected, $actual);
113+
self::assertItCanBeCreatedFromItsArrayForm($requirement, $actual);
114+
}
115+
116+
public function test_it_can_be_created_for_a_provided_extension_constraint_for_a_package(): void
117+
{
118+
$requirement = Requirement::forProvidedExtension('mbstring', 'box/test');
119+
120+
$expected = [
121+
'type' => 'provided-extension',
122+
'condition' => 'mbstring',
123+
'source' => 'box/test',
124+
'message' => 'The package "box/test" provides the extension "mbstring".',
125+
'helpMessage' => 'This application does not require the extension "box/test", it is provided by the package "mbstring".',
126+
];
127+
128+
$actual = $requirement->toArray();
129+
130+
self::assertSame($expected, $actual);
131+
self::assertItCanBeCreatedFromItsArrayForm($requirement, $actual);
132+
}
133+
98134
public function test_it_can_be_created_for_a_conflicting_extension_constraint(): void
99135
{
100136
$requirement = Requirement::forConflictingExtension('mbstring', null);

0 commit comments

Comments
 (0)