Skip to content

Commit 3fb3ba0

Browse files
committed
Fix prepareQueryOrNewObj with object values
In convertToDatabaseValue, fallback to Type::convertPHPToDatabaseValue if the field doesn't have a mapping.
1 parent e2d0595 commit 3fb3ba0

File tree

2 files changed

+54
-7
lines changed

2 files changed

+54
-7
lines changed

lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,10 +1012,7 @@ public function prepareQueryOrNewObj(array $query, bool $isNewObj = false) : arr
10121012

10131013
$preparedQueryElements = $this->prepareQueryElement((string) $key, $value, null, true, $isNewObj);
10141014
foreach ($preparedQueryElements as [$preparedKey, $preparedValue]) {
1015-
$preparedValue = Type::convertPHPToDatabaseValue($preparedValue);
1016-
if ($this->class->hasField($key)) {
1017-
$preparedValue = $this->convertToDatabaseValue($key, $preparedValue);
1018-
}
1015+
$preparedValue = $this->convertToDatabaseValue($key, $preparedValue);
10191016
$preparedQuery[$preparedKey] = $preparedValue;
10201017
}
10211018
}
@@ -1024,16 +1021,23 @@ public function prepareQueryOrNewObj(array $query, bool $isNewObj = false) : arr
10241021
}
10251022

10261023
/**
1027-
* Converts a single value to its database representation based on the mapping type
1024+
* Converts a single value to its database representation based on the mapping type if possible.
10281025
*
10291026
* @param mixed $value
10301027
*
10311028
* @return mixed
10321029
*/
10331030
private function convertToDatabaseValue(string $fieldName, $value)
10341031
{
1035-
$mapping = $this->class->fieldMappings[$fieldName];
1036-
$typeName = $mapping['type'];
1032+
$mapping = [];
1033+
$typeName = '';
1034+
$dbValue = false;
1035+
if ($this->class->hasField($fieldName)) {
1036+
$mapping = $this->class->fieldMappings[$fieldName];
1037+
$typeName = $mapping['type'];
1038+
} else {
1039+
$dbValue = Type::convertPHPToDatabaseValue($value);
1040+
}
10371041

10381042
if (is_array($value)) {
10391043
foreach ($value as $k => $v) {
@@ -1043,6 +1047,10 @@ private function convertToDatabaseValue(string $fieldName, $value)
10431047
return $value;
10441048
}
10451049

1050+
if ($dbValue !== false) {
1051+
return $dbValue;
1052+
}
1053+
10461054
if (! empty($mapping['reference']) || ! empty($mapping['embedded'])) {
10471055
return $value;
10481056
}

tests/Doctrine/ODM/MongoDB/Tests/Functional/DocumentPersisterTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Doctrine\ODM\MongoDB\Tests\Functional;
66

77
use Closure;
8+
use DateTime;
89
use Doctrine\ODM\MongoDB\DocumentManager;
910
use Doctrine\ODM\MongoDB\LockException;
1011
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
@@ -15,6 +16,7 @@
1516
use Generator;
1617
use InvalidArgumentException;
1718
use MongoDB\BSON\ObjectId;
19+
use MongoDB\BSON\UTCDateTime;
1820
use MongoDB\Collection;
1921
use ReflectionProperty;
2022
use function get_class;
@@ -461,6 +463,43 @@ public function testPrepareQueryOrNewObjWithDBRefReferenceToTargetDocumentWithHa
461463
$this->assertEquals($expected, $documentPersister->prepareQueryOrNewObj($value));
462464
}
463465

466+
/**
467+
* @dataProvider queryProviderForComplexRefWithObjectValue
468+
*/
469+
public function testPrepareQueryOrNewObjWithComplexRefToTargetDocumentFieldWithObjectValue(array $expected, array $query)
470+
{
471+
$class = DocumentPersisterTestDocument::class;
472+
$documentPersister = $this->uow->getDocumentPersister($class);
473+
474+
$this->assertEquals(
475+
$expected,
476+
$documentPersister->prepareQueryOrNewObj($query)
477+
);
478+
}
479+
480+
public static function queryProviderForComplexRefWithObjectValue() : Generator
481+
{
482+
yield 'Direct comparison' => [
483+
'expected' => ['complexRef.date' => new UTCDateTime('1590710400000')],
484+
'query' => ['complexRef.date' => new DateTime('2020-05-29')],
485+
];
486+
487+
yield 'Operator with single value' => [
488+
'expected' => ['complexRef.date' => ['$ne' => new UTCDateTime('1590710400000')]],
489+
'query' => ['complexRef.date' => ['$ne' => new DateTime('2020-05-29')]],
490+
];
491+
492+
yield 'Operator with multiple values' => [
493+
'expected' => ['complexRef.date' => ['$in' => [new UTCDateTime('1590710400000'), new UTCDateTime('1590796800000')]]],
494+
'query' => ['complexRef.date' => ['$in' => [new DateTime('2020-05-29'), new DateTime('2020-05-30')]]],
495+
];
496+
497+
yield 'Nested operator' => [
498+
'expected' => ['complexRef.date' => ['$not' => ['$in' => [new UTCDateTime('1590710400000'), new UTCDateTime('1590796800000')]]]],
499+
'query' => ['complexRef.date' => ['$not' => ['$in' => [new DateTime('2020-05-29'), new DateTime('2020-05-30')]]]],
500+
];
501+
}
502+
464503
public function testPrepareQueryOrNewObjWithEmbeddedReferenceToTargetDocumentWithNormalIdType()
465504
{
466505
$class = DocumentPersisterTestHashIdDocument::class;

0 commit comments

Comments
 (0)