Skip to content

Commit

Permalink
feature #1439 [make:*] improve support for ORM 3.x / DBAL 4.x
Browse files Browse the repository at this point in the history
  • Loading branch information
jrushlow authored Feb 6, 2024
1 parent 5aaf82c commit d3a0cdb
Show file tree
Hide file tree
Showing 29 changed files with 578 additions and 163 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci-linux.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
env:
PHPUNIT_FLAGS: "-v"
SYMFONY_PHPUNIT_DIR: "$HOME/symfony-bridge/.phpunit"
MAKER_SKIP_MERCURE_TEST: 1

jobs:
coding-standards:
Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"require-dev": {
"composer/semver": "^3.0",
"doctrine/doctrine-bundle": "^2.5.0",
"doctrine/orm": "^2.10.0",
"doctrine/orm": "^2.15|^3",
"symfony/http-client": "^6.4|^7.0",
"symfony/phpunit-bridge": "^6.4.1|^7.0",
"symfony/security-core": "^6.4|^7.0",
Expand All @@ -41,8 +41,8 @@
"sort-packages": true
},
"conflict": {
"doctrine/orm": "<2.10",
"doctrine/doctrine-bundle": "<2.4"
"doctrine/orm": "<2.15",
"doctrine/doctrine-bundle": "<2.10"
},
"autoload": {
"psr-4": { "Symfony\\Bundle\\MakerBundle\\": "src/" }
Expand Down
2 changes: 2 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
<env name="SYMFONY_PHPUNIT_VERSION" value="9.6" />
<env name="MAKER_SKIP_MERCURE_TEST" value="false"/>
<env name="MAKER_SKIP_PANTHER_TEST" value="false" />
<!-- Overrides process timeout when step debugging -->
<!-- <env name="MAKER_PROCESS_TIMEOUT" value="null" /> -->
</php>

<testsuites>
Expand Down
6 changes: 3 additions & 3 deletions src/Doctrine/DoctrineHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\ORM\Mapping\MappingException as ORMMappingException;
use Doctrine\ORM\Mapping\NamingStrategy;
use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\Mapping\AbstractClassMetadataFactory;
use Doctrine\Persistence\Mapping\ClassMetadata;
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
use Doctrine\Persistence\Mapping\Driver\MappingDriverChain;
use Doctrine\Persistence\Mapping\MappingException as PersistenceMappingException;
use Doctrine\Persistence\Mapping\StaticReflectionService;
use Symfony\Bundle\MakerBundle\Util\ClassNameDetails;
use Symfony\Component\Uid\Ulid;
use Symfony\Component\Uid\Uuid;
Expand Down Expand Up @@ -174,8 +174,8 @@ public function getMetadata(string $classOrNamespace = null, bool $disconnected
$loaded = $this->isInstanceOf($cmf, AbstractClassMetadataFactory::class) ? $cmf->getLoadedMetadata() : [];
}

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

foreach ($loaded as $m) {
$cmf->setMetadataFor($m->getName(), $m);
Expand Down
62 changes: 13 additions & 49 deletions src/Doctrine/EntityRegenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
namespace Symfony\Bundle\MakerBundle\Doctrine;

use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\EmbeddedClassMapping;
use Doctrine\ORM\Mapping\MappingException;
use Doctrine\Persistence\Mapping\MappingException as PersistenceMappingException;
use Symfony\Bundle\MakerBundle\Exception\RuntimeCommandException;
use Symfony\Bundle\MakerBundle\FileManager;
use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Bundle\MakerBundle\Util\ClassSource\Model\ClassProperty;
use Symfony\Bundle\MakerBundle\Util\ClassSourceManipulator;

/**
Expand Down Expand Up @@ -75,7 +77,8 @@ public function regenerateEntities(string $classOrNamespace): void
continue;
}

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

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

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

$operations[$embeddedClasses[$fieldName]]->addEntityField($embeddedFiledName, $mapping);
$property = ClassProperty::createFromObject($mapping);
$property->propertyName = $embeddedFiledName;

$operations[$embeddedClasses[$fieldName]]->addEntityField($property);

continue;
}
Expand All @@ -102,71 +108,29 @@ public function regenerateEntities(string $classOrNamespace): void
continue;
}

$manipulator->addEntityField($fieldName, $mapping);
$manipulator->addEntityField(ClassProperty::createFromObject($mapping));
}

$getIsNullable = function (array $mapping) {
if (!isset($mapping['joinColumns'][0]['nullable'])) {
// the default for relationships IS nullable
return true;
}

return $mapping['joinColumns'][0]['nullable'];
};

foreach ($classMetadata->associationMappings as $fieldName => $mapping) {
if (!\in_array($fieldName, $mappedFields)) {
continue;
}

switch ($mapping['type']) {
case ClassMetadata::MANY_TO_ONE:
$relation = (new RelationManyToOne(
propertyName: $mapping['fieldName'],
targetClassName: $mapping['targetEntity'],
targetPropertyName: $mapping['inversedBy'],
mapInverseRelation: null !== $mapping['inversedBy'],
isOwning: true,
isNullable: $getIsNullable($mapping),
));

$manipulator->addManyToOneRelation($relation);
$manipulator->addManyToOneRelation(RelationManyToOne::createFromObject($mapping));

break;
case ClassMetadata::ONE_TO_MANY:
$relation = (new RelationOneToMany(
propertyName: $mapping['fieldName'],
targetClassName: $mapping['targetEntity'],
targetPropertyName: $mapping['mappedBy'],
orphanRemoval: $mapping['orphanRemoval'],
));

$manipulator->addOneToManyRelation($relation);
$manipulator->addOneToManyRelation(RelationOneToMany::createFromObject($mapping));

break;
case ClassMetadata::MANY_TO_MANY:
$relation = (new RelationManyToMany(
propertyName: $mapping['fieldName'],
targetClassName: $mapping['targetEntity'],
targetPropertyName: $mapping['mappedBy'],
mapInverseRelation: $mapping['isOwningSide'] ? (null !== $mapping['inversedBy']) : true,
isOwning: $mapping['isOwningSide'],
));

$manipulator->addManyToManyRelation($relation);
$manipulator->addManyToManyRelation(RelationManyToMany::createFromObject($mapping));

break;
case ClassMetadata::ONE_TO_ONE:
$relation = (new RelationOneToOne(
propertyName: $mapping['fieldName'],
targetClassName: $mapping['targetEntity'],
targetPropertyName: $mapping['isOwningSide'] ? $mapping['inversedBy'] : $mapping['mappedBy'],
mapInverseRelation: $mapping['isOwningSide'] ? (null !== $mapping['inversedBy']) : true,
isOwning: $mapping['isOwningSide'],
isNullable: $getIsNullable($mapping),
));

$manipulator->addOneToOneRelation($relation);
$manipulator->addOneToOneRelation(RelationOneToOne::createFromObject($mapping));

break;
default:
Expand Down
34 changes: 34 additions & 0 deletions src/Doctrine/RelationManyToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

namespace Symfony\Bundle\MakerBundle\Doctrine;

use Doctrine\ORM\Mapping\ManyToManyInverseSideMapping;
use Doctrine\ORM\Mapping\ManyToManyOwningSideMapping;
use Symfony\Bundle\MakerBundle\Str;

/**
Expand All @@ -27,4 +29,36 @@ public function getTargetRemoverMethodName(): string
{
return 'remove'.Str::asCamelCase(Str::pluralCamelCaseToSingular($this->getTargetPropertyName()));
}

public static function createFromObject(ManyToManyInverseSideMapping|ManyToManyOwningSideMapping|array $mapping): self
{
/* @legacy Remove conditional when ORM 2.x is no longer supported! */
if (\is_array($mapping)) {
return new self(
propertyName: $mapping['fieldName'],
targetClassName: $mapping['targetEntity'],
targetPropertyName: $mapping['mappedBy'],
mapInverseRelation: !$mapping['isOwningSide'] || null !== $mapping['inversedBy'],
isOwning: $mapping['isOwningSide'],
);
}

if ($mapping instanceof ManyToManyOwningSideMapping) {
return new self(
propertyName: $mapping->fieldName,
targetClassName: $mapping->targetEntity,
targetPropertyName: $mapping->inversedBy,
mapInverseRelation: (null !== $mapping->inversedBy),
isOwning: $mapping->isOwningSide(),
);
}

return new self(
propertyName: $mapping->fieldName,
targetClassName: $mapping->targetEntity,
targetPropertyName: $mapping->mappedBy,
mapInverseRelation: true,
isOwning: $mapping->isOwningSide(),
);
}
}
25 changes: 25 additions & 0 deletions src/Doctrine/RelationManyToOne.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,34 @@

