Skip to content

Commit

Permalink
Optimizing Channel persist listener
Browse files Browse the repository at this point in the history
1. Don't load all customer options to filter in PHP
2. Rename the class to have a more descriptive name
and fixing the tests
  • Loading branch information
mamazu committed Nov 28, 2023
1 parent ca208ed commit 7af3fba
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 82 deletions.
58 changes: 0 additions & 58 deletions src/EventListener/ChannelListener.php

This file was deleted.

48 changes: 48 additions & 0 deletions src/EventListener/ChannelPersistListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

/**
* This file is part of the Brille24 customer options plugin.
*
* (c) Brille24 GmbH
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);

namespace Brille24\SyliusCustomerOptionsPlugin\EventListener;

use Brille24\SyliusCustomerOptionsPlugin\Entity\CustomerOptions\CustomerOptionValuePriceInterface;
use Brille24\SyliusCustomerOptionsPlugin\Factory\CustomerOptionValuePriceFactoryInterface;
use Brille24\SyliusCustomerOptionsPlugin\Repository\CustomerOptionValueRepositoryInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Sylius\Component\Core\Model\ChannelInterface;

final class ChannelPersistListener
{
public function __construct(
private CustomerOptionValuePriceFactoryInterface $customerOptionValuePriceFactory,
private CustomerOptionValueRepositoryInterface $customerOptionValueRepository
) {
}

public function prePersist(LifecycleEventArgs $args): void
{
$channel = $args->getObject();

if (!$channel instanceof ChannelInterface) {
return;
}

$customerOptionValues = $this->customerOptionValueRepository->findValuesWithoutPricingInChannel($channel);

foreach ($customerOptionValues as $customerOptionValue) {
/** @var CustomerOptionValuePriceInterface $newPrice */
$newPrice = $this->customerOptionValuePriceFactory->createNew();
$newPrice->setChannel($channel);
$customerOptionValue->addPrice($newPrice);
$args->getObjectManager()->persist($customerOptionValue);
}
}
}
15 changes: 15 additions & 0 deletions src/Repository/CustomerOptionValueRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use Brille24\SyliusCustomerOptionsPlugin\Entity\CustomerOptions\CustomerOptionValueInterface;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
use Sylius\Component\Core\Model\ChannelInterface;

class CustomerOptionValueRepository extends EntityRepository implements CustomerOptionValueRepositoryInterface
{
Expand All @@ -29,4 +30,18 @@ public function findOneByCode(string $code): ?CustomerOptionValueInterface
->getOneOrNullResult()
;
}

/**
* @inheritdoc
*/
public function findValuesWithoutPricingInChannel(ChannelInterface $channel): array
{
return $this->createQueryBuilder('v')
->join('v.prices', 'p')
->where('p.channel = :channel')
->setParameter('channel', $channel)
->getQuery()
->getResult()
;
}
}
8 changes: 8 additions & 0 deletions src/Repository/CustomerOptionValueRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
namespace Brille24\SyliusCustomerOptionsPlugin\Repository;

use Brille24\SyliusCustomerOptionsPlugin\Entity\CustomerOptions\CustomerOptionValueInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;

interface CustomerOptionValueRepositoryInterface extends RepositoryInterface
Expand All @@ -21,4 +22,11 @@ interface CustomerOptionValueRepositoryInterface extends RepositoryInterface
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function findOneByCode(string $code): ?CustomerOptionValueInterface;

/**
* Returns a list of values that does not have a price for the provided channel.
*
* @return array<CustomerOptionValueInterface>
*/
public function findValuesWithoutPricingInChannel(ChannelInterface $channel): array;
}
4 changes: 3 additions & 1 deletion src/Resources/config/app/services/eventListener.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
</service>

<service
class="Brille24\SyliusCustomerOptionsPlugin\EventListener\ChannelListener"
class="Brille24\SyliusCustomerOptionsPlugin\EventListener\ChannelPersistListener"
id="brille24.customer_options_plugin.event_listener.channel"
>
<argument type="service" id="brille24.customer_options_plugin.factory.customer_option_value_price_factory" />
<argument type="service" id="brille24.customer_options_plugin.repository.customer_option_value" />

<tag name="doctrine.event_listener" event="prePersist" />
</service>
</services>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@
namespace Tests\Brille24\SyliusCustomerOptionsPlugin\PHPUnit\EventListener;

use Brille24\SyliusCustomerOptionsPlugin\Entity\CustomerOptions\CustomerOption;
use Brille24\SyliusCustomerOptionsPlugin\Entity\CustomerOptions\CustomerOptionValue;
use Brille24\SyliusCustomerOptionsPlugin\Entity\CustomerOptions\CustomerOptionValueInterface;
use Brille24\SyliusCustomerOptionsPlugin\Entity\CustomerOptions\CustomerOptionValuePriceInterface;
use Brille24\SyliusCustomerOptionsPlugin\EventListener\ChannelListener;
use Brille24\SyliusCustomerOptionsPlugin\EventListener\ChannelPersistListener;
use Brille24\SyliusCustomerOptionsPlugin\Factory\CustomerOptionValuePriceFactoryInterface;
use Brille24\SyliusCustomerOptionsPlugin\Repository\CustomerOptionValueRepositoryInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Event\LifecycleEventArgs;
use PHPUnit\Framework\TestCase;
use Sylius\Component\Core\Model\Channel;

class ChannelListenerTest extends TestCase
class ChannelPersistListenerTest extends TestCase
{
private \Brille24\SyliusCustomerOptionsPlugin\EventListener\ChannelListener $channelCreateListener;
private ChannelPersistListener $channelCreateListener;

private array $customerOptionValue = [];

Expand All @@ -31,8 +30,18 @@ public function setUp(): void
$customerOptionValueFactory = self::createMock(CustomerOptionValuePriceFactoryInterface::class);
$customerOptionValueFactory
->method('createNew')
->willReturn(self::createMock(CustomerOptionValuePriceInterface::class));
$this->channelCreateListener = new ChannelListener($customerOptionValueFactory);
->willReturn(self::createMock(CustomerOptionValuePriceInterface::class))
;

$customerOptionValueRepository = self::createMock(CustomerOptionValueRepositoryInterface::class);
$customerOptionValueRepository
->method('findValuesWithoutPricingInChannel')
->willReturnCallback(fn () => $this->customerOptionValue);

$this->channelCreateListener = new ChannelPersistListener(
$customerOptionValueFactory,
$customerOptionValueRepository,
);
}

private function createArguments($entity): LifecycleEventArgs
Expand All @@ -42,22 +51,10 @@ private function createArguments($entity): LifecycleEventArgs
++$this->persistCount;
});

$customerOptionValueRepository = self::createMock(EntityRepository::class);
$customerOptionValueRepository->method('findAll')->willReturnCallback(fn () => $this->customerOptionValue);

$entityManger->method('getRepository')->willReturnCallback(
function (string $entityClass) use ($customerOptionValueRepository) {
self::assertEquals(CustomerOptionValue::class, $entityClass);

return $customerOptionValueRepository;
},
);

$arguments = self::createMock(LifecycleEventArgs::class);
$arguments->method('getEntityManager')->willReturn($entityManger);
$arguments->method('getEntity')->willReturn($entity);

return $arguments;
return self::createConfiguredMock(LifecycleEventArgs::class, [
'getObject'=>$entity,
'getObjectManager'=>$entityManger,
]);
}

private function createValue(): CustomerOptionValueInterface
Expand Down

0 comments on commit 7af3fba

Please sign in to comment.