From 9f932732b97464cb4f11e285ef225db883320872 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Wed, 29 Jan 2025 21:07:49 +0000 Subject: [PATCH 01/14] Move Composer event listeners into namespace --- .../{ => Listeners}/OverrideWindowsUrlInstallListener.php | 3 ++- .../{ => Listeners}/RemoveUnrelatedInstallOperations.php | 3 ++- src/ComposerIntegration/PieComposerFactory.php | 2 ++ .../{ => Listeners}/OverrideWindowsUrlInstallListenerTest.php | 4 ++-- .../{ => Listeners}/RemoveUnrelatedInstallOperationsTest.php | 4 ++-- 5 files changed, 10 insertions(+), 6 deletions(-) rename src/ComposerIntegration/{ => Listeners}/OverrideWindowsUrlInstallListener.php (96%) rename src/ComposerIntegration/{ => Listeners}/RemoveUnrelatedInstallOperations.php (96%) rename test/unit/ComposerIntegration/{ => Listeners}/OverrideWindowsUrlInstallListenerTest.php (97%) rename test/unit/ComposerIntegration/{ => Listeners}/RemoveUnrelatedInstallOperationsTest.php (97%) diff --git a/src/ComposerIntegration/OverrideWindowsUrlInstallListener.php b/src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php similarity index 96% rename from src/ComposerIntegration/OverrideWindowsUrlInstallListener.php rename to src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php index 43e064a..657f605 100644 --- a/src/ComposerIntegration/OverrideWindowsUrlInstallListener.php +++ b/src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Php\Pie\ComposerIntegration; +namespace Php\Pie\ComposerIntegration\Listeners; use Composer\Composer; use Composer\DependencyResolver\Operation\InstallOperation; @@ -12,6 +12,7 @@ use Composer\Package\CompletePackageInterface; use Composer\Util\AuthHelper; use Composer\Util\HttpDownloader; +use Php\Pie\ComposerIntegration\PieComposerRequest; use Php\Pie\DependencyResolver\Package; use Php\Pie\Downloading\PackageReleaseAssets; use Php\Pie\Platform\OperatingSystem; diff --git a/src/ComposerIntegration/RemoveUnrelatedInstallOperations.php b/src/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperations.php similarity index 96% rename from src/ComposerIntegration/RemoveUnrelatedInstallOperations.php rename to src/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperations.php index 874ce7e..eb7a8a4 100644 --- a/src/ComposerIntegration/RemoveUnrelatedInstallOperations.php +++ b/src/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperations.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Php\Pie\ComposerIntegration; +namespace Php\Pie\ComposerIntegration\Listeners; use Closure; use Composer\Composer; @@ -11,6 +11,7 @@ use Composer\DependencyResolver\Transaction; use Composer\Installer\InstallerEvent; use Composer\Installer\InstallerEvents; +use Php\Pie\ComposerIntegration\PieComposerRequest; use Symfony\Component\Console\Output\OutputInterface; use function array_filter; diff --git a/src/ComposerIntegration/PieComposerFactory.php b/src/ComposerIntegration/PieComposerFactory.php index 279348d..2207b7f 100644 --- a/src/ComposerIntegration/PieComposerFactory.php +++ b/src/ComposerIntegration/PieComposerFactory.php @@ -11,6 +11,8 @@ use Composer\PartialComposer; use Composer\Util\Filesystem; use Composer\Util\ProcessExecutor; +use Php\Pie\ComposerIntegration\Listeners\OverrideWindowsUrlInstallListener; +use Php\Pie\ComposerIntegration\Listeners\RemoveUnrelatedInstallOperations; use Php\Pie\ExtensionType; use Php\Pie\Platform; use Psr\Container\ContainerInterface; diff --git a/test/unit/ComposerIntegration/OverrideWindowsUrlInstallListenerTest.php b/test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php similarity index 97% rename from test/unit/ComposerIntegration/OverrideWindowsUrlInstallListenerTest.php rename to test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php index 8e9d269..115600f 100644 --- a/test/unit/ComposerIntegration/OverrideWindowsUrlInstallListenerTest.php +++ b/test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Php\PieUnitTest\ComposerIntegration; +namespace Php\PieUnitTest\ComposerIntegration\Listeners; use Composer\Composer; use Composer\DependencyResolver\Transaction; @@ -11,7 +11,7 @@ use Composer\Installer\InstallerEvents; use Composer\IO\IOInterface; use Composer\Package\CompletePackage; -use Php\Pie\ComposerIntegration\OverrideWindowsUrlInstallListener; +use Php\Pie\ComposerIntegration\Listeners\OverrideWindowsUrlInstallListener; use Php\Pie\ComposerIntegration\PieComposerRequest; use Php\Pie\ComposerIntegration\PieOperation; use Php\Pie\DependencyResolver\RequestedPackageAndVersion; diff --git a/test/unit/ComposerIntegration/RemoveUnrelatedInstallOperationsTest.php b/test/unit/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperationsTest.php similarity index 97% rename from test/unit/ComposerIntegration/RemoveUnrelatedInstallOperationsTest.php rename to test/unit/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperationsTest.php index 0703e3b..44dd5a9 100644 --- a/test/unit/ComposerIntegration/RemoveUnrelatedInstallOperationsTest.php +++ b/test/unit/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperationsTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Php\PieUnitTest\ComposerIntegration; +namespace Php\PieUnitTest\ComposerIntegration\Listeners; use Composer\Composer; use Composer\DependencyResolver\Operation\InstallOperation; @@ -15,7 +15,7 @@ use Composer\Package\CompletePackage; use Php\Pie\ComposerIntegration\PieComposerRequest; use Php\Pie\ComposerIntegration\PieOperation; -use Php\Pie\ComposerIntegration\RemoveUnrelatedInstallOperations; +use Php\Pie\ComposerIntegration\Listeners\RemoveUnrelatedInstallOperations; use Php\Pie\DependencyResolver\RequestedPackageAndVersion; use Php\Pie\Platform\Architecture; use Php\Pie\Platform\OperatingSystem; From a6fad772f3abba273fd690249a87598ddef378a7 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Wed, 29 Jan 2025 22:22:07 +0000 Subject: [PATCH 02/14] Externalise the possible asset names when fetching release assets --- .../OverrideWindowsUrlInstallListener.php | 10 ++++- .../GithubPackageReleaseAssets.php | 32 +++++++-------- src/Downloading/PackageReleaseAssets.php | 9 ++++- .../GithubPackageReleaseAssetsTest.php | 7 +++- .../OverrideWindowsUrlInstallListenerTest.php | 2 +- .../RemoveUnrelatedInstallOperationsTest.php | 2 +- .../GithubPackageReleaseAssetsTest.php | 40 +++++++++++++++++-- 7 files changed, 76 insertions(+), 26 deletions(-) diff --git a/src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php b/src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php index 657f605..17df0bf 100644 --- a/src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php +++ b/src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php @@ -16,6 +16,7 @@ use Php\Pie\DependencyResolver\Package; use Php\Pie\Downloading\PackageReleaseAssets; use Php\Pie\Platform\OperatingSystem; +use Php\Pie\Platform\WindowsExtensionAssetName; use Psr\Container\ContainerInterface; use Webmozart\Assert\Assert; @@ -62,12 +63,17 @@ public function __invoke(InstallerEvent $installerEvent): void $composerPackage = $operation->getPackage(); Assert::isInstanceOf($composerPackage, CompletePackageInterface::class, 'I can only handle %2$s, got %s'); + $piePackage = Package::fromComposerCompletePackage($composerPackage); $packageReleaseAssets = $this->container->get(PackageReleaseAssets::class); - $url = $packageReleaseAssets->findWindowsDownloadUrlForPackage( + $url = $packageReleaseAssets->findMatchingReleaseAssetUrl( $this->composerRequest->targetPlatform, - Package::fromComposerCompletePackage($composerPackage), + $piePackage, new AuthHelper($this->io, $this->composer->getConfig()), new HttpDownloader($this->io, $this->composer->getConfig()), + WindowsExtensionAssetName::zipNames( + $this->composerRequest->targetPlatform, + $piePackage, + ), ); $this->composerRequest->pieOutput->writeln('Found prebuilt archive: ' . $url); diff --git a/src/Downloading/GithubPackageReleaseAssets.php b/src/Downloading/GithubPackageReleaseAssets.php index 69f338d..d2cde98 100644 --- a/src/Downloading/GithubPackageReleaseAssets.php +++ b/src/Downloading/GithubPackageReleaseAssets.php @@ -9,7 +9,6 @@ use Composer\Util\HttpDownloader; use Php\Pie\DependencyResolver\Package; use Php\Pie\Platform\TargetPlatform; -use Php\Pie\Platform\WindowsExtensionAssetName; use Webmozart\Assert\Assert; use function array_map; @@ -25,47 +24,48 @@ public function __construct( ) { } - /** @return non-empty-string */ - public function findWindowsDownloadUrlForPackage( + /** + * @param non-empty-list $possibleReleaseAssetNames + * + * @return non-empty-string + */ + public function findMatchingReleaseAssetUrl( TargetPlatform $targetPlatform, Package $package, AuthHelper $authHelper, HttpDownloader $httpDownloader, + array $possibleReleaseAssetNames, ): string { $releaseAsset = $this->selectMatchingReleaseAsset( - $targetPlatform, $package, $this->getReleaseAssetsForPackage($package, $authHelper, $httpDownloader), + $possibleReleaseAssetNames, ); return $releaseAsset['browser_download_url']; } - /** @return non-empty-list */ - private function expectedWindowsAssetNames(TargetPlatform $targetPlatform, Package $package): array - { - return WindowsExtensionAssetName::zipNames($targetPlatform, $package); - } - /** @link https://github.com/squizlabs/PHP_CodeSniffer/issues/3734 */ // phpcs:disable Squiz.Commenting.FunctionComment.MissingParamName /** * @param list $releaseAssets + * @param non-empty-list $possibleReleaseAssetNames * * @return array{name: non-empty-string, browser_download_url: non-empty-string, ...} */ // phpcs:enable - private function selectMatchingReleaseAsset(TargetPlatform $targetPlatform, Package $package, array $releaseAssets): array - { - $expectedAssetNames = $this->expectedWindowsAssetNames($targetPlatform, $package); - + private function selectMatchingReleaseAsset( + Package $package, + array $releaseAssets, + array $possibleReleaseAssetNames, + ): array { foreach ($releaseAssets as $releaseAsset) { - if (in_array(strtolower($releaseAsset['name']), $expectedAssetNames, true)) { + if (in_array(strtolower($releaseAsset['name']), $possibleReleaseAssetNames, true)) { return $releaseAsset; } } - throw Exception\CouldNotFindReleaseAsset::forPackage($package, $expectedAssetNames); + throw Exception\CouldNotFindReleaseAsset::forPackage($package, $possibleReleaseAssetNames); } /** @return list */ diff --git a/src/Downloading/PackageReleaseAssets.php b/src/Downloading/PackageReleaseAssets.php index 5f79cc3..4e49885 100644 --- a/src/Downloading/PackageReleaseAssets.php +++ b/src/Downloading/PackageReleaseAssets.php @@ -12,11 +12,16 @@ /** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */ interface PackageReleaseAssets { - /** @return non-empty-string */ - public function findWindowsDownloadUrlForPackage( + /** + * @param non-empty-list $possibleReleaseAssetNames + * + * @return non-empty-string + */ + public function findMatchingReleaseAssetUrl( TargetPlatform $targetPlatform, Package $package, AuthHelper $authHelper, HttpDownloader $httpDownloader, + array $possibleReleaseAssetNames, ): string; } diff --git a/test/integration/Downloading/GithubPackageReleaseAssetsTest.php b/test/integration/Downloading/GithubPackageReleaseAssetsTest.php index 1bd9d56..664b1cb 100644 --- a/test/integration/Downloading/GithubPackageReleaseAssetsTest.php +++ b/test/integration/Downloading/GithubPackageReleaseAssetsTest.php @@ -20,6 +20,7 @@ use Php\Pie\Platform\TargetPlatform; use Php\Pie\Platform\ThreadSafetyMode; use Php\Pie\Platform\WindowsCompiler; +use Php\Pie\Platform\WindowsExtensionAssetName; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -77,11 +78,15 @@ public function testDeterminingReleaseAssetUrlForWindows(): void self::assertSame( 'https://github.com/asgrim/example-pie-extension/releases/download/2.0.2/php_example_pie_extension-2.0.2-8.3-ts-vs16-x86_64.zip', (new GithubPackageReleaseAssets('https://api.github.com')) - ->findWindowsDownloadUrlForPackage( + ->findMatchingReleaseAssetUrl( $targetPlatform, $package, new AuthHelper($io, $config), new HttpDownloader($io, $config), + WindowsExtensionAssetName::zipNames( + $targetPlatform, + $package, + ), ), ); } diff --git a/test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php b/test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php index 115600f..942049c 100644 --- a/test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php +++ b/test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php @@ -157,7 +157,7 @@ public function testDistUrlIsUpdatedForWindowsInstallers(): void $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); $packageReleaseAssets ->expects(self::once()) - ->method('findWindowsDownloadUrlForPackage') + ->method('findMatchingReleaseAssetUrl') ->willReturn('https://example.com/windows-download-url'); $this->container diff --git a/test/unit/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperationsTest.php b/test/unit/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperationsTest.php index 44dd5a9..f251c42 100644 --- a/test/unit/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperationsTest.php +++ b/test/unit/ComposerIntegration/Listeners/RemoveUnrelatedInstallOperationsTest.php @@ -13,9 +13,9 @@ use Composer\Installer\InstallerEvents; use Composer\IO\IOInterface; use Composer\Package\CompletePackage; +use Php\Pie\ComposerIntegration\Listeners\RemoveUnrelatedInstallOperations; use Php\Pie\ComposerIntegration\PieComposerRequest; use Php\Pie\ComposerIntegration\PieOperation; -use Php\Pie\ComposerIntegration\Listeners\RemoveUnrelatedInstallOperations; use Php\Pie\DependencyResolver\RequestedPackageAndVersion; use Php\Pie\Platform\Architecture; use Php\Pie\Platform\OperatingSystem; diff --git a/test/unit/Downloading/GithubPackageReleaseAssetsTest.php b/test/unit/Downloading/GithubPackageReleaseAssetsTest.php index 34d8e25..a6cf7cf 100644 --- a/test/unit/Downloading/GithubPackageReleaseAssetsTest.php +++ b/test/unit/Downloading/GithubPackageReleaseAssetsTest.php @@ -21,6 +21,7 @@ use Php\Pie\Platform\TargetPlatform; use Php\Pie\Platform\ThreadSafetyMode; use Php\Pie\Platform\WindowsCompiler; +use Php\Pie\Platform\WindowsExtensionAssetName; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -89,7 +90,19 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrl(): void $releaseAssets = new GithubPackageReleaseAssets('https://test-github-api-base-url.thephp.foundation'); - self::assertSame('actual_download_url', $releaseAssets->findWindowsDownloadUrlForPackage($targetPlatform, $package, $authHelper, $httpDownloader)); + self::assertSame( + 'actual_download_url', + $releaseAssets->findMatchingReleaseAssetUrl( + $targetPlatform, + $package, + $authHelper, + $httpDownloader, + WindowsExtensionAssetName::zipNames( + $targetPlatform, + $package, + ), + ), + ); } public function testUrlIsReturnedWhenFindingWindowsDownloadUrlWithCompilerAndThreadSafetySwapped(): void @@ -152,7 +165,19 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrlWithCompilerAndThr $releaseAssets = new GithubPackageReleaseAssets('https://test-github-api-base-url.thephp.foundation'); - self::assertSame('actual_download_url', $releaseAssets->findWindowsDownloadUrlForPackage($targetPlatform, $package, $authHelper, $httpDownloader)); + self::assertSame( + 'actual_download_url', + $releaseAssets->findMatchingReleaseAssetUrl( + $targetPlatform, + $package, + $authHelper, + $httpDownloader, + WindowsExtensionAssetName::zipNames( + $targetPlatform, + $package, + ), + ), + ); } public function testFindWindowsDownloadUrlForPackageThrowsExceptionWhenAssetNotFound(): void @@ -197,6 +222,15 @@ public function testFindWindowsDownloadUrlForPackageThrowsExceptionWhenAssetNotF $releaseAssets = new GithubPackageReleaseAssets('https://test-github-api-base-url.thephp.foundation'); $this->expectException(CouldNotFindReleaseAsset::class); - $releaseAssets->findWindowsDownloadUrlForPackage($targetPlatform, $package, $authHelper, $httpDownloader); + $releaseAssets->findMatchingReleaseAssetUrl( + $targetPlatform, + $package, + $authHelper, + $httpDownloader, + WindowsExtensionAssetName::zipNames( + $targetPlatform, + $package, + ), + ); } } From 933b9946262a1779d84b73776629439a50e20214 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 30 Jan 2025 11:57:23 +0000 Subject: [PATCH 03/14] Update download URL override to support different DownloadUrlMethod values --- .../OverrideDownloadUrlInstallListener.php | 110 ++++++++++++++++++ .../OverrideWindowsUrlInstallListener.php | 82 ------------- .../PieComposerFactory.php | 4 +- src/Downloading/DownloadUrlMethod.php | 50 ++++++++ src/Platform/PrePackagedSourceAssetName.php | 42 +++++++ ...verrideDownloadUrlInstallListenerTest.php} | 90 ++++++++++++-- .../Downloading/DownloadUrlMethodTest.php | 28 +++++ .../PrePackagedSourceAssetNameTest.php | 18 +++ 8 files changed, 333 insertions(+), 91 deletions(-) create mode 100644 src/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListener.php delete mode 100644 src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php create mode 100644 src/Downloading/DownloadUrlMethod.php create mode 100644 src/Platform/PrePackagedSourceAssetName.php rename test/unit/ComposerIntegration/Listeners/{OverrideWindowsUrlInstallListenerTest.php => OverrideDownloadUrlInstallListenerTest.php} (67%) create mode 100644 test/unit/Downloading/DownloadUrlMethodTest.php create mode 100644 test/unit/Platform/PrePackagedSourceAssetNameTest.php diff --git a/src/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListener.php b/src/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListener.php new file mode 100644 index 0000000..fc8a6cd --- /dev/null +++ b/src/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListener.php @@ -0,0 +1,110 @@ +getEventDispatcher() + ->addListener( + InstallerEvents::PRE_OPERATIONS_EXEC, + new self($composer, $io, $container, $composerRequest), + ); + } + + public function __invoke(InstallerEvent $installerEvent): void + { + /** @psalm-suppress InternalMethod */ + $operations = $installerEvent->getTransaction()?->getOperations() ?? []; + + array_walk( + $operations, + function (OperationInterface $operation): void { + if (! $operation instanceof InstallOperation) { + return; + } + + $composerPackage = $operation->getPackage(); + if (! $composerPackage instanceof CompletePackageInterface) { + return; + } + + // Install requests for other packages than the one we want should be ignored + if ($this->composerRequest->requestedPackage->package !== $composerPackage->getName()) { + return; + } + + $piePackage = Package::fromComposerCompletePackage($composerPackage); + $targetPlatform = $this->composerRequest->targetPlatform; + $downloadUrlMethod = DownloadUrlMethod::fromPackage($piePackage, $targetPlatform); + + // Exit early if we should just use Composer's normal download + if ($downloadUrlMethod === DownloadUrlMethod::ComposerDefaultDownload) { + return; + } + + $possibleAssetNames = $downloadUrlMethod->possibleAssetNames($piePackage, $targetPlatform); + if ($possibleAssetNames === null) { + return; + } + + // @todo https://github.com/php/pie/issues/138 will need to depend on the repo type (GH/GL/BB/etc.) + $packageReleaseAssets = $this->container->get(PackageReleaseAssets::class); + + $url = $packageReleaseAssets->findMatchingReleaseAssetUrl( + $targetPlatform, + $piePackage, + new AuthHelper($this->io, $this->composer->getConfig()), + new HttpDownloader($this->io, $this->composer->getConfig()), + $possibleAssetNames, + ); + + $this->composerRequest->pieOutput->writeln('Found prebuilt archive: ' . $url); + $composerPackage->setDistUrl($url); + + if (pathinfo($url, PATHINFO_EXTENSION) !== 'tgz') { + return; + } + + $composerPackage->setDistType('tar'); + }, + ); + } +} diff --git a/src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php b/src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php deleted file mode 100644 index 17df0bf..0000000 --- a/src/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListener.php +++ /dev/null @@ -1,82 +0,0 @@ -getEventDispatcher() - ->addListener( - InstallerEvents::PRE_OPERATIONS_EXEC, - new self($composer, $io, $container, $composerRequest), - ); - } - - public function __invoke(InstallerEvent $installerEvent): void - { - if ($this->composerRequest->targetPlatform->operatingSystem !== OperatingSystem::Windows) { - return; - } - - /** @psalm-suppress InternalMethod */ - $operations = $installerEvent->getTransaction()?->getOperations() ?? []; - - Assert::count($operations, 1, 'I can only do exactly %d thing at once, %d attempted'); - $operation = reset($operations); - Assert::isInstanceOf($operation, InstallOperation::class, 'I can only handle %2$s, got %s'); - - $composerPackage = $operation->getPackage(); - Assert::isInstanceOf($composerPackage, CompletePackageInterface::class, 'I can only handle %2$s, got %s'); - - $piePackage = Package::fromComposerCompletePackage($composerPackage); - $packageReleaseAssets = $this->container->get(PackageReleaseAssets::class); - $url = $packageReleaseAssets->findMatchingReleaseAssetUrl( - $this->composerRequest->targetPlatform, - $piePackage, - new AuthHelper($this->io, $this->composer->getConfig()), - new HttpDownloader($this->io, $this->composer->getConfig()), - WindowsExtensionAssetName::zipNames( - $this->composerRequest->targetPlatform, - $piePackage, - ), - ); - - $this->composerRequest->pieOutput->writeln('Found prebuilt archive: ' . $url); - $composerPackage->setDistUrl($url); - } -} diff --git a/src/ComposerIntegration/PieComposerFactory.php b/src/ComposerIntegration/PieComposerFactory.php index 2207b7f..7acb235 100644 --- a/src/ComposerIntegration/PieComposerFactory.php +++ b/src/ComposerIntegration/PieComposerFactory.php @@ -11,7 +11,7 @@ use Composer\PartialComposer; use Composer\Util\Filesystem; use Composer\Util\ProcessExecutor; -use Php\Pie\ComposerIntegration\Listeners\OverrideWindowsUrlInstallListener; +use Php\Pie\ComposerIntegration\Listeners\OverrideDownloadUrlInstallListener; use Php\Pie\ComposerIntegration\Listeners\RemoveUnrelatedInstallOperations; use Php\Pie\ExtensionType; use Php\Pie\Platform; @@ -61,7 +61,7 @@ public static function createPieComposer( true, ); - OverrideWindowsUrlInstallListener::selfRegister($composer, $io, $container, $composerRequest); + OverrideDownloadUrlInstallListener::selfRegister($composer, $io, $container, $composerRequest); RemoveUnrelatedInstallOperations::selfRegister($composer, $composerRequest); $composer->getConfig()->merge(['config' => ['__PIE_REQUEST__' => $composerRequest]]); diff --git a/src/Downloading/DownloadUrlMethod.php b/src/Downloading/DownloadUrlMethod.php new file mode 100644 index 0000000..2b27085 --- /dev/null +++ b/src/Downloading/DownloadUrlMethod.php @@ -0,0 +1,50 @@ +|null */ + public function possibleAssetNames(Package $package, TargetPlatform $targetPlatform): array|null + { + return match ($this) { + self::WindowsBinaryDownload => WindowsExtensionAssetName::zipNames($targetPlatform, $package), + self::PrePackagedSourceDownload => PrePackagedSourceAssetName::packageNames($package), + self::ComposerDefaultDownload => null, + }; + } + + public static function fromPackage(Package $package, TargetPlatform $targetPlatform): self + { + /** + * PIE does not support building on Windows (yet, at least). Maintainers + * should provide pre-built Windows binaries. + */ + if ($targetPlatform->operatingSystem === OperatingSystem::Windows) { + return self::WindowsBinaryDownload; + } + + /** + * Some packages pre-package source code (e.g. mongodb) as there are + * external dependencies in Git submodules that otherwise aren't + * included in GitHub/Gitlab/etc "dist" downloads + */ + if (false) { // @todo check $package `php-ext` + return self::PrePackagedSourceDownload; + } + + return self::ComposerDefaultDownload; + } +} diff --git a/src/Platform/PrePackagedSourceAssetName.php b/src/Platform/PrePackagedSourceAssetName.php new file mode 100644 index 0000000..139e1ae --- /dev/null +++ b/src/Platform/PrePackagedSourceAssetName.php @@ -0,0 +1,42 @@ + */ + public static function packageNames(Package $package): array + { + return [ + strtolower(sprintf( + 'php_%s-%s-src.tgz', + $package->extensionName->name(), + $package->version, + )), + strtolower(sprintf( + 'php_%s-%s-src.zip', + $package->extensionName->name(), + $package->version, + )), + // @todo remove this: + strtolower(sprintf( + '%s-%s.tgz', + $package->extensionName->name(), + $package->version, + )), + ]; + } +} diff --git a/test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php similarity index 67% rename from test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php rename to test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php index 942049c..4e215bd 100644 --- a/test/unit/ComposerIntegration/Listeners/OverrideWindowsUrlInstallListenerTest.php +++ b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php @@ -11,7 +11,7 @@ use Composer\Installer\InstallerEvents; use Composer\IO\IOInterface; use Composer\Package\CompletePackage; -use Php\Pie\ComposerIntegration\Listeners\OverrideWindowsUrlInstallListener; +use Php\Pie\ComposerIntegration\Listeners\OverrideDownloadUrlInstallListener; use Php\Pie\ComposerIntegration\PieComposerRequest; use Php\Pie\ComposerIntegration\PieOperation; use Php\Pie\DependencyResolver\RequestedPackageAndVersion; @@ -29,8 +29,8 @@ use Psr\Container\ContainerInterface; use Symfony\Component\Console\Output\OutputInterface; -#[CoversClass(OverrideWindowsUrlInstallListener::class)] -final class OverrideWindowsUrlInstallListenerTest extends TestCase +#[CoversClass(OverrideDownloadUrlInstallListener::class)] +final class OverrideDownloadUrlInstallListenerTest extends TestCase { private Composer&MockObject $composer; private IOInterface&MockObject $io; @@ -53,7 +53,7 @@ public function testEventListenerRegistration(): void ->method('addListener') ->with( InstallerEvents::PRE_OPERATIONS_EXEC, - self::isInstanceOf(OverrideWindowsUrlInstallListener::class), + self::isInstanceOf(OverrideDownloadUrlInstallListener::class), ); $this->composer @@ -61,7 +61,7 @@ public function testEventListenerRegistration(): void ->method('getEventDispatcher') ->willReturn($eventDispatcher); - OverrideWindowsUrlInstallListener::selfRegister( + OverrideDownloadUrlInstallListener::selfRegister( $this->composer, $this->io, $this->container, @@ -85,6 +85,21 @@ public function testEventListenerRegistration(): void ); } + public function testNonInstallOperationsAreIgnored(): void + { + self::markTestIncomplete('todo'); // @todo + } + + public function testNonCompletePackagesAreIgnored(): void + { + self::markTestIncomplete('todo'); // @todo + } + + public function testInstallOperationsForDifferentPackagesAreIgnored(): void + { + self::markTestIncomplete('todo'); // @todo + } + public function testWindowsUrlInstallerDoesNotRunOnNonWindows(): void { $composerPackage = new CompletePackage('foo/bar', '1.2.3.0', '1.2.3'); @@ -107,7 +122,7 @@ public function testWindowsUrlInstallerDoesNotRunOnNonWindows(): void ->expects(self::never()) ->method('get'); - (new OverrideWindowsUrlInstallListener( + (new OverrideDownloadUrlInstallListener( $this->composer, $this->io, $this->container, @@ -165,7 +180,7 @@ public function testDistUrlIsUpdatedForWindowsInstallers(): void ->with(PackageReleaseAssets::class) ->willReturn($packageReleaseAssets); - (new OverrideWindowsUrlInstallListener( + (new OverrideDownloadUrlInstallListener( $this->composer, $this->io, $this->container, @@ -193,4 +208,65 @@ public function testDistUrlIsUpdatedForWindowsInstallers(): void $composerPackage->getDistUrl(), ); } + + public function testDistUrlIsUpdatedForPrePackagedTgzSource(): void + { + $composerPackage = new CompletePackage('foo/bar', '1.2.3.0', '1.2.3'); + $composerPackage->setDistType('zip'); + $composerPackage->setDistUrl('https://example.com/git-archive-zip-url'); + $composerPackage->setPhpExt(['extension-name' => 'mongodb']); + + /** + * @psalm-suppress InternalClass + * @psalm-suppress InternalMethod + */ + $installerEvent = new InstallerEvent( + InstallerEvents::PRE_OPERATIONS_EXEC, + $this->composer, + $this->io, + false, + true, + new Transaction([], [$composerPackage]), + ); + + $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); + $packageReleaseAssets + ->expects(self::once()) + ->method('findMatchingReleaseAssetUrl') + ->willReturn('https://example.com/pre-packaged-source-download-url.tgz'); + + $this->container + ->method('get') + ->with(PackageReleaseAssets::class) + ->willReturn($packageReleaseAssets); + + (new OverrideDownloadUrlInstallListener( + $this->composer, + $this->io, + $this->container, + new PieComposerRequest( + $this->createMock(OutputInterface::class), + new TargetPlatform( + OperatingSystem::NonWindows, + OperatingSystemFamily::Linux, + PhpBinaryPath::fromCurrentProcess(), + Architecture::x86_64, + ThreadSafetyMode::NonThreadSafe, + 1, + WindowsCompiler::VC15, + ), + new RequestedPackageAndVersion('foo/bar', '^1.1'), + PieOperation::Install, + [], + null, + false, + ), + ))($installerEvent); + + self::assertSame( + 'https://example.com/pre-packaged-source-download-url.tgz', + $composerPackage->getDistUrl(), + ); + self::assertSame('tar', $composerPackage->getDistType()); + } } diff --git a/test/unit/Downloading/DownloadUrlMethodTest.php b/test/unit/Downloading/DownloadUrlMethodTest.php new file mode 100644 index 0000000..53da6c5 --- /dev/null +++ b/test/unit/Downloading/DownloadUrlMethodTest.php @@ -0,0 +1,28 @@ + Date: Fri, 31 Jan 2025 10:34:55 +0000 Subject: [PATCH 04/14] Refactor PIE Package VO to improve the API --- src/Building/UnixBuild.php | 2 +- src/Command/BuildCommand.php | 2 +- src/Command/CommandHelper.php | 4 +- src/Command/DownloadCommand.php | 2 +- src/Command/InfoCommand.php | 16 +- src/Command/InstallCommand.php | 2 +- src/Command/ShowCommand.php | 4 +- .../ComposerIntegrationHandler.php | 4 +- src/DependencyResolver/Package.php | 158 +++++++++++++----- .../ResolveDependencyWithComposer.php | 12 +- src/Downloading/DownloadedPackage.php | 4 +- .../GithubPackageReleaseAssets.php | 6 +- .../Ini/AddExtensionToTheIniFile.php | 14 +- .../Ini/CheckAndAddExtensionToIniIfNeeded.php | 6 +- src/Installing/Ini/DockerPhpExtEnable.php | 8 +- src/Installing/Ini/OndrejPhpenmod.php | 6 +- .../Ini/PreCheckExtensionAlreadyLoaded.php | 2 +- .../Ini/StandardAdditionalPhpIniDirectory.php | 4 +- src/Installing/SetupIniFile.php | 4 +- src/Installing/UnixInstall.php | 2 +- src/Installing/WindowsInstall.php | 8 +- src/Platform/PrePackagedSourceAssetName.php | 12 +- src/Platform/WindowsExtensionAssetName.php | 8 +- test/integration/Building/UnixBuildTest.php | 51 +----- .../ResolveDependencyWithComposerTest.php | 6 +- .../GithubPackageReleaseAssetsTest.php | 7 - .../Installing/UnixInstallTest.php | 8 - .../Installing/WindowsInstallTest.php | 7 - test/unit/Command/CommandHelperTest.php | 33 ++-- test/unit/DependencyResolver/PackageTest.php | 45 +++-- .../ResolveDependencyWithComposerTest.php | 8 +- .../Downloading/DownloadedPackageTest.php | 29 +--- .../CouldNotFindReleaseAssetTest.php | 14 -- .../GithubPackageReleaseAssetsTest.php | 21 --- .../Ini/AddExtensionToTheIniFileTest.php | 39 +---- .../CheckAndAddExtensionToIniIfNeededTest.php | 25 +-- .../Installing/Ini/DockerPhpExtEnableTest.php | 13 +- .../Installing/Ini/OndrejPhpenmodTest.php | 7 - .../Ini/PickBestSetupIniApproachTest.php | 21 --- .../PreCheckExtensionAlreadyLoadedTest.php | 13 +- .../StandardAdditionalPhpIniDirectoryTest.php | 13 +- .../Ini/StandardSinglePhpIniTest.php | 7 - .../WindowsExtensionAssetNameTest.php | 7 - 43 files changed, 251 insertions(+), 413 deletions(-) diff --git a/src/Building/UnixBuild.php b/src/Building/UnixBuild.php index 6e7c994..3130407 100644 --- a/src/Building/UnixBuild.php +++ b/src/Building/UnixBuild.php @@ -76,7 +76,7 @@ public function __invoke( $this->make($targetPlatform, $downloadedPackage, $output, $outputCallback); - $expectedSoFile = $downloadedPackage->extractedSourcePath . '/modules/' . $downloadedPackage->package->extensionName->name() . '.so'; + $expectedSoFile = $downloadedPackage->extractedSourcePath . '/modules/' . $downloadedPackage->package->extensionName()->name() . '.so'; if (! file_exists($expectedSoFile)) { throw ExtensionBinaryNotFound::fromExpectedBinary($expectedSoFile); diff --git a/src/Command/BuildCommand.php b/src/Command/BuildCommand.php index 0998364..b118d68 100644 --- a/src/Command/BuildCommand.php +++ b/src/Command/BuildCommand.php @@ -64,7 +64,7 @@ public function execute(InputInterface $input, OutputInterface $output): int $requestedNameAndVersion, $forceInstallPackageVersion, ); - $output->writeln(sprintf('Found package: %s which provides %s', $package->prettyNameAndVersion(), $package->extensionName->nameWithExtPrefix())); + $output->writeln(sprintf('Found package: %s which provides %s', $package->prettyNameAndVersion(), $package->extensionName()->nameWithExtPrefix())); // Now we know what package we have, we can validate the configure options for the command and re-create the // Composer instance with the populated configure options diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index 1fc4c7a..8614fd2 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -226,7 +226,7 @@ public static function requestedNameAndVersionPair(InputInterface $input): Reque public static function bindConfigureOptionsFromPackage(Command $command, Package $package, InputInterface $input): void { - foreach ($package->configureOptions as $configureOption) { + foreach ($package->configureOptions() as $configureOption) { $command->addOption( $configureOption->name, null, @@ -242,7 +242,7 @@ public static function bindConfigureOptionsFromPackage(Command $command, Package public static function processConfigureOptionsFromInput(Package $package, InputInterface $input): array { $configureOptionsValues = []; - foreach ($package->configureOptions as $configureOption) { + foreach ($package->configureOptions() as $configureOption) { if (! $input->hasOption($configureOption->name)) { continue; } diff --git a/src/Command/DownloadCommand.php b/src/Command/DownloadCommand.php index 4a7439b..7d27add 100644 --- a/src/Command/DownloadCommand.php +++ b/src/Command/DownloadCommand.php @@ -66,7 +66,7 @@ public function execute(InputInterface $input, OutputInterface $output): int $requestedNameAndVersion, $forceInstallPackageVersion, ); - $output->writeln(sprintf('Found package: %s which provides %s', $package->prettyNameAndVersion(), $package->extensionName->nameWithExtPrefix())); + $output->writeln(sprintf('Found package: %s which provides %s', $package->prettyNameAndVersion(), $package->extensionName()->nameWithExtPrefix())); try { ($this->composerIntegrationHandler)( diff --git a/src/Command/InfoCommand.php b/src/Command/InfoCommand.php index 0d03e93..4cb5694 100644 --- a/src/Command/InfoCommand.php +++ b/src/Command/InfoCommand.php @@ -64,17 +64,17 @@ public function execute(InputInterface $input, OutputInterface $output): int $requestedNameAndVersion, CommandHelper::determineForceInstallingPackageVersion($input), ); - $output->writeln(sprintf('Found package: %s which provides %s', $package->prettyNameAndVersion(), $package->extensionName->nameWithExtPrefix())); + $output->writeln(sprintf('Found package: %s which provides %s', $package->prettyNameAndVersion(), $package->extensionName()->nameWithExtPrefix())); - $output->writeln(sprintf('Extension name: %s', $package->extensionName->name())); - $output->writeln(sprintf('Extension type: %s (%s)', $package->extensionType->value, $package->extensionType->name)); - $output->writeln(sprintf('Composer package name: %s', $package->name)); - $output->writeln(sprintf('Version: %s', $package->version)); - $output->writeln(sprintf('Download URL: %s', $package->downloadUrl ?? '(not specified)')); + $output->writeln(sprintf('Extension name: %s', $package->extensionName()->name())); + $output->writeln(sprintf('Extension type: %s (%s)', $package->extensionType()->value, $package->extensionType()->name)); + $output->writeln(sprintf('Composer package name: %s', $package->name())); + $output->writeln(sprintf('Version: %s', $package->version())); + $output->writeln(sprintf('Download URL: %s', $package->downloadUrl() ?? '(not specified)')); - if (count($package->configureOptions)) { + if (count($package->configureOptions())) { $output->writeln('Configure options:'); - foreach ($package->configureOptions as $configureOption) { + foreach ($package->configureOptions() as $configureOption) { $output->writeln(sprintf(' --%s%s (%s)', $configureOption->name, $configureOption->needsValue ? '=?' : '', $configureOption->description)); } } else { diff --git a/src/Command/InstallCommand.php b/src/Command/InstallCommand.php index 0640b5e..068f3c3 100644 --- a/src/Command/InstallCommand.php +++ b/src/Command/InstallCommand.php @@ -69,7 +69,7 @@ public function execute(InputInterface $input, OutputInterface $output): int $requestedNameAndVersion, $forceInstallPackageVersion, ); - $output->writeln(sprintf('Found package: %s which provides %s', $package->prettyNameAndVersion(), $package->extensionName->nameWithExtPrefix())); + $output->writeln(sprintf('Found package: %s which provides %s', $package->prettyNameAndVersion(), $package->extensionName()->nameWithExtPrefix())); // Now we know what package we have, we can validate the configure options for the command and re-create the // Composer instance with the populated configure options diff --git a/src/Command/ShowCommand.php b/src/Command/ShowCommand.php index cb750f1..2c07282 100644 --- a/src/Command/ShowCommand.php +++ b/src/Command/ShowCommand.php @@ -80,7 +80,7 @@ static function (string $version, string $phpExtensionName) use ($output, $piePa $extensionPath, $phpExtensionName, $extensionEnding, - PieInstalledJsonMetadataKeys::pieMetadataFromComposerPackage($piePackage->composerPackage), + PieInstalledJsonMetadataKeys::pieMetadataFromComposerPackage($piePackage->composerPackage()), ), )); }, @@ -152,7 +152,7 @@ static function (BasePackage $basePackage): bool { array_map( /** @return non-empty-string */ static function (Package $package): string { - return $package->extensionName->name(); + return $package->extensionName()->name(); }, $composerInstalledPackages, ), diff --git a/src/ComposerIntegration/ComposerIntegrationHandler.php b/src/ComposerIntegration/ComposerIntegrationHandler.php index 48d93aa..d9b8f7b 100644 --- a/src/ComposerIntegration/ComposerIntegrationHandler.php +++ b/src/ComposerIntegration/ComposerIntegrationHandler.php @@ -39,7 +39,7 @@ public function __invoke( // If user did not request a specific require version, use Composer to recommend one for the pie.json if ($recommendedRequireVersion === null) { - $recommendedRequireVersion = $versionSelector->findRecommendedRequireVersion($package->composerPackage); + $recommendedRequireVersion = $versionSelector->findRecommendedRequireVersion($package->composerPackage()); } // Write the new requirement to pie.json; because we later essentially just do a `composer install` using that file @@ -60,7 +60,7 @@ public function __invoke( $composerInstaller = PieComposerInstaller::createWithPhpBinary( $targetPlatform->phpBinaryPath, - $package->extensionName, + $package->extensionName(), $this->arrayCollectionIo, $composer, ); diff --git a/src/DependencyResolver/Package.php b/src/DependencyResolver/Package.php index d09a8a0..94519ff 100644 --- a/src/DependencyResolver/Package.php +++ b/src/DependencyResolver/Package.php @@ -26,53 +26,62 @@ * @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks * * @immutable + * + * @psalm-suppress PropertyNotSetInConstructor */ final class Package { - /** - * @param list $configureOptions - * @param non-empty-list|null $compatibleOsFamilies - * @param non-empty-list|null $incompatibleOsFamilies - */ + /** @var list */ + private array $configureOptions; + private int $priority; + private string|null $buildPath; + /** @var non-empty-list|null */ + private array|null $compatibleOsFamilies; + /** @var non-empty-list|null */ + private array|null $incompatibleOsFamilies; + private bool $supportZts; + private bool $supportNts; + public function __construct( - public readonly CompletePackageInterface $composerPackage, - public readonly ExtensionType $extensionType, - public readonly ExtensionName $extensionName, - public readonly string $name, - public readonly string $version, - public readonly string|null $downloadUrl, - public readonly array $configureOptions, - public readonly bool $supportZts, - public readonly bool $supportNts, - public readonly string|null $buildPath, - public readonly array|null $compatibleOsFamilies, - public readonly array|null $incompatibleOsFamilies, - public readonly int $priority, + private readonly CompletePackageInterface $composerPackage, + private readonly ExtensionType $extensionType, + private readonly ExtensionName $extensionName, + private readonly string $name, + private readonly string $version, + private readonly string|null $downloadUrl, ) { + $this->configureOptions = []; + $this->supportZts = true; + $this->supportNts = true; + $this->buildPath = null; + $this->compatibleOsFamilies = null; + $this->incompatibleOsFamilies = null; + $this->priority = 80; } public static function fromComposerCompletePackage(CompletePackageInterface $completePackage): self { + $package = new self( + $completePackage, + ExtensionType::tryFrom($completePackage->getType()) ?? ExtensionType::PhpModule, + ExtensionName::determineFromComposerPackage($completePackage), + $completePackage->getPrettyName(), + $completePackage->getPrettyVersion(), + $completePackage->getDistUrl(), + ); + $phpExtOptions = $completePackage->getPhpExt(); - $configureOptions = $phpExtOptions !== null && array_key_exists('configure-options', $phpExtOptions) + $package->configureOptions = $phpExtOptions !== null && array_key_exists('configure-options', $phpExtOptions) ? array_map( static fn (array $configureOption): ConfigureOption => ConfigureOption::fromComposerJsonDefinition($configureOption), $phpExtOptions['configure-options'], ) : []; - $supportZts = $phpExtOptions !== null && array_key_exists('support-zts', $phpExtOptions) - ? $phpExtOptions['support-zts'] - : true; - - $supportNts = $phpExtOptions !== null && array_key_exists('support-nts', $phpExtOptions) - ? $phpExtOptions['support-nts'] - : true; - - $buildPath = $phpExtOptions !== null && array_key_exists('build-path', $phpExtOptions) - ? $phpExtOptions['build-path'] - : null; + $package->supportZts = $phpExtOptions['support-zts'] ?? true; + $package->supportNts = $phpExtOptions['support-nts'] ?? true; + $package->buildPath = $phpExtOptions['build-path'] ?? null; $compatibleOsFamilies = $phpExtOptions['os-families'] ?? null; $incompatibleOsFamilies = $phpExtOptions['os-families-exclude'] ?? null; @@ -81,21 +90,12 @@ public static function fromComposerCompletePackage(CompletePackageInterface $com throw new InvalidArgumentException('Cannot specify both "os-families" and "os-families-exclude" in composer.json'); } - return new self( - $completePackage, - ExtensionType::tryFrom($completePackage->getType()) ?? ExtensionType::PhpModule, - ExtensionName::determineFromComposerPackage($completePackage), - $completePackage->getPrettyName(), - $completePackage->getPrettyVersion(), - $completePackage->getDistUrl(), - $configureOptions, - $supportZts, - $supportNts, - $buildPath, - self::convertInputStringsToOperatingSystemFamilies($compatibleOsFamilies), - self::convertInputStringsToOperatingSystemFamilies($incompatibleOsFamilies), - $phpExtOptions['priority'] ?? 80, - ); + $package->compatibleOsFamilies = self::convertInputStringsToOperatingSystemFamilies($compatibleOsFamilies); + $package->incompatibleOsFamilies = self::convertInputStringsToOperatingSystemFamilies($incompatibleOsFamilies); + + $package->priority = $phpExtOptions['priority'] ?? 80; + + return $package; } public function prettyNameAndVersion(): string @@ -146,4 +146,72 @@ private static function convertInputStringsToOperatingSystemFamilies(array|null return $osFamilies; } + + public function composerPackage(): CompletePackageInterface + { + return $this->composerPackage; + } + + public function extensionType(): ExtensionType + { + return $this->extensionType; + } + + public function extensionName(): ExtensionName + { + return $this->extensionName; + } + + public function name(): string + { + return $this->name; + } + + public function version(): string + { + return $this->version; + } + + /** @return list */ + public function configureOptions(): array + { + return $this->configureOptions; + } + + public function downloadUrl(): string|null + { + return $this->downloadUrl; + } + + public function priority(): int + { + return $this->priority; + } + + public function buildPath(): string|null + { + return $this->buildPath; + } + + /** @return non-empty-list|null */ + public function compatibleOsFamilies(): array|null + { + return $this->compatibleOsFamilies; + } + + /** @return non-empty-list|null */ + public function incompatibleOsFamilies(): array|null + { + return $this->incompatibleOsFamilies; + } + + public function supportZts(): bool + { + return $this->supportZts; + } + + public function supportNts(): bool + { + return $this->supportNts; + } } diff --git a/src/DependencyResolver/ResolveDependencyWithComposer.php b/src/DependencyResolver/ResolveDependencyWithComposer.php index d2bdbd2..9e4fe60 100644 --- a/src/DependencyResolver/ResolveDependencyWithComposer.php +++ b/src/DependencyResolver/ResolveDependencyWithComposer.php @@ -70,27 +70,27 @@ public function __invoke( private function assertCompatibleThreadSafetyMode(ThreadSafetyMode $threadSafetyMode, Package $resolvedPackage): void { - if ($threadSafetyMode === ThreadSafetyMode::NonThreadSafe && ! $resolvedPackage->supportNts) { + if ($threadSafetyMode === ThreadSafetyMode::NonThreadSafe && ! $resolvedPackage->supportNts()) { throw IncompatibleThreadSafetyMode::ztsExtensionOnNtsPlatform(); } - if ($threadSafetyMode === ThreadSafetyMode::ThreadSafe && ! $resolvedPackage->supportZts) { + if ($threadSafetyMode === ThreadSafetyMode::ThreadSafe && ! $resolvedPackage->supportZts()) { throw IncompatibleThreadSafetyMode::ntsExtensionOnZtsPlatform(); } } private function assertCompatibleOsFamily(TargetPlatform $targetPlatform, Package $resolvedPackage): void { - if ($resolvedPackage->compatibleOsFamilies !== null && ! in_array($targetPlatform->operatingSystemFamily, $resolvedPackage->compatibleOsFamilies, true)) { + if ($resolvedPackage->compatibleOsFamilies() !== null && ! in_array($targetPlatform->operatingSystemFamily, $resolvedPackage->compatibleOsFamilies(), true)) { throw IncompatibleOperatingSystemFamily::notInCompatibleOperatingSystemFamilies( - $resolvedPackage->compatibleOsFamilies, + $resolvedPackage->compatibleOsFamilies(), $targetPlatform->operatingSystemFamily, ); } - if ($resolvedPackage->incompatibleOsFamilies !== null && in_array($targetPlatform->operatingSystemFamily, $resolvedPackage->incompatibleOsFamilies, true)) { + if ($resolvedPackage->incompatibleOsFamilies() !== null && in_array($targetPlatform->operatingSystemFamily, $resolvedPackage->incompatibleOsFamilies(), true)) { throw IncompatibleOperatingSystemFamily::inIncompatibleOperatingSystemFamily( - $resolvedPackage->incompatibleOsFamilies, + $resolvedPackage->incompatibleOsFamilies(), $targetPlatform->operatingSystemFamily, ); } diff --git a/src/Downloading/DownloadedPackage.php b/src/Downloading/DownloadedPackage.php index 3f6adeb..ba57c4b 100644 --- a/src/Downloading/DownloadedPackage.php +++ b/src/Downloading/DownloadedPackage.php @@ -26,8 +26,8 @@ private function __construct( public static function fromPackageAndExtractedPath(Package $package, string $extractedSourcePath): self { - if ($package->buildPath !== null) { - $extractedSourcePathWithBuildPath = realpath($extractedSourcePath . DIRECTORY_SEPARATOR . $package->buildPath); + if ($package->buildPath() !== null) { + $extractedSourcePathWithBuildPath = realpath($extractedSourcePath . DIRECTORY_SEPARATOR . $package->buildPath()); if (is_string($extractedSourcePathWithBuildPath)) { $extractedSourcePath = $extractedSourcePathWithBuildPath; diff --git a/src/Downloading/GithubPackageReleaseAssets.php b/src/Downloading/GithubPackageReleaseAssets.php index d2cde98..4b526ae 100644 --- a/src/Downloading/GithubPackageReleaseAssets.php +++ b/src/Downloading/GithubPackageReleaseAssets.php @@ -74,16 +74,16 @@ private function getReleaseAssetsForPackage( AuthHelper $authHelper, HttpDownloader $httpDownloader, ): array { - Assert::notNull($package->downloadUrl); + Assert::notNull($package->downloadUrl()); try { $decodedRepsonse = $httpDownloader->get( - $this->githubApiBaseUrl . '/repos/' . $package->githubOrgAndRepository() . '/releases/tags/' . $package->version, + $this->githubApiBaseUrl . '/repos/' . $package->githubOrgAndRepository() . '/releases/tags/' . $package->version(), [ 'retry-auth-failure' => false, 'http' => [ 'method' => 'GET', - 'header' => $authHelper->addAuthenticationHeader([], $this->githubApiBaseUrl, $package->downloadUrl), + 'header' => $authHelper->addAuthenticationHeader([], $this->githubApiBaseUrl, $package->downloadUrl()), ], ], )->decodeJson(); diff --git a/src/Installing/Ini/AddExtensionToTheIniFile.php b/src/Installing/Ini/AddExtensionToTheIniFile.php index 73469e9..f4cece3 100644 --- a/src/Installing/Ini/AddExtensionToTheIniFile.php +++ b/src/Installing/Ini/AddExtensionToTheIniFile.php @@ -63,7 +63,7 @@ public function __invoke( $output->writeln( sprintf( 'Enabled extension %s in the INI file %s', - $package->extensionName->name(), + $package->extensionName()->name(), $ini, ), OutputInterface::VERBOSITY_VERBOSE, @@ -73,7 +73,7 @@ public function __invoke( return false; } - $phpBinaryPath->assertExtensionIsLoadedInRuntime($package->extensionName, $output); + $phpBinaryPath->assertExtensionIsLoadedInRuntime($package->extensionName(), $output); return true; } catch (Throwable $anything) { @@ -81,7 +81,7 @@ public function __invoke( $output->writeln(sprintf( 'Something went wrong enabling the %s extension: %s', - $package->extensionName->name(), + $package->extensionName()->name(), $anything->getMessage(), )); @@ -93,10 +93,10 @@ public function __invoke( private function iniFileContent(Package $package): string { return PHP_EOL - . '; PIE automatically added this to enable the ' . $package->name . ' extension' . PHP_EOL - . '; priority=' . $package->priority . PHP_EOL - . ($package->extensionType === ExtensionType::PhpModule ? 'extension' : 'zend_extension') + . '; PIE automatically added this to enable the ' . $package->name() . ' extension' . PHP_EOL + . '; priority=' . $package->priority() . PHP_EOL + . ($package->extensionType() === ExtensionType::PhpModule ? 'extension' : 'zend_extension') . '=' - . $package->extensionName->name() . PHP_EOL; + . $package->extensionName()->name() . PHP_EOL; } } diff --git a/src/Installing/Ini/CheckAndAddExtensionToIniIfNeeded.php b/src/Installing/Ini/CheckAndAddExtensionToIniIfNeeded.php index eec39db..1c3a57e 100644 --- a/src/Installing/Ini/CheckAndAddExtensionToIniIfNeeded.php +++ b/src/Installing/Ini/CheckAndAddExtensionToIniIfNeeded.php @@ -45,7 +45,7 @@ public function __invoke( return false; } - if (($this->isExtensionAlreadyInTheIniFile)($iniFile, $downloadedPackage->package->extensionName)) { + if (($this->isExtensionAlreadyInTheIniFile)($iniFile, $downloadedPackage->package->extensionName())) { $output->writeln( sprintf( 'Extension is already enabled in the INI file %s', @@ -59,13 +59,13 @@ public function __invoke( } try { - $targetPlatform->phpBinaryPath->assertExtensionIsLoadedInRuntime($downloadedPackage->package->extensionName, $output); + $targetPlatform->phpBinaryPath->assertExtensionIsLoadedInRuntime($downloadedPackage->package->extensionName(), $output); return true; } catch (Throwable $anything) { $output->writeln(sprintf( 'Something went wrong verifying the %s extension is enabled: %s', - $downloadedPackage->package->extensionName->name(), + $downloadedPackage->package->extensionName()->name(), $anything->getMessage(), )); diff --git a/src/Installing/Ini/DockerPhpExtEnable.php b/src/Installing/Ini/DockerPhpExtEnable.php index 2878af4..195b80b 100644 --- a/src/Installing/Ini/DockerPhpExtEnable.php +++ b/src/Installing/Ini/DockerPhpExtEnable.php @@ -41,12 +41,12 @@ public function setup( } try { - $enableOutput = Process::run([$dockerPhpExtEnable, $downloadedPackage->package->extensionName->name()]); + $enableOutput = Process::run([$dockerPhpExtEnable, $downloadedPackage->package->extensionName()->name()]); } catch (ProcessFailedException $processFailed) { $output->writeln( sprintf( 'Could not enable extension %s using %s. Exception was: %s', - $downloadedPackage->package->extensionName->name(), + $downloadedPackage->package->extensionName()->name(), $this->dockerPhpExtEnableName, $processFailed->getMessage(), ), @@ -58,7 +58,7 @@ public function setup( try { $targetPlatform->phpBinaryPath->assertExtensionIsLoadedInRuntime( - $downloadedPackage->package->extensionName, + $downloadedPackage->package->extensionName(), $output, ); @@ -67,7 +67,7 @@ public function setup( $output->writeln( sprintf( 'Asserting that extension %s was enabled using %s failed. Output was: %s', - $downloadedPackage->package->extensionName->name(), + $downloadedPackage->package->extensionName()->name(), $this->dockerPhpExtEnableName, $enableOutput !== '' ? $enableOutput : '(empty)', ), diff --git a/src/Installing/Ini/OndrejPhpenmod.php b/src/Installing/Ini/OndrejPhpenmod.php index 051dfb6..7c52d7d 100644 --- a/src/Installing/Ini/OndrejPhpenmod.php +++ b/src/Installing/Ini/OndrejPhpenmod.php @@ -119,7 +119,7 @@ public function setup( '%s%s%s.ini', rtrim($expectedModsAvailablePath, DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR, - $downloadedPackage->package->extensionName->name(), + $downloadedPackage->package->extensionName()->name(), ); $pieCreatedTheIniFile = false; @@ -148,7 +148,7 @@ static function () use ($phpenmodPath, $targetPlatform, $downloadedPackage, $out $targetPlatform->phpBinaryPath->majorMinorVersion(), '-s', 'ALL', - $downloadedPackage->package->extensionName->name(), + $downloadedPackage->package->extensionName()->name(), ]); return true; @@ -157,7 +157,7 @@ static function () use ($phpenmodPath, $targetPlatform, $downloadedPackage, $out sprintf( 'Failed to use %s to enable %s for PHP %s: %s', $phpenmodPath, - $downloadedPackage->package->extensionName->name(), + $downloadedPackage->package->extensionName()->name(), $targetPlatform->phpBinaryPath->majorMinorVersion(), $processFailedException->getMessage(), ), diff --git a/src/Installing/Ini/PreCheckExtensionAlreadyLoaded.php b/src/Installing/Ini/PreCheckExtensionAlreadyLoaded.php index 89f3681..9ae8c55 100644 --- a/src/Installing/Ini/PreCheckExtensionAlreadyLoaded.php +++ b/src/Installing/Ini/PreCheckExtensionAlreadyLoaded.php @@ -26,7 +26,7 @@ public function setup( ): bool { try { $targetPlatform->phpBinaryPath->assertExtensionIsLoadedInRuntime( - $downloadedPackage->package->extensionName, + $downloadedPackage->package->extensionName(), $output, ); diff --git a/src/Installing/Ini/StandardAdditionalPhpIniDirectory.php b/src/Installing/Ini/StandardAdditionalPhpIniDirectory.php index 84a4b50..af94dab 100644 --- a/src/Installing/Ini/StandardAdditionalPhpIniDirectory.php +++ b/src/Installing/Ini/StandardAdditionalPhpIniDirectory.php @@ -60,8 +60,8 @@ public function setup( '%s%s%d-%s.ini', rtrim($additionalIniFilesPath, DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR, - $downloadedPackage->package->priority, - $downloadedPackage->package->extensionName->name(), + $downloadedPackage->package->priority(), + $downloadedPackage->package->extensionName()->name(), ); $pieCreatedTheIniFile = false; diff --git a/src/Installing/SetupIniFile.php b/src/Installing/SetupIniFile.php index d6ca58b..35b11f5 100644 --- a/src/Installing/SetupIniFile.php +++ b/src/Installing/SetupIniFile.php @@ -45,8 +45,8 @@ public function __invoke( $output->writeln('⚠️ Extension has NOT been automatically enabled.'); $output->writeln(sprintf( 'You must now add "%s=%s" to your php.ini', - $downloadedPackage->package->extensionType === ExtensionType::PhpModule ? 'extension' : 'zend_extension', - $downloadedPackage->package->extensionName->name(), + $downloadedPackage->package->extensionType() === ExtensionType::PhpModule ? 'extension' : 'zend_extension', + $downloadedPackage->package->extensionName()->name(), )); } } diff --git a/src/Installing/UnixInstall.php b/src/Installing/UnixInstall.php index da831ee..efe9bea 100644 --- a/src/Installing/UnixInstall.php +++ b/src/Installing/UnixInstall.php @@ -33,7 +33,7 @@ public function __invoke( ): BinaryFile { $targetExtensionPath = $targetPlatform->phpBinaryPath->extensionPath(); - $sharedObjectName = $downloadedPackage->package->extensionName->name() . '.so'; + $sharedObjectName = $downloadedPackage->package->extensionName()->name() . '.so'; $expectedSharedObjectLocation = sprintf( '%s/%s', $targetExtensionPath, diff --git a/src/Installing/WindowsInstall.php b/src/Installing/WindowsInstall.php index 7ff5ef1..29d4ef2 100644 --- a/src/Installing/WindowsInstall.php +++ b/src/Installing/WindowsInstall.php @@ -86,8 +86,8 @@ public function __invoke( */ $output->writeln(sprintf( 'You must now add "%s=%s" to your php.ini', - $downloadedPackage->package->extensionType === ExtensionType::PhpModule ? 'extension' : 'zend_extension', - $downloadedPackage->package->extensionName->name(), + $downloadedPackage->package->extensionType() === ExtensionType::PhpModule ? 'extension' : 'zend_extension', + $downloadedPackage->package->extensionName()->name(), )); $binaryFile = BinaryFile::fromFileWithSha256Checksum($destinationDllName); @@ -122,7 +122,7 @@ private function normalisedPathsMatch(string $first, string $second): bool private function copyExtensionDll(TargetPlatform $targetPlatform, DownloadedPackage $downloadedPackage, string $sourceDllName): string { $destinationDllName = $targetPlatform->phpBinaryPath->extensionPath() . DIRECTORY_SEPARATOR - . 'php_' . $downloadedPackage->package->extensionName->name() . '.dll'; + . 'php_' . $downloadedPackage->package->extensionName()->name() . '.dll'; if (! copy($sourceDllName, $destinationDllName) || ! file_exists($destinationDllName) && ! is_file($destinationDllName)) { throw new RuntimeException('Failed to install DLL to ' . $destinationDllName); @@ -190,7 +190,7 @@ private function copyExtraFile(TargetPlatform $targetPlatform, DownloadedPackage { $destinationFullFilename = dirname($targetPlatform->phpBinaryPath->phpBinaryPath) . DIRECTORY_SEPARATOR . 'extras' . DIRECTORY_SEPARATOR - . $downloadedPackage->package->extensionName->name() . DIRECTORY_SEPARATOR + . $downloadedPackage->package->extensionName()->name() . DIRECTORY_SEPARATOR . substr($file->getPathname(), strlen($downloadedPackage->extractedSourcePath) + 1); $destinationPath = dirname($destinationFullFilename); diff --git a/src/Platform/PrePackagedSourceAssetName.php b/src/Platform/PrePackagedSourceAssetName.php index 139e1ae..13aea73 100644 --- a/src/Platform/PrePackagedSourceAssetName.php +++ b/src/Platform/PrePackagedSourceAssetName.php @@ -23,19 +23,19 @@ public static function packageNames(Package $package): array return [ strtolower(sprintf( 'php_%s-%s-src.tgz', - $package->extensionName->name(), - $package->version, + $package->extensionName()->name(), + $package->version(), )), strtolower(sprintf( 'php_%s-%s-src.zip', - $package->extensionName->name(), - $package->version, + $package->extensionName()->name(), + $package->version(), )), // @todo remove this: strtolower(sprintf( '%s-%s.tgz', - $package->extensionName->name(), - $package->version, + $package->extensionName()->name(), + $package->version(), )), ]; } diff --git a/src/Platform/WindowsExtensionAssetName.php b/src/Platform/WindowsExtensionAssetName.php index f2383c7..9fe38f7 100644 --- a/src/Platform/WindowsExtensionAssetName.php +++ b/src/Platform/WindowsExtensionAssetName.php @@ -36,8 +36,8 @@ private static function assetNames(TargetPlatform $targetPlatform, Package $pack return [ strtolower(sprintf( 'php_%s-%s-%s-%s-%s-%s.%s', - $package->extensionName->name(), - $package->version, + $package->extensionName()->name(), + $package->version(), $targetPlatform->phpBinaryPath->majorMinorVersion(), $targetPlatform->threadSafety->asShort(), strtolower($targetPlatform->windowsCompiler->name), @@ -46,8 +46,8 @@ private static function assetNames(TargetPlatform $targetPlatform, Package $pack )), strtolower(sprintf( 'php_%s-%s-%s-%s-%s-%s.%s', - $package->extensionName->name(), - $package->version, + $package->extensionName()->name(), + $package->version(), $targetPlatform->phpBinaryPath->majorMinorVersion(), strtolower($targetPlatform->windowsCompiler->name), $targetPlatform->threadSafety->asShort(), diff --git a/test/integration/Building/UnixBuildTest.php b/test/integration/Building/UnixBuildTest.php index 976ca7a..1d6daa6 100644 --- a/test/integration/Building/UnixBuildTest.php +++ b/test/integration/Building/UnixBuildTest.php @@ -8,7 +8,6 @@ use Composer\Util\Platform; use Php\Pie\Building\ExtensionBinaryNotFound; use Php\Pie\Building\UnixBuild; -use Php\Pie\ConfigureOption; use Php\Pie\DependencyResolver\Package; use Php\Pie\Downloading\DownloadedPackage; use Php\Pie\ExtensionName; @@ -44,13 +43,6 @@ public function testUnixBuildCanBuildExtension(): void 'pie_test_ext', '0.1.0', null, - [ConfigureOption::fromComposerJsonDefinition(['name' => 'enable-pie_test_ext'])], - true, - true, - null, - null, - null, - 99, ), self::TEST_EXTENSION_PATH, ); @@ -100,13 +92,6 @@ public function testUnixBuildWillThrowExceptionWhenExpectedBinaryNameMismatches( 'pie_test_ext', '0.1.0', null, - [ConfigureOption::fromComposerJsonDefinition(['name' => 'enable-pie_test_ext'])], - true, - true, - null, - null, - null, - 99, ), self::TEST_EXTENSION_PATH, ); @@ -136,22 +121,14 @@ public function testUnixBuildCanBuildExtensionWithBuildPath(): void $output = new BufferedOutput(); + $composerPackage = $this->createMock(CompletePackage::class); + $composerPackage->method('getPrettyName')->willReturn('myvendor/pie_test_ext'); + $composerPackage->method('getPrettyVersion')->willReturn('0.1.0'); + $composerPackage->method('getType')->willReturn('php-ext'); + $composerPackage->method('getPhpExt')->willReturn(['build-path' => 'pie_test_ext']); + $downloadedPackage = DownloadedPackage::fromPackageAndExtractedPath( - new Package( - $this->createMock(CompletePackage::class), - ExtensionType::PhpModule, - ExtensionName::normaliseFromString('pie_test_ext'), - 'pie_test_ext', - '0.1.0', - null, - [ConfigureOption::fromComposerJsonDefinition(['name' => 'enable-pie_test_ext'])], - true, - true, - 'pie_test_ext', - null, - null, - 99, - ), + Package::fromComposerCompletePackage($composerPackage), dirname(self::TEST_EXTENSION_PATH), ); @@ -204,13 +181,6 @@ public function testCleanupDoesNotCleanWhenConfigureIsMissing(): void 'pie_test_ext', '0.1.0', null, - [], - true, - true, - null, - null, - null, - 99, ), self::TEST_EXTENSION_PATH, ); @@ -249,13 +219,6 @@ public function testVerboseOutputShowsCleanupMessages(): void 'pie_test_ext', '0.1.0', null, - [ConfigureOption::fromComposerJsonDefinition(['name' => 'enable-pie_test_ext'])], - true, - true, - null, - null, - null, - 99, ), self::TEST_EXTENSION_PATH, ); diff --git a/test/integration/DependencyResolver/ResolveDependencyWithComposerTest.php b/test/integration/DependencyResolver/ResolveDependencyWithComposerTest.php index 43d5799..c250fbf 100644 --- a/test/integration/DependencyResolver/ResolveDependencyWithComposerTest.php +++ b/test/integration/DependencyResolver/ResolveDependencyWithComposerTest.php @@ -98,8 +98,8 @@ public function testDependenciesAreResolvedToExpectedVersions( false, ); - self::assertSame($expectedVersion, $package->version); - self::assertNotNull($package->downloadUrl); - self::assertStringMatchesFormat($expectedDownloadUrl, $package->downloadUrl); + self::assertSame($expectedVersion, $package->version()); + self::assertNotNull($package->downloadUrl()); + self::assertStringMatchesFormat($expectedDownloadUrl, $package->downloadUrl()); } } diff --git a/test/integration/Downloading/GithubPackageReleaseAssetsTest.php b/test/integration/Downloading/GithubPackageReleaseAssetsTest.php index 664b1cb..4dd883c 100644 --- a/test/integration/Downloading/GithubPackageReleaseAssetsTest.php +++ b/test/integration/Downloading/GithubPackageReleaseAssetsTest.php @@ -54,13 +54,6 @@ public function testDeterminingReleaseAssetUrlForWindows(): void 'asgrim/example-pie-extension', '2.0.2', 'https://api.github.com/repos/asgrim/example-pie-extension/zipball/f9ed13ea95dada34c6cc5a052da258dbda059d27', - [], - true, - true, - null, - null, - null, - 99, ); $io = $this->createMock(IOInterface::class); diff --git a/test/integration/Installing/UnixInstallTest.php b/test/integration/Installing/UnixInstallTest.php index ca28ee0..1156eb6 100644 --- a/test/integration/Installing/UnixInstallTest.php +++ b/test/integration/Installing/UnixInstallTest.php @@ -7,7 +7,6 @@ use Composer\Package\CompletePackage; use Composer\Util\Platform; use Php\Pie\Building\UnixBuild; -use Php\Pie\ConfigureOption; use Php\Pie\DependencyResolver\Package; use Php\Pie\Downloading\DownloadedPackage; use Php\Pie\ExtensionName; @@ -89,13 +88,6 @@ public function testUnixInstallCanInstallExtension(string $phpConfig): void 'pie_test_ext', '0.1.0', null, - [ConfigureOption::fromComposerJsonDefinition(['name' => 'enable-pie_test_ext'])], - true, - true, - null, - null, - null, - 99, ), self::TEST_EXTENSION_PATH, ); diff --git a/test/integration/Installing/WindowsInstallTest.php b/test/integration/Installing/WindowsInstallTest.php index 4d04341..58cb065 100644 --- a/test/integration/Installing/WindowsInstallTest.php +++ b/test/integration/Installing/WindowsInstallTest.php @@ -53,13 +53,6 @@ public function testWindowsInstallCanInstallExtension(): void 'php/pie-test-ext', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ), self::TEST_EXTENSION_PATH, ); diff --git a/test/unit/Command/CommandHelperTest.php b/test/unit/Command/CommandHelperTest.php index f70eb93..73f80d7 100644 --- a/test/unit/Command/CommandHelperTest.php +++ b/test/unit/Command/CommandHelperTest.php @@ -14,11 +14,8 @@ use Composer\Util\Platform; use InvalidArgumentException; use Php\Pie\Command\CommandHelper; -use Php\Pie\ConfigureOption; use Php\Pie\DependencyResolver\Package; use Php\Pie\DependencyResolver\RequestedPackageAndVersion; -use Php\Pie\ExtensionName; -use Php\Pie\ExtensionType; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\RequiresOperatingSystemFamily; @@ -102,27 +99,21 @@ public function testBindingConfigurationOptionsFromPackage(): void public function testProcessingConfigureOptionsFromInput(): void { - $package = new Package( - $this->createMock(CompletePackage::class), - ExtensionType::PhpModule, - ExtensionName::normaliseFromString('lolz'), - 'foo/bar', - '1.0.0', - null, - [ - ConfigureOption::fromComposerJsonDefinition([ + $composerPackage = $this->createMock(CompletePackage::class); + $composerPackage->method('getPrettyName')->willReturn('foo/bar'); + $composerPackage->method('getPrettyVersion')->willReturn('1.0.0'); + $composerPackage->method('getType')->willReturn('php-ext'); + $composerPackage->method('getPhpExt')->willReturn([ + 'configure-options' => [ + [ 'name' => 'with-stuff', 'needs-value' => true, - ]), - ConfigureOption::fromComposerJsonDefinition(['name' => 'enable-thing']), + ], + ['name' => 'enable-thing'], ], - true, - true, - null, - null, - null, - 99, - ); + ]); + $package = Package::fromComposerCompletePackage($composerPackage); + $inputDefinition = new InputDefinition(); $inputDefinition->addOption(new InputOption('with-stuff', null, InputOption::VALUE_REQUIRED)); $inputDefinition->addOption(new InputOption('enable-thing', null, InputOption::VALUE_NONE)); diff --git a/test/unit/DependencyResolver/PackageTest.php b/test/unit/DependencyResolver/PackageTest.php index fc99924..47b3b10 100644 --- a/test/unit/DependencyResolver/PackageTest.php +++ b/test/unit/DependencyResolver/PackageTest.php @@ -23,12 +23,12 @@ public function testFromComposerCompletePackage(): void new CompletePackage('vendor/foo', '1.2.3.0', '1.2.3'), ); - self::assertSame('foo', $package->extensionName->name()); - self::assertSame('vendor/foo', $package->name); - self::assertSame('1.2.3', $package->version); + self::assertSame('foo', $package->extensionName()->name()); + self::assertSame('vendor/foo', $package->name()); + self::assertSame('1.2.3', $package->version()); self::assertSame('vendor/foo:1.2.3', $package->prettyNameAndVersion()); - self::assertNull($package->downloadUrl); - self::assertNull($package->buildPath); + self::assertNull($package->downloadUrl()); + self::assertNull($package->buildPath()); } public function testFromComposerCompletePackageWithExtensionName(): void @@ -38,11 +38,11 @@ public function testFromComposerCompletePackageWithExtensionName(): void $package = Package::fromComposerCompletePackage($composerCompletePackage); - self::assertSame('something_else', $package->extensionName->name()); - self::assertSame('vendor/foo', $package->name); - self::assertSame('1.2.3', $package->version); + self::assertSame('something_else', $package->extensionName()->name()); + self::assertSame('vendor/foo', $package->name()); + self::assertSame('1.2.3', $package->version()); self::assertSame('vendor/foo:1.2.3', $package->prettyNameAndVersion()); - self::assertNull($package->downloadUrl); + self::assertNull($package->downloadUrl()); } public function testFromComposerCompletePackageWithExcludedOsFamilies(): void @@ -52,11 +52,11 @@ public function testFromComposerCompletePackageWithExcludedOsFamilies(): void $package = Package::fromComposerCompletePackage($composerCompletePackage); - self::assertSame([OperatingSystemFamily::Windows, OperatingSystemFamily::Darwin], $package->incompatibleOsFamilies); - self::assertSame('vendor/foo', $package->name); - self::assertSame('1.2.3', $package->version); + self::assertSame([OperatingSystemFamily::Windows, OperatingSystemFamily::Darwin], $package->incompatibleOsFamilies()); + self::assertSame('vendor/foo', $package->name()); + self::assertSame('1.2.3', $package->version()); self::assertSame('vendor/foo:1.2.3', $package->prettyNameAndVersion()); - self::assertNull($package->downloadUrl); + self::assertNull($package->downloadUrl()); } public function testFromComposerCompletePackageWithOsFamilies(): void @@ -66,12 +66,12 @@ public function testFromComposerCompletePackageWithOsFamilies(): void $package = Package::fromComposerCompletePackage($composerCompletePackage); - self::assertEmpty($package->incompatibleOsFamilies); - self::assertSame([OperatingSystemFamily::Windows, OperatingSystemFamily::Darwin], $package->compatibleOsFamilies); - self::assertSame('vendor/foo', $package->name); - self::assertSame('1.2.3', $package->version); + self::assertEmpty($package->incompatibleOsFamilies()); + self::assertSame([OperatingSystemFamily::Windows, OperatingSystemFamily::Darwin], $package->compatibleOsFamilies()); + self::assertSame('vendor/foo', $package->name()); + self::assertSame('1.2.3', $package->version()); self::assertSame('vendor/foo:1.2.3', $package->prettyNameAndVersion()); - self::assertNull($package->downloadUrl); + self::assertNull($package->downloadUrl()); } public function testFromComposerCompletePackageWithBothOsFamiliesAndExcludedOsFamiliesThrows(): void @@ -134,13 +134,6 @@ public function testGithubOrgAndRepo(string $composerPackageName, string|null $d $composerPackageName, '1.2.3', $downloadUrl, - [], - true, - true, - null, - null, - null, - 99, ); self::assertSame($expectedGithubOrgAndRepo, $package->githubOrgAndRepository()); @@ -154,6 +147,6 @@ public function testFromComposerCompletePackageWithBuildPath(): void $package = Package::fromComposerCompletePackage($composerCompletePackage); self::assertSame('vendor/foo:1.2.3', $package->prettyNameAndVersion()); - self::assertSame('some/subdirectory/path/', $package->buildPath); + self::assertSame('some/subdirectory/path/', $package->buildPath()); } } diff --git a/test/unit/DependencyResolver/ResolveDependencyWithComposerTest.php b/test/unit/DependencyResolver/ResolveDependencyWithComposerTest.php index 6cdd9a4..9e9f828 100644 --- a/test/unit/DependencyResolver/ResolveDependencyWithComposerTest.php +++ b/test/unit/DependencyResolver/ResolveDependencyWithComposerTest.php @@ -66,8 +66,8 @@ public function testPackageThatCanBeResolved(): void $this->createMock(QuieterConsoleIO::class), ))($this->composer, $targetPlatform, new RequestedPackageAndVersion('asgrim/example-pie-extension', '^1.0'), false); - self::assertSame('asgrim/example-pie-extension', $package->name); - self::assertStringStartsWith('1.', $package->version); + self::assertSame('asgrim/example-pie-extension', $package->name()); + self::assertStringStartsWith('1.', $package->version()); } /** @@ -159,8 +159,8 @@ public function testUnresolvedPackageCanBeInstalledWithForceOption(array $platfo true, ); - self::assertSame('asgrim/example-pie-extension', $package->name); - self::assertStringStartsWith('1.', $package->version); + self::assertSame('asgrim/example-pie-extension', $package->name()); + self::assertStringStartsWith('1.', $package->version()); } public function testZtsOnlyPackageCannotBeInstalledOnNtsSystem(): void diff --git a/test/unit/Downloading/DownloadedPackageTest.php b/test/unit/Downloading/DownloadedPackageTest.php index c4edf0b..409abf6 100644 --- a/test/unit/Downloading/DownloadedPackageTest.php +++ b/test/unit/Downloading/DownloadedPackageTest.php @@ -29,13 +29,6 @@ public function testFromPackageAndExtractedPath(): void 'foo/bar', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ); $extractedSourcePath = uniqid('/path/to/downloaded/package', true); @@ -48,21 +41,13 @@ public function testFromPackageAndExtractedPath(): void public function testFromPackageAndExtractedPathWithBuildPath(): void { - $package = new Package( - $this->createMock(CompletePackage::class), - ExtensionType::PhpModule, - ExtensionName::normaliseFromString('foo'), - 'foo/bar', - '1.2.3', - null, - [], - true, - true, - 'Downloading', - null, - null, - 99, - ); + $composerPackage = $this->createMock(CompletePackage::class); + $composerPackage->method('getPrettyName')->willReturn('foo/bar'); + $composerPackage->method('getPrettyVersion')->willReturn('1.2.3'); + $composerPackage->method('getType')->willReturn('php-ext'); + $composerPackage->method('getPhpExt')->willReturn(['build-path' => 'Downloading']); + + $package = Package::fromComposerCompletePackage($composerPackage); $extractedSourcePath = realpath(__DIR__ . '/../'); diff --git a/test/unit/Downloading/Exception/CouldNotFindReleaseAssetTest.php b/test/unit/Downloading/Exception/CouldNotFindReleaseAssetTest.php index e25bcec..86718a8 100644 --- a/test/unit/Downloading/Exception/CouldNotFindReleaseAssetTest.php +++ b/test/unit/Downloading/Exception/CouldNotFindReleaseAssetTest.php @@ -30,13 +30,6 @@ public function testForPackage(): void 'foo/bar', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ); $exception = CouldNotFindReleaseAsset::forPackage($package, ['something.zip', 'something2.zip']); @@ -53,13 +46,6 @@ public function testForPackageWithMissingTag(): void 'foo/bar', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ); $exception = CouldNotFindReleaseAsset::forPackageWithMissingTag($package); diff --git a/test/unit/Downloading/GithubPackageReleaseAssetsTest.php b/test/unit/Downloading/GithubPackageReleaseAssetsTest.php index a6cf7cf..58b99b1 100644 --- a/test/unit/Downloading/GithubPackageReleaseAssetsTest.php +++ b/test/unit/Downloading/GithubPackageReleaseAssetsTest.php @@ -79,13 +79,6 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrl(): void 'asgrim/example-pie-extension', '1.2.3', 'https://test-uri/' . uniqid('downloadUrl', true), - [], - true, - true, - null, - null, - null, - 99, ); $releaseAssets = new GithubPackageReleaseAssets('https://test-github-api-base-url.thephp.foundation'); @@ -154,13 +147,6 @@ public function testUrlIsReturnedWhenFindingWindowsDownloadUrlWithCompilerAndThr 'asgrim/example-pie-extension', '1.2.3', 'https://test-uri/' . uniqid('downloadUrl', true), - [], - true, - true, - null, - null, - null, - 99, ); $releaseAssets = new GithubPackageReleaseAssets('https://test-github-api-base-url.thephp.foundation'); @@ -210,13 +196,6 @@ public function testFindWindowsDownloadUrlForPackageThrowsExceptionWhenAssetNotF 'asgrim/example-pie-extension', '1.2.3', 'https://test-uri/' . uniqid('downloadUrl', true), - [], - true, - true, - null, - null, - null, - 99, ); $releaseAssets = new GithubPackageReleaseAssets('https://test-github-api-base-url.thephp.foundation'); diff --git a/test/unit/Installing/Ini/AddExtensionToTheIniFileTest.php b/test/unit/Installing/Ini/AddExtensionToTheIniFileTest.php index 3f6f3f2..66820d7 100644 --- a/test/unit/Installing/Ini/AddExtensionToTheIniFileTest.php +++ b/test/unit/Installing/Ini/AddExtensionToTheIniFileTest.php @@ -63,13 +63,6 @@ public function testReturnsFalseWhenFileIsNotWritable(): void 'foo/bar', '1.0.0', null, - [], - true, - true, - null, - null, - null, - 99, ), $this->mockPhpBinary, $this->output, @@ -107,13 +100,6 @@ public function testReturnsFalseWhenExistingIniCouldNotBeRead(): void 'foo/bar', '1.0.0', null, - [], - true, - true, - null, - null, - null, - 99, ), $this->mockPhpBinary, $this->output, @@ -161,13 +147,6 @@ public function testReturnsFalseWhenExtensionWasAddedButPhpRuntimeDidNotLoadExte 'foo/bar', '1.0.0', null, - [], - true, - true, - null, - null, - null, - 99, ), $this->mockPhpBinary, $this->output, @@ -205,13 +184,6 @@ public function testReturnsTrueWhenExtensionAdded(): void 'foo/bar', '1.0.0', null, - [], - true, - true, - null, - null, - null, - 99, ), $this->mockPhpBinary, $this->output, @@ -221,7 +193,7 @@ public function testReturnsTrueWhenExtensionAdded(): void $iniContent = file_get_contents($iniFile); self::assertSame( PHP_EOL . '; PIE automatically added this to enable the foo/bar extension' . PHP_EOL - . '; priority=99' . PHP_EOL + . '; priority=80' . PHP_EOL . 'extension=foobar' . PHP_EOL, $iniContent, ); @@ -255,13 +227,6 @@ public function testReturnsTrueWhenExtensionAddedWithAdditionalStep(): void 'foo/bar', '1.0.0', null, - [], - true, - true, - null, - null, - null, - 99, ), $this->mockPhpBinary, $this->output, @@ -277,7 +242,7 @@ static function () use (&$additionalStepInvoked): bool { $iniContent = file_get_contents($iniFile); self::assertSame( PHP_EOL . '; PIE automatically added this to enable the foo/bar extension' . PHP_EOL - . '; priority=99' . PHP_EOL + . '; priority=80' . PHP_EOL . 'extension=foobar' . PHP_EOL, $iniContent, ); diff --git a/test/unit/Installing/Ini/CheckAndAddExtensionToIniIfNeededTest.php b/test/unit/Installing/Ini/CheckAndAddExtensionToIniIfNeededTest.php index ac31ecc..b7ae9a8 100644 --- a/test/unit/Installing/Ini/CheckAndAddExtensionToIniIfNeededTest.php +++ b/test/unit/Installing/Ini/CheckAndAddExtensionToIniIfNeededTest.php @@ -72,13 +72,6 @@ public function setUp(): void 'foo/bar', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 66, ), '/path/to/extracted/source', ); @@ -122,16 +115,16 @@ public function testExtensionIsAlreadyEnabledButExtensionDoesNotLoad(): void $this->isExtensionAlreadyInTheIniFile ->expects(self::once()) ->method('__invoke') - ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName) + ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName()) ->willReturn(true); $this->mockPhpBinary ->expects(self::once()) ->method('assertExtensionIsLoadedInRuntime') - ->with($this->downloadedPackage->package->extensionName, $this->output) + ->with($this->downloadedPackage->package->extensionName(), $this->output) ->willThrowException(ExtensionIsNotLoaded::fromExpectedExtension( $this->mockPhpBinary, - $this->downloadedPackage->package->extensionName, + $this->downloadedPackage->package->extensionName(), )); $this->addExtensionToTheIniFile @@ -162,13 +155,13 @@ public function testExtensionIsAlreadyEnabledAndExtensionLoaded(): void $this->isExtensionAlreadyInTheIniFile ->expects(self::once()) ->method('__invoke') - ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName) + ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName()) ->willReturn(true); $this->mockPhpBinary ->expects(self::once()) ->method('assertExtensionIsLoadedInRuntime') - ->with($this->downloadedPackage->package->extensionName, $this->output); + ->with($this->downloadedPackage->package->extensionName(), $this->output); $this->addExtensionToTheIniFile ->expects(self::never()) @@ -194,13 +187,13 @@ public function testExtensionIsAlreadyEnabledWithAdditionalStepAndExtensionLoade $this->isExtensionAlreadyInTheIniFile ->expects(self::once()) ->method('__invoke') - ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName) + ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName()) ->willReturn(true); $this->mockPhpBinary ->expects(self::once()) ->method('assertExtensionIsLoadedInRuntime') - ->with($this->downloadedPackage->package->extensionName, $this->output); + ->with($this->downloadedPackage->package->extensionName(), $this->output); $this->addExtensionToTheIniFile ->expects(self::never()) @@ -233,7 +226,7 @@ public function testExtensionIsNotYetAdded(): void $this->isExtensionAlreadyInTheIniFile ->expects(self::once()) ->method('__invoke') - ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName) + ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName()) ->willReturn(false); $this->mockPhpBinary @@ -265,7 +258,7 @@ public function testExtensionIsNotYetAddedButFailsToBeAdded(): void $this->isExtensionAlreadyInTheIniFile ->expects(self::once()) ->method('__invoke') - ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName) + ->with(self::INI_FILE, $this->downloadedPackage->package->extensionName()) ->willReturn(false); $this->mockPhpBinary diff --git a/test/unit/Installing/Ini/DockerPhpExtEnableTest.php b/test/unit/Installing/Ini/DockerPhpExtEnableTest.php index 410190a..ab407af 100644 --- a/test/unit/Installing/Ini/DockerPhpExtEnableTest.php +++ b/test/unit/Installing/Ini/DockerPhpExtEnableTest.php @@ -70,13 +70,6 @@ public function setUp(): void 'foo/bar', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ), '/path/to/extracted/source', ); @@ -122,7 +115,7 @@ public function testReturnsTrueWhenDockerPhpExtEnableSuccessfullyEnablesExtensio $this->mockPhpBinary ->expects(self::once()) ->method('assertExtensionIsLoadedInRuntime') - ->with($this->downloadedPackage->package->extensionName, $this->output); + ->with($this->downloadedPackage->package->extensionName(), $this->output); self::assertTrue( (new DockerPhpExtEnable(self::GOOD_DOCKER_PHP_EXT_ENABLE)) @@ -157,10 +150,10 @@ public function testReturnsFalseWhenDockerPhpExtEnableFailsToAssertExtensionWasE $this->mockPhpBinary ->expects(self::once()) ->method('assertExtensionIsLoadedInRuntime') - ->with($this->downloadedPackage->package->extensionName, $this->output) + ->with($this->downloadedPackage->package->extensionName(), $this->output) ->willThrowException(ExtensionIsNotLoaded::fromExpectedExtension( $this->mockPhpBinary, - $this->downloadedPackage->package->extensionName, + $this->downloadedPackage->package->extensionName(), )); self::assertFalse( diff --git a/test/unit/Installing/Ini/OndrejPhpenmodTest.php b/test/unit/Installing/Ini/OndrejPhpenmodTest.php index 4fcecb4..527fe42 100644 --- a/test/unit/Installing/Ini/OndrejPhpenmodTest.php +++ b/test/unit/Installing/Ini/OndrejPhpenmodTest.php @@ -83,13 +83,6 @@ public function setUp(): void 'foo/bar', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ), '/path/to/extracted/source', ); diff --git a/test/unit/Installing/Ini/PickBestSetupIniApproachTest.php b/test/unit/Installing/Ini/PickBestSetupIniApproachTest.php index 07d4bd6..1c35c02 100644 --- a/test/unit/Installing/Ini/PickBestSetupIniApproachTest.php +++ b/test/unit/Installing/Ini/PickBestSetupIniApproachTest.php @@ -97,13 +97,6 @@ public function testVerboseMessageIsEmittedSettingUpWithoutAnyApproaches(): void 'test-vendor/test-package', '1.2.3', 'https://test-uri/', - [], - true, - true, - null, - null, - null, - 99, ), '/path/to/extracted/source', ), @@ -139,13 +132,6 @@ public function testWorkingApproachIsUsed(): void 'test-vendor/test-package', '1.2.3', 'https://test-uri/', - [], - true, - true, - null, - null, - null, - 99, ), '/path/to/extracted/source', ), @@ -181,13 +167,6 @@ public function testSetupFailsWhenNoApproachesWork(): void 'test-vendor/test-package', '1.2.3', 'https://test-uri/', - [], - true, - true, - null, - null, - null, - 99, ), '/path/to/extracted/source', ), diff --git a/test/unit/Installing/Ini/PreCheckExtensionAlreadyLoadedTest.php b/test/unit/Installing/Ini/PreCheckExtensionAlreadyLoadedTest.php index de1795f..6435e6b 100644 --- a/test/unit/Installing/Ini/PreCheckExtensionAlreadyLoadedTest.php +++ b/test/unit/Installing/Ini/PreCheckExtensionAlreadyLoadedTest.php @@ -65,13 +65,6 @@ public function setUp(): void 'foo/bar', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ), '/path/to/extracted/source', ); @@ -93,7 +86,7 @@ public function testSetupReturnsTrueWhenExtAlreadyRuntimeLoaded(): void $this->mockPhpBinary ->expects(self::once()) ->method('assertExtensionIsLoadedInRuntime') - ->with($this->downloadedPackage->package->extensionName, $this->output); + ->with($this->downloadedPackage->package->extensionName(), $this->output); self::assertTrue($this->preCheckExtensionAlreadyLoaded->setup( $this->targetPlatform, @@ -108,10 +101,10 @@ public function testSetupReturnsFalseWhenExtIsNotRuntimeLoaded(): void $this->mockPhpBinary ->expects(self::once()) ->method('assertExtensionIsLoadedInRuntime') - ->with($this->downloadedPackage->package->extensionName, $this->output) + ->with($this->downloadedPackage->package->extensionName(), $this->output) ->willThrowException(ExtensionIsNotLoaded::fromExpectedExtension( $this->mockPhpBinary, - $this->downloadedPackage->package->extensionName, + $this->downloadedPackage->package->extensionName(), )); self::assertFalse($this->preCheckExtensionAlreadyLoaded->setup( diff --git a/test/unit/Installing/Ini/StandardAdditionalPhpIniDirectoryTest.php b/test/unit/Installing/Ini/StandardAdditionalPhpIniDirectoryTest.php index 83f5b9e..45a073d 100644 --- a/test/unit/Installing/Ini/StandardAdditionalPhpIniDirectoryTest.php +++ b/test/unit/Installing/Ini/StandardAdditionalPhpIniDirectoryTest.php @@ -77,13 +77,6 @@ public function setUp(): void 'foo/bar', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ), '/path/to/extracted/source', ); @@ -163,7 +156,7 @@ public function testReturnsTrueWhenCheckAndAddExtensionIsInvoked(): void unlink($additionalPhpIniDirectory); mkdir($additionalPhpIniDirectory, recursive: true); - $expectedIniFile = $additionalPhpIniDirectory . DIRECTORY_SEPARATOR . '99-foobar.ini'; + $expectedIniFile = $additionalPhpIniDirectory . DIRECTORY_SEPARATOR . '80-foobar.ini'; $this->mockPhpBinary ->expects(self::once()) @@ -199,7 +192,7 @@ public function testReturnsFalseAndRemovesPieCreatedIniFileWhenCheckAndAddExtens unlink($additionalPhpIniDirectory); mkdir($additionalPhpIniDirectory, recursive: true); - $expectedIniFile = $additionalPhpIniDirectory . DIRECTORY_SEPARATOR . '99-foobar.ini'; + $expectedIniFile = $additionalPhpIniDirectory . DIRECTORY_SEPARATOR . '80-foobar.ini'; $this->mockPhpBinary ->expects(self::once()) @@ -234,7 +227,7 @@ public function testReturnsFalseAndLeavesNonPieCreatedIniFileWhenCheckAndAddExte unlink($additionalPhpIniDirectory); mkdir($additionalPhpIniDirectory, recursive: true); - $expectedIniFile = $additionalPhpIniDirectory . DIRECTORY_SEPARATOR . '99-foobar.ini'; + $expectedIniFile = $additionalPhpIniDirectory . DIRECTORY_SEPARATOR . '80-foobar.ini'; touch($expectedIniFile); $this->mockPhpBinary diff --git a/test/unit/Installing/Ini/StandardSinglePhpIniTest.php b/test/unit/Installing/Ini/StandardSinglePhpIniTest.php index 34b19da..21f4771 100644 --- a/test/unit/Installing/Ini/StandardSinglePhpIniTest.php +++ b/test/unit/Installing/Ini/StandardSinglePhpIniTest.php @@ -70,13 +70,6 @@ public function setUp(): void 'foo/bar', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ), '/path/to/extracted/source', ); diff --git a/test/unit/Platform/WindowsExtensionAssetNameTest.php b/test/unit/Platform/WindowsExtensionAssetNameTest.php index 75e72a6..77a7776 100644 --- a/test/unit/Platform/WindowsExtensionAssetNameTest.php +++ b/test/unit/Platform/WindowsExtensionAssetNameTest.php @@ -49,13 +49,6 @@ public function setUp(): void 'phpf/foo', '1.2.3', null, - [], - true, - true, - null, - null, - null, - 99, ); } From f515b7300caa95d3d270279c071303a31b847658 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Mon, 3 Feb 2025 21:59:25 +0000 Subject: [PATCH 05/14] Add {version} template to download package path --- docs/extension-maintainers.md | 6 ++++++ src/Downloading/DownloadedPackage.php | 6 +++++- test/assets/package-1.2.3/.gitkeep | 0 .../unit/Downloading/DownloadedPackageTest.php | 18 ++++++++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 test/assets/package-1.2.3/.gitkeep diff --git a/docs/extension-maintainers.md b/docs/extension-maintainers.md index 610728b..5a25c4c 100644 --- a/docs/extension-maintainers.md +++ b/docs/extension-maintainers.md @@ -160,6 +160,12 @@ should specify this path in `build-path`, for example: } ``` +The `build-path` may contain some templated values which are replaced: + + * `{version}` to be replaced with the package version. For example a package + with version 1.2.3 with a `build-path` of `myext-{version}` the actual build + path would become `myext-{version}`. + ### Extension dependencies Extension authors may define some dependencies in `require`, but practically, diff --git a/src/Downloading/DownloadedPackage.php b/src/Downloading/DownloadedPackage.php index ba57c4b..1ef0b25 100644 --- a/src/Downloading/DownloadedPackage.php +++ b/src/Downloading/DownloadedPackage.php @@ -27,7 +27,11 @@ private function __construct( public static function fromPackageAndExtractedPath(Package $package, string $extractedSourcePath): self { if ($package->buildPath() !== null) { - $extractedSourcePathWithBuildPath = realpath($extractedSourcePath . DIRECTORY_SEPARATOR . $package->buildPath()); + $extractedSourcePathWithBuildPath = realpath( + $extractedSourcePath + . DIRECTORY_SEPARATOR + . str_replace("{version}", $package->version(), $package->buildPath()) + ); if (is_string($extractedSourcePathWithBuildPath)) { $extractedSourcePath = $extractedSourcePathWithBuildPath; diff --git a/test/assets/package-1.2.3/.gitkeep b/test/assets/package-1.2.3/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/unit/Downloading/DownloadedPackageTest.php b/test/unit/Downloading/DownloadedPackageTest.php index 409abf6..dcdc5dd 100644 --- a/test/unit/Downloading/DownloadedPackageTest.php +++ b/test/unit/Downloading/DownloadedPackageTest.php @@ -56,4 +56,22 @@ public function testFromPackageAndExtractedPathWithBuildPath(): void self::assertSame($extractedSourcePath . DIRECTORY_SEPARATOR . 'Downloading', $downloadedPackage->extractedSourcePath); self::assertSame($package, $downloadedPackage->package); } + + public function testFromPackageAndExtractedPathWithBuildPathWithVersionTemplate(): void + { + $composerPackage = $this->createMock(CompletePackage::class); + $composerPackage->method('getPrettyName')->willReturn('foo/bar'); + $composerPackage->method('getPrettyVersion')->willReturn('1.2.3'); + $composerPackage->method('getType')->willReturn('php-ext'); + $composerPackage->method('getPhpExt')->willReturn(['build-path' => 'package-{version}']); + + $package = Package::fromComposerCompletePackage($composerPackage); + + $extractedSourcePath = realpath(__DIR__ . '/../../assets'); + + $downloadedPackage = DownloadedPackage::fromPackageAndExtractedPath($package, $extractedSourcePath); + + self::assertSame($extractedSourcePath . DIRECTORY_SEPARATOR . 'package-1.2.3', $downloadedPackage->extractedSourcePath); + self::assertSame($package, $downloadedPackage->package); + } } From 702b71dae5a65152e530217c04bb8c8d518f9d7a Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Mon, 3 Feb 2025 22:08:39 +0000 Subject: [PATCH 06/14] Add handling for override-download-url-method configuration --- src/DependencyResolver/Package.php | 26 ++++++++++++++----- src/Downloading/DownloadUrlMethod.php | 10 +++---- ...OverrideDownloadUrlInstallListenerTest.php | 6 ++++- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/DependencyResolver/Package.php b/src/DependencyResolver/Package.php index 94519ff..03263ee 100644 --- a/src/DependencyResolver/Package.php +++ b/src/DependencyResolver/Package.php @@ -7,6 +7,7 @@ use Composer\Package\CompletePackageInterface; use InvalidArgumentException; use Php\Pie\ConfigureOption; +use Php\Pie\Downloading\DownloadUrlMethod; use Php\Pie\ExtensionName; use Php\Pie\ExtensionType; use Php\Pie\Platform\OperatingSystemFamily; @@ -41,6 +42,7 @@ final class Package private array|null $incompatibleOsFamilies; private bool $supportZts; private bool $supportNts; + private DownloadUrlMethod|null $overrideDownloadUrlMethod; public function __construct( private readonly CompletePackageInterface $composerPackage, @@ -50,13 +52,14 @@ public function __construct( private readonly string $version, private readonly string|null $downloadUrl, ) { - $this->configureOptions = []; - $this->supportZts = true; - $this->supportNts = true; - $this->buildPath = null; - $this->compatibleOsFamilies = null; - $this->incompatibleOsFamilies = null; - $this->priority = 80; + $this->configureOptions = []; + $this->supportZts = true; + $this->supportNts = true; + $this->buildPath = null; + $this->compatibleOsFamilies = null; + $this->incompatibleOsFamilies = null; + $this->priority = 80; + $this->overrideDownloadUrlMethod = null; } public static function fromComposerCompletePackage(CompletePackageInterface $completePackage): self @@ -95,6 +98,10 @@ public static function fromComposerCompletePackage(CompletePackageInterface $com $package->priority = $phpExtOptions['priority'] ?? 80; + if (array_key_exists('override-download-url-method', $phpExtOptions)) { + $package->overrideDownloadUrlMethod = DownloadUrlMethod::tryFrom($phpExtOptions['override-download-url-method']); + } + return $package; } @@ -214,4 +221,9 @@ public function supportNts(): bool { return $this->supportNts; } + + public function overrideDownloadUrlMethod(): DownloadUrlMethod|null + { + return $this->overrideDownloadUrlMethod; + } } diff --git a/src/Downloading/DownloadUrlMethod.php b/src/Downloading/DownloadUrlMethod.php index 2b27085..ae1eadb 100644 --- a/src/Downloading/DownloadUrlMethod.php +++ b/src/Downloading/DownloadUrlMethod.php @@ -10,11 +10,11 @@ use Php\Pie\Platform\TargetPlatform; use Php\Pie\Platform\WindowsExtensionAssetName; -enum DownloadUrlMethod +enum DownloadUrlMethod: string { - case ComposerDefaultDownload; - case WindowsBinaryDownload; - case PrePackagedSourceDownload; + case ComposerDefaultDownload = 'composer-default'; + case WindowsBinaryDownload = 'windows-binary'; + case PrePackagedSourceDownload = 'pre-packaged-source'; /** @return non-empty-list|null */ public function possibleAssetNames(Package $package, TargetPlatform $targetPlatform): array|null @@ -41,7 +41,7 @@ public static function fromPackage(Package $package, TargetPlatform $targetPlatf * external dependencies in Git submodules that otherwise aren't * included in GitHub/Gitlab/etc "dist" downloads */ - if (false) { // @todo check $package `php-ext` + if ($package->overrideDownloadUrlMethod() === DownloadUrlMethod::PrePackagedSourceDownload) { return self::PrePackagedSourceDownload; } diff --git a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php index 4e215bd..97de007 100644 --- a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php +++ b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php @@ -15,6 +15,7 @@ use Php\Pie\ComposerIntegration\PieComposerRequest; use Php\Pie\ComposerIntegration\PieOperation; use Php\Pie\DependencyResolver\RequestedPackageAndVersion; +use Php\Pie\Downloading\DownloadUrlMethod; use Php\Pie\Downloading\PackageReleaseAssets; use Php\Pie\Platform\Architecture; use Php\Pie\Platform\OperatingSystem; @@ -214,7 +215,10 @@ public function testDistUrlIsUpdatedForPrePackagedTgzSource(): void $composerPackage = new CompletePackage('foo/bar', '1.2.3.0', '1.2.3'); $composerPackage->setDistType('zip'); $composerPackage->setDistUrl('https://example.com/git-archive-zip-url'); - $composerPackage->setPhpExt(['extension-name' => 'mongodb']); + $composerPackage->setPhpExt([ + 'extension-name' => 'foobar', + 'override-download-url-method' => 'pre-packaged-source', + ]); /** * @psalm-suppress InternalClass From f0c5b662c169d51ee4809449f9b60b8d156f40bc Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Mon, 3 Feb 2025 22:15:49 +0000 Subject: [PATCH 07/14] Move php-ext schema from pie-design repo --- resources/composer-json-php-ext-schema.json | 106 ++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 resources/composer-json-php-ext-schema.json diff --git a/resources/composer-json-php-ext-schema.json b/resources/composer-json-php-ext-schema.json new file mode 100644 index 0000000..b41199d --- /dev/null +++ b/resources/composer-json-php-ext-schema.json @@ -0,0 +1,106 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://raw.githubusercontent.com/php/pie/main/composer-json-php-ext-schema.json", + "title": "composer.json php-ext schema", + "description": "Schema for the proposed php-ext section in composer.json that the new PECL will use to build packages", + "type": "object", + "properties": { + "php-ext": { + "type": "object", + "description": "Settings for PHP extension packages.", + "properties": { + "extension-name": { + "type": "string", + "description": "If specified, this will be used as the name of the extension, where needed by tooling. If this is not specified, the extension name will be derived from the Composer package name (e.g. `vendor/name` would become `ext-name`). The extension name may be specified with or without the `ext-` prefix, and tools that use this must normalise this appropriately.", + "example": "ext-xdebug" + }, + "priority": { + "type": "integer", + "description": "This is used to add a prefix to the INI file, e.g. `90-xdebug.ini` which affects the loading order. The priority is a number in the range 10-99 inclusive, with 10 being the highest priority (i.e. will be processed first), and 99 being the lowest priority (i.e. will be processed last). There are two digits so that the files sort correctly on any platform, whether the sorting is natural or not.", + "minimum": 10, + "maximum": 99, + "example": 80, + "default": 80 + }, + "support-zts": { + "type": "boolean", + "description": "Does this package support Zend Thread Safety", + "example": false, + "default": true + }, + "support-nts": { + "type": "boolean", + "description": "Does this package support non-Thread Safe mode", + "example": false, + "default": true + }, + "build-path": { + "type": ["string", "null"], + "description": "If specified, this is the subdirectory that will be used to build the extension instead of the root of the project.", + "example": "my-extension-source", + "default": null + }, + "override-download-url-method": { + "type": "string", + "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.", + "enum": ["composer-default", "override-download-url-method"], + "example": "composer-default" + }, + "os-families": { + "type": "array", + "minItems": 1, + "description": "An array of OS families to mark as compatible with the extension. Specifying this property will mean this package is not installable with PIE on any OS family not listed here. Must not be specified alongside os-families-exclude.", + "items": { + "type": "string", + "enum": ["windows", "bsd", "darwin", "solaris", "linux", "unknown"], + "description": "The name of the OS family to mark as compatible." + } + }, + "os-families-exclude": { + "type": "array", + "minItems": 1, + "description": "An array of OS families to mark as incompatible with the extension. Specifying this property will mean this package is installable on any OS family except those listed here. Must not be specified alongside os-families.", + "items": { + "type": "string", + "enum": ["windows", "bsd", "darwin", "solaris", "linux", "unknown"], + "description": "The name of the OS family to exclude." + } + }, + "configure-options": { + "type": "array", + "description": "These configure options make up the flags that can be passed to ./configure when installing the extension.", + "items": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string", + "description": "The name of the flag, this would typically be prefixed with `--`, for example, the value 'the-flag' would be passed as `./configure --the-flag`.", + "example": "without-xdebug-compression", + "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]*$" + }, + "needs-value": { + "type": "boolean", + "description": "If this is set to true, the flag needs a value (e.g. --with-somelib=), otherwise it is a flag without a value (e.g. --enable-some-feature).", + "example": false, + "default": false + }, + "description": { + "type": "string", + "description": "The description of what the flag does or means.", + "example": "Disable compression through zlib" + } + } + } + } + }, + "allOf": [ + { + "not": { + "required": ["os-families", "os-families-exclude"] + } + } + ] + } + } +} From 2d4779ffe41d7b17b153f29d48e0f09227ffb81a Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Tue, 4 Feb 2025 21:08:03 +0000 Subject: [PATCH 08/14] CS and SA fixes --- src/DependencyResolver/Package.php | 7 ++++++- src/Downloading/DownloadedPackage.php | 3 ++- .../Listeners/OverrideDownloadUrlInstallListenerTest.php | 1 - 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/DependencyResolver/Package.php b/src/DependencyResolver/Package.php index 03263ee..331b14c 100644 --- a/src/DependencyResolver/Package.php +++ b/src/DependencyResolver/Package.php @@ -18,6 +18,7 @@ use function array_slice; use function explode; use function implode; +use function is_string; use function parse_url; use function str_contains; use function str_starts_with; @@ -98,7 +99,11 @@ public static function fromComposerCompletePackage(CompletePackageInterface $com $package->priority = $phpExtOptions['priority'] ?? 80; - if (array_key_exists('override-download-url-method', $phpExtOptions)) { + if ( + $phpExtOptions !== null + && array_key_exists('override-download-url-method', $phpExtOptions) + && is_string($phpExtOptions['override-download-url-method']) + ) { $package->overrideDownloadUrlMethod = DownloadUrlMethod::tryFrom($phpExtOptions['override-download-url-method']); } diff --git a/src/Downloading/DownloadedPackage.php b/src/Downloading/DownloadedPackage.php index 1ef0b25..7836d3d 100644 --- a/src/Downloading/DownloadedPackage.php +++ b/src/Downloading/DownloadedPackage.php @@ -8,6 +8,7 @@ use function is_string; use function realpath; +use function str_replace; use const DIRECTORY_SEPARATOR; @@ -30,7 +31,7 @@ public static function fromPackageAndExtractedPath(Package $package, string $ext $extractedSourcePathWithBuildPath = realpath( $extractedSourcePath . DIRECTORY_SEPARATOR - . str_replace("{version}", $package->version(), $package->buildPath()) + . str_replace('{version}', $package->version(), $package->buildPath()), ); if (is_string($extractedSourcePathWithBuildPath)) { diff --git a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php index 97de007..2ca8671 100644 --- a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php +++ b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php @@ -15,7 +15,6 @@ use Php\Pie\ComposerIntegration\PieComposerRequest; use Php\Pie\ComposerIntegration\PieOperation; use Php\Pie\DependencyResolver\RequestedPackageAndVersion; -use Php\Pie\Downloading\DownloadUrlMethod; use Php\Pie\Downloading\PackageReleaseAssets; use Php\Pie\Platform\Architecture; use Php\Pie\Platform\OperatingSystem; From 7f93eb3491020a14d35be6bcf2df09a491f7f448 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Tue, 4 Feb 2025 21:28:20 +0000 Subject: [PATCH 09/14] Documentation for override-download-url-method --- docs/extension-maintainers.md | 14 ++++++++++++++ resources/composer-json-php-ext-schema.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/extension-maintainers.md b/docs/extension-maintainers.md index 5a25c4c..4bbfd43 100644 --- a/docs/extension-maintainers.md +++ b/docs/extension-maintainers.md @@ -166,6 +166,20 @@ The `build-path` may contain some templated values which are replaced: with version 1.2.3 with a `build-path` of `myext-{version}` the actual build path would become `myext-{version}`. +#### `override-download-url-method` + +The `override-download-url-method` directive allows extension maintainers to +change the behaviour of downloading the source package. + + * Setting this to `composer-default`, which is the default value if not + specified, will use the default behaviour implemented by Composer, which is + to use the standard ZIP archive from the GitHub API (or other source control + system). + * Using `pre-packaged-source` will locate a source code package in the release + assets list based matching one of the following naming conventions: + * `php_{ExtensionName}-{Version}-src.tgz` (e.g. `php_myext-1.20.1-src.tgz`) + * `php_{ExtensionName}-{Version}-src.zip` (e.g. `php_myext-1.20.1-src.zip`) + ### Extension dependencies Extension authors may define some dependencies in `require`, but practically, diff --git a/resources/composer-json-php-ext-schema.json b/resources/composer-json-php-ext-schema.json index b41199d..22ca370 100644 --- a/resources/composer-json-php-ext-schema.json +++ b/resources/composer-json-php-ext-schema.json @@ -43,7 +43,7 @@ "override-download-url-method": { "type": "string", "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.", - "enum": ["composer-default", "override-download-url-method"], + "enum": ["composer-default", "pre-packaged-source"], "example": "composer-default" }, "os-families": { From 504aa88a4b3c818904716eb4d62a904024ac9657 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Wed, 5 Feb 2025 09:46:30 +0000 Subject: [PATCH 10/14] Update docs with actual expected build path Co-authored-by: Christophe Coevoet --- docs/extension-maintainers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extension-maintainers.md b/docs/extension-maintainers.md index 4bbfd43..bd70497 100644 --- a/docs/extension-maintainers.md +++ b/docs/extension-maintainers.md @@ -164,7 +164,7 @@ The `build-path` may contain some templated values which are replaced: * `{version}` to be replaced with the package version. For example a package with version 1.2.3 with a `build-path` of `myext-{version}` the actual build - path would become `myext-{version}`. + path would become `myext-1.2.3`. #### `override-download-url-method` From 36da7b22442ec445959115581f693ed49ff8fa2b Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Wed, 5 Feb 2025 10:26:17 +0000 Subject: [PATCH 11/14] Update to remove superfluous override- prefix and pull latest composer/composer --- composer.json | 2 +- composer.lock | 21 +++++++------ docs/extension-maintainers.md | 4 +-- resources/composer-json-php-ext-schema.json | 2 +- src/DependencyResolver/Package.php | 31 ++++++++----------- src/Downloading/DownloadUrlMethod.php | 2 +- ...OverrideDownloadUrlInstallListenerTest.php | 2 +- 7 files changed, 31 insertions(+), 33 deletions(-) diff --git a/composer.json b/composer.json index ba043ff..037a249 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ ], "require": { "php": "8.1.*||8.2.*||8.3.*||8.4.*", - "composer/composer": "^2.8.5", + "composer/composer": "dev-main", "composer/pcre": "^3.3.2", "composer/semver": "^3.4.3", "fidry/cpu-core-counter": "^1.2", diff --git a/composer.lock b/composer.lock index c6ecdfb..fa31873 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "819abdc1a00f374dc389cde52c096979", + "content-hash": "010234aff469fe878aace1bf281c1dff", "packages": [ { "name": "composer/ca-bundle", @@ -157,16 +157,16 @@ }, { "name": "composer/composer", - "version": "2.8.5", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "ae208dc1e182bd45d99fcecb956501da212454a1" + "reference": "b70b6bd0709f6b2071935ee2f2b6061b812724d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/ae208dc1e182bd45d99fcecb956501da212454a1", - "reference": "ae208dc1e182bd45d99fcecb956501da212454a1", + "url": "https://api.github.com/repos/composer/composer/zipball/b70b6bd0709f6b2071935ee2f2b6061b812724d0", + "reference": "b70b6bd0709f6b2071935ee2f2b6061b812724d0", "shasum": "" }, "require": { @@ -205,6 +205,7 @@ "ext-zip": "Enabling the zip extension allows you to unzip archives", "ext-zlib": "Allow gzip compression of HTTP requests" }, + "default-branch": true, "bin": [ "bin/composer" ], @@ -251,7 +252,7 @@ "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", "security": "https://github.com/composer/composer/security/policy", - "source": "https://github.com/composer/composer/tree/2.8.5" + "source": "https://github.com/composer/composer/tree/main" }, "funding": [ { @@ -267,7 +268,7 @@ "type": "tidelift" } ], - "time": "2025-01-21T14:23:40+00:00" + "time": "2025-02-05T10:20:56+00:00" }, { "name": "composer/metadata-minifier", @@ -7003,13 +7004,15 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "composer/composer": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": "8.1.*||8.2.*||8.3.*||8.4.*" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "8.1.99" }, diff --git a/docs/extension-maintainers.md b/docs/extension-maintainers.md index bd70497..7f34de3 100644 --- a/docs/extension-maintainers.md +++ b/docs/extension-maintainers.md @@ -166,9 +166,9 @@ The `build-path` may contain some templated values which are replaced: with version 1.2.3 with a `build-path` of `myext-{version}` the actual build path would become `myext-1.2.3`. -#### `override-download-url-method` +#### `download-url-method` -The `override-download-url-method` directive allows extension maintainers to +The `download-url-method` directive allows extension maintainers to change the behaviour of downloading the source package. * Setting this to `composer-default`, which is the default value if not diff --git a/resources/composer-json-php-ext-schema.json b/resources/composer-json-php-ext-schema.json index 22ca370..ca28351 100644 --- a/resources/composer-json-php-ext-schema.json +++ b/resources/composer-json-php-ext-schema.json @@ -40,7 +40,7 @@ "example": "my-extension-source", "default": null }, - "override-download-url-method": { + "download-url-method": { "type": "string", "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.", "enum": ["composer-default", "pre-packaged-source"], diff --git a/src/DependencyResolver/Package.php b/src/DependencyResolver/Package.php index 331b14c..42bee00 100644 --- a/src/DependencyResolver/Package.php +++ b/src/DependencyResolver/Package.php @@ -18,7 +18,6 @@ use function array_slice; use function explode; use function implode; -use function is_string; use function parse_url; use function str_contains; use function str_starts_with; @@ -43,7 +42,7 @@ final class Package private array|null $incompatibleOsFamilies; private bool $supportZts; private bool $supportNts; - private DownloadUrlMethod|null $overrideDownloadUrlMethod; + private DownloadUrlMethod|null $downloadUrlMethod; public function __construct( private readonly CompletePackageInterface $composerPackage, @@ -53,14 +52,14 @@ public function __construct( private readonly string $version, private readonly string|null $downloadUrl, ) { - $this->configureOptions = []; - $this->supportZts = true; - $this->supportNts = true; - $this->buildPath = null; - $this->compatibleOsFamilies = null; - $this->incompatibleOsFamilies = null; - $this->priority = 80; - $this->overrideDownloadUrlMethod = null; + $this->configureOptions = []; + $this->supportZts = true; + $this->supportNts = true; + $this->buildPath = null; + $this->compatibleOsFamilies = null; + $this->incompatibleOsFamilies = null; + $this->priority = 80; + $this->downloadUrlMethod = null; } public static function fromComposerCompletePackage(CompletePackageInterface $completePackage): self @@ -99,12 +98,8 @@ public static function fromComposerCompletePackage(CompletePackageInterface $com $package->priority = $phpExtOptions['priority'] ?? 80; - if ( - $phpExtOptions !== null - && array_key_exists('override-download-url-method', $phpExtOptions) - && is_string($phpExtOptions['override-download-url-method']) - ) { - $package->overrideDownloadUrlMethod = DownloadUrlMethod::tryFrom($phpExtOptions['override-download-url-method']); + if ($phpExtOptions !== null && array_key_exists('download-url-method', $phpExtOptions)) { + $package->downloadUrlMethod = DownloadUrlMethod::tryFrom($phpExtOptions['download-url-method']); } return $package; @@ -227,8 +222,8 @@ public function supportNts(): bool return $this->supportNts; } - public function overrideDownloadUrlMethod(): DownloadUrlMethod|null + public function downloadUrlMethod(): DownloadUrlMethod|null { - return $this->overrideDownloadUrlMethod; + return $this->downloadUrlMethod; } } diff --git a/src/Downloading/DownloadUrlMethod.php b/src/Downloading/DownloadUrlMethod.php index ae1eadb..397de17 100644 --- a/src/Downloading/DownloadUrlMethod.php +++ b/src/Downloading/DownloadUrlMethod.php @@ -41,7 +41,7 @@ public static function fromPackage(Package $package, TargetPlatform $targetPlatf * external dependencies in Git submodules that otherwise aren't * included in GitHub/Gitlab/etc "dist" downloads */ - if ($package->overrideDownloadUrlMethod() === DownloadUrlMethod::PrePackagedSourceDownload) { + if ($package->downloadUrlMethod() === DownloadUrlMethod::PrePackagedSourceDownload) { return self::PrePackagedSourceDownload; } diff --git a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php index 2ca8671..237cbb6 100644 --- a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php +++ b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php @@ -216,7 +216,7 @@ public function testDistUrlIsUpdatedForPrePackagedTgzSource(): void $composerPackage->setDistUrl('https://example.com/git-archive-zip-url'); $composerPackage->setPhpExt([ 'extension-name' => 'foobar', - 'override-download-url-method' => 'pre-packaged-source', + 'download-url-method' => 'pre-packaged-source', ]); /** From 30714fe2baf50cdfb55f2fca75b0b0b9d548c46d Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 6 Feb 2025 08:00:15 +0000 Subject: [PATCH 12/14] Specify Package VO defaults in properties --- src/DependencyResolver/Package.php | 46 +++++++++++++----------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/src/DependencyResolver/Package.php b/src/DependencyResolver/Package.php index 42bee00..2e4d31e 100644 --- a/src/DependencyResolver/Package.php +++ b/src/DependencyResolver/Package.php @@ -33,16 +33,16 @@ final class Package { /** @var list */ - private array $configureOptions; - private int $priority; - private string|null $buildPath; + private array $configureOptions = []; + private int $priority = 80; + private string|null $buildPath = null; /** @var non-empty-list|null */ - private array|null $compatibleOsFamilies; + private array|null $compatibleOsFamilies = null; /** @var non-empty-list|null */ - private array|null $incompatibleOsFamilies; - private bool $supportZts; - private bool $supportNts; - private DownloadUrlMethod|null $downloadUrlMethod; + private array|null $incompatibleOsFamilies = null; + private bool $supportZts = true; + private bool $supportNts = true; + private DownloadUrlMethod|null $downloadUrlMethod = null; public function __construct( private readonly CompletePackageInterface $composerPackage, @@ -52,14 +52,6 @@ public function __construct( private readonly string $version, private readonly string|null $downloadUrl, ) { - $this->configureOptions = []; - $this->supportZts = true; - $this->supportNts = true; - $this->buildPath = null; - $this->compatibleOsFamilies = null; - $this->incompatibleOsFamilies = null; - $this->priority = 80; - $this->downloadUrlMethod = null; } public static function fromComposerCompletePackage(CompletePackageInterface $completePackage): self @@ -140,18 +132,20 @@ private static function convertInputStringsToOperatingSystemFamilies(array|null return null; } - $osFamilies = []; - foreach ($input as $value) { - $valueToTry = strtolower($value); + Assert::isNonEmptyList($input, 'Expected operating systems families to be a non-empty list.'); - Assert::inArray($valueToTry, OperatingSystemFamily::asValuesList(), 'Expected operating system family to be one of: %2$s. Got: %s'); + return array_map( + static function ($value): OperatingSystemFamily { + Assert::inArray( + strtolower($value), + OperatingSystemFamily::asValuesList(), + 'Expected operating system family to be one of: %2$s. Got: %s', + ); - $osFamilies[] = OperatingSystemFamily::from($valueToTry); - } - - Assert::isNonEmptyList($osFamilies, 'Expected operating systems families to be a non-empty list.'); - - return $osFamilies; + return OperatingSystemFamily::from(strtolower($value)); + }, + $input, + ); } public function composerPackage(): CompletePackageInterface From 9f5e15a68c7fce61a11b5fb05606f1f4e620f2ee Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 6 Feb 2025 08:16:54 +0000 Subject: [PATCH 13/14] Removed testing package name format --- src/Platform/PrePackagedSourceAssetName.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Platform/PrePackagedSourceAssetName.php b/src/Platform/PrePackagedSourceAssetName.php index 13aea73..3261b69 100644 --- a/src/Platform/PrePackagedSourceAssetName.php +++ b/src/Platform/PrePackagedSourceAssetName.php @@ -31,12 +31,6 @@ public static function packageNames(Package $package): array $package->extensionName()->name(), $package->version(), )), - // @todo remove this: - strtolower(sprintf( - '%s-%s.tgz', - $package->extensionName()->name(), - $package->version(), - )), ]; } } From 70639a71a47df22fbfa238d8addad80c296b51d9 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 6 Feb 2025 09:18:53 +0000 Subject: [PATCH 14/14] Add remaining unit tests for download URL override --- ...OverrideDownloadUrlInstallListenerTest.php | 130 +++++++++++++++++- .../Downloading/DownloadUrlMethodTest.php | 103 +++++++++++++- .../PrePackagedSourceAssetNameTest.php | 21 ++- 3 files changed, 247 insertions(+), 7 deletions(-) diff --git a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php index 237cbb6..859bdb9 100644 --- a/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php +++ b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php @@ -11,6 +11,7 @@ use Composer\Installer\InstallerEvents; use Composer\IO\IOInterface; use Composer\Package\CompletePackage; +use Composer\Package\Package; use Php\Pie\ComposerIntegration\Listeners\OverrideDownloadUrlInstallListener; use Php\Pie\ComposerIntegration\PieComposerRequest; use Php\Pie\ComposerIntegration\PieOperation; @@ -87,17 +88,140 @@ public function testEventListenerRegistration(): void public function testNonInstallOperationsAreIgnored(): void { - self::markTestIncomplete('todo'); // @todo + $composerPackage = new CompletePackage('foo/bar', '1.2.3.0', '1.2.3'); + $composerPackage->setDistUrl('https://example.com/git-archive-zip-url'); + + /** + * @psalm-suppress InternalClass + * @psalm-suppress InternalMethod + */ + $installerEvent = new InstallerEvent( + InstallerEvents::PRE_OPERATIONS_EXEC, + $this->composer, + $this->io, + false, + true, + new Transaction([$composerPackage], []), + ); + + $this->container + ->expects(self::never()) + ->method('get'); + + (new OverrideDownloadUrlInstallListener( + $this->composer, + $this->io, + $this->container, + new PieComposerRequest( + $this->createMock(OutputInterface::class), + new TargetPlatform( + OperatingSystem::NonWindows, + OperatingSystemFamily::Linux, + PhpBinaryPath::fromCurrentProcess(), + Architecture::x86_64, + ThreadSafetyMode::NonThreadSafe, + 1, + WindowsCompiler::VC15, + ), + new RequestedPackageAndVersion('foo/bar', '^1.1'), + PieOperation::Install, + [], + null, + false, + ), + ))($installerEvent); } public function testNonCompletePackagesAreIgnored(): void { - self::markTestIncomplete('todo'); // @todo + $composerPackage = new Package('foo/bar', '1.2.3.0', '1.2.3'); + $composerPackage->setDistUrl('https://example.com/git-archive-zip-url'); + + /** + * @psalm-suppress InternalClass + * @psalm-suppress InternalMethod + */ + $installerEvent = new InstallerEvent( + InstallerEvents::PRE_OPERATIONS_EXEC, + $this->composer, + $this->io, + false, + true, + new Transaction([], [$composerPackage]), + ); + + $this->container + ->expects(self::never()) + ->method('get'); + + (new OverrideDownloadUrlInstallListener( + $this->composer, + $this->io, + $this->container, + new PieComposerRequest( + $this->createMock(OutputInterface::class), + new TargetPlatform( + OperatingSystem::NonWindows, + OperatingSystemFamily::Linux, + PhpBinaryPath::fromCurrentProcess(), + Architecture::x86_64, + ThreadSafetyMode::NonThreadSafe, + 1, + WindowsCompiler::VC15, + ), + new RequestedPackageAndVersion('foo/bar', '^1.1'), + PieOperation::Install, + [], + null, + false, + ), + ))($installerEvent); } public function testInstallOperationsForDifferentPackagesAreIgnored(): void { - self::markTestIncomplete('todo'); // @todo + $composerPackage = new CompletePackage('different/package', '1.2.3.0', '1.2.3'); + $composerPackage->setDistUrl('https://example.com/git-archive-zip-url'); + + /** + * @psalm-suppress InternalClass + * @psalm-suppress InternalMethod + */ + $installerEvent = new InstallerEvent( + InstallerEvents::PRE_OPERATIONS_EXEC, + $this->composer, + $this->io, + false, + true, + new Transaction([], [$composerPackage]), + ); + + $this->container + ->expects(self::never()) + ->method('get'); + + (new OverrideDownloadUrlInstallListener( + $this->composer, + $this->io, + $this->container, + new PieComposerRequest( + $this->createMock(OutputInterface::class), + new TargetPlatform( + OperatingSystem::NonWindows, + OperatingSystemFamily::Linux, + PhpBinaryPath::fromCurrentProcess(), + Architecture::x86_64, + ThreadSafetyMode::NonThreadSafe, + 1, + WindowsCompiler::VC15, + ), + new RequestedPackageAndVersion('foo/bar', '^1.1'), + PieOperation::Install, + [], + null, + false, + ), + ))($installerEvent); } public function testWindowsUrlInstallerDoesNotRunOnNonWindows(): void diff --git a/test/unit/Downloading/DownloadUrlMethodTest.php b/test/unit/Downloading/DownloadUrlMethodTest.php index 53da6c5..f48b8e8 100644 --- a/test/unit/Downloading/DownloadUrlMethodTest.php +++ b/test/unit/Downloading/DownloadUrlMethodTest.php @@ -4,7 +4,19 @@ namespace Php\PieUnitTest\Downloading; +use Composer\Package\CompletePackage; +use Composer\Package\CompletePackageInterface; +use Php\Pie\DependencyResolver\Package; use Php\Pie\Downloading\DownloadUrlMethod; +use Php\Pie\ExtensionName; +use Php\Pie\ExtensionType; +use Php\Pie\Platform\Architecture; +use Php\Pie\Platform\OperatingSystem; +use Php\Pie\Platform\OperatingSystemFamily; +use Php\Pie\Platform\TargetPhp\PhpBinaryPath; +use Php\Pie\Platform\TargetPlatform; +use Php\Pie\Platform\ThreadSafetyMode; +use Php\Pie\Platform\WindowsCompiler; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -13,16 +25,101 @@ final class DownloadUrlMethodTest extends TestCase { public function testWindowsPackages(): void { - self::markTestIncomplete('todo'); // @todo + $package = new Package( + $this->createMock(CompletePackageInterface::class), + ExtensionType::PhpModule, + ExtensionName::normaliseFromString('foo'), + 'foo/foo', + '1.2.3', + null, + ); + + $phpBinaryPath = $this->createMock(PhpBinaryPath::class); + $phpBinaryPath + ->method('majorMinorVersion') + ->willReturn('8.1'); + + $targetPlatform = new TargetPlatform( + OperatingSystem::Windows, + OperatingSystemFamily::Windows, + $phpBinaryPath, + Architecture::x86_64, + ThreadSafetyMode::NonThreadSafe, + 1, + WindowsCompiler::VC15, + ); + + $downloadUrlMethod = DownloadUrlMethod::fromPackage($package, $targetPlatform); + + self::assertSame(DownloadUrlMethod::WindowsBinaryDownload, $downloadUrlMethod); + + self::assertSame( + [ + 'php_foo-1.2.3-8.1-nts-vc15-x86_64.zip', + 'php_foo-1.2.3-8.1-vc15-nts-x86_64.zip', + ], + $downloadUrlMethod->possibleAssetNames($package, $targetPlatform), + ); } public function testPrePackagedSourceDownloads(): void { - self::markTestIncomplete('todo'); // @todo + $composerPackage = $this->createMock(CompletePackage::class); + $composerPackage->method('getPrettyName')->willReturn('foo/bar'); + $composerPackage->method('getPrettyVersion')->willReturn('1.2.3'); + $composerPackage->method('getType')->willReturn('php-ext'); + $composerPackage->method('getPhpExt')->willReturn(['download-url-method' => 'pre-packaged-source']); + + $package = Package::fromComposerCompletePackage($composerPackage); + + $targetPlatform = new TargetPlatform( + OperatingSystem::NonWindows, + OperatingSystemFamily::Linux, + PhpBinaryPath::fromCurrentProcess(), + Architecture::x86_64, + ThreadSafetyMode::NonThreadSafe, + 1, + null, + ); + + $downloadUrlMethod = DownloadUrlMethod::fromPackage($package, $targetPlatform); + + self::assertSame(DownloadUrlMethod::PrePackagedSourceDownload, $downloadUrlMethod); + + self::assertSame( + [ + 'php_bar-1.2.3-src.tgz', + 'php_bar-1.2.3-src.zip', + ], + $downloadUrlMethod->possibleAssetNames($package, $targetPlatform), + ); } public function testComposerDefaultDownload(): void { - self::markTestIncomplete('todo'); // @todo + $package = new Package( + $this->createMock(CompletePackageInterface::class), + ExtensionType::PhpModule, + ExtensionName::normaliseFromString('foo'), + 'foo/foo', + '1.2.3', + null, + ); + + $targetPlatform = new TargetPlatform( + OperatingSystem::NonWindows, + OperatingSystemFamily::Linux, + PhpBinaryPath::fromCurrentProcess(), + Architecture::x86_64, + ThreadSafetyMode::NonThreadSafe, + 1, + null, + ); + + $downloadUrlMethod = DownloadUrlMethod::fromPackage($package, $targetPlatform); + + self::assertSame(DownloadUrlMethod::ComposerDefaultDownload, $downloadUrlMethod); + + self::assertNull($downloadUrlMethod->possibleAssetNames($package, $targetPlatform)); } } diff --git a/test/unit/Platform/PrePackagedSourceAssetNameTest.php b/test/unit/Platform/PrePackagedSourceAssetNameTest.php index 426aebc..5a47f14 100644 --- a/test/unit/Platform/PrePackagedSourceAssetNameTest.php +++ b/test/unit/Platform/PrePackagedSourceAssetNameTest.php @@ -4,6 +4,10 @@ namespace Php\PieUnitTest\Platform; +use Composer\Package\CompletePackageInterface; +use Php\Pie\DependencyResolver\Package; +use Php\Pie\ExtensionName; +use Php\Pie\ExtensionType; use Php\Pie\Platform\PrePackagedSourceAssetName; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; @@ -13,6 +17,21 @@ final class PrePackagedSourceAssetNameTest extends TestCase { public function testPackageNames(): void { - self::markTestIncomplete('todo'); // @todo + self::assertSame( + [ + 'php_foobar-1.2.3-src.tgz', + 'php_foobar-1.2.3-src.zip', + ], + PrePackagedSourceAssetName::packageNames( + new Package( + $this->createMock(CompletePackageInterface::class), + ExtensionType::PhpModule, + ExtensionName::normaliseFromString('foobar'), + 'foo/bar', + '1.2.3', + null, + ), + ), + ); } }