mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
Prevent from deleting last available channel
This commit is contained in:
parent
67761b9626
commit
6e0edf1db3
5 changed files with 191 additions and 0 deletions
|
|
@ -0,0 +1,47 @@
|
|||
<?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\ApiBundle\EventListener;
|
||||
|
||||
use Sylius\Bundle\ApiBundle\Exception\ChannelCannotBeRemoved;
|
||||
use Sylius\Component\Channel\Model\ChannelInterface;
|
||||
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\ViewEvent;
|
||||
|
||||
/** @experimental */
|
||||
final class ChannelDeletionEventListener
|
||||
{
|
||||
/**
|
||||
* @param ChannelRepositoryInterface<ChannelInterface> $channelRepository
|
||||
*/
|
||||
public function __construct(private ChannelRepositoryInterface $channelRepository)
|
||||
{
|
||||
}
|
||||
|
||||
public function protectFromRemovalTheOnlyChannelInStore(ViewEvent $event): void
|
||||
{
|
||||
$channel = $event->getControllerResult();
|
||||
$method = $event->getRequest()->getMethod();
|
||||
|
||||
if (!$channel instanceof ChannelInterface || $method !== Request::METHOD_DELETE) {
|
||||
return;
|
||||
}
|
||||
|
||||
$results = $this->channelRepository->findBy(['enabled' => true]);
|
||||
|
||||
if (!$results || (count($results) === 1 && current($results) === $channel)) {
|
||||
throw new ChannelCannotBeRemoved('The channel cannot be deleted. At least one enabled channel is required.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?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\ApiBundle\Exception;
|
||||
|
||||
/** @experimental */
|
||||
final class ChannelCannotBeRemoved extends \RuntimeException
|
||||
{
|
||||
public function __construct(
|
||||
string $message = 'Cannot remove, the channel is in use.',
|
||||
int $code = 0,
|
||||
\Throwable $previous = null,
|
||||
) {
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
||||
|
|
@ -50,6 +50,7 @@ api_platform:
|
|||
# Sylius exception to status code mapping
|
||||
SM\SMException: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\CannotRemoveCurrentlyLoggedInUser: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\ChannelCannotBeRemoved: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\InvalidProductAttributeValueTypeException: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\OrderItemNotFoundException: 422
|
||||
Sylius\Bundle\ApiBundle\Exception\OrderNoLongerEligibleForPromotion: 422
|
||||
|
|
|
|||
|
|
@ -177,6 +177,11 @@
|
|||
<tag name="kernel.event_listener" event="lexik_jwt_authentication.on_authentication_success" method="onAuthenticationSuccessResponse" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\EventListener\ChannelDeletionEventListener">
|
||||
<argument type="service" id="sylius.repository.channel"/>
|
||||
<tag name="kernel.event_listener" event="kernel.view" method="protectFromRemovalTheOnlyChannelInStore" priority="33"/>
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\Validator\ResourceInputDataPropertiesValidatorInterface" class="Sylius\Bundle\ApiBundle\Validator\ResourceApiInputDataPropertiesValidator">
|
||||
<argument type="service" id="validator" />
|
||||
</service>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
<?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 spec\Sylius\Bundle\ApiBundle\EventListener;
|
||||
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Bundle\ApiBundle\Exception\ChannelCannotBeRemoved;
|
||||
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
|
||||
use Sylius\Component\Core\Model\ChannelInterface;
|
||||
use Sylius\Component\Core\Model\OrderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\ViewEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
final class ChannelDeletionEventListenerSpec extends ObjectBehavior
|
||||
{
|
||||
function let(ChannelRepositoryInterface $channelRepository)
|
||||
{
|
||||
$this->beConstructedWith($channelRepository);
|
||||
}
|
||||
|
||||
function it_throws_exception_when_trying_to_delete_the_only_enabled_channel(
|
||||
Request $request,
|
||||
ChannelInterface $channel,
|
||||
ChannelRepositoryInterface $channelRepository,
|
||||
HttpKernelInterface $kernel,
|
||||
): void {
|
||||
$request->getMethod()->willReturn(Request::METHOD_DELETE);
|
||||
|
||||
$event = new ViewEvent(
|
||||
$kernel->getWrappedObject(),
|
||||
$request->getWrappedObject(),
|
||||
HttpKernelInterface::MAIN_REQUEST,
|
||||
$channel->getWrappedObject(),
|
||||
);
|
||||
|
||||
$channelRepository->findBy(['enabled' => true])->willReturn([$channel]);
|
||||
|
||||
$this->shouldThrow(ChannelCannotBeRemoved::class)->during('protectFromRemovalTheOnlyChannelInStore', [$event]);
|
||||
}
|
||||
|
||||
function it_does_nothing_when_there_are_more_than_one_enabled_channels(
|
||||
Request $request,
|
||||
ChannelInterface $channel,
|
||||
ChannelInterface $channel2,
|
||||
ChannelRepositoryInterface $channelRepository,
|
||||
HttpKernelInterface $kernel,
|
||||
): void {
|
||||
$request->getMethod()->willReturn(Request::METHOD_DELETE);
|
||||
|
||||
$event = new ViewEvent(
|
||||
$kernel->getWrappedObject(),
|
||||
$request->getWrappedObject(),
|
||||
HttpKernelInterface::MAIN_REQUEST,
|
||||
$channel->getWrappedObject(),
|
||||
);
|
||||
|
||||
$channelRepository->findBy(['enabled' => true])->willReturn([$channel, $channel2]);
|
||||
|
||||
$this->shouldNotThrow(ChannelCannotBeRemoved::class)->during('protectFromRemovalTheOnlyChannelInStore', [$event]);
|
||||
}
|
||||
|
||||
function it_does_nothing_when_request_method_is_not_delete(
|
||||
Request $request,
|
||||
ChannelInterface $channel,
|
||||
ChannelRepositoryInterface $channelRepository,
|
||||
HttpKernelInterface $kernel,
|
||||
): void {
|
||||
$request->getMethod()->willReturn(Request::METHOD_GET);
|
||||
|
||||
$event = new ViewEvent(
|
||||
$kernel->getWrappedObject(),
|
||||
$request->getWrappedObject(),
|
||||
HttpKernelInterface::MAIN_REQUEST,
|
||||
$channel->getWrappedObject(),
|
||||
);
|
||||
|
||||
$channelRepository->findBy(['enabled' => true])->willReturn([$channel]);
|
||||
|
||||
$this->shouldNotThrow(ChannelCannotBeRemoved::class)->during('protectFromRemovalTheOnlyChannelInStore', [$event]);
|
||||
}
|
||||
|
||||
function it_does_nothing_when_event_controller_result_is_not_channel(
|
||||
Request $request,
|
||||
ChannelRepositoryInterface $channelRepository,
|
||||
HttpKernelInterface $kernel,
|
||||
OrderInterface $order,
|
||||
): void {
|
||||
$request->getMethod()->willReturn(Request::METHOD_DELETE);
|
||||
|
||||
$event = new ViewEvent(
|
||||
$kernel->getWrappedObject(),
|
||||
$request->getWrappedObject(),
|
||||
HttpKernelInterface::MAIN_REQUEST,
|
||||
$order->getWrappedObject(),
|
||||
);
|
||||
|
||||
$channelRepository->findBy(['enabled' => true])->willReturn([]);
|
||||
|
||||
$this->shouldNotThrow(ChannelCannotBeRemoved::class)->during('protectFromRemovalTheOnlyChannelInStore', [$event]);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue