commerce_amws-8.x-1.x-dev/modules/shipping/src/Plugin/EntitySync/OperationConfigurator/FeedPostOrderFulfillmentData.php
modules/shipping/src/Plugin/EntitySync/OperationConfigurator/FeedPostOrderFulfillmentData.php
<?php
namespace Drupal\commerce_amws_shipping\Plugin\EntitySync\OperationConfigurator;
use Drupal\commerce_amws\MachineName\Field\Order as OrderField;
use Drupal\commerce_shipping\Entity\ShipmentInterface;
use Drupal\entity_sync\Client\ClientFactory;
use Drupal\entity_sync\Entity\OperationInterface;
use Drupal\entity_sync\Entity\OperationTypeInterface;
use Drupal\entity_sync\Entity\Runner\RunnerInterface;
use Drupal\entity_sync\Exception\FieldExportException;
use Drupal\entity_sync\Field\BundleFieldDefinition;
use Drupal\entity_sync\MachineName\Field\Operation as OperationField;
use Drupal\entity_sync\OperationConfigurator\SupportsRunnerInterface;
use Drupal\entity_sync_async\OperationConfigurator\EntityAsyncBase;
use Drupal\entity_sync_async\Operation\SupportsOperationUpdatingInterface;
use Drupal\Component\Plugin\DerivativeInspectionInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Plugin for shipment export operations.
*
* @EntitySyncOperationConfigurator(
* id = "commerce_amws_feed:_post_order_fulfillment_data_",
* label = @Translation("Amazon MWS feed: post order fulfillment data"),
* action_types = {
* "export_entity",
* },
* workflow_id = "commerce_amws_feed_operation",
* )
* phpcs:disable
* @I Move common functionality e.g. config, fields, runner to a base plugin
* type : task
* priority : normal
* labels : modularity
* phpcs:enable
*/
class FeedPostOrderFulfillmentData extends EntityAsyncBase implements
ContainerFactoryPluginInterface,
DerivativeInspectionInterface,
SupportsOperationUpdatingInterface,
SupportsRunnerInterface {
/**
* The Entity Synchronization client factory.
*
* @var \Drupal\entity_sync\Client\ClientFactory
*/
protected $clientFactory;
/**
* The runner for operations the types of which are configured by this plugin.
*
* @var \Drupal\entity_sync\Entity\Runner\RunnerInterface
*/
protected $runner;
/**
* Constructs a \Drupal\Component\Plugin\PluginBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\entity_sync\Client\ClientFactory $client_factory
* The Entity Synchronization client factory.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\entity_sync\Entity\Runner\RunnerInterface $runner
* The runner.
* phpcs:disable
* @I The runner should be lazy injected
* type : bug
* priority : normal
* labels : performance
* phpcs:enable
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
ClientFactory $client_factory,
EntityTypeManagerInterface $entity_type_manager,
RunnerInterface $runner
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->clientFactory = $client_factory;
$this->entityTypeManager = $entity_type_manager;
$this->runner = $runner;
}
/**
* {@inheritdoc}
*/
public static function create(
ContainerInterface $container,
array $configuration,
$plugin_id,
$plugin_definition
) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_sync.client.factory'),
$container->get('entity_type.manager'),
$container->get('commerce_amws_shipping.entity_sync_runner.feed_post_order_fulfillment_data')
);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'action_type' => 'export_entity',
'local_entity' => [
'type_id' => 'commerce_shipment',
],
'remote_resource' => [
'provider_id' => 'amws_selling_partner_api',
'client' => [
'type' => 'factory',
'service' => 'commerce_amws_shipping.entity_sync_client.feed_post_order_fulfillment_data_factory',
],
],
'operations' => [
'export_entity' => [
'status' => TRUE,
'create_entities' => TRUE,
'update_entities' => FALSE,
'label' => 'Export shipment',
'queue' => TRUE,
'queue_error_handling' => 'log_and_skip',
'state' => [
'manager' => 'entity_sync',
],
],
],
'field_mapping' => [
[
'machine_name' => 'amws_seller_id',
'remote_name' => 'MerchantIdentifier',
'export' => [
'callback' => [
'callable' => '\Drupal\commerce_amws_shipping\EntitySync\FieldMapping\ExportHandler::shipmentToMerchantIdentifier',
],
],
],
[
'machine_name' => 'amws_order_id',
'remote_name' => 'AmazonOrderID',
'export' => [
'callback' => [
'callable' => '\Drupal\commerce_amws_shipping\EntitySync\FieldMapping\ExportHandler::shipmentToAmwsOrderId',
],
],
],
[
'machine_name' => 'shipment_id',
'remote_name' => 'MerchantFulfillmentID',
],
[
'machine_name' => 'shipped',
'remote_name' => 'FulfillmentDate',
'export' => [
'callback' => [
'callable' => '\Drupal\commerce_amws\EntitySync\FieldMapping\ExportHandler::timestampToIso8601',
],
],
],
[
'machine_name' => 'tracking_code',
'remote_name' => 'FulfillmentData',
'export' => [
'callback' => [
'callable' => '\Drupal\commerce_amws_shipping\EntitySync\FieldMapping\ExportHandler::shipmentToAmwsFulfillmentData',
],
],
],
[
'machine_name' => 'items',
'remote_name' => 'Item',
'export' => [
'callback' => [
'callable' => '\Drupal\commerce_amws_shipping\EntitySync\FieldMapping\ExportHandler::shipmentItemsToAmwsFulfillmentItems',
],
],
],
],
'ui' => [
'disallowed_transitions' => [
'fail_submission',
'complete_submission',
'cancel_feed',
'process_feed',
'complete_feed',
'fail_feed',
'disconnected',
],
'uneditable_states' => [
'submission_cancelled',
'submitting',
'submission_completed',
'submission_failed',
'feed_cancelled',
'feed_in_progress',
'feed_processed',
'feed_failed',
],
],
] + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function bundleFieldDefinitions() {
$fields = parent::bundleFieldDefinitions();
$fields['amws_feed_document_id'] = BundleFieldDefinition::create('string')
->setLabel($this->t('The feed document ID'))
->setDescription($this->t(
'The Amazon MWS ID of the document submitted in the feed.'
));
$fields['amws_result_feed_document_id'] = BundleFieldDefinition::create('string')
->setLabel($this->t('The result feed document ID'))
->setDescription($this->t(
'The Amazon MWS ID of the document containing the result of the feed.'
));
return $fields;
}
/**
* {@inheritdoc}
*/
public function runner() {
return $this->runner;
}
/**
* {@inheritdoc}
*/
public function operationUpdaterPendingStates() {
return [
'submission_completed',
'feed_in_progress',
];
}
/**
* {@inheritdoc}
*/
public function updateOperation(
OperationTypeInterface $operation_type,
OperationInterface $operation
) {
$shipment = $operation->get(OperationField::ENTITY)->entity;
// If the shipment has been somehow been deleted, we're out of luck. We do
// cannot retrieve the Amazon MWS store anymore and cannot fetch the
// updates. We therefore move the operation to the disconnected state so
// that the update manager does not keep picking it up as pending updates.
// phpcs:disable
// @I Consider storing the AMWS store on the operation as well
// type : bug
// priority : low
// labels : export, feed, shipment
// @I Consider removing the operation when the shipment gets deleted
// type : bug
// priority : low
// labels : export, feed, shipment
// phpcs:enable
if (!$shipment) {
$operation->get(OperationField::STATE)
->first()
->applyTransitionById('disconnect');
$this->entityTypeManager
->getStorage('entity_sync_operation')
->save($operation);
return;
}
$amws_store = $this->getStoreFromShipment($shipment);
$client_config = $operation_type->getRemoteResourceSettings()['client'];
if (!isset($client_config['parameters'])) {
$client_config['parameters'] = [];
}
$client_config['parameters']['amws_store'] = $amws_store;
$client = $this->clientFactory->getByClientConfig($client_config);
$client->fetchFeedUpdates($operation);
}
/**
* Returns the AMWS store that the given shipment's order belongs to.
*
* @param \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment
* The shipment.
*
* @return \Drupal\commerce_amws\Entity\StoreInterface
* The Amazon MWS store.
*
* @throws \Drupal\entity_sync\Exception\FieldExportException
* If no Amazon MWS store associated with the shipment's order was found.
*/
protected function getStoreFromShipment(ShipmentInterface $shipment) {
$order = $shipment->getOrder();
if (!$order) {
throw new FieldExportException(sprintf(
'No order found for shipment with ID "%s".',
$shipment->id()
));
}
$amws_store_field = $order->get(OrderField::AMWS_STORE);
if ($amws_store_field->isEmpty()) {
throw new FieldExportException(sprintf(
'Order with ID "%s" does not belong to an Amazon MWS store.',
$order->id()
));
}
$amws_store = $amws_store_field->entity;
if (!$amws_store) {
throw new FieldExportException(sprintf(
'Order with ID "%s" belongs a non-existing Amazon MWS store with ID "%s".',
$order->id(),
$amws_store_field->target_id
));
}
return $amws_store;
}
}
