contacts_events-8.x-1.x-dev/src/Entity/OrderHooks.php
src/Entity/OrderHooks.php
<?php namespace Drupal\contacts_events\Entity; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\contacts_events\OrderItemStateTrait; use Drupal\contacts_events\OrderStateTrait; use Drupal\Core\Access\AccessResult; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountProxyInterface; /** * Implementations for Order hooks. */ class OrderHooks { use OrderStateTrait; use OrderItemStateTrait; /** * The current user proxy. * * @var \Drupal\Core\Session\AccountProxyInterface */ protected $currentUser; /** * OrderHooks constructor. * * @param \Drupal\Core\Session\AccountProxyInterface $current_user * The current user proxy. */ public function __construct(AccountProxyInterface $current_user) { $this->currentUser = $current_user; } /** * Pre-save operations for Commerce Orders by Contacts Events. * * @param \Drupal\commerce_order\Entity\OrderInterface $order * The order item. * @param \Drupal\commerce_order\Entity\OrderInterface|null $original * The original order item, if any. */ public function preSave(OrderInterface $order, ?OrderInterface $original = NULL) { // Only operate on bookings. if ($order->bundle() != 'contacts_booking') { return; } if ($order->isNew() && $order->get('creator')->isEmpty()) { $order->set('creator', $this->currentUser->id()); } $modified = $this->updateStateIfModified($order); // If this is not a draft and we have not marked as modified, see if we need // to move between paid_in_full and confirmed. if (!$modified && $order->getState()->value != 'draft') { // Check for a positive balance on the new and original. $balance = $order->getBalance(); $is_positive = $balance && $balance->isPositive(); // If there is a balance now, use the payment_undone transition. if ($is_positive) { $this->applyTransitionIfAllowed($order->getState(), 'payment_undone'); } // Otherwise, transition to the paid_in_full state. else { // If we are confirming the booking and paying in full in the same // transition we need to reset the order state back to the original // state (likely 'draft') before applying the transition. $order->set('state', $original->getState()->getId()); $state_item = $order->getState(); // Transition might be paid_in_full or confirmed_paid_in_full. $transition = $state_item->getWorkflow()->findTransition($state_item->getId(), 'paid_in_full'); if ($transition) { $state_item->applyTransition($transition); } } } } /** * Post save callback for order. * * @param \Drupal\commerce_order\Entity\OrderInterface $order * The order entity. * @param \Drupal\commerce_order\Entity\OrderInterface|null $original * The original order entity, if any. */ public function postSave(OrderInterface $order, OrderInterface $original = NULL) { // Only operate on bookings. if ($order->bundle() != 'contacts_booking') { return; } // If the total paid has changed, check the order item states. if ($this->hasPaidChanged($order, $original)) { foreach ($order->getItems() as $item) { // Check the state and save if changed. if ($this->checkOrderItemStatus($item)) { $item->save(); } } } } /** * Prior to saving, update the state if have made modifications. * * @param \Drupal\commerce_order\Entity\OrderInterface $order * The order being saved. * * @return bool * Whether we changed the state. */ protected function updateStateIfModified(OrderInterface $order): bool { // Only operate on bookings. if ($order->bundle() != 'contacts_booking') { return FALSE; } // Check if we are in a state that can be modified. $state = $order->getState(); $transitions = $state->getWorkflow()->getPossibleTransitions($state->value); if (!isset($transitions['modified'])) { return FALSE; } // If there are any unconfirmed line items, we should mark as modified. if ($this->orderHasUnconfirmedItems($order)) { $state->applyTransition($transitions['modified']); return TRUE; } return FALSE; } /** * Access checks for bookings. * * @param \Drupal\commerce_order\Entity\OrderInterface $order * The order item. * @param string $operation * The operation being checked. * @param \Drupal\Core\Session\AccountInterface $account * The account performing the operation. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. */ public function access(OrderInterface $order, $operation, AccountInterface $account) { // Only change access for booking order types. if ($order->bundle() != 'contacts_booking') { return AccessResult::neutral(); } if ($operation == 'delete') { return AccessResult::forbiddenIf($order->hasItems(), 'Cannot delete a booking with order items.'); } return AccessResult::neutral(); } }