Added separate service, fix issues

This commit is contained in:
Mateusz 2026-03-30 14:30:04 +02:00
parent 0b64b135d4
commit 2f12aacf16
4 changed files with 78 additions and 29 deletions

View file

@ -12,7 +12,7 @@ Feature: Removing disabled products from cart
And this product's price is "$19.99"
And I am a logged in customer
@ui
@no-api @ui
Scenario: Disabled product is automatically removed from cart when cart page is loaded
Given I added product "PHP T-Shirt" to the cart
But the product "PHP T-Shirt" has been disabled
@ -20,7 +20,7 @@ Feature: Removing disabled products from cart
Then my cart should be empty
And I should be notified that some products in my cart are no longer available
@ui
@no-api @ui
Scenario: Disabled product variant is automatically removed from cart when cart page is loaded
Given I have "Large" variant of product "Super Cool T-Shirt" in the cart
But the "Large" product variant is disabled
@ -28,7 +28,7 @@ Feature: Removing disabled products from cart
Then my cart should be empty
And I should be notified that some products in my cart are no longer available
@ui
@no-api @ui
Scenario: Product no longer available in channel is automatically removed from cart when cart page is loaded
Given I added product "PHP T-Shirt" to the cart
But this product is not available in "United States" channel

View file

@ -0,0 +1,60 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\ShopBundle\Cart;
use Doctrine\Persistence\ObjectManager;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Order\SyliusCartEvents;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
final class DisabledCartItemsRemover
{
public function __construct(
private readonly ObjectManager $manager,
private readonly EventDispatcherInterface $eventDispatcher,
) {
}
public function removeFromOrder(OrderInterface $order): bool
{
$channel = $order->getChannel();
$itemsToRemove = [];
foreach ($order->getItems() as $item) {
$variant = $item->getVariant();
$product = $item->getProduct();
if ((null === $variant || !$variant->isEnabled()) ||
(null === $product || !$product->isEnabled()) ||
(null !== $channel && !$product->hasChannel($channel))) {
$itemsToRemove[] = $item;
}
}
if ([] === $itemsToRemove) {
return false;
}
foreach ($itemsToRemove as $item) {
$order->removeItem($item);
}
$this->eventDispatcher->dispatch(new GenericEvent($order), SyliusCartEvents::CART_CHANGE);
$this->manager->flush();
$this->manager->refresh($order);
return true;
}
}

View file

@ -11,6 +11,14 @@
<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_shop.cart.disabled_cart_items_remover"
class="Sylius\Bundle\ShopBundle\Cart\DisabledCartItemsRemover"
>
<argument type="service" id="doctrine.orm.entity_manager" />
<argument type="service" id="event_dispatcher" />
</service>
<service
id="sylius_shop.twig.component.cart.form"
class="Sylius\Bundle\ShopBundle\Twig\Component\Cart\FormComponent"
@ -21,6 +29,7 @@
<argument>Sylius\Bundle\ShopBundle\Form\Type\CartType</argument>
<argument type="service" id="doctrine.orm.entity_manager" />
<argument type="service" id="event_dispatcher" />
<argument type="service" id="sylius_shop.cart.disabled_cart_items_remover" />
<argument type="service" id="request_stack" />
<call method="setLiveResponder">

View file

@ -15,6 +15,7 @@ namespace Sylius\Bundle\ShopBundle\Twig\Component\Cart;
use Doctrine\Persistence\ObjectManager;
use Sylius\Bundle\CoreBundle\Provider\FlashBagProvider;
use Sylius\Bundle\ShopBundle\Cart\DisabledCartItemsRemover;
use Sylius\Bundle\UiBundle\Twig\Component\ResourceFormComponentTrait;
use Sylius\Bundle\UiBundle\Twig\Component\TemplatePropTrait;
use Sylius\Component\Core\Model\OrderInterface;
@ -57,7 +58,8 @@ class FormComponent
string $formClass,
protected readonly ObjectManager $manager,
protected readonly EventDispatcherInterface $eventDispatcher,
protected readonly RequestStack $requestStack,
protected readonly DisabledCartItemsRemover $disabledCartItemsRemover,
protected readonly ?RequestStack $requestStack = null,
) {
$this->initialize($orderRepository, $formFactory, $resourceClass, $formClass);
}
@ -72,33 +74,11 @@ class FormComponent
return;
}
$channel = $order->getChannel();
$itemsToRemove = [];
$removed = $this->disabledCartItemsRemover->removeFromOrder($order);
foreach ($order->getItems() as $item) {
$variant = $item->getVariant();
$product = $item->getProduct();
if ((null === $variant || !$variant->isEnabled()) ||
(null === $product || !$product->isEnabled()) ||
(null !== $channel && !$product->hasChannel($channel))) {
$itemsToRemove[] = $item;
}
if ($removed && null !== $this->requestStack) {
FlashBagProvider::getFlashBag($this->requestStack)->add('error', 'sylius.order.cart_item_removed');
}
if ([] === $itemsToRemove) {
return;
}
foreach ($itemsToRemove as $item) {
$order->removeItem($item);
}
$this->eventDispatcher->dispatch(new GenericEvent($order), SyliusCartEvents::CART_CHANGE);
$this->manager->flush();
$this->manager->refresh($order);
FlashBagProvider::getFlashBag($this->requestStack)->add('error', 'sylius.order.cart_item_removed');
}
public function hydrateResource(mixed $value): ?ResourceInterface