Skip to content

Commit d3a0cdb

Browse files
authored
feature #1439 [make:*] improve support for ORM 3.x / DBAL 4.x
1 parent 5aaf82c commit d3a0cdb

29 files changed

+578
-163
lines changed

.github/workflows/ci-linux.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ on:
1111
env:
1212
PHPUNIT_FLAGS: "-v"
1313
SYMFONY_PHPUNIT_DIR: "$HOME/symfony-bridge/.phpunit"
14+
MAKER_SKIP_MERCURE_TEST: 1
1415

1516
jobs:
1617
coding-standards:

composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"require-dev": {
3030
"composer/semver": "^3.0",
3131
"doctrine/doctrine-bundle": "^2.5.0",
32-
"doctrine/orm": "^2.10.0",
32+
"doctrine/orm": "^2.15|^3",
3333
"symfony/http-client": "^6.4|^7.0",
3434
"symfony/phpunit-bridge": "^6.4.1|^7.0",
3535
"symfony/security-core": "^6.4|^7.0",
@@ -41,8 +41,8 @@
4141
"sort-packages": true
4242
},
4343
"conflict": {
44-
"doctrine/orm": "<2.10",
45-
"doctrine/doctrine-bundle": "<2.4"
44+
"doctrine/orm": "<2.15",
45+
"doctrine/doctrine-bundle": "<2.10"
4646
},
4747
"autoload": {
4848
"psr-4": { "Symfony\\Bundle\\MakerBundle\\": "src/" }

phpunit.xml.dist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
<env name="SYMFONY_PHPUNIT_VERSION" value="9.6" />
2020
<env name="MAKER_SKIP_MERCURE_TEST" value="false"/>
2121
<env name="MAKER_SKIP_PANTHER_TEST" value="false" />
22+
<!-- Overrides process timeout when step debugging -->
23+
<!-- <env name="MAKER_PROCESS_TIMEOUT" value="null" /> -->
2224
</php>
2325

2426
<testsuites>

src/Doctrine/DoctrineHelper.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
1818
use Doctrine\ORM\Mapping\MappingException as ORMMappingException;
1919
use Doctrine\ORM\Mapping\NamingStrategy;
20-
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
2120
use Doctrine\Persistence\ManagerRegistry;
2221
use Doctrine\Persistence\Mapping\AbstractClassMetadataFactory;
2322
use Doctrine\Persistence\Mapping\ClassMetadata;
2423
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
2524
use Doctrine\Persistence\Mapping\Driver\MappingDriverChain;
2625
use Doctrine\Persistence\Mapping\MappingException as PersistenceMappingException;
26+
use Doctrine\Persistence\Mapping\StaticReflectionService;
2727
use Symfony\Bundle\MakerBundle\Util\ClassNameDetails;
2828
use Symfony\Component\Uid\Ulid;
2929
use Symfony\Component\Uid\Uuid;
@@ -174,8 +174,8 @@ public function getMetadata(string $classOrNamespace = null, bool $disconnected
174174
$loaded = $this->isInstanceOf($cmf, AbstractClassMetadataFactory::class) ? $cmf->getLoadedMetadata() : [];
175175
}
176176

177-
$cmf = new DisconnectedClassMetadataFactory();
178-
$cmf->setEntityManager($em);
177+
// Set the reflection service that was used in the now removed DisconnectedClassMetadataFactory::class
178+
$cmf->setReflectionService(new StaticReflectionService());
179179

180180
foreach ($loaded as $m) {
181181
$cmf->setMetadataFor($m->getName(), $m);

src/Doctrine/EntityRegenerator.php

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
namespace Symfony\Bundle\MakerBundle\Doctrine;
1313

1414
use Doctrine\ORM\Mapping\ClassMetadata;
15+
use Doctrine\ORM\Mapping\EmbeddedClassMapping;
1516
use Doctrine\ORM\Mapping\MappingException;
1617
use Doctrine\Persistence\Mapping\MappingException as PersistenceMappingException;
1718
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
1819
use Symfony\Bundle\MakerBundle\FileManager;
1920
use Symfony\Bundle\MakerBundle\Generator;
21+
use Symfony\Bundle\MakerBundle\Util\ClassSource\Model\ClassProperty;
2022
use Symfony\Bundle\MakerBundle\Util\ClassSourceManipulator;
2123

2224
/**
@@ -75,7 +77,8 @@ public function regenerateEntities(string $classOrNamespace): void
7577
continue;
7678
}
7779

78-
$className = $mapping['class'];
80+
/** @legacy - Remove conditional when ORM 2.x is no longer supported. */
81+
$className = ($mapping instanceof EmbeddedClassMapping) ? $mapping->class : $mapping['class'];
7982

8083
$embeddedClasses[$fieldName] = $this->getPathOfClass($className);
8184

@@ -93,7 +96,10 @@ public function regenerateEntities(string $classOrNamespace): void
9396
if (str_contains($fieldName, '.')) {
9497
[$fieldName, $embeddedFiledName] = explode('.', $fieldName);
9598

96-
$operations[$embeddedClasses[$fieldName]]->addEntityField($embeddedFiledName, $mapping);
99+
$property = ClassProperty::createFromObject($mapping);
100+
$property->propertyName = $embeddedFiledName;
101+
102+
$operations[$embeddedClasses[$fieldName]]->addEntityField($property);
97103

98104
continue;
99105
}
@@ -102,71 +108,29 @@ public function regenerateEntities(string $classOrNamespace): void
102108
continue;
103109
}
104110

105-
$manipulator->addEntityField($fieldName, $mapping);
111+
$manipulator->addEntityField(ClassProperty::createFromObject($mapping));
106112
}
107113

