Skip to content

Commit

Permalink
Implemented compatibility with sylius 1.8 and added integrations test…
Browse files Browse the repository at this point in the history
…s for product eligibility
  • Loading branch information
Nenad Stefanovic authored and Nenad Stefanovic committed Nov 18, 2020
1 parent 775e657 commit ec87c8c
Show file tree
Hide file tree
Showing 38 changed files with 824 additions and 57 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
/phpunit.xml

/.idea/
/docker/
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"require": {
"php": "^7.2",

"sylius/sylius": "^1.4",
"sylius/sylius": "^1.8",
"lexik/jwt-authentication-bundle": "^2.5",
"symfony/messenger": "^4.3"
},
Expand Down
93 changes: 93 additions & 0 deletions spec/Validator/Cart/CartCheckoutItemEligibilityValidatorSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

namespace spec\Sylius\ShopApiPlugin\Validator\Cart;

use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\ShopApiPlugin\Validator\Constraints\CartCheckoutItemEligibility;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

final class CartCheckoutItemEligibilityValidatorSpec extends ObjectBehavior
{
function let(
RepositoryInterface $repository,
ExecutionContextInterface $context
): void {
$this->beConstructedWith($repository);
$this->initialize($context);
}

function it_add_no_violation_if_cart_has_eligible_item(
RepositoryInterface $repository,
OrderInterface $order,
OrderItemInterface $orderItem,
ProductVariantInterface $productVariant,
ProductInterface $product,
ArrayCollection $collection,
ExecutionContextInterface $context
): void {
$repository->findOneBy(['tokenValue' => 'CART_TOKEN'])->willReturn($order);
$order->getItems()->willReturn($collection);
$collection->toArray()->willReturn([$orderItem]);
$orderItem->getVariant()->willReturn($productVariant);
$productVariant->getProduct()->willReturn($product);

$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();

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

function it_add_violation_if_cart_has_non_eligible_item_variant(
RepositoryInterface $repository,
OrderInterface $order,
OrderItemInterface $orderItem,
ProductVariantInterface $productVariant,
ArrayCollection $collection,
ExecutionContextInterface $context
): void {
$repository->findOneBy(['tokenValue' => 'CART_TOKEN'])->willReturn($order);
$order->getItems()->willReturn($collection);
$collection->toArray()->willReturn([$orderItem]);
$orderItem->getVariant()->willReturn($productVariant);
$productVariant->isEnabled()->willReturn(false);

$context->addViolation('sylius.shop_api.checkout.cart_item_variant.non_eligible')->shouldBeCalled();

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

function it_add_violation_if_cart_has_non_eligible_item(
RepositoryInterface $repository,
OrderInterface $order,
OrderItemInterface $orderItem,
ProductVariantInterface $productVariant,
ProductInterface $product,
ArrayCollection $collection,
ExecutionContextInterface $context
): void {
$repository->findOneBy(['tokenValue' => 'CART_TOKEN'])->willReturn($order);
$order->getItems()->willReturn($collection);
$collection->toArray()->willReturn([$orderItem]);
$orderItem->getVariant()->willReturn($productVariant);
$productVariant->isEnabled()->willReturn(true);

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

$context->addViolation('sylius.shop_api.checkout.cart_item.non_eligible')->shouldBeCalled();

$this->validate('CART_TOKEN', new CartCheckoutItemEligibility());
}
}
78 changes: 78 additions & 0 deletions spec/Validator/Cart/CartItemEligibilityValidatorSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

namespace spec\Sylius\ShopApiPlugin\Validator\Cart;

use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\ProductVariant;
use Sylius\Component\Order\Repository\OrderItemRepositoryInterface;
use Sylius\Component\Core\Model\Product;
use Sylius\ShopApiPlugin\Validator\Constraints\CartItemEligibility;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

final class CartItemEligibilityValidatorSpec extends ObjectBehavior
{
function let(ExecutionContextInterface $executionContext, OrderItemRepositoryInterface $orderItemRepository): void
{
$this->beConstructedWith($orderItemRepository);

$this->initialize($executionContext);
}

function it_does_not_add_constraint_if_order_item_and_order_item_variant_is_eligible(
OrderItemRepositoryInterface $orderItemRepository,
ExecutionContextInterface $executionContext,
OrderItemInterface $orderItem,
ProductVariant $productVariant,
Product $product
): void {
$orderItemRepository->find(1)->willReturn($orderItem);
$orderItem->getVariant()->willReturn($productVariant);
$productVariant->isEnabled()->willReturn(true);

$productVariant->getProduct()->willReturn($product);
$product->isEnabled()->willReturn(true);

$executionContext->addViolation('sylius.shop_api.cart_item.product.non_eligible')->shouldNotBeCalled();
$executionContext->addViolation('sylius.shop_api.cart_item.product_variant.non_eligible')->shouldNotBeCalled();

$this->validate(1, new CartItemEligibility());
}

function it_adds_constraint_if_order_item_is_not_eligible(
OrderItemRepositoryInterface $orderItemRepository,
ExecutionContextInterface $executionContext,
OrderItemInterface $orderItem,
ProductVariant $productVariant,
Product $product
): void {
$orderItemRepository->find(1)->willReturn($orderItem);
$orderItem->getVariant()->willReturn($productVariant);
$productVariant->isEnabled()->willReturn(true);

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

$executionContext->addViolation('sylius.shop_api.cart_item.product.non_eligible')->shouldBeCalled();

$this->validate(1, new CartItemEligibility());
}

function it_adds_constraint_if_order_item_variant_is_not_eligible(
OrderItemRepositoryInterface $orderItemRepository,
ExecutionContextInterface $executionContext,
OrderItemInterface $orderItem,
ProductVariant $productVariant,
Product $product
): void {
$orderItemRepository->find(1)->willReturn($orderItem);
$orderItem->getVariant()->willReturn($productVariant);
$productVariant->isEnabled()->willReturn(false);

$executionContext->addViolation('sylius.shop_api.cart_item.product_variant.non_eligible')->shouldBeCalled();

$this->validate(1, new CartItemEligibility());
}
}
4 changes: 2 additions & 2 deletions spec/Validator/Product/ProductEligibilityValidatorSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function it_does_not_add_constraint_if_product_enabled(
$productRepository->findOneByCode('BARBECUE_CODE')->willReturn($product);
$product->isEnabled()->willReturn(true);

$executionContext->addViolation('sylius.shop_api.product.eligibility')->shouldNotBeCalled();
$executionContext->addViolation('sylius.shop_api.product.non_eligible')->shouldNotBeCalled();

$this->validate('BARBECUE_CODE', new ProductEligibility());
}
Expand All @@ -47,7 +47,7 @@ function it_adds_constraint_if_product_is_disabled(
$productRepository->findOneByCode('BARBECUE_CODE')->willReturn($product);
$product->isEnabled()->willReturn(false);

$executionContext->addViolation('sylius.shop_api.product.eligibility')->shouldBeCalled();
$executionContext->addViolation('sylius.shop_api.product.non_eligible')->shouldBeCalled();

$this->validate('BARBECUE_CODE', new ProductEligibility());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function it_does_not_add_a_violation_if_the_product_variant_is_enabled(
$productVariantRepository->findOneBy(['code' => 'VARIANT_CODE'])->willReturn($productVariant);
$productVariant->isEnabled()->willReturn(true);

$executionContext->addViolation('sylius.shop_api.product_variant.eligibility')->shouldNotBeCalled();
$executionContext->addViolation('sylius.shop_api.product_variant.non_eligible')->shouldNotBeCalled();

$this->validate('VARIANT_CODE', new ProductVariantEligibility());
}
Expand All @@ -43,7 +43,7 @@ function it_adds_a_violation_if_the_product_variant_does_not_exist(
$productVariantRepository->findOneBy(['code' => 'VARIANT_CODE'])->willReturn($productVariant);
$productVariant->isEnabled()->willReturn(false);

$executionContext->addViolation('sylius.shop_api.product_variant.eligibility')->shouldBeCalled();
$executionContext->addViolation('sylius.shop_api.product_variant.non_eligible')->shouldBeCalled();

$this->validate('VARIANT_CODE', new ProductVariantEligibility());
}
Expand Down
2 changes: 2 additions & 0 deletions src/Handler/Cart/PutSimpleItemToCartHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariant;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Sylius\ShopApiPlugin\Checker\ProductInCartChannelCheckerInterface;
Expand Down Expand Up @@ -52,6 +53,7 @@ public function __invoke(PutSimpleItemToCart $putSimpleItemToCart): void
Assert::true($this->channelChecker->isProductInCartChannel($product, $cart), 'Product is not in same channel as cart');
Assert::true($product->isSimple(), 'Product has to be simple');

/** @var ProductVariant $productVariant */
$productVariant = $product->getVariants()[0];

$this->orderModifier->modify($cart, $productVariant, $putSimpleItemToCart->quantity());
Expand Down
12 changes: 12 additions & 0 deletions src/Resources/config/services/validators/cart.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,17 @@
<argument type="service" id="sylius.shop_api_plugin.checker.promotion_coupon_eligibility_checker" />
<tag name="validator.constraint_validator" alias="sylius_shop_api_valid_coupon_code_validator" />
</service>

<service id="sylius.shop_api_plugin.validator.cart_item_eligibility_validator"
class="Sylius\ShopApiPlugin\Validator\Cart\CartItemEligibilityValidator">
<argument type="service" id="sylius.repository.order_item" />
<tag name="validator.constraint_validator" alias="sylius_shop_api_cart_item_eligibility_validator" />
</service>

<service id="sylius.shop_api_plugin.validator.cart.cart_checkout_item_eligibility_validator"
class="Sylius\ShopApiPlugin\Validator\Cart\CartCheckoutItemEligibilityValidator">
<argument type="service" id="sylius.repository.order" />
<tag name="validator.constraint_validator" alias="sylius_shop_api_cart_checkout_item_eligibility_validator" />
</service>
</services>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<option name="message">sylius.shop_api.cart_item.not_null</option>
</constraint>
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartItemExists" />
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartItemEligibility" />
</property>
</class>
</constraint-mapping>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
</constraint>
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartExists" />
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartReadyForCheckout" />
<constraint name="Sylius\ShopApiPlugin\Validator\Constraints\CartCheckoutItemEligibility" />
</property>
</class>
</constraint-mapping>
62 changes: 62 additions & 0 deletions src/Validator/Cart/CartCheckoutItemEligibilityValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace Sylius\ShopApiPlugin\Validator\Cart;

use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Sylius\ShopApiPlugin\Validator\Constraints\CartCheckoutItemEligibility;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

final class CartCheckoutItemEligibilityValidator extends ConstraintValidator
{
/** @var RepositoryInterface */
private $cartRepository;

public function __construct(RepositoryInterface $cartRepository)
{
$this->cartRepository = $cartRepository;
}

/** {@inheritdoc} */
public function validate($value, Constraint $constraint): void
{
/** @var OrderInterface|null $cart */
$cart = $this->cartRepository->findOneBy(['tokenValue' => $value]);
if ($cart === null) {
return;
}

$cartItems = $cart->getItems()->toArray();

/** @var OrderItemInterface $item */
foreach ($cartItems as $item) {

/** @var ProductVariantInterface $variant */
$variant = $item->getVariant();

if ($variant->isEnabled()) {

/** @var ProductInterface $product */
$product = $variant->getProduct();

if (!$product->isEnabled()) {

/** @var CartCheckoutItemEligibility $constraint */
$this->context->addViolation($constraint->messageOnNonEligibleCartItem);
break;
}
} else {

/** @var CartCheckoutItemEligibility $constraint */
$this->context->addViolation($constraint->messageOnNonEligibleCartItemVariant);
break;
}
}
}
}
57 changes: 57 additions & 0 deletions src/Validator/Cart/CartItemEligibilityValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

namespace Sylius\ShopApiPlugin\Validator\Cart;

use Sylius\Component\Core\Model\OrderItem;
use Sylius\Component\Core\Model\Product;
use Sylius\Component\Core\Model\ProductVariant;
use Sylius\Component\Order\Repository\OrderItemRepositoryInterface;
use Sylius\ShopApiPlugin\Validator\Constraints\CartItemEligibility;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

final class CartItemEligibilityValidator extends ConstraintValidator
{
/** @var OrderItemRepositoryInterface */
private $orderItemRepository;

public function __construct(OrderItemRepositoryInterface $orderItemRepository)
{
$this->orderItemRepository = $orderItemRepository;
}

/** {@inheritdoc} */
public function validate($id, Constraint $constraint): void
{
if (null === $id) {
return;
}

/** @var OrderItem|null $orderItem */
$orderItem = $this->orderItemRepository->find($id);

if ($orderItem) {

/** @var ProductVariant $variant */
$variant = $orderItem->getVariant();

if ($variant->isEnabled()) {

/** @var Product $product */
$product = $variant->getProduct();

if (!$product->isEnabled()) {

/** @var CartItemEligibility $constraint */
$this->context->addViolation($constraint->messageOnNonEligible);
}
} else {

/** @var CartItemEligibility $constraint */
$this->context->addViolation($constraint->messageOnNonEligibleVariant);
}
}
}
}
Loading

0 comments on commit ec87c8c

Please sign in to comment.