65c1b5fb75
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
98 lines
3.0 KiB
PHP
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),
|
|
));
|
|
}
|
|
}
|