contacts_events-8.x-1.x-dev/modules/accommodation/src/EventSubscriber/BookingConfirmedSubscriber.php
modules/accommodation/src/EventSubscriber/BookingConfirmedSubscriber.php
<?php
namespace Drupal\contacts_events_accommodation\EventSubscriber;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Contacts Events Accommodation event subscriber for booking confirmation.
*/
class BookingConfirmedSubscriber implements EventSubscriberInterface {
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
// Before line items are confirmed by contacts events, we want to aggregate
// any line items.
// phpcs:ignore Drupal.Arrays.Array.LongLineDeclaration
$events['commerce_order.place.pre_transition'][] = ['combineLineItems', 900];
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';
}
/**
* Combine unconfirmed line items into the confirmed items.
*
* @param \Drupal\state_machine\Event\WorkflowTransitionEvent $event
* The transition event.
*/
public function combineLineItems(WorkflowTransitionEvent $event) {
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = $event->getEntity();
if (!$this->applies($order)) {
return;
}
/** @var \Drupal\commerce_order\Entity\OrderItemInterface[] $items */
$items = array_filter($order->getItems(), function (OrderItemInterface $item) {
return substr($item->bundle(), 0, 9) === 'ce_accom_';
});
// Build an array of confirmed items by accommodation ID.
$confirmed_items = [];
foreach ($items as $item) {
if (in_array($item->get('state')->value, ['confirmed', 'paid_in_full'])) {
$confirmed_items += [$item->getPurchasedEntityId() => $item];
}
}
// Now loop over and merge in any unconfirmed items.
/** @var \Drupal\commerce_order\Entity\OrderItemInterface $item */
foreach ($items as $delta => $item) {
/** @var \Drupal\commerce_order\Entity\OrderItemInterface|false $confirmed_item */
$confirmed_item = $confirmed_items[$item->getPurchasedEntityId()] ?? FALSE;
if ($confirmed_item && $confirmed_item->id() != $item->id()) {
// If not cancelled or zero quantity, combine to quantities.
$quantity = (int) $item->getQuantity();
if ($item->get('state')->value != 'cancelled' && $quantity !== 0) {
$confirmed_item->setQuantity((int) $confirmed_item->getQuantity() + $quantity);
$confirmed_item->save();
}
// Remove this item and delete it.
$order->removeItem($item);
$item->delete();
unset($items[$delta]);
}
}
// Remove any zero quantity line items.
foreach ($items as $delta => $item) {
if ((int) $item->getQuantity() === 0) {
$order->removeItem($item);
$item->delete();
}
}
}
}
