Skip to content

Commit

Permalink
Add AsEntityListener attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed May 13, 2021
1 parent e5cc632 commit 2035302
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 0 deletions.
20 changes: 20 additions & 0 deletions Attribute/AsEntityListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Doctrine\Bundle\DoctrineBundle\Attribute;

use Attribute;

/**
* Service tag to autoconfigure entity listeners.
*/
#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)]
class AsEntityListener
{
public function __construct(
public ?string $event = null,
public ?string $method = null,
public ?bool $lazy = null,
public ?string $entityManager = null,
) {
}
}
12 changes: 12 additions & 0 deletions DependencyInjection/DoctrineExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
use Doctrine\Bundle\DoctrineBundle\CacheWarmer\DoctrineMetadataCacheWarmer;
use Doctrine\Bundle\DoctrineBundle\Command\Proxy\ImportDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Dbal\ManagerRegistryAwareConnectionProvider;
Expand Down Expand Up @@ -524,6 +525,17 @@ protected function ormLoad(array $config, ContainerBuilder $container)
$container->registerForAutoconfiguration(AbstractIdGenerator::class)
->addTag(IdGeneratorPass::ID_GENERATOR_TAG);

if (method_exists($container, 'registerAttributeForAutoconfiguration')) {
$container->registerAttributeForAutoconfiguration(AsEntityListener::class, static function (ChildDefinition $definition, AsEntityListener $attribute) {
$definition->addTag('doctrine.orm.entity_listener', [
'event' => $attribute->event,
'method' => $attribute->method,
'lazy' => $attribute->lazy,
'entity_manager' => $attribute->entityManager,
]);
});
}

/** @see DoctrineBundle::boot() */
$container->getDefinition($defaultEntityManagerDefinitionId)
->addTag('container.preload', [
Expand Down
41 changes: 41 additions & 0 deletions Tests/DependencyInjection/DoctrineExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

namespace Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection;

use Closure;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
use Doctrine\Bundle\DoctrineBundle\CacheWarmer\DoctrineMetadataCacheWarmer;
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\DoctrineExtension;
use Doctrine\Bundle\DoctrineBundle\Tests\Builder\BundleConfigurationBuilder;
use Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\Fixtures\Php8EntityListener;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Connection as DriverConnection;
use Doctrine\DBAL\Sharding\PoolingShardManager;
Expand All @@ -14,11 +17,13 @@
use InvalidArgumentException;
use LogicException;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use Symfony\Bridge\Doctrine\Messenger\DoctrineClearEntityManagerWorkerSubscriber;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Cache\Adapter\DoctrineAdapter;
use Symfony\Component\Cache\Adapter\PhpArrayAdapter;
use Symfony\Component\Cache\DoctrineProvider;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
Expand All @@ -29,6 +34,7 @@
use function array_values;
use function class_exists;
use function interface_exists;
use function method_exists;
use function sprintf;
use function sys_get_temp_dir;

Expand Down Expand Up @@ -1071,6 +1077,41 @@ public function testShardManager(): void
$this->assertEquals($managerClass, $bazManagerDef->getClass());
}

/** @requires PHP 8 */
public function testAsEntityListenerAttribute()
{
if (! method_exists(ContainerBuilder::class, 'getAutoconfiguredAttributes')) {
$this->markTestSkipped('symfony/dependency-injection 5.3.0 needed');
}

$container = $this->getContainer();
$extension = new DoctrineExtension();

$config = BundleConfigurationBuilder::createBuilder()
->addBaseConnection()
->addBaseEntityManager()
->build();

$extension->load([$config], $container);

$attributes = $container->getAutoconfiguredAttributes();
$this->assertInstanceOf(Closure::class, $attributes[AsEntityListener::class]);

$reflector = new ReflectionClass(Php8EntityListener::class);
$definition = new ChildDefinition('');
$attribute = $reflector->getAttributes(AsEntityListener::class)[0]->newInstance();

$attributes[AsEntityListener::class]($definition, $attribute);

$expected = [
'event' => null,
'method' => null,
'lazy' => null,
'entity_manager' => null,
];
$this->assertSame([$expected], $definition->getTag('doctrine.orm.entity_listener'));
}

/** @param list<string> $bundles */
private function getContainer(array $bundles = ['YamlBundle'], string $vendor = ''): ContainerBuilder
{
Expand Down
17 changes: 17 additions & 0 deletions Tests/DependencyInjection/Fixtures/Php8EntityListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\Fixtures;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;

#[AsEntityListener()]
final class Php8EntityListener
{
public function __invoke(): void
{
}

public function postPersist(): void
{
}
}

0 comments on commit 2035302

Please sign in to comment.