Skip to content

Commit

Permalink
add order for args for nested dtos
Browse files Browse the repository at this point in the history
  • Loading branch information
eltharin committed Feb 14, 2025
1 parent c9557c5 commit 72695a8
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/Internal/Hydration/AbstractHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
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 @@ -343,13 +344,14 @@ protected function gatherRowData(array $data, array &$id, array &$nonemptyCompon

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

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

$rowData['newObjects'][$ownerIndex]['args'][$argIndex] = $obj;
}

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

$rowData['newObjects'][$objIndex]['obj'] = $obj;
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 $other = null)

Check failure on line 9 in tests/Tests/Models/CMS/CmsAddressDTO.php

View workflow job for this annotation

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

Usage of short nullable type hint in "?CmsDumbDTO" is disallowed.
{
}
}
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

Check failure on line 14 in tests/Tests/Models/CMS/CmsDumbDTO.php

View workflow job for this annotation

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

Multi-line function declaration must have a trailing comma after the last parameter.
) {
}
}
186 changes: 185 additions & 1 deletion tests/Tests/ORM/Functional/NewOperatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Doctrine\Tests\Models\CMS\CmsAddress;
use Doctrine\Tests\Models\CMS\CmsAddressDTO;
use Doctrine\Tests\Models\CMS\CmsAddressDTONamedArgs;
use Doctrine\Tests\Models\CMS\CmsDumbDTO;
use Doctrine\Tests\Models\CMS\CmsEmail;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Tests\Models\CMS\CmsUser;
Expand Down Expand Up @@ -1031,7 +1032,7 @@ public function testShouldSupportNestedNewOperators(): void
a.country,
a.city,
a.zip,
new CmsAddressDTO(
new CmsDumbDTO(
a.country,
a.city,
a.zip
Expand Down Expand Up @@ -1078,6 +1079,85 @@ public function testShouldSupportNestedNewOperators(): void
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->country);
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->country);

self::assertInstanceOf(CmsDumbDTO::class, $result[0]['user']->address->other);
self::assertInstanceOf(CmsDumbDTO::class, $result[1]['user']->address->other);
self::assertInstanceOf(CmsDumbDTO::class, $result[2]['user']->address->other);

self::assertSame($this->fixtures[0]->address->country, $result[0]['user']->address->other->val1);
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->other->val1);
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->other->val1);

self::assertSame($this->fixtures[0]->address->city, $result[0]['user']->address->other->val2);
self::assertSame($this->fixtures[1]->address->city, $result[1]['user']->address->other->val2);
self::assertSame($this->fixtures[2]->address->city, $result[2]['user']->address->other->val2);

self::assertSame($this->fixtures[0]->status, $result[0]['status']);
self::assertSame($this->fixtures[1]->status, $result[1]['status']);
self::assertSame($this->fixtures[2]->status, $result[2]['status']);

self::assertSame($this->fixtures[0]->username, $result[0]['cmsUserUsername']);
self::assertSame($this->fixtures[1]->username, $result[1]['cmsUserUsername']);
self::assertSame($this->fixtures[2]->username, $result[2]['cmsUserUsername']);
}

public function testShouldSupportNestedNewOperatorsWithDtoFirst(): void
{
$dql = '
SELECT
new CmsUserDTO(
u.name,
e.email,
new CmsAddressDTO(
a.country,
a.city,
a.zip
),
555812452
) as user,
u.status,
u.username as cmsUserUsername
FROM
Doctrine\Tests\Models\CMS\CmsUser u
JOIN
u.email e
JOIN
u.address a
ORDER BY
u.name';

$query = $this->getEntityManager()->createQuery($dql);
$result = $query->getResult();

self::assertCount(3, $result);

self::assertInstanceOf(CmsUserDTO::class, $result[0]['user']);
self::assertInstanceOf(CmsUserDTO::class, $result[1]['user']);
self::assertInstanceOf(CmsUserDTO::class, $result[2]['user']);

self::assertInstanceOf(CmsAddressDTO::class, $result[0]['user']->address);
self::assertInstanceOf(CmsAddressDTO::class, $result[1]['user']->address);
self::assertInstanceOf(CmsAddressDTO::class, $result[2]['user']->address);

self::assertSame($this->fixtures[0]->name, $result[0]['user']->name);
self::assertSame($this->fixtures[1]->name, $result[1]['user']->name);
self::assertSame($this->fixtures[2]->name, $result[2]['user']->name);

self::assertSame($this->fixtures[0]->email->email, $result[0]['user']->email);
self::assertSame($this->fixtures[1]->email->email, $result[1]['user']->email);
self::assertSame($this->fixtures[2]->email->email, $result[2]['user']->email);

self::assertSame($this->fixtures[0]->address->city, $result[0]['user']->address->city);
self::assertSame($this->fixtures[1]->address->city, $result[1]['user']->address->city);
self::assertSame($this->fixtures[2]->address->city, $result[2]['user']->address->city);

self::assertSame($this->fixtures[0]->address->country, $result[0]['user']->address->country);
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->country);
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->country);

self::assertSame(555812452, $result[0]['user']->phonenumbers);
self::assertSame(555812452, $result[1]['user']->phonenumbers);
self::assertSame(555812452, $result[2]['user']->phonenumbers);

