Skip to content

Commit

Permalink
[Cart] Add custom put item to cart command provider
Browse files Browse the repository at this point in the history
  • Loading branch information
GSadee committed Jul 25, 2019
1 parent 91bd466 commit da515f4
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 41 deletions.
87 changes: 87 additions & 0 deletions spec/CommandProvider/PutItemToCartCommandProviderSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

namespace spec\Sylius\ShopApiPlugin\CommandProvider;

use PhpSpec\ObjectBehavior;
use Sylius\ShopApiPlugin\CommandProvider\CommandProviderInterface;
use Sylius\ShopApiPlugin\Request\Cart\PutOptionBasedConfigurableItemToCartRequest;
use Sylius\ShopApiPlugin\Request\Cart\PutSimpleItemToCartRequest;
use Sylius\ShopApiPlugin\Request\Cart\PutVariantBasedConfigurableItemToCartRequest;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

final class PutItemToCartCommandProviderSpec extends ObjectBehavior
{
function let(ValidatorInterface $validator): void
{
$this->beConstructedWith($validator);
}

function it_implements_command_provider_interface(): void
{
$this->shouldHaveType(CommandProviderInterface::class);
}

function it_validates_put_simple_item_to_cart_request(
ValidatorInterface $validator,
Request $httpRequest,
ConstraintViolationListInterface $constraintViolationList
): void {
$httpRequest->attributes = new ParameterBag(['token' => 'ORDERTOKEN']);
$httpRequest->request = new ParameterBag([
'productCode' => 'HACKTOBERFEST_TSHIRT_CODE',
'quantity' => 4,
]);

$validator
->validate(PutSimpleItemToCartRequest::fromHttpRequest($httpRequest->getWrappedObject()))
->willReturn($constraintViolationList)
;

$this->validate($httpRequest)->shouldReturn($constraintViolationList);
}

function it_validates_put_variant_based_configurable_item_to_cart_request(
ValidatorInterface $validator,
Request $httpRequest,
ConstraintViolationListInterface $constraintViolationList
): void {
$httpRequest->attributes = new ParameterBag(['token' => 'ORDERTOKEN']);
$httpRequest->request = new ParameterBag([
'productCode' => 'HACKTOBERFEST_TSHIRT_CODE',
'variantCode' => 'LARGE_HACKTOBERFEST_TSHIRT_CODE',
'quantity' => 4,
]);

$validator
->validate(PutVariantBasedConfigurableItemToCartRequest::fromHttpRequest($httpRequest->getWrappedObject()))
->willReturn($constraintViolationList)
;

$this->validate($httpRequest)->shouldReturn($constraintViolationList);
}

function it_validates_put_option_based_configurable_item_to_cart_request(
ValidatorInterface $validator,
Request $httpRequest,
ConstraintViolationListInterface $constraintViolationList
): void {
$httpRequest->attributes = new ParameterBag(['token' => 'ORDERTOKEN']);
$httpRequest->request = new ParameterBag([
'productCode' => 'HACKTOBERFEST_TSHIRT_CODE',
'options' => ['LARGE_CODE'],
'quantity' => 4,
]);

$validator
->validate(PutOptionBasedConfigurableItemToCartRequest::fromHttpRequest($httpRequest->getWrappedObject()))
->willReturn($constraintViolationList)
;

$this->validate($httpRequest)->shouldReturn($constraintViolationList);
}
}
56 changes: 56 additions & 0 deletions src/CommandProvider/PutItemToCartCommandProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Sylius\ShopApiPlugin\CommandProvider;

use Sylius\ShopApiPlugin\Command\CommandInterface;
use Sylius\ShopApiPlugin\Request\Cart\PutOptionBasedConfigurableItemToCartRequest;
use Sylius\ShopApiPlugin\Request\Cart\PutSimpleItemToCartRequest;
use Sylius\ShopApiPlugin\Request\Cart\PutVariantBasedConfigurableItemToCartRequest;
use Sylius\ShopApiPlugin\Request\RequestInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

