mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-05 20:57:12 +00:00
Refactor checking whether the channel can be deleted
This commit is contained in:
parent
14a94c043b
commit
8d4214d18c
17 changed files with 310 additions and 171 deletions
|
|
@ -24,5 +24,7 @@
|
||||||
|
|
||||||
<server name="IS_DOCTRINE_ORM_SUPPORTED" value="true" />
|
<server name="IS_DOCTRINE_ORM_SUPPORTED" value="true" />
|
||||||
<server name="ESCAPE_JSON" value="true" />
|
<server name="ESCAPE_JSON" value="true" />
|
||||||
|
|
||||||
|
<server name="KERNEL_CLASS" value="App\Kernel" />
|
||||||
</php>
|
</php>
|
||||||
</phpunit>
|
</phpunit>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?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\DataPersister;
|
||||||
|
|
||||||
|
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
||||||
|
use Sylius\Bundle\ApiBundle\Exception\ChannelCannotBeRemoved;
|
||||||
|
use Sylius\Component\Channel\Checker\ChannelDeletionCheckerInterface;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
|
||||||
|
final class ChannelDataPersister implements ContextAwareDataPersisterInterface
|
||||||
|
{
|
||||||
|
public function __construct (
|
||||||
|
private ContextAwareDataPersisterInterface $decoratedDataPersister,
|
||||||
|
private ChannelDeletionCheckerInterface $channelDeletionChecker,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $context
|
||||||
|
*/
|
||||||
|
public function supports($data, array $context = []): bool
|
||||||
|
{
|
||||||
|
return $data instanceof ChannelInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $context
|
||||||
|
*/
|
||||||
|
public function persist($data, array $context = [])
|
||||||
|
{
|
||||||
|
return $this->decoratedDataPersister->persist($data, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $context
|
||||||
|
*/
|
||||||
|
public function remove($data, array $context = []): void
|
||||||
|
{
|
||||||
|
if (!$this->channelDeletionChecker->isDeletable($data)) {
|
||||||
|
throw new ChannelCannotBeRemoved('The channel cannot be deleted. At least one enabled channel is required.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->decoratedDataPersister->remove($data, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
<?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.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -177,11 +177,6 @@
|
||||||
<tag name="kernel.event_listener" event="lexik_jwt_authentication.on_authentication_success" method="onAuthenticationSuccessResponse" />
|
<tag name="kernel.event_listener" event="lexik_jwt_authentication.on_authentication_success" method="onAuthenticationSuccessResponse" />
|
||||||
</service>
|
</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">
|
<service id="Sylius\Bundle\ApiBundle\Validator\ResourceInputDataPropertiesValidatorInterface" class="Sylius\Bundle\ApiBundle\Validator\ResourceApiInputDataPropertiesValidator">
|
||||||
<argument type="service" id="validator" />
|
<argument type="service" id="validator" />
|
||||||
</service>
|
</service>
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,12 @@
|
||||||
<tag name="api_platform.data_persister" />
|
<tag name="api_platform.data_persister" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="Sylius\Bundle\ApiBundle\DataPersister\ChannelDataPersister">
|
||||||
|
<argument type="service" id="api_platform.doctrine.orm.data_persister" />
|
||||||
|
<argument type="service" id="sylius.checker.channel_deletion" />
|
||||||
|
<tag name="api_platform.data_persister" />
|
||||||
|
</service>
|
||||||
|
|
||||||
<service id="Sylius\Bundle\ApiBundle\DataPersister\MessengerDataPersister">
|
<service id="Sylius\Bundle\ApiBundle\DataPersister\MessengerDataPersister">
|
||||||
<argument type="service" id="api_platform.messenger.data_persister" />
|
<argument type="service" id="api_platform.messenger.data_persister" />
|
||||||
<tag name="api_platform.data_persister" />
|
<tag name="api_platform.data_persister" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
<?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\DataPersister;
|
||||||
|
|
||||||
|
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
|
||||||
|
use PhpSpec\ObjectBehavior;
|
||||||
|
use Sylius\Bundle\ApiBundle\Exception\ChannelCannotBeRemoved;
|
||||||
|
use Sylius\Component\Channel\Checker\ChannelDeletionCheckerInterface;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
|
||||||
|
final class ChannelDataPersisterSpec extends ObjectBehavior
|
||||||
|
{
|
||||||
|
function let(
|
||||||
|
ContextAwareDataPersisterInterface $decoratedDataPersister,
|
||||||
|
ChannelDeletionCheckerInterface $channelDeletionChecker,
|
||||||
|
): void {
|
||||||
|
$this->beConstructedWith($decoratedDataPersister, $channelDeletionChecker);
|
||||||
|
}
|
||||||
|
|
||||||
|
function it_supports_only_channel_entity(ChannelInterface $channel, \stdClass $object): void
|
||||||
|
{
|
||||||
|
$this->supports($channel)->shouldReturn(true);
|
||||||
|
$this->supports($object)->shouldReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function it_persists_channel(
|
||||||
|
ContextAwareDataPersisterInterface $decoratedDataPersister,
|
||||||
|
ChannelInterface $channel
|
||||||
|
): void {
|
||||||
|
$decoratedDataPersister->persist($channel, [])->willReturn($channel);
|
||||||
|
|
||||||
|
$this->persist($channel, [])->shouldReturn($channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
function it_throws_an_exception_if_channel_is_not_deletable(
|
||||||
|
ChannelDeletionCheckerInterface $channelDeletionChecker,
|
||||||
|
ChannelInterface $channel
|
||||||
|
): void {
|
||||||
|
$channelDeletionChecker->isDeletable($channel)->willReturn(false);
|
||||||
|
|
||||||
|
$this
|
||||||
|
->shouldThrow(ChannelCannotBeRemoved::class)
|
||||||
|
->during('remove', [$channel])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
function it_removes_channel(
|
||||||
|
ContextAwareDataPersisterInterface $decoratedDataPersister,
|
||||||
|
ChannelDeletionCheckerInterface $channelDeletionChecker,
|
||||||
|
ChannelInterface $channel
|
||||||
|
): void {
|
||||||
|
$channelDeletionChecker->isDeletable($channel)->willReturn(true);
|
||||||
|
$decoratedDataPersister->remove($channel, [])->willReturn(null);
|
||||||
|
|
||||||
|
$this->remove($channel, [])->shouldReturn(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
<?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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -56,6 +56,17 @@ class ChannelRepository extends EntityRepository implements ChannelRepositoryInt
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ChannelInterface[]
|
||||||
|
*/
|
||||||
|
public function findEnabled(): iterable
|
||||||
|
{
|
||||||
|
/** @var ChannelInterface[] $enabledChannels */
|
||||||
|
$enabledChannels = $this->findBy(['enabled' => true]);
|
||||||
|
|
||||||
|
return $enabledChannels;
|
||||||
|
}
|
||||||
|
|
||||||
public function countAll(): int
|
public function countAll(): int
|
||||||
{
|
{
|
||||||
return $this->count([]);
|
return $this->count([]);
|
||||||
|
|
|
||||||
|
|
@ -69,5 +69,10 @@
|
||||||
<argument>false</argument>
|
<argument>false</argument>
|
||||||
<tag name="data_collector" template="@SyliusChannel/Collector/channel.html.twig" id="sylius.channel_collector" />
|
<tag name="data_collector" template="@SyliusChannel/Collector/channel.html.twig" id="sylius.channel_collector" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="sylius.checker.channel_deletion" class="Sylius\Component\Channel\Checker\ChannelDeletionChecker">
|
||||||
|
<argument type="service" id="sylius.repository.channel" />
|
||||||
|
</service>
|
||||||
|
<service id="Sylius\Component\Channel\Checker\ChannelDeletionCheckerInterface" alias="sylius.checker.channel_deletion" />
|
||||||
</services>
|
</services>
|
||||||
</container>
|
</container>
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,13 @@ declare(strict_types=1);
|
||||||
namespace Sylius\Bundle\CoreBundle\EventListener;
|
namespace Sylius\Bundle\CoreBundle\EventListener;
|
||||||
|
|
||||||
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
|
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
|
||||||
|
use Sylius\Component\Channel\Checker\ChannelDeletionCheckerInterface;
|
||||||
use Sylius\Component\Channel\Model\ChannelInterface;
|
use Sylius\Component\Channel\Model\ChannelInterface;
|
||||||
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
|
|
||||||
use Sylius\Component\Resource\Exception\UnexpectedTypeException;
|
use Sylius\Component\Resource\Exception\UnexpectedTypeException;
|
||||||
|
|
||||||
final class ChannelDeletionListener
|
final class ChannelDeletionListener
|
||||||
{
|
{
|
||||||
public function __construct(private ChannelRepositoryInterface $channelRepository)
|
public function __construct(private ChannelDeletionCheckerInterface $channelDeletionChecker)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,9 +38,7 @@ final class ChannelDeletionListener
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$results = $this->channelRepository->findBy(['enabled' => true]);
|
if (!$this->channelDeletionChecker->isDeletable($channel)) {
|
||||||
|
|
||||||
if (!$results || (count($results) === 1 && current($results) === $channel)) {
|
|
||||||
$event->stop('sylius.channel.delete_error');
|
$event->stop('sylius.channel.delete_error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<defaults public="true" />
|
<defaults public="true" />
|
||||||
|
|
||||||
<service id="sylius.listener.channel" class="Sylius\Bundle\CoreBundle\EventListener\ChannelDeletionListener">
|
<service id="sylius.listener.channel" class="Sylius\Bundle\CoreBundle\EventListener\ChannelDeletionListener">
|
||||||
<argument type="service" id="sylius.repository.channel" />
|
<argument type="service" id="sylius.checker.channel_deletion" />
|
||||||
<tag name="kernel.event_listener" event="sylius.channel.pre_delete" method="onChannelPreDelete" />
|
<tag name="kernel.event_listener" event="sylius.channel.pre_delete" method="onChannelPreDelete" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?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\Component\Channel\Checker;
|
||||||
|
|
||||||
|
use Sylius\Component\Channel\Model\ChannelInterface;
|
||||||
|
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
|
||||||
|
|
||||||
|
final class ChannelDeletionChecker implements ChannelDeletionCheckerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param ChannelRepositoryInterface<ChannelInterface> $channelRepository
|
||||||
|
*/
|
||||||
|
public function __construct(private ChannelRepositoryInterface $channelRepository)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isDeletable(ChannelInterface $channel): bool
|
||||||
|
{
|
||||||
|
if (!$channel->isEnabled()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$enabledChannels = $this->channelRepository->findEnabled();
|
||||||
|
|
||||||
|
return count($enabledChannels) > 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?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\Component\Channel\Checker;
|
||||||
|
|
||||||
|
use Sylius\Component\Channel\Model\ChannelInterface;
|
||||||
|
|
||||||
|
interface ChannelDeletionCheckerInterface
|
||||||
|
{
|
||||||
|
public function isDeletable(ChannelInterface $channel): bool;
|
||||||
|
}
|
||||||
|
|
@ -35,5 +35,10 @@ interface ChannelRepositoryInterface extends RepositoryInterface
|
||||||
|
|
||||||
public function findAllWithBasicData(): iterable;
|
public function findAllWithBasicData(): iterable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ChannelInterface[]
|
||||||
|
*/
|
||||||
|
public function findEnabled(): iterable;
|
||||||
|
|
||||||
public function countAll(): int;
|
public function countAll(): int;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?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\Component\Channel\Checker;
|
||||||
|
|
||||||
|
use PhpSpec\ObjectBehavior;
|
||||||
|
use Sylius\Component\Channel\Model\ChannelInterface;
|
||||||
|
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
|
||||||
|
|
||||||
|
final class ChannelDeletionCheckerSpec extends ObjectBehavior
|
||||||
|
{
|
||||||
|
function let(ChannelRepositoryInterface $channelRepository): void
|
||||||
|
{
|
||||||
|
$this->beConstructedWith($channelRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
function it_returns_a_channel_can_be_deleted_when_is_disabled(ChannelInterface $channel): void
|
||||||
|
{
|
||||||
|
$channel->isEnabled()->willReturn(false);
|
||||||
|
|
||||||
|
$this->isDeletable($channel)->shouldReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function it_returns_a_channel_can_be_deleted_when_at_least_two_channels_are_enabled(
|
||||||
|
ChannelRepositoryInterface $channelRepository,
|
||||||
|
ChannelInterface $channel,
|
||||||
|
ChannelInterface $anotherChannel
|
||||||
|
): void {
|
||||||
|
$channel->isEnabled()->willReturn(true);
|
||||||
|
$channelRepository->findEnabled()->willReturn([$channel, $anotherChannel]);
|
||||||
|
|
||||||
|
$this->isDeletable($channel)->shouldReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function it_returns_a_channel_cannot_be_deleted_when_only_one_channel_is_enabled(
|
||||||
|
ChannelRepositoryInterface $channelRepository,
|
||||||
|
ChannelInterface $channel
|
||||||
|
): void {
|
||||||
|
$channel->isEnabled()->willReturn(true);
|
||||||
|
$channelRepository->findEnabled()->willReturn([$channel]);
|
||||||
|
|
||||||
|
$this->isDeletable($channel)->shouldReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function it_returns_a_channel_cannot_be_deleted_when_no_channel_is_enabled(
|
||||||
|
ChannelRepositoryInterface $channelRepository,
|
||||||
|
ChannelInterface $channel
|
||||||
|
): void {
|
||||||
|
$channel->isEnabled()->willReturn(true);
|
||||||
|
$channelRepository->findEnabled()->willReturn([]);
|
||||||
|
|
||||||
|
$this->isDeletable($channel)->shouldReturn(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,7 +14,6 @@ declare(strict_types=1);
|
||||||
namespace Sylius\Tests\Api\Admin;
|
namespace Sylius\Tests\Api\Admin;
|
||||||
|
|
||||||
use Sylius\Component\Core\Model\ChannelInterface;
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
use Sylius\Component\Core\Model\ShopBillingData;
|
|
||||||
use Sylius\Tests\Api\JsonApiTestCase;
|
use Sylius\Tests\Api\JsonApiTestCase;
|
||||||
use Sylius\Tests\Api\Utils\AdminUserLoginTrait;
|
use Sylius\Tests\Api\Utils\AdminUserLoginTrait;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
@ -76,6 +75,30 @@ final class ChannelsTest extends JsonApiTestCase
|
||||||
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NOT_FOUND);
|
$this->assertResponseCode($this->client->getResponse(), Response::HTTP_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function it_prevents_deleting_the_only_channel(): void
|
||||||
|
{
|
||||||
|
$this->loadFixturesFromFiles(['authentication/api_administrator.yaml', 'channel.yaml']);
|
||||||
|
$header = array_merge($this->logInAdminUser('api@example.com'), self::CONTENT_TYPE_HEADER);
|
||||||
|
|
||||||
|
$this->client->request(
|
||||||
|
method: 'DELETE',
|
||||||
|
uri: '/api/v2/admin/channels/MOBILE',
|
||||||
|
server: $header,
|
||||||
|
);
|
||||||
|
$this->client->request(
|
||||||
|
method: 'DELETE',
|
||||||
|
uri: '/api/v2/admin/channels/WEB',
|
||||||
|
server: $header,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertResponse(
|
||||||
|
$this->client->getResponse(),
|
||||||
|
'admin/channel/delete_channel_that_cannot_be_deleted',
|
||||||
|
Response::HTTP_UNPROCESSABLE_ENTITY
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
public function it_gets_channels(): void
|
public function it_gets_channels(): void
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"@context": "\/api\/v2\/contexts\/Error",
|
||||||
|
"@type": "hydra:Error",
|
||||||
|
"hydra:title": "An error occurred",
|
||||||
|
"hydra:description": "The channel cannot be deleted. At least one enabled channel is required."
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue