Skip to content

Commit

Permalink
Add a "boot" phase (#192)
Browse files Browse the repository at this point in the history
* Add Mount Hook and allow classnames in registration

* Fix styling

* Update src/Lifecycle/Dispatcher.php

Co-authored-by: Chris Morrell <[email protected]>

* WIP

* Fix styling

* Add support for base class matching

* Rename mount to boot

* Fix styling

* WIP

* WIP

* Fix styling

* Scope down to just "boot" portion of changes

* Account for Laravel bug

* Fix styling

* Revert for now

* Fix styling

---------

Co-authored-by: DanielCoulbourne <[email protected]>
Co-authored-by: Chris Morrell <[email protected]>
  • Loading branch information
3 people authored Dec 19, 2024
1 parent b178c35 commit d83543b
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Lifecycle/Broker.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public function fire(Event $event): ?Event
// NOTE: Any changes to how the dispatcher is called here
// should also be applied to the `replay` method

$this->dispatcher->boot($event);

Guards::for($event)->check();

$this->dispatcher->apply($event);
Expand Down
19 changes: 19 additions & 0 deletions src/Lifecycle/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ public function skipPhases(Phase ...$phases): void
$this->skipped_phases = $phases;
}

public function boot(Event $event): void
{
if ($this->shouldDispatchPhase(Phase::Boot)) {
$this->getBootHooks($event)->each(fn (Hook $hook) => $hook->boot($this->container, $event));
}
}

public function validate(Event $event): bool
{
if (! $this->shouldDispatchPhase(Phase::Validate)) {
Expand Down Expand Up @@ -85,6 +92,18 @@ public function replay(Event $event): void
}
}

/** @return Collection<int, Hook> */
protected function getBootHooks(Event $event): Collection
{
$hooks = $this->hooksFor($event, Phase::Boot);

if (method_exists($event, 'boot')) {
$hooks->prepend(Hook::fromClassMethod($event, 'boot')->forcePhases(Phase::Boot));
}

return $hooks;
}

/** @return Collection<int, Hook> */
protected function getFiredHooks(Event $event): Collection
{
Expand Down
1 change: 1 addition & 0 deletions src/Lifecycle/EventStore.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ protected function formatRelationshipsForWrite(array $event_objects): array
'created_at' => now(),
'updated_at' => now(),
]))
->values()
->all();
}
}
9 changes: 9 additions & 0 deletions src/Lifecycle/Hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ public function runsInPhase(Phase $phase): bool
return isset($this->phases[$phase]) && $this->phases[$phase] === true;
}

public function boot(Container $container, Event $event): bool
{
if ($this->runsInPhase(Phase::Boot)) {
return $this->execute($container, $event) ?? true;
}

throw new RuntimeException('Hook::boot called on a non-boot hook.');
}

public function validate(Container $container, Event $event): bool
{
if ($this->runsInPhase(Phase::Validate)) {
Expand Down
1 change: 1 addition & 0 deletions src/Lifecycle/Phase.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

enum Phase: string
{
case Boot = 'boot';
case Authorize = 'authorize';
case Validate = 'validate';
case Apply = 'apply';
Expand Down
32 changes: 32 additions & 0 deletions tests/Feature/BootHookTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Thunk\Verbs\Attributes\Hooks\On;
use Thunk\Verbs\Event;
use Thunk\Verbs\Lifecycle\Dispatcher;
use Thunk\Verbs\Lifecycle\Phase;

it('can modify props on events in the Boot phase', function () {
app(Dispatcher::class)->register(new BootHookTestListener);

$e = BootHookTestEvent::fire(
album: 'Tha Carter 2'
);

expect($e)->name->toBe('Lil Wayne');
});

class BootHookTestEvent extends Event
{
public string $name;

public string $album;
}

class BootHookTestListener
{
#[On(Phase::Boot)]
public function setNameToLilWayne(BootHookTestEvent $event)
{
$event->name = 'Lil Wayne';
}
}

0 comments on commit d83543b

Please sign in to comment.