Skip to content

Commit

Permalink
Merge pull request shlinkio#73 from acelaya-forks/feature/orm-listeners
Browse files Browse the repository at this point in the history
Added ability to register ORM listeners
  • Loading branch information
acelaya authored Apr 10, 2021
2 parents 3777189 + c12eae9 commit 554e370
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
## [Unreleased]
### Added
* [#70](https://github.com/shlinkio/shlink-common/issues/70) Added support for `symfony/mercure` 0.5.
* [#72](https://github.com/shlinkio/shlink-common/issues/72) Added ability to register event listeners in the EntityManager through the `EntityManagerFactory`.

### Changed
* *Nothing*
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ declare(strict_types=1);

namespace Shlinkio\Shlink\Common;

use Doctrine\ORM\Events;

return [

'entity_manager' => [
Expand All @@ -125,6 +127,10 @@ return [
Doctrine\Type\ChronosDateTimeType::CHRONOS_DATETIME => Doctrine\Type\ChronosDateTimeType::class,
],
'load_mappings_using_functional_style' => true, // Makes loader assume mappings return a function which should be invoked. Defaults to false
'listeners' => [ // Map telling which service listeners to invoke for every ORM event
Events::postFlush => ['some_service'],
Events::preUpdate => ['foo', 'bar'],
]
],
'connection' => [ // Database connection params
'driver' => 'pdo_mysql',
Expand Down
18 changes: 17 additions & 1 deletion src/Doctrine/EntityManagerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ public function __invoke(ContainerInterface $container): EntityManager
$config->setDefaultRepositoryClassName($defaultRepo);
}

return EntityManager::create($connectionConfig, $config);
$em = EntityManager::create($connectionConfig, $config);

$this->registerListeners($ormConfig, $em, $container);

return $em;
}

/**
Expand All @@ -58,4 +62,16 @@ private function registerTypes(array $ormConfig): void
}
}
}

private function registerListeners(array $ormConfig, EntityManager $em, ContainerInterface $container): void
{
$listeners = $ormConfig['listeners'] ?? [];
$events = $em->getEventManager();

foreach ($listeners as $event => $services) {
foreach ($services as $service) {
$events->addEventListener($event, $container->get($service));
}
}
}
}
55 changes: 47 additions & 8 deletions test/Doctrine/EntityManagerFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@
use Doctrine\DBAL\Driver\PDO\SQLite\Driver as SQLiteDriver;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Events;
use Doctrine\Persistence\Mapping\Driver\PHPDriver;
use Laminas\ServiceManager\ServiceManager;
use PHPUnit\Framework\TestCase;
use ReflectionObject;
use Shlinkio\Shlink\Common\Doctrine\EntityManagerFactory;
use Shlinkio\Shlink\Common\Doctrine\Type\ChronosDateTimeType;
use ShlinkioTest\Shlink\Common\Repository\CustomRepository;
use stdClass;

use function array_filter;
use function array_merge;
use function array_merge_recursive;
use function count;

use const ARRAY_FILTER_USE_KEY;

Expand Down Expand Up @@ -47,10 +50,17 @@ public function setUp(): void
* @test
* @dataProvider provideConfig
*/
public function serviceIsCreated(array $config, int $expectedAutoGenerateProxies, string $expectedDefaultRepo): void
{
public function serviceIsCreated(
array $config,
int $expectedAutoGenerateProxies,
string $expectedDefaultRepo,
int $expectedListeners
): void {
$sm = new ServiceManager(['services' => [
'config' => $config,
'foo_listener' => new stdClass(),
'bar_listener' => new stdClass(),
'baz_listener' => new stdClass(),
]]);

self::assertFalse(Type::hasType(ChronosDateTimeType::CHRONOS_DATETIME));
Expand All @@ -65,6 +75,19 @@ public function serviceIsCreated(array $config, int $expectedAutoGenerateProxies
/** @var PHPDriver $metaDriver */
$metaDriver = $em->getConfiguration()->getMetadataDriverImpl();
self::assertEquals([__FILE__], $metaDriver->getLocator()->getPaths());

$events = $em->getEventManager();
$ref = new ReflectionObject($events);
$prop = $ref->getProperty('_listeners');
$prop->setAccessible(true);
$listeners = $prop->getValue($events);

$listenersCount = 0;
foreach ($listeners as $list) {
$listenersCount += count($list);
}

self::assertEquals($expectedListeners, $listenersCount);
}

public function provideConfig(): iterable
Expand All @@ -84,12 +107,12 @@ public function provideConfig(): iterable
],
];

yield [array_merge($baseConfig, ['debug' => true]), 1, EntityRepository::class];
yield [array_merge($baseConfig, ['debug' => '1']), 1, EntityRepository::class];
yield [array_merge($baseConfig, ['debug' => 'true']), 1, EntityRepository::class];
yield [array_merge($baseConfig, ['debug' => false]), 0, EntityRepository::class];
yield [array_merge($baseConfig, ['debug' => null]), 0, EntityRepository::class];
yield [array_merge($baseConfig, ['debug' => null]), 0, EntityRepository::class];
yield [array_merge($baseConfig, ['debug' => true]), 1, EntityRepository::class, 0];
yield [array_merge($baseConfig, ['debug' => '1']), 1, EntityRepository::class, 0];
yield [array_merge($baseConfig, ['debug' => 'true']), 1, EntityRepository::class, 0];
yield [array_merge($baseConfig, ['debug' => false]), 0, EntityRepository::class, 0];
yield [array_merge($baseConfig, ['debug' => null]), 0, EntityRepository::class, 0];
yield [array_merge($baseConfig, ['debug' => null]), 0, EntityRepository::class, 0];
yield [
array_merge_recursive($baseConfig, [
'entity_manager' => [
Expand All @@ -98,6 +121,22 @@ public function provideConfig(): iterable
]),
0,
CustomRepository::class,
0,
];
yield [
array_merge_recursive($baseConfig, [
'entity_manager' => [
'orm' => [
'listeners' => [
Events::postFlush => ['foo_listener', 'bar_listener'],
Events::prePersist => ['foo_listener', 'bar_listener', 'baz_listener'],
],
],
],
]),
0,
EntityRepository::class,
5,
];
}
}

0 comments on commit 554e370

Please sign in to comment.