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
  • Loading branch information
eltharin committed Feb 15, 2025
1 parent c9557c5 commit b009897
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 31 deletions.
40 changes: 28 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,27 @@ 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'])) {
$rowData['newObjects'][$ownerIndex]['args'][$argIndex] = $rowData['data'][$argAlias];

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

View check run for this annotation

Codecov / codecov/patch

src/Internal/Hydration/AbstractHydrator.php#L356-L357

Added lines #L356 - L357 were not covered by tests
} else {
throw new LogicException($argAlias . ' not exist');

Check warning on line 359 in src/Internal/Hydration/AbstractHydrator.php

View check run for this annotation

Codecov / codecov/patch

src/Internal/Hydration/AbstractHydrator.php#L359

Added line #L359 was not covered by tests
}
}

$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 363 in src/Internal/Hydration/AbstractHydrator.php

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (default, phpstan.neon)

Empty array passed to foreach.

Check failure on line 363 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 FOREACH keyword; 0 found

Check failure on line 363 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

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

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (3.8.2, phpstan-dbal3.neon)

Empty array passed to foreach.
{
unset($rowData['data'][$entity]);

Check warning on line 365 in src/Internal/Hydration/AbstractHydrator.php

View check run for this annotation

Codecov / codecov/patch

src/Internal/Hydration/AbstractHydrator.php#L365

Added line #L365 was not covered by tests
}

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']);

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

View workflow job for this annotation

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

Useless parentheses.

$rowData['newObjects'][$objIndex]['obj'] = $obj;
}
Expand Down Expand Up @@ -454,7 +471,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, array<string, mixed>>
*/
public array $newObject = [];

/**
* Maps last argument for new objects in order to initiate object construction
*
Expand Down
21 changes: 7 additions & 14 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 @@ -1507,14 +1505,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 +1514,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 +1571,10 @@ public function walkNewObject(AST\NewObjectExpression $newObjectExpression, stri
];
}

$this->rsm->newObject[$objIndex] = [

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

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (default, phpstan.neon)

Property Doctrine\ORM\Query\ResultSetMapping::$newObject (array<string, array<string, mixed>>) does not accept array<int|string, array<string, mixed>>.

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

View workflow job for this annotation

GitHub Actions / Static Analysis with PHPStan (3.8.2, phpstan-dbal3.neon)

Property Doctrine\ORM\Query\ResultSetMapping::$newObject (array<string, array<string, mixed>>) does not accept array<int|string, array<string, mixed>>.
'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 b009897

Please sign in to comment.