Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2e499d8

Browse files
author
Sergey Naumov
committed
SimpleObjectHydrator: skip unsuit custom type before convert it
SimpleObjectHydrator tries to convert the value, and only then checks if we need it. This results in an error if our custom type does not get expected data to initialize php value.
1 parent 3f3de70 commit 2e499d8

7 files changed

Lines changed: 151 additions & 5 deletions

File tree

lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ protected function hydrateRowData(array $row, array &$result)
133133
continue;
134134
}
135135

136+
// If we have inheritance in resultset, make sure the field belongs to the correct class
137+
if (isset($cacheKeyInfo['discriminatorValues']) && ! in_array((string) $discrColumnValue, $cacheKeyInfo['discriminatorValues'], true)) {
138+
continue;
139+
}
140+
136141
// Check if value is null before conversion (because some types convert null to something else)
137142
$valueIsNull = $value === null;
138143

@@ -146,11 +151,6 @@ protected function hydrateRowData(array $row, array &$result)
146151

147152
// Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
148153
if (! isset($data[$fieldName]) || ! $valueIsNull) {
149-
// If we have inheritance in resultset, make sure the field belongs to the correct class
150-
if (isset($cacheKeyInfo['discriminatorValues']) && ! in_array((string) $discrColumnValue, $cacheKeyInfo['discriminatorValues'], true)) {
151-
continue;
152-
}
153-
154154
$data[$fieldName] = $value;
155155
}
156156
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\DbalTypes;
6+
7+
use Doctrine\DBAL\Platforms\AbstractPlatform;
8+
use Doctrine\DBAL\Types\JsonType;
9+
use Exception;
10+
11+
class GH8565EmployeePayloadType extends JsonType
12+
{
13+
public const NAME = 'GH8565EmployeePayloadType';
14+
15+
public function convertToPHPValue($value, AbstractPlatform $platform): string
16+
{
17+
if (! isset($value['GH8565EmployeePayloadRequiredField'])) {
18+
throw new Exception('GH8565EmployeePayloadType cannot be initialized without required field');
19+
}
20+
21+
return $value['GH8565EmployeePayloadRequiredField'];
22+
}
23+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\DbalTypes;
6+
7+
use Doctrine\DBAL\Platforms\AbstractPlatform;
8+
use Doctrine\DBAL\Types\JsonType;
9+
10+
class GH8565ManagerPayloadType extends JsonType
11+
{
12+
public const NAME = 'GH8565ManagerPayloadType';
13+
14+
public function convertToPHPValue($value, AbstractPlatform $platform): string
15+
{
16+
return $value;
17+
}
18+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\GH8565;
6+
7+
use Doctrine\Tests\DbalTypes\GH8565EmployeePayloadType;
8+
9+
/**
10+
* @Entity
11+
* @Table(name="gh8565_employees")
12+
*/
13+
class GH8565Employee extends GH8565Person
14+
{
15+
/**
16+
* @Column(type="GH8565EmployeePayloadType", nullable=false)
17+
* @var GH8565EmployeePayloadType
18+
*/
19+
public $type;
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\GH8565;
6+
7+
use Doctrine\Tests\DbalTypes\GH8565ManagerPayloadType;
8+
9+
/**
10+
* @Entity
11+
* @Table(name="gh8565_managers")
12+
*/
13+
class GH8565Manager extends GH8565Person
14+
{
15+
/**
16+
* @Column(type="GH8565ManagerPayloadType", nullable=false)
17+
* @var GH8565ManagerPayloadType
18+
*/
19+
public $type;
20+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Tests\Models\GH8565;
6+
7+
/**
8+
* @Entity
9+
* @Table(name="gh8565_persons")
10+
* @InheritanceType("JOINED")
11+
* @DiscriminatorColumn(name="discr", type="string")
12+
* @DiscriminatorMap({
13+
* "person" = "GH8565Person",
14+
* "manager" = "GH8565Manager",
15+
* "employee" = "GH8565Employee"
16+
* })
17+
*/
18+
class GH8565Person
19+
{
20+
/**
21+
* @var int
22+
* @Id
23+
* @Column(type="integer")
24+
* @GeneratedValue
25+
*/
26+
public $id;
27+
}

tests/Doctrine/Tests/ORM/Hydration/SimpleObjectHydratorTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@
44

55
namespace Doctrine\Tests\ORM\Hydration;
66

7+
use Doctrine\DBAL\Types\Type as DBALType;
78
use Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator;
89
use Doctrine\ORM\Query\ResultSetMapping;
10+
use Doctrine\Tests\DbalTypes\GH8565EmployeePayloadType;
11+
use Doctrine\Tests\DbalTypes\GH8565ManagerPayloadType;
912
use Doctrine\Tests\Mocks\HydratorMockStatement;
1013
use Doctrine\Tests\Models\CMS\CmsAddress;
1114
use Doctrine\Tests\Models\Company\CompanyPerson;
15+
use Doctrine\Tests\Models\GH8565\GH8565Employee;
16+
use Doctrine\Tests\Models\GH8565\GH8565Manager;
17+
use Doctrine\Tests\Models\GH8565\GH8565Person;
1218
use Doctrine\Tests\Models\Issue5989\Issue5989Employee;
1319
use Doctrine\Tests\Models\Issue5989\Issue5989Manager;
1420
use Doctrine\Tests\Models\Issue5989\Issue5989Person;
@@ -122,4 +128,36 @@ public function testNullValueShouldNotOverwriteFieldWithSameNameInJoinedInherita
122128
$result = $hydrator->hydrateAll($stmt, $rsm);
123129
$this->assertEquals($result[0], $expectedEntity);
124130
}
131+
132+
public function testWrongValuesShouldNotBeConvertedToPhpValue(): void
133+
{
134+
DBALType::addType(GH8565EmployeePayloadType::NAME, GH8565EmployeePayloadType::class);
135+
DBALType::addType(GH8565ManagerPayloadType::NAME, GH8565ManagerPayloadType::class);
136+
137+
$rsm = new ResultSetMapping();
138+
$rsm->addEntityResult(GH8565Person::class, 'p');
139+
$rsm->addFieldResult('p', 'p__id', 'id');
140+
$rsm->addFieldResult('p', 'm__type', 'type', GH8565Manager::class);
141+
$rsm->addFieldResult('p', 'e__type', 'type', GH8565Employee::class);
142+
$rsm->addMetaResult('p', 'discr', 'discr', false, 'string');
143+
$rsm->setDiscriminatorColumn('p', 'type');
144+
$resultSet = [
145+
[
146+
'p__id' => '1',
147+
'm__type' => 'type field',
148+
'e__type' => 'type field',
149+
'e__tags' => null,
150+
'discr' => 'manager',
151+
],
152+
];
153+
154+
$expectedEntity = new GH8565Manager();
155+
$expectedEntity->id = 1;
156+
$expectedEntity->type = 'type field';
157+
158+
$stmt = new HydratorMockStatement($resultSet);
159+
$hydrator = new SimpleObjectHydrator($this->entityManager);
160+
$result = $hydrator->hydrateAll($stmt, $rsm);
161+
$this->assertEquals($result[0], $expectedEntity);
162+
}
125163
}

0 commit comments

Comments
 (0)