Skip to content

Commit

Permalink
add enumType to discriminatorColumn
Browse files Browse the repository at this point in the history
  • Loading branch information
michnovka committed Dec 12, 2022
1 parent c1c089a commit e9a2f5a
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 6 deletions.
1 change: 1 addition & 0 deletions docs/en/reference/attributes-reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ Optional parameters:

- **type**: By default this is string.
- **length**: By default this is 255.
- **enumType**: By default this is `null`. Allows to map discriminatorColumn value to PHP enum

.. _attrref_discriminatormap:

Expand Down
1 change: 1 addition & 0 deletions doctrine-mapping.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@
<xs:attribute name="field-name" type="xs:NMTOKEN" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:attribute name="column-definition" type="xs:string" />
<xs:attribute name="enum-type" type="xs:string" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>

Expand Down
2 changes: 2 additions & 0 deletions lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,8 @@ protected function hydrateColumnInfo($key)
'fieldName' => $fieldName,
'type' => $type,
'dqlAlias' => $dqlAlias,
'enumType' => $this->_rsm->enumMappings[$key] ?? null,

];
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ class ClassMetadataInfo implements ClassMetadata
* READ-ONLY: The definition of the discriminator column used in JOINED and SINGLE_TABLE
* inheritance mappings.
*
* @psalm-var array{name: string, fieldName: string, type: string, length?: int, columnDefinition?: string|null}|null
* @psalm-var array{name: string, fieldName: string, type: string, length?: int, columnDefinition?: string|null, enumType?: class-string<BackedEnum>|null}|null
*/
public $discriminatorColumn;

Expand Down
11 changes: 10 additions & 1 deletion lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,24 @@ final class DiscriminatorColumn implements MappingAttribute
*/
public $columnDefinition;

/**
* @var class-string<\BackedEnum>|null
* @readonly
*/
public $enumType = null;

/** @param class-string<\BackedEnum>|null $enumType */
public function __construct(
?string $name = null,
?string $type = null,
?int $length = null,
?string $columnDefinition = null
?string $columnDefinition = null,
?string $enumType = null
) {
$this->name = $name;
$this->type = $type;
$this->length = $length;
$this->columnDefinition = $columnDefinition;
$this->enumType = $enumType;
}
}
1 change: 1 addition & 0 deletions lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ public function loadMetadataForClass($className, PersistenceClassMetadata $metad
'type' => $discrColumnAnnot->type ?: 'string',
'length' => $discrColumnAnnot->length ?? 255,
'columnDefinition' => $discrColumnAnnot->columnDefinition,
'enumType' => $discrColumnAnnot->enumType,
]
);
} else {
Expand Down
1 change: 1 addition & 0 deletions lib/Doctrine/ORM/Mapping/Driver/AttributeDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ public function loadMetadataForClass($className, PersistenceClassMetadata $metad
'type' => isset($discrColumnAttribute->type) ? (string) $discrColumnAttribute->type : 'string',
'length' => isset($discrColumnAttribute->length) ? (int) $discrColumnAttribute->length : 255,
'columnDefinition' => isset($discrColumnAttribute->columnDefinition) ? (string) $discrColumnAttribute->columnDefinition : null,
'enumType' => isset($discrColumnAttribute->enumType) ? (string) $discrColumnAttribute->enumType : null,
]
);
} else {
Expand Down
1 change: 1 addition & 0 deletions lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ public function loadMetadataForClass($className, PersistenceClassMetadata $metad
'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string',
'length' => isset($discrColumn['length']) ? (int) $discrColumn['length'] : 255,
'columnDefinition' => isset($discrColumn['column-definition']) ? (string) $discrColumn['column-definition'] : null,
'enumType' => isset($discrColumn['enum-type']) ? (string) $discrColumn['enum-type'] : null,
]
);
} else {
Expand Down
3 changes: 3 additions & 0 deletions lib/Doctrine/ORM/Query/SqlWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,9 @@ public function walkSelectClause($selectClause)

$this->rsm->setDiscriminatorColumn($dqlAlias, $columnAlias);
$this->rsm->addMetaResult($dqlAlias, $columnAlias, $discrColumn['fieldName'], false, $discrColumn['type']);
if(!empty($discrColumn['enumType'])){
$this->rsm->addEnumResult($columnAlias, $discrColumn['enumType']);
}
}

// Add foreign key columns to SQL, if necessary
Expand Down
12 changes: 8 additions & 4 deletions tests/Doctrine/Tests/ORM/Functional/Ticket/GH10288Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
use Doctrine\Tests\OrmFunctionalTestCase;