namespace Symfony\Bundle\MakerBundle\Doctrine;

use Doctrine\ORM\Mapping\ManyToOneAssociationMapping;

/**
* @internal
*/
final class RelationManyToOne extends BaseRelation
{
public static function createFromObject(ManyToOneAssociationMapping|array $mapping): self
{
/* @legacy Remove conditional when ORM 2.x is no longer supported! */
if (\is_array($mapping)) {
return new self(
propertyName: $mapping['fieldName'],
targetClassName: $mapping['targetEntity'],
targetPropertyName: $mapping['inversedBy'],
mapInverseRelation: null !== $mapping['inversedBy'],
isOwning: true,
isNullable: $mapping['joinColumns'][0]['nullable'] ?? true,
);
}

return new self(
propertyName: $mapping->fieldName,
targetClassName: $mapping->targetEntity,
targetPropertyName: $mapping->inversedBy,
mapInverseRelation: null !== $mapping->inversedBy,
isOwning: true,
isNullable: $mapping->joinColumns[0]->nullable ?? true,
);
}
}
21 changes: 21 additions & 0 deletions src/Doctrine/RelationOneToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Bundle\MakerBundle\Doctrine;

use Doctrine\ORM\Mapping\OneToManyAssociationMapping;
use Symfony\Bundle\MakerBundle\Str;

/**
Expand All @@ -32,4 +33,24 @@ public function isMapInverseRelation(): bool
{
throw new \Exception('OneToMany IS the inverse side!');
}

public static function createFromObject(OneToManyAssociationMapping|array $mapping): self
{
/* @legacy Remove conditional when ORM 2.x is no longer supported! */
if (\is_array($mapping)) {
return new self(
propertyName: $mapping['fieldName'],
targetClassName: $mapping['targetEntity'],
targetPropertyName: $mapping['mappedBy'],
orphanRemoval: $mapping['orphanRemoval'],
);
}

return new self(
propertyName: $mapping->fieldName,
targetClassName: $mapping->targetEntity,
targetPropertyName: $mapping->mappedBy,
orphanRemoval: $mapping->orphanRemoval,
);
}
}
37 changes: 37 additions & 0 deletions src/Doctrine/RelationOneToOne.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

namespace Symfony\Bundle\MakerBundle\Doctrine;

use Doctrine\ORM\Mapping\OneToOneInverseSideMapping;
use Doctrine\ORM\Mapping\OneToOneOwningSideMapping;
use Symfony\Bundle\MakerBundle\Str;

/**
Expand All @@ -27,4 +29,39 @@ public function getTargetSetterMethodName(): string
{
return 'set'.Str::asCamelCase($this->getTargetPropertyName());
}

public static function createFromObject(OneToOneInverseSideMapping|OneToOneOwningSideMapping|array $mapping): self
{
/* @legacy Remove conditional when ORM 2.x is no longer supported! */
if (\is_array($mapping)) {
return new self(
propertyName: $mapping['fieldName'],
targetClassName: $mapping['targetEntity'],
targetPropertyName: $mapping['isOwningSide'] ? $mapping['inversedBy'] : $mapping['mappedBy'],
mapInverseRelation: !$mapping['isOwningSide'] || null !== $mapping['inversedBy'],
isOwning: $mapping['isOwningSide'],
isNullable: $mapping['joinColumns'][0]['nullable'] ?? true,
);
}

if ($mapping instanceof OneToOneOwningSideMapping) {
return new self(
propertyName: $mapping->fieldName,
targetClassName: $mapping->targetEntity,
targetPropertyName: $mapping->inversedBy,
mapInverseRelation: (null !== $mapping->inversedBy),
isOwning: true,
isNullable: $mapping->joinColumns[0]->nullable ?? true,
);
}

return new self(
propertyName: $mapping->fieldName,
targetClassName: $mapping->targetEntity,
targetPropertyName: $mapping->mappedBy,
mapInverseRelation: true,
isOwning: false,
isNullable: $mapping->joinColumns[0]->nullable ?? true,
);
}
}
Loading

0 comments on commit d3a0cdb

Please sign in to comment.