diff --git a/modules/checkout/commerce_checkout.services.yml b/modules/checkout/commerce_checkout.services.yml index e0191ef45d..29b44dded0 100644 --- a/modules/checkout/commerce_checkout.services.yml +++ b/modules/checkout/commerce_checkout.services.yml @@ -1,7 +1,18 @@ services: + commerce_checkout.chain_checkout_flow_resolver: + class: Drupal\commerce_checkout\Resolver\ChainCheckoutFlowResolver + tags: + - { name: service_collector, call: addResolver, tag: commerce_checkout.checkout_flow_resolver } + + commerce_checkout.default_checkout_flow_resolver: + class: Drupal\commerce_checkout\Resolver\DefaultCheckoutFlowResolver + arguments: ['@entity_type.manager'] + tags: + - { name: commerce_checkout.checkout_flow_resolver, priority: -100 } + commerce_checkout.checkout_order_manager: class: Drupal\commerce_checkout\CheckoutOrderManager - arguments: ['@entity_type.manager'] + arguments: ['@commerce_checkout.chain_checkout_flow_resolver'] plugin.manager.commerce_checkout_flow: class: Drupal\commerce_checkout\CheckoutFlowManager diff --git a/modules/checkout/src/CheckoutOrderManager.php b/modules/checkout/src/CheckoutOrderManager.php index 31e1fd5ef6..705fa507b9 100644 --- a/modules/checkout/src/CheckoutOrderManager.php +++ b/modules/checkout/src/CheckoutOrderManager.php @@ -2,26 +2,29 @@ namespace Drupal\commerce_checkout; +use Drupal\commerce_checkout\Resolver\ChainCheckoutFlowResolverInterface; use Drupal\commerce_order\Entity\OrderInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; +/** + * Manages checkout flows for orders. + */ class CheckoutOrderManager implements CheckoutOrderManagerInterface { /** - * The entity type manager. + * The chain checkout flow resolver. * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface + * @var \Drupal\commerce_checkout\Resolver\ChainCheckoutFlowResolverInterface */ - protected $entityTypeManager; + protected $chainCheckoutFlowResolver; /** * Constructs a new CheckoutOrderManager object. * - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * The entity type manager. + * @param \Drupal\commerce_checkout\Resolver\ChainCheckoutFlowResolverInterface $chain_checkout_flow_resolver + * The chain checkout flow resolver. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager) { - $this->entityTypeManager = $entity_type_manager; + public function __construct(ChainCheckoutFlowResolverInterface $chain_checkout_flow_resolver) { + $this->chainCheckoutFlowResolver = $chain_checkout_flow_resolver; } /** @@ -29,11 +32,7 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager) { */ public function getCheckoutFlow(OrderInterface $order) { if ($order->checkout_flow->isEmpty()) { - /** @var \Drupal\commerce_order\Entity\OrderTypeInterface $order_type */ - $order_type = $this->entityTypeManager->getStorage('commerce_order_type')->load($order->bundle()); - $checkout_flow = $order_type->getThirdPartySetting('commerce_checkout', 'checkout_flow', 'default'); - // @todo Allow other modules to add their own resolving logic. - $order->checkout_flow->target_id = $checkout_flow; + $order->checkout_flow = $this->chainCheckoutFlowResolver->resolve($order); $order->save(); } diff --git a/modules/checkout/src/Resolver/ChainCheckoutFlowResolver.php b/modules/checkout/src/Resolver/ChainCheckoutFlowResolver.php new file mode 100644 index 0000000000..bd072f0476 --- /dev/null +++ b/modules/checkout/src/Resolver/ChainCheckoutFlowResolver.php @@ -0,0 +1,58 @@ +resolvers = $resolvers; + } + + /** + * {@inheritdoc} + */ + public function addResolver(CheckoutFlowResolverInterface $resolver) { + $this->resolvers[] = $resolver; + } + + /** + * {@inheritdoc} + */ + public function getResolvers() { + return $this->resolvers; + } + + /** + * {@inheritdoc} + */ + public function resolve(OrderInterface $order) { + foreach ($this->resolvers as $resolver) { + $result = $resolver->resolve($order); + if ($result instanceof CheckoutFlowInterface) { + return $result; + } + } + + return NULL; + } + +} diff --git a/modules/checkout/src/Resolver/ChainCheckoutFlowResolverInterface.php b/modules/checkout/src/Resolver/ChainCheckoutFlowResolverInterface.php new file mode 100644 index 0000000000..57c8bc69a5 --- /dev/null +++ b/modules/checkout/src/Resolver/ChainCheckoutFlowResolverInterface.php @@ -0,0 +1,29 @@ +entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public function resolve(OrderInterface $order) { + /** @var \Drupal\commerce_order\Entity\OrderTypeInterface $order_type */ + $order_type = $this->entityTypeManager->getStorage('commerce_order_type')->load($order->bundle()); + $checkout_flow_id = $order_type->getThirdPartySetting('commerce_checkout', 'checkout_flow', 'default'); + $checkout_flow = $this->entityTypeManager->getStorage('commerce_checkout_flow')->load($checkout_flow_id); + return $checkout_flow; + } + +} diff --git a/modules/checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php b/modules/checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php new file mode 100644 index 0000000000..551b2d9162 --- /dev/null +++ b/modules/checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php @@ -0,0 +1,69 @@ +installEntitySchema('commerce_order'); + $this->installConfig('commerce_order'); + $this->installConfig('commerce_product'); + $this->installConfig('commerce_checkout'); + } + + /** + * Tests resolving the checkout flow. + */ + public function testCheckoutFlowResolution() { + $user = $this->createUser(['mail' => $this->randomString() . '@example.com']); + $order = Order::create([ + 'type' => 'default', + 'mail' => $user->getEmail(), + 'uid' => $user->id(), + 'store_id' => $this->store->id(), + ]); + $order->save(); + + $resolver = $this->container->get('commerce_checkout.chain_checkout_flow_resolver'); + /** @var \Drupal\commerce_checkout\Entity\CheckoutFlowInterface $checkout_flow */ + $checkout_flow = $resolver->resolve($order); + + $this->assertEquals('default', $checkout_flow->id()); + } + +}