Skip to content

Commit

Permalink
Refactor obtaining discriminator values for a class
Browse files Browse the repository at this point in the history
  • Loading branch information
mpdude committed Feb 3, 2024
1 parent 5401367 commit 0507785
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 27 deletions.
29 changes: 29 additions & 0 deletions src/Mapping/ClassMetadata.php
Expand Up @@ -2199,6 +2199,35 @@ public function addDiscriminatorMapClass(int|string $name, string $className): v
$this->addSubClass($className);
}

/**
* @internal
*
* @return list<int|string>
*
* @psalm-internal Doctrine\ORM
*/
public function getDiscriminatorValuesForClassAndSubclasses(): array
{
$values = [];
$valueByClass = array_flip($this->discriminatorMap);

Check failure on line 2212 in src/Mapping/ClassMetadata.php

View workflow job for this annotation

GitHub Actions / coding-standards / Coding Standards (8.2)

Function array_flip() should not be referenced via a fallback global name, but via a use statement.

// Even if this class is part of an inheritance hierarchy, the discriminator
// value may be null in case the class is abstract.
if ($this->discriminatorValue !== null) {
$values[] = $this->discriminatorValue;
}

foreach ($this->subClasses as $subClass) {
// Abstract entity classes show up in the list of subClasses,
// but may be omitted from the discriminator map.
if (isset($valueByClass[$subClass])) {
$values[] = $valueByClass[$subClass];
}
}

return $values;
}

/** @param array<class-string> $classes */
public function addSubClasses(array $classes): void
{
Expand Down
20 changes: 5 additions & 15 deletions src/Persisters/Entity/SingleTablePersister.php
Expand Up @@ -10,10 +10,7 @@
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Utility\PersisterHelper;

use function array_flip;
use function array_intersect;
use function array_map;
use function array_unshift;
use function implode;
use function strval;

Expand Down Expand Up @@ -138,19 +135,12 @@ protected function getSelectConditionCriteriaSQL(Criteria $criteria): string

protected function getSelectConditionDiscriminatorValueSQL(): string
{
$values = array_map($this->conn->quote(...), array_map(
strval(...),
array_flip(array_intersect($this->class->discriminatorMap, $this->class->subClasses)),
));

if ($this->class->discriminatorValue !== null) { // discriminators can be 0
array_unshift($values, $this->conn->quote((string) $this->class->discriminatorValue));
}

$tableAlias = $this->getSQLTableAlias($this->class->name);
$discColumnName = $this->class->getDiscriminatorColumn()->name;

$values = implode(', ', $values);
$tableAlias = $this->getSQLTableAlias($this->class->name);
$values = implode(', ', array_map(
$this->conn->quote(...),
array_map(strval(...), $this->class->getDiscriminatorValuesForClassAndSubclasses())

Check failure on line 142 in src/Persisters/Entity/SingleTablePersister.php

View workflow job for this annotation

GitHub Actions / coding-standards / Coding Standards (8.2)

Multi-line function calls must have a trailing comma after the last parameter.
));

return $tableAlias . '.' . $discColumnName . ' IN (' . $values . ')';
}
Expand Down
23 changes: 11 additions & 12 deletions src/Query/SqlWalker.php
Expand Up @@ -368,6 +368,7 @@ private function generateOrderedCollectionOrderByItems(): string
private function generateDiscriminatorColumnConditionSQL(array $dqlAliases): string
{
$sqlParts = [];
$conn = $this->em->getConnection();

foreach ($dqlAliases as $dqlAlias) {
$class = $this->getMetadataForDqlAlias($dqlAlias);
Expand All @@ -376,22 +377,20 @@ private function generateDiscriminatorColumnConditionSQL(array $dqlAliases): str
continue;
}

$conn = $this->em->getConnection();
$values = [];

if ($class->discriminatorValue !== null) { // discriminators can be 0
$values[] = $conn->quote($class->discriminatorValue);
}

foreach ($class->subClasses as $subclassName) {
$values[] = $conn->quote((string) $this->em->getClassMetadata($subclassName)->discriminatorValue);
}

$sqlTableAlias = $this->useSqlTableAliases
? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.'
: '';

$sqlParts[] = $sqlTableAlias . $class->getDiscriminatorColumn()->name . ' IN (' . implode(', ', $values) . ')';
$discriminatorValues = array_map(
$conn->quote(...),
array_map(strval(...), $class->getDiscriminatorValuesForClassAndSubclasses())

Check failure on line 386 in src/Query/SqlWalker.php

View workflow job for this annotation

GitHub Actions / coding-standards / Coding Standards (8.2)

Function strval() should not be referenced via a fallback global name, but via a use statement.

Check failure on line 386 in src/Query/SqlWalker.php

View workflow job for this annotation

GitHub Actions / coding-standards / Coding Standards (8.2)

Multi-line function calls must have a trailing comma after the last parameter.
);

if ($discriminatorValues !== []) {
$sqlParts[] = $sqlTableAlias . $class->getDiscriminatorColumn()->name . ' IN (' . implode(', ', $discriminatorValues) . ')';
} else {
$sqlParts[] = '1=0'; // impossible condition
}
}

$sql = implode(' AND ', $sqlParts);
Expand Down

0 comments on commit 0507785

Please sign in to comment.