Skip to content

Commit

Permalink
[API] [Checkout] Extract presenting available shipping and payment me…
Browse files Browse the repository at this point in the history
…thods to custom controllers
  • Loading branch information
lchrusciel committed Feb 8, 2017
1 parent bb1d610 commit daaaf35
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 194 deletions.
@@ -0,0 +1,145 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sylius\Bundle\ApiBundle\Controller;

use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use SM\Factory\FactoryInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Payment\Resolver\PaymentMethodsResolverInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
*/
final class ShowAvailablePaymentMethodsController
{
/**
* @var FactoryInterface
*/
private $stateMachineFactory;

/**
* @var OrderRepositoryInterface
*/
private $orderRepository;

/**
* @var PaymentMethodsResolverInterface
*/
private $paymentMethodResolver;

/**
* @var ViewHandlerInterface
*/
private $restViewHandler;

/**
* @param FactoryInterface $stateMachineFactory
* @param OrderRepositoryInterface $orderRepository
* @param PaymentMethodsResolverInterface $paymentMethodResolver
* @param ViewHandlerInterface $restViewHandler
*/
public function __construct(
FactoryInterface $stateMachineFactory,
OrderRepositoryInterface $orderRepository,
PaymentMethodsResolverInterface $paymentMethodResolver,
ViewHandlerInterface $restViewHandler
) {
$this->stateMachineFactory = $stateMachineFactory;
$this->orderRepository = $orderRepository;
$this->paymentMethodResolver = $paymentMethodResolver;
$this->restViewHandler = $restViewHandler;
}

/**
* @param Request $request
*
* @return Response
*/
public function showAction(Request $request)
{
/** @var OrderInterface $cart */
$cart = $this->getCartOr404($request->attributes->get('orderId'));

if (!$this->isCheckoutTransitionPossible($cart, OrderCheckoutTransitions::TRANSITION_SELECT_PAYMENT)) {
throw new BadRequestHttpException('The payment methods cannot be resolved in the current state of cart!');
}

$payments = [];

foreach ($cart->getPayments() as $payment) {
$payments['payments'][] = [
'methods' => $this->getPaymentMethods($payment, $cart->getLocaleCode()),
];
}

return $this->restViewHandler->handle(View::create($payments));
}

/**
* @param mixed $cartId
*
* @return OrderInterface
*/
private function getCartOr404($cartId)
{
$cart = $this->orderRepository->findCartById($cartId);

if (null === $cart) {
throw new NotFoundHttpException(sprintf("The cart with %s id could not be found!", $cartId));
}

return $cart;
}

/**
* @param OrderInterface $cart
* @param string $transition
*
* @return bool
*/
private function isCheckoutTransitionPossible(OrderInterface $cart, $transition)
{
return $this->stateMachineFactory->get($cart, OrderCheckoutTransitions::GRAPH)->can($transition);
}

/**
* @param PaymentInterface $payment
* @param string $locale
*
* @return array
*/
private function getPaymentMethods(PaymentInterface $payment, $locale)
{
$paymentMethods = $this->paymentMethodResolver->getSupportedMethods($payment);

$rawPaymentMethods = [];

foreach ($paymentMethods as $paymentMethod) {
$rawPaymentMethods[] = [
'id' => $paymentMethod->getId(),
'code' => $paymentMethod->getCode(),
'name' => $paymentMethod->getTranslation($locale)->getName(),
'description' => $paymentMethod->getTranslation($locale)->getDescription(),
];
}

return $rawPaymentMethods;
}
}
@@ -0,0 +1,157 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sylius\Bundle\ApiBundle\Controller;

