Skip to content

Commit

Permalink
Wire EntityArgumentResolver when available
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas authored and ostrolucky committed Sep 7, 2022
1 parent 40dda75 commit 71d6411
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 0 deletions.
13 changes: 13 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,19 @@ private function addOrmSection(ArrayNodeDefinition $node): void
->end()
->scalarNode('proxy_dir')->defaultValue('%kernel.cache_dir%/doctrine/orm/Proxies')->end()
->scalarNode('proxy_namespace')->defaultValue('Proxies')->end()
->arrayNode('controller_resolver')
->canBeDisabled()
->children()
->booleanNode('auto_mapping')
->defaultTrue()
->info('Set to false to disable using route placeholders as lookup criteria when the primary key doesn\'t match the argument name')
->end()
->booleanNode('evict_cache')
->info('Set to true to fetch the entity from the database instead of using the cache, if any')
->defaultFalse()
->end()
->end()
->end()
->end()
->fixXmlConfig('entity_manager')
->append($this->getOrmEntityManagersNode())
Expand Down
41 changes: 41 additions & 0 deletions DependencyInjection/DoctrineExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
use Doctrine\ORM\UnitOfWork;
use LogicException;
use ReflectionMethod;
use Symfony\Bridge\Doctrine\ArgumentResolver\EntityValueResolver;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bridge\Doctrine\DependencyInjection\AbstractDoctrineExtension;
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
Expand All @@ -52,6 +54,7 @@
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Messenger\Bridge\Doctrine\Transport\DoctrineTransportFactory;
use Symfony\Component\Messenger\MessageBusInterface;
Expand Down Expand Up @@ -527,6 +530,44 @@ protected function ormLoad(array $config, ContainerBuilder $container)
$container->removeDefinition('doctrine.uuid_generator');
}

// available in Symfony 6.2 and higher
if (! class_exists(EntityValueResolver::class)) {
$container->removeDefinition('doctrine.orm.entity_value_resolvers');
$container->removeDefinition('doctrine.orm.entity_value_resolver.expression_language');
} else {
if (! class_exists(ExpressionLanguage::class)) {
$container->removeDefinition('doctrine.orm.entity_value_resolver.expression_language');
}

$controllerResolverDefaults = [];

if (! $config['controller_resolver']['enabled']) {
$controllerResolverDefaults['disabled'] = true;
}

if (! $config['controller_resolver']['auto_mapping']) {
$controllerResolverDefaults['mapping'] = [];
}

if ($config['controller_resolver']['evict_cache']) {
$controllerResolverDefaults['evict_cache'] = true;
}

if ($controllerResolverDefaults) {
$container->getDefinition('doctrine.orm.entity_value_resolver')->setArgument(2, (new Definition(MapEntity::class))->setArguments([
null,
null,
null,
$controllerResolverDefaults['mapping'] ?? null,
null,
null,
null,
$controllerResolverDefaults['evict_cache'] ?? null,
$controllerResolverDefaults['disabled'] ?? false,
]));
}
}

// not available in Doctrine ORM 3.0 and higher
if (! class_exists(ConvertMappingCommand::class)) {
$container->removeDefinition('doctrine.mapping_convert_command');
Expand Down
8 changes: 8 additions & 0 deletions Resources/config/orm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@
<argument type="service" id="doctrine" />
</service>

<service id="doctrine.orm.entity_value_resolver" class="Symfony\Bridge\Doctrine\ArgumentResolver\EntityValueResolver">
<argument type="service" id="doctrine" />
<argument type="service" id="doctrine.orm.entity_value_resolver.expression_language" on-invalid="ignore" />
<tag name="controller.argument_value_resolver" priority="110" />
</service>

<service id="doctrine.orm.entity_value_resolver.expression_language" class="Symfony\Component\ExpressionLanguage\ExpressionLanguage" />

<!-- commands -->
<service id="doctrine.cache_clear_metadata_command" class="Doctrine\Bundle\DoctrineBundle\Command\Proxy\ClearMetadataCacheDoctrineCommand">
<argument type="service" id="doctrine.orm.command.entity_manager_provider" />
Expand Down
29 changes: 29 additions & 0 deletions Tests/DependencyInjection/DoctrineExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use ReflectionMethod;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bridge\Doctrine\Messenger\DoctrineClearEntityManagerWorkerSubscriber;
use Symfony\Bridge\Doctrine\Middleware\Debug\DebugDataHolder;
use Symfony\Bridge\Doctrine\Middleware\Debug\Middleware as SfDebugMiddleware;
Expand Down Expand Up @@ -1564,6 +1565,34 @@ public function testDefinitionsToLogQueriesLoggingFalse(): void
$this->assertArrayNotHasKey('doctrine.middleware', $abstractMiddlewareDefTags);
}

/**
* @requires function \Symfony\Bridge\Doctrine\ArgumentResolver\EntityValueResolver::__construct
*/
public function testControllerResolver(): void
{
$container = $this->getContainer();
$extension = new DoctrineExtension();
$config = BundleConfigurationBuilder::createBuilderWithBaseValues()->build();
$extension->load([$config], $container);

$controllerResolver = $container->getDefinition('doctrine.orm.entity_value_resolver');

$this->assertEquals([new Reference('doctrine'), new Reference('doctrine.orm.entity_value_resolver.expression_language', $container::IGNORE_ON_INVALID_REFERENCE)], $controllerResolver->getArguments());

$container = $this->getContainer();

$config['orm']['controller_resolver'] = [
'enabled' => false,
'auto_mapping' => false,
'evict_cache' => true,
];
$extension->load([$config], $container);

$container->setDefinition('controller_resolver_defaults', $container->getDefinition('doctrine.orm.entity_value_resolver')->getArgument(2))->setPublic(true);
$container->compile();
$this->assertEquals(new MapEntity(null, null, null, [], null, null, null, true, true), $container->get('controller_resolver_defaults'));
}

// phpcs:enable

/** @param list<string> $bundles */
Expand Down
1 change: 1 addition & 0 deletions psalm.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
<errorLevel type="suppress">
<!-- We use the "Foo" namespace in unit tests. We are aware that those classes don't exist. -->
<referencedClass name="Foo\*"/>
<referencedClass name="Symfony\Bridge\Doctrine\Attribute\MapEntity"/>
<referencedClass name="Symfony\Component\VarExporter\LazyObjectInterface"/>
</errorLevel>
</UndefinedClass>
Expand Down

0 comments on commit 71d6411

Please sign in to comment.