108-
$getIsNullable = function (array $mapping) {
109-
if (!isset($mapping['joinColumns'][0]['nullable'])) {
110-
// the default for relationships IS nullable
111-
return true;
112-
}
113-
114-
return $mapping['joinColumns'][0]['nullable'];
115-
};
116-
117114
foreach ($classMetadata->associationMappings as $fieldName => $mapping) {
118115
if (!\in_array($fieldName, $mappedFields)) {
119116
continue;
120117
}
121118

122119
switch ($mapping['type']) {
123120
case ClassMetadata::MANY_TO_ONE:
124-
$relation = (new RelationManyToOne(
125-
propertyName: $mapping['fieldName'],
126-
targetClassName: $mapping['targetEntity'],
127-
targetPropertyName: $mapping['inversedBy'],
128-
mapInverseRelation: null !== $mapping['inversedBy'],
129-
isOwning: true,
130-
isNullable: $getIsNullable($mapping),
131-
));
132-
133-
$manipulator->addManyToOneRelation($relation);
121+
$manipulator->addManyToOneRelation(RelationManyToOne::createFromObject($mapping));
134122

135123
break;
136124
case ClassMetadata::ONE_TO_MANY:
137-
$relation = (new RelationOneToMany(
138-
propertyName: $mapping['fieldName'],
139-
targetClassName: $mapping['targetEntity'],
140-
targetPropertyName: $mapping['mappedBy'],
141-
orphanRemoval: $mapping['orphanRemoval'],
142-
));
143-
144-
$manipulator->addOneToManyRelation($relation);
125+
$manipulator->addOneToManyRelation(RelationOneToMany::createFromObject($mapping));
145126

146127
break;
147128
case ClassMetadata::MANY_TO_MANY:
148-
$relation = (new RelationManyToMany(
149-
propertyName: $mapping['fieldName'],
150-
targetClassName: $mapping['targetEntity'],
151-
targetPropertyName: $mapping['mappedBy'],
152-
mapInverseRelation: $mapping['isOwningSide'] ? (null !== $mapping['inversedBy']) : true,
153-
isOwning: $mapping['isOwningSide'],
154-
));
155-
156-
$manipulator->addManyToManyRelation($relation);
129+
$manipulator->addManyToManyRelation(RelationManyToMany::createFromObject($mapping));
157130

158131
break;
159132
case ClassMetadata::ONE_TO_ONE:
160-
$relation = (new RelationOneToOne(
161-
propertyName: $mapping['fieldName'],
162-
targetClassName: $mapping['targetEntity'],
163-
targetPropertyName: $mapping['isOwningSide'] ? $mapping['inversedBy'] : $mapping['mappedBy'],
164-
mapInverseRelation: $mapping['isOwningSide'] ? (null !== $mapping['inversedBy']) : true,
165-
isOwning: $mapping['isOwningSide'],
166-
isNullable: $getIsNullable($mapping),
167-
));
168-
169-
$manipulator->addOneToOneRelation($relation);
133+
$manipulator->addOneToOneRelation(RelationOneToOne::createFromObject($mapping));
170134

171135
break;
172136
default:

src/Doctrine/RelationManyToMany.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Bundle\MakerBundle\Doctrine;
1313

14+
use Doctrine\ORM\Mapping\ManyToManyInverseSideMapping;
15+
use Doctrine\ORM\Mapping\ManyToManyOwningSideMapping;
1416
use Symfony\Bundle\MakerBundle\Str;
1517

1618
/**
@@ -27,4 +29,36 @@ public function getTargetRemoverMethodName(): string
2729
{
2830
return 'remove'.Str::asCamelCase(Str::pluralCamelCaseToSingular($this->getTargetPropertyName()));
2931
}
32+
33+
public static function createFromObject(ManyToManyInverseSideMapping|ManyToManyOwningSideMapping|array $mapping): self
34+
{
35+
/* @legacy Remove conditional when ORM 2.x is no longer supported! */
36+
if (\is_array($mapping)) {
37+
return new self(
38+
propertyName: $mapping['fieldName'],
39+
targetClassName: $mapping['targetEntity'],
40+
targetPropertyName: $mapping['mappedBy'],
41+
mapInverseRelation: !$mapping['isOwningSide'] || null !== $mapping['inversedBy'],
42+
isOwning: $mapping['isOwningSide'],
43+
);
44+
}
45+
46+
if ($mapping instanceof ManyToManyOwningSideMapping) {
47+
return new self(
48+
propertyName: $mapping->fieldName,
49+
targetClassName: $mapping->targetEntity,
50+
targetPropertyName: $mapping->inversedBy,
51+
mapInverseRelation: (null !== $mapping->inversedBy),
52+
isOwning: $mapping->isOwningSide(),
53+
);
54+
}
55+
56+
return new self(
57+
propertyName: $mapping->fieldName,
58+
targetClassName: $mapping->targetEntity,
59+
targetPropertyName: $mapping->mappedBy,
60+
mapInverseRelation: true,
61+
isOwning: $mapping->isOwningSide(),
62+
);
63+
}
3064
}

