Skip to content

Commit f65dec0

Browse files
authored
Merge pull request #623 from asgrim/622-use-providers-api
622: use providers API to find matching exts in pie install for PHP projects
2 parents 60c1d22 + bee44c4 commit f65dec0

6 files changed

Lines changed: 97 additions & 17 deletions

File tree

phpstan-baseline.neon

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ parameters:
169169
path: src/File/WindowsDelete.php
170170

171171
-
172-
message: '#^Call to function array_key_exists\(\) with ''downloads'' and array\{name\: string, description\: string\|null, abandoned\?\: string\|true, url\?\: string\} will always evaluate to false\.$#'
173-
identifier: function.impossibleType
174-
count: 2
172+
message: '#^Call to static method Php\\Pie\\ExtensionName\:\:isValidExtensionName\(\) with non\-empty\-string will always evaluate to true\.$#'
173+
identifier: staticMethod.alreadyNarrowedType
174+
count: 1
175175
path: src/Installing/InstallForPhpProject/FindMatchingPackages.php
176176

177177
-

src/Command/CommandHelper.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
use function array_key_exists;
3838
use function array_map;
39+
use function assert;
3940
use function count;
4041
use function is_array;
4142
use function is_string;
@@ -430,6 +431,8 @@ public static function handlePackageNotFound(
430431
$requestedPackageName = substr($requestedPackageName, 4);
431432
}
432433

434+
assert($requestedPackageName !== '');
435+
433436
$io->writeError('');
434437
$io->writeError(sprintf('<error>Could not install package: %s</error>', $requestedPackageName));
435438
$io->writeError($exception->getMessage());
@@ -460,7 +463,7 @@ static function (array $match) use ($io, $pieComposer): array {
460463

461464
return $match;
462465
},
463-
$findMatchingPackages->for($pieComposer, $requestedPackageName),
466+
$findMatchingPackages->bySearching($pieComposer, $requestedPackageName),
464467
);
465468

466469
if (count($matches)) {

src/Command/InstallExtensionsForProjectCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ function (Link $link) use ($pieComposer, $phpEnabledExtensions, $installedPiePac
225225
));
226226

