diff --git a/src/Command/InstallExtensionsForProjectCommand.php b/src/Command/InstallExtensionsForProjectCommand.php index 511d43bb..400f6f12 100644 --- a/src/Command/InstallExtensionsForProjectCommand.php +++ b/src/Command/InstallExtensionsForProjectCommand.php @@ -162,13 +162,18 @@ public function execute(InputInterface $input, OutputInterface $output): int array_walk( $extensionsRequired, - function (Link $link) use ($pieComposer, $phpEnabledExtensions, $installedPiePackages, $input, &$anyErrorsHappened): void { + function (Link $link) use ($pieComposer, $phpEnabledExtensions, $installedPiePackages, $input, &$anyErrorsHappened, $targetPlatform): void { $extension = ExtensionName::normaliseFromString($link->getTarget()); $linkRequiresConstraint = $link->getPrettyConstraint(); + $piePackagesForExtension = $installedPiePackages + ->findByPhpFormattedExtensionName($extension->phpFormattedExtensionName()) + ->onlyVerifiedFor($targetPlatform); + $piePackageVersion = null; - if (in_array($extension->name(), array_keys($installedPiePackages))) { - $piePackageVersion = $installedPiePackages[$extension->name()]->version(); + + if (count($piePackagesForExtension) === 1) { + $piePackageVersion = $piePackagesForExtension->onlyOne()->version(); } $piePackageVersionMatchesLinkConstraint = null; diff --git a/src/Command/ShowCommand.php b/src/Command/ShowCommand.php index 77f88b9f..c291dc6a 100644 --- a/src/Command/ShowCommand.php +++ b/src/Command/ShowCommand.php @@ -10,15 +10,14 @@ use Php\Pie\ComposerIntegration\PieComposerRequest; use Php\Pie\ComposerIntegration\PieInstalledJsonMetadataKeys; use Php\Pie\DependencyResolver\BundledPhpExtensionRefusal; +use Php\Pie\DependencyResolver\Package; use Php\Pie\DependencyResolver\RequestedPackageAndVersion; use Php\Pie\DependencyResolver\ResolveDependencyWithComposer; use Php\Pie\DependencyResolver\UnableToResolveRequirement; -use Php\Pie\File\BinaryFile; -use Php\Pie\File\BinaryFileFailedVerification; use Php\Pie\Platform as PiePlatform; use Php\Pie\Platform\InstalledPiePackages; -use Php\Pie\Platform\OperatingSystem; use Php\Pie\Util\Emoji; +use Php\Pie\Util\PackageVerificationStatus; use Psr\Container\ContainerInterface; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -28,15 +27,11 @@ use Webmozart\Assert\Assert; use function array_diff; -use function array_key_exists; -use function array_keys; +use function array_map; use function array_walk; use function count; -use function file_exists; +use function rtrim; use function sprintf; -use function substr; - -use const DIRECTORY_SEPARATOR; /** @phpstan-import-type PieMetadata from PieInstalledJsonMetadataKeys */ #[AsCommand( @@ -99,8 +94,6 @@ public function execute(InputInterface $input, OutputInterface $output): int $piePackages = $this->installedPiePackages->allPiePackages($composer); $phpEnabledExtensions = $targetPlatform->phpBinaryPath->extensions(); - $extensionPath = $targetPlatform->phpBinaryPath->extensionPath(); - $extensionEnding = $targetPlatform->operatingSystem === OperatingSystem::Windows ? '.dll' : '.so'; $piePackagesMatched = []; $rootPackageRequires = $composer->getPackage()->getRequires(); @@ -110,8 +103,10 @@ public function execute(InputInterface $input, OutputInterface $output): int )); array_walk( $phpEnabledExtensions, - function (string $version, string $phpExtensionName) use ($composer, $rootPackageRequires, $targetPlatform, $showAll, $piePackages, $extensionPath, $extensionEnding, &$piePackagesMatched): void { - if (! array_key_exists($phpExtensionName, $piePackages)) { + function (string $version, string $phpExtensionName) use ($composer, $rootPackageRequires, $targetPlatform, $showAll, $piePackages, &$piePackagesMatched): void { + $pieMatchesForExtension = $piePackages->findByPhpFormattedExtensionName($phpExtensionName); + + if (! count($pieMatchesForExtension)) { if ($showAll) { $this->io->write(sprintf(' %s:%s', $phpExtensionName, $version)); } @@ -119,64 +114,66 @@ function (string $version, string $phpExtensionName) use ($composer, $rootPackag return; } - $piePackage = $piePackages[$phpExtensionName]; - $piePackagesMatched[] = $phpExtensionName; - $packageName = $piePackage->name(); - $packageRequirement = $rootPackageRequires[$piePackage->name()]->getPrettyConstraint(); + foreach ($pieMatchesForExtension->packages() as $piePackage) { + $packageName = $piePackage->name(); + $verificationStatus = $piePackage->verifyPackageStatus($targetPlatform); + $packageRequirement = $rootPackageRequires[$packageName]->getPrettyConstraint(); - try { - // Don't check for updates for bundled PHP extensions - if ($piePackage->isBundledPhpExtension()) { - throw new BundledPhpExtensionRefusal(); + if ($verificationStatus === PackageVerificationStatus::InstalledBinaryMetadataMissing) { + continue; } - Assert::stringNotEmpty($packageName); - Assert::stringNotEmpty($packageRequirement); - - $latestConstrainedPackage = ($this->resolveDependencyWithComposer)( - $composer, - $targetPlatform, - new RequestedPackageAndVersion($packageName, $packageRequirement), - false, - ); - - $latestPackage = ($this->resolveDependencyWithComposer)( - $composer, - $targetPlatform, - new RequestedPackageAndVersion($packageName, '*'), - false, - ); - } catch (UnableToResolveRequirement | BundledPhpExtensionRefusal) { - $latestConstrainedPackage = null; - $latestPackage = null; - } + $piePackagesMatched[] = $packageName; + + try { + // Don't check for updates for bundled PHP extensions + if ($piePackage->isBundledPhpExtension()) { + throw new BundledPhpExtensionRefusal(); + } + + Assert::stringNotEmpty($packageName); + Assert::stringNotEmpty($packageRequirement); + + $latestConstrainedPackage = ($this->resolveDependencyWithComposer)( + $composer, + $targetPlatform, + new RequestedPackageAndVersion($packageName, $packageRequirement), + false, + ); + + $latestPackage = ($this->resolveDependencyWithComposer)( + $composer, + $targetPlatform, + new RequestedPackageAndVersion($packageName, '*'), + false, + ); + } catch (UnableToResolveRequirement | BundledPhpExtensionRefusal) { + $latestConstrainedPackage = null; + $latestPackage = null; + } - $updateNotice = ''; - if ($latestConstrainedPackage !== null && $latestConstrainedPackage->version() !== $piePackage->version()) { - $updateNotice = sprintf( - ', upgradable to %s (within %s)', - $latestConstrainedPackage->version(), - $packageRequirement, - ); - } + $updateNotice = ''; + if ($latestConstrainedPackage !== null && $latestConstrainedPackage->version() !== $piePackage->version()) { + $updateNotice = sprintf( + ', upgradable to %s (within %s)', + $latestConstrainedPackage->version(), + $packageRequirement, + ); + } - if ($latestPackage !== null && $latestPackage->version() !== $latestConstrainedPackage->version()) { - $updateNotice .= sprintf(', latest version is %s', $latestPackage->version()); - } + if ($latestPackage !== null && $latestPackage->version() !== $latestConstrainedPackage->version()) { + $updateNotice .= sprintf(', latest version is %s', $latestPackage->version()); + } - $this->io->write(sprintf( - ' %s:%s (from 🥧 %s%s)%s', - $phpExtensionName, - $version, - $piePackage->prettyNameAndVersion(), - self::verifyChecksumInformation( - $extensionPath, + $this->io->write(sprintf( + ' %s:%s (from 🥧 %s %s)%s', $phpExtensionName, - $extensionEnding, - PieInstalledJsonMetadataKeys::pieMetadataFromComposerPackage($piePackage->composerPackage()), - ), - $updateNotice, - )); + $version, + $piePackage->prettyNameAndVersion(), + $verificationStatus->description(), + $updateNotice, + )); + } }, ); @@ -184,67 +181,28 @@ function (string $version, string $phpExtensionName) use ($composer, $rootPackag $this->io->write('(none)'); } - $unmatchedPiePackages = array_diff(array_keys($piePackages), $piePackagesMatched); + $unmatchedPiePackageNames = array_diff(array_map(static fn (Package $piePackage) => $piePackage->name(), $piePackages->packages()), $piePackagesMatched); - if (count($unmatchedPiePackages)) { + if (count($unmatchedPiePackageNames)) { $this->io->write(sprintf( '%s %s PIE packages not loaded:', "\n", Emoji::WARNING, )); - $this->io->write('These extensions were installed with PIE but are not currently enabled.' . "\n"); + $this->io->write('These extensions were set up with PIE but are not currently enabled.' . "\n"); - foreach ($unmatchedPiePackages as $unmatchedPiePackage) { - $this->io->write(sprintf(' - %s', $piePackages[$unmatchedPiePackage]->prettyNameAndVersion())); + foreach ($unmatchedPiePackageNames as $unmatchedPiePackageName) { + $unmatchedPiePackage = $piePackages->findByPackageName($unmatchedPiePackageName); + + $message = match ($unmatchedPiePackage->verifyPackageStatus($targetPlatform)) { + PackageVerificationStatus::ChecksumMetadataMissing => '- was built but not installed yet.', + PackageVerificationStatus::InstalledBinaryMetadataMissing => '- was downloaded but has not been built yet.', + default => '- installed but not enabled in INI file', + }; + $this->io->write(rtrim(sprintf(' - %s %s', $unmatchedPiePackage->prettyNameAndVersion(), $message))); } } return Command::SUCCESS; } - - /** - * @param PieMetadata $installedJsonMetadata - * @phpstan-param '.dll'|'.so' $extensionEnding - */ - private static function verifyChecksumInformation( - string $extensionPath, - string $phpExtensionName, - string $extensionEnding, - array $installedJsonMetadata, - ): string { - $actualBinaryPathByConvention = $extensionPath . DIRECTORY_SEPARATOR . $phpExtensionName . $extensionEnding; - - // The extension may not be in the usual path (since you can specify a full path to an extension in the INI file) - if (! file_exists($actualBinaryPathByConvention)) { - return ''; - } - - $pieExpectedBinaryPath = array_key_exists(PieInstalledJsonMetadataKeys::InstalledBinary->value, $installedJsonMetadata) ? $installedJsonMetadata[PieInstalledJsonMetadataKeys::InstalledBinary->value] : null; - $pieExpectedChecksum = array_key_exists(PieInstalledJsonMetadataKeys::BinaryChecksum->value, $installedJsonMetadata) ? $installedJsonMetadata[PieInstalledJsonMetadataKeys::BinaryChecksum->value] : null; - - // Some other kind of mismatch of file path, or we don't have a stored checksum available - if ( - $pieExpectedBinaryPath === null - || $pieExpectedChecksum === null - || $pieExpectedBinaryPath !== $actualBinaryPathByConvention - ) { - return ''; - } - - $expectedBinaryFileFromMetadata = new BinaryFile($pieExpectedBinaryPath, $pieExpectedChecksum); - $actualBinaryFile = BinaryFile::fromFileWithSha256Checksum($actualBinaryPathByConvention); - - try { - $expectedBinaryFileFromMetadata->verifyAgainstOther($actualBinaryFile); - } catch (BinaryFileFailedVerification) { - return sprintf( - ' %s was %s..., expected %s...', - Emoji::WARNING, - substr($actualBinaryFile->checksum, 0, 8), - substr($expectedBinaryFileFromMetadata->checksum, 0, 8), - ); - } - - return ' ' . Emoji::GREEN_CHECKMARK; - } } diff --git a/src/Command/UninstallCommand.php b/src/Command/UninstallCommand.php index c06980a0..86b2bf67 100644 --- a/src/Command/UninstallCommand.php +++ b/src/Command/UninstallCommand.php @@ -109,7 +109,7 @@ private function findPiePackageByPackageName(string $packageToRemove, Composer $ { $piePackages = $this->installedPiePackages->allPiePackages($composer); - foreach ($piePackages as $piePackage) { + foreach ($piePackages->packages() as $piePackage) { if ($piePackage->name() === $packageToRemove) { return $piePackage; } diff --git a/src/ComposerIntegration/PhpBinaryPathBasedPlatformRepository.php b/src/ComposerIntegration/PhpBinaryPathBasedPlatformRepository.php index 2e60dd95..1adabc02 100644 --- a/src/ComposerIntegration/PhpBinaryPathBasedPlatformRepository.php +++ b/src/ComposerIntegration/PhpBinaryPathBasedPlatformRepository.php @@ -44,7 +44,7 @@ public function __construct(PhpBinaryPath $phpBinaryPath, Composer $composer, In $piePackages = $installedPiePackages->allPiePackages($composer); $extensionsBeingReplacedByPiePackages = []; - foreach ($piePackages as $piePackage) { + foreach ($piePackages->packages() as $piePackage) { foreach ($piePackage->composerPackage()->getReplaces() as $replaceLink) { $target = $replaceLink->getTarget(); if ( diff --git a/src/DependencyResolver/Package.php b/src/DependencyResolver/Package.php index 154c01ec..7352540e 100644 --- a/src/DependencyResolver/Package.php +++ b/src/DependencyResolver/Package.php @@ -6,11 +6,17 @@ use Composer\Package\CompletePackageInterface; use InvalidArgumentException; +use Php\Pie\ComposerIntegration\PieInstalledJsonMetadataKeys; use Php\Pie\ConfigureOption; use Php\Pie\Downloading\DownloadUrlMethod; use Php\Pie\ExtensionName; use Php\Pie\ExtensionType; +use Php\Pie\File\BinaryFile; +use Php\Pie\File\BinaryFileFailedVerification; +use Php\Pie\Platform\OperatingSystem; use Php\Pie\Platform\OperatingSystemFamily; +use Php\Pie\Platform\TargetPlatform; +use Php\Pie\Util\PackageVerificationStatus; use Webmozart\Assert\Assert; use function array_key_exists; @@ -18,6 +24,7 @@ use function array_slice; use function count; use function explode; +use function file_exists; use function implode; use function is_array; use function parse_url; @@ -25,6 +32,8 @@ use function str_starts_with; use function strtolower; +use const DIRECTORY_SEPARATOR; + /** * @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks * @@ -235,4 +244,45 @@ public function supportedDownloadUrlMethods(): array|null { return $this->supportedDownloadUrlMethods; } + + public function verifyPackageStatus(TargetPlatform $targetPlatform): PackageVerificationStatus + { + $extensionPath = $targetPlatform->phpBinaryPath->extensionPath(); + $extensionEnding = $targetPlatform->operatingSystem === OperatingSystem::Windows ? '.dll' : '.so'; + $phpExtensionName = $this->extensionName->name(); + + $actualBinaryPathByConvention = $extensionPath . DIRECTORY_SEPARATOR . $phpExtensionName . $extensionEnding; + + // The extension may not be in the usual path (since you can specify a full path to an extension in the INI file) + if (! file_exists($actualBinaryPathByConvention)) { + return PackageVerificationStatus::ActualBinaryNotFound; + } + + $installedJsonMetadata = PieInstalledJsonMetadataKeys::pieMetadataFromComposerPackage($this->composerPackage()); + $pieExpectedBinaryPath = array_key_exists(PieInstalledJsonMetadataKeys::InstalledBinary->value, $installedJsonMetadata) ? $installedJsonMetadata[PieInstalledJsonMetadataKeys::InstalledBinary->value] : null; + $pieExpectedChecksum = array_key_exists(PieInstalledJsonMetadataKeys::BinaryChecksum->value, $installedJsonMetadata) ? $installedJsonMetadata[PieInstalledJsonMetadataKeys::BinaryChecksum->value] : null; + + if ($pieExpectedBinaryPath === null) { + return PackageVerificationStatus::InstalledBinaryMetadataMissing; + } + + if ($pieExpectedChecksum === null) { + return PackageVerificationStatus::ChecksumMetadataMissing; + } + + if ($pieExpectedBinaryPath !== $actualBinaryPathByConvention) { + return PackageVerificationStatus::InstalledBinaryPathDoesNotMatchActualBinaryPath; + } + + $expectedBinaryFileFromMetadata = new BinaryFile($pieExpectedBinaryPath, $pieExpectedChecksum); + $actualBinaryFile = BinaryFile::fromFileWithSha256Checksum($actualBinaryPathByConvention); + + try { + $expectedBinaryFileFromMetadata->verifyAgainstOther($actualBinaryFile); + } catch (BinaryFileFailedVerification) { + return PackageVerificationStatus::ChecksumMismatch; + } + + return PackageVerificationStatus::Verified; + } } diff --git a/src/ExtensionName.php b/src/ExtensionName.php index 860d5fc0..eae8dc43 100644 --- a/src/ExtensionName.php +++ b/src/ExtensionName.php @@ -94,4 +94,20 @@ public function nameWithExtPrefix(): string { return 'ext-' . $this->normalisedExtensionName; } + + /** @return non-empty-string */ + public function phpFormattedExtensionName(): string + { + return match ($this->name()) { + 'core' => 'Core', + 'spl' => 'SPL', + 'phar' => 'Phar', + 'reflection' => 'Reflection', + 'pdo' => 'PDO', + 'ffi' => 'FFI', + 'opcache' => 'Zend OPcache', + 'simplexml' => 'SimpleXML', + default => $this->name(), + }; + } } diff --git a/src/Platform/InstalledPiePackages.php b/src/Platform/InstalledPiePackages.php index 4eb5346f..9324586a 100644 --- a/src/Platform/InstalledPiePackages.php +++ b/src/Platform/InstalledPiePackages.php @@ -11,26 +11,20 @@ use Php\Pie\DependencyResolver\Package; use Php\Pie\ExtensionName; -use function array_combine; use function array_filter; use function array_map; +use function array_values; -/** - * @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks - * - * @phpstan-type ListOfPiePackages = array - */ +/** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */ class InstalledPiePackages { /** * Returns a list of PIE packages according to PIE; this does NOT check if * the extension is actually enabled in the target PHP. - * - * @return ListOfPiePackages */ - public function allPiePackages(Composer $composer): array + public function allPiePackages(Composer $composer): PiePackageList { - $composerInstalledPackages = array_map( + return new PiePackageList(array_values(array_map( static function (CompletePackageInterface $package): Package { return Package::fromComposerCompletePackage($package); }, @@ -49,27 +43,6 @@ static function (BasePackage $basePackage): bool { return $basePackage instanceof CompletePackageInterface; }, ), - ); - - return array_combine( - array_map( - /** @return non-empty-string */ - static function (Package $package): string { - return match ($package->extensionName()->name()) { - 'core' => 'Core', - 'spl' => 'SPL', - 'phar' => 'Phar', - 'reflection' => 'Reflection', - 'pdo' => 'PDO', - 'ffi' => 'FFI', - 'opcache' => 'Zend OPcache', - 'simplexml' => 'SimpleXML', - default => $package->extensionName()->name(), - }; - }, - $composerInstalledPackages, - ), - $composerInstalledPackages, - ); + ))); } } diff --git a/src/Platform/PiePackageList.php b/src/Platform/PiePackageList.php new file mode 100644 index 00000000..4e7078bf --- /dev/null +++ b/src/Platform/PiePackageList.php @@ -0,0 +1,70 @@ + $piePackages */ + public function __construct(private readonly array $piePackages) + { + } + + public function findByPhpFormattedExtensionName(string $phpFormattedExtensionName): PiePackageList + { + return new self(array_values(array_filter( + $this->piePackages, + static fn (Package $piePackage) => $piePackage->extensionName()->phpFormattedExtensionName() === $phpFormattedExtensionName, + ))); + } + + public function findByPackageName(string $packageName): Package + { + foreach ($this->piePackages as $piePackage) { + if ($piePackage->name() === $packageName) { + return $piePackage; + } + } + + throw new OutOfRangeException('Package ' . $packageName . ' not in the list'); + } + + public function onlyVerifiedFor(TargetPlatform $targetPlatform): self + { + return new self(array_values(array_filter( + $this->piePackages, + static fn (Package $piePackage) => $piePackage->verifyPackageStatus($targetPlatform) === PackageVerificationStatus::Verified, + ))); + } + + public function onlyOne(): Package + { + Assert::count($this->piePackages, 1); + + return $this->piePackages[array_key_first($this->piePackages)]; + } + + /** @return list */ + public function packages(): array + { + return $this->piePackages; + } + + public function count(): int + { + return count($this->piePackages); + } +} diff --git a/src/Util/PackageVerificationStatus.php b/src/Util/PackageVerificationStatus.php new file mode 100644 index 00000000..d0048194 --- /dev/null +++ b/src/Util/PackageVerificationStatus.php @@ -0,0 +1,27 @@ + Emoji::GREEN_CHECKMARK, + self::ChecksumMismatch => Emoji::PROHIBITED . ' - checksum mismatch', + self::ActualBinaryNotFound => Emoji::WARNING . ' - extension file not found', + self::InstalledBinaryMetadataMissing => Emoji::WARNING . ' - installed extension metadata missing', + self::ChecksumMetadataMissing => Emoji::WARNING . ' - binary checksum metadata missing', + self::InstalledBinaryPathDoesNotMatchActualBinaryPath => Emoji::WARNING . ' - binary path mismatch', + }; + } +} diff --git a/test/integration/Command/InstallExtensionsForProjectCommandTest.php b/test/integration/Command/InstallExtensionsForProjectCommandTest.php index ad9f6cfa..34e758be 100644 --- a/test/integration/Command/InstallExtensionsForProjectCommandTest.php +++ b/test/integration/Command/InstallExtensionsForProjectCommandTest.php @@ -26,6 +26,7 @@ use Php\Pie\Installing\InstallForPhpProject\InstallPiePackageFromPath; use Php\Pie\Installing\InstallForPhpProject\InstallSelectedPackage; use Php\Pie\Platform\InstalledPiePackages; +use Php\Pie\Platform\PiePackageList; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -135,6 +136,8 @@ public function testInstallingExtensionsForPhpProject(): void ) ->willReturn(0); + $this->installedPiePackages->method('allPiePackages')->willReturn(new PiePackageList([])); + $this->commandTester->execute( ['--allow-non-interactive-project-install' => true], ['verbosity' => BufferedOutput::VERBOSITY_VERY_VERBOSE], @@ -182,6 +185,8 @@ public function testInstallingExtensionsForPhpProjectWithMultipleMatches(): void $this->installSelectedPackage->expects(self::never()) ->method('withSubCommand'); + $this->installedPiePackages->method('allPiePackages')->willReturn(new PiePackageList([])); + $this->commandTester->execute( ['--allow-non-interactive-project-install' => true], ['verbosity' => BufferedOutput::VERBOSITY_VERY_VERBOSE], diff --git a/test/unit/ComposerIntegration/PhpBinaryPathBasedPlatformRepositoryTest.php b/test/unit/ComposerIntegration/PhpBinaryPathBasedPlatformRepositoryTest.php index fa38aec8..e827f201 100644 --- a/test/unit/ComposerIntegration/PhpBinaryPathBasedPlatformRepositoryTest.php +++ b/test/unit/ComposerIntegration/PhpBinaryPathBasedPlatformRepositoryTest.php @@ -14,6 +14,7 @@ use Php\Pie\DependencyResolver\Package; use Php\Pie\ExtensionName; use Php\Pie\Platform\InstalledPiePackages; +use Php\Pie\Platform\PiePackageList; use Php\Pie\Platform\TargetPhp\PhpBinaryPath; use Php\Pie\Util\Process; use PHPUnit\Framework\Attributes\CoversClass; @@ -35,7 +36,7 @@ public function testPlatformRepositoryContainsExpectedPacakges(): void $composer = $this->createMock(Composer::class); $installedPiePackages = $this->createMock(InstalledPiePackages::class); - $installedPiePackages->method('allPiePackages')->willReturn([]); + $installedPiePackages->method('allPiePackages')->willReturn(new PiePackageList([])); $phpBinaryPath = $this->createMock(PhpBinaryPath::class); $phpBinaryPath->expects(self::once()) @@ -75,7 +76,7 @@ public function testPlatformRepositoryExcludesExtensionBeingInstalled(): void $composer = $this->createMock(Composer::class); $installedPiePackages = $this->createMock(InstalledPiePackages::class); - $installedPiePackages->method('allPiePackages')->willReturn([]); + $installedPiePackages->method('allPiePackages')->willReturn(new PiePackageList([])); $extensionBeingInstalled = ExtensionName::normaliseFromString('extension_being_installed'); @@ -116,9 +117,9 @@ public function testPlatformRepositoryExcludesReplacedExtensions(): void 'ext-replaced_extension' => new Link('myvendor/replaced_extension', 'ext-replaced_extension', new Constraint('==', '*')), ]); $installedPiePackages = $this->createMock(InstalledPiePackages::class); - $installedPiePackages->method('allPiePackages')->willReturn([ + $installedPiePackages->method('allPiePackages')->willReturn(new PiePackageList([ Package::fromComposerCompletePackage($composerPackage), - ]); + ])); $extensionBeingInstalled = ExtensionName::normaliseFromString('extension_being_installed'); @@ -216,6 +217,9 @@ public function testLibrariesAreIncluded(string $packageName): void self::markTestSkipped('pkg-config not available on Windows'); } + $installedPiePackages = $this->createMock(InstalledPiePackages::class); + $installedPiePackages->method('allPiePackages')->willReturn(new PiePackageList([])); + self::assertTrue(in_array( 'lib-' . $packageName, array_map( @@ -223,7 +227,7 @@ public function testLibrariesAreIncluded(string $packageName): void (new PhpBinaryPathBasedPlatformRepository( PhpBinaryPath::fromCurrentProcess(), $this->createMock(Composer::class), - $this->createMock(InstalledPiePackages::class), + $installedPiePackages, ExtensionName::normaliseFromString('extension_being_installed'), ))->getPackages(), ), diff --git a/test/unit/Platform/InstalledPiePackagesTest.php b/test/unit/Platform/InstalledPiePackagesTest.php index b273cd2a..e4682ce1 100644 --- a/test/unit/Platform/InstalledPiePackagesTest.php +++ b/test/unit/Platform/InstalledPiePackagesTest.php @@ -29,15 +29,14 @@ public function testAllPiePackages(): void $composer = $this->createMock(Composer::class); $composer->method('getRepositoryManager')->willReturn($repoManager); - $packages = (new InstalledPiePackages())->allPiePackages($composer); + $packages = (new InstalledPiePackages())->allPiePackages($composer)->packages(); - self::assertArrayHasKey('bar1', $packages); - self::assertArrayHasKey('bar2', $packages); + self::assertCount(2, $packages); - self::assertSame('bar1', $packages['bar1']->extensionName()->name()); - self::assertSame('foo/bar1', $packages['bar1']->name()); - self::assertSame('bar2', $packages['bar2']->extensionName()->name()); - self::assertSame('foo/bar2', $packages['bar2']->name()); + self::assertSame('bar1', $packages[0]->extensionName()->name()); + self::assertSame('foo/bar1', $packages[0]->name()); + self::assertSame('bar2', $packages[1]->extensionName()->name()); + self::assertSame('foo/bar2', $packages[1]->name()); } public function testInvalidExtensionNamesAreFilteredOut(): void