Events¶
The engine dispatches Symfony events at every lifecycle transition so
consumers (mail, payment, workflow, logging) can react without the core
knowing they exist. Event names are constants on
\Drupal\yoyaku\Event\BookingEvents.
Event catalog¶
| Constant | Name | Event class | When |
|---|---|---|---|
HOLD_REQUESTED |
booking.hold_requested |
BookingHoldRequestedEvent |
Before a hold - vetoable. |
HELD |
booking.held |
BookingEvent |
After a hold is created. |
CONFIRMED |
booking.confirmed |
BookingEvent |
After confirm(). |
RELEASED |
booking.released |
BookingEvent |
After release(). |
EXPIRED |
booking.expired |
BookingEvent |
After a hold expires. |
CANCELED |
booking.canceled |
BookingEvent |
After cancel(). |
BookingEvent exposes the readonly ->booking. Transition events fire
after the transaction commits (the row lock is released first), so
subscribers can safely do slow work.
Order notifications¶
yoyaku_order dispatches one more event, outside BookingEvents:
\Drupal\yoyaku_order\Event\OrderNotificationEvent, when an order's booker is
to be told about it (confirmed, released, canceled, rejected). Subscribers add
files, images and sections of HTML to the email before a delivery module sends
it; see Booker emails.
Where they fire¶
sequenceDiagram
participant Caller
participant BM as BookingManager
participant D as Dispatcher
Caller->>BM: hold()
BM->>D: HOLD_REQUESTED (vetoable)
alt denied
D-->>BM: deny(reason)
BM-->>Caller: BookingException
else allowed
BM->>BM: txn + lock + reserve + COMMIT
BM->>D: HELD
BM-->>Caller: booking
end
Caller->>BM: confirm()
BM->>BM: txn + lock + COMMIT
BM->>D: CONFIRMED
Vetoing a hold¶
Subscribe to HOLD_REQUESTED and call deny() to section a hold for any reason
the built-in capacity check does not cover. The tariff, requested quantity
and subject are available on the event.
use Drupal\yoyaku\Event\BookingEvents;
use Drupal\yoyaku\Event\BookingHoldRequestedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
final class MyBookingRules implements EventSubscriberInterface {
public static function getSubscribedEvents(): array {
return [BookingEvents::HOLD_REQUESTED => 'onHoldRequested'];
}
public function onHoldRequested(BookingHoldRequestedEvent $event): void {
if ($event->quantity > 4) {
$event->deny('At most 4 units per booking.');
}
}
}
Tip
For reusable, configurable rules prefer a constraint plugin; use the vetoable event for one-off or contextual logic.
Reacting to a confirmed booking¶
use Drupal\yoyaku\Event\BookingEvent;
use Drupal\yoyaku\Event\BookingEvents;
public static function getSubscribedEvents(): array {
return [BookingEvents::CONFIRMED => 'onConfirmed'];
}
public function onConfirmed(BookingEvent $event): void {
$booking = $event->booking;
// Send a confirmation email, issue a ticket, notify a workflow…
}