Implement commands

This commit is contained in:
Tim 2023-08-16 16:04:35 +02:00
parent 1ee5c1c992
commit f8d1c66934
17 changed files with 200 additions and 48 deletions

View File

@ -0,0 +1,17 @@
<?php
namespace App\Console;
use Ardent\Undercurrent\Attribute\Command;
use Ardent\Undercurrent\Console\BaseCommand;
use Ardent\Undercurrent\Console\Output;
#[Command('app:test')]
class TestCommand extends BaseCommand
{
protected function run(Output $output): void
{
$output->printLine('Hello, command!');
}
}

View File

@ -7,7 +7,7 @@ use App\View\RouteView;
use Ardent\Undercurrent\Attribute\Route;
use Ardent\Undercurrent\Http\GenericResponse;
use Ardent\Undercurrent\Http\ResponseInterface;
use Ardent\Undercurrent\Http\RouterConfig;
use Ardent\Undercurrent\Http\RoutesConfig;
use Ardent\Undercurrent\Http\StatusEnum;
use Ardent\Undercurrent\View\BaseView;
use Ardent\Undercurrent\View\ViewInterface;
@ -40,7 +40,7 @@ class HelloWorldController
}
#[Route('/routes')]
public function routes(RouterConfig $config): ViewInterface
public function routes(RoutesConfig $config): ViewInterface
{
return new RouteView($config);
}

View File

@ -10,4 +10,22 @@ class Book
{
#[ORM\Id, ORM\Column, ORM\GeneratedValue]
private int $id;
#[ORM\Column]
private string $title;
public function getId(): int
{
return $this->id;
}
public function getTitle(): string
{
return $this->title;
}
public function setTitle(string $title): void
{
$this->title = $title;
}
}

View File

@ -2,16 +2,23 @@
namespace App;
use App\Console\TestCommand;
use App\Controller\HelloWorldController;
use Ardent\Undercurrent\Console\CommandsConfig;
use Ardent\Undercurrent\Container\ContainerInterface;
use Ardent\Undercurrent\Http\RoutesConfig;
use Ardent\Undercurrent\Kernel\BaseKernel;
class Kernel extends BaseKernel
{
protected function dependencies(ContainerInterface $container): void
{
$this->addControllers($container, [
HelloWorldController::class,
]);
$routes = new RoutesConfig();
$routes->add(HelloWorldController::class);
$this->addControllers($container, $routes);
$commands = new CommandsConfig();
$commands->add(TestCommand::class);
$this->addCommands($container, $commands);
}
}

View File

