From e9286a6bcc64eeb7ebbae16a985763a5a5d46c3e Mon Sep 17 00:00:00 2001 From: Matt Breden Date: Wed, 12 Oct 2016 10:35:13 -0700 Subject: [PATCH 1/4] Issue #2710989 by mbreden: Create a resolver API for picking a checkout flow --- .../checkout/commerce_checkout.services.yml | 13 +++- modules/checkout/src/CheckoutOrderManager.php | 24 +++---- .../Resolver/ChainCheckoutFlowResolver.php | 58 +++++++++++++++ .../ChainCheckoutFlowResolverInterface.php | 29 ++++++++ .../CheckoutFlowResolverInterface.php | 24 +++++++ .../Resolver/DefaultCheckoutFlowResolver.php | 41 +++++++++++ .../Kernel/ChainCheckoutFlowResolverTest.php | 71 +++++++++++++++++++ 7 files changed, 247 insertions(+), 13 deletions(-) create mode 100644 modules/checkout/src/Resolver/ChainCheckoutFlowResolver.php create mode 100644 modules/checkout/src/Resolver/ChainCheckoutFlowResolverInterface.php create mode 100644 modules/checkout/src/Resolver/CheckoutFlowResolverInterface.php create mode 100644 modules/checkout/src/Resolver/DefaultCheckoutFlowResolver.php create mode 100644 modules/checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php 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..ca64e4b9f0 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,10 +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. + $checkout_flow = $this->chainCheckoutFlowResolver->resolve($order); $order->checkout_flow->target_id = $checkout_flow; $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..bb66a0829d --- /dev/null +++ b/modules/checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php @@ -0,0 +1,71 @@ +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()); + } + +} From badc750915b2cfb15fd4a4c452ffa2d2c40816d2 Mon Sep 17 00:00:00 2001 From: Bojan Zivanovic Date: Thu, 19 Jan 2017 00:26:59 +0100 Subject: [PATCH 2/4] Update DefaultCheckoutFlowResolver.php --- modules/checkout/src/Resolver/DefaultCheckoutFlowResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/checkout/src/Resolver/DefaultCheckoutFlowResolver.php b/modules/checkout/src/Resolver/DefaultCheckoutFlowResolver.php index eb9ed81f3a..1032562f8d 100644 --- a/modules/checkout/src/Resolver/DefaultCheckoutFlowResolver.php +++ b/modules/checkout/src/Resolver/DefaultCheckoutFlowResolver.php @@ -6,7 +6,7 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; /** - * Returns the default checkout flow, if known. + * Returns the order type's default checkout flow. */ class DefaultCheckoutFlowResolver implements CheckoutFlowResolverInterface { From beeebaee73c27cb547f2cddbf4d7bab88bbe05b7 Mon Sep 17 00:00:00 2001 From: Bojan Zivanovic Date: Thu, 19 Jan 2017 00:27:18 +0100 Subject: [PATCH 3/4] Update ChainCheckoutFlowResolverTest.php --- .../checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php b/modules/checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php index bb66a0829d..551b2d9162 100644 --- a/modules/checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php +++ b/modules/checkout/tests/src/Kernel/ChainCheckoutFlowResolverTest.php @@ -50,7 +50,6 @@ protected function setUp() { * Tests resolving the checkout flow. */ public function testCheckoutFlowResolution() { - $user = $this->createUser(['mail' => $this->randomString() . '@example.com']); $order = Order::create([ 'type' => 'default', @@ -61,7 +60,6 @@ public function testCheckoutFlowResolution() { $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); From aa5ce849a552d897b67f8d87ccd3842fb6d2de5e Mon Sep 17 00:00:00 2001 From: Bojan Zivanovic Date: Thu, 19 Jan 2017 00:30:53 +0100 Subject: [PATCH 4/4] Update CheckoutOrderManager.php --- modules/checkout/src/CheckoutOrderManager.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/checkout/src/CheckoutOrderManager.php b/modules/checkout/src/CheckoutOrderManager.php index ca64e4b9f0..705fa507b9 100644 --- a/modules/checkout/src/CheckoutOrderManager.php +++ b/modules/checkout/src/CheckoutOrderManager.php @@ -32,8 +32,7 @@ public function __construct(ChainCheckoutFlowResolverInterface $chain_checkout_f */ public function getCheckoutFlow(OrderInterface $order) { if ($order->checkout_flow->isEmpty()) { - $checkout_flow = $this->chainCheckoutFlowResolver->resolve($order); - $order->checkout_flow->target_id = $checkout_flow; + $order->checkout_flow = $this->chainCheckoutFlowResolver->resolve($order); $order->save(); }