commerce_amws-8.x-1.x-dev/modules/order/src/EventSubscriber/OrderSetStore.php
modules/order/src/EventSubscriber/OrderSetStore.php
<?php
namespace Drupal\commerce_amws_order\EventSubscriber;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\entity_sync\Event\TerminateOperationEvent;
use Drupal\entity_sync\Exception\EntityImportException;
use Drupal\entity_sync\Import\Event\Events;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Sets the order's store after the order items have been imported.
*/
class OrderSetStore implements EventSubscriberInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Constructs a new OrderSetStore object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events = [
Events::REMOTE_LIST_TERMINATE => ['setStore', 100],
];
return $events;
}
/**
* Trigger dependent synchronizations for the order import.
*
* @param \Drupal\entity_sync\Event\TerminateOperationEvent $event
* The terminate operation event.
*/
public function setStore(TerminateOperationEvent $event) {
if (!$this->isApplicable($event)) {
return;
}
$context = $event->getContext();
$order = $context['commerce_order'];
$order->setStoreId($this->resolveStore($order));
$order->save();
}
/**
* Determines which store the created order will belong to.
*
* Since the order may contain products belonging to different stores, which
* is not allowed by Drupal Commerce, we are assigning the order to the first
* store of the first order item's product.
*
* This functions assumes that order items for the given order have already
* been validated and contain all required data.
*
* @param \Drupal\commerce_order\Entity\OrderInterface $order
* The order.
*
* @return int|string|null
* The store ID.
*
* @throws \Drupal\entity_sync\Exception\EntityImportException
* When the store for the order could not be determined.
*/
protected function resolveStore(OrderInterface $order) {
$store_id = NULL;
$order_items = $this->entityTypeManager
->getStorage('commerce_order_item')
->loadByProperties([
'order_id' => $order->id(),
]);
foreach ($order_items as $order_item) {
// We currently only support product variations as purchased entities.
$variation = $order_item->getPurchasedEntity();
$product = $variation->getProduct();
if (!$product) {
throw new EntityImportException(sprintf(
'No product could be determined for the variation with ID "%s" and SKU "%s". A parent product is required for every variation by Drupal Commerce, and it is used by Commerce Amazon MWS to determine the store that the order will be assigned to.',
$variation->id(),
$variation->getSku()
));
}
$store_ids = $product->getStoreIds();
if (!$store_ids) {
continue;
}
$store_id = current($store_ids);
break;
}
if (!$store_id) {
throw new EntityImportException(
'No store could be determined because none of the products corresponding to the order items belong to a store.',
);
}
return $store_id;
}
/**
* Returns whether our changes apply to the given sync, operation and action.
*
* The order's store is resolved and stored in the corresponding order field
* after we have imported the order items.
*
* @param \Drupal\entity_sync\Event\TerminateOperationEvent $event
* The terminate operation event.
*
* @return bool
* Whether the changes in this subscriber should be applied.
*/
protected function isApplicable(TerminateOperationEvent $event) {
if ($event->getOperation() !== 'import_list') {
return FALSE;
}
$sync = $event->getSync();
if ($sync->get('id') !== 'commerce_amws__order_item') {
return FALSE;
}
return TRUE;
}
}
