View source
<?php
namespace Drupal\xquantity_stock\EventSubscriber;
use Drupal\commerce\Context;
use Drupal\commerce_order\Event\OrderEvent;
use Drupal\commerce_order\Event\OrderEvents;
use Drupal\commerce_order\Event\OrderItemEvent;
use Drupal\state_machine\Event\WorkflowTransitionEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\commerce_order\AvailabilityManagerInterface;
use Drupal\commerce_order\AvailabilityCheckerInterface;
use Drupal\commerce_order\Entity\Order;
use Drupal\commerce_order\Entity\OrderItem;
class XquantityStockOrderEventSubscriber implements EventSubscriberInterface {
protected $routeMatch;
protected $currentUser;
public $availabilityManager;
public function __construct(RouteMatchInterface $route_match, AccountProxyInterface $user, AvailabilityCheckerInterface $availability_manager) {
$this->routeMatch = $route_match;
$this->currentUser = $user;
$this->availabilityManager = $availability_manager;
}
public static function getSubscribedEvents() {
$events = [
'commerce_order.cancel.post_transition' => [
'onOrderCancel',
-100,
],
OrderEvents::ORDER_PREDELETE => [
'onOrderDelete',
-100,
],
OrderEvents::ORDER_ITEM_UPDATE => [
'onOrderItemUpdate',
-100,
],
OrderEvents::ORDER_ITEM_DELETE => [
'onOrderItemDelete',
-100,
],
];
return $events;
}
public function onOrderCancel(WorkflowTransitionEvent $event) {
$order = $event
->getEntity();
foreach ($order
->getItems() as $order_item) {
$this
->updateStock($order, $order_item, TRUE);
}
}
public function onOrderDelete(OrderEvent $event) {
$order = $event
->getOrder();
foreach ($order
->getItems() as $order_item) {
$this
->updateStock($order, $order_item, TRUE);
}
}
public function onOrderItemUpdate(OrderItemEvent $event) {
if ($this->routeMatch
->getParameter('commerce_order')) {
if (($order_item = $event
->getOrderItem()) && ($order = $order_item
->getOrder())) {
$this
->updateStock($order, $order_item);
}
}
}
public function onOrderItemDelete(OrderItemEvent $event) {
$order_item = $event
->getOrderItem();
if ($order = $order_item
->getOrder()) {
$this
->updateStock($order, $order_item, TRUE);
}
}
protected function updateStock(Order $order, OrderItem $order_item, $delete = FALSE) {
$state = $order
->getState()->value;
if ($state != 'canceled' && $state != 'completed') {
$quantity = $delete ? '0' : $order_item
->getQuantity();
$old = $delete ? $order_item
->getQuantity() : $order_item->original
->getQuantity();
$context = new Context($this->currentUser, $order
->getStore(), time(), [
'xquantity' => $delete ? 'delete' : 'update',
'old' => $old,
]);
$result = $this->availabilityManager
->check($order_item, $context, $quantity);
if ($result
->isUnavailable()) {
throw new \InvalidArgumentException("The quantity {$quantity} to update on the {$order_item->getTitle()} order item is not available on the stock.");
}
}
}
}