Skip to content

Commit

Permalink
Merge branch '6.4' into 7.0
Browse files Browse the repository at this point in the history
* 6.4:
  forward-compatibility with field mappings in Doctrine ORM 4
  • Loading branch information
fabpot committed Feb 4, 2024
2 parents fbea8d2 + cfd456b commit aded7ef
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 22 deletions.
14 changes: 12 additions & 2 deletions Form/DoctrineOrmTypeGuesser.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\JoinColumnMapping;
use Doctrine\ORM\Mapping\MappingException as LegacyMappingException;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\Mapping\MappingException;
Expand Down Expand Up @@ -110,13 +111,13 @@ public function guessRequired(string $class, string $property): ?ValueGuess
if ($classMetadata->isAssociationWithSingleJoinColumn($property)) {
$mapping = $classMetadata->getAssociationMapping($property);

if (!isset($mapping['joinColumns'][0]['nullable'])) {
if (null === self::getMappingValue($mapping['joinColumns'][0], 'nullable')) {
// The "nullable" option defaults to true, in that case the
// field should not be required.
return new ValueGuess(false, Guess::HIGH_CONFIDENCE);
}

return new ValueGuess(!$mapping['joinColumns'][0]['nullable'], Guess::HIGH_CONFIDENCE);
return new ValueGuess(!self::getMappingValue($mapping['joinColumns'][0], 'nullable'), Guess::HIGH_CONFIDENCE);
}

return null;
Expand Down Expand Up @@ -190,4 +191,13 @@ private static function getRealClass(string $class): string

return substr($class, $pos + Proxy::MARKER_LENGTH + 2);
}

