mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 09:02:12 +00:00
override data persister from api platform, refactor
override data persister from api platform, refactor override data persister from api platform, refactor override data persister from api platform, refactor override data persister from api platform, refactor override data persister from api platform, refactor [Spec] spec for messenger data persister removed one useless tests in OrderPromotionsIntegrityCheckerSpec review changes clean useless change removed blank space in upgradefile typo
This commit is contained in:
parent
c3858be109
commit
339fb712b3
19 changed files with 281 additions and 77 deletions
|
|
@ -7,7 +7,17 @@
|
|||
|
||||
2. Both `getCreatedByGuest` and `setCreatedByGuest` methods were deprecated on `\Sylius\Component\Core\Model\Order`.
|
||||
Please use `isCreatedByGuest` instead of the first one. The latter is a part of the `setCustomerWithAuthorization` logic
|
||||
and should be used only this way.
|
||||
and should be used only this way.
|
||||
|
||||
3. Due to refactoring constructor has been changed in service `src/Sylius/Bundle/ShopBundle/EventListener/OrderIntegrityChecker.php`:
|
||||
```diff
|
||||
public function __construct(
|
||||
private RouterInterface $router,
|
||||
- private OrderProcessorInterface $orderProcessor,
|
||||
private ObjectManager $manager
|
||||
+ private OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker
|
||||
)
|
||||
```
|
||||
|
||||
### Asset management changes
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ Feature: Order promotions integrity
|
|||
And I should not see the thank you page
|
||||
|
||||
@ui @api
|
||||
Scenario: Preventing customer from completing checkout with already expired promotion
|
||||
Scenario: Recalculating cart when promotion already expired
|
||||
Given this promotion gives "$10.00" discount to every order
|
||||
And this promotion expires tomorrow
|
||||
And I added product "PHP T-Shirt" to the cart
|
||||
|
|
@ -33,9 +33,7 @@ Feature: Order promotions integrity
|
|||
And I proceeded with "Free" shipping method and "Offline" payment method
|
||||
And this promotion has already expired
|
||||
When I try to confirm my order
|
||||
Then I should be informed that this promotion is no longer applied
|
||||
And I should not see the thank you page
|
||||
When I confirm my order
|
||||
And I confirm my order
|
||||
Then I should see the thank you page
|
||||
|
||||
@ui @api
|
||||
|
|
|
|||
|
|
@ -1158,7 +1158,7 @@ final class CheckoutContext implements Context
|
|||
{
|
||||
Assert::contains(
|
||||
$this->client->getLastResponse()->getContent(),
|
||||
'Order is no longer eligible for one of applied promotions. Your cart was recalculated.'
|
||||
sprintf('Order is no longer eligible for this %s promotion. Your cart was recalculated.', $promotion->getName())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,14 @@ declare(strict_types=1);
|
|||
namespace Sylius\Bundle\ApiBundle\Command\Cart;
|
||||
|
||||
/** @experimental */
|
||||
class InformAboutCartRecalculate
|
||||
class InformAboutCartRecalculation
|
||||
{
|
||||
public function __construct()
|
||||
public function __construct(private string $promotionName)
|
||||
{
|
||||
}
|
||||
|
||||
public function promotionName(): string
|
||||
{
|
||||
return $this->promotionName;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,14 +13,15 @@ declare(strict_types=1);
|
|||
|
||||
namespace Sylius\Bundle\ApiBundle\CommandHandler\Cart;
|
||||
|
||||
use Sylius\Bundle\ApiBundle\Command\Cart\InformAboutCartRecalculate;
|
||||
use Sylius\Bundle\ApiBundle\Command\Cart\InformAboutCartRecalculation;
|
||||
use Sylius\Bundle\ApiBundle\Exception\OrderNoLongerEligibleForPromotion;
|
||||
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
|
||||
|
||||
class InformAboutCartRecalculateHandler implements MessageHandlerInterface
|
||||
/** @experimental */
|
||||
final class InformAboutCartRecalculationHandler implements MessageHandlerInterface
|
||||
{
|
||||
public function __invoke(InformAboutCartRecalculate $command): void
|
||||
public function __invoke(InformAboutCartRecalculation $command): void
|
||||
{
|
||||
throw new OrderNoLongerEligibleForPromotion();
|
||||
throw new OrderNoLongerEligibleForPromotion($command->promotionName());
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ declare(strict_types=1);
|
|||
namespace Sylius\Bundle\ApiBundle\CommandHandler\Checkout;
|
||||
|
||||
use SM\Factory\FactoryInterface;
|
||||
use Sylius\Bundle\ApiBundle\Command\Cart\InformAboutCartRecalculate;
|
||||
use Sylius\Bundle\ApiBundle\Command\Cart\InformAboutCartRecalculation;
|
||||
use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder;
|
||||
use Sylius\Bundle\ApiBundle\Event\OrderCompleted;
|
||||
use Sylius\Bundle\CoreBundle\Order\Checker\OrderPromotionsIntegrityCheckerInterface;
|
||||
|
|
@ -52,8 +52,10 @@ final class CompleteOrderHandler implements MessageHandlerInterface
|
|||
$cart->setNotes($completeOrder->notes);
|
||||
}
|
||||
|
||||
if (!$this->orderPromotionsIntegrityChecker->check($cart)) {
|
||||
$this->commandBus->dispatch(new InformAboutCartRecalculate(), [new DispatchAfterCurrentBusStamp()]);
|
||||
if ($promotion = $this->orderPromotionsIntegrityChecker->check($cart)){
|
||||
$this->commandBus->dispatch(
|
||||
new InformAboutCartRecalculation($promotion->getName()), [new DispatchAfterCurrentBusStamp()]
|
||||
);
|
||||
|
||||
return $cart;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* 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\ApiBundle\DataPersister;
|
||||
|
||||
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
||||
use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException;
|
||||
use Symfony\Component\Messenger\Exception\HandlerFailedException;
|
||||
|
||||
/** @experimental */
|
||||
final class MessengerDataPersister implements ContextAwareDataPersisterInterface
|
||||
{
|
||||
public function __construct(private ContextAwareDataPersisterInterface $decoratedDataPersister)
|
||||
{
|
||||
}
|
||||
|
||||
public function supports($data, array $context = []): bool
|
||||
{
|
||||
return $this->decoratedDataPersister->supports($data, $context);
|
||||
}
|
||||
|
||||
public function persist($data, array $context = [])
|
||||
{
|
||||
try {
|
||||
return $this->decoratedDataPersister->persist($data, $context);
|
||||
} catch (DelayedMessageHandlingException|HandlerFailedException $e) {
|
||||
while ($e instanceof DelayedMessageHandlingException) {
|
||||
/** @var \Throwable $e */
|
||||
$e = $e->getPrevious();
|
||||
}
|
||||
while ($e instanceof HandlerFailedException) {
|
||||
/** @var \Throwable $e */
|
||||
$e = $e->getPrevious();
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function remove($data, array $context = [])
|
||||
{
|
||||
$this->decoratedDataPersister->remove($data, $context);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,8 +16,8 @@ namespace Sylius\Bundle\ApiBundle\Exception;
|
|||
/** @experimental */
|
||||
final class OrderNoLongerEligibleForPromotion extends \RuntimeException
|
||||
{
|
||||
public function __construct()
|
||||
public function __construct(string $promotionName)
|
||||
{
|
||||
parent::__construct('Order is no longer eligible for one of applied promotions. Your cart was recalculated.');
|
||||
parent::__construct(\sprintf('Order is no longer eligible for this %s promotion. Your cart was recalculated.', $promotionName));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
<tag name="messenger.message_handler" bus="sylius_default.bus" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\CommandHandler\Cart\InformAboutCartRecalculateHandler">
|
||||
<service id="Sylius\Bundle\ApiBundle\CommandHandler\Cart\InformAboutCartRecalculationHandler">
|
||||
<tag name="messenger.message_handler" bus="sylius.command_bus" />
|
||||
<tag name="messenger.message_handler" bus="sylius_default.bus" />
|
||||
</service>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@
|
|||
<tag name="api_platform.data_persister" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\DataPersister\MessengerDataPersister">
|
||||
<argument type="service" id="api_platform.messenger.data_persister" />
|
||||
<tag name="api_platform.data_persister" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\DataPersister\ShippingMethodDataPersister">
|
||||
<argument type="service" id="api_platform.doctrine.orm.data_persister" />
|
||||
<tag name="api_platform.data_persister" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace spec\Sylius\Bundle\ApiBundle\CommandHandler\Cart;
|
||||
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Bundle\ApiBundle\Command\Cart\InformAboutCartRecalculation;
|
||||
use Sylius\Bundle\ApiBundle\Exception\OrderNoLongerEligibleForPromotion;
|
||||
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
|
||||
|
||||
final class InformAboutCartRecalculationHandlerSpec extends ObjectBehavior
|
||||
{
|
||||
function it_is_a_message_handler(): void
|
||||
{
|
||||
$this->shouldImplement(MessageHandlerInterface::class);
|
||||
}
|
||||
|
||||
function it_throws_order_no_longer_eligible_for_promotion_exception(): void
|
||||
{
|
||||
$this
|
||||
->shouldThrow(OrderNoLongerEligibleForPromotion::class)
|
||||
->during('__invoke', [new InformAboutCartRecalculation('Holiday Sale')])
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,11 +16,13 @@ namespace spec\Sylius\Bundle\ApiBundle\CommandHandler\Checkout;
|
|||
use PhpSpec\ObjectBehavior;
|
||||
use SM\Factory\FactoryInterface;
|
||||
use SM\StateMachine\StateMachineInterface;
|
||||
use Sylius\Bundle\ApiBundle\Checker\OrderIntegrityCheckerInterface;
|
||||
use Sylius\Bundle\ApiBundle\Command\Cart\InformAboutCartRecalculation;
|
||||
use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder;
|
||||
use Sylius\Bundle\ApiBundle\Event\OrderCompleted;
|
||||
use Sylius\Bundle\CoreBundle\Order\Checker\OrderPromotionsIntegrityCheckerInterface;
|
||||
use Sylius\Component\Core\Model\CustomerInterface;
|
||||
use Sylius\Component\Core\Model\OrderInterface;
|
||||
use Sylius\Component\Core\Model\PromotionInterface;
|
||||
use Sylius\Component\Core\OrderCheckoutTransitions;
|
||||
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
|
|
@ -34,9 +36,9 @@ final class CompleteOrderHandlerSpec extends ObjectBehavior
|
|||
FactoryInterface $stateMachineFactory,
|
||||
MessageBusInterface $commandBus,
|
||||
MessageBusInterface $eventBus,
|
||||
OrderIntegrityCheckerInterface $orderIntegrityChecker
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker
|
||||
): void {
|
||||
$this->beConstructedWith($orderRepository, $stateMachineFactory, $commandBus, $eventBus, $orderIntegrityChecker);
|
||||
$this->beConstructedWith($orderRepository, $stateMachineFactory, $commandBus, $eventBus, $orderPromotionsIntegrityChecker);
|
||||
}
|
||||
|
||||
function it_handles_order_completion_without_notes(
|
||||
|
|
@ -46,7 +48,7 @@ final class CompleteOrderHandlerSpec extends ObjectBehavior
|
|||
FactoryInterface $stateMachineFactory,
|
||||
MessageBusInterface $eventBus,
|
||||
CustomerInterface $customer,
|
||||
OrderIntegrityCheckerInterface $orderIntegrityChecker
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker
|
||||
): void {
|
||||
$completeOrder = new CompleteOrder();
|
||||
$completeOrder->setOrderTokenValue('ORDERTOKEN');
|
||||
|
|
@ -57,7 +59,7 @@ final class CompleteOrderHandlerSpec extends ObjectBehavior
|
|||
|
||||
$order->setNotes(null)->shouldNotBeCalled();
|
||||
|
||||
$orderIntegrityChecker->check($order)->shouldBeCalled();
|
||||
$orderPromotionsIntegrityChecker->check($order)->willReturn(null);
|
||||
|
||||
$stateMachineFactory->get($order, OrderCheckoutTransitions::GRAPH)->willReturn($stateMachine);
|
||||
$stateMachine->can('complete')->willReturn(true);
|
||||
|
|
@ -83,7 +85,7 @@ final class CompleteOrderHandlerSpec extends ObjectBehavior
|
|||
FactoryInterface $stateMachineFactory,
|
||||
MessageBusInterface $eventBus,
|
||||
CustomerInterface $customer,
|
||||
OrderIntegrityCheckerInterface $orderIntegrityChecker
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker
|
||||
): void {
|
||||
$completeOrder = new CompleteOrder('ThankYou');
|
||||
$completeOrder->setOrderTokenValue('ORDERTOKEN');
|
||||
|
|
@ -94,7 +96,7 @@ final class CompleteOrderHandlerSpec extends ObjectBehavior
|
|||
|
||||
$order->setNotes('ThankYou')->shouldBeCalled();
|
||||
|
||||
$orderIntegrityChecker->check($order)->shouldBeCalled();
|
||||
$orderPromotionsIntegrityChecker->check($order)->willReturn(null);
|
||||
|
||||
$stateMachineFactory->get($order, OrderCheckoutTransitions::GRAPH)->willReturn($stateMachine);
|
||||
$stateMachine->can('complete')->willReturn(true);
|
||||
|
|
@ -113,6 +115,37 @@ final class CompleteOrderHandlerSpec extends ObjectBehavior
|
|||
$this($completeOrder)->shouldReturn($order);
|
||||
}
|
||||
|
||||
function it_delays_an_information_about_cart_recalculate(
|
||||
OrderRepositoryInterface $orderRepository,
|
||||
OrderInterface $order,
|
||||
MessageBusInterface $commandBus,
|
||||
CustomerInterface $customer,
|
||||
PromotionInterface $promotion,
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker
|
||||
): void {
|
||||
$completeOrder = new CompleteOrder('ThankYou');
|
||||
$completeOrder->setOrderTokenValue('ORDERTOKEN');
|
||||
|
||||
$order->getCustomer()->willReturn($customer);
|
||||
|
||||
$orderRepository->findOneBy(['tokenValue' => 'ORDERTOKEN'])->willReturn($order);
|
||||
|
||||
$order->setNotes('ThankYou')->shouldBeCalled();
|
||||
|
||||
$orderPromotionsIntegrityChecker->check($order)->willReturn($promotion);
|
||||
$promotion->getName()->willReturn('Christmas');
|
||||
|
||||
$informAboutCartRecalculate = new InformAboutCartRecalculation('Christmas');
|
||||
|
||||
$commandBus
|
||||
->dispatch($informAboutCartRecalculate, [new DispatchAfterCurrentBusStamp()])
|
||||
->willReturn(new Envelope($informAboutCartRecalculate))
|
||||
->shouldBeCalled()
|
||||
;
|
||||
|
||||
$this($completeOrder)->shouldReturn($order);
|
||||
}
|
||||
|
||||
function it_throws_an_exception_if_order_does_not_exist(
|
||||
OrderRepositoryInterface $orderRepository
|
||||
): void {
|
||||
|
|
@ -133,7 +166,7 @@ final class CompleteOrderHandlerSpec extends ObjectBehavior
|
|||
OrderInterface $order,
|
||||
FactoryInterface $stateMachineFactory,
|
||||
CustomerInterface $customer,
|
||||
OrderIntegrityCheckerInterface $orderIntegrityChecker
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker
|
||||
): void {
|
||||
$completeOrder = new CompleteOrder();
|
||||
$completeOrder->setOrderTokenValue('ORDERTOKEN');
|
||||
|
|
@ -142,7 +175,7 @@ final class CompleteOrderHandlerSpec extends ObjectBehavior
|
|||
|
||||
$order->getCustomer()->willReturn($customer);
|
||||
|
||||
$orderIntegrityChecker->check($order)->shouldBeCalled();
|
||||
$orderPromotionsIntegrityChecker->check($order)->willReturn(null);
|
||||
|
||||
$stateMachineFactory->get($order, OrderCheckoutTransitions::GRAPH)->willReturn($stateMachine);
|
||||
$stateMachine->can(OrderCheckoutTransitions::TRANSITION_COMPLETE)->willReturn(false);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace spec\Sylius\Bundle\ApiBundle\DataPersister;
|
||||
|
||||
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Prophecy\Argument;
|
||||
use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException;
|
||||
use Symfony\Component\Messenger\Exception\HandlerFailedException;
|
||||
|
||||
final class MessengerDataPersisterSpec extends ObjectBehavior
|
||||
{
|
||||
function let(ContextAwareDataPersisterInterface $decoratedDataPersister)
|
||||
{
|
||||
$this->beConstructedWith($decoratedDataPersister);
|
||||
}
|
||||
|
||||
function it_calls_supports_method_from_decorated_data_presister(
|
||||
ContextAwareDataPersisterInterface $decoratedDataPersister
|
||||
): void {
|
||||
$decoratedDataPersister->supports(Argument::any(), [])->shouldBeCalled();
|
||||
|
||||
$this->supports(Argument::any(), []);
|
||||
}
|
||||
|
||||
function it_unwraps_delayed_message_handling_exception(ContextAwareDataPersisterInterface $decoratedDataPersister): void
|
||||
{
|
||||
$completeOrder = new CompleteOrder('ThankYou');
|
||||
$completeOrder->setOrderTokenValue('ORDERTOKEN');
|
||||
$envelope = new Envelope($completeOrder);
|
||||
|
||||
$decoratedDataPersister->persist($envelope, [])->willThrow(new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')]));
|
||||
|
||||
$this->shouldThrow(new \RuntimeException('Delayed message exception'))->during('persist', [$envelope, []]);
|
||||
}
|
||||
|
||||
function it_unwraps_handler_failed_exception(ContextAwareDataPersisterInterface $decoratedDataPersister): void
|
||||
{
|
||||
$completeOrder = new CompleteOrder('ThankYou');
|
||||
$completeOrder->setOrderTokenValue('ORDERTOKEN');
|
||||
$envelope = new Envelope($completeOrder);
|
||||
|
||||
$decoratedDataPersister->persist($envelope, [])->willThrow(
|
||||
new HandlerFailedException(
|
||||
$envelope,
|
||||
[new \RuntimeException('Delayed message exception')]
|
||||
)
|
||||
);
|
||||
|
||||
$this->shouldThrow(new \RuntimeException('Delayed message exception'))->during('persist', [$envelope, []]);
|
||||
}
|
||||
|
||||
function it_calls_remove_method_from_decorated_data_presister(
|
||||
ContextAwareDataPersisterInterface $decoratedDataPersister
|
||||
): void {
|
||||
$decoratedDataPersister->remove(Argument::any(), [])->shouldBeCalled();
|
||||
|
||||
$this->remove(Argument::any(), []);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,17 +15,16 @@ namespace Sylius\Bundle\CoreBundle\Order\Checker;
|
|||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Sylius\Component\Core\Model\OrderInterface;
|
||||
use Sylius\Component\Core\Model\PromotionInterface;
|
||||
use Sylius\Component\Order\Processor\OrderProcessorInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class OrderPromotionsIntegrityChecker implements OrderPromotionsIntegrityCheckerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private OrderProcessorInterface $orderProcessor,
|
||||
) {
|
||||
public function __construct(private OrderProcessorInterface $orderProcessor)
|
||||
{
|
||||
}
|
||||
|
||||
public function check(OrderInterface $order): bool
|
||||
public function check(OrderInterface $order): ?PromotionInterface
|
||||
{
|
||||
$previousPromotions = new ArrayCollection($order->getPromotions()->toArray());
|
||||
|
||||
|
|
@ -33,10 +32,10 @@ final class OrderPromotionsIntegrityChecker implements OrderPromotionsIntegrityC
|
|||
|
||||
foreach ($previousPromotions as $previousPromotion) {
|
||||
if (!$order->getPromotions()->contains($previousPromotion)) {
|
||||
return false;
|
||||
return $previousPromotion;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ declare(strict_types=1);
|
|||
namespace Sylius\Bundle\CoreBundle\Order\Checker;
|
||||
|
||||
use Sylius\Component\Core\Model\OrderInterface;
|
||||
use Sylius\Component\Core\Model\PromotionInterface;
|
||||
|
||||
interface OrderPromotionsIntegrityCheckerInterface
|
||||
{
|
||||
public function check(OrderInterface $order): bool;
|
||||
|
||||
public function check(OrderInterface $order): ?PromotionInterface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ final class OrderPromotionsIntegrityCheckerSpec extends ObjectBehavior
|
|||
$this->beConstructedWith($orderProcessor);
|
||||
}
|
||||
|
||||
function it_returns_true_when_promotion_is_still_valid(
|
||||
function it_returns_null_if_promotion_is_valid(
|
||||
OrderInterface $order,
|
||||
PromotionInterface $promotion,
|
||||
OrderProcessorInterface $orderProcessor
|
||||
|
|
@ -37,10 +37,10 @@ final class OrderPromotionsIntegrityCheckerSpec extends ObjectBehavior
|
|||
|
||||
$orderProcessor->process($order)->shouldBeCalled();
|
||||
|
||||
$this->check($order)->shouldReturn(true);
|
||||
$this->check($order)->shouldReturn(null);
|
||||
}
|
||||
|
||||
function it_returns_false_if_promotion_is_not_valid(
|
||||
function it_returns_promotion_if_promotion_is_not_valid(
|
||||
OrderInterface $order,
|
||||
PromotionInterface $oldPromotion,
|
||||
PromotionInterface $newPromotion,
|
||||
|
|
@ -53,6 +53,6 @@ final class OrderPromotionsIntegrityCheckerSpec extends ObjectBehavior
|
|||
|
||||
$orderProcessor->process($order)->shouldBeCalled();
|
||||
|
||||
$this->check($order)->shouldReturn(false);
|
||||
$this->check($order)->shouldReturn($oldPromotion);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace Sylius\Bundle\ShopBundle\EventListener;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Sylius\Bundle\CoreBundle\Order\Checker\OrderPromotionsIntegrityCheckerInterface;
|
||||
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
|
||||
use Sylius\Component\Core\Model\OrderInterface;
|
||||
use Sylius\Component\Core\Model\PromotionInterface;
|
||||
use Sylius\Component\Order\Processor\OrderProcessorInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
|
@ -27,8 +25,8 @@ final class OrderIntegrityChecker
|
|||
{
|
||||
public function __construct(
|
||||
private RouterInterface $router,
|
||||
private OrderProcessorInterface $orderProcessor,
|
||||
private ObjectManager $manager
|
||||
private ObjectManager $manager,
|
||||
private OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -39,28 +37,21 @@ final class OrderIntegrityChecker
|
|||
/** @var OrderInterface $order */
|
||||
Assert::isInstanceOf($order, OrderInterface::class);
|
||||
|
||||
/** @var ArrayCollection<array-key, PromotionInterface> $previousPromotions */
|
||||
$previousPromotions = new ArrayCollection($order->getPromotions()->toArray());
|
||||
$oldTotal = $order->getTotal();
|
||||
|
||||
$this->orderProcessor->process($order);
|
||||
if ($promotion = $this->orderPromotionsIntegrityChecker->check($order)) {
|
||||
$event->stop(
|
||||
'sylius.order.promotion_integrity',
|
||||
ResourceControllerEvent::TYPE_ERROR,
|
||||
['%promotionName%' => $promotion->getName()]
|
||||
);
|
||||
|
||||
/** @var PromotionInterface $previousPromotion */
|
||||
foreach ($previousPromotions as $previousPromotion) {
|
||||
if (!$order->getPromotions()->contains($previousPromotion)) {
|
||||
$event->stop(
|
||||
'sylius.order.promotion_integrity',
|
||||
ResourceControllerEvent::TYPE_ERROR,
|
||||
['%promotionName%' => $previousPromotion->getName()]
|
||||
);
|
||||
$event->setResponse(new RedirectResponse($this->router->generate('sylius_shop_checkout_complete')));
|
||||
|
||||
$event->setResponse(new RedirectResponse($this->router->generate('sylius_shop_checkout_complete')));
|
||||
$this->manager->persist($order);
|
||||
$this->manager->flush();
|
||||
|
||||
$this->manager->persist($order);
|
||||
$this->manager->flush();
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($order->getTotal() !== $oldTotal) {
|
||||
|
|
@ -69,8 +60,6 @@ final class OrderIntegrityChecker
|
|||
|
||||
$this->manager->persist($order);
|
||||
$this->manager->flush();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@
|
|||
|
||||
<service id="sylius.listener.order_integrity_checker" class="Sylius\Bundle\ShopBundle\EventListener\OrderIntegrityChecker">
|
||||
<argument type="service" id="router" />
|
||||
<argument type="service" id="sylius.order_processing.order_processor" />
|
||||
<argument type="service" id="sylius.manager.order" />
|
||||
<argument type="service" id="Sylius\Bundle\CoreBundle\Order\Checker\OrderPromotionsIntegrityCheckerInterface" />
|
||||
<tag name="kernel.event_listener" event="sylius.order.pre_complete" method="check" />
|
||||
</service>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ use Doctrine\Common\Collections\ArrayCollection;
|
|||
use Doctrine\Persistence\ObjectManager;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Prophecy\Argument;
|
||||
use Sylius\Bundle\CoreBundle\Order\Checker\OrderPromotionsIntegrityCheckerInterface;
|
||||
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
|
||||
use Sylius\Component\Core\Model\OrderInterface;
|
||||
use Sylius\Component\Core\Model\PromotionInterface;
|
||||
use Sylius\Component\Order\Processor\OrderProcessorInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
|
|
@ -28,14 +28,14 @@ final class OrderIntegrityCheckerSpec extends ObjectBehavior
|
|||
{
|
||||
function let(
|
||||
RouterInterface $router,
|
||||
OrderProcessorInterface $orderProcessor,
|
||||
ObjectManager $orderManager
|
||||
ObjectManager $orderManager,
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker
|
||||
): void {
|
||||
$this->beConstructedWith($router, $orderProcessor, $orderManager);
|
||||
$this->beConstructedWith($router, $orderManager, $orderPromotionsIntegrityChecker);
|
||||
}
|
||||
|
||||
function it_does_nothing_if_given_order_has_valid_promotion_applied(
|
||||
OrderProcessorInterface $orderProcessor,
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker,
|
||||
OrderInterface $order,
|
||||
PromotionInterface $promotion,
|
||||
ResourceControllerEvent $event
|
||||
|
|
@ -45,7 +45,7 @@ final class OrderIntegrityCheckerSpec extends ObjectBehavior
|
|||
$order->getPromotions()->willReturn(new ArrayCollection([$promotion->getWrappedObject()]));
|
||||
$order->getTotal()->willReturn(1000);
|
||||
|
||||
$orderProcessor->process($order)->shouldBeCalled();
|
||||
$orderPromotionsIntegrityChecker->check($order)->willReturn(null);
|
||||
|
||||
$event->stop(Argument::any())->shouldNotBeCalled();
|
||||
$event->setResponse(Argument::any())->shouldNotBeCalled();
|
||||
|
|
@ -54,7 +54,7 @@ final class OrderIntegrityCheckerSpec extends ObjectBehavior
|
|||
}
|
||||
|
||||
function it_stops_future_action_if_given_order_has_different_promotion_applied(
|
||||
OrderProcessorInterface $orderProcessor,
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker,
|
||||
RouterInterface $router,
|
||||
OrderInterface $order,
|
||||
PromotionInterface $oldPromotion,
|
||||
|
|
@ -74,7 +74,7 @@ final class OrderIntegrityCheckerSpec extends ObjectBehavior
|
|||
|
||||
$router->generate('sylius_shop_checkout_complete')->willReturn('checkout.com');
|
||||
|
||||
$orderProcessor->process($order)->shouldBeCalled();
|
||||
$orderPromotionsIntegrityChecker->check($order)->willReturn($oldPromotion);
|
||||
|
||||
$event->stop(
|
||||
'sylius.order.promotion_integrity',
|
||||
|
|
@ -90,7 +90,7 @@ final class OrderIntegrityCheckerSpec extends ObjectBehavior
|
|||
}
|
||||
|
||||
function it_stops_future_action_if_given_order_has_different_total_value(
|
||||
OrderProcessorInterface $orderProcessor,
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker,
|
||||
RouterInterface $router,
|
||||
OrderInterface $order,
|
||||
PromotionInterface $promotion,
|
||||
|
|
@ -104,7 +104,7 @@ final class OrderIntegrityCheckerSpec extends ObjectBehavior
|
|||
|
||||
$router->generate('sylius_shop_checkout_complete')->willReturn('checkout.com');
|
||||
|
||||
$orderProcessor->process($order)->shouldBeCalled();
|
||||
$orderPromotionsIntegrityChecker->check($order)->willReturn(null);
|
||||
|
||||
$event->stop('sylius.order.total_integrity', ResourceControllerEvent::TYPE_ERROR)->shouldBeCalled();
|
||||
$event->setResponse(new RedirectResponse('checkout.com'))->shouldBeCalled();
|
||||
|
|
@ -116,7 +116,7 @@ final class OrderIntegrityCheckerSpec extends ObjectBehavior
|
|||
}
|
||||
|
||||
function it_stops_future_action_if_given_order_has_no_promotion_applied(
|
||||
OrderProcessorInterface $orderProcessor,
|
||||
OrderPromotionsIntegrityCheckerInterface $orderPromotionsIntegrityChecker,
|
||||
RouterInterface $router,
|
||||
OrderInterface $order,
|
||||
PromotionInterface $promotion,
|
||||
|
|
@ -134,7 +134,7 @@ final class OrderIntegrityCheckerSpec extends ObjectBehavior
|
|||
$promotion->getName()->willReturn('Christmas');
|
||||
$promotion->getCode()->willReturn('CHRISTMAS_PROMO_CODE');
|
||||
|
||||
$orderProcessor->process($order)->shouldBeCalled();
|
||||
$orderPromotionsIntegrityChecker->check($order)->willReturn($promotion);
|
||||
|
||||
$router->generate('sylius_shop_checkout_complete')->willReturn('checkout.com');
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue