chore: complete update
This commit is contained in:
48
src/Framework/QueryBus/DefaultQueryBus.php
Normal file
48
src/Framework/QueryBus/DefaultQueryBus.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\QueryBus;
|
||||
|
||||
use App\Framework\DI\DefaultContainer;
|
||||
|
||||
final readonly class DefaultQueryBus implements QueryBus
|
||||
{
|
||||
public function __construct(
|
||||
private array $eventHandlers,
|
||||
private DefaultContainer $container
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Dispatcht ein Event an alle registrierten Handler
|
||||
*
|
||||
* @param object $event Das zu dispatchende Event
|
||||
* @return void
|
||||
*/
|
||||
public function dispatch(object $event): mixed {
|
||||
$eventClass = get_class($event);
|
||||
|
||||
// Prüfe, ob Handler für diesen Event-Typ registriert sind
|
||||
if (empty($this->eventHandlers) || !isset($this->eventHandlers[$eventClass])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Führe alle Handler für diesen Event-Typ aus
|
||||
foreach ($this->eventHandlers[$eventClass] as $handler) {
|
||||
try {
|
||||
$handlerClass = $this->container->get($handler['class']);
|
||||
$method = $handler['method'];
|
||||
|
||||
return $handlerClass->$method($event);
|
||||
|
||||
// Stoppe die Propagation, wenn der Handler dies anfordert
|
||||
if (isset($handler['stopPropagation']) && $handler['stopPropagation']) {
|
||||
break;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Fehler in Event-Handlern sollten die Anwendung nicht abstürzen lassen
|
||||
// In einer echten Anwendung würde hier ein Logger verwendet
|
||||
error_log('Fehler bei der Ausführung des Event-Handlers: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/Framework/QueryBus/QueryBus.php
Normal file
8
src/Framework/QueryBus/QueryBus.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\QueryBus;
|
||||
|
||||
interface QueryBus
|
||||
{
|
||||
public function dispatch(object $event): mixed;
|
||||
}
|
||||
23
src/Framework/QueryBus/QueryBusInitializer.php
Normal file
23
src/Framework/QueryBus/QueryBusInitializer.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\QueryBus;
|
||||
|
||||
use App\Framework\DI\Container;
|
||||
use App\Framework\DI\Initializer;
|
||||
use App\Framework\Discovery\Results\DiscoveryResults;
|
||||
|
||||
final readonly class QueryBusInitializer
|
||||
{
|
||||
public function __construct(
|
||||
private Container $container,
|
||||
private DiscoveryResults $results
|
||||
){}
|
||||
|
||||
#[Initializer]
|
||||
public function __invoke(): QueryBus
|
||||
{
|
||||
$handlers = $this->results->get(QueryHandler::class);
|
||||
|
||||
return new DefaultQueryBus($handlers, $this->container);
|
||||
}
|
||||
}
|
||||
24
src/Framework/QueryBus/QueryHandler.php
Normal file
24
src/Framework/QueryBus/QueryHandler.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\QueryBus;
|
||||
|
||||
/**
|
||||
* Attribut, das eine Methode als Event-Handler kennzeichnet.
|
||||
*
|
||||
* Beispiel:
|
||||
* #[EventHandler]
|
||||
* public function handleUserRegistered(UserRegistered $event): void { ... }
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||
final readonly class QueryHandler
|
||||
{
|
||||
/**
|
||||
* @param int|null $priority Priorität des Handlers (höhere Werte werden zuerst ausgeführt)
|
||||
* @param bool $stopPropagation Gibt an, ob die Event-Propagation nach diesem Handler gestoppt werden soll
|
||||
*/
|
||||
public function __construct(
|
||||
public ?int $priority = null,
|
||||
public bool $stopPropagation = false
|
||||
) {}
|
||||
}
|
||||
71
src/Framework/QueryBus/QueryHandlerCompiler.php
Normal file
71
src/Framework/QueryBus/QueryHandlerCompiler.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\QueryBus;
|
||||
|
||||
use App\Framework\Core\AttributeCompiler;
|
||||
use App\Framework\QueryBus\QueryHandler;
|
||||
|
||||
/**
|
||||
* Compiler für Event-Handler
|
||||
*/
|
||||
final readonly class QueryHandlerCompiler implements AttributeCompiler
|
||||
{
|
||||
/**
|
||||
* Gibt die Attributklasse zurück, die dieser Compiler verarbeitet
|
||||
*/
|
||||
public function getAttributeClass(): string
|
||||
{
|
||||
return QueryHandler::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kompiliert die Event-Handler
|
||||
*
|
||||
* @param array $handlers Array mit Attributdaten aus dem Mapper
|
||||
* @return array Kompilierte Event-Handler
|
||||
*/
|
||||
public function compile(array $handlers): array
|
||||
{
|
||||
$compiledHandlers = [];
|
||||
|
||||
// Wenn keine Handler vorhanden sind, leeres Array zurückgeben
|
||||
if (empty($handlers)) {
|
||||
return $compiledHandlers;
|
||||
}
|
||||
|
||||
foreach ($handlers as $handler) {
|
||||
$className = $handler['class'] ?? null;
|
||||
$methodName = $handler['method'] ?? null;
|
||||
$eventClass = $handler['event_class'] ?? null;
|
||||
$priority = $handler['attribute_data']['priority'] ?? 0;
|
||||
$stopPropagation = $handler['attribute_data']['stopPropagation'] ?? false;
|
||||
|
||||
// Prüfe, ob alle erforderlichen Daten vorhanden sind
|
||||
if (!$className || !$methodName || !$eventClass) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Füge den Handler zur Liste der Handler für diesen Event-Typ hinzu
|
||||
if (!isset($compiledHandlers[$eventClass])) {
|
||||
$compiledHandlers[$eventClass] = [];
|
||||
}
|
||||
|
||||
$compiledHandlers[$eventClass][] = [
|
||||
'class' => $className,
|
||||
'method' => $methodName,
|
||||
'priority' => $priority,
|
||||
'stopPropagation' => $stopPropagation
|
||||
];
|
||||
}
|
||||
|
||||
// Sortiere die Handler nach Priorität für jeden Event-Typ
|
||||
foreach ($compiledHandlers as $eventClass => $eventHandlers) {
|
||||
usort($compiledHandlers[$eventClass], function ($a, $b) {
|
||||
return $b['priority'] <=> $a['priority'];
|
||||
});
|
||||
}
|
||||
|
||||
return $compiledHandlers;
|
||||
}
|
||||
}
|
||||
60
src/Framework/QueryBus/QueryHandlerMapper.php
Normal file
60
src/Framework/QueryBus/QueryHandlerMapper.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\QueryBus;
|
||||
|
||||
use App\Framework\Core\AttributeMapper;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
|
||||
/**
|
||||
* Mapper für das EventHandler-Attribut
|
||||
*/
|
||||
final class QueryHandlerMapper implements AttributeMapper
|
||||
{
|
||||
/**
|
||||
* Gibt die Attributklasse zurück, die dieser Mapper verarbeitet
|
||||
*/
|
||||
public function getAttributeClass(): string
|
||||
{
|
||||
return QueryHandler::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert die map-Methode aus dem AttributeMapper-Interface
|
||||
*
|
||||
* @param object $reflectionTarget Das Reflektionsobjekt (ReflectionClass|ReflectionMethod)
|
||||
* @param object $attributeInstance Die Attributinstanz
|
||||
* @return array|null Die Attributdaten oder null, wenn nicht verarbeitet werden kann
|
||||
*/
|
||||
public function map(object $reflectionTarget, object $attributeInstance): ?array
|
||||
{
|
||||
if (!($reflectionTarget instanceof ReflectionMethod)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parameters = $reflectionTarget->getParameters();
|
||||
|
||||
// Event-Handler müssen mindestens einen Parameter haben (das Event)
|
||||
if (count($parameters) < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$eventType = $parameters[0]->getType();
|
||||
if (!$eventType || $eventType->isBuiltin()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$eventClassName = $eventType->getName();
|
||||
|
||||
return [
|
||||
'class' => $reflectionTarget->getDeclaringClass()->getName(),
|
||||
'method' => $reflectionTarget->getName(),
|
||||
'event_class' => $eventClassName,
|
||||
'attribute_data' => [
|
||||
'priority' => $attributeInstance->priority ?? 0,
|
||||
'stopPropagation' => $attributeInstance->stopPropagation ?? false
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user