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

Add AsEntityListener attribute #1345

Merged
merged 1 commit into from
May 13, 2021
Merged
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
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
@@ -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;
@@ -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', [
41 changes: 41 additions & 0 deletions Tests/DependencyInjection/DoctrineExtensionTest.php
Original file line number Diff line number Diff line change
@@ -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;
@@ -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;
@@ -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;

@@ -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
{
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
{
}
}