src/Doctrine/RelationManyToOne.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,34 @@
1111

1212
namespace Symfony\Bundle\MakerBundle\Doctrine;
1313

14+
use Doctrine\ORM\Mapping\ManyToOneAssociationMapping;
15+
1416
/**
1517
* @internal
1618
*/
1719
final class RelationManyToOne extends BaseRelation
1820
{
21+
public static function createFromObject(ManyToOneAssociationMapping|array $mapping): self
22+
{
23+
/* @legacy Remove conditional when ORM 2.x is no longer supported! */
24+
if (\is_array($mapping)) {
25+
return new self(
26+
propertyName: $mapping['fieldName'],
27+
targetClassName: $mapping['targetEntity'],
28+
targetPropertyName: $mapping['inversedBy'],
29+
mapInverseRelation: null !== $mapping['inversedBy'],
30+
isOwning: true,
31+
isNullable: $mapping['joinColumns'][0]['nullable'] ?? true,
32+
);
33+
}
34+
35+
return new self(
36+
propertyName: $mapping->fieldName,
37+
targetClassName: $mapping->targetEntity,
38+
targetPropertyName: $mapping->inversedBy,
39+
mapInverseRelation: null !== $mapping->inversedBy,
40+
isOwning: true,
41+
isNullable: $mapping->joinColumns[0]->nullable ?? true,
42+
);
43+
}
1944
}

