|  | 
| 4 | 4 | 
 | 
| 5 | 5 | namespace Doctrine\Tests\ORM\Mapping; | 
| 6 | 6 | 
 | 
|  | 7 | +use Doctrine\ORM\Mapping\DefaultNamingStrategy; | 
| 7 | 8 | use Doctrine\ORM\Mapping\JoinColumnMapping; | 
| 8 | 9 | use Doctrine\ORM\Mapping\ManyToOneAssociationMapping; | 
|  | 10 | +use PHPUnit\Framework\Attributes\DataProvider; | 
| 9 | 11 | use PHPUnit\Framework\TestCase; | 
| 10 | 12 | 
 | 
| 11 | 13 | use function assert; | 
| @@ -35,4 +37,60 @@ public function testItSurvivesSerialization(): void | 
| 35 | 37 |         self::assertSame(['foo' => 'bar'], $resurrectedMapping->sourceToTargetKeyColumns); | 
| 36 | 38 |         self::assertSame(['bar' => 'foo'], $resurrectedMapping->targetToSourceKeyColumns); | 
| 37 | 39 |     } | 
|  | 40 | + | 
|  | 41 | +    #[DataProvider('mappingsProvider')] | 
|  | 42 | +    public function testNullableDefaults(bool $expectedValue, ManyToOneAssociationMapping $mapping): void | 
|  | 43 | +    { | 
|  | 44 | +        foreach ($mapping->joinColumns as $joinColumn) { | 
|  | 45 | +            self::assertSame($expectedValue, $joinColumn->nullable); | 
|  | 46 | +        } | 
|  | 47 | +    } | 
|  | 48 | + | 
|  | 49 | +    /** @return iterable<string, array{bool, ManyToOneAssociationMapping}> */ | 
|  | 50 | +    public static function mappingsProvider(): iterable | 
|  | 51 | +    { | 
|  | 52 | +        $namingStrategy = new DefaultNamingStrategy(); | 
|  | 53 | + | 
|  | 54 | +        yield 'not part of the identifier' => [ | 
|  | 55 | +            true, | 
|  | 56 | +            ManyToOneAssociationMapping::fromMappingArrayAndName([ | 
|  | 57 | +                'fieldName' => 'foo', | 
|  | 58 | +                'sourceEntity' => self::class, | 
|  | 59 | +                'targetEntity' => self::class, | 
|  | 60 | +                'isOwningSide' => true, | 
|  | 61 | +                'joinColumns' => [ | 
|  | 62 | +                    ['name' => 'foo_id', 'referencedColumnName' => 'id'], | 
|  | 63 | +                ], | 
|  | 64 | +                'id' => false, | 
|  | 65 | +            ], $namingStrategy, self::class, null, false), | 
|  | 66 | +        ]; | 
|  | 67 | + | 
|  | 68 | +        yield 'part of the identifier' => [ | 
|  | 69 | +            false, | 
|  | 70 | +            ManyToOneAssociationMapping::fromMappingArrayAndName([ | 
|  | 71 | +                'fieldName' => 'foo', | 
|  | 72 | +                'sourceEntity' => self::class, | 
|  | 73 | +                'targetEntity' => self::class, | 
|  | 74 | +                'isOwningSide' => true, | 
|  | 75 | +                'joinColumns' => [ | 
|  | 76 | +                    ['name' => 'foo_id', 'referencedColumnName' => 'id'], | 
|  | 77 | +                ], | 
|  | 78 | +                'id' => true, | 
|  | 79 | +            ], $namingStrategy, self::class, null, false), | 
|  | 80 | +        ]; | 
|  | 81 | + | 
|  | 82 | +        yield 'part of the identifier, but explicitly marked as nullable' => [ | 
|  | 83 | +            false, // user's intent is ignored at the ORM level | 
|  | 84 | +            ManyToOneAssociationMapping::fromMappingArrayAndName([ | 
|  | 85 | +                'fieldName' => 'foo', | 
|  | 86 | +                'sourceEntity' => self::class, | 
|  | 87 | +                'targetEntity' => self::class, | 
|  | 88 | +                'isOwningSide' => true, | 
|  | 89 | +                'joinColumns' => [ | 
|  | 90 | +                    ['name' => 'foo_id', 'referencedColumnName' => 'id', 'nullable' => true], | 
|  | 91 | +                ], | 
|  | 92 | +                'id' => true, | 
|  | 93 | +            ], $namingStrategy, self::class, null, false), | 
|  | 94 | +        ]; | 
|  | 95 | +    } | 
| 38 | 96 | } | 
0 commit comments