/**
* This test makes sure that Discriminator columns can use both custom types using PHP enums as well as
* enumType definition of enums.
*
* @requires PHP 8.1
*/
class GH10288Test extends OrmFunctionalTestCase
Expand Down Expand Up @@ -73,10 +76,11 @@ public function testEnumDiscriminatorsShouldBeConvertedToString(): void
->getQuery();

$query->setParameter('name', 'John');
$bossArray = $query->getOneOrNullResult(AbstractQuery::HYDRATE_ARRAY);
self::assertEquals($boss, $query->getOneOrNullResult(AbstractQuery::HYDRATE_OBJECT));
self::assertEquals(
GH10288People::BOSS,
$query->getOneOrNullResult(AbstractQuery::HYDRATE_ARRAY)['discr']
$bossArray['discr']
);

$bossId = $boss->id;
Expand Down Expand Up @@ -106,7 +110,7 @@ public function testEnumDiscriminatorsShouldBeConvertedToString(): void

class GH10288PeopleType extends StringType
{
public const NAME = 'GH10288people';
public const NAME = 'GH10288PeopleType';

/**
* {@inheritdoc}
Expand Down Expand Up @@ -140,7 +144,7 @@ public function getName()
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="GH10288people")
* @DiscriminatorColumn(name="discr", enumType=GH10288People::class)
* @DiscriminatorMap({
* "boss" = GH10288BossJoined::class,
* "employee" = GH10288EmployeeJoined::class
Expand Down Expand Up @@ -186,7 +190,7 @@ class GH10288EmployeeJoined extends GH10288PersonJoined
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="GH10288people")
* @DiscriminatorColumn(name="discr", type="GH10288PeopleType")
* @DiscriminatorMap({
* "boss" = GH10288BossSingleTable::class,
* "employee" = GH10288EmployeeSingleTable::class
Expand Down
45 changes: 45 additions & 0 deletions tests/Doctrine/Tests/ORM/Mapping/MappingDriverTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
use Doctrine\Tests\Models\DDC964\DDC964Guest;
use Doctrine\Tests\Models\Enums\Card;
use Doctrine\Tests\Models\Enums\Suit;
use Doctrine\Tests\Models\GH10288\GH10288People;
use Doctrine\Tests\Models\TypedProperties\Contact;
use Doctrine\Tests\Models\TypedProperties\UserTyped;
use Doctrine\Tests\Models\Upsertable\Insertable;
Expand Down Expand Up @@ -555,6 +556,20 @@ public function testDiscriminatorColumnDefinition(): void
self::assertEquals('dtype', $class->discriminatorColumn['name']);
}

/**
* @group GH10288
*/
public function testDiscriminatorColumnEnumTypeDefinition(): void
{
$class = $this->createClassMetadata(GH10288EnumTypePerson::class);

self::assertArrayHasKey('enumType', $class->discriminatorColumn);
self::assertArrayHasKey('name', $class->discriminatorColumn);

self::assertEquals(GH10288People::class, $class->discriminatorColumn['enumType']);
self::assertEquals('discr', $class->discriminatorColumn['name']);
}

/** @group DDC-889 */
public function testInvalidEntityOrMappedSuperClassShouldMentionParentClasses(): void
{
Expand Down Expand Up @@ -1795,3 +1810,33 @@ class UserIncorrectAttributes extends User
class UserMissingAttributes extends User
{
}


/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", enumType=GH10288People::class)
* @DiscriminatorMap({
* "boss" = GH10288EnumTypeBoss::class
* })
*/
#[Entity]
#[InheritanceType('JOINED')]
#[DiscriminatorColumn(name: 'discr', enumType: GH10288People::class)]
#[DiscriminatorMap(['boss' => GH10288EnumTypeBoss::class])]
abstract class GH10288EnumTypePerson
{
/**
* @var int
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
}

/** @Entity */
#[Entity]
class GH10288EnumTypeBoss extends GH10288EnumTypePerson
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

<entity name="Doctrine\Tests\ORM\Mapping\GH10288EnumTypePerson" inheritance-type="SINGLE_TABLE">
<discriminator-column name="discr" enum-type="Doctrine\Tests\Models\GH10288\GH10288People"/>

<discriminator-map>
<discriminator-mapping value="boss" class="Doctrine\Tests\ORM\Mapping\GH10288EnumTypeBoss" />
</discriminator-map>

<id name="id">
<generator strategy="NONE"/>
</id>
</entity>

</doctrine-mapping>

0 comments on commit e9a2f5a

Please sign in to comment.