From 7b1c5676cca294b1f0cbe3427ba6602a74f02c20 Mon Sep 17 00:00:00 2001 From: Jonathan Sacksick <jonathan.sacksick@gmail.com> Date: Mon, 14 Apr 2025 18:27:21 +0300 Subject: [PATCH 1/2] Issue #2931044 by megachriz, istavros, goz, s.messaris, jsacksick: Trying to get checkout steps of an order outside of checkout pages throws an error. --- modules/checkout/src/CheckoutOrderManager.php | 3 + .../CheckoutFlow/CheckoutFlowBase.php | 8 +++ .../CheckoutFlow/CheckoutFlowInterface.php | 9 +++ .../src/Kernel/CheckoutOrderManagerTest.php | 58 ++++++++++++++++--- 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/modules/checkout/src/CheckoutOrderManager.php b/modules/checkout/src/CheckoutOrderManager.php index 766d1f942..5217b40c7 100644 --- a/modules/checkout/src/CheckoutOrderManager.php +++ b/modules/checkout/src/CheckoutOrderManager.php @@ -28,6 +28,9 @@ class CheckoutOrderManager implements CheckoutOrderManagerInterface { $order->save(); } + // Set the order on the checkout flow's checkout flow plugin. + $order->get('checkout_flow')->entity->getPlugin()->setOrder($order); + return $order->get('checkout_flow')->entity; } diff --git a/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php b/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php index 96bca7e7d..77ec52ca6 100644 --- a/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php +++ b/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php @@ -15,6 +15,7 @@ use Drupal\Core\Url; use Drupal\commerce\AjaxFormTrait; use Drupal\commerce\Response\NeedsRedirectException; use Drupal\commerce_checkout\Event\CheckoutEvents; +use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_order\Event\OrderEvent; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -160,6 +161,13 @@ abstract class CheckoutFlowBase extends PluginBase implements CheckoutFlowInterf } } + /** + * {@inheritdoc} + */ + public function setOrder(OrderInterface $order) { + $this->order = $order; + } + /** * {@inheritdoc} */ diff --git a/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowInterface.php b/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowInterface.php index 3c1b0416e..d70261f4a 100644 --- a/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowInterface.php +++ b/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowInterface.php @@ -9,6 +9,7 @@ use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Core\Form\BaseFormIdInterface; use Drupal\Core\Form\FormInterface; use Drupal\Core\Plugin\PluginFormInterface; +use Drupal\commerce_order\Entity\OrderInterface; /** * Places an order through a series of steps. @@ -19,6 +20,14 @@ use Drupal\Core\Plugin\PluginFormInterface; */ interface CheckoutFlowInterface extends FormInterface, BaseFormIdInterface, ConfigurableInterface, DependentPluginInterface, PluginFormInterface, PluginInspectionInterface, DerivativeInspectionInterface { + /** + * Sets the current order. + * + * @param \Drupal\commerce_order\Entity\OrderInterface $order + * The order. + */ + public function setOrder(OrderInterface $order); + /** * Gets the current order. * diff --git a/modules/checkout/tests/src/Kernel/CheckoutOrderManagerTest.php b/modules/checkout/tests/src/Kernel/CheckoutOrderManagerTest.php index 2dd2ed11c..44167a77e 100644 --- a/modules/checkout/tests/src/Kernel/CheckoutOrderManagerTest.php +++ b/modules/checkout/tests/src/Kernel/CheckoutOrderManagerTest.php @@ -51,21 +51,25 @@ class CheckoutOrderManagerTest extends OrderKernelTestBase { $this->installConfig('commerce_checkout'); $user = $this->createUser(); - $order = Order::create([ + $this->order = Order::create([ 'type' => 'default', 'mail' => $user->getEmail(), 'uid' => $user->id(), 'store_id' => $this->store->id(), ]); - $order->save(); - $this->order = $order; + $this->order->save(); $this->checkoutOrderManager = $this->container->get('commerce_checkout.checkout_order_manager'); + } - // Fake a request so that the current_route_match works. - // @todo Remove this when CheckoutFlowBase stops using the route match. + /** + * Fakes a request so that the current_route_match works. + * + * @todo Remove this when CheckoutFlowBase stops using the route match. + */ + protected function setupRequestWithOrderParameter() { $url = Url::fromRoute('commerce_checkout.form', [ - 'commerce_order' => $order->id(), + 'commerce_order' => $this->order->id(), ]); $route_provider = $this->container->get('router.route_provider'); $route = $route_provider->getRouteByName($url->getRouteName()); @@ -73,7 +77,7 @@ class CheckoutOrderManagerTest extends OrderKernelTestBase { $request->setSession(new Session(new MockArraySessionStorage())); $request->attributes->add([ RouteObjectInterface::ROUTE_OBJECT => $route, - 'commerce_order' => $order, + 'commerce_order' => $this->order, ]); $this->container->get('request_stack')->push($request); } @@ -82,6 +86,8 @@ class CheckoutOrderManagerTest extends OrderKernelTestBase { * Tests getting the order's checkout flow. */ public function testGetCheckoutFlow() { + $this->setupRequestWithOrderParameter(); + $checkout_flow = $this->checkoutOrderManager->getCheckoutFlow($this->order); $this->assertInstanceOf(CheckoutFlow::class, $checkout_flow); $this->assertEquals('default', $checkout_flow->id()); @@ -96,6 +102,8 @@ class CheckoutOrderManagerTest extends OrderKernelTestBase { * Tests getting the order's checkout step ID. */ public function testGetCheckoutStepId() { + $this->setupRequestWithOrderParameter(); + // Empty requested step ID when no checkout step was set. $step_id = $this->checkoutOrderManager->getCheckoutStepId($this->order); $this->assertEquals('login', $step_id); @@ -137,4 +145,40 @@ class CheckoutOrderManagerTest extends OrderKernelTestBase { } + /** + * Tests getting checkout's visible steps. + */ + public function testGetVisibleSteps() { + /** @var \Drupal\commerce_checkout\Entity\CheckoutFlowInterface $checkout_flow */ + $checkout_flow = $this->checkoutOrderManager->getCheckoutFlow($this->order); + + /** @var \Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowInterface $checkout_flow_plugin */ + $checkout_flow_plugin = $checkout_flow->getPlugin(); + + /** @var array $steps */ + $steps = $checkout_flow_plugin->getVisibleSteps(); + + $expected_steps = [ + 'login', + 'order_information', + 'review', + 'complete', + ]; + $this->assertEquals($expected_steps, array_keys($steps)); + } + + /** + * Tests getting the order from the checkout flow plugin. + */ + public function testGetOrderFromCheckoutPane() { + /** @var \Drupal\commerce_checkout\Entity\CheckoutFlowInterface $checkout_flow */ + $checkout_flow = $this->checkoutOrderManager->getCheckoutFlow($this->order); + + /** @var \Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowInterface $checkout_flow_plugin */ + $checkout_flow_plugin = $checkout_flow->getPlugin(); + + // Assert that the checkout flow plugin contains the order. + $this->assertSame($this->order, $checkout_flow_plugin->getOrder()); + } + } -- GitLab From 8e0c831db5e6d3d37ceba63f0a94d09325fae343 Mon Sep 17 00:00:00 2001 From: Jonathan Sacksick <jonathan.sacksick@gmail.com> Date: Mon, 14 Apr 2025 18:35:16 +0300 Subject: [PATCH 2/2] Return from setOrder(). --- .../src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php | 3 ++- .../Plugin/Commerce/CheckoutFlow/CheckoutFlowInterface.php | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php b/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php index 77ec52ca6..059d1febe 100644 --- a/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php +++ b/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php @@ -164,8 +164,9 @@ abstract class CheckoutFlowBase extends PluginBase implements CheckoutFlowInterf /** * {@inheritdoc} */ - public function setOrder(OrderInterface $order) { + public function setOrder(OrderInterface $order): static { $this->order = $order; + return $this; } /** diff --git a/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowInterface.php b/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowInterface.php index d70261f4a..33b85870a 100644 --- a/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowInterface.php +++ b/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowInterface.php @@ -25,8 +25,10 @@ interface CheckoutFlowInterface extends FormInterface, BaseFormIdInterface, Conf * * @param \Drupal\commerce_order\Entity\OrderInterface $order * The order. + * + * @return $this */ - public function setOrder(OrderInterface $order); + public function setOrder(OrderInterface $order): static; /** * Gets the current order. -- GitLab