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();
}
}
