Skip to content

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…
}