final class PutItemToCartCommandProvider implements CommandProviderInterface
{
/** @var ValidatorInterface */
private $validator;

public function __construct(ValidatorInterface $validator)
{
$this->validator = $validator;
}

public function validate(Request $httpRequest): ConstraintViolationListInterface
{
return $this->validator->validate($this->transformHttpRequest($httpRequest));
}

public function getCommand(Request $httpRequest): CommandInterface
{
return $this->transformHttpRequest($httpRequest)->getCommand();
}

private function transformHttpRequest(Request $httpRequest): RequestInterface
{
$hasVariantCode = $httpRequest->request->has('variantCode');
$hasOptionCode = $httpRequest->request->has('options');

if (!$hasVariantCode && !$hasOptionCode) {
return PutSimpleItemToCartRequest::fromHttpRequest($httpRequest);
}

if ($hasVariantCode && !$hasOptionCode) {
return PutVariantBasedConfigurableItemToCartRequest::fromHttpRequest($httpRequest);
}

if (!$hasVariantCode && $hasOptionCode) {
return PutOptionBasedConfigurableItemToCartRequest::fromHttpRequest($httpRequest);
}

throw new NotFoundHttpException('Variant not found for given configuration');
}
}
46 changes: 9 additions & 37 deletions src/Controller/Cart/PutItemToCartAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@
use Sylius\ShopApiPlugin\Command\Cart\PutOptionBasedConfigurableItemToCart;
use Sylius\ShopApiPlugin\Command\Cart\PutSimpleItemToCart;
use Sylius\ShopApiPlugin\Command\Cart\PutVariantBasedConfigurableItemToCart;
use Sylius\ShopApiPlugin\CommandProvider\CommandProviderInterface;
use Sylius\ShopApiPlugin\Factory\ValidationErrorViewFactoryInterface;
use Sylius\ShopApiPlugin\Normalizer\RequestCartTokenNormalizerInterface;
use Sylius\ShopApiPlugin\Request\Cart\PutOptionBasedConfigurableItemToCartRequest;
use Sylius\ShopApiPlugin\Request\Cart\PutSimpleItemToCartRequest;
use Sylius\ShopApiPlugin\Request\Cart\PutVariantBasedConfigurableItemToCartRequest;
use Sylius\ShopApiPlugin\Request\RequestInterface;
use Sylius\ShopApiPlugin\ViewRepository\Cart\CartViewRepositoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

final class PutItemToCartAction
{
Expand All @@ -31,9 +26,6 @@ final class PutItemToCartAction
/** @var MessageBusInterface */
private $bus;

/** @var ValidatorInterface */
private $validator;

/** @var ValidationErrorViewFactoryInterface */
private $validationErrorViewFactory;

Expand All @@ -43,20 +35,23 @@ final class PutItemToCartAction
/** @var RequestCartTokenNormalizerInterface */
private $requestCartTokenNormalizer;

/** @var CommandProviderInterface */
private $putItemToCartCommandProvider;

public function __construct(
ViewHandlerInterface $viewHandler,
MessageBusInterface $bus,
ValidatorInterface $validator,
ValidationErrorViewFactoryInterface $validationErrorViewFactory,
CartViewRepositoryInterface $cartQuery,
RequestCartTokenNormalizerInterface $requestCartTokenNormalizer
RequestCartTokenNormalizerInterface $requestCartTokenNormalizer,
CommandProviderInterface $putItemToCartCommandProvider
) {
$this->viewHandler = $viewHandler;
$this->bus = $bus;
$this->validator = $validator;
$this->validationErrorViewFactory = $validationErrorViewFactory;
$this->cartQuery = $cartQuery;
$this->requestCartTokenNormalizer = $requestCartTokenNormalizer;
$this->putItemToCartCommandProvider = $putItemToCartCommandProvider;
}

public function __invoke(Request $request): Response
Expand All @@ -67,10 +62,7 @@ public function __invoke(Request $request): Response
throw new BadRequestHttpException($exception->getMessage());
}

$commandRequest = $this->provideCommandRequest($request);

$validationResults = $this->validator->validate($commandRequest);

$validationResults = $this->putItemToCartCommandProvider->validate($request);
if (0 !== count($validationResults)) {
return $this->viewHandler->handle(View::create(
$this->validationErrorViewFactory->create($validationResults),
Expand All @@ -79,7 +71,7 @@ public function __invoke(Request $request): Response
}

/** @var PutOptionBasedConfigurableItemToCart|PutSimpleItemToCart|PutVariantBasedConfigurableItemToCart $command */
$command = $commandRequest->getCommand();
$command = $this->putItemToCartCommandProvider->getCommand($request);
$this->bus->dispatch($command);

try {
Expand All @@ -91,24 +83,4 @@ public function __invoke(Request $request): Response
throw new BadRequestHttpException($exception->getMessage());
}
}

private function provideCommandRequest(Request $request): RequestInterface
{
$hasVariantCode = $request->request->has('variantCode');
$hasOptionCode = $request->request->has('options');

if (!$hasVariantCode && !$hasOptionCode) {
return PutSimpleItemToCartRequest::fromHttpRequest($request);
}

if ($hasVariantCode && !$hasOptionCode) {
return PutVariantBasedConfigurableItemToCartRequest::fromHttpRequest($request);
}

if (!$hasVariantCode && $hasOptionCode) {
return PutOptionBasedConfigurableItemToCartRequest::fromHttpRequest($request);
}

throw new NotFoundHttpException('Variant not found for given configuration');
}
}
6 changes: 3 additions & 3 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
use Sylius\ShopApiPlugin\Request\Cart\ChangeItemQuantityRequest;
use Sylius\ShopApiPlugin\Request\Cart\DropCartRequest;
use Sylius\ShopApiPlugin\Request\Cart\PickupCartRequest;
use Sylius\ShopApiPlugin\Request\Product\AddProductReviewByCodeRequest;
use Sylius\ShopApiPlugin\Request\Product\AddProductReviewBySlugRequest;
use Sylius\ShopApiPlugin\Request\Cart\RemoveCouponRequest;
use Sylius\ShopApiPlugin\Request\Cart\RemoveItemFromCartRequest;
use Sylius\ShopApiPlugin\Request\Product\AddProductReviewByCodeRequest;
use Sylius\ShopApiPlugin\Request\Product\AddProductReviewBySlugRequest;
use Sylius\ShopApiPlugin\View;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
Expand Down Expand Up @@ -91,7 +91,7 @@ private function buildRequestClassesNode(ArrayNodeDefinition $rootNode): void
->arrayNode('request_classes')
->addDefaultsIfNotSet()
->children()
->scalarNode('add_coupon')->defaultValue(AddCouponRequest::class)->end()
->scalarNode('add_coupon')->defaultValue(AddCouponRequest::class)->end()
->scalarNode('add_product_review_by_code')->defaultValue(AddProductReviewByCodeRequest::class)->end()
->scalarNode('add_product_review_by_slug')->defaultValue(AddProductReviewBySlugRequest::class)->end()
->scalarNode('change_item_quantity')->defaultValue(ChangeItemQuantityRequest::class)->end()
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/config/services/actions/cart.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@
>
<argument type="service" id="fos_rest.view_handler" />
<argument type="service" id="sylius_shop_api_plugin.command_bus" />
<argument type="service" id="validator" />
<argument type="service" id="sylius.shop_api_plugin.factory.validation_error_view_factory" />
<argument type="service" id="sylius.shop_api_plugin.view_repository.cart_view_repository" />
<argument type="service" id="sylius.shop_api_plugin.normalizer.request_cart_token_normalizer" />
<argument type="service" id="sylius.shop_api_plugin.command_provider.put_item_to_cart" />
</service>

<service
Expand Down
7 changes: 7 additions & 0 deletions src/Resources/config/services/command_providers/cart.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
<argument type="service" id="validator" />
</service>

<service
id="sylius.shop_api_plugin.command_provider.put_item_to_cart"
class="Sylius\ShopApiPlugin\CommandProvider\PutItemToCartCommandProvider"
>
<argument type="service" id="validator" />
</service>

<service
id="sylius.shop_api_plugin.command_provider.remove_coupon"
class="Sylius\ShopApiPlugin\CommandProvider\DefaultCommandProvider"
Expand Down

0 comments on commit da515f4

Please sign in to comment.