src/Doctrine/RelationOneToMany.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Bundle\MakerBundle\Doctrine;
1313

14+
use Doctrine\ORM\Mapping\OneToManyAssociationMapping;
1415
use Symfony\Bundle\MakerBundle\Str;
1516

1617
/**
@@ -32,4 +33,24 @@ public function isMapInverseRelation(): bool
3233
{
3334
throw new \Exception('OneToMany IS the inverse side!');
3435
}
36+
37+
public static function createFromObject(OneToManyAssociationMapping|array $mapping): self
38+
{
39+
/* @legacy Remove conditional when ORM 2.x is no longer supported! */
40+
if (\is_array($mapping)) {
41+
return new self(
42+
propertyName: $mapping['fieldName'],
43+
targetClassName: $mapping['targetEntity'],
44+
targetPropertyName: $mapping['mappedBy'],
45+
orphanRemoval: $mapping['orphanRemoval'],
46+
);
47+
}
48+
49+
return new self(
50+
propertyName: $mapping->fieldName,
51+
targetClassName: $mapping->targetEntity,
52+
targetPropertyName: $mapping->mappedBy,
53+
orphanRemoval: $mapping->orphanRemoval,
54+
);
55+
}
3556
}

src/Doctrine/RelationOneToOne.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Bundle\MakerBundle\Doctrine;
1313

14+
use Doctrine\ORM\Mapping\OneToOneInverseSideMapping;
15+
use Doctrine\ORM\Mapping\OneToOneOwningSideMapping;
1416
use Symfony\Bundle\MakerBundle\Str;
1517

1618
/**
@@ -27,4 +29,39 @@ public function getTargetSetterMethodName(): string
2729
{
2830
return 'set'.Str::asCamelCase($this->getTargetPropertyName());
2931
}
32+
33+
public static function createFromObject(OneToOneInverseSideMapping|OneToOneOwningSideMapping|array $mapping): self
34+
{
35+
/* @legacy Remove conditional when ORM 2.x is no longer supported! */
36+
if (\is_array($mapping)) {
37+
return new self(
38+
propertyName: $mapping['fieldName'],
39+
targetClassName: $mapping['targetEntity'],
40+
targetPropertyName: $mapping['isOwningSide'] ? $mapping['inversedBy'] : $mapping['mappedBy'],
41+
mapInverseRelation: !$mapping['isOwningSide'] || null !== $mapping['inversedBy'],
42+
isOwning: $mapping['isOwningSide'],
43+
isNullable: $mapping['joinColumns'][0]['nullable'] ?? true,
44+
);
45+
}
46+
47+
if ($mapping instanceof OneToOneOwningSideMapping) {
48+
return new self(
49+
propertyName: $mapping->fieldName,
50+
targetClassName: $mapping->targetEntity,
51+
targetPropertyName: $mapping->inversedBy,
52+
mapInverseRelation: (null !== $mapping->inversedBy),
53+
isOwning: true,
54+
isNullable: $mapping->joinColumns[0]->nullable ?? true,
55+
);
56+
}
57+
58+
return new self(
59+
propertyName: $mapping->fieldName,
60+
targetClassName: $mapping->targetEntity,
61+
targetPropertyName: $mapping->mappedBy,
62+
mapInverseRelation: true,
63+
isOwning: false,
64+
isNullable: $mapping->joinColumns[0]->nullable ?? true,
65+
);
66+
}
3067
}

0 commit comments

Comments
 (0)