self::assertSame($this->fixtures[0]->status, $result[0]['status']);
self::assertSame($this->fixtures[1]->status, $result[1]['status']);
self::assertSame($this->fixtures[2]->status, $result[2]['status']);
Expand Down Expand Up @@ -1159,6 +1239,110 @@ public function testNamedArguments(): void
self::assertSame($this->fixtures[2]->username, $result[2]['cmsUserUsername']);
}

public function testShouldSupportNestedNewOperatorsWithNestedDtoNotLast(): void
{
$dql = '
SELECT
new CmsUserDTO(
u.name,
e.email,
new CmsAddressDTO(
a.country,
a.city,
a.zip,
new CmsDumbDTO(
a.country,
a.city,
new CmsDumbDTO(
a.zip,
456
),
a.zip
)
),
555812452
) as user,
u.status,
u.username as cmsUserUsername
FROM
Doctrine\Tests\Models\CMS\CmsUser u
JOIN
u.email e
JOIN
u.address a
ORDER BY
u.name';

$query = $this->getEntityManager()->createQuery($dql);
$result = $query->getResult();

self::assertCount(3, $result);

self::assertInstanceOf(CmsUserDTO::class, $result[0]['user']);
self::assertInstanceOf(CmsUserDTO::class, $result[1]['user']);
self::assertInstanceOf(CmsUserDTO::class, $result[2]['user']);

self::assertSame($this->fixtures[0]->name, $result[0]['user']->name);
self::assertSame($this->fixtures[1]->name, $result[1]['user']->name);
self::assertSame($this->fixtures[2]->name, $result[2]['user']->name);

self::assertSame($this->fixtures[0]->email->email, $result[0]['user']->email);
self::assertSame($this->fixtures[1]->email->email, $result[1]['user']->email);
self::assertSame($this->fixtures[2]->email->email, $result[2]['user']->email);

self::assertInstanceOf(CmsAddressDTO::class, $result[0]['user']->address);
self::assertInstanceOf(CmsAddressDTO::class, $result[1]['user']->address);
self::assertInstanceOf(CmsAddressDTO::class, $result[2]['user']->address);

self::assertSame($this->fixtures[0]->address->country, $result[0]['user']->address->country);
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->country);
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->country);

self::assertSame($this->fixtures[2]->address->city, $result[2]['user']->address->city);
self::assertSame($this->fixtures[0]->address->city, $result[0]['user']->address->city);
self::assertSame($this->fixtures[1]->address->city, $result[1]['user']->address->city);

self::assertInstanceOf(CmsDumbDTO::class, $result[0]['user']->address->other);
self::assertInstanceOf(CmsDumbDTO::class, $result[1]['user']->address->other);
self::assertInstanceOf(CmsDumbDTO::class, $result[2]['user']->address->other);

self::assertSame($this->fixtures[0]->address->country, $result[0]['user']->address->other->val1);
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->other->val1);
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->other->val1);

self::assertSame($this->fixtures[0]->address->city, $result[0]['user']->address->other->val2);
self::assertSame($this->fixtures[1]->address->city, $result[1]['user']->address->other->val2);
self::assertSame($this->fixtures[2]->address->city, $result[2]['user']->address->other->val2);

self::assertInstanceOf(CmsDumbDTO::class, $result[0]['user']->address->other->val3);
self::assertInstanceOf(CmsDumbDTO::class, $result[1]['user']->address->other->val3);
self::assertInstanceOf(CmsDumbDTO::class, $result[2]['user']->address->other->val3);

self::assertSame($this->fixtures[0]->address->zip, $result[0]['user']->address->other->val3->val1);
self::assertSame($this->fixtures[1]->address->zip, $result[1]['user']->address->other->val3->val1);
self::assertSame($this->fixtures[2]->address->zip, $result[2]['user']->address->other->val3->val1);

self::assertSame(456, $result[0]['user']->address->other->val3->val2);
self::assertSame(456, $result[1]['user']->address->other->val3->val2);
self::assertSame(456, $result[2]['user']->address->other->val3->val2);

self::assertSame($this->fixtures[0]->address->zip, $result[0]['user']->address->other->val4);
self::assertSame($this->fixtures[1]->address->zip, $result[1]['user']->address->other->val4);
self::assertSame($this->fixtures[2]->address->zip, $result[2]['user']->address->other->val4);

self::assertSame(555812452, $result[0]['user']->phonenumbers);
self::assertSame(555812452, $result[1]['user']->phonenumbers);
self::assertSame(555812452, $result[2]['user']->phonenumbers);

self::assertSame($this->fixtures[0]->status, $result[0]['status']);
self::assertSame($this->fixtures[1]->status, $result[1]['status']);
self::assertSame($this->fixtures[2]->status, $result[2]['status']);

self::assertSame($this->fixtures[0]->username, $result[0]['cmsUserUsername']);
self::assertSame($this->fixtures[1]->username, $result[1]['cmsUserUsername']);
self::assertSame($this->fixtures[2]->username, $result[2]['cmsUserUsername']);
}

public function testVariadicArgument(): void
{
$dql = <<<'SQL'
Expand Down

0 comments on commit 72695a8

Please sign in to comment.