diff --git a/spec/Validator/Cart/CartExistsValidatorSpec.php b/spec/Validator/Cart/CartExistsValidatorSpec.php index 1f824819e..fb71d5ae7 100644 --- a/spec/Validator/Cart/CartExistsValidatorSpec.php +++ b/spec/Validator/Cart/CartExistsValidatorSpec.php @@ -9,6 +9,7 @@ use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Repository\OrderRepositoryInterface; use Sylius\ShopApiPlugin\Validator\Constraints\CartExists; +use Sylius\ShopApiPlugin\Validator\Constraints\CartItemExists; use Symfony\Component\Validator\Context\ExecutionContextInterface; final class CartExistsValidatorSpec extends ObjectBehavior @@ -42,4 +43,12 @@ function it_adds_constraint_if_order_does_not_exits_exists( $this->validate('ORDERTOKEN', new CartExists()); } + + function it_throws_an_exception_if_constraint_is_not_cart_exists(): void + { + $this + ->shouldThrow(\InvalidArgumentException::class) + ->during('validate', ['ORDERTOKEN', new CartItemExists()]) + ; + } } diff --git a/src/Controller/Checkout/AddressAction.php b/src/Controller/Checkout/AddressAction.php index 10c92820b..90fc84b4d 100644 --- a/src/Controller/Checkout/AddressAction.php +++ b/src/Controller/Checkout/AddressAction.php @@ -6,11 +6,12 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; -use Sylius\ShopApiPlugin\Command\Cart\AddressOrder; -use Sylius\ShopApiPlugin\Model\Address; +use Sylius\ShopApiPlugin\Factory\ValidationErrorViewFactoryInterface; +use Sylius\ShopApiPlugin\Request\Checkout\AddressOrderRequest; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; final class AddressAction { @@ -20,20 +21,38 @@ final class AddressAction /** @var MessageBusInterface */ private $bus; - public function __construct(ViewHandlerInterface $viewHandler, MessageBusInterface $bus) - { + /** @var ValidatorInterface */ + private $validator; + + /** @var ValidationErrorViewFactoryInterface */ + private $validationErrorViewFactory; + + public function __construct( + ViewHandlerInterface $viewHandler, + MessageBusInterface $bus, + ValidatorInterface $validator, + ValidationErrorViewFactoryInterface $validationErrorViewFactory + ) { $this->viewHandler = $viewHandler; $this->bus = $bus; + $this->validator = $validator; + $this->validationErrorViewFactory = $validationErrorViewFactory; } public function __invoke(Request $request): Response { - $this->bus->dispatch(new AddressOrder( - $request->attributes->get('token'), - Address::createFromArray($request->request->get('shippingAddress')), - Address::createFromArray($request->request->get('billingAddress') ?: $request->request->get('shippingAddress')) - )); + $addressOrderRequest = new AddressOrderRequest($request); - return $this->viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT)); + $validationResults = $this->validator->validate($addressOrderRequest); + if (0 === count($validationResults)) { + $this->bus->dispatch($addressOrderRequest->getCommand()); + + return $this->viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT)); + } + + return $this->viewHandler->handle(View::create( + $this->validationErrorViewFactory->create($validationResults), + Response::HTTP_BAD_REQUEST + )); } } diff --git a/src/Request/Checkout/AddressOrderRequest.php b/src/Request/Checkout/AddressOrderRequest.php new file mode 100644 index 000000000..69da535b2 --- /dev/null +++ b/src/Request/Checkout/AddressOrderRequest.php @@ -0,0 +1,52 @@ +token = $request->attributes->get('token'); + $this->shippingAddress = $request->request->get('shippingAddress'); + $this->billingAddress = $request->request->get('billingAddress') ?: $request->request->get('shippingAddress'); + } + + public function getCommand(): AddressOrder + { + return new AddressOrder( + $this->token, + Address::createFromArray($this->shippingAddress), + Address::createFromArray($this->billingAddress) + ); + } + + public function getToken(): ?string + { + return $this->token; + } + + public function getShippingAddress(): ?array + { + return $this->shippingAddress; + } + + public function getBillingAddress(): ?array + { + return $this->billingAddress; + } +} diff --git a/src/Resources/config/services/actions/checkout.xml b/src/Resources/config/services/actions/checkout.xml index 7f2a437f5..06b9e4c33 100644 --- a/src/Resources/config/services/actions/checkout.xml +++ b/src/Resources/config/services/actions/checkout.xml @@ -9,6 +9,8 @@ > + + + + + + + + + + + + + + + diff --git a/src/Validator/Cart/CartExistsValidator.php b/src/Validator/Cart/CartExistsValidator.php index 3b913d790..c0b387101 100644 --- a/src/Validator/Cart/CartExistsValidator.php +++ b/src/Validator/Cart/CartExistsValidator.php @@ -6,8 +6,10 @@ use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Repository\OrderRepositoryInterface; +use Sylius\ShopApiPlugin\Validator\Constraints\CartExists; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; +use Webmozart\Assert\Assert; final class CartExistsValidator extends ConstraintValidator { @@ -22,6 +24,8 @@ public function __construct(OrderRepositoryInterface $orderRepository) /** {@inheritdoc} */ public function validate($token, Constraint $constraint) { + Assert::isInstanceOf($constraint, CartExists::class); + if (null === $this->orderRepository->findOneBy(['tokenValue' => $token, 'state' => OrderInterface::STATE_CART])) { $this->context->addViolation($constraint->message); } diff --git a/tests/Controller/Checkout/CheckoutAddressApiTest.php b/tests/Controller/Checkout/CheckoutAddressApiTest.php index c26a11d0b..da85958c0 100644 --- a/tests/Controller/Checkout/CheckoutAddressApiTest.php +++ b/tests/Controller/Checkout/CheckoutAddressApiTest.php @@ -14,14 +14,30 @@ final class CheckoutAddressApiTest extends JsonApiTestCase { /** - * TODO check is it possible (test annotation make it fail) + * @test */ public function it_does_not_allow_to_address_non_existing_order(): void { - $this->client->request('PUT', '/shop-api/WEB_GB/checkout/SDAOSLEFNWU35H3QLI5325/address', [], [], self::CONTENT_TYPE_HEADER); + $this->loadFixturesFromFiles(['shop.yml']); + + $data = +<<client->request('PUT', '/shop-api/WEB_GB/checkout/WRONGTOKEN/address', [], [], self::CONTENT_TYPE_HEADER, $data); $response = $this->client->getResponse(); - $this->assertResponse($response, 'cart/cart_has_not_been_found_response', Response::HTTP_NOT_FOUND); + $this->assertResponse($response, 'cart/validation_cart_not_exists_response', Response::HTTP_BAD_REQUEST); } /**