commerce-8.x-2.8/modules/order/src/OrderRefresh.php
modules/order/src/OrderRefresh.php
<?php namespace Drupal\commerce_order; use Drupal\commerce\Context; use Drupal\Component\Datetime\TimeInterface; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_order\Entity\OrderType; use Drupal\commerce_price\Resolver\ChainPriceResolverInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Session\AccountInterface; /** * Default implementation for order refresh. */ class OrderRefresh implements OrderRefreshInterface { /** * The order type storage. * * @var \Drupal\Core\Entity\EntityStorageInterface */ protected $orderTypeStorage; /** * The chain price resolver. * * @var \Drupal\commerce_price\Resolver\ChainPriceResolverInterface */ protected $chainPriceResolver; /** * The current user. * * @var \Drupal\Core\Session\AccountProxyInterface */ protected $currentUser; /** * The time. * * @var \Drupal\Component\Datetime\TimeInterface */ protected $time; /** * The order processors. * * @var \Drupal\commerce_order\OrderProcessorInterface[] */ protected $processors = []; /** * Constructs a new OrderRefresh object. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\commerce_price\Resolver\ChainPriceResolverInterface $chain_price_resolver * The chain price resolver. * @param \Drupal\Core\Session\AccountInterface $current_user * The current user. * @param \Drupal\Component\Datetime\TimeInterface $time * The time. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, ChainPriceResolverInterface $chain_price_resolver, AccountInterface $current_user, TimeInterface $time) { $this->orderTypeStorage = $entity_type_manager->getStorage('commerce_order_type'); $this->chainPriceResolver = $chain_price_resolver; $this->currentUser = $current_user; $this->time = $time; } /** * {@inheritdoc} */ public function addProcessor(OrderProcessorInterface $processor) { $this->processors[] = $processor; } /** * {@inheritdoc} */ public function shouldRefresh(OrderInterface $order) { if (!$this->needsRefresh($order)) { return FALSE; } /** @var \Drupal\commerce_order\Entity\OrderTypeInterface $order_type */ $order_type = $this->orderTypeStorage->load($order->bundle()); // Ensure the order is only refreshed for its customer, when configured so. if ($order_type->getRefreshMode() == OrderType::REFRESH_CUSTOMER) { if ($order->getCustomerId() != $this->currentUser->id()) { return FALSE; } } return TRUE; } /** * {@inheritdoc} */ public function needsRefresh(OrderInterface $order) { // Only draft orders should be automatically refreshed. if ($order->getState()->value != 'draft') { return FALSE; } // Accommodate long-running processes by always using the current time. $current_time = $this->time->getCurrentTime(); $order_time = $order->getChangedTime(); if (date('Y-m-d', $current_time) != date('Y-m-d', $order_time)) { // Refresh on a date change regardless of the refresh frequency. // Date changes can impact tax rate amounts, availability of promotions. return TRUE; } /** @var \Drupal\commerce_order\Entity\OrderTypeInterface $order_type */ $order_type = $this->orderTypeStorage->load($order->bundle()); $refreshed_ago = $current_time - $order_time; if ($refreshed_ago >= $order_type->getRefreshFrequency()) { return TRUE; } return FALSE; } /** * {@inheritdoc} */ public function refresh(OrderInterface $order) { $current_time = $this->time->getCurrentTime(); $order->setChangedTime($current_time); $order->clearAdjustments(); // Nothing else can be done while the order is empty. if (!$order->hasItems()) { return; } $context = new Context($order->getCustomer(), $order->getStore()); foreach ($order->getItems() as $order_item) { $purchased_entity = $order_item->getPurchasedEntity(); if ($purchased_entity) { $order_item->setTitle($purchased_entity->getOrderItemTitle()); if (!$order_item->isUnitPriceOverridden()) { $unit_price = $this->chainPriceResolver->resolve($purchased_entity, $order_item->getQuantity(), $context); $order_item->setUnitPrice($unit_price); } } // If the order refresh is running during order preSave(), // $order_item->getOrder() will point to the original order (or // NULL, in case the order item is new). $order_item->order_id->entity = $order; } // Allow the processors to modify the order and its items. foreach ($this->processors as $processor) { $processor->process($order); } foreach ($order->getItems() as $order_item) { if ($order_item->hasTranslationChanges()) { // Remove the order that was set above, to avoid // crashes during the entity save process. $order_item->order_id->entity = NULL; $order_item->setChangedTime($current_time); $order_item->save(); } } } }