227227
try {
228-
$matches = $this->findMatchingPackages->for($pieComposer, $extension->name());
228+
$matches = $this->findMatchingPackages->byProvider($pieComposer, $extension);
229229
} catch (OutOfRangeException) {
230230
$anyErrorsHappened = true;
231231

src/Installing/InstallForPhpProject/FindMatchingPackages.php

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
use OutOfRangeException;
1111
use Php\Pie\DependencyResolver\Package;
1212
use Php\Pie\ExtensionName;
13+
use Php\Pie\ExtensionType;
1314

1415
use function array_filter;
1516
use function array_key_exists;
1617
use function array_merge;
18+
use function array_values;
1719
use function count;
1820
use function usort;
1921

@@ -24,15 +26,14 @@
2426
*/
2527
class FindMatchingPackages
2628
{
27-
/** @return MatchingPackages */
28-
public function for(Composer $pieComposer, string $searchTerm): array
29+
/**
30+
* @param list<array{name: string, description: ?string, downloads?: int}> $matches
31+
* @param non-empty-string $searchTerm
32+
*
33+
* @return MatchingPackages
34+
*/
35+
private function filterToCompatible(Composer $pieComposer, array $matches, string $searchTerm): array
2936
{
30-
$matches = [];
31-
foreach ($pieComposer->getRepositoryManager()->getRepositories() as $repo) {
32-
$matches = array_merge($matches, $repo->search($searchTerm, RepositoryInterface::SEARCH_FULLTEXT, 'php-ext'));
33-
$matches = array_merge($matches, $repo->search($searchTerm, RepositoryInterface::SEARCH_FULLTEXT, 'php-ext-zend'));
34-
}
35-
3637
if (ExtensionName::isValidExtensionName($searchTerm)) {
3738
$extensionName = ExtensionName::normaliseFromString($searchTerm);
3839

@@ -41,7 +42,7 @@ public function for(Composer $pieComposer, string $searchTerm): array
4142
static function (array $match) use ($pieComposer, $extensionName): bool {
4243
$package = $pieComposer->getRepositoryManager()->findPackage($match['name'], '*');
4344

44-
if (! $package instanceof CompletePackageInterface) {
45+
if (! $package instanceof CompletePackageInterface || ! ExtensionType::isValid($package->getType())) {
4546
return false;
4647
}
4748

@@ -61,4 +62,31 @@ static function (array $match) use ($pieComposer, $extensionName): bool {
6162

6263
return $matches;
6364
}
65+
66+
/** @return MatchingPackages */
67+
public function byProvider(Composer $pieComposer, ExtensionName $extensionName): array
68+
{
69+
$matches = [];
70+
foreach ($pieComposer->getRepositoryManager()->getRepositories() as $repo) {
71+
$matches = array_merge($matches, $repo->getProviders($extensionName->nameWithExtPrefix()));
72+
}
73+
74+
return $this->filterToCompatible($pieComposer, array_values($matches), $extensionName->name());
75+
}
76+
77+
/**
78+
* @param non-empty-string $searchTerm
79+
*
80+
* @return MatchingPackages
81+
*/
82+
public function bySearching(Composer $pieComposer, string $searchTerm): array
83+
{
84+
$matches = [];
85+
foreach ($pieComposer->getRepositoryManager()->getRepositories() as $repo) {
86+
$matches = array_merge($matches, $repo->search($searchTerm, RepositoryInterface::SEARCH_FULLTEXT, 'php-ext'));
87+
$matches = array_merge($matches, $repo->search($searchTerm, RepositoryInterface::SEARCH_FULLTEXT, 'php-ext-zend'));
88+
}
89+
90+
return $this->filterToCompatible($pieComposer, $matches, $searchTerm);
91+
}
6492
}

test/integration/Command/InstallExtensionsForProjectCommandTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public function testInstallingExtensionsForPhpProject(): void
119119

120120
$this->composerFactoryForProject->method('composer')->willReturn($composer);
121121

122-
$this->findMatchingPackages->method('for')->willReturn([
122+
$this->findMatchingPackages->method('byProvider')->willReturn([
123123
['name' => 'vendor1/foobar', 'description' => 'The official foobar implementation'],
124124
]);
125125

@@ -175,7 +175,7 @@ public function testInstallingExtensionsForPhpProjectWithMultipleMatches(): void
175175

176176
$this->composerFactoryForProject->method('composer')->willReturn($composer);
177177

178-
$this->findMatchingPackages->method('for')->willReturn([
178+
$this->findMatchingPackages->method('byProvider')->willReturn([
179179
['name' => 'vendor1/foobar', 'description' => 'The official foobar implementation'],
180180
['name' => 'vendor2/afoobar', 'description' => 'An improved async foobar extension'],
181181
]);

test/unit/Installing/InstallForPhpProject/FindMatchingPackagesTest.php

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Composer\Repository\ArrayRepository;
1313
use Composer\Repository\RepositoryManager;
1414
use Composer\Util\HttpDownloader;
15+
use Php\Pie\ExtensionName;
1516
use Php\Pie\ExtensionType;
1617
use Php\Pie\Installing\InstallForPhpProject\FindMatchingPackages;
1718
use PHPUnit\Framework\Attributes\CoversClass;
@@ -66,7 +67,55 @@ public function testSearchResultsAreFilteredByExtensionName(): void
6667
'description' => 'The best extension there is',
6768
],
6869
],
69-
(new FindMatchingPackages())->for($composer, 'bar'),
70+
(new FindMatchingPackages())->bySearching($composer, 'bar'),
71+
);
72+
}
73+
74+
public function testByProvider(): void
75+
{
76+
$package = new CompletePackage('foo/bar', '2.0.0.0', '2.0.0');
77+
$package->setDescription('The best extension there is');
78+
$package->setType(ExtensionType::PhpModule->value);
79+
80+
$repository = $this->createPartialMock(ArrayRepository::class, ['getProviders']);
81+
$repository->addPackage($package);
82+
$repository->expects(self::once())
83+
->method('getProviders')
84+
->with('ext-bar')
85+
->willReturn([
86+
'foo1/bar' => [
87+
'name' => 'foo1/bar',
88+
'description' => 'This is foo1/bar, not quite what you are looking for',
89+
'type' => 'library',
90+
],
91+
'foo/bar' => [
92+
'name' => 'foo/bar',
93+
'description' => 'The best extension there is',
94+
'type' => 'php-ext',
95+
],
96+
]);
97+
98+
$repoManager = new RepositoryManager(
99+
$this->createMock(IOInterface::class),
100+
$this->createMock(Config::class),
101+
$this->createMock(HttpDownloader::class),
102+
null,
103+
null,
104+
);
105+
$repoManager->addRepository($repository);
106+
107+
$composer = $this->createMock(Composer::class);
108+
$composer->method('getRepositoryManager')->willReturn($repoManager);
109+
110+
self::assertSame(
111+
[
112+
[
113+
'name' => 'foo/bar',
114+
'description' => 'The best extension there is',
115+
'type' => 'php-ext',
116+
],
117+
],
118+
(new FindMatchingPackages())->byProvider($composer, ExtensionName::normaliseFromString('bar')),
70119
);
71120
}
72121
}

0 commit comments

Comments
 (0)