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 610728b..7f34de3 100644 --- a/docs/extension-maintainers.md +++ b/docs/extension-maintainers.md @@ -160,6 +160,26 @@ 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-1.2.3`. + +#### `download-url-method` + +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 + 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 new file mode 100644 index 0000000..ca28351 --- /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 + }, + "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"], + "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"] + } + } + ] + } + } +} 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/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/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/OverrideWindowsUrlInstallListener.php b/src/ComposerIntegration/OverrideWindowsUrlInstallListener.php deleted file mode 100644 index 43e064a..0000000 --- a/src/ComposerIntegration/OverrideWindowsUrlInstallListener.php +++ /dev/null @@ -1,75 +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'); - - $packageReleaseAssets = $this->container->get(PackageReleaseAssets::class); - $url = $packageReleaseAssets->findWindowsDownloadUrlForPackage( - $this->composerRequest->targetPlatform, - Package::fromComposerCompletePackage($composerPackage), - new AuthHelper($this->io, $this->composer->getConfig()), - new HttpDownloader($this->io, $this->composer->getConfig()), - ); - - $this->composerRequest->pieOutput->writeln('Found prebuilt archive: ' . $url); - $composerPackage->setDistUrl($url); - } -} diff --git a/src/ComposerIntegration/PieComposerFactory.php b/src/ComposerIntegration/PieComposerFactory.php index 279348d..7acb235 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\OverrideDownloadUrlInstallListener; +use Php\Pie\ComposerIntegration\Listeners\RemoveUnrelatedInstallOperations; use Php\Pie\ExtensionType; use Php\Pie\Platform; use Psr\Container\ContainerInterface; @@ -59,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/DependencyResolver/Package.php b/src/DependencyResolver/Package.php index d09a8a0..2e4d31e 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; @@ -26,53 +27,56 @@ * @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 = 80; + private string|null $buildPath = null; + /** @var non-empty-list|null */ + private array|null $compatibleOsFamilies = null; + /** @var non-empty-list|null */ + private array|null $incompatibleOsFamilies = null; + private bool $supportZts = true; + private bool $supportNts = true; + private DownloadUrlMethod|null $downloadUrlMethod = null; + 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, ) { } 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 +85,16 @@ 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; + + if ($phpExtOptions !== null && array_key_exists('download-url-method', $phpExtOptions)) { + $package->downloadUrlMethod = DownloadUrlMethod::tryFrom($phpExtOptions['download-url-method']); + } + + return $package; } public function prettyNameAndVersion(): string @@ -133,17 +132,92 @@ 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); - } + return OperatingSystemFamily::from(strtolower($value)); + }, + $input, + ); + } + + public function composerPackage(): CompletePackageInterface + { + return $this->composerPackage; + } - Assert::isNonEmptyList($osFamilies, 'Expected operating systems families to be a non-empty list.'); + public function extensionType(): ExtensionType + { + return $this->extensionType; + } - return $osFamilies; + 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; + } + + public function downloadUrlMethod(): DownloadUrlMethod|null + { + return $this->downloadUrlMethod; } } 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/DownloadUrlMethod.php b/src/Downloading/DownloadUrlMethod.php new file mode 100644 index 0000000..397de17 --- /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 ($package->downloadUrlMethod() === DownloadUrlMethod::PrePackagedSourceDownload) { + return self::PrePackagedSourceDownload; + } + + return self::ComposerDefaultDownload; + } +} diff --git a/src/Downloading/DownloadedPackage.php b/src/Downloading/DownloadedPackage.php index 3f6adeb..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; @@ -26,8 +27,12 @@ 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 + . str_replace('{version}', $package->version(), $package->buildPath()), + ); if (is_string($extractedSourcePathWithBuildPath)) { $extractedSourcePath = $extractedSourcePathWithBuildPath; diff --git a/src/Downloading/GithubPackageReleaseAssets.php b/src/Downloading/GithubPackageReleaseAssets.php index 69f338d..4b526ae 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 */ @@ -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/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/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 new file mode 100644 index 0000000..3261b69 --- /dev/null +++ b/src/Platform/PrePackagedSourceAssetName.php @@ -0,0 +1,36 @@ + */ + 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(), + )), + ]; + } +} 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/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/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 1bd9d56..4dd883c 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; @@ -53,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); @@ -77,11 +71,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/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/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php new file mode 100644 index 0000000..859bdb9 --- /dev/null +++ b/test/unit/ComposerIntegration/Listeners/OverrideDownloadUrlInstallListenerTest.php @@ -0,0 +1,399 @@ +composer = $this->createMock(Composer::class); + $this->io = $this->createMock(IOInterface::class); + $this->container = $this->createMock(ContainerInterface::class); + } + + public function testEventListenerRegistration(): void + { + $eventDispatcher = $this->createMock(EventDispatcher::class); + $eventDispatcher + ->expects(self::once()) + ->method('addListener') + ->with( + InstallerEvents::PRE_OPERATIONS_EXEC, + self::isInstanceOf(OverrideDownloadUrlInstallListener::class), + ); + + $this->composer + ->expects(self::once()) + ->method('getEventDispatcher') + ->willReturn($eventDispatcher); + + OverrideDownloadUrlInstallListener::selfRegister( + $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, + ), + ); + } + + public function testNonInstallOperationsAreIgnored(): void + { + $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 + { + $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 + { + $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 + { + $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); + + self::assertSame( + 'https://example.com/git-archive-zip-url', + $composerPackage->getDistUrl(), + ); + } + + public function testDistUrlIsUpdatedForWindowsInstallers(): void + { + $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]), + ); + + $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); + $packageReleaseAssets + ->expects(self::once()) + ->method('findMatchingReleaseAssetUrl') + ->willReturn('https://example.com/windows-download-url'); + + $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::Windows, + 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/windows-download-url', + $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' => 'foobar', + 'download-url-method' => 'pre-packaged-source', + ]); + + /** + * @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/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..f251c42 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; @@ -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\RemoveUnrelatedInstallOperations; use Php\Pie\DependencyResolver\RequestedPackageAndVersion; use Php\Pie\Platform\Architecture; use Php\Pie\Platform\OperatingSystem; diff --git a/test/unit/ComposerIntegration/OverrideWindowsUrlInstallListenerTest.php b/test/unit/ComposerIntegration/OverrideWindowsUrlInstallListenerTest.php deleted file mode 100644 index 8e9d269..0000000 --- a/test/unit/ComposerIntegration/OverrideWindowsUrlInstallListenerTest.php +++ /dev/null @@ -1,196 +0,0 @@ -composer = $this->createMock(Composer::class); - $this->io = $this->createMock(IOInterface::class); - $this->container = $this->createMock(ContainerInterface::class); - } - - public function testEventListenerRegistration(): void - { - $eventDispatcher = $this->createMock(EventDispatcher::class); - $eventDispatcher - ->expects(self::once()) - ->method('addListener') - ->with( - InstallerEvents::PRE_OPERATIONS_EXEC, - self::isInstanceOf(OverrideWindowsUrlInstallListener::class), - ); - - $this->composer - ->expects(self::once()) - ->method('getEventDispatcher') - ->willReturn($eventDispatcher); - - OverrideWindowsUrlInstallListener::selfRegister( - $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, - ), - ); - } - - public function testWindowsUrlInstallerDoesNotRunOnNonWindows(): void - { - $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 OverrideWindowsUrlInstallListener( - $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/git-archive-zip-url', - $composerPackage->getDistUrl(), - ); - } - - public function testDistUrlIsUpdatedForWindowsInstallers(): void - { - $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]), - ); - - $packageReleaseAssets = $this->createMock(PackageReleaseAssets::class); - $packageReleaseAssets - ->expects(self::once()) - ->method('findWindowsDownloadUrlForPackage') - ->willReturn('https://example.com/windows-download-url'); - - $this->container - ->method('get') - ->with(PackageReleaseAssets::class) - ->willReturn($packageReleaseAssets); - - (new OverrideWindowsUrlInstallListener( - $this->composer, - $this->io, - $this->container, - new PieComposerRequest( - $this->createMock(OutputInterface::class), - new TargetPlatform( - OperatingSystem::Windows, - 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/windows-download-url', - $composerPackage->getDistUrl(), - ); - } -} 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/DownloadUrlMethodTest.php b/test/unit/Downloading/DownloadUrlMethodTest.php new file mode 100644 index 0000000..f48b8e8 --- /dev/null +++ b/test/unit/Downloading/DownloadUrlMethodTest.php @@ -0,0 +1,125 @@ +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 + { + $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 + { + $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/Downloading/DownloadedPackageTest.php b/test/unit/Downloading/DownloadedPackageTest.php index c4edf0b..dcdc5dd 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__ . '/../'); @@ -71,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); + } } 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 34d8e25..58b99b1 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; @@ -78,18 +79,23 @@ 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'); - 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 @@ -141,18 +147,23 @@ 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'); - 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 @@ -185,18 +196,20 @@ 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'); $this->expectException(CouldNotFindReleaseAsset::class); - $releaseAssets->findWindowsDownloadUrlForPackage($targetPlatform, $package, $authHelper, $httpDownloader); + $releaseAssets->findMatchingReleaseAssetUrl( + $targetPlatform, + $package, + $authHelper, + $httpDownloader, + WindowsExtensionAssetName::zipNames( + $targetPlatform, + $package, + ), + ); } } 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/PrePackagedSourceAssetNameTest.php b/test/unit/Platform/PrePackagedSourceAssetNameTest.php new file mode 100644 index 0000000..5a47f14 --- /dev/null +++ b/test/unit/Platform/PrePackagedSourceAssetNameTest.php @@ -0,0 +1,37 @@ +createMock(CompletePackageInterface::class), + ExtensionType::PhpModule, + ExtensionName::normaliseFromString('foobar'), + 'foo/bar', + '1.2.3', + null, + ), + ), + ); + } +} 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, ); }