private static function getMappingValue(array|JoinColumnMapping $mapping, string $key): mixed
{
if ($mapping instanceof JoinColumnMapping) {
return $mapping->$key;
}

return $mapping[$key] ?? null;
}
}
34 changes: 23 additions & 11 deletions PropertyInfo/DoctrineExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\AssociationMapping;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\EmbeddedClassMapping;
use Doctrine\ORM\Mapping\FieldMapping;
use Doctrine\ORM\Mapping\JoinColumnMapping;
use Doctrine\ORM\Mapping\MappingException as OrmMappingException;
use Doctrine\Persistence\Mapping\MappingException;
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
Expand Down Expand Up @@ -78,20 +81,20 @@ public function getTypes(string $class, string $property, array $context = []):
if ($metadata instanceof ClassMetadata) {
$associationMapping = $metadata->getAssociationMapping($property);

if (isset($associationMapping['indexBy'])) {
$subMetadata = $this->entityManager->getClassMetadata($associationMapping['targetEntity']);
if (self::getMappingValue($associationMapping, 'indexBy')) {
$subMetadata = $this->entityManager->getClassMetadata(self::getMappingValue($associationMapping, 'targetEntity'));

// Check if indexBy value is a property
$fieldName = $associationMapping['indexBy'];
$fieldName = self::getMappingValue($associationMapping, 'indexBy');
if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) {
$fieldName = $subMetadata->getFieldForColumn($associationMapping['indexBy']);
$fieldName = $subMetadata->getFieldForColumn(self::getMappingValue($associationMapping, 'indexBy'));
// Not a property, maybe a column name?
if (null === ($typeOfField = $subMetadata->getTypeOfField($fieldName))) {
// Maybe the column name is the association join column?
$associationMapping = $subMetadata->getAssociationMapping($fieldName);

$indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($fieldName);
$subMetadata = $this->entityManager->getClassMetadata($associationMapping['targetEntity']);
$subMetadata = $this->entityManager->getClassMetadata(self::getMappingValue($associationMapping, 'targetEntity'));

// Not a property, maybe a column name?
if (null === ($typeOfField = $subMetadata->getTypeOfField($indexProperty))) {
Expand All @@ -118,7 +121,7 @@ public function getTypes(string $class, string $property, array $context = []):
}

if ($metadata instanceof ClassMetadata && isset($metadata->embeddedClasses[$property])) {
return [new Type(Type::BUILTIN_TYPE_OBJECT, false, $metadata->embeddedClasses[$property]['class'])];
return [new Type(Type::BUILTIN_TYPE_OBJECT, false, self::getMappingValue($metadata->embeddedClasses[$property], 'class'))];
}

if ($metadata->hasField($property)) {
Expand All @@ -130,7 +133,7 @@ public function getTypes(string $class, string $property, array $context = []):

$nullable = $metadata instanceof ClassMetadata && $metadata->isNullable($property);
$enumType = null;
if (null !== $enumClass = $metadata->getFieldMapping($property)['enumType'] ?? null) {
if (null !== $enumClass = self::getMappingValue($metadata->getFieldMapping($property), 'enumType') ?? null) {
$enumType = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $enumClass);
}

Expand Down Expand Up @@ -220,17 +223,17 @@ private function getMetadata(string $class): ?ClassMetadata
*/
private function isAssociationNullable(array|AssociationMapping $associationMapping): bool
{
if (isset($associationMapping['id']) && $associationMapping['id']) {
if (self::getMappingValue($associationMapping, 'id')) {
return false;
}

if (!isset($associationMapping['joinColumns'])) {
if (!self::getMappingValue($associationMapping, 'joinColumns')) {
return true;
}

$joinColumns = $associationMapping['joinColumns'];
$joinColumns = self::getMappingValue($associationMapping, 'joinColumns');
foreach ($joinColumns as $joinColumn) {
if (isset($joinColumn['nullable']) && !$joinColumn['nullable']) {
if (false === self::getMappingValue($joinColumn, 'nullable')) {
return false;
}
}
Expand Down Expand Up @@ -272,4 +275,13 @@ private function getPhpType(string $doctrineType): ?string
default => null,
};
}

private static function getMappingValue(array|AssociationMapping|EmbeddedClassMapping|FieldMapping|JoinColumnMapping $mapping, string $key): mixed
{
if ($mapping instanceof AssociationMapping || $mapping instanceof EmbeddedClassMapping || $mapping instanceof FieldMapping || $mapping instanceof JoinColumnMapping) {
return $mapping->$key;
}

return $mapping[$key] ?? null;
}
}
28 changes: 19 additions & 9 deletions Validator/DoctrineLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata as OrmClassMetadata;
use Doctrine\ORM\Mapping\FieldMapping;
use Doctrine\ORM\Mapping\MappingException as OrmMappingException;
use Doctrine\Persistence\Mapping\MappingException;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
Expand Down Expand Up @@ -69,7 +70,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool
foreach ($doctrineMetadata->fieldMappings as $mapping) {
$enabledForProperty = $enabledForClass;
$lengthConstraint = null;
foreach ($metadata->getPropertyMetadata($mapping['fieldName']) as $propertyMetadata) {
foreach ($metadata->getPropertyMetadata(self::getFieldMappingValue($mapping, 'fieldName')) as $propertyMetadata) {
// Enabling or disabling auto-mapping explicitly always takes precedence
if (AutoMappingStrategy::DISABLED === $propertyMetadata->getAutoMappingStrategy()) {
continue 2;
Expand All @@ -89,26 +90,26 @@ public function loadClassMetadata(ClassMetadata $metadata): bool
continue;
}

if (true === ($mapping['unique'] ?? false) && !isset($existingUniqueFields[$mapping['fieldName']])) {
$metadata->addConstraint(new UniqueEntity(['fields' => $mapping['fieldName']]));
if (true === (self::getFieldMappingValue($mapping, 'unique') ?? false) && !isset($existingUniqueFields[self::getFieldMappingValue($mapping, 'fieldName')])) {
$metadata->addConstraint(new UniqueEntity(['fields' => self::getFieldMappingValue($mapping, 'fieldName')]));
$loaded = true;
}

if (null === ($mapping['length'] ?? null) || null !== ($mapping['enumType'] ?? null) || !\in_array($mapping['type'], ['string', 'text'], true)) {
if (null === (self::getFieldMappingValue($mapping, 'length') ?? null) || null !== (self::getFieldMappingValue($mapping, 'enumType') ?? null) || !\in_array(self::getFieldMappingValue($mapping, 'type'), ['string', 'text'], true)) {
continue;
}

if (null === $lengthConstraint) {
if (isset($mapping['originalClass']) && !str_contains($mapping['declaredField'], '.')) {
$metadata->addPropertyConstraint($mapping['declaredField'], new Valid());
if (self::getFieldMappingValue($mapping, 'originalClass') && !str_contains(self::getFieldMappingValue($mapping, 'declaredField'), '.')) {
$metadata->addPropertyConstraint(self::getFieldMappingValue($mapping, 'declaredField'), new Valid());
$loaded = true;
} elseif (property_exists($className, $mapping['fieldName']) && (!$doctrineMetadata->isMappedSuperclass || $metadata->getReflectionClass()->getProperty($mapping['fieldName'])->isPrivate())) {
$metadata->addPropertyConstraint($mapping['fieldName'], new Length(['max' => $mapping['length']]));
} elseif (property_exists($className, self::getFieldMappingValue($mapping, 'fieldName')) && (!$doctrineMetadata->isMappedSuperclass || $metadata->getReflectionClass()->getProperty(self::getFieldMappingValue($mapping, 'fieldName'))->isPrivate())) {
$metadata->addPropertyConstraint(self::getFieldMappingValue($mapping, 'fieldName'), new Length(['max' => self::getFieldMappingValue($mapping, 'length')]));
$loaded = true;
}
} elseif (null === $lengthConstraint->max) {
// If a Length constraint exists and no max length has been explicitly defined, set it
$lengthConstraint->max = $mapping['length'];
$lengthConstraint->max = self::getFieldMappingValue($mapping, 'length');
}
}

Expand All @@ -132,4 +133,13 @@ private function getExistingUniqueFields(ClassMetadata $metadata): array

return $fields;
}

private static function getFieldMappingValue(array|FieldMapping $mapping, string $key): mixed
{
if ($mapping instanceof FieldMapping) {
return $mapping->$key;
}

return $mapping[$key] ?? null;
}
}

0 comments on commit aded7ef

Please sign in to comment.