Skip to content

Commit

Permalink
Refactor checking whether the channel can be deleted
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubtobiasz committed Nov 6, 2023
1 parent 14a94c0 commit 2e05cbc
Show file tree
Hide file tree
Showing 17 changed files with 295 additions and 171 deletions.
2 changes: 2 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,7 @@

<server name="IS_DOCTRINE_ORM_SUPPORTED" value="true" />
<server name="ESCAPE_JSON" value="true" />

<server name="KERNEL_CLASS" value="App\Kernel" />
</php>
</phpunit>
47 changes: 47 additions & 0 deletions src/Sylius/Bundle/ApiBundle/DataPersister/ChannelDataPersister.php
Original file line number Diff line number Diff line change
@@ -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\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,
) {
}

public function supports($data, array $context = []): bool
{
return $data instanceof ChannelInterface;
}

public function persist($data, array $context = [])
{
return $this->decoratedDataPersister->persist($data, $context);
}

public function remove($data, array $context = [])
{
if (!$this->channelDeletionChecker->isDeletable($data)) {
throw new ChannelCannotBeRemoved('The channel cannot be deleted. At least one enabled channel is required.');
}

return $this->decoratedDataPersister->remove($data, $context);
}
}

This file was deleted.

5 changes: 0 additions & 5 deletions src/Sylius/Bundle/ApiBundle/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,6 @@
<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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
<tag name="api_platform.data_persister" />
</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">
<argument type="service" id="api_platform.messenger.data_persister" />
<tag name="api_platform.data_persister" />
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public function findAllWithBasicData(): iterable
;
}

public function findEnabled(): iterable

Check failure on line 59 in src/Sylius/Bundle/ChannelBundle/Doctrine/ORM/ChannelRepository.php

View workflow job for this annotation

GitHub Actions / Static checks / PHP 8.0, Symfony ^5.4, API Platform ^2.7.10

InvalidReturnType

src/Sylius/Bundle/ChannelBundle/Doctrine/ORM/ChannelRepository.php:59:36: InvalidReturnType: The declared return type 'iterable<mixed, Sylius\Component\Channel\Model\ChannelInterface>' for Sylius\Bundle\ChannelBundle\Doctrine\ORM\ChannelRepository::findEnabled is incorrect, got 'list<mixed>' (see https://psalm.dev/011)

Check failure on line 59 in src/Sylius/Bundle/ChannelBundle/Doctrine/ORM/ChannelRepository.php

View workflow job for this annotation

GitHub Actions / Static checks / PHP 8.2, Symfony ^6.0, API Platform ^2.7.10

InvalidReturnType

src/Sylius/Bundle/ChannelBundle/Doctrine/ORM/ChannelRepository.php:59:36: InvalidReturnType: The declared return type 'iterable<mixed, Sylius\Component\Channel\Model\ChannelInterface>' for Sylius\Bundle\ChannelBundle\Doctrine\ORM\ChannelRepository::findEnabled is incorrect, got 'list<mixed>' (see https://psalm.dev/011)
{
return $this->findBy(['enabled' => true]);

Check failure on line 61 in src/Sylius/Bundle/ChannelBundle/Doctrine/ORM/ChannelRepository.php

View workflow job for this annotation

GitHub Actions / Static checks / PHP 8.0, Symfony ^5.4, API Platform ^2.7.10

InvalidReturnStatement

src/Sylius/Bundle/ChannelBundle/Doctrine/ORM/ChannelRepository.php:61:16: InvalidReturnStatement: The inferred type 'list<mixed>' does not match the declared return type 'iterable<mixed, Sylius\Component\Channel\Model\ChannelInterface>' for Sylius\Bundle\ChannelBundle\Doctrine\ORM\ChannelRepository::findEnabled (see https://psalm.dev/128)

Check failure on line 61 in src/Sylius/Bundle/ChannelBundle/Doctrine/ORM/ChannelRepository.php

View workflow job for this annotation

GitHub Actions / Static checks / PHP 8.2, Symfony ^6.0, API Platform ^2.7.10

InvalidReturnStatement

src/Sylius/Bundle/ChannelBundle/Doctrine/ORM/ChannelRepository.php:61:16: InvalidReturnStatement: The inferred type 'list<mixed>' does not match the declared return type 'iterable<mixed, Sylius\Component\Channel\Model\ChannelInterface>' for Sylius\Bundle\ChannelBundle\Doctrine\ORM\ChannelRepository::findEnabled (see https://psalm.dev/128)
}

public function countAll(): int
{
return $this->count([]);
Expand Down
5 changes: 5 additions & 0 deletions src/Sylius/Bundle/ChannelBundle/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,10 @@
<argument>false</argument>
<tag name="data_collector" template="@SyliusChannel/Collector/channel.html.twig" id="sylius.channel_collector" />
</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>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
namespace Sylius\Bundle\CoreBundle\EventListener;

use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
use Sylius\Component\Channel\Checker\ChannelDeletionCheckerInterface;
use Sylius\Component\Channel\Model\ChannelInterface;
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
use Sylius\Component\Resource\Exception\UnexpectedTypeException;

final class ChannelDeletionListener
{
public function __construct(private ChannelRepositoryInterface $channelRepository)
public function __construct(private ChannelDeletionCheckerInterface $channelDeletionChecker)
{
}

Expand All @@ -38,9 +38,7 @@ public function onChannelPreDelete(ResourceControllerEvent $event): void
);
}

$results = $this->channelRepository->findBy(['enabled' => true]);

if (!$results || (count($results) === 1 && current($results) === $channel)) {
if (!$this->channelDeletionChecker->isDeletable($channel)) {
$event->stop('sylius.channel.delete_error');
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<defaults public="true" />

<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" />
</service>

Expand Down

0 comments on commit 2e05cbc

Please sign in to comment.