Files
server/core/lib/Runtime/Console/ConsoleRuntime.php
T
2026-07-27 00:48:11 -04:00

98 lines
3.0 KiB
PHP

<?php
declare(strict_types=1);
namespace KTXC\Runtime\Console;
use KTXC\Application\Execution\ExecutionDescriptor;
use KTXC\Application\Execution\ExecutionOutcome;
use KTXC\Kernel;
use KTXC\KernelInterface;
use KTXC\Module\ModuleManager;
use KTXF\Module\ModuleConsoleInterface;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Application as ConsoleApplication;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\LazyCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class ConsoleRuntime
{
public function __construct(
private readonly KernelInterface $kernel,
) {
}
public function run(
?InputInterface $input = null,
?OutputInterface $output = null,
): int
{
$scope = $this->kernel->beginExecution(ExecutionDescriptor::cli());
$outcome = ExecutionOutcome::incomplete();
try {
$exitCode = $this->application()->run($input, $output);
$outcome = ExecutionOutcome::success($exitCode);
return $exitCode;
} catch (\Throwable $error) {
$outcome = ExecutionOutcome::failure($error);
throw $error;
} finally {
$this->kernel->terminateExecution($scope, $outcome);
}
}
private function application(): ConsoleApplication
{
$container = $this->kernel->container();
$console = new ConsoleApplication('Vallarx Console', Kernel::VERSION);
$console->setAutoExit(false);
/** @var ModuleManager $moduleManager */
$moduleManager = $container->get(ModuleManager::class);
foreach ($moduleManager->list() as $module) {
$instance = $module->instance();
if (!$instance instanceof ModuleConsoleInterface) {
continue;
}
foreach ($instance->registerCI() as $commandClass) {
$this->registerLazyCommand($console, $container, $commandClass);
}
}
return $console;
}
/**
* @param class-string $commandClass
*/
private function registerLazyCommand(
ConsoleApplication $console,
ContainerInterface $container,
string $commandClass,
): void {
if (!class_exists($commandClass)) {
throw new \RuntimeException("Command class not found: {$commandClass}");
}
$reflection = new \ReflectionClass($commandClass);
$attributes = $reflection->getAttributes(AsCommand::class);
if ($attributes === []) {
throw new \RuntimeException("Command {$commandClass} is missing #[AsCommand].");
}
$attribute = $attributes[0]->newInstance();
$console->add(new LazyCommand(
$attribute->name,
[],
$attribute->description ?? '',
$attribute->hidden ?? false,
static fn() => $container->get($commandClass),
));
}
}