contacts_events-8.x-1.x-dev/modules/teams/src/EventSubscriber/TeamTicketStateSubscriber.php

modules/teams/src/EventSubscriber/TeamTicketStateSubscriber.php
<?php

namespace Drupal\contacts_events_teams\EventSubscriber;

use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\contacts_events\OrderEventTransitionTrait;
use Drupal\contacts_events\OrderStateTrait;
use Drupal\contacts_events\PriceCalculator;
use Drupal\contacts_events_teams\TeamQueries;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Event subscriber for handling team ticket state transitions.
 *
 * @package Drupal\contacts_events_teams\EventSubscriber
 */
class TeamTicketStateSubscriber implements EventSubscriberInterface {

  use OrderStateTrait;
  use OrderEventTransitionTrait;

  /**
   * The price calculator.
   *
   * @var \Drupal\contacts_events\PriceCalculator
   */
  protected $calculator;

  /**
   * The event dispatcher.
   *
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
   */
  protected $eventDispatcher;

  /**
   * The team queries service.
   *
   * @var \Drupal\contacts_events_teams\TeamQueries
   */
  protected $queries;

  /**
   * Construct the team ticket state subscriber event subscriber.
   *
   * @param \Drupal\contacts_events\PriceCalculator $calculator
   *   The price calculator.
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
   *   The event dispatcher service.
   * @param \Drupal\contacts_events_teams\TeamQueries $queries
   *   The team queries service.
   */
  public function __construct(PriceCalculator $calculator, EventDispatcherInterface $event_dispatcher, TeamQueries $queries) {
    $this->calculator = $calculator;
    $this->eventDispatcher = $event_dispatcher;
    $this->queries = $queries;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    // phpcs:disable Drupal.Arrays.Array.LongLineDeclaration
    // After a team ticket has been confirmed, move to application in progress.
    $events['commerce_order.place.pre_transition'][] = ['beginTeamApplicationProcess', 500];

    // When a team application moves to a different state  update the ticket
    // state to match.
    $events['contacts_events_teams_applications.post_transition'][] = ['updateTicketState'];

    // When a ticket goes back to pending, clear the team details.
    $events['contacts_events_order_items.team_app_back_to_pending.pre_transition'][] = ['resetTeamTicket'];
    $events['contacts_events_order_items.cancel.pre_transition'][] = ['resetTeamTicket'];

    // Make sure the confirm events get fired for team tickets.
    $events['contacts_events_order_items.team_app_in_progress.pre_transition'][] = ['fireOrderItemConfirmedEvents', -999];
    $events['contacts_events_order_items.team_app_in_progress.post_transition'][] = ['fireOrderItemConfirmedEvents', 90];

    // phpcs:enable
    return $events;
  }

  /**
   * Check whether this subscriber applies to the event.
   *
   * @param \Drupal\commerce_order\Entity\OrderInterface $order
   *   The order we are checking.
   *
   * @return bool
   *   Whether this subscriber applies to the given order.
   */
  protected function applies(OrderInterface $order) {
    return $order->bundle() == 'contacts_booking';
  }

  /**
   * Triggered after the order item has moved to the confirmed state.
   *
   * If this is a team ticket, then start the application process.
   *
   * @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
   *   The workflow transition event.
   *
   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
   */
  public function beginTeamApplicationProcess(WorkflowTransitionEvent $event) {
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $event->getEntity();

    if (!$this->applies($order)) {
      return;
    }

    foreach ($order->getItems() as $order_item) {
      if ($order_item->bundle() === 'contacts_ticket') {
        /** @var \Drupal\state_machine\Plugin\Field\FieldType\StateItem $state */
        $state = $order_item->get('state')->first();
        $this->applyTransitionIfAllowed($state, 'team_app_in_progress', TRUE);
      }
    }
  }

  /**
   * Updates the ticket state to match the team application state.
   *
   * @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
   *   Transition event on the team app.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public function updateTicketState(WorkflowTransitionEvent $event) {
    $transition = $event->getTransition();
    $to_state = $transition->getToState()->getId();

    // If we are transitioning to rejected_notified or archive, the ticket
    // should go back to pending.
    if (in_array($to_state, ['rejected_notified', 'archived'])) {
      $order_item_transition = 'team_app_back_to_pending';
      // The team_app_back_to_pending transition causes the team details
      // to be removed from the ticket. If we're in the middle of transferring
      // a team application from one team to another then we explicitly *don't*
      // want this to happen. The transfer process will have flagged that this
      // is happening using a surrogate property.
      if ($event->getEntity()->is_transferring) {
        return;
      }
    }
    // If it is to approved, we should allow the ticket to be moved to paid in
    // full.
    elseif ($to_state == 'approved') {
      $order_item_transition = 'paid_in_full';
    }
    // Otherwise, do nothing.
    else {
      return;
    }

    /** @var \Drupal\contacts_events_teams\Entity\TeamApplication */
    $app = $event->getEntity();
    /** @var \Drupal\contacts_events\Entity\Ticket $ticket */
    $ticket = $app->get('ticket')->entity;
    $order_item = $ticket->getOrderItem();
    $this->applyTransitionIfAllowed($order_item->get('state')->first(), $order_item_transition, TRUE);
  }

  /**
   * Triggered when a team ticket is reset back to pending.
   *
   * If this is a team ticket, then start the application process.
   *
   * @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
   *   The workflow transition event.
   *
   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
   */
  public function resetTeamTicket(WorkflowTransitionEvent $event) {
    /** @var \Drupal\commerce_order\Entity\OrderItem $order_item */
    $order_item = $event->getEntity();

    if ($order_item->bundle() === 'contacts_ticket') {
      /** @var \Drupal\contacts_events\Entity\TicketInterface $ticket */
      $ticket = $order_item->getPurchasedEntity();

      // If there is a team application for the ticket being cancelled then
      // archive it.
      if ($application = $this->queries->getTeamApplicationForTicket($ticket)) {
        /** @var \Drupal\state_machine\Plugin\Field\FieldType\StateItem $application_state */
        $application_state = $application->get('state')->first();
        $this->applyTransitionIfAllowed($application_state, 'archive', TRUE);
      }

      $ticket->set('team', NULL);
      $ticket->set('is_team_ticket', NULL);
      $this->calculator->calculatePrice($order_item);
      $ticket->save();
    }
  }

  /**
   * Manually fire the confirmed events for team ticket confirmations.
   *
   * @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
   *   The confirmed_paid_in_full transition event.
   * @param string $event_name
   *   The event name.
   */
  public function fireOrderItemConfirmedEvents(WorkflowTransitionEvent $event, $event_name) {
    /** @var \Drupal\commerce_order\Entity\OrderItemInterface $entity */
    $entity = $event->getEntity();
    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $entity->getOrder();

    if (!$this->applies($order)) {
      return;
    }

    // We have bypassed the normal confirm transition so trigger any events that
    // we may have missed.
    $event_parts = explode('.', $event_name);
    $phase = $event_parts[2];
    $this->dispatchTransitionEvent('confirm', $phase, $event, $entity);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc