Skip to content

Commit

Permalink
Added cart eligibility validation property mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
Nenad Stefanovic authored and Nenad Stefanovic committed Dec 17, 2020
1 parent 30719d9 commit 2e5d54d
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 24 deletions.
41 changes: 31 additions & 10 deletions spec/Validator/Cart/CartEligibilityValidatorSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\ShopApiPlugin\Request\Checkout\CompleteOrderRequest;
use Sylius\ShopApiPlugin\Validator\Constraints\CartEligibility;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;

final class CartEligibilityValidatorSpec extends ObjectBehavior
{
Expand All @@ -34,15 +36,19 @@ function it_add_no_violation_if_cart_has_eligible_item(
ProductInterface $product,
ArrayCollection $collection,
ArrayIterator $arrayIterator,
ExecutionContextInterface $context
ExecutionContextInterface $context,
CompleteOrderRequest $completeOrderRequest
): void {
$completeOrderRequest->getToken()->willReturn('CART_TOKEN');

$repository->findOneBy(['tokenValue' => 'CART_TOKEN', 'state' => OrderInterface::STATE_CART])->willReturn($order);

$arrayIterator->valid()->will(new ReturnPromise(array_merge(array_fill(0, count([$orderItem]), true), [false])));
$arrayIterator->current()->will(new ReturnPromise([$orderItem]));
$arrayIterator->count()->willReturn(count([$orderItem]));
$arrayIterator->next()->willReturn();
$arrayIterator->rewind()->willReturn();
$arrayIterator->key()->willReturn(0);

$order->getItems()->willReturn($collection);
$collection->getIterator()->willReturn($arrayIterator);
Expand All @@ -53,10 +59,11 @@ function it_add_no_violation_if_cart_has_eligible_item(
$productVariant->isEnabled()->willReturn(true);
$product->isEnabled()->willReturn(true);

$context->addViolation('sylius.shop_api.checkout.cart_item.non_eligible')->shouldNotBeCalled();
$context->addViolation('sylius.shop_api.checkout.cart_item_variant.non_eligible')->shouldNotBeCalled();
$context->buildViolation('sylius.shop_api.checkout.cart_item.non_eligible')->shouldNotBeCalled();

$this->validate('CART_TOKEN', new CartEligibility());
$context->buildViolation('sylius.shop_api.checkout.cart_item_variant.non_eligible')->shouldNotBeCalled();

$this->validate($completeOrderRequest, new CartEligibility());
}

function it_add_violation_if_cart_has_non_eligible_item_variant(
Expand All @@ -66,15 +73,20 @@ function it_add_violation_if_cart_has_non_eligible_item_variant(
ProductVariantInterface $productVariant,
ArrayCollection $collection,
ArrayIterator $arrayIterator,
ExecutionContextInterface $context
ExecutionContextInterface $context,
ConstraintViolationBuilderInterface $builder,
CompleteOrderRequest $completeOrderRequest
): void {
$completeOrderRequest->getToken()->willReturn('CART_TOKEN');

$repository->findOneBy(['tokenValue' => 'CART_TOKEN', 'state' => OrderInterface::STATE_CART])->willReturn($order);

$arrayIterator->valid()->will(new ReturnPromise(array_merge(array_fill(0, count([$orderItem]), true), [false])));
$arrayIterator->current()->will(new ReturnPromise([$orderItem]));
$arrayIterator->count()->willReturn(count([$orderItem]));
$arrayIterator->next()->willReturn();
$arrayIterator->rewind()->willReturn();
$arrayIterator->key()->willReturn(0);

$order->getItems()->willReturn($collection);
$collection->getIterator()->willReturn($arrayIterator);
Expand All @@ -83,9 +95,11 @@ function it_add_violation_if_cart_has_non_eligible_item_variant(

$productVariant->isEnabled()->willReturn(false);

$context->addViolation('sylius.shop_api.checkout.cart_item_variant.non_eligible')->shouldBeCalled();
$context->buildViolation('sylius.shop_api.checkout.cart_item_variant.non_eligible')->willReturn($builder);
$builder->atPath('items[0].product.variants[0].code')->willReturn($builder);
$builder->addViolation()->shouldBeCalled();

$this->validate('CART_TOKEN', new CartEligibility());
$this->validate($completeOrderRequest, new CartEligibility());
}

function it_add_violation_if_cart_has_non_eligible_item(
Expand All @@ -96,15 +110,20 @@ function it_add_violation_if_cart_has_non_eligible_item(
ProductInterface $product,
ArrayCollection $collection,
ArrayIterator $arrayIterator,
ExecutionContextInterface $context
ExecutionContextInterface $context,
ConstraintViolationBuilderInterface $builder,
CompleteOrderRequest $completeOrderRequest
): void {
$completeOrderRequest->getToken()->willReturn('CART_TOKEN');

$repository->findOneBy(['tokenValue' => 'CART_TOKEN', 'state' => OrderInterface::STATE_CART])->willReturn($order);

$arrayIterator->valid()->will(new ReturnPromise(array_merge(array_fill(0, count([$orderItem]), true), [false])));
$arrayIterator->current()->will(new ReturnPromise([$orderItem]));
$arrayIterator->count()->willReturn(count([$orderItem]));
$arrayIterator->next()->willReturn();
$arrayIterator->rewind()->willReturn();
$arrayIterator->key()->willReturn(0);

$order->getItems()->willReturn($collection);
$collection->getIterator()->willReturn($arrayIterator);
Expand All @@ -115,8 +134,10 @@ function it_add_violation_if_cart_has_non_eligible_item(
$productVariant->isEnabled()->willReturn(true);
$product->isEnabled()->willReturn(false);

$context->addViolation('sylius.shop_api.checkout.cart_item.non_eligible')->shouldBeCalled();
$context->buildViolation('sylius.shop_api.checkout.cart_item.non_eligible')->willReturn($builder);
$builder->atPath('items[0].product.code')->willReturn($builder);
$builder->addViolation()->shouldBeCalled();

$this->validate('CART_TOKEN', new CartEligibility());
$this->validate($completeOrderRequest, new CartEligibility());
}
}
5 changes: 5 additions & 0 deletions src/Request/Checkout/CompleteOrderRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ public function getCommand(): CommandInterface
{
return new CompleteOrder($this->token, $this->notes);
}

public function getToken(): string
{
return $this->token;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
<class name="Sylius\ShopApiPlugin\Request\Checkout\CompleteOrderRequest">
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartEligibility" />

<property name="token">
<constraint name="NotNull">
Expand All @@ -21,7 +22,6 @@
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartExists" />
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartNotEmpty" />
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartReadyForCheckout" />
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartEligibility" />
</property>
</class>
</constraint-mapping>
22 changes: 12 additions & 10 deletions src/Validator/Cart/CartEligibilityValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\ShopApiPlugin\Request\Checkout\CompleteOrderRequest;
use Sylius\ShopApiPlugin\Validator\Constraints\CartEligibility;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
Expand All @@ -28,15 +29,16 @@ public function __construct(OrderRepositoryInterface $cartRepository)
}

/**
* @param mixed $token
* @param mixed $request
*/
public function validate($token, Constraint $constraint): void
public function validate($request, Constraint $constraint): void
{
Assert::isInstanceOf($request, CompleteOrderRequest::class);
Assert::isInstanceOf($constraint, CartEligibility::class);

$cart = $this->_cartRepository->findOneBy(
[
'tokenValue' => $token,
'tokenValue' => $request->getToken(),
'state' => OrderInterface::STATE_CART,
]
);
Expand All @@ -48,16 +50,16 @@ public function validate($token, Constraint $constraint): void
Assert::isInstanceOf($cart, OrderInterface::class);

$cartItems = $cart->getItems();
foreach ($cartItems as $item) {
foreach ($cartItems as $key => $item) {
Assert::isInstanceOf($item, OrderItemInterface::class);

$variant = $item->getVariant();

Assert::isInstanceOf($variant, ProductVariantInterface::class);
if (!$variant->isEnabled()) {
$this->context->addViolation(
$constraint->nonEligibleCartItemVariantMessage
);
$this->context->buildViolation($constraint->nonEligibleCartItemVariantMessage)
->atPath('items[' . $key . '].product.variants[0].code')
->addViolation();

break;
}
Expand All @@ -66,9 +68,9 @@ public function validate($token, Constraint $constraint): void

Assert::isInstanceOf($product, ProductInterface::class);
if (!$product->isEnabled()) {
$this->context->addViolation(
$constraint->nonEligibleCartItemMessage
);
$this->context->buildViolation($constraint->nonEligibleCartItemMessage)
->atPath('items[' . $key . '].product.code')
->addViolation();

break;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Validator/Constraints/CartEligibility.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class CartEligibility extends Constraint
/** {@inheritdoc} */
public function getTargets()
{
return self::PROPERTY_CONSTRAINT;
return self::CLASS_CONSTRAINT;
}

/** {@inheritdoc} */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"code":400,
"message":"Validation failed",
"errors":{
"token":[
"items[0].product.code":[
"sylius.shop_api.checkout.cart_item.non_eligible"
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"code":400,
"message":"Validation failed",
"errors":{
"token":[
"items[0].product.variants[0].code":[
"sylius.shop_api.checkout.cart_item_variant.non_eligible"
]
}
Expand Down

0 comments on commit 2e5d54d

Please sign in to comment.