<?php
/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace Ibexa\Bundle\Checkout\EventSubscriber;
use Ibexa\Contracts\Cart\CartServiceInterface;
use Ibexa\Contracts\Cart\Value\CartInterface;
use Ibexa\Contracts\Checkout\Value\CheckoutInterface;
use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\GuardEvent;
use Symfony\Component\Workflow\TransitionBlocker;
final class CheckoutWorkflowSubscriber implements EventSubscriberInterface
{
private CartServiceInterface $cartService;
public function __construct(CartServiceInterface $cartService)
{
$this->cartService = $cartService;
}
public static function getSubscribedEvents(): array
{
return [
'workflow.guard' => ['guardTransition'],
];
}
public function guardTransition(GuardEvent $event): void
{
$transition = $event->getTransition();
$subject = $event->getSubject();
if (!$subject instanceof CheckoutInterface) {
return;
}
try {
$cart = $this->cartService->getCart($subject->getCartIdentifier());
} catch (NotFoundException $exception) {
return;
}
$hasVirtualProductsOnly = $this->hasVirtualProductsOnly($cart);
if (!$hasVirtualProductsOnly && $event->getMetadata('virtual_products_step', $transition)) {
$event->addTransitionBlocker(
new TransitionBlocker(
'Cannot make transition for virtual products when cart contains mixed or physical products.',
'0'
)
);
}
if ($hasVirtualProductsOnly && $event->getMetadata('physical_products_step', $transition)) {
$event->addTransitionBlocker(
new TransitionBlocker(
'Cannot make transition for physical products when cart contains only virtual products.',
'0'
)
);
}
}
private function hasVirtualProductsOnly(CartInterface $cart): bool
{
foreach ($cart->getEntries() as $entry) {
if (!$entry->getProduct()->getProductType()->isVirtual()) {
return false;
}
}
return true;
}
}