Skip to content

Commit

Permalink
fix bugs
Browse files Browse the repository at this point in the history
nested dto are not in good argument order
dto with only dto does'nt work

phpstan correction
  • Loading branch information
eltharin committed Feb 15, 2025
1 parent c9557c5 commit f4c5705
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 38 deletions.
43 changes: 31 additions & 12 deletions src/Internal/Hydration/AbstractHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
use LogicException;
use ReflectionClass;

use function array_key_exists;
use function array_keys;
use function array_map;
use function array_merge;
use function count;
use function end;
use function in_array;
use function is_array;
use function ksort;

/**
* Base class for all hydrators. A hydrator is a class that provides some form
Expand Down Expand Up @@ -263,6 +266,15 @@ protected function gatherRowData(array $data, array &$id, array &$nonemptyCompon
{
$rowData = ['data' => [], 'newObjects' => []];

foreach ($this->rsm->newObjectMappings as $mapping) {
$this->rsm->newObject[$mapping['objIndex']] = ['className' => $mapping['className']];
}

foreach ($this->rsm->newObject as $objIndex => $newObject) {
$rowData['newObjects'][$objIndex]['class'] = new ReflectionClass($newObject['className']);
$rowData['newObjects'][$objIndex]['args'] = [];
}

foreach ($data as $key => $value) {
$cacheKeyInfo = $this->hydrateColumnInfo($key);
if ($cacheKeyInfo === null) {
Expand All @@ -282,7 +294,6 @@ protected function gatherRowData(array $data, array &$id, array &$nonemptyCompon
$value = $this->buildEnum($value, $cacheKeyInfo['enumType']);
}

$rowData['newObjects'][$objIndex]['class'] = $cacheKeyInfo['class'];
$rowData['newObjects'][$objIndex]['args'][$argIndex] = $value;
break;

Expand Down Expand Up @@ -336,21 +347,30 @@ protected function gatherRowData(array $data, array &$id, array &$nonemptyCompon
}
}

foreach ($this->resultSetMapping()->nestedNewObjectArguments as $objIndex => ['ownerIndex' => $ownerIndex, 'argIndex' => $argIndex]) {
if (! isset($rowData['newObjects'][$ownerIndex . ':' . $argIndex])) {
continue;
$nestedEntities = [];
foreach ($this->resultSetMapping()->nestedNewObjectArguments as ['ownerIndex' => $ownerIndex, 'argIndex' => $argIndex, 'argAlias' => $argAlias]) {
if (array_key_exists($argAlias, $rowData['newObjects'])) {
ksort($rowData['newObjects'][$argAlias]['args']);
$rowData['newObjects'][$ownerIndex]['args'][$argIndex] = $rowData['newObjects'][$argAlias]['class']->newInstanceArgs($rowData['newObjects'][$argAlias]['args']);
unset($rowData['newObjects'][$argAlias]);
} elseif (array_key_exists($argAlias, $rowData['data'])) {
if (!array_key_exists($argAlias, $nestedEntities)) {

Check failure on line 357 in src/Internal/Hydration/AbstractHydrator.php

View workflow job for this annotation

GitHub Actions / coding-standards / Coding Standards (PHP: 8.4)

Expected 1 line after "if", found 0.

Check failure on line 357 in src/Internal/Hydration/AbstractHydrator.php

View workflow job for this annotation

GitHub Actions / coding-standards / Coding Standards (PHP: 8.4)

Expected 1 space(s) after NOT operator; 0 found
$nestedEntities[$argAlias] = 1;
}
$rowData['newObjects'][$ownerIndex]['args'][$argIndex] = $rowData['data'][$argAlias];
} else {
throw new LogicException($argAlias . ' not exist');
}
}

$newObject = $rowData['newObjects'][$ownerIndex . ':' . $argIndex];
unset($rowData['newObjects'][$ownerIndex . ':' . $argIndex]);

$obj = $newObject['class']->newInstanceArgs($newObject['args']);

$rowData['newObjects'][$ownerIndex]['args'][$argIndex] = $obj;
foreach (array_keys($nestedEntities) as $entity)

Check failure on line 366 in src/Internal/Hydration/AbstractHydrator.php

View workflow job for this annotation

GitHub Actions / coding-standards / Coding Standards (PHP: 8.4)

Expected 1 space(s) after closing parenthesis; found newline
{
unset($rowData['data'][$entity]);
}

foreach ($rowData['newObjects'] as $objIndex => $newObject) {
$obj = $newObject['class']->newInstanceArgs($newObject['args']);
ksort($rowData['newObjects'][$objIndex]['args']);
$obj = $rowData['newObjects'][$objIndex]['class']->newInstanceArgs($rowData['newObjects'][$objIndex]['args']);

$rowData['newObjects'][$objIndex]['obj'] = $obj;
}
Expand Down Expand Up @@ -454,7 +474,6 @@ protected function hydrateColumnInfo(string $key): array|null
'type' => Type::getType($this->rsm->typeMappings[$key]),
'argIndex' => $mapping['argIndex'],
'objIndex' => $mapping['objIndex'],
'class' => new ReflectionClass($mapping['className']),
'enumType' => $this->rsm->enumMappings[$key] ?? null,
];

Expand Down
4 changes: 2 additions & 2 deletions src/Query/AST/NewObjectExpression.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public function __construct(public string $className, public array $args)
{
}

public function dispatch(SqlWalker $walker): string
public function dispatch(SqlWalker $walker, string|null $parentAlias = null): string
{
return $walker->walkNewObject($this);
return $walker->walkNewObject($this, $parentAlias);
}
}
6 changes: 5 additions & 1 deletion src/Query/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -1854,7 +1854,11 @@ public function NewObjectArg(string|null &$fieldAlias = null): mixed

if ($this->lexer->isNextToken(TokenType::T_AS)) {
$this->match(TokenType::T_AS);
$fieldAlias = $this->AliasIdentificationVariable();
$this->match(TokenType::T_IDENTIFIER);

assert($this->lexer->token !== null);

$fieldAlias = $this->lexer->token->value;
}

return $expression;
Expand Down
7 changes: 7 additions & 0 deletions src/Query/ResultSetMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ class ResultSetMapping
*/
public array $newObjectMappings = [];