@ -2,12 +2,12 @@
namespace App\View;
use Ardent\Undercurrent\Http\RouterConfig;
use Ardent\Undercurrent\Http\RoutesConfig;
use Ardent\Undercurrent\View\BaseView;
class RouteView extends BaseView
{
public function __construct(protected readonly RouterConfig $routes)
public function __construct(protected readonly RoutesConfig $routes)
{
parent::__construct('/routes.php', extends: '/base');
}

View File

@ -3,9 +3,12 @@
use App\Kernel;
use Ardent\Undercurrent\Config\AppConfig;
use Ardent\Undercurrent\Console\Console;
require_once dirname(__DIR__) . '/vendor/autoload.php';
$kernel = new Kernel(new AppConfig(__DIR__ . '/../app'));
$container = $kernel->setup();
$console = new Console($container);
$console->run();

View File

@ -8,7 +8,7 @@ error_reporting(E_ALL);
use App\Kernel;
use Ardent\Undercurrent\Config\AppConfig;
use Ardent\Undercurrent\Kernel\Renderer;
use Ardent\Undercurrent\Http\Renderer;
require_once dirname(__DIR__) . '/vendor/autoload.php';

15
src/Attribute/Command.php Normal file
View File

@ -0,0 +1,15 @@
<?php
namespace Ardent\Undercurrent\Attribute;
use Attribute;
#[Attribute]
class Command
{
public function __construct(
public string $signature,
)
{
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Ardent\Undercurrent\Console;
abstract class BaseCommand
{
public function execute(Output $output): void
{
$this->run($output);
}
abstract protected function run(Output $output): void;
}

View File

@ -0,0 +1,40 @@
<?php
namespace Ardent\Undercurrent\Console;
use Ardent\Undercurrent\Attribute\Command;
use ReflectionAttribute;
use ReflectionClass;
class CommandsConfig
{
private array $commands = [];
public function add(string $commandClass): self
{
$reflectionClass = new ReflectionClass($commandClass);
$attributes = $reflectionClass->getAttributes(Command::class, ReflectionAttribute::IS_INSTANCEOF);
if (count($attributes) === 0) {
return $this;
}
$command = $attributes[0]->newInstance();
$this->commands[] = [
$command,
$commandClass,
];
return $this;
}
/**
* @return array<array{Command, string}>
*/
public function getCommands(): array
{
return $this->commands;
}
}

39
src/Console/Console.php Normal file
View File

@ -0,0 +1,39 @@
<?php
namespace Ardent\Undercurrent\Console;
use Ardent\Undercurrent\Container\ContainerInterface;
class Console
{
public function __construct(
private readonly ContainerInterface $container,
)
{
}
public function run(): void
{
$argv = $_SERVER['argv'];
$command = $argv[1] ?? '';
$output = new Output();
if (empty($command)) {
$output->printLine('No command defined');
return;
}
$config = $this->container->get(CommandsConfig::class);
foreach ($config->getCommands() as [$commandConfig, $commandClass]) {
if ($commandConfig->signature === $command) {
$commandInstance = $this->container->get($commandClass);
$commandInstance->execute($output);
return;
}
}
$output->printLine(sprintf('Command not found: "%s"', $command));
}
}

11
src/Console/Output.php Normal file
View File

@ -0,0 +1,11 @@
<?php
namespace Ardent\Undercurrent\Console;
class Output
{
public function printLine(string $line): void
{
echo $line . PHP_EOL;
}
}

View File

@ -13,7 +13,7 @@ class GenericRouter implements RouterInterface
public function __construct(
private readonly ContainerInterface $container,
private readonly LoggerInterface $logger,
private readonly RouterConfig $config,
private readonly RoutesConfig $config,
)
{
}

View File

@ -1,13 +1,8 @@
<?php
namespace Ardent\Undercurrent\Kernel;
namespace Ardent\Undercurrent\Http;
use Ardent\Undercurrent\Container\ContainerInterface;
use Ardent\Undercurrent\Http\GenericRequest;
use Ardent\Undercurrent\Http\GenericResponse;
use Ardent\Undercurrent\Http\MethodEnum;
use Ardent\Undercurrent\Http\RouterInterface;
use Ardent\Undercurrent\Http\StatusEnum;
use Ardent\Undercurrent\Logger\LogContainer;
class Renderer
@ -34,7 +29,7 @@ class Renderer
$e->getMessage(),
StatusEnum::NOT_FOUND
);
//$response = $container->get(RouterConfig::class)->getExceptionRoute()->getController()::exception($e);
//$response = $container->get(RoutesConfig::class)->getExceptionRoute()->getController()::exception($e);
}
http_response_code($response->getStatus()->value);

View File

@ -6,16 +6,19 @@ use Ardent\Undercurrent\Attribute\Route;
use ReflectionAttribute;
use ReflectionClass;
class RouterConfig
class RoutesConfig
{
/**
* @var array<RouteConfig>
*/
private array $routes = [];
public function addController(string $controller): self
private array $controllers = [];
public function add(string $controllerClass): self
{
$reflectionClass = new ReflectionClass($controller);
$this->controllers[] = $controllerClass;
$reflectionClass = new ReflectionClass($controllerClass);
foreach ($reflectionClass->getMethods() as $method) {
$attributes = $method->getAttributes(Route::class, ReflectionAttribute::IS_INSTANCEOF);
@ -28,7 +31,7 @@ class RouterConfig
$this->routes[] = new RouteConfig(
$route,
$controller,
$controllerClass,
$method->getName(),
);
}
@ -43,4 +46,9 @@ class RouterConfig
{
return $this->routes;
}
public function getControllers(): array
{
return $this->controllers;
}
}

View File

@ -4,10 +4,11 @@ namespace Ardent\Undercurrent\Kernel;
use Ardent\Undercurrent\Config\AppConfig;
use Ardent\Undercurrent\Config\GenericConfig;
use Ardent\Undercurrent\Console\CommandsConfig;
use Ardent\Undercurrent\Container\ContainerInterface;
use Ardent\Undercurrent\Container\GenericContainer;
use Ardent\Undercurrent\Http\GenericRouter;
use Ardent\Undercurrent\Http\RouterConfig;
use Ardent\Undercurrent\Http\RoutesConfig;
use Ardent\Undercurrent\Http\RouterInterface;
use Ardent\Undercurrent\Logger\LogContainer;
use Ardent\Undercurrent\Logger\LoggerInterface;
@ -56,16 +57,22 @@ class BaseKernel
return $container;
}
protected function addControllers(ContainerInterface $container, array $controllers): void
protected function addControllers(ContainerInterface $container, RoutesConfig $routes): void
{
$config = new RouterConfig();
foreach ($controllers as $controller) {
foreach ($routes->getControllers() as $controller) {
$container->add($controller);
$config->addController($controller);
}
$container->add(RouterConfig::class, fn() => $config);
$container->add(RoutesConfig::class, fn() => $routes);
}
protected function addCommands(ContainerInterface $container, CommandsConfig $commands): void
{
foreach ($commands->getCommands() as [$commandConfig, $commandClass]) {
$container->add($commandClass);
}
$container->add(CommandsConfig::class, fn() => $commands);
}
protected function dependencies(ContainerInterface $container): void

View File

@ -1,21 +0,0 @@
<?php
namespace Ardent\Undercurrent\Kernel;
use Ardent\Undercurrent\Container\ContainerInterface;
class Console
{
public function __construct(
private readonly ContainerInterface $container,
)
{
}
public function run(): void
{
$argv = $_SERVER['argv'];
dump($argv);
}
}