Skip to content

Commit 21c82f5

Browse files
committed
feature: add support for
1 parent 6d5eede commit 21c82f5

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@
134134
"async-aws/sns": "^1.0",
135135
"cache/integration-tests": "dev-master",
136136
"doctrine/collections": "^1.8|^2.0",
137-
"doctrine/data-fixtures": "^1.1",
137+
"doctrine/data-fixtures": "^1.1|^2.0",
138138
"doctrine/dbal": "^3.6|^4",
139139
"doctrine/orm": "^2.15|^3",
140140
"dragonmantank/cron-expression": "^3.1",

src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111

1212
namespace Symfony\Bridge\Doctrine\DependencyInjection;
1313

14+
use Doctrine\Persistence\Mapping\Driver\ClassLocator;
15+
use Doctrine\Persistence\Mapping\Driver\FileClassLocator;
1416
use Symfony\Component\DependencyInjection\Alias;
1517
use Symfony\Component\DependencyInjection\ContainerBuilder;
1618
use Symfony\Component\DependencyInjection\Definition;
1719
use Symfony\Component\DependencyInjection\Reference;
20+
use Symfony\Component\Finder\Finder;
1821
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
1922

2023
/**
@@ -30,6 +33,8 @@ abstract class AbstractDoctrineExtension extends Extension
3033
protected array $aliasMap = [];
3134

3235
/**
36+
* @var array<string,array<string,string>> An array of directory paths by namespace, indexed by driver type.
37+
*
3338
* Used inside metadata driver method to simplify aggregation of data.
3439
*/
3540
protected array $drivers = [];
@@ -202,6 +207,15 @@ protected function registerMappingDrivers(array $objectManager, ContainerBuilder
202207
$mappingDriverDef->setArguments([array_flip($driverPaths)]);
203208
$mappingDriverDef->addMethodCall('setGlobalBasename', ['mapping']);
204209
}
210+
// Available since doctrine/persistence >= 4.1
211+
if (interface_exists(ClassLocator::class)
212+
&& \in_array($driverType, ['annotation', 'attribute'], true)
213+
) {
214+
/** @var string[] $directoryPaths */
215+
$directoryPaths = $mappingDriverDef->getArgument(0);
216+
$classLocator = $this->registerMappingClassLocatorService($objectManager['name'].'_'.$driverType, $container, $directoryPaths);
217+
$mappingDriverDef->replaceArgument(0, new Reference($classLocator));
218+
}
205219

206220
$container->setDefinition($mappingService, $mappingDriverDef);
207221

@@ -213,6 +227,40 @@ protected function registerMappingDrivers(array $objectManager, ContainerBuilder
213227
$container->setDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'), $chainDriverDef);
214228
}
215229

230+
/** @param string[] $dirs */
231+
private function registerMappingClassLocatorService(string $driverName, ContainerBuilder $container, array $dirs): string
232+
{
233+
$classLocator = $this->getObjectManagerElementName($driverName.'_mapping_class_locator');
234+
235+
$iteratorDefinition = new Definition(
236+
FileClassLocator::class,
237+
[new Reference($this->registerMappingClassFinderService($driverName, $container, $dirs))],
238+
);
239+
240+
$container->setDefinition($classLocator, $iteratorDefinition);
241+
242+
return $classLocator;
243+
}
244+
245+
private function registerMappingClassFinderService(string $driverName, ContainerBuilder $container, array $dirs): string
246+
{
247+
$finderService = $this->getObjectManagerElementName($driverName.'_mapping_class_finder');
248+
249+
if ($container->hasDefinition($finderService)) {
250+
$finderDefinition = $container->getDefinition($finderService);
251+
} else {
252+
$finderDefinition = new Definition(Finder::class, []);
253+
}
254+
255+
$finderDefinition->addMethodCall('files');
256+
$finderDefinition->addMethodCall('name', ['*.php']);
257+
$finderDefinition->addMethodCall('in', [$dirs]);
258+
259+
$container->setDefinition($finderService, $finderDefinition);
260+
261+
return $finderService;
262+
}
263+
216264
/**
217265
* Assertion if the specified mapping information is valid.
218266
*

src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/DoctrineExtensionTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@
1111

1212
namespace Symfony\Bridge\Doctrine\Tests\DependencyInjection;
1313

14+
use Doctrine\Persistence\Mapping\Driver\ClassLocator;
15+
use Doctrine\Persistence\Mapping\Driver\FileClassLocator;
1416
use PHPUnit\Framework\Attributes\DataProvider;
1517
use PHPUnit\Framework\MockObject\MockObject;
1618
use PHPUnit\Framework\TestCase;
1719
use Symfony\Bridge\Doctrine\DependencyInjection\AbstractDoctrineExtension;
1820
use Symfony\Component\DependencyInjection\ContainerBuilder;
1921
use Symfony\Component\DependencyInjection\Definition;
2022
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
23+
use Symfony\Component\Finder\Finder;
2124
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
2225

2326
/**
@@ -55,6 +58,37 @@ protected function setUp(): void
5558
->willReturn('orm');
5659
}
5760

61+
public function testRegisterMappingFilesIteratorService(): void
62+
{
63+
if (!interface_exists(ClassLocator::class)) {
64+
$this->markTestSkipped('This test is only relevant for versions of doctrine/persistence >= 4.1');
65+
}
66+
67+
$driverName = 'default_attribute';
68+
$container = $this->createContainer();
69+
$dirs = [__DIR__.'/../Fixtures'];
70+
71+
$locatorServiceId = $this->invokeRegisterMappingClassLocatorService($driverName, $container, $dirs);
72+
73+
$this->assertSame('doctrine.orm.default_attribute_mapping_class_locator', $locatorServiceId);
74+
$fileClassLocator = $container->get($locatorServiceId);
75+
$this->assertInstanceOf(FileClassLocator::class, $fileClassLocator);
76+
77+
$classNames = $fileClassLocator->getClassNames();
78+
self::assertGreaterThan(1, \count($classNames));
79+
80+
$finderServiceId = 'doctrine.orm.default_attribute_mapping_class_finder';
81+
$finderDefinition = $container->getDefinition($finderServiceId);
82+
83+
$this->assertSame(Finder::class, $finderDefinition->getClass());
84+
$this->assertTrue($finderDefinition->isShared());
85+
$this->assertSame([
86+
['files', []],
87+
['name', ['*.php']],
88+
['in', [$dirs]],
89+
], $finderDefinition->getMethodCalls());
90+
}
91+
5892
public function testFixManagersAutoMappingsWithTwoAutomappings()
5993
{
6094
$emConfigs = [
@@ -334,4 +368,16 @@ protected function createContainer(array $data = [], array $extraBundles = []):
334368
'kernel.project_dir' => __DIR__,
335369
], $data)));
336370
}
371+
372+
/** @param string[] $dirs */
373+
private function invokeRegisterMappingClassLocatorService(string $driverName, ContainerBuilder $container, array $dirs): string
374+
{
375+
$reflection = new \ReflectionClass($this->extension);
376+
$method = $reflection->getMethod('registerMappingClassLocatorService');
377+
378+
/** @var string $locatorServiceId */
379+
$locatorServiceId = $method->invoke($this->extension, $driverName, $container, $dirs);
380+
381+
return $locatorServiceId;
382+
}
337383
}

0 commit comments

Comments
 (0)