use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use SM\Factory\FactoryInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Registry\ServiceRegistryInterface;
use Sylius\Component\Shipping\Resolver\ShippingMethodsResolverInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
*/
final class ShowAvailableShippingMethodsController
{
/**
* @var FactoryInterface
*/
private $stateMachineFactory;

/**
* @var OrderRepositoryInterface
*/
private $orderRepository;

/**
* @var ShippingMethodsResolverInterface
*/
private $shippingMethodsResolver;

/**
* @var ViewHandlerInterface
*/
private $restViewHandler;

/**
* @var ServiceRegistryInterface
*/
private $calculators;

/**
* @param FactoryInterface $stateMachineFactory
* @param OrderRepositoryInterface $orderRepository
* @param ShippingMethodsResolverInterface $shippingMethodsResolver
* @param ViewHandlerInterface $restViewHandler
* @param ServiceRegistryInterface $calculators
*/
public function __construct(
FactoryInterface $stateMachineFactory,
OrderRepositoryInterface $orderRepository,
ShippingMethodsResolverInterface $shippingMethodsResolver,
ViewHandlerInterface $restViewHandler,
ServiceRegistryInterface $calculators
) {
$this->stateMachineFactory = $stateMachineFactory;
$this->orderRepository = $orderRepository;
$this->shippingMethodsResolver = $shippingMethodsResolver;
$this->restViewHandler = $restViewHandler;
$this->calculators = $calculators;
}

/**
* @param Request $request
*
* @return Response
*/
public function showAction(Request $request)
{
/** @var OrderInterface $cart */
$cart = $this->getCartOr404($request->attributes->get('orderId'));

if (!$this->isCheckoutTransitionPossible($cart, OrderCheckoutTransitions::TRANSITION_SELECT_SHIPPING)) {
throw new BadRequestHttpException('The shipment methods cannot be resolved in the current state of cart!');
}

$shipments = [];

foreach ($cart->getShipments() as $shipment) {
$shipments['shipments'][] = [
'methods' => $this->getCalculatedShippingMethods($shipment, $cart->getLocaleCode()),
];
}

return $this->restViewHandler->handle(View::create($shipments));
}

/**
* @param mixed $cartId
*
* @return OrderInterface
*/
private function getCartOr404($cartId)
{
$cart = $this->orderRepository->findCartById($cartId);

if (null === $cart) {
throw new NotFoundHttpException(sprintf("The cart with %s id could not be found!", $cartId));
}

return $cart;
}

/**
* @param OrderInterface $cart
* @param string $transition
*
* @return bool
*/
private function isCheckoutTransitionPossible(OrderInterface $cart, $transition)
{
return $this->stateMachineFactory->get($cart, OrderCheckoutTransitions::GRAPH)->can($transition);
}

/**
* @param ShipmentInterface $shipment
* @param string $locale
*
* @return array
*/
private function getCalculatedShippingMethods(ShipmentInterface $shipment, $locale)
{
$shippingMethods = $this->shippingMethodsResolver->getSupportedMethods($shipment);

$rawShippingMethods = [];

foreach ($shippingMethods as $shippingMethod) {
$calculator = $this->calculators->get($shippingMethod->getCalculator());

$rawShippingMethods[] = [
'id' => $shippingMethod->getId(),
'code' => $shippingMethod->getCode(),
'name' => $shippingMethod->getTranslation($locale)->getName(),
'description' => $shippingMethod->getTranslation($locale)->getDescription(),
'price' => $calculator->calculate($shipment, $shippingMethod->getConfiguration()),
];
}

return $rawShippingMethods;
}
}
Expand Up @@ -29,7 +29,7 @@ sylius_api_checkout_available_shipping_methods:
path: /select-shipping/{orderId}
methods: [GET]
defaults:
_controller: sylius.controller.order:showAvailableShippingMethodsAction
_controller: sylius.controller.show_available_shipping_methods:showAction
_sylius:
serialization_version: $version

Expand All @@ -52,7 +52,7 @@ sylius_api_checkout_available_payment_methods:
path: /select-payment/{orderId}
methods: [GET]
defaults:
_controller: sylius.controller.order:showAvailablePaymentMethodsAction
_controller: sylius.controller.show_available_payment_methods:showAction
_sylius:
serialization_version: $version

Expand Down
1 change: 1 addition & 0 deletions src/Sylius/Bundle/ApiBundle/Resources/config/services.xml
Expand Up @@ -13,6 +13,7 @@

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<imports>
<import resource="services/controller.xml" />
<import resource="services/form.xml" />
<import resource="services/fixture.xml" />
<import resource="services/fixtures_factories.xml" />
Expand Down
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>

<!--
This file is part of the Sylius package.
(c) Paweł Jędrzejewski
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
-->

<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="sylius.controller.show_available_payment_methods" class="Sylius\Bundle\ApiBundle\Controller\ShowAvailablePaymentMethodsController">
<argument type="service" id="sm.factory" />
<argument type="service" id="sylius.repository.order" />
<argument type="service" id="sylius.payment_methods_resolver" />
<argument type="service" id="fos_rest.view_handler" />
</service>
<service id="sylius.controller.show_available_shipping_methods" class="Sylius\Bundle\ApiBundle\Controller\ShowAvailableShippingMethodsController">
<argument type="service" id="sm.factory" />
<argument type="service" id="sylius.repository.order" />
<argument type="service" id="sylius.shipping_methods_resolver" />
<argument type="service" id="fos_rest.view_handler" />
<argument type="service" id="sylius.registry.shipping_calculator" />
</service>
</services>
</container>

0 comments on commit daaaf35

Please sign in to comment.