From 47e7a406a8762b3cf67a08d8e04dcab133888d27 Mon Sep 17 00:00:00 2001 From: Delacry <45132928+delacry@users.noreply.github.com> Date: Fri, 3 Apr 2026 16:32:26 +0200 Subject: [PATCH] Add support for inferNullabilityFromPHPType mapping option --- composer.json | 2 +- src/DI/Helpers/MappingHelper.php | 14 +++++-- src/DI/OrmExtension.php | 3 +- src/DI/Pass/ManagerPass.php | 12 +++++- tests/Cases/DI/OrmExtension.mapping.phpt | 49 ++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index f55171dd3..f70d126b4 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ ], "require": { "php": ">=8.2", - "doctrine/orm": "^3.3.0", + "doctrine/orm": "3.7.x-dev#5e9e57c49ccb36b7591e348cdffde3816558dd9a", "nette/di": "^3.1.2", "nettrine/dbal": "^0.10.2 || ^0.11.0", "psr/cache": "^3.0.0", diff --git a/src/DI/Helpers/MappingHelper.php b/src/DI/Helpers/MappingHelper.php index bb8f585e6..35b4f056c 100644 --- a/src/DI/Helpers/MappingHelper.php +++ b/src/DI/Helpers/MappingHelper.php @@ -25,7 +25,7 @@ public static function of(CompilerExtension $extension): self return new self($extension); } - public function addAttribute(string $connection, string $namespace, string $path): self + public function addAttribute(string $connection, string $namespace, string $path, bool $inferNullabilityFromPHPType = false): self { if (!is_dir($path)) { throw new LogicalException(sprintf('Given mapping path "%s" does not exist', $path)); @@ -33,14 +33,17 @@ public function addAttribute(string $connection, string $namespace, string $path $chainDriver = $this->getChainDriver($connection); $chainDriver->addSetup('addDriver', [ - new Statement(AttributeDriver::class, [[$path]]), + new Statement(AttributeDriver::class, [ + [$path], + 'inferNullabilityFromPHPType' => $inferNullabilityFromPHPType, + ]), $namespace, ]); return $this; } - public function addXml(string $connection, string $namespace, string $path): self + public function addXml(string $connection, string $namespace, string $path, bool $inferNullabilityFromPHPType = false): self { if (!is_dir($path)) { throw new LogicalException(sprintf('Given mapping path "%s" does not exist', $path)); @@ -48,7 +51,10 @@ public function addXml(string $connection, string $namespace, string $path): sel $chainDriver = $this->getChainDriver($connection); $chainDriver->addSetup('addDriver', [ - new Statement(SimplifiedXmlDriver::class, [[$path => $namespace]]), + new Statement(SimplifiedXmlDriver::class, [ + [$path => $namespace], + 'inferNullabilityFromPHPType' => $inferNullabilityFromPHPType, + ]), $namespace, ]); diff --git a/src/DI/OrmExtension.php b/src/DI/OrmExtension.php index 9da67de1f..b37aa733f 100644 --- a/src/DI/OrmExtension.php +++ b/src/DI/OrmExtension.php @@ -42,7 +42,7 @@ * repositoryFactory: string|Statement|null, * defaultQueryHints: array, * filters: array, - * mapping: array, + * mapping: array, * defaultCache: string|Statement|null, * queryCache: string|Statement|null, * resultCache: string|Statement|null, @@ -128,6 +128,7 @@ public function getConfigSchema(): Schema 'type' => Expect::anyOf('attributes', 'xml')->default('attributes'), 'directories' => Expect::listOf(Expect::string())->min(1)->required(), 'namespace' => Expect::string()->required(), + 'inferNullabilityFromPHPType' => Expect::bool()->default(false), 'options' => Expect::structure([ 'fileExtension' => Expect::string()->default('.orm.xml'), 'xsdValidation' => Expect::bool()->default(true), diff --git a/src/DI/Pass/ManagerPass.php b/src/DI/Pass/ManagerPass.php index 77f5f18a2..2ff01b7f3 100644 --- a/src/DI/Pass/ManagerPass.php +++ b/src/DI/Pass/ManagerPass.php @@ -272,12 +272,20 @@ public function loadManagerConfiguration(string $managerName, mixed $managerConf foreach ($managerConfig->mapping as $mapping) { if ($mapping->type === 'attributes') { $mappingDriver->addSetup('addDriver', [ - new Statement(AttributeDriver::class, [array_values($mapping->directories)]), + new Statement(AttributeDriver::class, [ + 'paths' => array_values($mapping->directories), + 'inferNullabilityFromPHPType' => $mapping->inferNullabilityFromPHPType, + ]), $mapping->namespace, ]); } elseif ($mapping->type === 'xml') { $mappingDriver->addSetup('addDriver', [ - new Statement(SimplifiedXmlDriver::class, [array_combine($mapping->directories, array_fill(0, count($mapping->directories), $mapping->namespace)), $mapping->options->fileExtension, $mapping->options->xsdValidation]), + new Statement(SimplifiedXmlDriver::class, [ + array_combine($mapping->directories, array_fill(0, count($mapping->directories), $mapping->namespace)), + $mapping->options->fileExtension, + $mapping->options->xsdValidation, + $mapping->inferNullabilityFromPHPType, + ]), $mapping->namespace, ]); } else { diff --git a/tests/Cases/DI/OrmExtension.mapping.phpt b/tests/Cases/DI/OrmExtension.mapping.phpt index 409bbd0ae..7201231bf 100644 --- a/tests/Cases/DI/OrmExtension.mapping.phpt +++ b/tests/Cases/DI/OrmExtension.mapping.phpt @@ -62,6 +62,55 @@ Toolkit::test(function (): void { Assert::count(2, $attributeDriver->getPaths()); }); +// Driver: attributes with inferNullabilityFromPHPType +Toolkit::test(function (): void { + $container = ContainerBuilder::of() + ->withCompiler(function (Compiler $compiler): void { + $compiler->addExtension('nettrine.dbal', new DbalExtension()); + $compiler->addExtension('nettrine.orm', new OrmExtension()); + $compiler->addConfig([ + 'parameters' => [ + 'tempDir' => Tests::TEMP_PATH, + 'fixturesDir' => Tests::FIXTURES_PATH, + ], + ]); + $compiler->addConfig(Neonkit::load( + <<<'NEON' + nettrine.dbal: + connections: + default: + driver: pdo_sqlite + password: test + user: test + path: ":memory:" + nettrine.orm: + managers: + default: + connection: default + mapping: + App: + type: attributes + directories: [%fixturesDir%/Entity, %fixturesDir%/../Toolkit] + namespace: Tests\Fixtures\Dummy + inferNullabilityFromPHPType: true + NEON + )); + }) + ->build(); + + /** @var MappingDriverChain $driver */ + $driver = $container->getService('nettrine.orm.managers.default.mappingDriver'); + Assert::count(1, $driver->getDrivers()); + + /** @var AttributeDriver $attributeDriver */ + $attributeDriver = current($driver->getDrivers()); + + Assert::type(AttributeDriver::class, $attributeDriver); + + $r = new ReflectionClass($attributeDriver); + Assert::true($r->getProperty('inferNullabilityFromPHPType')->getValue($attributeDriver)); +}); + // Driver: xml Toolkit::test(function (): void { $container = ContainerBuilder::of()