Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CatalogPromotions] Refactor processing catalog promotions states to use commands #13624

Merged
merged 1 commit into from
Feb 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?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\CoreBundle\CatalogPromotion\Command;

final class UpdateCatalogPromotionState
{
public function __construct(public string $code)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?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\CoreBundle\CatalogPromotion\CommandHandler;

use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\UpdateCatalogPromotionState;
use Sylius\Bundle\CoreBundle\Processor\CatalogPromotionStateProcessorInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;

final class UpdateCatalogPromotionStateHandler
{
public function __construct(
private CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
private RepositoryInterface $catalogPromotionRepository
) {
}

public function __invoke(UpdateCatalogPromotionState $command): void
{
/** @var CatalogPromotionInterface|null $catalogPromotion */
$catalogPromotion = $this->catalogPromotionRepository->findOneBy(['code' => $command->code]);
if (null === $catalogPromotion) {
return;
}

$this->catalogPromotionStateProcessor->process($catalogPromotion);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,22 @@

namespace Sylius\Bundle\CoreBundle\Fixture\Listener;

use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\UpdateCatalogPromotionState;
use Sylius\Bundle\CoreBundle\Fixture\CatalogPromotionFixture;
use Sylius\Bundle\CoreBundle\Processor\AllProductVariantsCatalogPromotionsProcessorInterface;
use Sylius\Bundle\CoreBundle\Processor\CatalogPromotionStateProcessorInterface;
use Sylius\Bundle\FixturesBundle\Listener\AbstractListener;
use Sylius\Bundle\FixturesBundle\Listener\AfterFixtureListenerInterface;
use Sylius\Bundle\FixturesBundle\Listener\FixtureEvent;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Promotion\Repository\CatalogPromotionRepositoryInterface;
use Symfony\Component\Messenger\MessageBusInterface;

final class CatalogPromotionExecutorListener extends AbstractListener implements AfterFixtureListenerInterface
{
public function __construct(
private AllProductVariantsCatalogPromotionsProcessorInterface $allCatalogPromotionsProcessor,
private CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
private CatalogPromotionRepositoryInterface $catalogPromotionsRepository,
private MessageBusInterface $messageBus,
private iterable $defaultCriteria = []
) {
}
Expand All @@ -41,8 +43,9 @@ public function afterFixture(FixtureEvent $fixtureEvent, array $options): void

$catalogPromotions = $this->catalogPromotionsRepository->findByCriteria($this->defaultCriteria);

/** @var CatalogPromotionInterface $catalogPromotion */
foreach ($catalogPromotions as $catalogPromotion) {
$this->catalogPromotionStateProcessor->process($catalogPromotion);
$this->messageBus->dispatch(new UpdateCatalogPromotionState($catalogPromotion->getCode()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,20 @@

namespace Sylius\Bundle\CoreBundle\Listener;

use Doctrine\ORM\EntityManagerInterface;
use Sylius\Bundle\CoreBundle\Processor\CatalogPromotionStateProcessorInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\UpdateCatalogPromotionState;
use Sylius\Component\Promotion\Event\CatalogPromotionCreated;
use Sylius\Component\Promotion\Event\CatalogPromotionEnded;
use Sylius\Component\Promotion\Event\CatalogPromotionUpdated;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\Messenger\MessageBusInterface;

final class CatalogPromotionStateChangedListener
{
public function __construct(
private CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
private RepositoryInterface $catalogPromotionRepository,
private EntityManagerInterface $entityManager
) {
public function __construct(private MessageBusInterface $messageBus)
{
}

public function __invoke(CatalogPromotionCreated|CatalogPromotionUpdated|CatalogPromotionEnded $event): void
{
/** @var CatalogPromotionInterface|null $catalogPromotion */
$catalogPromotion = $this->catalogPromotionRepository->findOneBy(['code' => $event->code]);
if (null === $catalogPromotion) {
return;
}

$this->catalogPromotionStateProcessor->process($catalogPromotion);

$this->entityManager->flush();
$this->messageBus->dispatch(new UpdateCatalogPromotionState($event->code));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ framework:

routing:
'Sylius\Bundle\CoreBundle\Command\ApplyCatalogPromotionsOnVariants': main
'Sylius\Bundle\CoreBundle\CatalogPromotion\Command\UpdateCatalogPromotionState': main
'Sylius\Component\Promotion\Event\CatalogPromotionCreated': main
'Sylius\Component\Promotion\Event\CatalogPromotionEnded': main
'Sylius\Component\Promotion\Event\CatalogPromotionUpdated': main
Expand Down
6 changes: 6 additions & 0 deletions src/Sylius/Bundle/CoreBundle/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,12 @@
<tag name="messenger.message_handler" bus="sylius.command_bus" />
</service>

<service id="Sylius\Bundle\CoreBundle\CatalogPromotion\CommandHandler\UpdateCatalogPromotionStateHandler">
<argument type="service" id="Sylius\Bundle\CoreBundle\Processor\CatalogPromotionStateProcessorInterface" />
<argument type="service" id="sylius.repository.catalog_promotion" />
<tag name="messenger.message_handler" bus="sylius.command_bus" />
</service>

<service
id="Sylius\Bundle\CoreBundle\Checker\ProductVariantForCatalogPromotionEligibilityInterface"
class="Sylius\Bundle\CoreBundle\Checker\ProductVariantForCatalogPromotionEligibility"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

<service id="sylius_fixtures.listener.catalog_promotion_executor" class="Sylius\Bundle\CoreBundle\Fixture\Listener\CatalogPromotionExecutorListener" public="false">
<argument type="service" id="Sylius\Bundle\CoreBundle\Processor\AllProductVariantsCatalogPromotionsProcessorInterface" />
<argument type="service" id="Sylius\Bundle\CoreBundle\Processor\CatalogPromotionStateProcessorInterface" />
<argument type="service" id="Sylius\Bundle\PromotionBundle\Doctrine\ORM\CatalogPromotionRepository" />
<argument type="service" id="sylius.command_bus" />
<argument type="tagged_iterator" tag="sylius.catalog_promotion.criteria" />
<tag name="sylius_fixtures.listener" />
</service>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@
</service>

<service id="Sylius\Bundle\CoreBundle\Listener\CatalogPromotionStateChangedListener">
<argument type="service" id="Sylius\Bundle\CoreBundle\Processor\CatalogPromotionStateProcessorInterface" />
<argument type="service" id="sylius.repository.catalog_promotion" />
<argument type="service" id="doctrine.orm.entity_manager" />
<argument type="service" id="sylius.command_bus" />
<tag name="messenger.message_handler" bus="sylius.event_bus" />
</service>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?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\CoreBundle\CatalogPromotion\CommandHandler;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\UpdateCatalogPromotionState;
use Sylius\Bundle\CoreBundle\Processor\CatalogPromotionStateProcessorInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;

final class UpdateCatalogPromotionStateHandlerSpec extends ObjectBehavior
{
function let(
CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
RepositoryInterface $catalogPromotionRepository
): void {
$this->beConstructedWith($catalogPromotionStateProcessor, $catalogPromotionRepository);
}

function it_processes_catalog_promotion_that_has_just_been_created(
CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
RepositoryInterface $catalogPromotionRepository,
CatalogPromotionInterface $catalogPromotion
): void {
$catalogPromotionRepository->findOneBy(['code' => 'WINTER_MUGS_SALE'])->willReturn($catalogPromotion);

$catalogPromotionStateProcessor->process($catalogPromotion)->shouldBeCalled();

$this(new UpdateCatalogPromotionState('WINTER_MUGS_SALE'));
}

function it_processes_catalog_promotion_that_has_just_been_updated(
CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
RepositoryInterface $catalogPromotionRepository,
CatalogPromotionInterface $catalogPromotion
): void {
$catalogPromotionRepository->findOneBy(['code' => 'WINTER_MUGS_SALE'])->willReturn($catalogPromotion);

$catalogPromotionStateProcessor->process($catalogPromotion)->shouldBeCalled();

$this(new UpdateCatalogPromotionState('WINTER_MUGS_SALE'));
}

function it_processes_catalog_promotion_that_has_just_been_ended(
CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
RepositoryInterface $catalogPromotionRepository,
CatalogPromotionInterface $catalogPromotion
): void {
$catalogPromotionRepository->findOneBy(['code' => 'WINTER_MUGS_SALE'])->willReturn($catalogPromotion);

$catalogPromotionStateProcessor->process($catalogPromotion)->shouldBeCalled();

$this(new UpdateCatalogPromotionState('WINTER_MUGS_SALE'));
}

function it_does_nothing_if_there_is_no_catalog_promotion_with_given_code(
CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
RepositoryInterface $catalogPromotionRepository
): void {
$catalogPromotionRepository->findOneBy(['code' => 'WINTER_MUGS_SALE'])->willReturn(null);
$catalogPromotionRepository->findAll()->shouldNotBeCalled();

$catalogPromotionStateProcessor->process(Argument::any())->shouldNotBeCalled();

$this(new UpdateCatalogPromotionState('WINTER_MUGS_SALE'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
namespace spec\Sylius\Bundle\CoreBundle\Fixture\Listener;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Bundle\CoreBundle\CatalogPromotion\Command\UpdateCatalogPromotionState;
use Sylius\Bundle\CoreBundle\Fixture\CatalogPromotionFixture;
use Sylius\Bundle\CoreBundle\Processor\AllProductVariantsCatalogPromotionsProcessorInterface;
use Sylius\Bundle\CoreBundle\Processor\CatalogPromotionStateProcessorInterface;
use Sylius\Bundle\FixturesBundle\Fixture\FixtureInterface;
use Sylius\Bundle\FixturesBundle\Listener\AfterFixtureListenerInterface;
use Sylius\Bundle\FixturesBundle\Listener\FixtureEvent;
Expand All @@ -25,20 +26,22 @@
use Sylius\Bundle\PromotionBundle\Criteria\CriteriaInterface;
use Sylius\Component\Core\Model\CatalogPromotionInterface;
use Sylius\Component\Promotion\Repository\CatalogPromotionRepositoryInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;

final class CatalogPromotionExecutorListenerSpec extends ObjectBehavior
{
function let(
AllProductVariantsCatalogPromotionsProcessorInterface $allCatalogPromotionsProcessor,
CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $messageBus,
CriteriaInterface $firstCriterion,
CriteriaInterface $secondCriterion
): void {
$this->beConstructedWith(
$allCatalogPromotionsProcessor,
$catalogPromotionStateProcessor,
$catalogPromotionRepository,
$messageBus,
[$firstCriterion, $secondCriterion]
);
}
Expand All @@ -55,10 +58,10 @@ function it_listens_for_after_fixture_events(): void

function it_triggers_catalog_promotion_processing_after_catalog_promotion_fixture_execution(
AllProductVariantsCatalogPromotionsProcessorInterface $allCatalogPromotionsProcessor,
CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $messageBus,
SuiteInterface $suite,
CatalogPromotionFixture $catalogPromotionFixture,
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
CatalogPromotionInterface $firstCatalogPromotion,
CatalogPromotionInterface $secondCatalogPromotion,
CriteriaInterface $firstCriterion,
Expand All @@ -69,27 +72,32 @@ function it_triggers_catalog_promotion_processing_after_catalog_promotion_fixtur
->willReturn([$firstCatalogPromotion, $secondCatalogPromotion])
;

$this->afterFixture(new FixtureEvent($suite->getWrappedObject(), $catalogPromotionFixture->getWrappedObject(), []), []);
$firstCatalogPromotion->getCode()->willReturn('WINTER');
$secondCatalogPromotion->getCode()->willReturn('AUTUMN');

$allCatalogPromotionsProcessor->process()->shouldBeCalled();
$catalogPromotionStateProcessor->process($firstCatalogPromotion)->shouldBeCalled();
$catalogPromotionStateProcessor->process($secondCatalogPromotion)->shouldBeCalled();

$firstCommand = new UpdateCatalogPromotionState('WINTER');
$messageBus->dispatch($firstCommand)->willReturn(new Envelope($firstCommand))->shouldBeCalled();

$secondCommand = new UpdateCatalogPromotionState('AUTUMN');
$messageBus->dispatch($secondCommand)->willReturn(new Envelope($secondCommand))->shouldBeCalled();

$this->afterFixture(new FixtureEvent($suite->getWrappedObject(), $catalogPromotionFixture->getWrappedObject(), []), []);
}

function it_does_not_trigger_catalog_promotion_processing_after_any_other_fixture_execution(
AllProductVariantsCatalogPromotionsProcessorInterface $allCatalogPromotionsProcessor,
CatalogPromotionStateProcessorInterface $catalogPromotionStateProcessor,
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
MessageBusInterface $messageBus,
SuiteInterface $suite,
FixtureInterface $fixture,
CatalogPromotionRepositoryInterface $catalogPromotionRepository,
CriteriaInterface $firstCriterion,
CriteriaInterface $secondCriterion
): void {
$catalogPromotionRepository->findByCriteria([$firstCriterion, $secondCriterion])->shouldNotBeCalled();

$this->afterFixture(new FixtureEvent($suite->getWrappedObject(), $fixture->getWrappedObject(), []), []);
$messageBus->dispatch(Argument::any())->shouldNotBeCalled();

$allCatalogPromotionsProcessor->process()->shouldNotBeCalled();
$catalogPromotionStateProcessor->process()->shouldNotBeCalled();
$this->afterFixture(new FixtureEvent($suite->getWrappedObject(), $fixture->getWrappedObject(), []), []);
}
}
Loading