/**
* Maps object Ids in the result set to classnames.
*
* @phpstan-var array<string|int, array<string, mixed>>
*/
public array $newObject = [];

/**
* Maps last argument for new objects in order to initiate object construction
*
Expand Down
28 changes: 7 additions & 21 deletions src/Query/SqlWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@
use function array_keys;
use function array_map;
use function array_merge;
use function array_pop;
use function assert;
use function count;
use function end;
use function implode;
use function in_array;
use function is_array;
Expand Down Expand Up @@ -84,13 +82,6 @@ class SqlWalker
*/
private int $newObjectCounter = 0;

/**
* Contains nesting levels of new objects arguments
*
* @phpstan-var array<int, array{0: string|int, 1: int}>
*/
private array $newObjectStack = [];

private readonly EntityManagerInterface $em;
private readonly Connection $conn;

Expand Down Expand Up @@ -1507,14 +1498,7 @@ public function walkParenthesisExpression(AST\ParenthesisExpression $parenthesis
public function walkNewObject(AST\NewObjectExpression $newObjectExpression, string|null $newObjectResultAlias = null): string
{
$sqlSelectExpressions = [];
$objOwner = $objOwnerIdx = null;

if ($this->newObjectStack !== []) {
[$objOwner, $objOwnerIdx] = end($this->newObjectStack);
$objIndex = $objOwner . ':' . $objOwnerIdx;
} else {
$objIndex = $newObjectResultAlias ?: $this->newObjectCounter++;
}
$objIndex = $newObjectResultAlias ?: $this->newObjectCounter++;

foreach ($newObjectExpression->args as $argIndex => $e) {
$resultAlias = $this->scalarResultCounter++;
Expand All @@ -1523,10 +1507,8 @@ public function walkNewObject(AST\NewObjectExpression $newObjectExpression, stri

switch (true) {
case $e instanceof AST\NewObjectExpression:
$this->newObjectStack[] = [$objIndex, $argIndex];
$sqlSelectExpressions[] = $e->dispatch($this);
array_pop($this->newObjectStack);
$this->rsm->nestedNewObjectArguments[$columnAlias] = ['ownerIndex' => $objIndex, 'argIndex' => $argIndex];
$sqlSelectExpressions[] = $e->dispatch($this, $columnAlias);
$this->rsm->nestedNewObjectArguments[$columnAlias] = ['ownerIndex' => $objIndex, 'argIndex' => $argIndex, 'argAlias' => $columnAlias];
break;

case $e instanceof AST\Subselect:
Expand Down Expand Up @@ -1582,6 +1564,10 @@ public function walkNewObject(AST\NewObjectExpression $newObjectExpression, stri
];
}

$this->rsm->newObject[$objIndex] = [
'className' => $newObjectExpression->className,
];

return implode(', ', $sqlSelectExpressions);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Tests/Models/CMS/CmsAddressDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class CmsAddressDTO
{
public function __construct(public string|null $country = null, public string|null $city = null, public string|null $zip = null, public CmsAddressDTO|string|null $address = null)
public function __construct(public string|null $country = null, public string|null $city = null, public string|null $zip = null, public CmsDumbDTO|null $other = null)
{
}
}
17 changes: 17 additions & 0 deletions tests/Tests/Models/CMS/CmsDumbDTO.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\Models\CMS;

class CmsDumbDTO
{
public function __construct(
public mixed $val1 = null,
public mixed $val2 = null,
public mixed $val3 = null,
public mixed $val4 = null,
public mixed $val5 = null,
) {
}
}
Loading

0 comments on commit f4c5705

Please sign in to comment.