1
0
mirror of https://github.com/php/pie.git synced 2026-03-24 07:22:17 +01:00
Files
archived-pie/src/Command/BuildCommand.php
2026-03-05 11:57:21 +00:00

169 lines
6.2 KiB
PHP

<?php
declare(strict_types=1);
namespace Php\Pie\Command;
use Composer\IO\IOInterface;
use Php\Pie\ComposerIntegration\ComposerIntegrationHandler;
use Php\Pie\ComposerIntegration\ComposerRunFailed;
use Php\Pie\ComposerIntegration\PieComposerFactory;
use Php\Pie\ComposerIntegration\PieComposerRequest;
use Php\Pie\ComposerIntegration\PieOperation;
use Php\Pie\DependencyResolver\BundledPhpExtensionRefusal;
use Php\Pie\DependencyResolver\DependencyInstaller\PrescanSystemDependencies;
use Php\Pie\DependencyResolver\DependencyResolver;
use Php\Pie\DependencyResolver\InvalidPackageName;
use Php\Pie\DependencyResolver\UnableToResolveRequirement;
use Php\Pie\Installing\InstallForPhpProject\FindMatchingPackages;
use Php\Pie\Platform\PackageManager;
use Php\Pie\SelfManage\BuildTools\CheckAllBuildTools;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;
use function sprintf;
#[AsCommand(
name: 'build',
description: 'Download and build a PIE-compatible PHP extension, without installing it.',
)]
final class BuildCommand extends Command
{
public function __construct(
private readonly ContainerInterface $container,
private readonly DependencyResolver $dependencyResolver,
private readonly PrescanSystemDependencies $prescanSystemDependencies,
private readonly ComposerIntegrationHandler $composerIntegrationHandler,
private readonly FindMatchingPackages $findMatchingPackages,
private readonly IOInterface $io,
private readonly CheckAllBuildTools $checkBuildTools,
) {
parent::__construct();
}
public function configure(): void
{
parent::configure();
CommandHelper::configureDownloadBuildInstallOptions($this);
}
public function execute(InputInterface $input, OutputInterface $output): int
{
$targetPlatform = CommandHelper::determineTargetPlatformFromInputs($input, $this->io);
try {
$requestedNameAndVersion = CommandHelper::requestedNameAndVersionPair($input);
} catch (InvalidPackageName $invalidPackageName) {
return CommandHelper::handlePackageNotFound(
$invalidPackageName,
$this->findMatchingPackages,
$this->io,
$targetPlatform,
$this->container,
);
}
$forceInstallPackageVersion = CommandHelper::determineForceInstallingPackageVersion($input);
CommandHelper::applyNoCacheOptionIfSet($input, $this->io);
if (CommandHelper::shouldCheckForBuildTools($input)) {
$this->checkBuildTools->check(
$this->io,
PackageManager::detect(),
$targetPlatform,
CommandHelper::autoInstallBuildTools($input),
);
}
$composer = PieComposerFactory::createPieComposer(
$this->container,
new PieComposerRequest(
$this->io,
$targetPlatform,
$requestedNameAndVersion,
PieOperation::Resolve,
[], // Configure options are not needed for resolve only
false, // setting up INI not needed for build
),
);
if (CommandHelper::shouldCheckSystemDependencies($input)) {
try {
($this->prescanSystemDependencies)(
$composer,
$targetPlatform,
$requestedNameAndVersion,
CommandHelper::autoInstallSystemDependencies($input),
);
} catch (Throwable $anything) {
$this->io->writeError(
'<comment>Skipping system dependency pre-scan due to exception:</comment> ' . $anything->getMessage(),
verbosity: IOInterface::VERBOSE,
);
}
}
try {
$package = ($this->dependencyResolver)(
$composer,
$targetPlatform,
$requestedNameAndVersion,
$forceInstallPackageVersion,
);
} catch (UnableToResolveRequirement $unableToResolveRequirement) {
return CommandHelper::handlePackageNotFound(
$unableToResolveRequirement,
$this->findMatchingPackages,
$this->io,
$targetPlatform,
$this->container,
);
} catch (BundledPhpExtensionRefusal $bundledPhpExtensionRefusal) {
$this->io->writeError('');
$this->io->writeError('<comment>' . $bundledPhpExtensionRefusal->getMessage() . '</comment>');
return self::INVALID;
}
$this->io->write(sprintf('<info>Found package:</info> %s which provides <info>%s</info>', $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
CommandHelper::bindConfigureOptionsFromPackage($this, $package, $input);
$configureOptionsValues = CommandHelper::processConfigureOptionsFromInput($package, $input);
$composer = PieComposerFactory::createPieComposer(
$this->container,
new PieComposerRequest(
$this->io,
$targetPlatform,
$requestedNameAndVersion,
PieOperation::Build,
$configureOptionsValues,
false, // setting up INI not needed for build
),
);
try {
$this->composerIntegrationHandler->runInstall(
$package,
$composer,
$targetPlatform,
$requestedNameAndVersion,
$forceInstallPackageVersion,
false,
);
} catch (ComposerRunFailed $composerRunFailed) {
$this->io->writeError('<error>' . $composerRunFailed->getMessage() . '</error>');
return $composerRunFailed->getCode();
}
return Command::SUCCESS;
}
}