diff --git a/composer.json b/composer.json index 87b1cfae..fab87ed2 100644 --- a/composer.json +++ b/composer.json @@ -32,6 +32,7 @@ "require-dev": { "deptrac/deptrac": "^4.4", "laravel/pint": "^1.26", + "monolog/monolog": "^3.9", "phpstan/phpstan": "^2.1", "phpunit/phpunit": "^11.5" }, diff --git a/deptrac.yaml b/deptrac.yaml index 7ce16fe3..0b6745f1 100644 --- a/deptrac.yaml +++ b/deptrac.yaml @@ -2,32 +2,38 @@ deptrac: paths: - ./src layers: - - name: Toolkit + - name: Application collectors: - type: classLike - value: CloudCreativity\\Modules\\Contracts\\Toolkit\\* + value: CloudCreativity\\Modules\\Contracts\\Application\\* - type: classLike - value: CloudCreativity\\Modules\\Toolkit\\* + value: CloudCreativity\\Modules\\Application\\* + - name: Bus + collectors: - type: classLike - value: Ramsey\\Uuid\\* + value: CloudCreativity\\Modules\\Contracts\\Bus\\* + - type: classLike + value: CloudCreativity\\Modules\\Bus\\* - name: Domain collectors: - type: classLike value: CloudCreativity\\Modules\\Contracts\\Domain\\* - type: classLike value: CloudCreativity\\Modules\\Domain\\* - - name: Application - collectors: - - type: classLike - value: CloudCreativity\\Modules\\Contracts\\Application\\* - - type: classLike - value: CloudCreativity\\Modules\\Application\\* - name: Infrastructure collectors: - type: classLike value: CloudCreativity\\Modules\\Contracts\\Infrastructure\\* - type: classLike value: CloudCreativity\\Modules\\Infrastructure\\* + - type: classLike + value: Monolog\\* + - name: Messaging + collectors: + - type: classLike + value: CloudCreativity\\Modules\\Contracts\\Messaging\\* + - type: classLike + value: CloudCreativity\\Modules\\Messaging\\* - name: PSR Container collectors: - type: classLike @@ -36,27 +42,38 @@ deptrac: collectors: - type: classLike value: Psr\\Log\\* - - name: Attributes + - name: Toolkit collectors: + - type: classLike + value: CloudCreativity\\Modules\\Contracts\\Toolkit\\* + - type: classLike + value: CloudCreativity\\Modules\\Toolkit\\* + - type: classLike + value: Ramsey\\Uuid\\* - type: classLike value: ^Deprecated$ ruleset: - Toolkit: - - Attributes - - PSR Container - Domain: - - Toolkit - - Attributes Application: - - Toolkit + - Bus - Domain + - Messaging - PSR Container - PSR Log - - Attributes - Infrastructure: - Toolkit - - Domain + Bus: + - Messaging + - PSR Container + - PSR Log + - Toolkit + Domain: + - Toolkit + Infrastructure: - Application + - Bus + - Messaging - PSR Container - PSR Log - - Attributes + - Toolkit + Messaging: + - Toolkit + Toolkit: diff --git a/docs/guide/application/asynchronous-processing.md b/docs/guide/application/asynchronous-processing.md index 2a1e9f9d..45b58b51 100644 --- a/docs/guide/application/asynchronous-processing.md +++ b/docs/guide/application/asynchronous-processing.md @@ -197,8 +197,7 @@ And then our port adapter is as follows: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\Ports\Driven\Queue\InternalCommandBus; -use CloudCreativity\Modules\Application\Bus\CommandDispatcher; +use App\Modules\EventManagement\Application\Ports\Driven\Queue\InternalCommandBus;use CloudCreativity\Modules\Bus\CommandDispatcher; final class InternalCommandBusAdapter extends CommandDispatcher implements InternalCommandBus @@ -221,7 +220,7 @@ public commands. I.e.: ```php namespace App\Modules\EventManagement\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue as Port; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue as Port; // injected into the command queuer for queuing public commands interface Queue extends Port @@ -239,4 +238,4 @@ internal bus - to dispatch the command to when it is pulled from the queue. If you prefer, it is acceptable to define a single queue driven port. This simplifies the implementation by having a single queue that deals with both. However, you might find it gets complicated knowing whether to dispatch queued -commands to either the public or internal command bus. \ No newline at end of file +commands to either the public or internal command bus. diff --git a/docs/guide/application/commands.md b/docs/guide/application/commands.md index a413eaa7..6c135d8e 100644 --- a/docs/guide/application/commands.md +++ b/docs/guide/application/commands.md @@ -18,9 +18,7 @@ For example: ```php namespace App\Modules\EventManagement\Application\UseCases\Commands\CancelAttendeeTicket; -use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use VendorName\EventManagement\Shared\Enums\CancellationReasonEnum; +use CloudCreativity\Modules\Contracts\Messaging\Command;use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier;use VendorName\EventManagement\Shared\Enums\CancellationReasonEnum; final readonly class CancelAttendeeTicketCommand implements Command { @@ -52,10 +50,7 @@ For example: ```php namespace App\Modules\EventManagement\Application\UseCases\Commands\CancelAttendeeTicket; -use App\Modules\EventManagement\Application\Ports\Driven\Persistence\AttendeeRepository; -use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; -use CloudCreativity\Modules\Toolkit\Results\Result; +use App\Modules\EventManagement\Application\Ports\Driven\Persistence\AttendeeRepository;use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork;use CloudCreativity\Modules\Contracts\Bus\DispatchThroughMiddleware;use CloudCreativity\Modules\Toolkit\Results\Result; final readonly class CancelAttendeeTicketHandler implements DispatchThroughMiddleware @@ -142,8 +137,7 @@ And then our implementation is as follows: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\Ports\Driving\CommandBus as Port; -use CloudCreativity\Modules\Application\Bus\CommandDispatcher; +use App\Modules\EventManagement\Application\Ports\Driving\CommandBus as Port;use CloudCreativity\Modules\Bus\CommandDispatcher; final class CommandBus extends CommandDispatcher implements Port { @@ -167,16 +161,7 @@ For example: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\UsesCases\Commands\{ - CancelAttendeeTicket\CancelAttendeeTicketCommand, - CancelAttendeeTicket\CancelAttendeeTicketHandler, -}; -use App\Modules\EventManagement\Application\Ports\Driving\CommandBus as CommandBusPort; -use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies; -use CloudCreativity\Modules\Application\Bus\CommandHandlerContainer; -use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; +use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies;use App\Modules\EventManagement\Application\Ports\Driving\CommandBus as CommandBusPort;use App\Modules\EventManagement\Application\UsesCases\Commands\{CancelAttendeeTicket\CancelAttendeeTicketCommand,CancelAttendeeTicket\CancelAttendeeTicketHandler,};use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork;use CloudCreativity\Modules\Bus\CommandHandlerContainer;use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch;use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; final class CommandBusProvider { @@ -343,9 +328,7 @@ And then our implementation is as follows: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\Ports\Driving\CommandQueuer as Port; -use App\Modules\EventManagement\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Application\Bus\CommandQueuer as Queuer; +use App\Modules\EventManagement\Application\Ports\Driven\Queue;use App\Modules\EventManagement\Application\Ports\Driving\CommandQueuer as Port;use CloudCreativity\Modules\Application\Bus\CommandQueuer as Queuer; final class CommandQueuer extends Queuer implements Port { @@ -466,8 +449,7 @@ singleton instances of dependencies. For example: ```php -use App\Modules\EventManagement\Domain\Services; -use CloudCreativity\Modules\Application\Bus\Middleware\SetupBeforeDispatch; +use App\Modules\EventManagement\Domain\Services;use CloudCreativity\Modules\Bus\Middleware\SetupBeforeDispatch; $middleware->bind( SetupBeforeDispatch::class, @@ -497,7 +479,7 @@ If you only need to do teardown work, use the `TeardownAfterDispatch` middleware closure as its only constructor argument: ```php -use CloudCreativity\Modules\Application\Bus\Middleware\TeardownAfterDispatch; +use CloudCreativity\Modules\Bus\Middleware\TeardownAfterDispatch; $middleware->bind( TeardownAfterDispatch::class, @@ -578,7 +560,7 @@ Use our `LogMessageDispatch` middleware to log the dispatch of a command, and th [PSR Logger](https://php-fig.org/psr/psr-3/). ```php -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; +use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch; $middleware->bind( LogMessageDispatch::class, @@ -620,9 +602,7 @@ However, there may be scenarios where a property should not be logged, e.g. beca In this scenario, use the `Sensitive` attribute on the property, and it will not be logged: ```php -use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Toolkit\Loggable\Sensitive; +use CloudCreativity\Modules\Toolkit\Sensitive;use CloudCreativity\Modules\Contracts\Messaging\Command;use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; final readonly class CancelAttendeeTicketCommand implements Command { @@ -638,9 +618,7 @@ final readonly class CancelAttendeeTicketCommand implements Command If you need full control over the log context, implement the `ContextProvider` interface on your command message: ```php -use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; -use CloudCreativity\Modules\Contracts\Toolkit\Loggable\ContextProvider; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Bus\Loggable\ContextProvider;use CloudCreativity\Modules\Contracts\Messaging\Command;use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; final readonly class CancelAttendeeTicketCommand implements Command, @@ -670,10 +648,7 @@ following signature: ```php namespace App\Modules\EventManagement\Application\Bus\Middleware; -use Closure; -use CloudCreativity\Modules\Contracts\Application\Bus\CommandMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; +use Closure;use CloudCreativity\Modules\Contracts\Bus\Middleware\CommandMiddleware;use CloudCreativity\Modules\Contracts\Messaging\Command;use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; final class MyMiddleware implements CommandMiddleware { @@ -685,7 +660,7 @@ final class MyMiddleware implements CommandMiddleware * @return Result */ public function __invoke( - Command $command, + Command $command, Closure $next, ): Result { @@ -712,11 +687,7 @@ instead: ```php namespace App\Modules\EventManagement\Application\Bus\Middleware; -use Closure; -use CloudCreativity\Modules\Contracts\Application\Bus\BusMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; -use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; +use Closure;use CloudCreativity\Modules\Contracts\Bus\Middleware\BusMiddleware;use CloudCreativity\Modules\Contracts\Messaging\Command;use CloudCreativity\Modules\Contracts\Messaging\Query;use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; class MyBusMiddleware implements BusMiddleware { @@ -728,7 +699,7 @@ class MyBusMiddleware implements BusMiddleware * @return Result */ public function __invoke( - Command|Query $message, + Command|Query $message, Closure $next, ): Result { diff --git a/docs/guide/application/domain-events.md b/docs/guide/application/domain-events.md index d847065f..b55aaa8e 100644 --- a/docs/guide/application/domain-events.md +++ b/docs/guide/application/domain-events.md @@ -54,7 +54,7 @@ namespace App\Modules\EventManagement\Application\Internal\DomainEvents; use App\Modules\EventManagement\Domain\Events\DomainEventDispatcher; use CloudCreativity\Modules\Application\DomainEventDispatching\UnitOfWorkAwareDispatcher; -final class DomainEventDispatcherAdapter extends UnitOfWorkAwareDispatcher implements +final class DomainEventDispatcherAdapter extends UnitOfWorkAwareDispatcher implements DomainEventDispatcher { } @@ -87,10 +87,10 @@ use CloudCreativity\Modules\Contracts\Application\UnitOfWork\UnitOfWorkManager; use CloudCreativity\Modules\Contracts\Domain\Events\DomainEvent; use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; -final readonly class DomainEventDispatcherProvider +final readonly class DomainEventDispatcherProvider { /** - * @var array, list> + * @var array, list> */ private array $subscriptions = [ AttendeeTicketWasCancelled::class => [ @@ -104,7 +104,7 @@ final readonly class DomainEventDispatcherProvider private ExternalDependencies $dependencies, ) { } - + public function getEventDispatcher(UnitOfWorkManager $unitOfWorkManager): DomainEventDispatcher { $dispatcher = new DomainEventDispatcherAdapter( @@ -112,7 +112,7 @@ final readonly class DomainEventDispatcherProvider listeners: $listeners = new ListenerContainer(), middleware: $middleware = new PipeContainer(), ); - + /** Bind listener factories */ $listeners->bind( Listeners\UpdateTicketSalesReport::class, @@ -120,19 +120,19 @@ final readonly class DomainEventDispatcherProvider $this->dependencies->getTicketSalesReportRepository(), ), ); - + $listeners->bind( Listeners\QueueTicketCancellationEmail::class, fn () => new Listeners\QueueTicketCancellationEmail( $this->dependencies->getMailer(), ), ); - + /** Subscribe listeners to events */ foreach ($this->subscriptions as $event => $listeners) { $dispatcher->listen($event, $listeners); } - + /** Bind middleware factories */ $middleware->bind( LogDomainEventDispatch::class, @@ -140,12 +140,12 @@ final readonly class DomainEventDispatcherProvider $this->dependencies->getLogger(), ), ); - + /** Attach middleware for all events */ $dispatcher->through([ LogDomainEventDispatch::class, ]); - + return $dispatcher; } } @@ -171,26 +171,17 @@ above: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\Ports\Driving\CommandBus; -use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies; -use App\Modules\EventManagement\Application\Internal\DomainEvents\DomainEventDispatcher; -use App\Modules\EventManagement\Application\Internal\DomainEvents\DomainEventDispatcherProvider; -use App\Modules\EventManagement\Domain\Services as DomainServices; -use CloudCreativity\Modules\Application\Bus\CommandHandlerContainer; -use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; -use CloudCreativity\Modules\Application\Bus\Middleware\SetupBeforeDispatch; -use CloudCreativity\Modules\Application\UnitOfWork\UnitOfWorkManager; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; +use App\Modules\EventManagement\Application\Internal\DomainEvents\DomainEventDispatcher;use App\Modules\EventManagement\Application\Internal\DomainEvents\DomainEventDispatcherProvider;use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies;use App\Modules\EventManagement\Application\Ports\Driving\CommandBus;use App\Modules\EventManagement\Domain\Services as DomainServices;use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork;use CloudCreativity\Modules\Application\UnitOfWork\UnitOfWorkManager;use CloudCreativity\Modules\Bus\CommandHandlerContainer;use CloudCreativity\Modules\Bus\Middleware\SetupBeforeDispatch;use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; final class CommandBusProvider { /** - * @var UnitOfWorkManager|null + * @var UnitOfWorkManager|null */ private ?UnitOfWorkManager $unitOfWorkManager = null; - + /** - * @var DomainEventDispatcher|null + * @var DomainEventDispatcher|null */ private ?DomainEventDispatcher $eventDispatcher = null; @@ -208,7 +199,7 @@ final class CommandBusProvider ); // ...handler bindings. - + $middleware->bind( SetupBeforeDispatch::class, fn () => new SetupBeforeDispatch(function (): Closure { @@ -218,45 +209,45 @@ final class CommandBusProvider }; }), ); - + $middleware->bind( ExecuteInUnitOfWork::class, fn () => new ExecuteInUnitOfWork($this->unitOfWorkManager), ); - + $bus->through([ SetupBeforeDispatch::class, ]); return $bus; } - + /** * Set up command handling state. - * - * @return void + * + * @return void */ private function setUp(): void { $this->unitOfWorkManager = new UnitOfWorkManager( $this->dependencies->getUnitOfWork(), ); - + DomainServices::setEvents(function () { if ($this->eventDispatcher) { return $this->eventDispatcher; } - + return $this->eventDispatcher = $this->eventDispatcherProvider->getEventDispatcher( $this->unitOfWorkManager ); }); } - + /** * Tear down command handling state. - * - * @return void + * + * @return void */ private function tearDown(): void { @@ -312,7 +303,7 @@ namespace App\Modules\EventManagement\Application\Internal\DomainEvents; use CloudCreativity\Modules\Application\DomainEventDispatching\DeferredDispatcher; -final class DomainEventDispatcherAdapter extends DeferredDispatcher implements +final class DomainEventDispatcherAdapter extends DeferredDispatcher implements DeferredDomainEventDispatcher { } @@ -335,10 +326,10 @@ use CloudCreativity\Modules\Application\DomainEventDispatching\Middleware\LogDom use CloudCreativity\Modules\Contracts\Domain\Events\DomainEvent; use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; -final readonly class DomainEventDispatcherProvider +final readonly class DomainEventDispatcherProvider { /** - * @var array, list> + * @var array, list> */ private array $subscriptions = [ AttendeeTicketWasCancelled::class => [ @@ -352,14 +343,14 @@ final readonly class DomainEventDispatcherProvider private ExternalDependencies $dependencies, ) { } - + public function getEventDispatcher(): DeferredDomainEventDispatcher { $dispatcher = new DomainEventDispatcherAdapter( listeners: $listeners = new ListenerContainer(), middleware: $middleware = new PipeContainer(), ); - + /** Bind listener factories */ $listeners->bind( Listeners\UpdateTicketSalesReport::class, @@ -367,19 +358,19 @@ final readonly class DomainEventDispatcherProvider $this->dependencies->getTicketSalesReportRepository(), ), ); - + $listeners->bind( Listeners\QueueTicketCancellationEmail::class, fn () => new Listeners\QueueTicketCancellationEmail( $this->dependencies->getMailer(), ), ); - + /** Subscribe listeners to events */ foreach ($this->subscriptions as $event => $listeners) { $dispatcher->listen($event, $listeners); } - + /** Bind middleware factories */ $middleware->bind( LogDomainEventDispatch::class, @@ -387,12 +378,12 @@ final readonly class DomainEventDispatcherProvider $this->dependencies->getLogger(), ), ); - + /** Attach middleware for all events */ $dispatcher->through([ LogDomainEventDispatch::class, ]); - + return $dispatcher; } } @@ -409,20 +400,12 @@ Here's an example: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\Ports\Driving\CommandBus as CommandBusPort; -use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies; -use App\Modules\EventManagement\Application\Internal\DomainEvents\DomainEventDispatcher; -use App\Modules\EventManagement\Application\Internal\DomainEvents\DomainEventDispatcherProvider; -use App\Modules\EventManagement\Domain\Services as DomainServices; -use CloudCreativity\Modules\Application\Bus\CommandHandlerContainer; -use CloudCreativity\Modules\Application\Bus\Middleware\FlushDeferredEvents; -use CloudCreativity\Modules\Application\Bus\Middleware\SetupBeforeDispatch; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; +use App\Modules\EventManagement\Application\Internal\DomainEvents\DomainEventDispatcher;use App\Modules\EventManagement\Application\Internal\DomainEvents\DomainEventDispatcherProvider;use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies;use App\Modules\EventManagement\Application\Ports\Driving\CommandBus as CommandBusPort;use App\Modules\EventManagement\Domain\Services as DomainServices;use CloudCreativity\Modules\Application\Bus\Middleware\FlushDeferredEvents;use CloudCreativity\Modules\Bus\CommandHandlerContainer;use CloudCreativity\Modules\Bus\Middleware\SetupBeforeDispatch;use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; final class CommandBusProvider { /** - * @var DomainEventDispatcher|null + * @var DomainEventDispatcher|null */ private ?DomainEventDispatcher $eventDispatcher = null; @@ -445,7 +428,7 @@ final class CommandBusProvider FlushDeferredEvents::class, fn () => new ExecuteInUnitOfWork($this->eventDispatcher), ); - + $middleware->bind( SetupBeforeDispatch::class, fn () => new SetupBeforeDispatch(function (): Closure { @@ -455,31 +438,31 @@ final class CommandBusProvider }; }), ); - + $bus->through([ SetupBeforeDispatch::class, ]); return $bus; } - + /** * Set up command handling state. - * - * @return void + * + * @return void */ private function setUp(): void { $this->eventDispatcher = $this->eventDispatcherProvider ->getEventDispatcher(); - + DomainServices::setEvents(fn () => $this->eventDispatcher); } - + /** * Tear down command handling state. - * - * @return void + * + * @return void */ private function tearDown(): void { @@ -679,7 +662,7 @@ final class MyMiddleware implements DomainEventMiddleware * @return void */ public function __invoke( - DomainEvent $event, + DomainEvent $event, Closure $next, ): Result { @@ -693,4 +676,4 @@ final class MyMiddleware implements DomainEventMiddleware ``` It is worth noting that here we are wrapping the event being emitted by the domain layer, which is the point at which it -may be deferred by the dispatcher. \ No newline at end of file +may be deferred by the dispatcher. diff --git a/docs/guide/application/integration-events.md b/docs/guide/application/integration-events.md index 3cff6bb4..9aa47dea 100644 --- a/docs/guide/application/integration-events.md +++ b/docs/guide/application/integration-events.md @@ -36,12 +36,9 @@ For example: ```php namespace VendorName\EventManagement\Shared\IntegrationEvents\V1; -use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; -use CloudCreativity\Modules\Toolkit\Identifiers\Uuid; -use VendorName\EventManagement\Shared\Enums\CancellationReasonEnum; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent;use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier;use CloudCreativity\Modules\Toolkit\Identifiers\Uuid;use VendorName\EventManagement\Shared\Enums\CancellationReasonEnum; -final readonly class AttendeeTicketWasCancelled implements +final readonly class AttendeeTicketWasCancelled implements IntegrationEvent { public function __construct( @@ -97,7 +94,7 @@ This can be expressed via an interface. To illustrate the point, a JSON serializ ```php namespace VendorName\Ordering\Shared\IntegrationEvents\V1\Serializers; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; interface JsonSerializer { @@ -151,7 +148,7 @@ Your application layer should define the driven port: ```php namespace App\Modules\EventManagement\Application\Ports\Driven\OutboundEventBus; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\OutboundEventPublisher; +use CloudCreativity\Modules\Contracts\Application\Ports\OutboundEventPublisher; interface OutboundEventBus extends OutboundEventPublisher { @@ -356,11 +353,7 @@ side effects are triggered. ```php namespace App\Modules\EventManagement\Application\UseCases\InboundEvents; -use App\Modules\EventManagement\Domain\Events\DomainEventDispatcher; -use App\Modules\EventManagement\Domain\Events\SalesAtEventDidChange; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\HandleInUnitOfWork; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; -use VendorName\Ordering\Shared\IntegrationEvents\V1\OrderWasFulfilled; +use App\Modules\EventManagement\Domain\Events\DomainEventDispatcher;use App\Modules\EventManagement\Domain\Events\SalesAtEventDidChange;use CloudCreativity\Modules\Application\InboundEventBus\Middleware\HandleInUnitOfWork;use CloudCreativity\Modules\Contracts\Bus\DispatchThroughMiddleware;use VendorName\Ordering\Shared\IntegrationEvents\V1\OrderWasFulfilled; final readonly class OrderWasFulfilledHandler implements DispatchThroughMiddleware @@ -403,7 +396,7 @@ We do this by defining an interface in our application's driving ports: ```php namespace App\Modules\EventManagement\Application\Ports\Driving; -use CloudCreativity\Modules\Contracts\Application\Ports\Driving\InboundEventDispatcher; +use CloudCreativity\Modules\Contracts\Messaging\InboundEventDispatcher; interface InboundEventBus extends InboundEventDispatcher { @@ -415,8 +408,7 @@ And then our implementation is as follows: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\Ports\Driving\InboundEventBus as Port; -use CloudCreativity\Modules\Application\InboundEventBus\InboundEventDispatcher; +use App\Modules\EventManagement\Application\Ports\Driving\InboundEventBus as Port;use CloudCreativity\Modules\Bus\InboundEventDispatcher; final class InboundEventBus extends InboundEventDispatcher implements Port { @@ -440,15 +432,7 @@ For example: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\Bus\CommandBusProvider; -use App\Modules\EventManagement\Application\UsesCases\InboundEvents\OrderWasFulfilledHandler; -use App\Modules\EventManagement\Application\Ports\Driving\InboundEventBus as InboundEventBusPort; -use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies; -use CloudCreativity\Modules\Application\InboundEventBus\EventHandlerContainer; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\HandleInUnitOfWork; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\LogInboundEvent; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; -use VendorName\Ordering\Shared\IntegrationEvents\V1\OrderWasFulfilled; +use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies;use App\Modules\EventManagement\Application\Ports\Driving\InboundEventBus as InboundEventBusPort;use App\Modules\EventManagement\Application\UsesCases\InboundEvents\OrderWasFulfilledHandler;use CloudCreativity\Modules\Application\InboundEventBus\Middleware\HandleInUnitOfWork;use CloudCreativity\Modules\Bus\EventHandlerContainer;use CloudCreativity\Modules\Bus\Middleware\LogInboundEvent;use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer;use VendorName\Ordering\Shared\IntegrationEvents\V1\OrderWasFulfilled; final class InboundEventBusProvider { @@ -539,9 +523,7 @@ Here is an example controller from a Laravel application to demonstrate the patt ```php namespace App\Http\Controllers\Api\PubSub; -use App\Modules\EventManagement\Application\Ports\Driving\InboundEventBus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; -use VendorName\Ordering\Shared\IntegrationEvents\V1\Serializers\JsonSerializer; +use App\Modules\EventManagement\Application\Ports\Driving\InboundEventBus;use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent;use VendorName\Ordering\Shared\IntegrationEvents\V1\Serializers\JsonSerializer; class InboundEventController extends Controller { @@ -590,8 +572,7 @@ To do this, we configure a default handler on the handler container that is give the `SwallowInboundEvent` handler for this purpose: ```php -use CloudCreativity\Modules\Application\InboundEventBus\EventHandlerContainer; -use CloudCreativity\Modules\Application\InboundEventBus\SwallowInboundEvent; +use CloudCreativity\Modules\Bus\EventHandlerContainer;use CloudCreativity\Modules\Bus\SwallowInboundEvent; $bus = new InboundEventBus( handlers: $handlers = new EventHandlerContainer( @@ -605,9 +586,7 @@ the `SwallowInboundEvent` handler will do nothing with the event. You can also p the `SwallowInboundEvent` handler, so that it logs that the event was swallowed: ```php -use CloudCreativity\Modules\Application\InboundEventBus\EventHandlerContainer; -use CloudCreativity\Modules\Application\InboundEventBus\SwallowInboundEvent; -use Psr\Log\LogLevel; +use CloudCreativity\Modules\Bus\EventHandlerContainer;use CloudCreativity\Modules\Bus\SwallowInboundEvent;use Psr\Log\LogLevel; $bus = new InboundEventBus( handlers: $handlers = new EventHandlerContainer( @@ -648,7 +627,7 @@ example: ```php namespace App\Modules\EventManagement\Application\Ports\Driving; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; interface Inbox { @@ -663,12 +642,12 @@ might look like this: ```php namespace App\Modules\EventManagement\Application\Ports\Driven\Inbox; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; interface InboxRepository { public function exists(IntegrationEvent $event): bool; - + public function store(IntegrationEvent $event): void; } ``` @@ -682,9 +661,7 @@ This means we can now update the previous controller example to use the inbox in ```php namespace App\Http\Controllers\Api\PubSub; -use App\Modules\EventManagement\Application\Ports\Driving\InboundEvents\Inbox; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; -use VendorName\Ordering\Shared\IntegrationEvents\V1\Serializers\JsonSerializer; +use App\Modules\EventManagement\Application\Ports\Driving\InboundEvents\Inbox;use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent;use VendorName\Ordering\Shared\IntegrationEvents\V1\Serializers\JsonSerializer; class InboundEventController extends Controller { @@ -753,7 +730,7 @@ whether the notifying or publishing completes or throws an exception. For example: ```php -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\SetupBeforeEvent; +use CloudCreativity\Modules\Bus\Middleware\SetupBeforeEvent; $middleware->bind( SetupBeforeEvent::class, @@ -780,7 +757,7 @@ If you only need to do any teardown work, use the `TeardownAfterEvent` middlewar closure as its only constructor argument: ```php -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\TearDownAfterEvent; +use CloudCreativity\Modules\Bus\Middleware\TearDownAfterEvent; $middleware->bind( TearDownAfterEvent::class, @@ -863,7 +840,7 @@ Use our `LogInboundEvent` middleware to log when an integration event is consume a [PSR Logger](https://php-fig.org/psr/psr-3/). ```php -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\LogInboundEvent; +use CloudCreativity\Modules\Bus\Middleware\LogInboundEvent; $middleware->bind( LogInboundEvent::class, @@ -888,11 +865,9 @@ following signature: ```php namespace App\Modules\EventManagement\Application\Bus\Middleware; -use Closure; -use CloudCreativity\Modules\Contracts\Application\InboundEventBus\InboundEventMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use Closure;use CloudCreativity\Modules\Contracts\Bus\Middleware\IntegrationEventMiddleware;use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; -final class MyMiddleware implements InboundEventMiddleware +final class MyMiddleware implements IntegrationEventMiddleware { /** * Execute the middleware. diff --git a/docs/guide/application/queries.md b/docs/guide/application/queries.md index 80d39b2c..8f032ec1 100644 --- a/docs/guide/application/queries.md +++ b/docs/guide/application/queries.md @@ -18,8 +18,7 @@ For example: ```php namespace App\Modules\EventManagement\Application\UseCases\Queries\GetAttendeeTickets; -use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Messaging\Query;use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; final readonly class GetAttendeeTicketsQuery implements Query { @@ -54,7 +53,7 @@ final readonly class GetAttendeeTicketsHandler /** * Execute the query. - * + * * @param GetAttendeeTicketsQuery $query * @return Result> */ @@ -106,7 +105,7 @@ We do this by defining an interface in our application's driving ports: ```php namespace App\Modules\EventManagement\Application\Ports\Driving; -use CloudCreativity\Modules\Contracts\Application\Ports\Driving\QueryDispatcher; +use CloudCreativity\Modules\Contracts\Messaging\QueryDispatcher; interface QueryBus extends QueryDispatcher { @@ -118,8 +117,7 @@ And then our implementation is as follows: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\Ports\Driving\QueryBus as Port; -use CloudCreativity\Modules\Application\Bus\QueryDispatcher; +use App\Modules\EventManagement\Application\Ports\Driving\QueryBus as Port;use CloudCreativity\Modules\Bus\QueryDispatcher; final class QueryBus extends QueryDispatcher implements Port { @@ -143,15 +141,7 @@ For example: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\UseCases\Queries\{ - GetAttendeeTickets\GetAttendeeTicketsQuery, - GetAttendeeTickets\GetAttendeeTicketsHandler, -}; -use App\Modules\EventManagement\Application\Ports\Driving\QueryBus as QueryBusPort; -use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies; -use CloudCreativity\Modules\Application\Bus\QueryHandlerContainer; -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; +use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies;use App\Modules\EventManagement\Application\Ports\Driving\QueryBus as QueryBusPort;use App\Modules\EventManagement\Application\UseCases\Queries\{GetAttendeeTickets\GetAttendeeTicketsHandler,GetAttendeeTickets\GetAttendeeTicketsQuery,};use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch;use CloudCreativity\Modules\Bus\QueryHandlerContainer;use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; final class QueryBusProvider { @@ -376,7 +366,7 @@ Use our `LogMessageDispatch` middleware to log the dispatch of a query, and the [PSR Logger](https://php-fig.org/psr/psr-3/). ```php -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; +use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch; $middleware->bind( LogMessageDispatch::class, @@ -401,10 +391,7 @@ following signature: ```php namespace App\Modules\EventManagement\Application\Bus\Middleware; -use Closure; -use CloudCreativity\Modules\Contracts\Application\Bus\QueryMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; -use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; +use Closure;use CloudCreativity\Modules\Contracts\Bus\Middleware\QueryMiddleware;use CloudCreativity\Modules\Contracts\Messaging\Query;use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; final class MyMiddleware implements QueryMiddleware { @@ -443,11 +430,7 @@ instead: ```php namespace App\Modules\EventManagement\Application\Bus\Middleware; -use Closure; -use CloudCreativity\Modules\Contracts\Application\Bus\BusMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; -use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; +use Closure;use CloudCreativity\Modules\Contracts\Bus\Middleware\BusMiddleware;use CloudCreativity\Modules\Contracts\Messaging\Command;use CloudCreativity\Modules\Contracts\Messaging\Query;use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; class MyBusMiddleware implements BusMiddleware { @@ -459,7 +442,7 @@ class MyBusMiddleware implements BusMiddleware * @return Result */ public function __invoke( - Command|Query $message, + Command|Query $message, Closure $next, ): Result { diff --git a/docs/guide/application/units-of-work.md b/docs/guide/application/units-of-work.md index 2aa4c5b5..4f08346c 100644 --- a/docs/guide/application/units-of-work.md +++ b/docs/guide/application/units-of-work.md @@ -125,10 +125,7 @@ Our previous example can be updated to add a unit of work that wraps the command ```php namespace App\Modules\EventManagement\Application\UseCases\Commands\CancelAttendeeTicket; -use App\Modules\EventManagement\Application\Ports\Driven\Persistence\AttendeeRepository; -use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; -use CloudCreativity\Modules\Toolkit\Results\Result; +use App\Modules\EventManagement\Application\Ports\Driven\Persistence\AttendeeRepository;use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork;use CloudCreativity\Modules\Contracts\Bus\DispatchThroughMiddleware;use CloudCreativity\Modules\Toolkit\Results\Result; final readonly class CancelAttendeeTicketHandler implements DispatchThroughMiddleware @@ -151,7 +148,7 @@ final readonly class CancelAttendeeTicketHandler implements return Result::ok(); } - + public function middleware(): array { return [ @@ -176,7 +173,7 @@ interface UnitOfWork * * @param \Closure $callback * @param int $attempts - * @return mixed + * @return mixed */ public function execute(Closure $callback, int $attempts = 1): mixed; } @@ -188,9 +185,7 @@ implementation for Laravel could look like this: ```php namespace App\Modules\Shared\Infrastructure; -use Closure; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\UnitOfWork; -use Illuminate\Database\ConnectionInterface; +use Closure;use CloudCreativity\Modules\Contracts\Application\Ports\UnitOfWork;use Illuminate\Database\ConnectionInterface; final readonly class IlluminateUnitOfWork implements UnitOfWork { @@ -201,7 +196,7 @@ final readonly class IlluminateUnitOfWork implements UnitOfWork public function execute(Closure $callback, int $attempts = 1): mixed { return $this->db->transaction( - static fn () => $callback(), + static fn () => $callback(), $attempts, ); } @@ -245,7 +240,7 @@ allows you to setup and tear down the unit of work manager for each operation. For example, we can use the setup before dispatch middleware on our command bus: ```php -use CloudCreativity\Modules\Application\Bus\Middleware\SetupBeforeDispatch; +use CloudCreativity\Modules\Bus\Middleware\SetupBeforeDispatch; $middleware->bind( SetupBeforeDispatch::class, @@ -405,10 +400,7 @@ Use the `ExecuteInUnitOfWork` middleware to wrap command handlers in a unit of w ```php namespace App\Modules\EventManagement\Application\UseCases\Commands\CancelAttendeeTicket; -use App\Modules\EventManagement\Application\Ports\Driven\Persistence\AttendeeRepository; -use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; -use CloudCreativity\Modules\Toolkit\Results\Result; +use App\Modules\EventManagement\Application\Ports\Driven\Persistence\AttendeeRepository;use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork;use CloudCreativity\Modules\Contracts\Bus\DispatchThroughMiddleware;use CloudCreativity\Modules\Toolkit\Results\Result; final readonly class CancelAttendeeTicketHandler implements DispatchThroughMiddleware @@ -431,7 +423,7 @@ final readonly class CancelAttendeeTicketHandler implements return Result::ok(); } - + public function middleware(): array { return [ @@ -460,11 +452,7 @@ This can be achieved via the `HandleInUnitOfWork` middleware on the inbound even ```php namespace App\Modules\EventManagement\Application\UseCases\InboundEvents; -use App\Modules\EventManagement\Domain\Events\DomainEventDispatcher; -use App\Modules\EventManagement\Domain\Events\SalesAtEventDidChange; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\HandleInUnitOfWork; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; -use VendorName\Ordering\Shared\IntegrationEvents\V1\OrderWasFulfilled; +use App\Modules\EventManagement\Domain\Events\DomainEventDispatcher;use App\Modules\EventManagement\Domain\Events\SalesAtEventDidChange;use CloudCreativity\Modules\Application\InboundEventBus\Middleware\HandleInUnitOfWork;use CloudCreativity\Modules\Contracts\Bus\DispatchThroughMiddleware;use VendorName\Ordering\Shared\IntegrationEvents\V1\OrderWasFulfilled; final readonly class OrderWasFulfilledHandler implements DispatchThroughMiddleware @@ -511,7 +499,7 @@ $unitOfWork = new FakeUnitOfWork(); // execute work that uses the unit of work $this->assertSame( - ['attempt:1', 'rollback:1', 'attempt:2', 'commit:2'], + ['attempt:1', 'rollback:1', 'attempt:2', 'commit:2'], $unitOfWork->sequence, ); -``` \ No newline at end of file +``` diff --git a/docs/guide/infrastructure/dependency-injection.md b/docs/guide/infrastructure/dependency-injection.md index 24919355..e173ee16 100644 --- a/docs/guide/infrastructure/dependency-injection.md +++ b/docs/guide/infrastructure/dependency-injection.md @@ -53,11 +53,11 @@ use Psr\Log\LoggerInterface; interface ExternalDependencies { public function getLogger(): LoggerInterface; - + public function getQueue(): Queue; - + public function getAttendeeRepository(): AttendeeRepository; - + // ...other methods } ``` @@ -68,16 +68,7 @@ creating a command bus: ```php namespace App\Modules\EventManagement\Application\Bus; -use App\Modules\EventManagement\Application\UsesCases\Commands\{ - CancelAttendeeTicket\CancelAttendeeTicketCommand, - CancelAttendeeTicket\CancelAttendeeTicketHandler, -}; -use App\Modules\EventManagement\Application\Ports\Driving\CommandBus as CommandBusPort; -use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies; -use CloudCreativity\Modules\Application\Bus\CommandHandlerContainer; -use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; +use App\Modules\EventManagement\Application\Ports\Driven\DependencyInjection\ExternalDependencies;use App\Modules\EventManagement\Application\Ports\Driving\CommandBus as CommandBusPort;use App\Modules\EventManagement\Application\UsesCases\Commands\{CancelAttendeeTicket\CancelAttendeeTicketCommand,CancelAttendeeTicket\CancelAttendeeTicketHandler,};use CloudCreativity\Modules\Bus\CommandHandlerContainer;use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch;use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; final class CommandBusProvider { @@ -137,9 +128,9 @@ use Psr\Log\LoggerInterface; interface ExternalDependencies { public function getLogger(): LoggerInterface; - + public function getQueue(): Queue; - + public function getRepositories(): RepositoryProvider; } ``` @@ -152,9 +143,9 @@ namespace App\Modules\EventManagement\Application\Ports\Driven\Persistence; interface RepositoryProvider { public function getAttendees(): AttendeeRepository; - + public function getSalesReports(): SalesReportRepository; - + // ...other repositories } ``` @@ -174,4 +165,4 @@ lifetime of that instance - allowing it to set it up and tear it down as needed. This also helps make the external dependencies port _predictable_. If some methods returned singletons and others did not, how does the application layer know what it has been given - a singleton, or a new instance? Also, the application layer would then not be able to tear down any singletons when it knew that they were no longer required, e.g. after -dispatching a command. \ No newline at end of file +dispatching a command. diff --git a/docs/guide/infrastructure/exception-reporting.md b/docs/guide/infrastructure/exception-reporting.md index 0a0f364c..982ade9f 100644 --- a/docs/guide/infrastructure/exception-reporting.md +++ b/docs/guide/infrastructure/exception-reporting.md @@ -93,11 +93,9 @@ implementation looks like this: ```php namespace App\Modules\Shared\Infrastructure\Exceptions; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\ExceptionReporter; -use Illuminate\Contracts\Debug\ExceptionHandler; -use Throwable; +use CloudCreativity\Modules\Contracts\Application\Ports\ExceptionReporter;use Illuminate\Contracts\Debug\ExceptionHandler;use Throwable; -final readonly class ExceptionReporterAdapter implements +final readonly class ExceptionReporterAdapter implements ExceptionReporter { public function __construct(private ExceptionHandler $handler) @@ -136,4 +134,4 @@ $expected = new \LogicException('Boom!'); // do work $this->assertSame($expected, $reporter->sole()); -``` \ No newline at end of file +``` diff --git a/docs/guide/infrastructure/outbox.md b/docs/guide/infrastructure/outbox.md index bf865ce8..e33ec21f 100644 --- a/docs/guide/infrastructure/outbox.md +++ b/docs/guide/infrastructure/outbox.md @@ -62,7 +62,7 @@ Our recommended approach is to first place these events into an outbox. This mea ```php namespace App\Modules\EventManagement\Application\Ports\Driven\OutboundEvents; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; interface Outbox { @@ -70,7 +70,7 @@ interface Outbox * Push the event into the outbox. * * @param IntegrationEvent $event - * @return void + * @return void */ public function push(IntegrationEvent $event): void; } @@ -126,7 +126,7 @@ port `Queue` - as suggested by the [Queues chapter](./queues) - call it `Outbox` ```php namespace App\Modules\EventManagement\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue; interface Outbox extends Queue { @@ -152,4 +152,4 @@ What about microservices in your own architecture? Prefer loose coupling over di integration events published via an outbox. Alternatively, if you want to directly call the microservice, ask yourself whether this definitely needs to be -immediate? If not immediate, push the work to a queued command and leverage the queuing outbox approach described above. \ No newline at end of file +immediate? If not immediate, push the work to a queued command and leverage the queuing outbox approach described above. diff --git a/docs/guide/infrastructure/publishing-events.md b/docs/guide/infrastructure/publishing-events.md index 7be9d734..83d85368 100644 --- a/docs/guide/infrastructure/publishing-events.md +++ b/docs/guide/infrastructure/publishing-events.md @@ -16,7 +16,7 @@ The following is an example port: ```php namespace App\Modules\EventManagement\Application\Ports\Driven\OutboundEventBus; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\OutboundEventPublisher; +use CloudCreativity\Modules\Contracts\Application\Ports\OutboundEventPublisher; interface OutboundEventBus extends OutboundEventPublisher { @@ -61,14 +61,7 @@ specific closures to specific events, and add middleware to the publisher. Here' ```php namespace App\Modules\EventManagement\Infrastructure\OutboundEventBus; -use App\Modules\EventManagement\Application\Ports\Driven\OutboundEventBus\OutboundEventBus; -use App\Modules\EventManagement\Infrastructure\GooglePubSub\EventSerializer; -use App\Modules\EventManagement\Infrastructure\GooglePubSub\SecureTopicFactory; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; -use CloudCreativity\Modules\Infrastructure\OutboundEventBus\Middleware\LogOutboundEvent; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; -use Psr\Log\LoggerInterface; -use VendorName\EventManagement\Shared\IntegrationEvents\V1\AttendeeTicketWasCancelled; +use App\Modules\EventManagement\Application\Ports\Driven\OutboundEventBus\OutboundEventBus;use App\Modules\EventManagement\Infrastructure\GooglePubSub\EventSerializer;use App\Modules\EventManagement\Infrastructure\GooglePubSub\SecureTopicFactory;use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent;use CloudCreativity\Modules\Infrastructure\OutboundEventBus\Middleware\LogOutboundEvent;use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer;use Psr\Log\LoggerInterface;use VendorName\EventManagement\Shared\IntegrationEvents\V1\AttendeeTicketWasCancelled; final readonly class OutboundEventBusAdapterProvider { @@ -90,7 +83,7 @@ final readonly class OutboundEventBusAdapterProvider }, middleware: $middleware = new PipeContainer(), ); - + /** Bind handlers for specific events (if needed) */ $publisher->bind( AttendeeTicketWasCancelled::class, @@ -226,7 +219,7 @@ final readonly class OutboundEventBusAdapterProvider ), middleware: $middleware = new PipeContainer(), ); - + /** Bind handlers for specific events (if needed) */ $handlers->bind( AttendeeTicketWasCancelled::class, @@ -262,7 +255,7 @@ implement the following interface that was extended by the driven port: ```php namespace CloudCreativity\Modules\Application\Ports\Driven\OutboundEventBus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; interface EventPublisher { @@ -320,9 +313,7 @@ following signature: ```php namespace App\Modules\EventManagement\Application\Adapters\Middleware; -use Closure; -use CloudCreativity\Modules\Contracts\Infrastructure\OutboundEventBus\OutboundEventMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use Closure;use CloudCreativity\Modules\Contracts\Infrastructure\OutboundEventBus\OutboundEventMiddleware;use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; final class MyMiddleware implements OutboundEventMiddleware { @@ -376,4 +367,4 @@ If you expect exactly one integration event to be published, use the `sole()` he $expected = new SomeIntegrationEvent(); $this->assertEquals($expected, $publisher->sole()); -``` \ No newline at end of file +``` diff --git a/docs/guide/infrastructure/queues.md b/docs/guide/infrastructure/queues.md index 4624fc52..d1bcaa43 100644 --- a/docs/guide/infrastructure/queues.md +++ b/docs/guide/infrastructure/queues.md @@ -2,7 +2,7 @@ As described in the [Asynchronous Processing chapter](../application/asynchronous-processing), your application layer can allow commands to be queued via a command queuer driving port. Additionally, it may also choose to implement some -internal processes as internal commands that are executed asynchronously. +internal processes as internal commands that are executed asynchronously. To do either (or both!), you need to define a queue driven port. The adapter implementation then handles pushing commands onto a queue, and dispatching the command when it is pulled from the queue. @@ -19,14 +19,14 @@ We do this by defining an interface in our application's driven ports: ```php namespace App\Modules\EventManagement\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue as Port; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue as Port; interface Queue extends Port { } ``` -If you have a command queuer driving port, you will need to inject your queue adapter into the command queuer. See the [command queuer documentation](../application/commands.md#command-queuer) for examples. +If you have a command queuer driving port, you will need to inject your queue adapter into the command queuer. See the [command queuer documentation](../application/commands.md#command-queuer) for examples. This allows the presentation and delivery layer to asynchronously dispatch commands. When pulling commands from the queue, your queue adapter will need to dispatch the command to the command bus. @@ -46,7 +46,7 @@ In this scenario, define another driven port: ```php namespace App\Modules\EventManagement\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue as Port; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue as Port; interface InternalQueue extends Port { @@ -79,10 +79,7 @@ Then you can create the adapter by providing it with the default closure for que ```php namespace App\Modules\EventManagement\Infrastructure\Queue; -use App\Modules\EventManagement\Application\Ports\Driven\Queue\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Infrastructure\Queue\Middleware\LogPushedToQueue; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; +use App\Modules\EventManagement\Application\Ports\Driven\Queue\Queue;use CloudCreativity\Modules\Contracts\Messaging\Command;use CloudCreativity\Modules\Infrastructure\Queue\Middleware\LogPushedToQueue;use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; final class QueueAdapterProvider { @@ -95,7 +92,7 @@ final class QueueAdapterProvider { $adapter = new QueueAdapter( fn: function (Command $command): void { - DispatchCommandJob::dispatch($command); + DispatchCommandJob::dispatch($command); }, middleware: $middleware = new PipeContainer(), ); @@ -104,9 +101,9 @@ final class QueueAdapterProvider LogPushedToQueue::class, fn () => new LogPushedToQueue($this->logger), ); - + $queue->through([LogPushedToQueue::class]); - + return $adapter; } } @@ -121,7 +118,7 @@ This default closure will be used for all commands, unless you register closures ```php $queue = new QueueAdapter( fn: function (Command $command): void { - DispatchCommandJob::dispatch($command); + DispatchCommandJob::dispatch($command); }, ); @@ -129,7 +126,7 @@ $queue->bind( RecalculateSalesAtEventCommand::class, function (RecalculateSalesAtEventCommand $command): void { DispatchCommandJob::dispatch($command) - ->onQueue('reporting'); + ->onQueue('reporting'); }, ); ``` @@ -186,9 +183,9 @@ final class QueueAdapterProvider LogPushedToQueue::class, fn () => new LogPushedToQueue($this->logger), ); - + $queue->through([LogPushedToQueue::class]); - + return $adapter; } } @@ -220,7 +217,7 @@ example: ```php namespace App\Modules\EventManagement\Infrastructure\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; final class DefaultEnqueuer { @@ -247,7 +244,7 @@ implements the port interface that is extended in your application layer: ```php namespace CloudCreativity\Modules\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; interface Queue { @@ -282,29 +279,23 @@ For example, a default Laravel job for queuing and dispatching commands would be ```php namespace App\Modules\EventManagement\Infrastructure\Queue; -use App\Modules\EventManagement\Application\Ports\Driving\CommandBus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Toolkit\Result\FailedResultException; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; -use Illuminate\Queue\InteractsWithQueue; +use App\Modules\EventManagement\Application\Ports\Driving\CommandBus;use CloudCreativity\Modules\Contracts\Messaging\Command;use CloudCreativity\Modules\Toolkit\Result\FailedResultException;use Illuminate\Bus\Queueable;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Foundation\Bus\Dispatchable;use Illuminate\Queue\InteractsWithQueue; class DispatchCommandJob implements ShouldQueue { use Dispatchable; use InteractsWithQueue; use Queueable; - + public function __construct( public readonly Command $command ) { } - + public function handle(CommandBus $bus): void { $result = $bus->dispatch($this->command); - + if ($result->didFail()) { throw new FailedResultException($result); } @@ -340,27 +331,27 @@ class QueueRecalculateSalesAtEventJob implements ShouldQueue use Dispatchable; use InteractsWithQueue; use Queueable; - + public function __construct( public readonly RecalculateSalesAtEventCommand $command ) { } - + public function handle(CommandBus $bus): void { $result = $bus->dispatch($this->command); $errors = $result->errors(); - + if ($errors->contains(ErrorCodeEnum::TemporaryFailure)) { $this->release(now()->addSeconds(30)); return; } - + if ($result->didFail()) { throw new FailedResultException($result); } } - + public function middleware(): array { return [ @@ -390,7 +381,7 @@ example, to create the queue that is injected into our command bus: // default command queuing $queue = new QueueAdapter( fn: function (Command $command): void { - DispatchCommandJob::dispatch($command); + DispatchCommandJob::dispatch($command); }, ); @@ -463,9 +454,7 @@ following signature: ```php namespace App\Modules\Shared\Infrastructure\Queue\Middleware; -use Closure; -use CloudCreativity\Modules\Contracts\Infrastructure\Queue\QueueMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use Closure;use CloudCreativity\Modules\Contracts\Infrastructure\Queue\QueueMiddleware;use CloudCreativity\Modules\Contracts\Messaging\Command; final class MyQueueMiddleware implements QueueMiddleware { @@ -477,7 +466,7 @@ final class MyQueueMiddleware implements QueueMiddleware * @return void */ public function __invoke( - Command $command, + Command $command, Closure $next, ): void { @@ -519,4 +508,4 @@ If you expect exactly one command to be queued, use the `sole()` helper: $expected = new SomeCommand(); $this->assertEquals($expected, $queue->sole()); -``` \ No newline at end of file +``` diff --git a/src/Application/Bus/Exceptions/AbortOnFailureException.php b/src/Application/Bus/AbortOnFailureException.php similarity index 85% rename from src/Application/Bus/Exceptions/AbortOnFailureException.php rename to src/Application/Bus/AbortOnFailureException.php index 78f0bdcd..9e8d89db 100644 --- a/src/Application/Bus/Exceptions/AbortOnFailureException.php +++ b/src/Application/Bus/AbortOnFailureException.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus\Exceptions; +namespace CloudCreativity\Modules\Application\Bus; use CloudCreativity\Modules\Toolkit\Result\FailedResultException; diff --git a/src/Application/Bus/CommandQueuer.php b/src/Application/Bus/CommandQueuer.php index ad439118..243e890d 100644 --- a/src/Application/Bus/CommandQueuer.php +++ b/src/Application/Bus/CommandQueuer.php @@ -12,9 +12,9 @@ namespace CloudCreativity\Modules\Application\Bus; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Contracts\Application\Ports\Driving\CommandQueuer as ICommandQueuer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue; +use CloudCreativity\Modules\Contracts\Bus\CommandQueuer as ICommandQueuer; +use CloudCreativity\Modules\Contracts\Messaging\Command; class CommandQueuer implements ICommandQueuer { diff --git a/src/Application/Bus/Middleware/ExecuteInUnitOfWork.php b/src/Application/Bus/Middleware/ExecuteInUnitOfWork.php index eed9ee94..e57ff90d 100644 --- a/src/Application/Bus/Middleware/ExecuteInUnitOfWork.php +++ b/src/Application/Bus/Middleware/ExecuteInUnitOfWork.php @@ -13,13 +13,13 @@ namespace CloudCreativity\Modules\Application\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Application\Bus\Exceptions\AbortOnFailureException; -use CloudCreativity\Modules\Contracts\Application\Bus\CommandMiddleware; +use CloudCreativity\Modules\Application\Bus\AbortOnFailureException; use CloudCreativity\Modules\Contracts\Application\UnitOfWork\UnitOfWorkManager; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Bus\Middleware\BusMiddleware; +use CloudCreativity\Modules\Contracts\Messaging\Message; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; -final readonly class ExecuteInUnitOfWork implements CommandMiddleware +final readonly class ExecuteInUnitOfWork implements BusMiddleware { /** * @param int<1, max> $attempts @@ -30,13 +30,16 @@ public function __construct( ) { } - public function __invoke(Command $command, Closure $next): Result + public function __invoke(Message $message, Closure $next): ?Result { try { return $this->unitOfWorkManager->execute( - static function () use ($command, $next): Result { - $res = $next($command); - return $res->didSucceed() ? $res : throw new AbortOnFailureException($res); + static function () use ($message, $next): ?Result { + $res = $next($message); + if ($res?->didFail()) { + throw new AbortOnFailureException($res); + } + return $res; }, $this->attempts, ); diff --git a/src/Application/Bus/Middleware/FlushDeferredEvents.php b/src/Application/Bus/Middleware/FlushDeferredEvents.php index f63ae9b9..2f853444 100644 --- a/src/Application/Bus/Middleware/FlushDeferredEvents.php +++ b/src/Application/Bus/Middleware/FlushDeferredEvents.php @@ -13,31 +13,31 @@ namespace CloudCreativity\Modules\Application\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Application\Bus\CommandMiddleware; use CloudCreativity\Modules\Contracts\Application\DomainEventDispatching\DeferredDispatcher; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Bus\Middleware\BusMiddleware; +use CloudCreativity\Modules\Contracts\Messaging\Message; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; use Throwable; -final readonly class FlushDeferredEvents implements CommandMiddleware +final readonly class FlushDeferredEvents implements BusMiddleware { public function __construct(private DeferredDispatcher $dispatcher) { } - public function __invoke(Command $command, Closure $next): Result + public function __invoke(Message $message, Closure $next): ?Result { try { - $result = $next($command); + $result = $next($message); } catch (Throwable $ex) { $this->dispatcher->forget(); throw $ex; } - if ($result->didSucceed()) { - $this->dispatcher->flush(); - } else { + if ($result?->didFail()) { $this->dispatcher->forget(); + } else { + $this->dispatcher->flush(); } return $result; diff --git a/src/Application/Bus/Middleware/ValidateCommand.php b/src/Application/Bus/Middleware/ValidateCommand.php deleted file mode 100644 index 08187877..00000000 --- a/src/Application/Bus/Middleware/ValidateCommand.php +++ /dev/null @@ -1,54 +0,0 @@ - - */ - abstract protected function rules(): iterable; - - public function __construct(private readonly Validator $validator) - { - } - - public function __invoke(Command $command, Closure $next): IResult - { - $errors = $this->validator - ->using($this->rules()) - ->stopOnFirstFailure($this->stopOnFirstFailure($command)) - ->validate($command); - - if ($errors->isNotEmpty()) { - return Result::failed($errors); - } - - return $next($command); - } - - protected function stopOnFirstFailure(Command $command): bool - { - return $this instanceof Bail; - } -} diff --git a/src/Application/Bus/Middleware/ValidateQuery.php b/src/Application/Bus/Middleware/ValidateQuery.php deleted file mode 100644 index 1b3d3bd3..00000000 --- a/src/Application/Bus/Middleware/ValidateQuery.php +++ /dev/null @@ -1,54 +0,0 @@ - - */ - abstract protected function rules(): iterable; - - public function __construct(private readonly Validator $validator) - { - } - - public function __invoke(Query $query, Closure $next): IResult - { - $errors = $this->validator - ->using($this->rules()) - ->stopOnFirstFailure($this->stopOnFirstFailure($query)) - ->validate($query); - - if ($errors->isNotEmpty()) { - return Result::failed($errors); - } - - return $next($query); - } - - protected function stopOnFirstFailure(Query $query): bool - { - return $this instanceof Bail; - } -} diff --git a/src/Application/DomainEventDispatching/Dispatcher.php b/src/Application/DomainEventDispatching/Dispatcher.php index 1007db3e..f74ce6f3 100644 --- a/src/Application/DomainEventDispatching/Dispatcher.php +++ b/src/Application/DomainEventDispatching/Dispatcher.php @@ -13,12 +13,12 @@ namespace CloudCreativity\Modules\Application\DomainEventDispatching; use Closure; +use CloudCreativity\Modules\Bus\PsrPipeContainer; use CloudCreativity\Modules\Contracts\Application\DomainEventDispatching\ListenerContainer as IListenerContainer; use CloudCreativity\Modules\Contracts\Domain\Events\DomainEvent; use CloudCreativity\Modules\Contracts\Domain\Events\DomainEventDispatcher; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\MiddlewareProcessor; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\PipelineBuilder; use CloudCreativity\Modules\Toolkit\Pipeline\Through; use Generator; @@ -51,7 +51,7 @@ public function __construct( $listeners; $this->middleware = $middleware === null && $listeners instanceof ContainerInterface ? - new PipeContainer($listeners) : + new PsrPipeContainer($listeners) : $middleware; $this->autowire(); diff --git a/src/Application/InboundEventBus/Middleware/FlushDeferredEvents.php b/src/Application/InboundEventBus/Middleware/FlushDeferredEvents.php deleted file mode 100644 index f2bb526a..00000000 --- a/src/Application/InboundEventBus/Middleware/FlushDeferredEvents.php +++ /dev/null @@ -1,38 +0,0 @@ -dispatcher->forget(); - throw $ex; - } - - $this->dispatcher->flush(); - } -} diff --git a/src/Application/InboundEventBus/Middleware/HandleInUnitOfWork.php b/src/Application/InboundEventBus/Middleware/HandleInUnitOfWork.php deleted file mode 100644 index ecd455c8..00000000 --- a/src/Application/InboundEventBus/Middleware/HandleInUnitOfWork.php +++ /dev/null @@ -1,40 +0,0 @@ - $attempts - */ - public function __construct( - private UnitOfWorkManager $unitOfWorkManager, - private int $attempts = 1, - ) { - } - - public function __invoke(IntegrationEvent $event, Closure $next): void - { - $this->unitOfWorkManager->execute( - static function () use ($event, $next): void { - $next($event); - }, - $this->attempts, - ); - } -} diff --git a/src/Application/InboundEventBus/Middleware/LogInboundEvent.php b/src/Application/InboundEventBus/Middleware/LogInboundEvent.php deleted file mode 100644 index fbf7b210..00000000 --- a/src/Application/InboundEventBus/Middleware/LogInboundEvent.php +++ /dev/null @@ -1,48 +0,0 @@ -toString() ?? $event::class; - - $this->log->log( - $this->publishLevel, - "Receiving integration event {$name}.", - $context = ['event' => $this->context->make($event)], - ); - - $next($event); - - $this->log->log($this->publishedLevel, "Received integration event {$name}.", $context); - } -} diff --git a/src/Application/UnitOfWork/UnitOfWorkManager.php b/src/Application/UnitOfWork/UnitOfWorkManager.php index 0e02207d..69e6a784 100644 --- a/src/Application/UnitOfWork/UnitOfWorkManager.php +++ b/src/Application/UnitOfWork/UnitOfWorkManager.php @@ -14,8 +14,8 @@ use Closure; use CloudCreativity\Modules\Application\ApplicationException; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\ExceptionReporter; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\UnitOfWork; +use CloudCreativity\Modules\Contracts\Application\Ports\ExceptionReporter; +use CloudCreativity\Modules\Contracts\Application\Ports\UnitOfWork; use CloudCreativity\Modules\Contracts\Application\UnitOfWork\UnitOfWorkManager as IUnitOfWorkManager; use Throwable; diff --git a/src/Contracts/Toolkit/Loggable/ContextProvider.php b/src/Bus/BusException.php similarity index 53% rename from src/Contracts/Toolkit/Loggable/ContextProvider.php rename to src/Bus/BusException.php index b7e680ca..b991db6d 100644 --- a/src/Contracts/Toolkit/Loggable/ContextProvider.php +++ b/src/Bus/BusException.php @@ -10,14 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Toolkit\Loggable; +namespace CloudCreativity\Modules\Bus; -interface ContextProvider +use RuntimeException; + +class BusException extends RuntimeException { - /** - * Get log context. - * - * @return array - */ - public function context(): array; } diff --git a/src/Application/Bus/CommandDispatcher.php b/src/Bus/CommandDispatcher.php similarity index 88% rename from src/Application/Bus/CommandDispatcher.php rename to src/Bus/CommandDispatcher.php index 3f0a4183..76a698d6 100644 --- a/src/Application/Bus/CommandDispatcher.php +++ b/src/Bus/CommandDispatcher.php @@ -10,15 +10,14 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus; -use CloudCreativity\Modules\Contracts\Application\Bus\CommandHandlerContainer as ICommandHandlerContainer; -use CloudCreativity\Modules\Contracts\Application\Ports\Driving\CommandDispatcher as ICommandDispatcher; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Bus\CommandHandlerContainer as ICommandHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\Command; +use CloudCreativity\Modules\Contracts\Messaging\CommandDispatcher as ICommandDispatcher; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; use CloudCreativity\Modules\Toolkit\Pipeline\MiddlewareProcessor; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\PipelineBuilder; use CloudCreativity\Modules\Toolkit\Pipeline\Through; use Psr\Container\ContainerInterface; @@ -44,7 +43,7 @@ public function __construct( $handlers; $this->middleware = $middleware === null && $handlers instanceof ContainerInterface - ? new PipeContainer($handlers) + ? new PsrPipeContainer($handlers) : $middleware; $this->autowire(); diff --git a/src/Application/Bus/CommandHandler.php b/src/Bus/CommandHandler.php similarity index 77% rename from src/Application/Bus/CommandHandler.php rename to src/Bus/CommandHandler.php index a3304f8d..d32b80db 100644 --- a/src/Application/Bus/CommandHandler.php +++ b/src/Bus/CommandHandler.php @@ -10,11 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus; -use CloudCreativity\Modules\Application\Messages\HandlesMessages; -use CloudCreativity\Modules\Contracts\Application\Bus\CommandHandler as ICommandHandler; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Bus\CommandHandler as ICommandHandler; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; final readonly class CommandHandler implements ICommandHandler diff --git a/src/Application/Bus/CommandHandlerContainer.php b/src/Bus/CommandHandlerContainer.php similarity index 76% rename from src/Application/Bus/CommandHandlerContainer.php rename to src/Bus/CommandHandlerContainer.php index 5092eaa7..07ede5be 100644 --- a/src/Application/Bus/CommandHandlerContainer.php +++ b/src/Bus/CommandHandlerContainer.php @@ -10,12 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus; use Closure; -use CloudCreativity\Modules\Application\ApplicationException; -use CloudCreativity\Modules\Contracts\Application\Bus\CommandHandlerContainer as ICommandHandlerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Bus\CommandHandlerContainer as ICommandHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\Command; use Psr\Container\ContainerInterface; final class CommandHandlerContainer implements ICommandHandlerContainer @@ -38,7 +37,7 @@ public function __construct(private readonly ?ContainerInterface $container = nu public function bind(string $commandClass, Closure|string $binding): void { if (is_string($binding) && $this->container === null) { - throw new ApplicationException('Cannot use a string command handler binding without a PSR container.'); + throw new BusException('Cannot use a string command handler binding without a PSR container.'); } $this->bindings[$commandClass] = $binding; @@ -60,6 +59,6 @@ public function get(string $commandClass): CommandHandler return new CommandHandler($instance); } - throw new ApplicationException('No command handler bound for command class: ' . $commandClass); + throw new BusException('No command handler bound for command class: ' . $commandClass); } } diff --git a/src/Application/InboundEventBus/EventHandler.php b/src/Bus/EventHandler.php similarity index 71% rename from src/Application/InboundEventBus/EventHandler.php rename to src/Bus/EventHandler.php index 631599eb..e9739f96 100644 --- a/src/Application/InboundEventBus/EventHandler.php +++ b/src/Bus/EventHandler.php @@ -10,11 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\InboundEventBus; +namespace CloudCreativity\Modules\Bus; -use CloudCreativity\Modules\Application\Messages\HandlesMessages; -use CloudCreativity\Modules\Contracts\Application\InboundEventBus\EventHandler as IEventHandler; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Bus\EventHandler as IEventHandler; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; final readonly class EventHandler implements IEventHandler { diff --git a/src/Application/InboundEventBus/EventHandlerContainer.php b/src/Bus/EventHandlerContainer.php similarity index 77% rename from src/Application/InboundEventBus/EventHandlerContainer.php rename to src/Bus/EventHandlerContainer.php index 1e42276e..29d160de 100644 --- a/src/Application/InboundEventBus/EventHandlerContainer.php +++ b/src/Bus/EventHandlerContainer.php @@ -10,12 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\InboundEventBus; +namespace CloudCreativity\Modules\Bus; use Closure; -use CloudCreativity\Modules\Application\ApplicationException; -use CloudCreativity\Modules\Contracts\Application\InboundEventBus\EventHandlerContainer as IEventHandlerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Bus\EventHandlerContainer as IEventHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use Psr\Container\ContainerInterface; final class EventHandlerContainer implements IEventHandlerContainer @@ -43,7 +42,7 @@ public function __construct( public function bind(string $eventName, Closure|string $binding): void { if (is_string($binding) && $this->container === null) { - throw new ApplicationException('Cannot use a string event handler binding without a PSR container.'); + throw new BusException('Cannot use a string event handler binding without a PSR container.'); } $this->bindings[$eventName] = $binding; @@ -61,7 +60,7 @@ public function withDefault(Closure|string $binding): void return; } - throw new ApplicationException('Default event handler binding is already set.'); + throw new BusException('Default event handler binding is already set.'); } public function get(string $eventName): EventHandler @@ -80,6 +79,6 @@ public function get(string $eventName): EventHandler return new EventHandler($instance); } - throw new ApplicationException('No handler bound for integration event: ' . $eventName); + throw new BusException('No handler bound for integration event: ' . $eventName); } } diff --git a/src/Application/Messages/HandlesMessages.php b/src/Bus/HandlesMessages.php similarity index 84% rename from src/Application/Messages/HandlesMessages.php rename to src/Bus/HandlesMessages.php index 67b3b728..bb12f7c5 100644 --- a/src/Application/Messages/HandlesMessages.php +++ b/src/Bus/HandlesMessages.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Messages; +namespace CloudCreativity\Modules\Bus; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; +use CloudCreativity\Modules\Contracts\Bus\DispatchThroughMiddleware; use CloudCreativity\Modules\Toolkit\Pipeline\Through; use ReflectionClass; diff --git a/src/Application/InboundEventBus/InboundEventDispatcher.php b/src/Bus/InboundEventDispatcher.php similarity index 86% rename from src/Application/InboundEventBus/InboundEventDispatcher.php rename to src/Bus/InboundEventDispatcher.php index 6ea4a825..d0861df9 100644 --- a/src/Application/InboundEventBus/InboundEventDispatcher.php +++ b/src/Bus/InboundEventDispatcher.php @@ -10,14 +10,13 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\InboundEventBus; +namespace CloudCreativity\Modules\Bus; -use CloudCreativity\Modules\Contracts\Application\InboundEventBus\EventHandlerContainer as IEventHandlerContainer; -use CloudCreativity\Modules\Contracts\Application\Ports\Driving\InboundEventDispatcher as IInboundEventDispatcher; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Bus\EventHandlerContainer as IEventHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\InboundEventDispatcher as IInboundEventDispatcher; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\MiddlewareProcessor; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\PipelineBuilder; use CloudCreativity\Modules\Toolkit\Pipeline\Through; use Psr\Container\ContainerInterface; @@ -42,7 +41,7 @@ public function __construct( $handlers; $this->middleware = $middleware === null && $handlers instanceof ContainerInterface ? - new PipeContainer(container: $handlers) : + new PsrPipeContainer(container: $handlers) : $middleware; $this->autowire(); diff --git a/src/Application/Bus/Middleware/LogMessageDispatch.php b/src/Bus/Middleware/LogMessageDispatch.php similarity index 56% rename from src/Application/Bus/Middleware/LogMessageDispatch.php rename to src/Bus/Middleware/LogMessageDispatch.php index 75c34996..469bb8f2 100644 --- a/src/Application/Bus/Middleware/LogMessageDispatch.php +++ b/src/Bus/Middleware/LogMessageDispatch.php @@ -10,15 +10,16 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus\Middleware; +namespace CloudCreativity\Modules\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Application\Bus\BusMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Loggable\ContextFactory; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Bus\SanitizedMessage; +use CloudCreativity\Modules\Contracts\Bus\Middleware\BusMiddleware; +use CloudCreativity\Modules\Contracts\Messaging\Command; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\Message; +use CloudCreativity\Modules\Contracts\Messaging\Query; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; -use CloudCreativity\Modules\Toolkit\Loggable\SimpleContextFactory; use CloudCreativity\Modules\Toolkit\ModuleBasename; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; @@ -29,28 +30,31 @@ public function __construct( private LoggerInterface $logger, private string $dispatchLevel = LogLevel::DEBUG, private string $dispatchedLevel = LogLevel::INFO, - private ContextFactory $context = new SimpleContextFactory(), ) { } - public function __invoke(Command|Query $message, Closure $next): Result + public function __invoke(Message $message, Closure $next): ?Result { $name = ModuleBasename::tryFrom($message)?->toString() ?? $message::class; - $key = ($message instanceof Command) ? 'command' : 'query'; + $key = match (true) { + $message instanceof Command => 'command', + $message instanceof Query => 'query', + $message instanceof IntegrationEvent => 'event', + default => 'message', + }; $this->logger->log( $this->dispatchLevel, "Bus dispatching {$name}.", - [$key => $this->context->make($message)], + [$key => (new SanitizedMessage($message))->context()], ); - /** @var Result $result */ $result = $next($message); $this->logger->log( $this->dispatchedLevel, "Bus dispatched {$name}.", - ['result' => $this->context->make($result)], + $result ? ['result' => $result->context()] : [], ); return $result; diff --git a/src/Application/Bus/Middleware/SetupBeforeDispatch.php b/src/Bus/Middleware/SetupBeforeDispatch.php similarity index 72% rename from src/Application/Bus/Middleware/SetupBeforeDispatch.php rename to src/Bus/Middleware/SetupBeforeDispatch.php index fd45c2fd..13e846be 100644 --- a/src/Application/Bus/Middleware/SetupBeforeDispatch.php +++ b/src/Bus/Middleware/SetupBeforeDispatch.php @@ -10,12 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus\Middleware; +namespace CloudCreativity\Modules\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Application\Bus\BusMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Bus\Middleware\BusMiddleware; +use CloudCreativity\Modules\Contracts\Messaging\Message; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; final readonly class SetupBeforeDispatch implements BusMiddleware @@ -27,7 +26,7 @@ public function __construct(private Closure $callback) { } - public function __invoke(Command|Query $message, Closure $next): Result + public function __invoke(Message $message, Closure $next): ?Result { $tearDown = ($this->callback)(); diff --git a/src/Application/InboundEventBus/Middleware/SetupBeforeEvent.php b/src/Bus/Middleware/SetupBeforeEvent.php similarity index 73% rename from src/Application/InboundEventBus/Middleware/SetupBeforeEvent.php rename to src/Bus/Middleware/SetupBeforeEvent.php index 98ffad83..4a9fc61d 100644 --- a/src/Application/InboundEventBus/Middleware/SetupBeforeEvent.php +++ b/src/Bus/Middleware/SetupBeforeEvent.php @@ -10,13 +10,13 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\InboundEventBus\Middleware; +namespace CloudCreativity\Modules\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Application\InboundEventBus\InboundEventMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Bus\Middleware\IntegrationEventMiddleware; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; -final readonly class SetupBeforeEvent implements InboundEventMiddleware +final readonly class SetupBeforeEvent implements IntegrationEventMiddleware { /** * @param Closure(): ?Closure(): void $callback diff --git a/src/Application/Bus/Middleware/TearDownAfterDispatch.php b/src/Bus/Middleware/TearDownAfterDispatch.php similarity index 65% rename from src/Application/Bus/Middleware/TearDownAfterDispatch.php rename to src/Bus/Middleware/TearDownAfterDispatch.php index 21322773..87a03cf6 100644 --- a/src/Application/Bus/Middleware/TearDownAfterDispatch.php +++ b/src/Bus/Middleware/TearDownAfterDispatch.php @@ -10,12 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus\Middleware; +namespace CloudCreativity\Modules\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Application\Bus\BusMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Bus\Middleware\BusMiddleware; +use CloudCreativity\Modules\Contracts\Messaging\Message; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; final readonly class TearDownAfterDispatch implements BusMiddleware @@ -27,7 +26,7 @@ public function __construct(private Closure $callback) { } - public function __invoke(Command|Query $message, Closure $next): Result + public function __invoke(Message $message, Closure $next): ?Result { try { return $next($message); diff --git a/src/Application/InboundEventBus/Middleware/TearDownAfterEvent.php b/src/Bus/Middleware/TearDownAfterEvent.php similarity index 64% rename from src/Application/InboundEventBus/Middleware/TearDownAfterEvent.php rename to src/Bus/Middleware/TearDownAfterEvent.php index b93a22af..2defda63 100644 --- a/src/Application/InboundEventBus/Middleware/TearDownAfterEvent.php +++ b/src/Bus/Middleware/TearDownAfterEvent.php @@ -10,13 +10,13 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\InboundEventBus\Middleware; +namespace CloudCreativity\Modules\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Application\InboundEventBus\InboundEventMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Bus\Middleware\IntegrationEventMiddleware; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; -final readonly class TearDownAfterEvent implements InboundEventMiddleware +final readonly class TearDownAfterEvent implements IntegrationEventMiddleware { /** * @param Closure(): void $callback diff --git a/src/Bus/Middleware/ValidateMessage.php b/src/Bus/Middleware/ValidateMessage.php new file mode 100644 index 00000000..0e4f162b --- /dev/null +++ b/src/Bus/Middleware/ValidateMessage.php @@ -0,0 +1,63 @@ +validator + ->using($this->rules()) + ->stopOnFirstFailure($this->stopOnFirstFailure($message)) + ->validate($message); + + if ($errors->isNotEmpty()) { + return Result::failed($errors); + } + + return $next($message); + } + + /** + * Get the rules for the validation. + * + * @return iterable + */ + protected function rules(): iterable + { + $reflection = new ReflectionClass($this); + + foreach ($reflection->getAttributes(WithRules::class) as $attribute) { + yield from $attribute->newInstance()->rules; + } + } + + protected function stopOnFirstFailure(Message $message): bool + { + return $this instanceof Bail; + } +} diff --git a/src/Bus/PsrPipeContainer.php b/src/Bus/PsrPipeContainer.php new file mode 100644 index 00000000..72d0b961 --- /dev/null +++ b/src/Bus/PsrPipeContainer.php @@ -0,0 +1,56 @@ + + */ + private array $pipes = []; + + public function __construct(private readonly ?ContainerInterface $container = null) + { + } + + /** + * Bind a pipe into the container. + */ + public function bind(string $pipeName, Closure $factory): void + { + $this->pipes[$pipeName] = $factory; + } + + public function get(string $pipeName): callable + { + $factory = $this->pipes[$pipeName] ?? null; + + if (is_callable($factory)) { + $pipe = $factory(); + assert(is_callable($pipe), "Expecting pipe {$pipeName} from factory to be callable."); + return $pipe; + } + + if ($this->container) { + $pipe = $this->container->get($pipeName); + assert(is_callable($pipe), "Expecting pipe {$pipeName} from PSR container to be callable."); + return $pipe; + } + + throw new BusException('Unrecognised pipe name: ' . $pipeName); + } +} diff --git a/src/Application/Bus/QueryDispatcher.php b/src/Bus/QueryDispatcher.php similarity index 88% rename from src/Application/Bus/QueryDispatcher.php rename to src/Bus/QueryDispatcher.php index bdaced40..5ee1b95b 100644 --- a/src/Application/Bus/QueryDispatcher.php +++ b/src/Bus/QueryDispatcher.php @@ -10,15 +10,14 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus; -use CloudCreativity\Modules\Contracts\Application\Bus\QueryHandlerContainer as IQueryHandlerContainer; -use CloudCreativity\Modules\Contracts\Application\Ports\Driving\QueryDispatcher as IQueryDispatcher; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Bus\QueryHandlerContainer as IQueryHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\Query; +use CloudCreativity\Modules\Contracts\Messaging\QueryDispatcher as IQueryDispatcher; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; use CloudCreativity\Modules\Toolkit\Pipeline\MiddlewareProcessor; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\PipelineBuilder; use CloudCreativity\Modules\Toolkit\Pipeline\Through; use Psr\Container\ContainerInterface; @@ -44,7 +43,7 @@ public function __construct( $handlers; $this->middleware = $middleware === null && $handlers instanceof ContainerInterface - ? new PipeContainer($handlers) + ? new PsrPipeContainer($handlers) : $middleware; $this->autowire(); diff --git a/src/Application/Bus/QueryHandler.php b/src/Bus/QueryHandler.php similarity index 77% rename from src/Application/Bus/QueryHandler.php rename to src/Bus/QueryHandler.php index 1b41fe56..ea27c167 100644 --- a/src/Application/Bus/QueryHandler.php +++ b/src/Bus/QueryHandler.php @@ -10,11 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus; -use CloudCreativity\Modules\Application\Messages\HandlesMessages; -use CloudCreativity\Modules\Contracts\Application\Bus\QueryHandler as IQueryHandler; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Bus\QueryHandler as IQueryHandler; +use CloudCreativity\Modules\Contracts\Messaging\Query; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; final readonly class QueryHandler implements IQueryHandler diff --git a/src/Application/Bus/QueryHandlerContainer.php b/src/Bus/QueryHandlerContainer.php similarity index 76% rename from src/Application/Bus/QueryHandlerContainer.php rename to src/Bus/QueryHandlerContainer.php index 36231f7f..3a10fa7d 100644 --- a/src/Application/Bus/QueryHandlerContainer.php +++ b/src/Bus/QueryHandlerContainer.php @@ -10,12 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus; use Closure; -use CloudCreativity\Modules\Application\ApplicationException; -use CloudCreativity\Modules\Contracts\Application\Bus\QueryHandlerContainer as IQueryHandlerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Bus\QueryHandlerContainer as IQueryHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\Query; use Psr\Container\ContainerInterface; final class QueryHandlerContainer implements IQueryHandlerContainer @@ -38,7 +37,7 @@ public function __construct(private readonly ?ContainerInterface $container = nu public function bind(string $queryClass, Closure|string $binding): void { if (is_string($binding) && !$this->container) { - throw new ApplicationException('Cannot use a string query handler binding without a PSR container.'); + throw new BusException('Cannot use a string query handler binding without a PSR container.'); } $this->bindings[$queryClass] = $binding; @@ -60,6 +59,6 @@ public function get(string $queryClass): QueryHandler return new QueryHandler($instance); } - throw new ApplicationException('No query handler bound for query class: ' . $queryClass); + throw new BusException('No query handler bound for query class: ' . $queryClass); } } diff --git a/src/Bus/SanitizedMessage.php b/src/Bus/SanitizedMessage.php new file mode 100644 index 00000000..14af304f --- /dev/null +++ b/src/Bus/SanitizedMessage.php @@ -0,0 +1,64 @@ + + */ +final readonly class SanitizedMessage implements IteratorAggregate, Contextual +{ + public function __construct(private Message $message) + { + } + + /** + * @return Generator + */ + public function getIterator(): Generator + { + foreach ($this->cursor() as $key) { + yield $key => $this->message->{$key}; + } + } + + /** + * @return array + */ + public function context(): array + { + return iterator_to_array($this); + } + + /** + * @return Generator + */ + private function cursor(): Generator + { + $reflect = new ReflectionClass($this->message); + + foreach ($reflect->getProperties(ReflectionProperty::IS_PUBLIC) as $property) { + $attributes = $property->getAttributes(Sensitive::class); + if (count($attributes) === 0) { + yield $property->getName(); + } + } + } +} diff --git a/src/Application/InboundEventBus/SwallowInboundEvent.php b/src/Bus/SwallowInboundEvent.php similarity index 86% rename from src/Application/InboundEventBus/SwallowInboundEvent.php rename to src/Bus/SwallowInboundEvent.php index 7e171207..858f14ea 100644 --- a/src/Application/InboundEventBus/SwallowInboundEvent.php +++ b/src/Bus/SwallowInboundEvent.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\InboundEventBus; +namespace CloudCreativity\Modules\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Toolkit\ModuleBasename; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; diff --git a/src/Application/Bus/ValidationProcessor.php b/src/Bus/Validation/ValidationProcessor.php similarity index 53% rename from src/Application/Bus/ValidationProcessor.php rename to src/Bus/Validation/ValidationProcessor.php index 2cbbac3e..ab9f9bb6 100644 --- a/src/Application/Bus/ValidationProcessor.php +++ b/src/Bus/Validation/ValidationProcessor.php @@ -10,11 +10,13 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus\Validation; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Bus\BusException; +use CloudCreativity\Modules\Contracts\Messaging\Message; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\Processor; +use CloudCreativity\Modules\Contracts\Toolkit\Result\Error as IError; +use CloudCreativity\Modules\Contracts\Toolkit\Result\ListOfErrors as IListOfErrors; use CloudCreativity\Modules\Toolkit\Result\ListOfErrors; final readonly class ValidationProcessor implements Processor @@ -24,20 +26,24 @@ public function __construct(private bool $stopOnFirstFailure = false) } /** - * @param (callable(Command|Query): ?ListOfErrors) ...$stages + * @param callable(Message): (IError|IListOfErrors|null) ...$stages */ - public function process(mixed $payload, callable ...$stages): ListOfErrors + public function process(mixed $payload, callable ...$stages): IListOfErrors { - assert($payload instanceof Command || $payload instanceof Query); + if (!$payload instanceof Message) { + throw new BusException('Expecting a message to validate.'); + } $errors = new ListOfErrors(); foreach ($stages as $stage) { $result = $stage($payload); - if ($result) { - $errors = $errors->merge($result); - } + $errors = match (true) { + $result instanceof IListOfErrors => $errors->merge($result), + $result instanceof IError => $errors->push($result), + $result === null => $errors, + }; if ($this->stopOnFirstFailure && $errors->isNotEmpty()) { return $errors; diff --git a/src/Application/Bus/Validator.php b/src/Bus/Validation/Validator.php similarity index 71% rename from src/Application/Bus/Validator.php rename to src/Bus/Validation/Validator.php index ee61b566..9cd5b21e 100644 --- a/src/Application/Bus/Validator.php +++ b/src/Bus/Validation/Validator.php @@ -10,19 +10,22 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus\Validation; -use CloudCreativity\Modules\Contracts\Application\Bus\Validator as IValidator; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Bus\PsrPipeContainer; +use CloudCreativity\Modules\Contracts\Bus\Validation\Validator as IValidator; +use CloudCreativity\Modules\Contracts\Messaging\Message; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\Pipeline; use CloudCreativity\Modules\Contracts\Toolkit\Result\ListOfErrors as IListOfErrors; use CloudCreativity\Modules\Toolkit\Pipeline\PipelineBuilder; use CloudCreativity\Modules\Toolkit\Result\ListOfErrors; +use Psr\Container\ContainerInterface; final class Validator implements IValidator { + private readonly ?PipeContainer $rules; + /** * @var iterable */ @@ -30,8 +33,11 @@ final class Validator implements IValidator private bool $stopOnFirstFailure = false; - public function __construct(private readonly ?PipeContainer $rules = null) + public function __construct(ContainerInterface|PipeContainer|null $rules = null) { + $this->rules = $rules instanceof ContainerInterface + ? new PsrPipeContainer($rules) + : $rules; } public function using(iterable $rules): static @@ -48,7 +54,7 @@ public function stopOnFirstFailure(bool $stop = true): static return $this; } - public function validate(Command|Query $message): IListOfErrors + public function validate(Message $message): IListOfErrors { $errors = $this ->getPipeline() diff --git a/src/Bus/Validation/WithRules.php b/src/Bus/Validation/WithRules.php new file mode 100644 index 00000000..078abd0f --- /dev/null +++ b/src/Bus/Validation/WithRules.php @@ -0,0 +1,26 @@ + $rules + */ + public function __construct(public readonly array $rules) + { + } +} diff --git a/src/Application/Bus/WithCommand.php b/src/Bus/WithCommand.php similarity index 82% rename from src/Application/Bus/WithCommand.php rename to src/Bus/WithCommand.php index d689ce49..fc757b64 100644 --- a/src/Application/Bus/WithCommand.php +++ b/src/Bus/WithCommand.php @@ -10,10 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus; use Attribute; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class WithCommand diff --git a/src/Application/InboundEventBus/WithDefault.php b/src/Bus/WithDefault.php similarity index 87% rename from src/Application/InboundEventBus/WithDefault.php rename to src/Bus/WithDefault.php index 2b919754..55d03819 100644 --- a/src/Application/InboundEventBus/WithDefault.php +++ b/src/Bus/WithDefault.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\InboundEventBus; +namespace CloudCreativity\Modules\Bus; use Attribute; diff --git a/src/Application/InboundEventBus/WithEvent.php b/src/Bus/WithEvent.php similarity index 80% rename from src/Application/InboundEventBus/WithEvent.php rename to src/Bus/WithEvent.php index 76f810b9..4ebf8bb6 100644 --- a/src/Application/InboundEventBus/WithEvent.php +++ b/src/Bus/WithEvent.php @@ -10,10 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\InboundEventBus; +namespace CloudCreativity\Modules\Bus; use Attribute; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class WithEvent diff --git a/src/Application/Bus/WithQuery.php b/src/Bus/WithQuery.php similarity index 82% rename from src/Application/Bus/WithQuery.php rename to src/Bus/WithQuery.php index 4dafba1a..3f4a5979 100644 --- a/src/Application/Bus/WithQuery.php +++ b/src/Bus/WithQuery.php @@ -10,10 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Application\Bus; +namespace CloudCreativity\Modules\Bus; use Attribute; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Messaging\Query; #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class WithQuery diff --git a/src/Contracts/Application/Bus/BusMiddleware.php b/src/Contracts/Application/Bus/BusMiddleware.php deleted file mode 100644 index 9daa1e4c..00000000 --- a/src/Contracts/Application/Bus/BusMiddleware.php +++ /dev/null @@ -1,29 +0,0 @@ - $next - * @return Result - */ - public function __invoke(Command|Query $message, Closure $next): Result; -} diff --git a/src/Contracts/Application/Ports/Driven/ExceptionReporter.php b/src/Contracts/Application/Ports/ExceptionReporter.php similarity index 84% rename from src/Contracts/Application/Ports/Driven/ExceptionReporter.php rename to src/Contracts/Application/Ports/ExceptionReporter.php index ade46806..dc623678 100644 --- a/src/Contracts/Application/Ports/Driven/ExceptionReporter.php +++ b/src/Contracts/Application/Ports/ExceptionReporter.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Ports\Driven; +namespace CloudCreativity\Modules\Contracts\Application\Ports; use Throwable; diff --git a/src/Contracts/Application/Ports/Driven/OutboundEventPublisher.php b/src/Contracts/Application/Ports/OutboundEventPublisher.php similarity index 73% rename from src/Contracts/Application/Ports/Driven/OutboundEventPublisher.php rename to src/Contracts/Application/Ports/OutboundEventPublisher.php index e7b62c80..795775ee 100644 --- a/src/Contracts/Application/Ports/Driven/OutboundEventPublisher.php +++ b/src/Contracts/Application/Ports/OutboundEventPublisher.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Ports\Driven; +namespace CloudCreativity\Modules\Contracts\Application\Ports; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; interface OutboundEventPublisher { diff --git a/src/Contracts/Application/Ports/Driven/Queue.php b/src/Contracts/Application/Ports/Queue.php similarity index 73% rename from src/Contracts/Application/Ports/Driven/Queue.php rename to src/Contracts/Application/Ports/Queue.php index 9ab19040..23ddb531 100644 --- a/src/Contracts/Application/Ports/Driven/Queue.php +++ b/src/Contracts/Application/Ports/Queue.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Ports\Driven; +namespace CloudCreativity\Modules\Contracts\Application\Ports; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; interface Queue { diff --git a/src/Contracts/Application/Ports/Driven/UnitOfWork.php b/src/Contracts/Application/Ports/UnitOfWork.php similarity index 88% rename from src/Contracts/Application/Ports/Driven/UnitOfWork.php rename to src/Contracts/Application/Ports/UnitOfWork.php index 7fde9968..df30afe4 100644 --- a/src/Contracts/Application/Ports/Driven/UnitOfWork.php +++ b/src/Contracts/Application/Ports/UnitOfWork.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Ports\Driven; +namespace CloudCreativity\Modules\Contracts\Application\Ports; use Closure; diff --git a/src/Contracts/Application/Bus/CommandHandler.php b/src/Contracts/Bus/CommandHandler.php similarity index 70% rename from src/Contracts/Application/Bus/CommandHandler.php rename to src/Contracts/Bus/CommandHandler.php index 79d68732..76703a20 100644 --- a/src/Contracts/Application/Bus/CommandHandler.php +++ b/src/Contracts/Bus/CommandHandler.php @@ -10,10 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Bus; +namespace CloudCreativity\Modules\Contracts\Bus; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; interface CommandHandler extends DispatchThroughMiddleware diff --git a/src/Contracts/Application/Bus/CommandHandlerContainer.php b/src/Contracts/Bus/CommandHandlerContainer.php similarity index 79% rename from src/Contracts/Application/Bus/CommandHandlerContainer.php rename to src/Contracts/Bus/CommandHandlerContainer.php index a4a4eef2..4d53ae81 100644 --- a/src/Contracts/Application/Bus/CommandHandlerContainer.php +++ b/src/Contracts/Bus/CommandHandlerContainer.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Bus; +namespace CloudCreativity\Modules\Contracts\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; interface CommandHandlerContainer { diff --git a/src/Contracts/Application/Ports/Driving/CommandQueuer.php b/src/Contracts/Bus/CommandQueuer.php similarity index 74% rename from src/Contracts/Application/Ports/Driving/CommandQueuer.php rename to src/Contracts/Bus/CommandQueuer.php index 0ab06b79..39f31498 100644 --- a/src/Contracts/Application/Ports/Driving/CommandQueuer.php +++ b/src/Contracts/Bus/CommandQueuer.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Ports\Driving; +namespace CloudCreativity\Modules\Contracts\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; interface CommandQueuer { diff --git a/src/Contracts/Application/Messages/DispatchThroughMiddleware.php b/src/Contracts/Bus/DispatchThroughMiddleware.php similarity index 86% rename from src/Contracts/Application/Messages/DispatchThroughMiddleware.php rename to src/Contracts/Bus/DispatchThroughMiddleware.php index 1fa9962d..17f6a0b5 100644 --- a/src/Contracts/Application/Messages/DispatchThroughMiddleware.php +++ b/src/Contracts/Bus/DispatchThroughMiddleware.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Messages; +namespace CloudCreativity\Modules\Contracts\Bus; interface DispatchThroughMiddleware { diff --git a/src/Contracts/Application/InboundEventBus/EventHandler.php b/src/Contracts/Bus/EventHandler.php similarity index 64% rename from src/Contracts/Application/InboundEventBus/EventHandler.php rename to src/Contracts/Bus/EventHandler.php index c4f4c041..952f19c3 100644 --- a/src/Contracts/Application/InboundEventBus/EventHandler.php +++ b/src/Contracts/Bus/EventHandler.php @@ -10,10 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\InboundEventBus; +namespace CloudCreativity\Modules\Contracts\Bus; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; interface EventHandler extends DispatchThroughMiddleware { diff --git a/src/Contracts/Application/InboundEventBus/EventHandlerContainer.php b/src/Contracts/Bus/EventHandlerContainer.php similarity index 76% rename from src/Contracts/Application/InboundEventBus/EventHandlerContainer.php rename to src/Contracts/Bus/EventHandlerContainer.php index c551cf03..15d4c53b 100644 --- a/src/Contracts/Application/InboundEventBus/EventHandlerContainer.php +++ b/src/Contracts/Bus/EventHandlerContainer.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\InboundEventBus; +namespace CloudCreativity\Modules\Contracts\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; interface EventHandlerContainer { diff --git a/src/Contracts/Bus/Middleware/BusMiddleware.php b/src/Contracts/Bus/Middleware/BusMiddleware.php new file mode 100644 index 00000000..be70086e --- /dev/null +++ b/src/Contracts/Bus/Middleware/BusMiddleware.php @@ -0,0 +1,28 @@ + $next + * @return Result|null + */ + public function __invoke(Message $message, Closure $next): ?Result; +} diff --git a/src/Contracts/Application/Bus/CommandMiddleware.php b/src/Contracts/Bus/Middleware/CommandMiddleware.php similarity index 66% rename from src/Contracts/Application/Bus/CommandMiddleware.php rename to src/Contracts/Bus/Middleware/CommandMiddleware.php index fe6bb0b7..68cc45c4 100644 --- a/src/Contracts/Application/Bus/CommandMiddleware.php +++ b/src/Contracts/Bus/Middleware/CommandMiddleware.php @@ -10,10 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Bus; +namespace CloudCreativity\Modules\Contracts\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; interface CommandMiddleware @@ -22,7 +22,7 @@ interface CommandMiddleware * Handle the command. * * @param Closure(Command): Result $next - * @return Result + * @return Result|null */ - public function __invoke(Command $command, Closure $next): Result; + public function __invoke(Command $command, Closure $next): ?Result; } diff --git a/src/Contracts/Application/InboundEventBus/InboundEventMiddleware.php b/src/Contracts/Bus/Middleware/IntegrationEventMiddleware.php similarity index 71% rename from src/Contracts/Application/InboundEventBus/InboundEventMiddleware.php rename to src/Contracts/Bus/Middleware/IntegrationEventMiddleware.php index d5141d8b..69cb2f2c 100644 --- a/src/Contracts/Application/InboundEventBus/InboundEventMiddleware.php +++ b/src/Contracts/Bus/Middleware/IntegrationEventMiddleware.php @@ -10,12 +10,12 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\InboundEventBus; +namespace CloudCreativity\Modules\Contracts\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; -interface InboundEventMiddleware +interface IntegrationEventMiddleware { /** * Handle the inbound event. diff --git a/src/Contracts/Application/Bus/QueryMiddleware.php b/src/Contracts/Bus/Middleware/QueryMiddleware.php similarity index 66% rename from src/Contracts/Application/Bus/QueryMiddleware.php rename to src/Contracts/Bus/Middleware/QueryMiddleware.php index fe76b2d4..85e297d4 100644 --- a/src/Contracts/Application/Bus/QueryMiddleware.php +++ b/src/Contracts/Bus/Middleware/QueryMiddleware.php @@ -10,10 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Bus; +namespace CloudCreativity\Modules\Contracts\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Messaging\Query; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; interface QueryMiddleware @@ -22,7 +22,7 @@ interface QueryMiddleware * Handle the query. * * @param Closure(Query): Result $next - * @return Result + * @return Result|null */ - public function __invoke(Query $query, Closure $next): Result; + public function __invoke(Query $query, Closure $next): ?Result; } diff --git a/src/Contracts/Application/Bus/QueryHandler.php b/src/Contracts/Bus/QueryHandler.php similarity index 70% rename from src/Contracts/Application/Bus/QueryHandler.php rename to src/Contracts/Bus/QueryHandler.php index a7f62533..f14230d0 100644 --- a/src/Contracts/Application/Bus/QueryHandler.php +++ b/src/Contracts/Bus/QueryHandler.php @@ -10,10 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Bus; +namespace CloudCreativity\Modules\Contracts\Bus; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Messaging\Query; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; interface QueryHandler extends DispatchThroughMiddleware diff --git a/src/Contracts/Application/Bus/QueryHandlerContainer.php b/src/Contracts/Bus/QueryHandlerContainer.php similarity index 78% rename from src/Contracts/Application/Bus/QueryHandlerContainer.php rename to src/Contracts/Bus/QueryHandlerContainer.php index 76be3b9a..37640261 100644 --- a/src/Contracts/Application/Bus/QueryHandlerContainer.php +++ b/src/Contracts/Bus/QueryHandlerContainer.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Bus; +namespace CloudCreativity\Modules\Contracts\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Messaging\Query; interface QueryHandlerContainer { diff --git a/src/Contracts/Application/Bus/Bail.php b/src/Contracts/Bus/Validation/Bail.php similarity index 80% rename from src/Contracts/Application/Bus/Bail.php rename to src/Contracts/Bus/Validation/Bail.php index b77a81a4..65baf358 100644 --- a/src/Contracts/Application/Bus/Bail.php +++ b/src/Contracts/Bus/Validation/Bail.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Bus; +namespace CloudCreativity\Modules\Contracts\Bus\Validation; interface Bail { diff --git a/src/Contracts/Application/Bus/Validator.php b/src/Contracts/Bus/Validation/Validator.php similarity index 74% rename from src/Contracts/Application/Bus/Validator.php rename to src/Contracts/Bus/Validation/Validator.php index f6bf9c66..78be603c 100644 --- a/src/Contracts/Application/Bus/Validator.php +++ b/src/Contracts/Bus/Validation/Validator.php @@ -10,10 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Contracts\Application\Bus; +namespace CloudCreativity\Modules\Contracts\Bus\Validation; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Messaging\Message; use CloudCreativity\Modules\Contracts\Toolkit\Result\ListOfErrors; interface Validator @@ -36,5 +35,5 @@ public function stopOnFirstFailure(bool $stop = true): static; /** * Validate the provided message. */ - public function validate(Command|Query $message): ListOfErrors; + public function validate(Message $message): ListOfErrors; } diff --git a/src/Contracts/Infrastructure/OutboundEventBus/OutboundEventMiddleware.php b/src/Contracts/Infrastructure/OutboundEventBus/OutboundEventMiddleware.php deleted file mode 100644 index 829514d9..00000000 --- a/src/Contracts/Infrastructure/OutboundEventBus/OutboundEventMiddleware.php +++ /dev/null @@ -1,26 +0,0 @@ - $object - * @return array - */ - public function make(Message|Result $object): array; -} diff --git a/src/Contracts/Toolkit/Result/Result.php b/src/Contracts/Toolkit/Result/Result.php index aa1f54f9..a76f5f43 100644 --- a/src/Contracts/Toolkit/Result/Result.php +++ b/src/Contracts/Toolkit/Result/Result.php @@ -13,6 +13,7 @@ namespace CloudCreativity\Modules\Contracts\Toolkit\Result; use Closure; +use CloudCreativity\Modules\Contracts\Toolkit\Contextual; use CloudCreativity\Modules\Contracts\Toolkit\Result\ListOfErrors as IListOfErrors; use CloudCreativity\Modules\Toolkit\Result\FailedResultException; use CloudCreativity\Modules\Toolkit\Result\Meta; @@ -21,7 +22,7 @@ /** * @template-covariant TValue */ -interface Result +interface Result extends Contextual { /** * Is the result a success? diff --git a/src/Infrastructure/ExceptionReporter/PsrLogExceptionReporter.php b/src/Infrastructure/ExceptionReporter/PsrLogExceptionReporter.php index 39baa2c7..23ce28e1 100644 --- a/src/Infrastructure/ExceptionReporter/PsrLogExceptionReporter.php +++ b/src/Infrastructure/ExceptionReporter/PsrLogExceptionReporter.php @@ -12,8 +12,7 @@ namespace CloudCreativity\Modules\Infrastructure\ExceptionReporter; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\ExceptionReporter; -use CloudCreativity\Modules\Contracts\Toolkit\Loggable\ContextProvider; +use CloudCreativity\Modules\Contracts\Application\Ports\ExceptionReporter; use Psr\Log\LoggerInterface; use Throwable; @@ -36,10 +35,6 @@ public function report(Throwable $ex): void */ private function context(Throwable $ex): array { - if ($ex instanceof ContextProvider) { - return $ex->context(); - } - if (method_exists($ex, 'context')) { $context = $ex->context(); return is_array($context) ? $context : []; diff --git a/src/Infrastructure/Monolog/ContextualProcessor.php b/src/Infrastructure/Monolog/ContextualProcessor.php new file mode 100644 index 00000000..b1e1b090 --- /dev/null +++ b/src/Infrastructure/Monolog/ContextualProcessor.php @@ -0,0 +1,52 @@ +parser = match (true) { + $recursive => new RecursiveParser($sorted, $parser), + default => $parser, + }; + } + + public function __invoke(LogRecord $record): LogRecord + { + $context = $record->context; + + foreach ($context as $key => $value) { + if ($key === 'exception') { + continue; + } + + if ($value instanceof Contextual) { + $value = $value->context(); + } + + $context[$key] = $this->parser ? $this->parser->parse($value) : $value; + } + + return $record->with(context: $context); + } +} diff --git a/src/Infrastructure/Monolog/RecursiveParser.php b/src/Infrastructure/Monolog/RecursiveParser.php new file mode 100644 index 00000000..17ddc697 --- /dev/null +++ b/src/Infrastructure/Monolog/RecursiveParser.php @@ -0,0 +1,49 @@ +parse($value->context()); + } + + if (!is_iterable($value)) { + return $this->innerParser ? $this->innerParser->parse($value) : null; + } + + $parsed = []; + + foreach ($value as $key => $item) { + if (is_string($key) || is_int($key)) { + $parsed[$key] = $this->parse($item); + } + } + + if ($this->sorted) { + ksort($parsed); + } + + return $parsed; + } +} diff --git a/src/Infrastructure/Monolog/ValueParser.php b/src/Infrastructure/Monolog/ValueParser.php new file mode 100644 index 00000000..7f366ad1 --- /dev/null +++ b/src/Infrastructure/Monolog/ValueParser.php @@ -0,0 +1,18 @@ +, Closure> */ @@ -36,8 +39,11 @@ class ClosurePublisher implements OutboundEventPublisher public function __construct( private readonly Closure $fn, - private readonly ContainerInterface|PipeContainer|null $middleware = null, + ContainerInterface|IPipeContainer|null $middleware = null, ) { + $this->middleware = $middleware instanceof ContainerInterface ? + new PsrPipeContainer($middleware) : $middleware; + $this->autowire(); } diff --git a/src/Infrastructure/OutboundEventBus/ComponentPublisher.php b/src/Infrastructure/OutboundEventBus/ComponentPublisher.php index 4a1d3f2d..2bda8ac5 100644 --- a/src/Infrastructure/OutboundEventBus/ComponentPublisher.php +++ b/src/Infrastructure/OutboundEventBus/ComponentPublisher.php @@ -12,12 +12,12 @@ namespace CloudCreativity\Modules\Infrastructure\OutboundEventBus; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\OutboundEventPublisher; +use CloudCreativity\Modules\Bus\PsrPipeContainer; +use CloudCreativity\Modules\Contracts\Application\Ports\OutboundEventPublisher; use CloudCreativity\Modules\Contracts\Infrastructure\OutboundEventBus\PublisherHandlerContainer as IPublisherHandlerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\MiddlewareProcessor; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\PipelineBuilder; use CloudCreativity\Modules\Toolkit\Pipeline\Through; use Psr\Container\ContainerInterface; @@ -43,7 +43,7 @@ public function __construct( $handlers; $this->middleware = $middleware === null && $handlers instanceof ContainerInterface ? - new PipeContainer(container: $handlers) : + new PsrPipeContainer(container: $handlers) : $middleware; $this->autowire(); diff --git a/src/Infrastructure/OutboundEventBus/Middleware/LogOutboundEvent.php b/src/Infrastructure/OutboundEventBus/Middleware/LogOutboundEvent.php index 8aedfbe1..0b274d5d 100644 --- a/src/Infrastructure/OutboundEventBus/Middleware/LogOutboundEvent.php +++ b/src/Infrastructure/OutboundEventBus/Middleware/LogOutboundEvent.php @@ -13,21 +13,19 @@ namespace CloudCreativity\Modules\Infrastructure\OutboundEventBus\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Infrastructure\OutboundEventBus\OutboundEventMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Loggable\ContextFactory; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; -use CloudCreativity\Modules\Toolkit\Loggable\SimpleContextFactory; +use CloudCreativity\Modules\Bus\SanitizedMessage; +use CloudCreativity\Modules\Contracts\Bus\Middleware\IntegrationEventMiddleware; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Toolkit\ModuleBasename; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; -final readonly class LogOutboundEvent implements OutboundEventMiddleware +final readonly class LogOutboundEvent implements IntegrationEventMiddleware { public function __construct( private LoggerInterface $log, private string $publishLevel = LogLevel::DEBUG, private string $publishedLevel = LogLevel::INFO, - private ContextFactory $context = new SimpleContextFactory(), ) { } @@ -38,7 +36,7 @@ public function __invoke(IntegrationEvent $event, Closure $next): void $this->log->log( $this->publishLevel, "Publishing integration event {$name}.", - $context = ['event' => $this->context->make($event)], + $context = ['event' => (new SanitizedMessage($event))->context()], ); $next($event); diff --git a/src/Infrastructure/OutboundEventBus/PublisherHandler.php b/src/Infrastructure/OutboundEventBus/PublisherHandler.php index 47559a2c..6b4c3ede 100644 --- a/src/Infrastructure/OutboundEventBus/PublisherHandler.php +++ b/src/Infrastructure/OutboundEventBus/PublisherHandler.php @@ -13,7 +13,7 @@ namespace CloudCreativity\Modules\Infrastructure\OutboundEventBus; use CloudCreativity\Modules\Contracts\Infrastructure\OutboundEventBus\PublisherHandler as IPublisherHandler; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; final readonly class PublisherHandler implements IPublisherHandler { diff --git a/src/Infrastructure/OutboundEventBus/PublisherHandlerContainer.php b/src/Infrastructure/OutboundEventBus/PublisherHandlerContainer.php index e04b1604..121327a2 100644 --- a/src/Infrastructure/OutboundEventBus/PublisherHandlerContainer.php +++ b/src/Infrastructure/OutboundEventBus/PublisherHandlerContainer.php @@ -13,11 +13,11 @@ namespace CloudCreativity\Modules\Infrastructure\OutboundEventBus; use Closure; -use Psr\Container\ContainerInterface; use CloudCreativity\Modules\Contracts\Infrastructure\OutboundEventBus\{ PublisherHandlerContainer as IPublisherHandlerContainer}; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Infrastructure\InfrastructureException; +use Psr\Container\ContainerInterface; final class PublisherHandlerContainer implements IPublisherHandlerContainer { diff --git a/src/Infrastructure/OutboundEventBus/Publishes.php b/src/Infrastructure/OutboundEventBus/Publishes.php index 77d68c0e..9da352ed 100644 --- a/src/Infrastructure/OutboundEventBus/Publishes.php +++ b/src/Infrastructure/OutboundEventBus/Publishes.php @@ -13,7 +13,7 @@ namespace CloudCreativity\Modules\Infrastructure\OutboundEventBus; use Attribute; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class Publishes diff --git a/src/Infrastructure/Queue/ClosureQueue.php b/src/Infrastructure/Queue/ClosureQueue.php index 45aafff9..d48dee04 100644 --- a/src/Infrastructure/Queue/ClosureQueue.php +++ b/src/Infrastructure/Queue/ClosureQueue.php @@ -13,9 +13,10 @@ namespace CloudCreativity\Modules\Infrastructure\Queue; use Closure; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer; +use CloudCreativity\Modules\Bus\PsrPipeContainer; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue; +use CloudCreativity\Modules\Contracts\Messaging\Command; +use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\MiddlewareProcessor; use CloudCreativity\Modules\Toolkit\Pipeline\PipelineBuilder; use CloudCreativity\Modules\Toolkit\Pipeline\Through; @@ -24,6 +25,8 @@ class ClosureQueue implements Queue { + private readonly ?IPipeContainer $middleware; + /** * @var array, Closure> */ @@ -36,8 +39,11 @@ class ClosureQueue implements Queue public function __construct( private readonly Closure $fn, - private readonly ContainerInterface|PipeContainer|null $middleware = null, + ContainerInterface|IPipeContainer|null $middleware = null, ) { + $this->middleware = $middleware instanceof ContainerInterface ? + new PsrPipeContainer($middleware) : $middleware; + $this->autowire(); } diff --git a/src/Infrastructure/Queue/ComponentQueue.php b/src/Infrastructure/Queue/ComponentQueue.php index 8496f20d..0dbe681b 100644 --- a/src/Infrastructure/Queue/ComponentQueue.php +++ b/src/Infrastructure/Queue/ComponentQueue.php @@ -12,12 +12,12 @@ namespace CloudCreativity\Modules\Infrastructure\Queue; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue; +use CloudCreativity\Modules\Bus\PsrPipeContainer; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue; use CloudCreativity\Modules\Contracts\Infrastructure\Queue\EnqueuerContainer as IEnqueuerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\MiddlewareProcessor; -use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Toolkit\Pipeline\PipelineBuilder; use CloudCreativity\Modules\Toolkit\Pipeline\Through; use Psr\Container\ContainerInterface; @@ -43,7 +43,7 @@ public function __construct( $enqueuers; $this->middleware = $middleware === null && $enqueuers instanceof ContainerInterface - ? new PipeContainer($enqueuers) + ? new PsrPipeContainer($enqueuers) : $middleware; $this->autowire(); diff --git a/src/Infrastructure/Queue/Enqueuer.php b/src/Infrastructure/Queue/Enqueuer.php index eadb40be..48a1f452 100644 --- a/src/Infrastructure/Queue/Enqueuer.php +++ b/src/Infrastructure/Queue/Enqueuer.php @@ -13,7 +13,7 @@ namespace CloudCreativity\Modules\Infrastructure\Queue; use CloudCreativity\Modules\Contracts\Infrastructure\Queue\Enqueuer as IEnqueuer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; final readonly class Enqueuer implements IEnqueuer { diff --git a/src/Infrastructure/Queue/EnqueuerContainer.php b/src/Infrastructure/Queue/EnqueuerContainer.php index 6113e128..023d4012 100644 --- a/src/Infrastructure/Queue/EnqueuerContainer.php +++ b/src/Infrastructure/Queue/EnqueuerContainer.php @@ -14,7 +14,7 @@ use Closure; use CloudCreativity\Modules\Contracts\Infrastructure\Queue\EnqueuerContainer as IEnqueuerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Infrastructure\InfrastructureException; use Psr\Container\ContainerInterface; diff --git a/src/Infrastructure/Queue/Middleware/LogPushedToQueue.php b/src/Infrastructure/Queue/Middleware/LogPushedToQueue.php index 91616cc5..2aa65aa8 100644 --- a/src/Infrastructure/Queue/Middleware/LogPushedToQueue.php +++ b/src/Infrastructure/Queue/Middleware/LogPushedToQueue.php @@ -13,36 +13,36 @@ namespace CloudCreativity\Modules\Infrastructure\Queue\Middleware; use Closure; -use CloudCreativity\Modules\Contracts\Infrastructure\Queue\QueueMiddleware; -use CloudCreativity\Modules\Contracts\Toolkit\Loggable\ContextFactory; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Toolkit\Loggable\SimpleContextFactory; +use CloudCreativity\Modules\Bus\SanitizedMessage; +use CloudCreativity\Modules\Contracts\Bus\Middleware\CommandMiddleware; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Toolkit\ModuleBasename; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; -final readonly class LogPushedToQueue implements QueueMiddleware +final readonly class LogPushedToQueue implements CommandMiddleware { public function __construct( private LoggerInterface $log, private string $queueLevel = LogLevel::DEBUG, private string $queuedLevel = LogLevel::INFO, - private ContextFactory $context = new SimpleContextFactory(), ) { } - public function __invoke(Command $command, Closure $next): void + public function __invoke(Command $command, Closure $next): null { $name = ModuleBasename::tryFrom($command)?->toString() ?? $command::class; $this->log->log( $this->queueLevel, "Queuing command {$name}.", - $context = ['command' => $this->context->make($command)], + $context = ['command' => (new SanitizedMessage($command))->context()], ); $next($command); $this->log->log($this->queuedLevel, "Queued command {$name}.", $context); + + return null; } } diff --git a/src/Infrastructure/Queue/Queues.php b/src/Infrastructure/Queue/Queues.php index 6977fa69..4027be6b 100644 --- a/src/Infrastructure/Queue/Queues.php +++ b/src/Infrastructure/Queue/Queues.php @@ -13,7 +13,7 @@ namespace CloudCreativity\Modules\Infrastructure\Queue; use Attribute; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class Queues diff --git a/src/Testing/FakeContainer.php b/src/Testing/FakeContainer.php index c6af06ff..5cf545e7 100644 --- a/src/Testing/FakeContainer.php +++ b/src/Testing/FakeContainer.php @@ -13,8 +13,8 @@ namespace CloudCreativity\Modules\Testing; use Closure; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\ExceptionReporter; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\UnitOfWork; +use CloudCreativity\Modules\Contracts\Application\Ports\ExceptionReporter; +use CloudCreativity\Modules\Contracts\Application\Ports\UnitOfWork; use Exception; use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; diff --git a/src/Testing/FakeExceptionReporter.php b/src/Testing/FakeExceptionReporter.php index 3ec11516..c04c82f5 100644 --- a/src/Testing/FakeExceptionReporter.php +++ b/src/Testing/FakeExceptionReporter.php @@ -13,7 +13,7 @@ namespace CloudCreativity\Modules\Testing; use ArrayAccess; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\ExceptionReporter; +use CloudCreativity\Modules\Contracts\Application\Ports\ExceptionReporter; use Countable; use Generator; use IteratorAggregate; diff --git a/src/Testing/FakeOutboundEventPublisher.php b/src/Testing/FakeOutboundEventPublisher.php index 85f2e164..b411565c 100644 --- a/src/Testing/FakeOutboundEventPublisher.php +++ b/src/Testing/FakeOutboundEventPublisher.php @@ -13,8 +13,8 @@ namespace CloudCreativity\Modules\Testing; use ArrayAccess; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\OutboundEventPublisher; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Application\Ports\OutboundEventPublisher; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use Countable; use Generator; use IteratorAggregate; diff --git a/src/Testing/FakeQueue.php b/src/Testing/FakeQueue.php index ff24839a..95316f3e 100644 --- a/src/Testing/FakeQueue.php +++ b/src/Testing/FakeQueue.php @@ -13,8 +13,8 @@ namespace CloudCreativity\Modules\Testing; use ArrayAccess; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue; +use CloudCreativity\Modules\Contracts\Messaging\Command; use Countable; use Generator; use IteratorAggregate; diff --git a/src/Testing/FakeUnitOfWork.php b/src/Testing/FakeUnitOfWork.php index f3a6ceb9..b4ac9a4e 100644 --- a/src/Testing/FakeUnitOfWork.php +++ b/src/Testing/FakeUnitOfWork.php @@ -13,7 +13,7 @@ namespace CloudCreativity\Modules\Testing; use Closure; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\UnitOfWork; +use CloudCreativity\Modules\Contracts\Application\Ports\UnitOfWork; use InvalidArgumentException; use RuntimeException; use Throwable; diff --git a/src/Toolkit/Identifiers/Guid.php b/src/Toolkit/Identifiers/Guid.php index db22231b..f6c9886f 100644 --- a/src/Toolkit/Identifiers/Guid.php +++ b/src/Toolkit/Identifiers/Guid.php @@ -18,6 +18,7 @@ use Ramsey\Uuid\Uuid as RamseyUuid; use Ramsey\Uuid\UuidInterface; use UnitEnum; +use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Uuid as IUuid; use function CloudCreativity\Modules\Toolkit\enum_string; @@ -62,7 +63,7 @@ public static function fromString(string|UnitEnum $type, string $id): self /** * Create a GUID for a UUID. */ - public static function fromUuid(string|UnitEnum $type, string|Uuid|UuidInterface $uuid): self + public static function fromUuid(string|UnitEnum $type, IUuid|string|UuidInterface $uuid): self { return new self($type, Uuid::from($uuid)); } @@ -70,10 +71,10 @@ public static function fromUuid(string|UnitEnum $type, string|Uuid|UuidInterface /** * Create a GUID. */ - public static function make(string|UnitEnum $type, int|string|Uuid|UuidInterface $id): self + public static function make(string|UnitEnum $type, int|IUuid|string|UuidInterface $id): self { return match (true) { - $id instanceof Uuid, $id instanceof UuidInterface, is_string($id) && RamseyUuid::isValid($id) + $id instanceof IUuid, $id instanceof UuidInterface, is_string($id) && RamseyUuid::isValid($id) => self::fromUuid($type, $id), is_string($id) => self::fromString($type, $id), is_int($id) => self::fromInteger($type, $id), @@ -82,7 +83,7 @@ public static function make(string|UnitEnum $type, int|string|Uuid|UuidInterface public function __construct( public string|UnitEnum $type, - public IntegerId|StringId|Uuid $id, + public IntegerId|IUuid|StringId $id, ) { Contracts::assert(!empty($this->type), 'Type must be a non-empty string.'); } @@ -129,8 +130,9 @@ public function equals(self $other): bool public function toString(string $glue = ':'): string { $type = enum_string($this->type); + $id = $this->id->toString(); - return "{$type}{$glue}{$this->id->value}"; + return "{$type}{$glue}{$id}"; } public function key(): string diff --git a/src/Toolkit/Identifiers/GuidTypeMap.php b/src/Toolkit/Identifiers/GuidTypeMap.php index c24b3654..293879f5 100644 --- a/src/Toolkit/Identifiers/GuidTypeMap.php +++ b/src/Toolkit/Identifiers/GuidTypeMap.php @@ -12,6 +12,7 @@ namespace CloudCreativity\Modules\Toolkit\Identifiers; +use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Uuid as IUuid; use Ramsey\Uuid\UuidInterface; use UnitEnum; @@ -39,7 +40,7 @@ public function define(string|UnitEnum $alias, string|UnitEnum $type): void /** * Get the GUID for the specified alias and id. */ - public function guidFor(string|UnitEnum $alias, int|string|Uuid|UuidInterface $id): Guid + public function guidFor(string|UnitEnum $alias, int|IUuid|string|UuidInterface $id): Guid { return Guid::make($this->typeFor($alias), $id); } diff --git a/src/Toolkit/Identifiers/IsUuid.php b/src/Toolkit/Identifiers/IsUuid.php index c13f25f3..53ef1089 100644 --- a/src/Toolkit/Identifiers/IsUuid.php +++ b/src/Toolkit/Identifiers/IsUuid.php @@ -13,6 +13,8 @@ namespace CloudCreativity\Modules\Toolkit\Identifiers; use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; +use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Uuid as IUuid; +use Ramsey\Uuid\UuidInterface; trait IsUuid { @@ -35,8 +37,8 @@ public function getBytes(): string public function is(?Identifier $other): bool { - if ($other instanceof self) { - return $this->equals($other); + if ($other instanceof IUuid) { + return $this->value->equals($other->toBase()); } return false; @@ -61,4 +63,9 @@ public function jsonSerialize(): string { return $this->value->toString(); } + + public function toBase(): UuidInterface + { + return $this->value; + } } diff --git a/src/Toolkit/Identifiers/Uuid.php b/src/Toolkit/Identifiers/Uuid.php index ee766d8d..f1c342e1 100644 --- a/src/Toolkit/Identifiers/Uuid.php +++ b/src/Toolkit/Identifiers/Uuid.php @@ -13,13 +13,13 @@ namespace CloudCreativity\Modules\Toolkit\Identifiers; use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; +use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Uuid as IUuid; use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\UuidFactory as IUuidFactory; use CloudCreativity\Modules\Toolkit\ContractException; -use JsonSerializable; use Ramsey\Uuid\Uuid as BaseUuid; use Ramsey\Uuid\UuidInterface as IBaseUuid; -final class Uuid implements Identifier, JsonSerializable +final class Uuid implements IUuid { use IsUuid; @@ -39,7 +39,7 @@ public static function getFactory(): IUuidFactory return self::$factory = new UuidFactory(); } - public static function from(IBaseUuid|Identifier|string|null $value): self + public static function from(IBaseUuid|Identifier|string|null $value): IUuid { $factory = self::getFactory(); @@ -50,10 +50,10 @@ public static function from(IBaseUuid|Identifier|string|null $value): self }; } - public static function tryFrom(IBaseUuid|Identifier|string|null $value): ?self + public static function tryFrom(IBaseUuid|Identifier|string|null $value): ?IUuid { return match(true) { - $value instanceof self => $value, + $value instanceof IUuid => $value, $value instanceof IBaseUuid => self::getFactory()->from($value), is_string($value) && BaseUuid::isValid($value) => self::getFactory()->fromString($value), default => null, @@ -63,7 +63,7 @@ public static function tryFrom(IBaseUuid|Identifier|string|null $value): ?self /** * Generate a random UUID, useful in tests. */ - public static function random(): self + public static function random(): UuidV4 { return self::getFactory()->uuid4(); } @@ -71,7 +71,7 @@ public static function random(): self /** * Create a nil UUID. */ - public static function nil(): self + public static function nil(): IUuid { return self::from(BaseUuid::NIL); } diff --git a/src/Toolkit/Identifiers/UuidFactory.php b/src/Toolkit/Identifiers/UuidFactory.php index b7e590d0..401b2f36 100644 --- a/src/Toolkit/Identifiers/UuidFactory.php +++ b/src/Toolkit/Identifiers/UuidFactory.php @@ -16,12 +16,16 @@ use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\UuidFactory as IUuidFactory; use CloudCreativity\Modules\Toolkit\ContractException; use DateTimeInterface; +use Ramsey\Uuid\Lazy\LazyUuidFromString; +use Ramsey\Uuid\Rfc4122\UuidV4 as BaseUuidV4; +use Ramsey\Uuid\Rfc4122\UuidV7 as BaseUuidV7; use Ramsey\Uuid\Type\Hexadecimal; use Ramsey\Uuid\Type\Integer as IntegerObject; use Ramsey\Uuid\Uuid as BaseUuid; use Ramsey\Uuid\UuidFactoryInterface as BaseUuidFactory; use Ramsey\Uuid\UuidInterface; use RuntimeException; +use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Uuid as IUuid; final readonly class UuidFactory implements IUuidFactory { @@ -32,10 +36,10 @@ public function __construct(?BaseUuidFactory $factory = null) $this->baseFactory = $factory ?? BaseUuid::getFactory(); } - public function from(Identifier|UuidInterface $uuid): Uuid + public function from(Identifier|UuidInterface $uuid): IUuid { return match(true) { - $uuid instanceof Uuid => $uuid, + $uuid instanceof IUuid => $uuid, $uuid instanceof UuidInterface => new Uuid($uuid), default => throw new ContractException( 'Unexpected identifier type, received: ' . get_debug_type($uuid), @@ -84,9 +88,11 @@ public function uuid3(string|UuidInterface $ns, string $name): Uuid return new Uuid($this->baseFactory->uuid3($ns, $name)); } - public function uuid4(): Uuid + public function uuid4(): UuidV4 { - return new Uuid($this->baseFactory->uuid4()); + $base = $this->baseFactory->uuid4(); + assert($base instanceof BaseUuidV4 || $base instanceof LazyUuidFromString); + return new UuidV4($base); } public function uuid5(string|UuidInterface $ns, string $name): Uuid @@ -99,12 +105,12 @@ public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): Uuid return new Uuid($this->baseFactory->uuid6($node, $clockSeq)); } - public function uuid7(?DateTimeInterface $dateTime = null): Uuid + public function uuid7(?DateTimeInterface $dateTime = null): UuidV7 { if (method_exists($this->baseFactory, 'uuid7')) { $base = $this->baseFactory->uuid7($dateTime); - assert($base instanceof UuidInterface); - return new Uuid($base); + assert($base instanceof BaseUuidV7 || $base instanceof LazyUuidFromString); + return new UuidV7($base); } throw new RuntimeException('UUID version 7 is not supported by the underlying factory.'); diff --git a/src/Toolkit/Identifiers/UuidV4.php b/src/Toolkit/Identifiers/UuidV4.php index 1d43ff64..28398c32 100644 --- a/src/Toolkit/Identifiers/UuidV4.php +++ b/src/Toolkit/Identifiers/UuidV4.php @@ -13,23 +13,21 @@ namespace CloudCreativity\Modules\Toolkit\Identifiers; use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; +use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Uuid as IUuid; use CloudCreativity\Modules\Toolkit\ContractException; use CloudCreativity\Modules\Toolkit\Contracts; -use JsonSerializable; use Ramsey\Uuid\Lazy\LazyUuidFromString; use Ramsey\Uuid\Rfc4122\UuidV4 as BaseUuidV4; use Ramsey\Uuid\Uuid as BaseUuid; use Ramsey\Uuid\UuidInterface as IBaseUuid; -final class UuidV4 implements Identifier, JsonSerializable +final class UuidV4 implements IUuid { use IsUuid; public static function make(): self { - $uuid = BaseUuid::getFactory()->uuid4(); - assert($uuid instanceof BaseUuidV4 || $uuid instanceof LazyUuidFromString); - return new self($uuid); + return Uuid::getFactory()->uuid4(); } public static function from(IBaseUuid|Identifier|string|null $value): self @@ -43,7 +41,7 @@ public static function tryFrom(IBaseUuid|Identifier|string|null $value): ?self { $parsed = match (true) { $value instanceof self, $value instanceof IBaseUuid => $value, - $value instanceof Uuid => $value->value, + $value instanceof IUuid => $value->toBase(), is_string($value) && BaseUuid::isValid($value) => BaseUuid::getFactory()->fromString($value), default => null, }; @@ -55,7 +53,7 @@ public static function tryFrom(IBaseUuid|Identifier|string|null $value): ?self }; } - private function __construct(public readonly BaseUuidV4|LazyUuidFromString $value) + public function __construct(public readonly BaseUuidV4|LazyUuidFromString $value) { if ($this->value instanceof LazyUuidFromString) { Contracts::assert($this->value->getVersion() === 4); diff --git a/src/Toolkit/Identifiers/UuidV7.php b/src/Toolkit/Identifiers/UuidV7.php index 9dabc716..ce03fada 100644 --- a/src/Toolkit/Identifiers/UuidV7.php +++ b/src/Toolkit/Identifiers/UuidV7.php @@ -13,24 +13,22 @@ namespace CloudCreativity\Modules\Toolkit\Identifiers; use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; +use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Uuid as IUuid; use CloudCreativity\Modules\Toolkit\ContractException; use CloudCreativity\Modules\Toolkit\Contracts; use DateTimeInterface; -use JsonSerializable; use Ramsey\Uuid\Lazy\LazyUuidFromString; use Ramsey\Uuid\Rfc4122\UuidV7 as BaseUuidV7; use Ramsey\Uuid\Uuid as BaseUuid; use Ramsey\Uuid\UuidInterface as IBaseUuid; -final class UuidV7 implements Identifier, JsonSerializable +final class UuidV7 implements IUuid { use IsUuid; public static function make(?DateTimeInterface $date = null): self { - $uuid = BaseUuid::uuid7($date); - assert($uuid instanceof BaseUuidV7 || $uuid instanceof LazyUuidFromString); - return new self($uuid); + return Uuid::getFactory()->uuid7($date); } public static function from(IBaseUuid|Identifier|string|null $value): self @@ -44,7 +42,7 @@ public static function tryFrom(IBaseUuid|Identifier|string|null $value): ?self { $parsed = match (true) { $value instanceof self, $value instanceof IBaseUuid => $value, - $value instanceof Uuid => $value->value, + $value instanceof IUuid => $value->toBase(), is_string($value) && BaseUuid::isValid($value) => BaseUuid::getFactory()->fromString($value), default => null, }; @@ -56,7 +54,7 @@ public static function tryFrom(IBaseUuid|Identifier|string|null $value): ?self }; } - private function __construct(public readonly BaseUuidV7|LazyUuidFromString $value) + public function __construct(public readonly BaseUuidV7|LazyUuidFromString $value) { if ($this->value instanceof LazyUuidFromString) { Contracts::assert($this->value->getVersion() === 7); diff --git a/src/Toolkit/Loggable/ObjectDecorator.php b/src/Toolkit/Loggable/ObjectDecorator.php deleted file mode 100644 index a31d62f1..00000000 --- a/src/Toolkit/Loggable/ObjectDecorator.php +++ /dev/null @@ -1,95 +0,0 @@ - - */ -final readonly class ObjectDecorator implements IteratorAggregate, ContextProvider -{ - private const DATE_FORMAT = 'Y-m-d\TH:i:s.uP'; - - public function __construct( - private object $source, - private ?string $dateFormat = self::DATE_FORMAT, - ) { - } - - /** - * @return Generator - */ - public function getIterator(): Generator - { - foreach ($this->cursor() as $key) { - $value = $this->source->{$key}; - yield $key => match (true) { - $value instanceof ContextProvider => $value->context(), - $value instanceof Contextual => $value->context(), - $value instanceof UuidInterface => $value->toString(), - $value instanceof UnitEnum => enum_string($value), - $value instanceof DateTimeInterface && $this->dateFormat !== null => $value->format($this->dateFormat), - $value instanceof DateTimeZone => $value->getName(), - default => $value, - }; - } - } - - /** - * @return array - */ - public function keys(): array - { - return iterator_to_array($this->cursor()); - } - - /** - * @return array - */ - public function all(): array - { - return iterator_to_array($this); - } - - public function context(): array - { - return $this->all(); - } - - /** - * @return Generator - */ - private function cursor(): Generator - { - $reflect = new ReflectionClass($this->source); - - foreach ($reflect->getProperties(ReflectionProperty::IS_PUBLIC) as $property) { - $attributes = $property->getAttributes(Sensitive::class); - if (count($attributes) === 0) { - yield $property->getName(); - } - } - } -} diff --git a/src/Toolkit/Loggable/ResultDecorator.php b/src/Toolkit/Loggable/ResultDecorator.php deleted file mode 100644 index 17b1351f..00000000 --- a/src/Toolkit/Loggable/ResultDecorator.php +++ /dev/null @@ -1,90 +0,0 @@ - $result - */ - public function __construct(private Result $result) - { - } - - public function context(): array - { - if ($this->result instanceof ContextProvider) { - return $this->result->context(); - } - - $value = $this->result->safe(); - $errors = $this->errors(); - $error = null; - - if ( - count($errors) === 1 && - count($errors[0]) === 1 && - (isset($errors[0]['message']) || isset($errors[0]['code'])) - ) { - $error = $errors[0]['message'] ?? $errors[0]['code']; - $errors = null; - } - - return array_filter([ - 'success' => $this->result->didSucceed(), - 'value' => match(true) { - $value instanceof ContextProvider => $value->context(), - $value instanceof Contextual => $value->context(), - is_scalar($value) => $value, - default => null, - }, - 'error' => $error, - 'errors' => $errors ?: null, - 'meta' => $this->result->meta()->all() ?: null, - ], static fn ($value) => $value !== null); - } - - /** - * @return array> - */ - private function errors(): array - { - return array_map( - fn (Error $error): array => $this->error($error), - $this->result->errors()->all(), - ); - } - - /** - * @return array - */ - private function error(Error $error): array - { - if ($error instanceof ContextProvider) { - return $error->context(); - } - - return array_filter([ - 'code' => enum_string($error->code() ?? ''), - 'key' => enum_string($error->key() ?? ''), - 'message' => $error->message(), - ]); - } -} diff --git a/src/Toolkit/Loggable/SimpleContextFactory.php b/src/Toolkit/Loggable/SimpleContextFactory.php deleted file mode 100644 index e0fd9433..00000000 --- a/src/Toolkit/Loggable/SimpleContextFactory.php +++ /dev/null @@ -1,32 +0,0 @@ - $object, - $object instanceof Result => new ResultDecorator($object), - $object instanceof Message => new ObjectDecorator($object), - }; - - return $object->context(); - } -} diff --git a/src/Toolkit/Pipeline/PipeContainer.php b/src/Toolkit/Pipeline/PipeContainer.php index 3e63da29..f94709a2 100644 --- a/src/Toolkit/Pipeline/PipeContainer.php +++ b/src/Toolkit/Pipeline/PipeContainer.php @@ -14,7 +14,6 @@ use Closure; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; -use Psr\Container\ContainerInterface; use RuntimeException; final class PipeContainer implements IPipeContainer @@ -24,10 +23,6 @@ final class PipeContainer implements IPipeContainer */ private array $pipes = []; - public function __construct(private readonly ?ContainerInterface $container = null) - { - } - /** * Bind a pipe into the container. */ @@ -46,12 +41,6 @@ public function get(string $pipeName): callable return $pipe; } - if ($this->container) { - $pipe = $this->container->get($pipeName); - assert(is_callable($pipe), "Expecting pipe {$pipeName} from PSR container to be callable."); - return $pipe; - } - throw new RuntimeException('Unrecognised pipe name: ' . $pipeName); } } diff --git a/src/Toolkit/Pipeline/PipelineBuilder.php b/src/Toolkit/Pipeline/PipelineBuilder.php index 88175b8e..eee983a4 100644 --- a/src/Toolkit/Pipeline/PipelineBuilder.php +++ b/src/Toolkit/Pipeline/PipelineBuilder.php @@ -15,7 +15,6 @@ use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipelineBuilder as IPipelineBuilder; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\Processor; -use Psr\Container\ContainerInterface; use RuntimeException; final class PipelineBuilder implements IPipelineBuilder @@ -25,12 +24,8 @@ final class PipelineBuilder implements IPipelineBuilder */ private array $stages = []; - public static function make(ContainerInterface|IPipeContainer|null $container = null): self + public static function make(?IPipeContainer $container = null): self { - if ($container instanceof ContainerInterface) { - return new self(new PipeContainer($container)); - } - return new self($container); } diff --git a/src/Toolkit/Result/ContextualResult.php b/src/Toolkit/Result/ContextualResult.php new file mode 100644 index 00000000..7f0707f6 --- /dev/null +++ b/src/Toolkit/Result/ContextualResult.php @@ -0,0 +1,101 @@ + $result + */ + public function __construct(private Result $result) + { + } + + public function success(): bool + { + return $this->result->didSucceed(); + } + + public function value(): mixed + { + $value = $this->result->safe(); + + if ($value instanceof Contextual) { + return $value->context(); + } + + // do not return strings as we do not know if they are sensitive or not. + if (is_bool($value) || is_int($value) || is_float($value)) { + return $value; + } + + return null; + } + + /** + * @return array|null + */ + public function meta(): ?array + { + $meta = $this->result->meta(); + + if ($meta->isNotEmpty()) { + return $meta->all(); + } + + return null; + } + + /** + * @return array> + */ + public function errors(): array + { + return array_map( + fn (Error $error): array => $this->error($error), + $this->result->errors()->all(), + ); + } + + /** + * @return array + */ + public function context(): array + { + $errors = $this->errors(); + + return array_filter([ + 'success' => $this->success(), + 'value' => $this->value(), + 'error' => count($errors) === 1 ? $errors[0] : null, + 'errors' => count($errors) > 1 ? $errors : null, + 'meta' => $this->meta(), + ], fn (mixed $value): bool => $value !== null); + } + + /** + * @return array + */ + private function error(Error $error): array + { + return array_filter([ + 'code' => $error->code(), + 'key' => $error->key(), + 'message' => $error->message(), + ]); + } +} diff --git a/src/Toolkit/Result/FailedResultException.php b/src/Toolkit/Result/FailedResultException.php index 237905ad..96851bb4 100644 --- a/src/Toolkit/Result/FailedResultException.php +++ b/src/Toolkit/Result/FailedResultException.php @@ -12,15 +12,13 @@ namespace CloudCreativity\Modules\Toolkit\Result; -use CloudCreativity\Modules\Contracts\Toolkit\Loggable\ContextProvider; use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; -use CloudCreativity\Modules\Toolkit\Loggable\SimpleContextFactory; use RuntimeException; use Throwable; use function CloudCreativity\Modules\Toolkit\enum_string; -class FailedResultException extends RuntimeException implements ContextProvider +class FailedResultException extends RuntimeException { /** * @param Result $result @@ -49,8 +47,13 @@ public function getResult(): Result return $this->result; } + /** + * @return array + */ public function context(): array { - return (new SimpleContextFactory())->make($this->result); + $context = $this->result->context(); + + return is_array($context) ? $context : [$context]; } } diff --git a/src/Toolkit/Result/Result.php b/src/Toolkit/Result/Result.php index c9263a42..e55db524 100644 --- a/src/Toolkit/Result/Result.php +++ b/src/Toolkit/Result/Result.php @@ -157,4 +157,12 @@ public function withMeta(array|Meta $meta): self meta: $this->meta->merge($meta), ); } + + /** + * @return array + */ + public function context(): array + { + return (new ContextualResult($this))->context(); + } } diff --git a/src/Toolkit/Loggable/Sensitive.php b/src/Toolkit/Sensitive.php similarity index 86% rename from src/Toolkit/Loggable/Sensitive.php rename to src/Toolkit/Sensitive.php index 01c71ecc..2e662e36 100644 --- a/src/Toolkit/Loggable/Sensitive.php +++ b/src/Toolkit/Sensitive.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Toolkit\Loggable; +namespace CloudCreativity\Modules\Toolkit; use Attribute; diff --git a/tests/Integration/Application/Bus/AddCommand.php b/tests/Integration/Bus/AddCommand.php similarity index 73% rename from tests/Integration/Application/Bus/AddCommand.php rename to tests/Integration/Bus/AddCommand.php index 2596e234..18a47e31 100644 --- a/tests/Integration/Application/Bus/AddCommand.php +++ b/tests/Integration/Bus/AddCommand.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; final readonly class AddCommand implements Command { diff --git a/tests/Integration/Application/Bus/AddCommandHandler.php b/tests/Integration/Bus/AddCommandHandler.php similarity index 89% rename from tests/Integration/Application/Bus/AddCommandHandler.php rename to tests/Integration/Bus/AddCommandHandler.php index b0aa53c9..0304c34e 100644 --- a/tests/Integration/Application/Bus/AddCommandHandler.php +++ b/tests/Integration/Bus/AddCommandHandler.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; use CloudCreativity\Modules\Toolkit\Result\Result; diff --git a/tests/Integration/Application/InboundEventBus/DefaultHandler.php b/tests/Integration/Bus/DefaultEventHandler.php similarity index 70% rename from tests/Integration/Application/InboundEventBus/DefaultHandler.php rename to tests/Integration/Bus/DefaultEventHandler.php index 73f6f21a..8d02813b 100644 --- a/tests/Integration/Application/InboundEventBus/DefaultHandler.php +++ b/tests/Integration/Bus/DefaultEventHandler.php @@ -10,11 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; -final class DefaultHandler +final class DefaultEventHandler { /** * @var array diff --git a/tests/Integration/Application/Bus/DivideQuery.php b/tests/Integration/Bus/DivideQuery.php similarity index 73% rename from tests/Integration/Application/Bus/DivideQuery.php rename to tests/Integration/Bus/DivideQuery.php index e439eba3..7cba9bae 100644 --- a/tests/Integration/Application/Bus/DivideQuery.php +++ b/tests/Integration/Bus/DivideQuery.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Messaging\Query; final readonly class DivideQuery implements Query { diff --git a/tests/Integration/Application/Bus/DivideQueryHandler.php b/tests/Integration/Bus/DivideQueryHandler.php similarity index 89% rename from tests/Integration/Application/Bus/DivideQueryHandler.php rename to tests/Integration/Bus/DivideQueryHandler.php index d32520be..d23a880e 100644 --- a/tests/Integration/Application/Bus/DivideQueryHandler.php +++ b/tests/Integration/Bus/DivideQueryHandler.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; use CloudCreativity\Modules\Toolkit\Pipeline\Through; use CloudCreativity\Modules\Toolkit\Result\Result; diff --git a/tests/Integration/Application/Bus/FloorCommand.php b/tests/Integration/Bus/FloorCommand.php similarity index 73% rename from tests/Integration/Application/Bus/FloorCommand.php rename to tests/Integration/Bus/FloorCommand.php index fc79999d..495ede05 100644 --- a/tests/Integration/Application/Bus/FloorCommand.php +++ b/tests/Integration/Bus/FloorCommand.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; final readonly class FloorCommand implements Command { diff --git a/tests/Integration/Application/Bus/MathCommandBus.php b/tests/Integration/Bus/MathCommandBus.php similarity index 66% rename from tests/Integration/Application/Bus/MathCommandBus.php rename to tests/Integration/Bus/MathCommandBus.php index dfad23f6..19f146c9 100644 --- a/tests/Integration/Application/Bus/MathCommandBus.php +++ b/tests/Integration/Bus/MathCommandBus.php @@ -10,11 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Application\Bus\CommandDispatcher; -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; -use CloudCreativity\Modules\Application\Bus\WithCommand; +use CloudCreativity\Modules\Bus\CommandDispatcher; +use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch; +use CloudCreativity\Modules\Bus\WithCommand; use CloudCreativity\Modules\Toolkit\Pipeline\Through; #[Through(LogMessageDispatch::class)] diff --git a/tests/Integration/Application/Bus/MathCommandBusTest.php b/tests/Integration/Bus/MathCommandBusTest.php similarity index 90% rename from tests/Integration/Application/Bus/MathCommandBusTest.php rename to tests/Integration/Bus/MathCommandBusTest.php index 6c0d46e3..805b2bde 100644 --- a/tests/Integration/Application/Bus/MathCommandBusTest.php +++ b/tests/Integration/Bus/MathCommandBusTest.php @@ -10,11 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; use CloudCreativity\Modules\Application\UnitOfWork\UnitOfWorkManager; +use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch; use CloudCreativity\Modules\Testing\FakeContainer; use PHPUnit\Framework\TestCase; diff --git a/tests/Integration/Application/InboundEventBus/MathEventBus.php b/tests/Integration/Bus/MathEventBus.php similarity index 51% rename from tests/Integration/Application/InboundEventBus/MathEventBus.php rename to tests/Integration/Bus/MathEventBus.php index cd56b7d2..a3a67921 100644 --- a/tests/Integration/Application/InboundEventBus/MathEventBus.php +++ b/tests/Integration/Bus/MathEventBus.php @@ -10,16 +10,16 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Application\InboundEventBus\InboundEventDispatcher; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\LogInboundEvent; -use CloudCreativity\Modules\Application\InboundEventBus\WithDefault; -use CloudCreativity\Modules\Application\InboundEventBus\WithEvent; +use CloudCreativity\Modules\Bus\InboundEventDispatcher; +use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch; +use CloudCreativity\Modules\Bus\WithDefault; +use CloudCreativity\Modules\Bus\WithEvent; use CloudCreativity\Modules\Toolkit\Pipeline\Through; -#[Through(LogInboundEvent::class)] -#[WithDefault(DefaultHandler::class)] +#[Through(LogMessageDispatch::class)] +#[WithDefault(DefaultEventHandler::class)] #[WithEvent(NumbersAdded::class, NumbersAddedHandler::class)] #[WithEvent(NumbersSubtracted::class, NumbersSubtractedHandler::class)] final class MathEventBus extends InboundEventDispatcher diff --git a/tests/Integration/Application/InboundEventBus/MathEventBusTest.php b/tests/Integration/Bus/MathEventBusTest.php similarity index 71% rename from tests/Integration/Application/InboundEventBus/MathEventBusTest.php rename to tests/Integration/Bus/MathEventBusTest.php index 7f73a901..40e53f7c 100644 --- a/tests/Integration/Application/InboundEventBus/MathEventBusTest.php +++ b/tests/Integration/Bus/MathEventBusTest.php @@ -10,11 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\HandleInUnitOfWork; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\LogInboundEvent; +use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; use CloudCreativity\Modules\Application\UnitOfWork\UnitOfWorkManager; +use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch; use CloudCreativity\Modules\Testing\FakeContainer; use PHPUnit\Framework\TestCase; @@ -24,14 +24,14 @@ public function test(): void { $a = new NumbersAddedHandler(); $b = new NumbersSubtractedHandler(); - $c = new DefaultHandler(); + $c = new DefaultEventHandler(); $container = new FakeContainer(); $container->bind(NumbersAddedHandler::class, fn () => $a); $container->bind(NumbersSubtractedHandler::class, fn () => $b); - $container->bind(DefaultHandler::class, fn () => $c); - $container->bind(LogInboundEvent::class, fn () => new LogInboundEvent($container->logger)); - $container->bind(HandleInUnitOfWork::class, fn () => new HandleInUnitOfWork( + $container->bind(DefaultEventHandler::class, fn () => $c); + $container->bind(LogMessageDispatch::class, fn () => new LogMessageDispatch($container->logger)); + $container->bind(ExecuteInUnitOfWork::class, fn () => new ExecuteInUnitOfWork( new UnitOfWorkManager($container->unitOfWork), )); diff --git a/tests/Integration/Application/Bus/MathQueryBus.php b/tests/Integration/Bus/MathQueryBus.php similarity index 66% rename from tests/Integration/Application/Bus/MathQueryBus.php rename to tests/Integration/Bus/MathQueryBus.php index 0cf831cf..6c913a32 100644 --- a/tests/Integration/Application/Bus/MathQueryBus.php +++ b/tests/Integration/Bus/MathQueryBus.php @@ -10,11 +10,11 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; -use CloudCreativity\Modules\Application\Bus\QueryDispatcher; -use CloudCreativity\Modules\Application\Bus\WithQuery; +use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch; +use CloudCreativity\Modules\Bus\QueryDispatcher; +use CloudCreativity\Modules\Bus\WithQuery; use CloudCreativity\Modules\Toolkit\Pipeline\Through; #[Through(LogMessageDispatch::class)] diff --git a/tests/Integration/Application/Bus/MathQueryBusTest.php b/tests/Integration/Bus/MathQueryBusTest.php similarity index 90% rename from tests/Integration/Application/Bus/MathQueryBusTest.php rename to tests/Integration/Bus/MathQueryBusTest.php index ab44250c..d07e0277 100644 --- a/tests/Integration/Application/Bus/MathQueryBusTest.php +++ b/tests/Integration/Bus/MathQueryBusTest.php @@ -10,10 +10,10 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; use Closure; -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; +use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch; use CloudCreativity\Modules\Testing\FakeContainer; use PHPUnit\Framework\TestCase; diff --git a/tests/Integration/Application/Bus/MultiplyCommand.php b/tests/Integration/Bus/MultiplyCommand.php similarity index 73% rename from tests/Integration/Application/Bus/MultiplyCommand.php rename to tests/Integration/Bus/MultiplyCommand.php index fe637476..aa839eaf 100644 --- a/tests/Integration/Application/Bus/MultiplyCommand.php +++ b/tests/Integration/Bus/MultiplyCommand.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; final readonly class MultiplyCommand implements Command { diff --git a/tests/Integration/Application/Bus/MultiplyCommandHandler.php b/tests/Integration/Bus/MultiplyCommandHandler.php similarity index 91% rename from tests/Integration/Application/Bus/MultiplyCommandHandler.php rename to tests/Integration/Bus/MultiplyCommandHandler.php index a76e4e85..3db406ac 100644 --- a/tests/Integration/Application/Bus/MultiplyCommandHandler.php +++ b/tests/Integration/Bus/MultiplyCommandHandler.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; use CloudCreativity\Modules\Toolkit\Pipeline\Through; diff --git a/tests/Integration/Application/InboundEventBus/NumbersAdded.php b/tests/Integration/Bus/NumbersAdded.php similarity index 72% rename from tests/Integration/Application/InboundEventBus/NumbersAdded.php rename to tests/Integration/Bus/NumbersAdded.php index 271af6d6..11bd0fa5 100644 --- a/tests/Integration/Application/InboundEventBus/NumbersAdded.php +++ b/tests/Integration/Bus/NumbersAdded.php @@ -10,16 +10,16 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Toolkit\Contracts; -use CloudCreativity\Modules\Toolkit\Identifiers\Uuid; +use CloudCreativity\Modules\Toolkit\Identifiers\UuidV4; use DateTimeImmutable; final readonly class NumbersAdded implements IntegrationEvent { - public Uuid $uuid; + public UuidV4 $uuid; public function __construct( public int $a, @@ -28,10 +28,10 @@ public function __construct( public DateTimeImmutable $calculatedAt = new DateTimeImmutable(), ) { Contracts::assert($sum === ($a + $b), 'The sum must be equal to a plus b.'); - $this->uuid = Uuid::random(); + $this->uuid = UuidV4::make(); } - public function getUuid(): Uuid + public function getUuid(): UuidV4 { return $this->uuid; } diff --git a/tests/Integration/Application/InboundEventBus/NumbersAddedHandler.php b/tests/Integration/Bus/NumbersAddedHandler.php similarity index 84% rename from tests/Integration/Application/InboundEventBus/NumbersAddedHandler.php rename to tests/Integration/Bus/NumbersAddedHandler.php index 686dd946..b7961cbf 100644 --- a/tests/Integration/Application/InboundEventBus/NumbersAddedHandler.php +++ b/tests/Integration/Bus/NumbersAddedHandler.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; final class NumbersAddedHandler { diff --git a/tests/Integration/Application/InboundEventBus/NumbersDivided.php b/tests/Integration/Bus/NumbersDivided.php similarity index 72% rename from tests/Integration/Application/InboundEventBus/NumbersDivided.php rename to tests/Integration/Bus/NumbersDivided.php index 020aae95..f99c5c2c 100644 --- a/tests/Integration/Application/InboundEventBus/NumbersDivided.php +++ b/tests/Integration/Bus/NumbersDivided.php @@ -10,16 +10,16 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Toolkit\Contracts; -use CloudCreativity\Modules\Toolkit\Identifiers\Uuid; +use CloudCreativity\Modules\Toolkit\Identifiers\UuidV4; use DateTimeImmutable; final readonly class NumbersDivided implements IntegrationEvent { - public Uuid $uuid; + public UuidV4 $uuid; public function __construct( public int $a, @@ -28,10 +28,10 @@ public function __construct( public DateTimeImmutable $calculatedAt = new DateTimeImmutable(), ) { Contracts::assert($sum == ($a / $b), 'The sum must be equal to a divided by b.'); - $this->uuid = Uuid::random(); + $this->uuid = UuidV4::make(); } - public function getUuid(): Uuid + public function getUuid(): UuidV4 { return $this->uuid; } diff --git a/tests/Integration/Application/InboundEventBus/NumbersSubtracted.php b/tests/Integration/Bus/NumbersSubtracted.php similarity index 72% rename from tests/Integration/Application/InboundEventBus/NumbersSubtracted.php rename to tests/Integration/Bus/NumbersSubtracted.php index 112fd561..cfed34ce 100644 --- a/tests/Integration/Application/InboundEventBus/NumbersSubtracted.php +++ b/tests/Integration/Bus/NumbersSubtracted.php @@ -10,16 +10,16 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Toolkit\Contracts; -use CloudCreativity\Modules\Toolkit\Identifiers\Uuid; +use CloudCreativity\Modules\Toolkit\Identifiers\UuidV4; use DateTimeImmutable; final readonly class NumbersSubtracted implements IntegrationEvent { - public Uuid $uuid; + public UuidV4 $uuid; public function __construct( public int $a, @@ -28,10 +28,10 @@ public function __construct( public DateTimeImmutable $calculatedAt = new DateTimeImmutable(), ) { Contracts::assert($sum === ($a - $b), 'The sum must be equal to a minus b.'); - $this->uuid = Uuid::random(); + $this->uuid = UuidV4::make(); } - public function getUuid(): Uuid + public function getUuid(): UuidV4 { return $this->uuid; } diff --git a/tests/Integration/Application/InboundEventBus/NumbersSubtractedHandler.php b/tests/Integration/Bus/NumbersSubtractedHandler.php similarity index 71% rename from tests/Integration/Application/InboundEventBus/NumbersSubtractedHandler.php rename to tests/Integration/Bus/NumbersSubtractedHandler.php index e2987680..db605af2 100644 --- a/tests/Integration/Application/InboundEventBus/NumbersSubtractedHandler.php +++ b/tests/Integration/Bus/NumbersSubtractedHandler.php @@ -10,12 +10,12 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\HandleInUnitOfWork; +use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; use CloudCreativity\Modules\Toolkit\Pipeline\Through; -#[Through(HandleInUnitOfWork::class)] +#[Through(ExecuteInUnitOfWork::class)] final class NumbersSubtractedHandler { /** diff --git a/tests/Integration/Application/Bus/SubtractQuery.php b/tests/Integration/Bus/SubtractQuery.php similarity index 73% rename from tests/Integration/Application/Bus/SubtractQuery.php rename to tests/Integration/Bus/SubtractQuery.php index 9983742c..3cd00b5f 100644 --- a/tests/Integration/Application/Bus/SubtractQuery.php +++ b/tests/Integration/Bus/SubtractQuery.php @@ -10,9 +10,9 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Messaging\Query; final readonly class SubtractQuery implements Query { diff --git a/tests/Integration/Application/Bus/SubtractQueryHandler.php b/tests/Integration/Bus/SubtractQueryHandler.php similarity index 89% rename from tests/Integration/Application/Bus/SubtractQueryHandler.php rename to tests/Integration/Bus/SubtractQueryHandler.php index 138b37a8..fe4ce8fe 100644 --- a/tests/Integration/Application/Bus/SubtractQueryHandler.php +++ b/tests/Integration/Bus/SubtractQueryHandler.php @@ -10,7 +10,7 @@ declare(strict_types=1); -namespace CloudCreativity\Modules\Tests\Integration\Application\Bus; +namespace CloudCreativity\Modules\Tests\Integration\Bus; use CloudCreativity\Modules\Toolkit\Result\Result; diff --git a/tests/Integration/Infrastructure/OutboundEventBus/MathEventPublisher.php b/tests/Integration/Infrastructure/OutboundEventBus/MathEventPublisher.php index 7fa6d566..c2ff62eb 100644 --- a/tests/Integration/Infrastructure/OutboundEventBus/MathEventPublisher.php +++ b/tests/Integration/Infrastructure/OutboundEventBus/MathEventPublisher.php @@ -13,11 +13,11 @@ namespace CloudCreativity\Modules\Tests\Integration\Infrastructure\OutboundEventBus; use CloudCreativity\Modules\Infrastructure\OutboundEventBus\ComponentPublisher; +use CloudCreativity\Modules\Infrastructure\OutboundEventBus\DefaultPublisher; use CloudCreativity\Modules\Infrastructure\OutboundEventBus\Middleware\LogOutboundEvent; use CloudCreativity\Modules\Infrastructure\OutboundEventBus\Publishes; -use CloudCreativity\Modules\Infrastructure\OutboundEventBus\DefaultPublisher; -use CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus\NumbersAdded; -use CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus\NumbersSubtracted; +use CloudCreativity\Modules\Tests\Integration\Bus\NumbersAdded; +use CloudCreativity\Modules\Tests\Integration\Bus\NumbersSubtracted; use CloudCreativity\Modules\Toolkit\Pipeline\Through; #[DefaultPublisher(TestDefaultPublisher::class)] diff --git a/tests/Integration/Infrastructure/OutboundEventBus/MathEventPublisherTest.php b/tests/Integration/Infrastructure/OutboundEventBus/MathEventPublisherTest.php index 4c7a045a..48793468 100644 --- a/tests/Integration/Infrastructure/OutboundEventBus/MathEventPublisherTest.php +++ b/tests/Integration/Infrastructure/OutboundEventBus/MathEventPublisherTest.php @@ -14,9 +14,9 @@ use CloudCreativity\Modules\Infrastructure\OutboundEventBus\Middleware\LogOutboundEvent; use CloudCreativity\Modules\Testing\FakeContainer; -use CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus\NumbersAdded; -use CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus\NumbersDivided; -use CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus\NumbersSubtracted; +use CloudCreativity\Modules\Tests\Integration\Bus\NumbersAdded; +use CloudCreativity\Modules\Tests\Integration\Bus\NumbersDivided; +use CloudCreativity\Modules\Tests\Integration\Bus\NumbersSubtracted; use PHPUnit\Framework\TestCase; class MathEventPublisherTest extends TestCase diff --git a/tests/Integration/Infrastructure/OutboundEventBus/NumbersAddedPublisher.php b/tests/Integration/Infrastructure/OutboundEventBus/NumbersAddedPublisher.php index c3f97a8e..86090d6f 100644 --- a/tests/Integration/Infrastructure/OutboundEventBus/NumbersAddedPublisher.php +++ b/tests/Integration/Infrastructure/OutboundEventBus/NumbersAddedPublisher.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Integration\Infrastructure\OutboundEventBus; -use CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus\NumbersAdded; +use CloudCreativity\Modules\Tests\Integration\Bus\NumbersAdded; final class NumbersAddedPublisher { diff --git a/tests/Integration/Infrastructure/OutboundEventBus/NumbersSubtractedPublisher.php b/tests/Integration/Infrastructure/OutboundEventBus/NumbersSubtractedPublisher.php index f9379a7b..9d86f21c 100644 --- a/tests/Integration/Infrastructure/OutboundEventBus/NumbersSubtractedPublisher.php +++ b/tests/Integration/Infrastructure/OutboundEventBus/NumbersSubtractedPublisher.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Integration\Infrastructure\OutboundEventBus; -use CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus\NumbersSubtracted; +use CloudCreativity\Modules\Tests\Integration\Bus\NumbersSubtracted; final class NumbersSubtractedPublisher { diff --git a/tests/Integration/Infrastructure/OutboundEventBus/TestClosurePublisherTest.php b/tests/Integration/Infrastructure/OutboundEventBus/TestClosurePublisherTest.php index 8d22c9ce..c363dc0b 100644 --- a/tests/Integration/Infrastructure/OutboundEventBus/TestClosurePublisherTest.php +++ b/tests/Integration/Infrastructure/OutboundEventBus/TestClosurePublisherTest.php @@ -14,7 +14,7 @@ use CloudCreativity\Modules\Infrastructure\OutboundEventBus\Middleware\LogOutboundEvent; use CloudCreativity\Modules\Testing\FakeContainer; -use CloudCreativity\Modules\Tests\Integration\Application\InboundEventBus\NumbersAdded; +use CloudCreativity\Modules\Tests\Integration\Bus\NumbersAdded; use PHPUnit\Framework\TestCase; class TestClosurePublisherTest extends TestCase diff --git a/tests/Integration/Infrastructure/OutboundEventBus/TestDefaultPublisher.php b/tests/Integration/Infrastructure/OutboundEventBus/TestDefaultPublisher.php index 36b1a214..ab767964 100644 --- a/tests/Integration/Infrastructure/OutboundEventBus/TestDefaultPublisher.php +++ b/tests/Integration/Infrastructure/OutboundEventBus/TestDefaultPublisher.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Integration\Infrastructure\OutboundEventBus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; final class TestDefaultPublisher { diff --git a/tests/Integration/Infrastructure/Queue/AddCommandEnqueuer.php b/tests/Integration/Infrastructure/Queue/AddCommandEnqueuer.php index 5bb7646b..345db5f1 100644 --- a/tests/Integration/Infrastructure/Queue/AddCommandEnqueuer.php +++ b/tests/Integration/Infrastructure/Queue/AddCommandEnqueuer.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Integration\Infrastructure\Queue; -use CloudCreativity\Modules\Tests\Integration\Application\Bus\AddCommand; +use CloudCreativity\Modules\Tests\Integration\Bus\AddCommand; final class AddCommandEnqueuer { diff --git a/tests/Integration/Infrastructure/Queue/MathQueue.php b/tests/Integration/Infrastructure/Queue/MathQueue.php index 4cd8fb00..4f59c246 100644 --- a/tests/Integration/Infrastructure/Queue/MathQueue.php +++ b/tests/Integration/Infrastructure/Queue/MathQueue.php @@ -16,8 +16,8 @@ use CloudCreativity\Modules\Infrastructure\Queue\DefaultEnqueuer; use CloudCreativity\Modules\Infrastructure\Queue\Middleware\LogPushedToQueue; use CloudCreativity\Modules\Infrastructure\Queue\Queues; -use CloudCreativity\Modules\Tests\Integration\Application\Bus\AddCommand; -use CloudCreativity\Modules\Tests\Integration\Application\Bus\MultiplyCommand; +use CloudCreativity\Modules\Tests\Integration\Bus\AddCommand; +use CloudCreativity\Modules\Tests\Integration\Bus\MultiplyCommand; use CloudCreativity\Modules\Toolkit\Pipeline\Through; #[DefaultEnqueuer(TestDefaultEnqueuer::class)] diff --git a/tests/Integration/Infrastructure/Queue/MathQueueTest.php b/tests/Integration/Infrastructure/Queue/MathQueueTest.php index 8b74c466..a8d8b3df 100644 --- a/tests/Integration/Infrastructure/Queue/MathQueueTest.php +++ b/tests/Integration/Infrastructure/Queue/MathQueueTest.php @@ -14,9 +14,9 @@ use CloudCreativity\Modules\Infrastructure\Queue\Middleware\LogPushedToQueue; use CloudCreativity\Modules\Testing\FakeContainer; -use CloudCreativity\Modules\Tests\Integration\Application\Bus\AddCommand; -use CloudCreativity\Modules\Tests\Integration\Application\Bus\FloorCommand; -use CloudCreativity\Modules\Tests\Integration\Application\Bus\MultiplyCommand; +use CloudCreativity\Modules\Tests\Integration\Bus\AddCommand; +use CloudCreativity\Modules\Tests\Integration\Bus\FloorCommand; +use CloudCreativity\Modules\Tests\Integration\Bus\MultiplyCommand; use PHPUnit\Framework\TestCase; class MathQueueTest extends TestCase diff --git a/tests/Integration/Infrastructure/Queue/MultiplyCommandEnqueuer.php b/tests/Integration/Infrastructure/Queue/MultiplyCommandEnqueuer.php index d2f9ee9d..670ec524 100644 --- a/tests/Integration/Infrastructure/Queue/MultiplyCommandEnqueuer.php +++ b/tests/Integration/Infrastructure/Queue/MultiplyCommandEnqueuer.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Integration\Infrastructure\Queue; -use CloudCreativity\Modules\Tests\Integration\Application\Bus\MultiplyCommand; +use CloudCreativity\Modules\Tests\Integration\Bus\MultiplyCommand; final class MultiplyCommandEnqueuer { diff --git a/tests/Integration/Infrastructure/Queue/TestClosureQueueTest.php b/tests/Integration/Infrastructure/Queue/TestClosureQueueTest.php index febdcef5..21daf3e4 100644 --- a/tests/Integration/Infrastructure/Queue/TestClosureQueueTest.php +++ b/tests/Integration/Infrastructure/Queue/TestClosureQueueTest.php @@ -14,7 +14,7 @@ use CloudCreativity\Modules\Infrastructure\Queue\Middleware\LogPushedToQueue; use CloudCreativity\Modules\Testing\FakeContainer; -use CloudCreativity\Modules\Tests\Integration\Application\Bus\AddCommand; +use CloudCreativity\Modules\Tests\Integration\Bus\AddCommand; use PHPUnit\Framework\TestCase; class TestClosureQueueTest extends TestCase diff --git a/tests/Integration/Infrastructure/Queue/TestDefaultEnqueuer.php b/tests/Integration/Infrastructure/Queue/TestDefaultEnqueuer.php index 6bec9c33..20c4e9f2 100644 --- a/tests/Integration/Infrastructure/Queue/TestDefaultEnqueuer.php +++ b/tests/Integration/Infrastructure/Queue/TestDefaultEnqueuer.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Integration\Infrastructure\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; final class TestDefaultEnqueuer { diff --git a/tests/Unit/Application/Bus/CommandDispatcherTest.php b/tests/Unit/Application/Bus/CommandDispatcherTest.php index 6a0eb804..4b6920af 100644 --- a/tests/Unit/Application/Bus/CommandDispatcherTest.php +++ b/tests/Unit/Application/Bus/CommandDispatcherTest.php @@ -12,10 +12,10 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Application\Bus\CommandDispatcher; -use CloudCreativity\Modules\Contracts\Application\Bus\CommandHandler; -use CloudCreativity\Modules\Contracts\Application\Bus\CommandHandlerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Bus\CommandDispatcher; +use CloudCreativity\Modules\Contracts\Bus\CommandHandler; +use CloudCreativity\Modules\Contracts\Bus\CommandHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\MockObject\MockObject; diff --git a/tests/Unit/Application/Bus/CommandHandlerContainerTest.php b/tests/Unit/Application/Bus/CommandHandlerContainerTest.php index ea99149d..efa1019f 100644 --- a/tests/Unit/Application/Bus/CommandHandlerContainerTest.php +++ b/tests/Unit/Application/Bus/CommandHandlerContainerTest.php @@ -12,10 +12,10 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Application\ApplicationException; -use CloudCreativity\Modules\Application\Bus\CommandHandler; -use CloudCreativity\Modules\Application\Bus\CommandHandlerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Bus\BusException; +use CloudCreativity\Modules\Bus\CommandHandler; +use CloudCreativity\Modules\Bus\CommandHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\Command; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; @@ -37,7 +37,7 @@ public function testItResolvesUsingClosureBindings(): void $this->assertEquals(new CommandHandler($a), $container->get($command1::class)); $this->assertEquals(new CommandHandler($b), $container->get($command2::class)); - $this->expectException(ApplicationException::class); + $this->expectException(BusException::class); $this->expectExceptionMessage('No command handler bound for command class: ' . $command3::class); $container->get($command3::class); @@ -69,7 +69,7 @@ public function testItResolvesViaPsrContainer(): void $this->assertEquals(new CommandHandler($a), $container->get($command1::class)); $this->assertEquals(new CommandHandler($b), $container->get($command2::class)); - $this->expectException(ApplicationException::class); + $this->expectException(BusException::class); $this->expectExceptionMessage('No command handler bound for command class: ' . $command3::class); $container->get($command3::class); diff --git a/tests/Unit/Application/Bus/CommandHandlerTest.php b/tests/Unit/Application/Bus/CommandHandlerTest.php index 63f9a8c6..cd283093 100644 --- a/tests/Unit/Application/Bus/CommandHandlerTest.php +++ b/tests/Unit/Application/Bus/CommandHandlerTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Application\Bus\CommandHandler; +use CloudCreativity\Modules\Bus\CommandHandler; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Application/Bus/CommandQueuerTest.php b/tests/Unit/Application/Bus/CommandQueuerTest.php index 02bc1b8f..06ee712b 100644 --- a/tests/Unit/Application/Bus/CommandQueuerTest.php +++ b/tests/Unit/Application/Bus/CommandQueuerTest.php @@ -13,7 +13,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; use CloudCreativity\Modules\Application\Bus\CommandQueuer; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Application/Bus/Middleware/ExecuteInUnitOfWorkTest.php b/tests/Unit/Application/Bus/Middleware/ExecuteInUnitOfWorkTest.php index a5ba7c6c..6d157986 100644 --- a/tests/Unit/Application/Bus/Middleware/ExecuteInUnitOfWorkTest.php +++ b/tests/Unit/Application/Bus/Middleware/ExecuteInUnitOfWorkTest.php @@ -14,7 +14,7 @@ use CloudCreativity\Modules\Application\Bus\Middleware\ExecuteInUnitOfWork; use CloudCreativity\Modules\Contracts\Application\UnitOfWork\UnitOfWorkManager; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\TestCase; use Throwable; diff --git a/tests/Unit/Application/Bus/Middleware/FlushDeferredEventsTest.php b/tests/Unit/Application/Bus/Middleware/FlushDeferredEventsTest.php index 4c5c76a3..481bd1d8 100644 --- a/tests/Unit/Application/Bus/Middleware/FlushDeferredEventsTest.php +++ b/tests/Unit/Application/Bus/Middleware/FlushDeferredEventsTest.php @@ -14,7 +14,7 @@ use CloudCreativity\Modules\Application\Bus\Middleware\FlushDeferredEvents; use CloudCreativity\Modules\Contracts\Application\DomainEventDispatching\DeferredDispatcher; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Application/Bus/Middleware/LogMessageDispatchTest.php b/tests/Unit/Application/Bus/Middleware/LogMessageDispatchTest.php index dee1e2f2..c71d87d6 100644 --- a/tests/Unit/Application/Bus/Middleware/LogMessageDispatchTest.php +++ b/tests/Unit/Application/Bus/Middleware/LogMessageDispatchTest.php @@ -12,118 +12,84 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus\Middleware; -use CloudCreativity\Modules\Application\Bus\Middleware\LogMessageDispatch; -use CloudCreativity\Modules\Contracts\Toolkit\Loggable\ContextFactory; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Message; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Bus\Middleware\LogMessageDispatch; +use CloudCreativity\Modules\Bus\SanitizedMessage; +use CloudCreativity\Modules\Contracts\Messaging\Command; +use CloudCreativity\Modules\Contracts\Messaging\Message; +use CloudCreativity\Modules\Contracts\Messaging\Query; use CloudCreativity\Modules\Toolkit\Result\Result; use LogicException; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; class LogMessageDispatchTest extends TestCase { - private LoggerInterface&MockObject $logger; - - private ContextFactory&MockObject $context; + private LoggerInterface&Stub $logger; private Command $message; + /** + * @var array + */ + private array $logs = []; + protected function setUp(): void { parent::setUp(); - $this->logger = $this->createMock(LoggerInterface::class); - $this->context = $this->createMock(ContextFactory::class); + $this->logger = $this->createStub(LoggerInterface::class); + $this->logger + ->method('log') + ->willReturnCallback(function ($level, $message, $context): bool { + $this->logs[] = [$level, $message, $context]; + return true; + }); + $this->message = new class () implements Command {}; } protected function tearDown(): void { parent::tearDown(); - unset($this->logger, $this->context, $this->message); + unset($this->logger, $this->message, $this->logs); } public function testWithDefaultLevels(): void { - $expected = Result::ok()->withMeta(['foobar' => 'bazbat']); + $expected = Result::ok(); $name = $this->message::class; - $logs = []; - - $this->logger - ->expects($this->exactly(2)) - ->method('log') - ->willReturnCallback(function ($level, $message, $context) use (&$logs): bool { - $logs[] = [$level, $message, $context]; - return true; - }); - - $context1 = ['message' => 'blah!']; - $context2 = ['result' => 'blah!']; - - $this->context - ->expects($this->exactly(2)) - ->method('make') - ->willReturnCallback(fn (object $in) => match ($in) { - $this->message => $context1, - $expected => $context2, - default => $this->fail('Unexpected object to convert to context.'), - }); - $middleware = new LogMessageDispatch($this->logger, context: $this->context); + $middleware = new LogMessageDispatch($this->logger); $actual = $middleware($this->message, function (Message $received) use ($expected) { $this->assertSame($this->message, $received); return $expected; }); $this->assertSame($expected, $actual); - $this->assertSame([ - [LogLevel::DEBUG, "Bus dispatching {$name}.", ['command' => $context1]], - [LogLevel::INFO, "Bus dispatched {$name}.", ['result' => $context2]], - ], $logs); + $this->assertEquals([ + [LogLevel::DEBUG, "Bus dispatching {$name}.", ['command' => (new SanitizedMessage($this->message))->context()]], + [LogLevel::INFO, "Bus dispatched {$name}.", ['result' => $expected->context()]], + ], $this->logs); } public function testWithCustomLevels(): void { $expected = Result::failed('Something went wrong.'); $name = $this->message::class; - $logs = []; - $this->logger - ->expects($this->exactly(2)) - ->method('log') - ->willReturnCallback(function ($level, $message, $context) use (&$logs): bool { - $logs[] = [$level, $message, $context]; - return true; - }); - - $context1 = ['message' => 'blah!']; - $context2 = ['result' => 'blah!']; - - $this->context - ->expects($this->exactly(2)) - ->method('make') - ->willReturnCallback(fn (object $in) => match ($in) { - $this->message => $context1, - $expected => $context2, - default => $this->fail('Unexpected object to convert to context.'), - }); - - - $middleware = new LogMessageDispatch($this->logger, LogLevel::NOTICE, LogLevel::WARNING, $this->context); + $middleware = new LogMessageDispatch($this->logger, LogLevel::NOTICE, LogLevel::WARNING); $actual = $middleware($this->message, function (Message $received) use ($expected) { $this->assertSame($this->message, $received); return $expected; }); $this->assertSame($expected, $actual); - $this->assertSame([ - [LogLevel::NOTICE, "Bus dispatching {$name}.", ['command' => $context1]], - [LogLevel::WARNING, "Bus dispatched {$name}.", ['result' => $context2]], - ], $logs); + $this->assertEquals([ + [LogLevel::NOTICE, "Bus dispatching {$name}.", ['command' => (new SanitizedMessage($this->message))->context()]], + [LogLevel::WARNING, "Bus dispatched {$name}.", ['result' => $expected->context()]], + ], $this->logs); } public function testItLogsAfterTheNextClosureIsInvoked(): void @@ -131,19 +97,7 @@ public function testItLogsAfterTheNextClosureIsInvoked(): void $expected = new LogicException(); $message = $this->createMock(Query::class); $name = $message::class; - - $this->context - ->expects($this->once()) - ->method('make') - ->with($this->identicalTo($message)) - ->willReturn($context = ['foo' => 'bar']); - - $this->logger - ->expects($this->once()) - ->method('log') - ->with(LogLevel::DEBUG, "Bus dispatching {$name}.", ['query' => $context]); - - $middleware = new LogMessageDispatch($this->logger, context: $this->context); + $middleware = new LogMessageDispatch($this->logger); try { $middleware($message, static function () use ($expected) { @@ -152,6 +106,9 @@ public function testItLogsAfterTheNextClosureIsInvoked(): void $this->fail('No exception thrown.'); } catch (LogicException $ex) { $this->assertSame($expected, $ex); + $this->assertEquals([ + [LogLevel::DEBUG, "Bus dispatching {$name}.", ['query' => (new SanitizedMessage($message))->context()]], + ], $this->logs); } } } diff --git a/tests/Unit/Application/Bus/Middleware/SetupBeforeDispatchTest.php b/tests/Unit/Application/Bus/Middleware/SetupBeforeDispatchTest.php index 6aaf319e..25a1f02b 100644 --- a/tests/Unit/Application/Bus/Middleware/SetupBeforeDispatchTest.php +++ b/tests/Unit/Application/Bus/Middleware/SetupBeforeDispatchTest.php @@ -13,9 +13,9 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus\Middleware; use Closure; -use CloudCreativity\Modules\Application\Bus\Middleware\SetupBeforeDispatch; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Bus\Middleware\SetupBeforeDispatch; +use CloudCreativity\Modules\Contracts\Messaging\Command; +use CloudCreativity\Modules\Contracts\Messaging\Query; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\TestCase; use RuntimeException; diff --git a/tests/Unit/Application/Bus/Middleware/TearDownAfterDispatchTest.php b/tests/Unit/Application/Bus/Middleware/TearDownAfterDispatchTest.php index 8e9c6e44..d8d5d0bd 100644 --- a/tests/Unit/Application/Bus/Middleware/TearDownAfterDispatchTest.php +++ b/tests/Unit/Application/Bus/Middleware/TearDownAfterDispatchTest.php @@ -12,9 +12,9 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus\Middleware; -use CloudCreativity\Modules\Application\Bus\Middleware\TearDownAfterDispatch; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Bus\Middleware\TearDownAfterDispatch; +use CloudCreativity\Modules\Contracts\Messaging\Command; +use CloudCreativity\Modules\Contracts\Messaging\Query; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\TestCase; use RuntimeException; diff --git a/tests/Unit/Application/Bus/Middleware/ValidateCommandTest.php b/tests/Unit/Application/Bus/Middleware/ValidateMessageTest.php similarity index 81% rename from tests/Unit/Application/Bus/Middleware/ValidateCommandTest.php rename to tests/Unit/Application/Bus/Middleware/ValidateMessageTest.php index f22c1357..2a0ac6d1 100644 --- a/tests/Unit/Application/Bus/Middleware/ValidateCommandTest.php +++ b/tests/Unit/Application/Bus/Middleware/ValidateMessageTest.php @@ -12,24 +12,26 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus\Middleware; -use CloudCreativity\Modules\Application\Bus\Middleware\ValidateCommand; -use CloudCreativity\Modules\Contracts\Application\Bus\Bail; -use CloudCreativity\Modules\Contracts\Application\Bus\Validator; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Result\Result; +use CloudCreativity\Modules\Bus\Middleware\ValidateMessage; +use CloudCreativity\Modules\Contracts\Bus\Validation\Bail; +use CloudCreativity\Modules\Contracts\Bus\Validation\Validator; +use CloudCreativity\Modules\Contracts\Messaging\Command; +use CloudCreativity\Modules\Contracts\Messaging\Message; +use CloudCreativity\Modules\Contracts\Messaging\Query; +use CloudCreativity\Modules\Toolkit\Result\Result; use CloudCreativity\Modules\Toolkit\Result\Error; use CloudCreativity\Modules\Toolkit\Result\ListOfErrors; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -class ValidateCommandTest extends TestCase +class ValidateMessageTest extends TestCase { /** * @var MockObject&Validator */ private Validator $validator; - private ValidateCommand $middleware; + private ValidateMessage $middleware; protected function setUp(): void { @@ -37,7 +39,7 @@ protected function setUp(): void $this->validator = $this->createMock(Validator::class); - $this->middleware = new class ($this->validator) extends ValidateCommand { + $this->middleware = new class ($this->validator) extends ValidateMessage { /** * @return iterable */ @@ -51,8 +53,8 @@ protected function rules(): iterable public function testItSucceeds(): void { $rules = []; - $command = $this->createMock(Command::class); - $expected = $this->createMock(Result::class); + $command = $this->createStub(Command::class); + $expected = Result::ok(); $this->validator ->expects($this->once()) @@ -104,7 +106,7 @@ public function testItFails(): void $this->validator ->expects($this->once()) ->method('validate') - ->with($command = $this->createMock(Command::class)) + ->with($command = $this->createStub(Query::class)) ->willReturn($errors = new ListOfErrors(new Error(null, 'Something went wrong.'))); $next = function () { @@ -113,13 +115,13 @@ public function testItFails(): void $result = ($this->middleware)($command, $next); - $this->assertTrue($result->didFail()); + $this->assertTrue($result?->didFail()); $this->assertSame($errors, $result->errors()); } public function testItStopsOnFirstFailureViaBail(): void { - $this->middleware = new class ($this->validator) extends ValidateCommand implements Bail { + $this->middleware = new class ($this->validator) extends ValidateMessage implements Bail { /** * @return iterable */ @@ -143,7 +145,7 @@ protected function rules(): iterable $this->validator ->expects($this->once()) ->method('validate') - ->with($command = $this->createMock(Command::class)) + ->with($command = $this->createStub(Message::class)) ->willReturn($errors = new ListOfErrors(new Error(null, 'Something went wrong.'))); $next = function () { @@ -152,16 +154,16 @@ protected function rules(): iterable $result = ($this->middleware)($command, $next); - $this->assertTrue($result->didFail()); + $this->assertTrue($result?->didFail()); $this->assertSame($errors, $result->errors()); } public function testItStopsOnFirstFailure(): void { - $command = $this->createMock(Command::class); + $command = $this->createStub(Command::class); - $this->middleware = new class ($command, $this->validator) extends ValidateCommand { - public function __construct(private Command $command, Validator $validator) + $this->middleware = new class ($command, $this->validator) extends ValidateMessage { + public function __construct(private Message $message, Validator $validator) { parent::__construct($validator); } @@ -174,9 +176,9 @@ protected function rules(): iterable return ['foo', 'bar']; } - protected function stopOnFirstFailure(Command $command): bool + protected function stopOnFirstFailure(Message $message): bool { - return $this->command === $command; + return $this->message === $message; } }; @@ -203,7 +205,7 @@ protected function stopOnFirstFailure(Command $command): bool $result = ($this->middleware)($command, $next); - $this->assertTrue($result->didFail()); + $this->assertTrue($result?->didFail()); $this->assertSame($errors, $result->errors()); } } diff --git a/tests/Unit/Application/Bus/Middleware/ValidateQueryTest.php b/tests/Unit/Application/Bus/Middleware/ValidateQueryTest.php deleted file mode 100644 index 36ecb45c..00000000 --- a/tests/Unit/Application/Bus/Middleware/ValidateQueryTest.php +++ /dev/null @@ -1,210 +0,0 @@ -validator = $this->createMock(Validator::class); - - $this->middleware = new class ($this->validator) extends ValidateQuery { - /** - * @return iterable - */ - protected function rules(): iterable - { - return ['foobar', 'bazbat']; - } - }; - } - - public function testItSucceeds(): void - { - $rules = []; - $query = $this->createMock(Query::class); - $expected = $this->createMock(Result::class); - - $this->validator - ->expects($this->once()) - ->method('using') - ->with($this->callback(function (array $actual) use (&$rules): bool { - $rules = $actual; - return true; - })) - ->willReturnSelf(); - - $this->validator - ->expects($this->once()) - ->method('stopOnFirstFailure') - ->with(false) - ->willReturnSelf(); - - $this->validator - ->expects($this->once()) - ->method('validate') - ->with($this->callback(function (Query $actual) use ($query, &$rules): bool { - $this->assertSame(['foobar', 'bazbat'], $rules); - $this->assertSame($query, $actual); - return true; - })) - ->willReturn(new ListOfErrors()); - - $next = function ($actual) use ($query, $expected) { - $this->assertSame($query, $actual); - return $expected; - }; - - $actual = ($this->middleware)($query, $next); - - $this->assertSame($expected, $actual); - } - - public function testItFails(): void - { - $this->validator - ->expects($this->once()) - ->method('using') - ->willReturnSelf(); - - $this->validator - ->expects($this->once()) - ->method('stopOnFirstFailure') - ->with(false) - ->willReturnSelf(); - - $this->validator - ->expects($this->once()) - ->method('validate') - ->with($query = $this->createMock(Query::class)) - ->willReturn($errors = new ListOfErrors(new Error(null, 'Something went wrong.'))); - - $next = function () { - throw new \LogicException('Not expecting next closure to be called.'); - }; - - $result = ($this->middleware)($query, $next); - - $this->assertTrue($result->didFail()); - $this->assertSame($errors, $result->errors()); - } - - public function testItStopsOnFirstFailureViaBail(): void - { - $this->middleware = new class ($this->validator) extends ValidateQuery implements Bail { - /** - * @return iterable - */ - protected function rules(): iterable - { - return ['foobar', 'bazbat']; - } - }; - - $this->validator - ->expects($this->once()) - ->method('using') - ->willReturnSelf(); - - $this->validator - ->expects($this->once()) - ->method('stopOnFirstFailure') - ->with(true) - ->willReturnSelf(); - - $this->validator - ->expects($this->once()) - ->method('validate') - ->with($query = $this->createMock(Query::class)) - ->willReturn($errors = new ListOfErrors(new Error(null, 'Something went wrong.'))); - - $next = function () { - throw new \LogicException('Not expecting next closure to be called.'); - }; - - $result = ($this->middleware)($query, $next); - - $this->assertTrue($result->didFail()); - $this->assertSame($errors, $result->errors()); - } - - public function testItStopsOnFirstFailure(): void - { - $query = $this->createMock(Query::class); - - $this->middleware = new class ($query, $this->validator) extends ValidateQuery { - public function __construct(private Query $query, Validator $validator) - { - parent::__construct($validator); - } - - /** - * @return iterable - */ - protected function rules(): iterable - { - return ['foobar', 'bazbat']; - } - - protected function stopOnFirstFailure(Query $query): bool - { - return $this->query === $query; - } - }; - - $this->validator - ->expects($this->once()) - ->method('using') - ->willReturnSelf(); - - $this->validator - ->expects($this->once()) - ->method('stopOnFirstFailure') - ->with(true) - ->willReturnSelf(); - - $this->validator - ->expects($this->once()) - ->method('validate') - ->with($query) - ->willReturn($errors = new ListOfErrors(new Error(null, 'Something went wrong.'))); - - $next = function () { - throw new \LogicException('Not expecting next closure to be called.'); - }; - - $result = ($this->middleware)($query, $next); - - $this->assertTrue($result->didFail()); - $this->assertSame($errors, $result->errors()); - } -} diff --git a/tests/Unit/Application/Bus/QueryDispatcherTest.php b/tests/Unit/Application/Bus/QueryDispatcherTest.php index 88a093bd..7a6595f4 100644 --- a/tests/Unit/Application/Bus/QueryDispatcherTest.php +++ b/tests/Unit/Application/Bus/QueryDispatcherTest.php @@ -12,10 +12,10 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Application\Bus\QueryDispatcher; -use CloudCreativity\Modules\Contracts\Application\Bus\QueryHandler; -use CloudCreativity\Modules\Contracts\Application\Bus\QueryHandlerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Bus\QueryDispatcher; +use CloudCreativity\Modules\Contracts\Bus\QueryHandler; +use CloudCreativity\Modules\Contracts\Bus\QueryHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\Query; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\MockObject\MockObject; diff --git a/tests/Unit/Application/Bus/QueryHandlerContainerTest.php b/tests/Unit/Application/Bus/QueryHandlerContainerTest.php index 45ad402a..24c83e83 100644 --- a/tests/Unit/Application/Bus/QueryHandlerContainerTest.php +++ b/tests/Unit/Application/Bus/QueryHandlerContainerTest.php @@ -12,10 +12,10 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Application\ApplicationException; -use CloudCreativity\Modules\Application\Bus\QueryHandler; -use CloudCreativity\Modules\Application\Bus\QueryHandlerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Bus\BusException; +use CloudCreativity\Modules\Bus\QueryHandler; +use CloudCreativity\Modules\Bus\QueryHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\Query; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; @@ -37,7 +37,7 @@ public function testItResolvesClosureBindings(): void $this->assertEquals(new QueryHandler($a), $container->get($query1::class)); $this->assertEquals(new QueryHandler($b), $container->get($query2::class)); - $this->expectException(ApplicationException::class); + $this->expectException(BusException::class); $this->expectExceptionMessage('No query handler bound for query class: ' . $query3::class); $container->get($query3::class); @@ -69,7 +69,7 @@ public function testItResolvesViaPsrContainer(): void $this->assertEquals(new QueryHandler($a), $container->get($query1::class)); $this->assertEquals(new QueryHandler($b), $container->get($query2::class)); - $this->expectException(ApplicationException::class); + $this->expectException(BusException::class); $this->expectExceptionMessage('No query handler bound for query class: ' . $query3::class); $container->get($query3::class); diff --git a/tests/Unit/Application/Bus/QueryHandlerTest.php b/tests/Unit/Application/Bus/QueryHandlerTest.php index 1c189ab4..d7fdb820 100644 --- a/tests/Unit/Application/Bus/QueryHandlerTest.php +++ b/tests/Unit/Application/Bus/QueryHandlerTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Application\Bus\QueryHandler; +use CloudCreativity\Modules\Bus\QueryHandler; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Application/Bus/TestCommand.php b/tests/Unit/Application/Bus/TestCommand.php index 845d514f..e778cdf4 100644 --- a/tests/Unit/Application/Bus/TestCommand.php +++ b/tests/Unit/Application/Bus/TestCommand.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; class TestCommand implements Command { diff --git a/tests/Unit/Application/Bus/TestCommandHandler.php b/tests/Unit/Application/Bus/TestCommandHandler.php index ab6cefbe..f5bc76c2 100644 --- a/tests/Unit/Application/Bus/TestCommandHandler.php +++ b/tests/Unit/Application/Bus/TestCommandHandler.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; +use CloudCreativity\Modules\Contracts\Bus\DispatchThroughMiddleware; use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; use CloudCreativity\Modules\Toolkit\Identifiers\Uuid; use CloudCreativity\Modules\Toolkit\Result\Result; diff --git a/tests/Unit/Application/Bus/TestQuery.php b/tests/Unit/Application/Bus/TestQuery.php index 72fc40c2..4bd7666b 100644 --- a/tests/Unit/Application/Bus/TestQuery.php +++ b/tests/Unit/Application/Bus/TestQuery.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Contracts\Messaging\Query; class TestQuery implements Query { diff --git a/tests/Unit/Application/Bus/TestQueryHandler.php b/tests/Unit/Application/Bus/TestQueryHandler.php index c11ab681..8a7e98ee 100644 --- a/tests/Unit/Application/Bus/TestQueryHandler.php +++ b/tests/Unit/Application/Bus/TestQueryHandler.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; +use CloudCreativity\Modules\Contracts\Bus\DispatchThroughMiddleware; use CloudCreativity\Modules\Toolkit\Result\Result; class TestQueryHandler implements DispatchThroughMiddleware diff --git a/tests/Unit/Application/Bus/ValidatorTest.php b/tests/Unit/Application/Bus/ValidatorTest.php index e8d8c1d8..c6ae6ab5 100644 --- a/tests/Unit/Application/Bus/ValidatorTest.php +++ b/tests/Unit/Application/Bus/ValidatorTest.php @@ -12,15 +12,16 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\Bus; -use CloudCreativity\Modules\Application\Bus\Validator; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Query; +use CloudCreativity\Modules\Bus\Validation\Validator; +use CloudCreativity\Modules\Contracts\Messaging\Command; +use CloudCreativity\Modules\Contracts\Messaging\Message; +use CloudCreativity\Modules\Contracts\Messaging\Query; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Toolkit\Result\Error; use CloudCreativity\Modules\Toolkit\Result\ListOfErrors; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; class ValidatorTest extends TestCase { @@ -32,33 +33,33 @@ public static function messageProvider(): array return [ [Query::class], [Command::class], + [Message::class], ]; } /** - * @param class-string $message + * @param class-string $class */ #[DataProvider('messageProvider')] - public function testItValidatesMessage(string $message): void + public function testItValidatesMessage(string $class): void { - /** @var (Command&MockObject)|(MockObject&Query) $query */ - $query = $this->createMock($message); + $message = $this->createStub($class); $error1 = new Error(null, 'Message 1'); $error2 = new Error(null, 'Message 2'); $error3 = new Error(null, 'Message 3'); - $a = function ($actual) use ($query, $error1): ListOfErrors { - $this->assertSame($query, $actual); + $a = function ($actual) use ($message, $error1): ListOfErrors { + $this->assertSame($message, $actual); return new ListOfErrors($error1); }; - $b = function ($actual) use ($query): ?ListOfErrors { - $this->assertSame($query, $actual); + $b = function ($actual) use ($message): ?ListOfErrors { + $this->assertSame($message, $actual); return null; }; - $c = function ($actual) use ($query, $error2, $error3): ListOfErrors { - $this->assertSame($query, $actual); + $c = function ($actual) use ($message, $error2, $error3): ListOfErrors { + $this->assertSame($message, $actual); return new ListOfErrors($error2, $error3); }; @@ -75,29 +76,73 @@ public function testItValidatesMessage(string $message): void $validator = new Validator(rules: $rules); $actual = $validator ->using([$a, 'Rule2', 'Rule3']) - ->validate($query); + ->validate($message); $this->assertInstanceOf(ListOfErrors::class, $actual); $this->assertSame([$error1, $error2, $error3], $actual->all()); } /** - * @param class-string $message + * @param class-string $class */ #[DataProvider('messageProvider')] - public function testItStopsOnFirstFailure(string $message): void + public function testItValidatesMessageUsingPsrContainer(string $class): void { - /** @var (Command&MockObject)|(MockObject&Query) $query */ - $query = $this->createMock($message); + $message = $this->createStub($class); + $error1 = new Error(null, 'Message 1'); + $error2 = new Error(null, 'Message 2'); + $error3 = new Error(null, 'Message 3'); + + $a = function ($actual) use ($message, $error1): Error { + $this->assertSame($message, $actual); + return $error1; + }; + + $b = function ($actual) use ($message): ?ListOfErrors { + $this->assertSame($message, $actual); + return null; + }; + + $c = function ($actual) use ($message, $error2, $error3): ListOfErrors { + $this->assertSame($message, $actual); + return new ListOfErrors($error2, $error3); + }; + + $rules = $this->createMock(ContainerInterface::class); + $rules + ->expects($this->exactly(2)) + ->method('get') + ->willReturnCallback(fn (string $name) => match ($name) { + 'Rule2' => $b, + 'Rule3' => $c, + default => $this->fail('Unexpected rule name: ' . $name), + }); + + $validator = new Validator(rules: $rules); + $actual = $validator + ->using([$a, 'Rule2', 'Rule3']) + ->validate($message); + + $this->assertInstanceOf(ListOfErrors::class, $actual); + $this->assertSame([$error1, $error2, $error3], $actual->all()); + } + + /** + * @param class-string $class + */ + #[DataProvider('messageProvider')] + public function testItStopsOnFirstFailure(string $class): void + { + $message = $this->createStub($class); $error = new Error(null, 'Message 1'); - $a = function ($actual) use ($query): null { - $this->assertSame($query, $actual); + $a = function ($actual) use ($message): null { + $this->assertSame($message, $actual); return null; }; - $b = function ($actual) use ($query, $error): ListOfErrors { - $this->assertSame($query, $actual); + $b = function ($actual) use ($message, $error): ListOfErrors { + $this->assertSame($message, $actual); return new ListOfErrors($error); }; @@ -109,7 +154,7 @@ public function testItStopsOnFirstFailure(string $message): void $actual = $validator ->using([$a, $b, $c]) ->stopOnFirstFailure() - ->validate($query); + ->validate($message); $this->assertInstanceOf(ListOfErrors::class, $actual); $this->assertSame([$error], $actual->all()); @@ -117,7 +162,7 @@ public function testItStopsOnFirstFailure(string $message): void public function testItHasNoRules(): void { - $query = $this->createMock(Query::class); + $query = $this->createStub(Query::class); $validator = new Validator(); $this->assertEquals(new ListOfErrors(), $validator->validate($query)); diff --git a/tests/Unit/Application/InboundEventBus/EventHandlerContainerTest.php b/tests/Unit/Application/InboundEventBus/EventHandlerContainerTest.php index b2ed74d5..1971d13a 100644 --- a/tests/Unit/Application/InboundEventBus/EventHandlerContainerTest.php +++ b/tests/Unit/Application/InboundEventBus/EventHandlerContainerTest.php @@ -12,9 +12,9 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\InboundEventBus; -use CloudCreativity\Modules\Application\ApplicationException; -use CloudCreativity\Modules\Application\InboundEventBus\EventHandler; -use CloudCreativity\Modules\Application\InboundEventBus\EventHandlerContainer; +use CloudCreativity\Modules\Bus\BusException; +use CloudCreativity\Modules\Bus\EventHandler; +use CloudCreativity\Modules\Bus\EventHandlerContainer; use CloudCreativity\Modules\Tests\Unit\Infrastructure\OutboundEventBus\TestOutboundEvent; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; @@ -94,7 +94,7 @@ public function testItDoesNotHaveHandler(): void $container = new EventHandlerContainer(); $container->bind(TestInboundEvent::class, fn () => new TestEventHandler()); - $this->expectException(ApplicationException::class); + $this->expectException(BusException::class); $this->expectExceptionMessage( 'No handler bound for integration event: ' . TestOutboundEvent::class, ); diff --git a/tests/Unit/Application/InboundEventBus/EventHandlerTest.php b/tests/Unit/Application/InboundEventBus/EventHandlerTest.php index 073d9b5a..3de0d4a0 100644 --- a/tests/Unit/Application/InboundEventBus/EventHandlerTest.php +++ b/tests/Unit/Application/InboundEventBus/EventHandlerTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\InboundEventBus; -use CloudCreativity\Modules\Application\InboundEventBus\EventHandler; +use CloudCreativity\Modules\Bus\EventHandler; use PHPUnit\Framework\TestCase; class EventHandlerTest extends TestCase diff --git a/tests/Unit/Application/InboundEventBus/InboundEventDispatcherTest.php b/tests/Unit/Application/InboundEventBus/InboundEventDispatcherTest.php index d75b8921..1331479d 100644 --- a/tests/Unit/Application/InboundEventBus/InboundEventDispatcherTest.php +++ b/tests/Unit/Application/InboundEventBus/InboundEventDispatcherTest.php @@ -12,10 +12,10 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\InboundEventBus; -use CloudCreativity\Modules\Application\InboundEventBus\InboundEventDispatcher; -use CloudCreativity\Modules\Contracts\Application\InboundEventBus\EventHandler; -use CloudCreativity\Modules\Contracts\Application\InboundEventBus\EventHandlerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Bus\InboundEventDispatcher; +use CloudCreativity\Modules\Contracts\Bus\EventHandler; +use CloudCreativity\Modules\Contracts\Bus\EventHandlerContainer; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Application/InboundEventBus/Middleware/FlushDeferredEventsTest.php b/tests/Unit/Application/InboundEventBus/Middleware/FlushDeferredEventsTest.php deleted file mode 100644 index 9c5e6c53..00000000 --- a/tests/Unit/Application/InboundEventBus/Middleware/FlushDeferredEventsTest.php +++ /dev/null @@ -1,94 +0,0 @@ - - */ - private array $sequence = []; - - protected function setUp(): void - { - parent::setUp(); - - $this->middleware = new FlushDeferredEvents( - $this->dispatcher = $this->createMock(DeferredDispatcher::class), - ); - } - - public function testItFlushesDeferredEvents(): void - { - $event = $this->createMock(IntegrationEvent::class); - - $this->dispatcher - ->expects($this->once()) - ->method('flush') - ->willReturnCallback(function () { - $this->sequence[] = 'flush'; - }); - - $this->dispatcher - ->expects($this->never()) - ->method('forget'); - - ($this->middleware)($event, function ($in) use ($event): void { - $this->assertSame($event, $in); - $this->sequence[] = 'next'; - }); - - $this->assertSame(['next', 'flush'], $this->sequence); - } - - - public function testItForgetsDeferredEventsOnException(): void - { - $event = $this->createMock(IntegrationEvent::class); - $expected = new \LogicException('Boom!'); - - $this->dispatcher - ->expects($this->once()) - ->method('forget') - ->willReturnCallback(function () { - $this->sequence[] = 'forget'; - }); - - $this->dispatcher - ->expects($this->never()) - ->method('flush'); - - try { - ($this->middleware)($event, function ($in) use ($event, $expected): never { - $this->assertSame($event, $in); - $this->sequence[] = 'next'; - throw $expected; - }); - $this->fail('No exception thrown.'); - } catch (\LogicException $ex) { - $this->assertSame($expected, $ex); - } - - $this->assertSame(['next', 'forget'], $this->sequence); - } -} diff --git a/tests/Unit/Application/InboundEventBus/Middleware/HandleInUnitOfWorkTest.php b/tests/Unit/Application/InboundEventBus/Middleware/HandleInUnitOfWorkTest.php deleted file mode 100644 index ededbd52..00000000 --- a/tests/Unit/Application/InboundEventBus/Middleware/HandleInUnitOfWorkTest.php +++ /dev/null @@ -1,91 +0,0 @@ - - */ - private array $sequence = []; - - public function testItCommitsUnitOfWork(): void - { - $event = $this->createMock(IntegrationEvent::class); - - $middleware = new HandleInUnitOfWork( - $transactions = $this->createMock(UnitOfWorkManager::class), - 2, - ); - - $transactions - ->expects($this->once()) - ->method('execute') - ->willReturnCallback(function (\Closure $callback, int $attempts) { - $this->assertSame(2, $attempts); - $this->sequence[] = 'begin'; - $result = $callback(); - $this->sequence[] = 'commit'; - return $result; - }); - - $middleware($event, function ($cmd) use ($event) { - $this->assertSame($event, $cmd); - $this->sequence[] = 'handler'; - }); - - $this->assertSame(['begin', 'handler', 'commit'], $this->sequence); - } - - public function testItDoesNotCatchExceptions(): void - { - $event = $this->createMock(IntegrationEvent::class); - $expected = new \RuntimeException('Boom! Something went wrong.'); - - $middleware = new HandleInUnitOfWork( - $transactions = $this->createMock(UnitOfWorkManager::class), - 2, - ); - - $transactions - ->expects($this->once()) - ->method('execute') - ->willReturnCallback(function (\Closure $callback, int $attempts) { - $this->assertSame(2, $attempts); - $this->sequence[] = 'begin'; - $callback(); - $this->sequence[] = 'commit'; - }); - - $actual = null; - - try { - $middleware($event, function ($cmd) use ($event, $expected): never { - $this->assertSame($event, $cmd); - $this->sequence[] = 'handler'; - throw $expected; - }); - } catch (Throwable $ex) { - $actual = $ex; - } - - $this->assertSame(['begin', 'handler'], $this->sequence); - $this->assertSame($expected, $actual); - } -} diff --git a/tests/Unit/Application/InboundEventBus/Middleware/LogInboundEventTest.php b/tests/Unit/Application/InboundEventBus/Middleware/LogInboundEventTest.php deleted file mode 100644 index a9212bc5..00000000 --- a/tests/Unit/Application/InboundEventBus/Middleware/LogInboundEventTest.php +++ /dev/null @@ -1,117 +0,0 @@ -logger = $this->createMock(LoggerInterface::class); - $this->event = new TestOutboundEvent(); - } - - public function test(): void - { - $eventName = ModuleBasename::from($this->event); - - $this->logger - ->expects($this->exactly(2)) - ->method('log') - ->willReturnCallback(function ($level, $message, $context) use (&$logs): bool { - $logs[] = [$level, $message, $context]; - return true; - }); - - $middleware = new LogInboundEvent($this->logger); - $middleware($this->event, function (IntegrationEvent $received): void { - $this->assertSame($this->event, $received); - }); - - $context = (new ObjectDecorator($this->event))->context(); - - $this->assertSame([ - [LogLevel::DEBUG, "Receiving integration event {$eventName}.", ['event' => $context]], - [LogLevel::INFO, "Received integration event {$eventName}.", ['event' => $context]], - ], $logs); - } - - public function testWithCustomLevels(): void - { - $eventName = ModuleBasename::from($this->event); - $logs = []; - - $this->logger - ->expects($this->exactly(2)) - ->method('log') - ->willReturnCallback(function ($level, $message, $context) use (&$logs): bool { - $logs[] = [$level, $message, $context]; - return true; - }); - - $middleware = new LogInboundEvent($this->logger, LogLevel::NOTICE, LogLevel::WARNING); - $middleware($this->event, function (IntegrationEvent $received) { - $this->assertSame($this->event, $received); - }); - - $context = (new ObjectDecorator($this->event))->context(); - - $this->assertSame([ - [LogLevel::NOTICE, "Receiving integration event {$eventName}.", ['event' => $context]], - [LogLevel::WARNING, "Received integration event {$eventName}.", ['event' => $context]], - ], $logs); - } - - public function testItLogsAfterTheNextClosureIsInvoked(): void - { - $expected = new LogicException(); - $eventName = ModuleBasename::from($this->event); - - $context = (new ObjectDecorator($this->event))->context(); - - $this->logger - ->expects($this->once()) - ->method('log') - ->with(LogLevel::DEBUG, "Receiving integration event {$eventName}.", ['event' => $context]); - - $middleware = new LogInboundEvent($this->logger); - - try { - $middleware($this->event, static function () use ($expected) { - throw $expected; - }); - $this->fail('No exception thrown.'); - } catch (LogicException $ex) { - $this->assertSame($expected, $ex); - } - } -} diff --git a/tests/Unit/Application/InboundEventBus/Middleware/SetupBeforeEventTest.php b/tests/Unit/Application/InboundEventBus/Middleware/SetupBeforeEventTest.php index ab1b1090..f9bf2311 100644 --- a/tests/Unit/Application/InboundEventBus/Middleware/SetupBeforeEventTest.php +++ b/tests/Unit/Application/InboundEventBus/Middleware/SetupBeforeEventTest.php @@ -13,8 +13,8 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\InboundEventBus\Middleware; use Closure; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\SetupBeforeEvent; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Bus\Middleware\SetupBeforeEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\TestCase; use RuntimeException; diff --git a/tests/Unit/Application/InboundEventBus/Middleware/TearDownAfterEventTest.php b/tests/Unit/Application/InboundEventBus/Middleware/TearDownAfterEventTest.php index 84feabec..1a55f553 100644 --- a/tests/Unit/Application/InboundEventBus/Middleware/TearDownAfterEventTest.php +++ b/tests/Unit/Application/InboundEventBus/Middleware/TearDownAfterEventTest.php @@ -12,8 +12,8 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\InboundEventBus\Middleware; -use CloudCreativity\Modules\Application\InboundEventBus\Middleware\TearDownAfterEvent; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Bus\Middleware\TearDownAfterEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use PHPUnit\Framework\TestCase; use RuntimeException; diff --git a/tests/Unit/Application/InboundEventBus/SwallowInboundEventTest.php b/tests/Unit/Application/InboundEventBus/SwallowInboundEventTest.php index 56a20193..bb12bdef 100644 --- a/tests/Unit/Application/InboundEventBus/SwallowInboundEventTest.php +++ b/tests/Unit/Application/InboundEventBus/SwallowInboundEventTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\InboundEventBus; -use CloudCreativity\Modules\Application\InboundEventBus\SwallowInboundEvent; +use CloudCreativity\Modules\Bus\SwallowInboundEvent; use CloudCreativity\Modules\Toolkit\ModuleBasename; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; diff --git a/tests/Unit/Application/InboundEventBus/TestEventHandler.php b/tests/Unit/Application/InboundEventBus/TestEventHandler.php index 7e84fa99..0bbbc845 100644 --- a/tests/Unit/Application/InboundEventBus/TestEventHandler.php +++ b/tests/Unit/Application/InboundEventBus/TestEventHandler.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\InboundEventBus; -use CloudCreativity\Modules\Contracts\Application\Messages\DispatchThroughMiddleware; +use CloudCreativity\Modules\Contracts\Bus\DispatchThroughMiddleware; class TestEventHandler implements DispatchThroughMiddleware { diff --git a/tests/Unit/Application/InboundEventBus/TestInboundEvent.php b/tests/Unit/Application/InboundEventBus/TestInboundEvent.php index 4f94cce6..ba18ecf9 100644 --- a/tests/Unit/Application/InboundEventBus/TestInboundEvent.php +++ b/tests/Unit/Application/InboundEventBus/TestInboundEvent.php @@ -12,15 +12,15 @@ namespace CloudCreativity\Modules\Tests\Unit\Application\InboundEventBus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; -use CloudCreativity\Modules\Toolkit\Identifiers\Uuid; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; +use CloudCreativity\Modules\Toolkit\Identifiers\UuidV4; use DateTimeImmutable; class TestInboundEvent implements IntegrationEvent { - public function getUuid(): Uuid + public function getUuid(): UuidV4 { - return Uuid::random(); + return UuidV4::make(); } public function getOccurredAt(): DateTimeImmutable diff --git a/tests/Unit/Application/UnitOfWork/UnitOfWorkManagerTest.php b/tests/Unit/Application/UnitOfWork/UnitOfWorkManagerTest.php index 1d0faf74..401a46bc 100644 --- a/tests/Unit/Application/UnitOfWork/UnitOfWorkManagerTest.php +++ b/tests/Unit/Application/UnitOfWork/UnitOfWorkManagerTest.php @@ -14,8 +14,8 @@ use Closure; use CloudCreativity\Modules\Application\UnitOfWork\UnitOfWorkManager; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\ExceptionReporter; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\UnitOfWork; +use CloudCreativity\Modules\Contracts\Application\Ports\ExceptionReporter; +use CloudCreativity\Modules\Contracts\Application\Ports\UnitOfWork; use LogicException; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Bus/PsrPipeContainerTest.php b/tests/Unit/Bus/PsrPipeContainerTest.php new file mode 100644 index 00000000..89cc2108 --- /dev/null +++ b/tests/Unit/Bus/PsrPipeContainerTest.php @@ -0,0 +1,61 @@ + 1; + $b = fn () => 2; + + $container = new PsrPipeContainer(); + $container->bind('PipeA', fn () => $a); + $container->bind('PipeB', fn () => $b); + + $this->assertSame($a, $container->get('PipeA')); + $this->assertSame($b, $container->get('PipeB')); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Unrecognised pipe name: PipeC'); + + $container->get('PipeC'); + } + + public function testItFallsBackToPsrContainer(): void + { + $psrContainer = $this->createMock(ContainerInterface::class); + + $a = fn () => 1; + $b = fn () => 2; + $c = fn () => 3; + + $container = new PsrPipeContainer($psrContainer); + $container->bind('PipeA', fn () => $a); + $container->bind('PipeB', fn () => $b); + + $psrContainer + ->expects($this->once()) + ->method('get') + ->with('PipeC') + ->willReturn($c); + + $this->assertSame($a, $container->get('PipeA')); + $this->assertSame($b, $container->get('PipeB')); + $this->assertSame($c, $container->get('PipeC')); + } +} diff --git a/tests/Unit/Infrastructure/ExceptionReporter/PsrLogExceptionReporterTest.php b/tests/Unit/Infrastructure/ExceptionReporter/PsrLogExceptionReporterTest.php index af3506fa..9fc79686 100644 --- a/tests/Unit/Infrastructure/ExceptionReporter/PsrLogExceptionReporterTest.php +++ b/tests/Unit/Infrastructure/ExceptionReporter/PsrLogExceptionReporterTest.php @@ -12,8 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Infrastructure\ExceptionReporter; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\ExceptionReporter; -use CloudCreativity\Modules\Contracts\Toolkit\Loggable\ContextProvider; +use CloudCreativity\Modules\Contracts\Application\Ports\ExceptionReporter; use CloudCreativity\Modules\Infrastructure\ExceptionReporter\PsrLogExceptionReporter; use LogicException; use PHPUnit\Framework\MockObject\MockObject; @@ -73,7 +72,10 @@ public function testItReportsDefaultMessageIfExceptionHasEmptyMessage(): void public function testItLogsContextForExceptionThatImplementsContextProvider(): void { - $exception = new class ('Boom!') extends LogicException implements ContextProvider { + $exception = new class ('Boom!') extends LogicException { + /** + * @return array + */ public function context(): array { return ['foo' => 'bar', 'exception' => null]; diff --git a/tests/Unit/Infrastructure/OutboundEventBus/ClosurePublisherTest.php b/tests/Unit/Infrastructure/OutboundEventBus/ClosurePublisherTest.php index 5973fab0..177751f0 100644 --- a/tests/Unit/Infrastructure/OutboundEventBus/ClosurePublisherTest.php +++ b/tests/Unit/Infrastructure/OutboundEventBus/ClosurePublisherTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Infrastructure\OutboundEventBus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer as IPipeContainer; use CloudCreativity\Modules\Infrastructure\OutboundEventBus\ClosurePublisher; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Infrastructure/OutboundEventBus/Middleware/LogOutboundEventTest.php b/tests/Unit/Infrastructure/OutboundEventBus/Middleware/LogOutboundEventTest.php deleted file mode 100644 index 5021e512..00000000 --- a/tests/Unit/Infrastructure/OutboundEventBus/Middleware/LogOutboundEventTest.php +++ /dev/null @@ -1,117 +0,0 @@ -logger = $this->createMock(LoggerInterface::class); - $this->event = new TestOutboundEvent(); - } - - public function test(): void - { - $eventName = ModuleBasename::from($this->event); - - $this->logger - ->expects($this->exactly(2)) - ->method('log') - ->willReturnCallback(function ($level, $message, $context) use (&$logs): bool { - $logs[] = [$level, $message, $context]; - return true; - }); - - $middleware = new LogOutboundEvent($this->logger); - $middleware($this->event, function (IntegrationEvent $received): void { - $this->assertSame($this->event, $received); - }); - - $context = (new ObjectDecorator($this->event))->context(); - - $this->assertSame([ - [LogLevel::DEBUG, "Publishing integration event {$eventName}.", ['event' => $context]], - [LogLevel::INFO, "Published integration event {$eventName}.", ['event' => $context]], - ], $logs); - } - - public function testWithCustomLevels(): void - { - $eventName = ModuleBasename::from($this->event); - $logs = []; - - $this->logger - ->expects($this->exactly(2)) - ->method('log') - ->willReturnCallback(function ($level, $message, $context) use (&$logs): bool { - $logs[] = [$level, $message, $context]; - return true; - }); - - $middleware = new LogOutboundEvent($this->logger, LogLevel::NOTICE, LogLevel::WARNING); - $middleware($this->event, function (IntegrationEvent $received) { - $this->assertSame($this->event, $received); - }); - - $context = (new ObjectDecorator($this->event))->context(); - - $this->assertSame([ - [LogLevel::NOTICE, "Publishing integration event {$eventName}.", ['event' => $context]], - [LogLevel::WARNING, "Published integration event {$eventName}.", ['event' => $context]], - ], $logs); - } - - public function testItLogsAfterTheNextClosureIsInvoked(): void - { - $expected = new LogicException(); - $eventName = ModuleBasename::from($this->event); - - $context = (new ObjectDecorator($this->event))->context(); - - $this->logger - ->expects($this->once()) - ->method('log') - ->with(LogLevel::DEBUG, "Publishing integration event {$eventName}.", ['event' => $context]); - - $middleware = new LogOutboundEvent($this->logger); - - try { - $middleware($this->event, static function () use ($expected) { - throw $expected; - }); - $this->fail('No exception thrown.'); - } catch (LogicException $ex) { - $this->assertSame($expected, $ex); - } - } -} diff --git a/tests/Unit/Infrastructure/OutboundEventBus/TestOutboundEvent.php b/tests/Unit/Infrastructure/OutboundEventBus/TestOutboundEvent.php index ca8ad198..8ec03222 100644 --- a/tests/Unit/Infrastructure/OutboundEventBus/TestOutboundEvent.php +++ b/tests/Unit/Infrastructure/OutboundEventBus/TestOutboundEvent.php @@ -12,13 +12,13 @@ namespace CloudCreativity\Modules\Tests\Unit\Infrastructure\OutboundEventBus; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; -use CloudCreativity\Modules\Toolkit\Identifiers\Uuid; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; +use CloudCreativity\Modules\Toolkit\Identifiers\UuidV4; use DateTimeImmutable; class TestOutboundEvent implements IntegrationEvent { - public readonly Uuid $uuid; + public readonly UuidV4 $uuid; public readonly DateTimeImmutable $occurredAt; @@ -27,11 +27,11 @@ class TestOutboundEvent implements IntegrationEvent */ public function __construct() { - $this->uuid = Uuid::random(); + $this->uuid = UuidV4::make(); $this->occurredAt = new DateTimeImmutable(); } - public function getUuid(): Uuid + public function getUuid(): UuidV4 { return $this->uuid; } diff --git a/tests/Unit/Infrastructure/Queue/ClosureQueueTest.php b/tests/Unit/Infrastructure/Queue/ClosureQueueTest.php index ca6a7eb2..12de5c2a 100644 --- a/tests/Unit/Infrastructure/Queue/ClosureQueueTest.php +++ b/tests/Unit/Infrastructure/Queue/ClosureQueueTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Infrastructure\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Infrastructure\Queue\ClosureQueue; use CloudCreativity\Modules\Tests\Unit\Application\Bus\TestCommand; diff --git a/tests/Unit/Infrastructure/Queue/ComponentQueueTest.php b/tests/Unit/Infrastructure/Queue/ComponentQueueTest.php index 35de6222..26821351 100644 --- a/tests/Unit/Infrastructure/Queue/ComponentQueueTest.php +++ b/tests/Unit/Infrastructure/Queue/ComponentQueueTest.php @@ -14,7 +14,7 @@ use CloudCreativity\Modules\Contracts\Infrastructure\Queue\Enqueuer; use CloudCreativity\Modules\Contracts\Infrastructure\Queue\EnqueuerContainer; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Contracts\Toolkit\Pipeline\PipeContainer; use CloudCreativity\Modules\Infrastructure\Queue\ComponentQueue; use PHPUnit\Framework\MockObject\MockObject; diff --git a/tests/Unit/Infrastructure/Queue/EnqueuerContainerTest.php b/tests/Unit/Infrastructure/Queue/EnqueuerContainerTest.php index 0b67a36c..a478f17d 100644 --- a/tests/Unit/Infrastructure/Queue/EnqueuerContainerTest.php +++ b/tests/Unit/Infrastructure/Queue/EnqueuerContainerTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Infrastructure\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Infrastructure\Queue\Enqueuer; use CloudCreativity\Modules\Infrastructure\Queue\EnqueuerContainer; use CloudCreativity\Modules\Tests\Unit\Application\Bus\TestCommand; diff --git a/tests/Unit/Infrastructure/Queue/EnqueuerTest.php b/tests/Unit/Infrastructure/Queue/EnqueuerTest.php index 3768cee6..7c18dd9b 100644 --- a/tests/Unit/Infrastructure/Queue/EnqueuerTest.php +++ b/tests/Unit/Infrastructure/Queue/EnqueuerTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Infrastructure\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Infrastructure\Queue\Enqueuer; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Infrastructure/Queue/Middleware/LogPushedToQueueTest.php b/tests/Unit/Infrastructure/Queue/Middleware/LogPushedToQueueTest.php deleted file mode 100644 index b4f864a1..00000000 --- a/tests/Unit/Infrastructure/Queue/Middleware/LogPushedToQueueTest.php +++ /dev/null @@ -1,153 +0,0 @@ -logger = $this->createMock(LoggerInterface::class); - $this->context = $this->createMock(ContextFactory::class); - } - - protected function tearDown(): void - { - parent::tearDown(); - unset($this->logger, $this->context); - } - - public function testWithDefaultLevels(): void - { - $command = new class () implements Command { - public string $foo = 'bar'; - public string $baz = 'bat'; - }; - - $name = $command::class; - $logs = []; - $context = $this->withContext($command); - - $this->logger - ->expects($this->exactly(2)) - ->method('log') - ->willReturnCallback(function ($level, $message, $context) use (&$logs): bool { - $logs[] = [$level, $message, $context]; - return true; - }); - - $middleware = new LogPushedToQueue($this->logger, context: $this->context); - $middleware( - $command, - function (Command $received) use ($command): void { - $this->assertSame($command, $received); - }, - ); - - $this->assertSame([ - [LogLevel::DEBUG, "Queuing command {$name}.", ['command' => $context]], - [LogLevel::INFO, "Queued command {$name}.", ['command' => $context]], - ], $logs); - } - - public function testWithCustomLevels(): void - { - $command = new class () implements Command { - public string $foo = 'bar'; - public string $baz = 'bat'; - }; - - $name = $command::class; - $logs = []; - $context = $this->withContext($command); - - $this->logger - ->expects($this->exactly(2)) - ->method('log') - ->willReturnCallback(function ($level, $message, $context) use (&$logs): bool { - $logs[] = [$level, $message, $context]; - return true; - }); - - $middleware = new LogPushedToQueue($this->logger, LogLevel::NOTICE, LogLevel::WARNING, $this->context); - $middleware($command, function (Command $received) use ($command): void { - $this->assertSame($command, $received); - }); - - $this->assertSame([ - [LogLevel::NOTICE, "Queuing command {$name}.", ['command' => $context]], - [LogLevel::WARNING, "Queued command {$name}.", ['command' => $context]], - ], $logs); - } - - public function testItLogsAfterTheNextClosureIsInvoked(): void - { - $command = new class () implements Command { - public string $foo = 'bar'; - public string $baz = 'bat'; - }; - - $expected = new LogicException(); - $name = $command::class; - $context = $this->withContext($command); - - $this->logger - ->expects($this->once()) - ->method('log') - ->with(LogLevel::DEBUG, "Queuing command {$name}.", ['command' => $context]); - - $middleware = new LogPushedToQueue($this->logger, context: $this->context); - - try { - $middleware($command, static function () use ($expected): never { - throw $expected; - }); - $this->fail('No exception thrown.'); - } catch (LogicException $ex) { - $this->assertSame($expected, $ex); - } - } - - /** - * @return array - */ - private function withContext(object $expected): array - { - $this->context - ->expects($this->once()) - ->method('make') - ->with($this->identicalTo($expected)) - ->willReturn($context = ['foobar' => 'bazbat!']); - - return $context; - } -} diff --git a/tests/Unit/Infrastructure/Queue/TestEnqueuer.php b/tests/Unit/Infrastructure/Queue/TestEnqueuer.php index 3a172302..8a1b845d 100644 --- a/tests/Unit/Infrastructure/Queue/TestEnqueuer.php +++ b/tests/Unit/Infrastructure/Queue/TestEnqueuer.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Infrastructure\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Messaging\Command; class TestEnqueuer { diff --git a/tests/Unit/Testing/FakeExceptionReporterTest.php b/tests/Unit/Testing/FakeExceptionReporterTest.php index 69c6fd96..3848d88a 100644 --- a/tests/Unit/Testing/FakeExceptionReporterTest.php +++ b/tests/Unit/Testing/FakeExceptionReporterTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Testing; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\ExceptionReporter; +use CloudCreativity\Modules\Contracts\Application\Ports\ExceptionReporter; use CloudCreativity\Modules\Testing\FakeExceptionReporter; use LogicException; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Testing/FakeOutboundEventPublisherTest.php b/tests/Unit/Testing/FakeOutboundEventPublisherTest.php index beaf2cd7..e30b3c4c 100644 --- a/tests/Unit/Testing/FakeOutboundEventPublisherTest.php +++ b/tests/Unit/Testing/FakeOutboundEventPublisherTest.php @@ -12,8 +12,8 @@ namespace CloudCreativity\Modules\Tests\Unit\Testing; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\OutboundEventPublisher; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\IntegrationEvent; +use CloudCreativity\Modules\Contracts\Application\Ports\OutboundEventPublisher; +use CloudCreativity\Modules\Contracts\Messaging\IntegrationEvent; use CloudCreativity\Modules\Testing\FakeOutboundEventPublisher; use LogicException; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Testing/FakeQueueTest.php b/tests/Unit/Testing/FakeQueueTest.php index 8d876c7b..7d0356d8 100644 --- a/tests/Unit/Testing/FakeQueueTest.php +++ b/tests/Unit/Testing/FakeQueueTest.php @@ -12,8 +12,8 @@ namespace CloudCreativity\Modules\Tests\Unit\Testing; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\Queue; -use CloudCreativity\Modules\Contracts\Toolkit\Messages\Command; +use CloudCreativity\Modules\Contracts\Application\Ports\Queue; +use CloudCreativity\Modules\Contracts\Messaging\Command; use CloudCreativity\Modules\Testing\FakeQueue; use LogicException; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Testing/FakeUnitOfWorkTest.php b/tests/Unit/Testing/FakeUnitOfWorkTest.php index e291ccdf..e09c1cef 100644 --- a/tests/Unit/Testing/FakeUnitOfWorkTest.php +++ b/tests/Unit/Testing/FakeUnitOfWorkTest.php @@ -12,7 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Testing; -use CloudCreativity\Modules\Contracts\Application\Ports\Driven\UnitOfWork; +use CloudCreativity\Modules\Contracts\Application\Ports\UnitOfWork; use CloudCreativity\Modules\Testing\FakeUnitOfWork; use PHPUnit\Framework\TestCase; use RuntimeException; diff --git a/tests/Unit/Toolkit/Identifiers/GuidTest.php b/tests/Unit/Toolkit/Identifiers/GuidTest.php index e42ec70d..51bec62a 100644 --- a/tests/Unit/Toolkit/Identifiers/GuidTest.php +++ b/tests/Unit/Toolkit/Identifiers/GuidTest.php @@ -13,6 +13,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Toolkit\Identifiers; use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Identifier; +use CloudCreativity\Modules\Contracts\Toolkit\Identifiers\Uuid as IUuid; use CloudCreativity\Modules\Tests\TestBackedEnum; use CloudCreativity\Modules\Tests\TestUnitEnum; use CloudCreativity\Modules\Toolkit\ContractException; @@ -20,6 +21,7 @@ use CloudCreativity\Modules\Toolkit\Identifiers\IntegerId; use CloudCreativity\Modules\Toolkit\Identifiers\StringId; use CloudCreativity\Modules\Toolkit\Identifiers\Uuid; +use CloudCreativity\Modules\Toolkit\Identifiers\UuidV4; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Ramsey\Uuid\Uuid as BaseUuid; @@ -115,7 +117,7 @@ public function testUuid(string|UnitEnum $type, string $value, string|UnitEnum $ $guid = Guid::fromUuid($type, $uuid->value); $this->assertSame($type, $guid->type); - $this->assertObjectEquals($uuid, $guid->id); + $this->assertTrue($uuid->is($guid->id)); $this->assertObjectEquals($guid, Guid::fromUuid($type, $uuid)); $this->assertSame($value . ':' . $uuid->toString(), $guid->toString()); $this->assertSame($value . ':' . $uuid->toString(), (string) $guid); @@ -132,11 +134,11 @@ public function testUuid(string|UnitEnum $type, string $value, string|UnitEnum $ } /** - * @return array + * @return array */ public static function makeProvider(): array { - $uuid = Uuid::random(); + $uuid = UuidV4::make(); return [ 'integer' => [123, new IntegerId(123)], @@ -148,10 +150,10 @@ public static function makeProvider(): array } #[DataProvider('makeProvider')] - public function testItMakesGuid(int|string|Uuid|UuidInterface $value, Identifier $expected): void + public function testItMakesGuid(int|IUuid|string|UuidInterface $value, Identifier $expected): void { $guid = Guid::make('SomeType', $value); - $this->assertObjectEquals($expected, $guid->id); + $this->assertTrue($expected->is($guid->id)); $this->assertSame($guid, Guid::from($guid)); $this->assertSame($guid, Guid::tryFrom($guid)); } diff --git a/tests/Unit/Toolkit/Identifiers/UuidFactoryTest.php b/tests/Unit/Toolkit/Identifiers/UuidFactoryTest.php index d7af207e..59e09ad0 100644 --- a/tests/Unit/Toolkit/Identifiers/UuidFactoryTest.php +++ b/tests/Unit/Toolkit/Identifiers/UuidFactoryTest.php @@ -16,6 +16,8 @@ use CloudCreativity\Modules\Toolkit\ContractException; use CloudCreativity\Modules\Toolkit\Identifiers\Uuid; use CloudCreativity\Modules\Toolkit\Identifiers\UuidFactory; +use CloudCreativity\Modules\Toolkit\Identifiers\UuidV4; +use CloudCreativity\Modules\Toolkit\Identifiers\UuidV7; use DateTimeImmutable; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -198,7 +200,7 @@ public function testUuid4(): void $uuid = $this->factory->uuid4(); - $this->assertInstanceOf(Uuid::class, $uuid); + $this->assertInstanceOf(UuidV4::class, $uuid); $this->assertSame($uuid->value, $base); } @@ -244,11 +246,11 @@ public function testUuid7(): void ->expects($this->once()) ->method('uuid7') ->with($this->identicalTo($date)) - ->willReturn($base = BaseUuid::uuid4()); + ->willReturn($base = BaseUuid::uuid7()); $uuid = $this->factory->uuid7($date); - $this->assertInstanceOf(Uuid::class, $uuid); + $this->assertInstanceOf(UuidV7::class, $uuid); $this->assertSame($uuid->value, $base); } diff --git a/tests/Unit/Toolkit/Identifiers/UuidTest.php b/tests/Unit/Toolkit/Identifiers/UuidTest.php index c211e7aa..b3505d25 100644 --- a/tests/Unit/Toolkit/Identifiers/UuidTest.php +++ b/tests/Unit/Toolkit/Identifiers/UuidTest.php @@ -51,8 +51,9 @@ public function test(): void public function testItIsEquals(): void { $base = RamseyUuid::uuid4(); + $id = new Uuid($base); - $this->assertObjectEquals($id = new Uuid($base), $other = Uuid::from($base)); + $this->assertTrue($id->is($other = Uuid::from($base))); $this->assertSame($id, Uuid::from($id)); $this->assertTrue($id->is($other)); $this->assertTrue($id->any(null, Uuid::random(), $other)); @@ -63,7 +64,7 @@ public function testItIsEquals(): void public function testItIsNotEqual(): void { $id = new Uuid(RamseyUuid::fromString('6dcbad65-ed92-4e60-973b-9ba58a022816')); - $this->assertFalse($id->equals($other = new Uuid( + $this->assertFalse($id->is($other = new Uuid( RamseyUuid::fromString('38c7be26-6887-4742-8b6b-7d07b30ca596'), ))); $this->assertFalse($id->is($other)); @@ -164,6 +165,6 @@ public function testNil(): void $base = RamseyUuid::fromString(RamseyUuid::NIL); $actual = Uuid::nil(); - $this->assertTrue($actual->value->equals($base)); + $this->assertTrue($actual->toBase()->equals($base)); } } diff --git a/tests/Unit/Toolkit/Identifiers/UuidV4Test.php b/tests/Unit/Toolkit/Identifiers/UuidV4Test.php index 9d183582..d9a86bee 100644 --- a/tests/Unit/Toolkit/Identifiers/UuidV4Test.php +++ b/tests/Unit/Toolkit/Identifiers/UuidV4Test.php @@ -46,22 +46,23 @@ public function test(): void public function testItIsEquals(): void { $base = RamseyUuid::uuid4(); + $id = UuidV4::from($base); - $this->assertObjectEquals($id = UuidV4::from($base), $other = UuidV4::from($base)); + $this->assertTrue($id->is($other = UuidV4::from($base))); $this->assertSame($id, UuidV4::from($id)); $this->assertTrue($id->is($other)); $this->assertTrue($id->any(null, UuidV4::make(), $other)); $this->assertEquals($id, UuidV4::tryFrom($base)); $this->assertSame($id, UuidV4::tryFrom($id)); + $this->assertTrue($id->is(new Uuid($base))); } public function testItIsNotEqual(): void { - $id = UuidV4::from($base = RamseyUuid::fromString('6dcbad65-ed92-4e60-973b-9ba58a022816')); - $this->assertFalse($id->equals($other = UuidV4::from( + $id = UuidV4::from(RamseyUuid::fromString('6dcbad65-ed92-4e60-973b-9ba58a022816')); + $this->assertFalse($id->is($other = UuidV4::from( RamseyUuid::fromString('38c7be26-6887-4742-8b6b-7d07b30ca596'), ))); - $this->assertFalse($id->is(new Uuid($base))); // not equal as not specifically UuidV4 $this->assertFalse($id->is($other)); $this->assertFalse($id->any(null, UuidV4::make(), $other)); } @@ -109,7 +110,7 @@ public function testFromWithString(): void { $base = RamseyUuid::fromString('6dcbad65-ed92-4e60-973b-9ba58a022816'); - $this->assertObjectEquals(UuidV4::from($base), UuidV4::from($base->toString())); + $this->assertTrue(UuidV4::from($base)->is(UuidV4::from($base->toString()))); } public function testTryFromWithString(): void diff --git a/tests/Unit/Toolkit/Identifiers/UuidV7Test.php b/tests/Unit/Toolkit/Identifiers/UuidV7Test.php index b914a93e..92ccbfca 100644 --- a/tests/Unit/Toolkit/Identifiers/UuidV7Test.php +++ b/tests/Unit/Toolkit/Identifiers/UuidV7Test.php @@ -46,22 +46,23 @@ public function test(): void public function testItIsEquals(): void { $base = RamseyUuid::uuid7(); + $id = UuidV7::from($base); - $this->assertObjectEquals($id = UuidV7::from($base), $other = UuidV7::from($base)); + $this->assertTrue($id->is($other = UuidV7::from($base))); $this->assertSame($id, UuidV7::from($id)); $this->assertTrue($id->is($other)); $this->assertTrue($id->any(null, UuidV7::make(), $other)); $this->assertEquals($id, UuidV7::tryFrom($base)); $this->assertSame($id, UuidV7::tryFrom($id)); + $this->assertTrue($id->is(new Uuid($base))); } public function testItIsNotEqual(): void { - $id = UuidV7::from($base = RamseyUuid::fromString('019b7acc-aff8-7f70-adc9-e9c7f632e6df')); - $this->assertFalse($id->equals($other = UuidV7::from( + $id = UuidV7::from(RamseyUuid::fromString('019b7acc-aff8-7f70-adc9-e9c7f632e6df')); + $this->assertFalse($id->is($other = UuidV7::from( RamseyUuid::fromString('019b7acd-0f6f-7828-a1cf-94c34a239594'), ))); - $this->assertFalse($id->is(new Uuid($base))); // not equal as not specifically UuidV7 $this->assertFalse($id->is($other)); $this->assertFalse($id->any(null, UuidV7::make(), $other)); } @@ -109,7 +110,7 @@ public function testFromWithString(): void { $base = RamseyUuid::fromString('019b7acc-aff8-7f70-adc9-e9c7f632e6df'); - $this->assertObjectEquals(UuidV7::from($base), UuidV7::from($base->toString())); + $this->assertTrue(UuidV7::from($base)->is(UuidV7::from($base->toString()))); } public function testTryFromWithString(): void diff --git a/tests/Unit/Toolkit/Loggable/ObjectDecoratorTest.php b/tests/Unit/Toolkit/Loggable/ObjectDecoratorTest.php deleted file mode 100644 index e5116aa7..00000000 --- a/tests/Unit/Toolkit/Loggable/ObjectDecoratorTest.php +++ /dev/null @@ -1,159 +0,0 @@ -factory = new SimpleContextFactory(); - } - - protected function tearDown(): void - { - parent::tearDown(); - unset($this->factory); - } - - public function testItUsesObjectProperties(): void - { - $uuid = Uuid::uuid4(); - $date1 = new \DateTimeImmutable(); - $date2 = new \DateTime('2025-01-01 12:34:56', new \DateTimeZone('Australia/Sydney')); - - $source = new class ($uuid, $date1, $date2, $date2->getTimezone()) implements Message { - public string $foo = 'bar'; - public string $baz = 'bat'; - public ?string $blah = null; - public UnitEnum $enum1 = TestBackedEnum::Foo; - public UnitEnum $enum2 = TestBackedIntEnum::FooBar; - public UnitEnum $enum3 = TestUnitEnum::Baz; - protected string $foobar = 'foobar'; - - public function __construct( - public UuidInterface $uuid, - public DateTimeInterface $date1, - public DateTimeInterface $date2, - public \DateTimeZone $timeZone, - ) { - } - }; - - $expected = [ - 'foo' => 'bar', - 'baz' => 'bat', - 'blah' => null, - 'enum1' => TestBackedEnum::Foo->value, - 'enum2' => TestBackedIntEnum::FooBar->name, - 'enum3' => TestUnitEnum::Baz->name, - 'uuid' => $uuid->toString(), - 'date1' => $date1->format('Y-m-d\TH:i:s.uP'), - 'date2' => $date2->format('Y-m-d\TH:i:s.uP'), - 'timeZone' => 'Australia/Sydney', - ]; - - $decorator = new ObjectDecorator($source); - - $this->assertInstanceOf(ContextProvider::class, $decorator); - $this->assertSame($expected, iterator_to_array($decorator)); - $this->assertSame($expected, $decorator->all()); - $this->assertSame($expected, $decorator->context()); - $this->assertSame($expected, $this->factory->make($source)); - $this->assertSame(array_keys($expected), $decorator->keys()); - } - - public function testItCanCustomiseDateFormat(): void - { - $date = new DateTimeImmutable('2025-01-01 12:34:56', new \DateTimeZone('Australia/Sydney')); - - $source = new class ($date) implements Message { - public function __construct(public DateTimeInterface $date) - { - } - }; - - $expected = [ - 'date' => $date->format('Y-m-d H:i:s'), - ]; - - $decorator = new ObjectDecorator($source, dateFormat: 'Y-m-d H:i:s'); - - $this->assertSame($expected, $decorator->context()); - } - - public function testItCanTurnOffDateFormatting(): void - { - $date = new DateTimeImmutable('2025-01-01 12:34:56', new \DateTimeZone('Australia/Sydney')); - - $source = new class ($date) implements Message { - public function __construct(public DateTimeInterface $date) - { - } - }; - - $expected = [ - 'date' => $date, - ]; - - $decorator = new ObjectDecorator($source, dateFormat: null); - - $this->assertSame($expected, $decorator->context()); - } - - public function testItExcludesSensitiveProperties(): void - { - $source = new class ('Hello', 'World') implements Message { - public string $foo = 'bar'; - #[Sensitive] - public string $baz = 'bat'; - public string $foobar = 'foobar'; - - public function __construct( - #[Sensitive] public string $blah1, - public string $blah2, - ) { - } - }; - - $expected = [ - 'foo' => 'bar', - 'foobar' => 'foobar', - 'blah2' => 'World', - ]; - - $decorator = new ObjectDecorator($source); - - $this->assertSame(array_keys($expected), $decorator->keys()); - $this->assertSame($expected, $decorator->all()); - $this->assertSame($expected, $decorator->context()); - $this->assertSame($expected, $this->factory->make($source)); - } -} diff --git a/tests/Unit/Toolkit/Loggable/ResultDecoratorTest.php b/tests/Unit/Toolkit/Loggable/ResultDecoratorTest.php deleted file mode 100644 index 59dcd866..00000000 --- a/tests/Unit/Toolkit/Loggable/ResultDecoratorTest.php +++ /dev/null @@ -1,294 +0,0 @@ - - */ -interface ResultWithContext extends IResult, ContextProvider -{ -} - -interface ErrorWithContext extends IError, ContextProvider -{ -} - -class ResultDecoratorTest extends TestCase -{ - private SimpleContextFactory $factory; - - protected function setUp(): void - { - parent::setUp(); - $this->factory = new SimpleContextFactory(); - } - - protected function tearDown(): void - { - parent::tearDown(); - unset($this->factory); - } - - public function testSuccess(): void - { - $result = Result::ok(); - - $expected = [ - 'success' => true, - ]; - - $decorator = new ResultDecorator($result); - - $this->assertInstanceOf(ContextProvider::class, $decorator); - $this->assertSame($expected, $decorator->context()); - $this->assertSame($expected, $this->factory->make($result)); - } - - public function testSuccessWithContextProvider(): void - { - $expected = [ - 'success' => true, - 'value' => [ - 'foo' => 'bar', - 'blah!' => 'blah!!', - ], - ]; - - $value = $this->createMock(ContextProvider::class); - $value->method('context')->willReturn($expected['value']); - - $result = Result::ok($value); - - $this->assertSame($expected, (new ResultDecorator($result))->context()); - $this->assertSame($expected, $this->factory->make($result)); - } - - public function testSuccessWithIdentifier(): void - { - $expected = [ - 'success' => true, - 'value' => 99, - ]; - - $value = $this->createMock(Contextual::class); - $value->method('context')->willReturn($expected['value']); - - $result = Result::ok($value); - - $this->assertSame($expected, (new ResultDecorator($result))->context()); - $this->assertSame($expected, $this->factory->make($result)); - } - - /** - * @return array> - */ - public static function scalarProvider(): array - { - return [ - [true], - [false], - [1], - [1.1], - ['foo'], - ]; - } - - #[DataProvider('scalarProvider')] - public function testSuccessWithScalarOrNull(mixed $value): void - { - $expected = [ - 'success' => true, - 'value' => $value, - ]; - - $result = Result::ok($value); - - $this->assertSame($expected, (new ResultDecorator($result))->context()); - $this->assertSame($expected, $this->factory->make($result)); - } - - public function testSuccessContextWithMeta(): void - { - $result = Result::ok()->withMeta(['foo' => 'bar']); - - $expected = [ - 'success' => true, - 'meta' => [ - 'foo' => 'bar', - ], - ]; - - $this->assertSame($expected, (new ResultDecorator($result))->context()); - $this->assertSame($expected, $this->factory->make($result)); - } - - /** - * @return array> - */ - public static function onlyMessageProvider(): array - { - return [ - ['Something went wrong.'], - [new Error(message: 'Something went wrong.')], - ]; - } - - #[DataProvider('onlyMessageProvider')] - public function testFailureContextWithErrorThatOnlyHasMessage(Error|string $error): void - { - $result = Result::failed($error); - - $expected = [ - 'success' => false, - 'error' => is_string($error) ? $error : $error->message(), - ]; - - $this->assertSame($expected, (new ResultDecorator($result))->context()); - $this->assertSame($expected, $this->factory->make($result)); - } - - /** - * @return array> - */ - public static function onlyCodeProvider(): array - { - return [ - [TestUnitEnum::Baz], - [new Error(code: TestBackedEnum::Bar)], - ]; - } - - /** - * @param BackedEnum|Error $error - */ - #[DataProvider('onlyCodeProvider')] - public function testFailureContextWithErrorThatOnlyHasCode(Error|UnitEnum $error): void - { - $result = Result::failed($error); - $code = $error instanceof UnitEnum ? $error : $error->code(); - - $expected = [ - 'success' => false, - 'error' => enum_string($code ?? '!!'), - ]; - - $this->assertSame($expected, (new ResultDecorator($result))->context()); - $this->assertSame($expected, $this->factory->make($result)); - } - - /** - * @return array> - */ - public static function errorsProvider(): array - { - $error1 = new Error( - code: TestBackedEnum::Bar, - message: 'Something went wrong.', - key: 'foo', - ); - - $error2 = new Error( - code: TestBackedIntEnum::FooBar, - message: 'Something else went wrong.', - key: TestBackedIntEnum::BazBat, - ); - - $expected1 = [ - 'code' => TestBackedEnum::Bar->value, - 'key' => 'foo', - 'message' => 'Something went wrong.', - ]; - - $expected2 = [ - 'code' => TestBackedIntEnum::FooBar->name, - 'key' => TestBackedIntEnum::BazBat->name, - 'message' => 'Something else went wrong.', - ]; - - return [ - [[$error1], [$expected1]], - [[$error1, $error2], [$expected1, $expected2]], - ]; - } - - /** - * @param array $errors - * @param array> $expected - */ - #[DataProvider('errorsProvider')] - public function testFailureContextWithMeta(array $errors, array $expected): void - { - $result = Result::failed($errors)->withMeta(['baz' => 'bat']); - - $expected = [ - 'success' => false, - 'errors' => $expected, - 'meta' => [ - 'baz' => 'bat', - ], - ]; - - $this->assertSame($expected, (new ResultDecorator($result))->context()); - $this->assertSame($expected, $this->factory->make($result)); - } - - public function testItHasLogContext(): void - { - $mock = $this->createMock(ResultWithContext::class); - $mock->method('context')->willReturn($expected = ['foo' => 'bar', 'baz' => 'bat']); - - $this->assertSame($expected, (new ResultDecorator($mock))->context()); - $this->assertSame($expected, $this->factory->make($mock)); - } - - public function testItHasErrorWithLogContext(): void - { - $mock = $this->createMock(ErrorWithContext::class); - $mock->method('context')->willReturn($expected = ['foo' => 'bar', 'baz' => 'bat']); - - $error = new Error(null, 'Something went wrong.'); - - $result = Result::failed([$mock, $error]); - - $expected = [ - 'success' => false, - 'errors' => [ - $expected, - [ - 'message' => 'Something went wrong.', - ], - ], - ]; - - $this->assertSame($expected, (new ResultDecorator($result))->context()); - $this->assertSame($expected, $this->factory->make($result)); - } -} diff --git a/tests/Unit/Toolkit/Pipeline/PipeContainerTest.php b/tests/Unit/Toolkit/Pipeline/PipeContainerTest.php index 85fc054d..2ff58ec3 100644 --- a/tests/Unit/Toolkit/Pipeline/PipeContainerTest.php +++ b/tests/Unit/Toolkit/Pipeline/PipeContainerTest.php @@ -14,7 +14,6 @@ use CloudCreativity\Modules\Toolkit\Pipeline\PipeContainer; use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; class PipeContainerTest extends TestCase { @@ -35,27 +34,4 @@ public function testItResolvesBoundPipes(): void $container->get('PipeC'); } - - public function testItFallsBackToPsrContainer(): void - { - $psrContainer = $this->createMock(ContainerInterface::class); - - $a = fn () => 1; - $b = fn () => 2; - $c = fn () => 3; - - $container = new PipeContainer($psrContainer); - $container->bind('PipeA', fn () => $a); - $container->bind('PipeB', fn () => $b); - - $psrContainer - ->expects($this->once()) - ->method('get') - ->with('PipeC') - ->willReturn($c); - - $this->assertSame($a, $container->get('PipeA')); - $this->assertSame($b, $container->get('PipeB')); - $this->assertSame($c, $container->get('PipeC')); - } } diff --git a/tests/Unit/Toolkit/Result/FailedResultExceptionTest.php b/tests/Unit/Toolkit/Result/FailedResultExceptionTest.php index 41cdf4c5..8e03049d 100644 --- a/tests/Unit/Toolkit/Result/FailedResultExceptionTest.php +++ b/tests/Unit/Toolkit/Result/FailedResultExceptionTest.php @@ -12,9 +12,7 @@ namespace CloudCreativity\Modules\Tests\Unit\Toolkit\Result; -use CloudCreativity\Modules\Contracts\Toolkit\Loggable\ContextProvider; use CloudCreativity\Modules\Tests\TestUnitEnum; -use CloudCreativity\Modules\Toolkit\Loggable\SimpleContextFactory; use CloudCreativity\Modules\Toolkit\Result\FailedResultException; use CloudCreativity\Modules\Toolkit\Result\Result; use PHPUnit\Framework\TestCase; @@ -30,8 +28,6 @@ public function testItFailsWithMessage(): void $this->assertSame($result, $exception->getResult()); $this->assertSame('Something went wrong.', $exception->getMessage()); - $this->assertInstanceOf(ContextProvider::class, $exception); - $this->assertSame((new SimpleContextFactory())->make($result), $exception->context()); } public function testItFailsWithErrorCode(): void