Skip to content

Commit 83ca5a8

Browse files
committed
PHPORM-230 Convert DateTimeInterface to UTCDateTime in queries
1 parent a453f8a commit 83ca5a8

File tree

4 files changed

+36
-45
lines changed

4 files changed

+36
-45
lines changed

src/Query/Builder.php

+20-38
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
use function array_map;
3333
use function array_merge;
3434
use function array_values;
35-
use function array_walk_recursive;
3635
use function assert;
3736
use function blank;
3837
use function call_user_func;
@@ -689,17 +688,7 @@ public function insert(array $values)
689688
$values = [$values];
690689
}
691690

692-
// Compatibility with Eloquent queries that uses "id" instead of MongoDB's _id
693-
foreach ($values as &$document) {
694-
if (isset($document['id'])) {
695-
if (isset($document['_id']) && $document['_id'] !== $document['id']) {
696-
throw new InvalidArgumentException('Cannot insert document with different "id" and "_id" values');
697-
}
698-
699-
$document['_id'] = $document['id'];
700-
unset($document['id']);
701-
}
702-
}
691+
$values = $this->aliasIdForQuery($values);
703692

704693
$options = $this->inheritConnectionOptions();
705694

@@ -876,6 +865,7 @@ public function delete($id = null)
876865
}
877866

878867
$wheres = $this->compileWheres();
868+
$wheres = $this->aliasIdForQuery($wheres);
879869
$options = $this->inheritConnectionOptions();
880870

881871
if (is_int($this->limit)) {
@@ -1080,6 +1070,7 @@ protected function performUpdate(array $update, array $options = [])
10801070
$options = $this->inheritConnectionOptions($options);
10811071

10821072
$wheres = $this->compileWheres();
1073+
$wheres = $this->aliasIdForQuery($wheres);
10831074
$result = $this->collection->updateMany($wheres, $update, $options);
10841075
if ($result->isAcknowledged()) {
10851076
return $result->getModifiedCount() ? $result->getModifiedCount() : $result->getUpsertedCount();
@@ -1191,32 +1182,12 @@ protected function compileWheres(): array
11911182
}
11921183
}
11931184

1194-
// Convert DateTime values to UTCDateTime.
1195-
if (isset($where['value'])) {
1196-
if (is_array($where['value'])) {
1197-
array_walk_recursive($where['value'], function (&$item, $key) {
1198-
if ($item instanceof DateTimeInterface) {
1199-
$item = new UTCDateTime($item);
1200-
}
1201-
});
1202-
} else {
1203-
if ($where['value'] instanceof DateTimeInterface) {
1204-
$where['value'] = new UTCDateTime($where['value']);
1205-
}
1206-
}
1207-
} elseif (isset($where['values'])) {
1208-
if (is_array($where['values'])) {
1209-
array_walk_recursive($where['values'], function (&$item, $key) {
1210-
if ($item instanceof DateTimeInterface) {
1211-
$item = new UTCDateTime($item);
1212-
}
1213-
});
1214-
} elseif ($where['values'] instanceof CarbonPeriod) {
1215-
$where['values'] = [
1216-
new UTCDateTime($where['values']->getStartDate()),
1217-
new UTCDateTime($where['values']->getEndDate()),
1218-
];
1219-
}
1185+
// Convert CarbonPeriod to DateTime interval.
1186+
if (isset($where['values']) && $where['values'] instanceof CarbonPeriod) {
1187+
$where['values'] = [
1188+
$where['values']->getStartDate(),
1189+
$where['values']->getEndDate(),
1190+
];
12201191
}
12211192

12221193
// In a sequence of "where" clauses, the logical operator of the
@@ -1631,12 +1602,21 @@ public function orWhereIntegerNotInRaw($column, $values, $boolean = 'and')
16311602
private function aliasIdForQuery(array $values): array
16321603
{
16331604
if (array_key_exists('id', $values)) {
1605+
if (array_key_exists('_id', $values)) {
1606+
throw new InvalidArgumentException('Cannot have both "id" and "_id" fields.');
1607+
}
1608+
16341609
$values['_id'] = $values['id'];
16351610
unset($values['id']);
16361611
}
16371612

16381613
foreach ($values as $key => $value) {
16391614
if (is_string($key) && str_ends_with($key, '.id')) {
1615+
$newkey = substr($key, 0, -3) . '._id';
1616+
if (array_key_exists($newkey, $values)) {
1617+
throw new InvalidArgumentException(sprintf('Cannot have both "%s" and "%s" fields.', $key, $newkey));
1618+
}
1619+
16401620
$values[substr($key, 0, -3) . '._id'] = $value;
16411621
unset($values[$key]);
16421622
}
@@ -1645,6 +1625,8 @@ private function aliasIdForQuery(array $values): array
16451625
foreach ($values as &$value) {
16461626
if (is_array($value)) {
16471627
$value = $this->aliasIdForQuery($value);
1628+
} elseif ($value instanceof DateTimeInterface) {
1629+
$value = new UTCDateTime($value);
16481630
}
16491631
}
16501632

tests/Query/AggregationBuilderTest.php

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use InvalidArgumentException;
1212
use MongoDB\BSON\Document;
1313
use MongoDB\BSON\ObjectId;
14-
use MongoDB\BSON\UTCDateTime;
1514
use MongoDB\Builder\BuilderEncoder;
1615
use MongoDB\Builder\Expression;
1716
use MongoDB\Builder\Pipeline;
@@ -33,8 +32,8 @@ public function tearDown(): void
3332
public function testCreateAggregationBuilder(): void
3433
{
3534
User::insert([
36-
['name' => 'John Doe', 'birthday' => new UTCDateTime(new DateTimeImmutable('1989-01-01'))],
37-
['name' => 'Jane Doe', 'birthday' => new UTCDateTime(new DateTimeImmutable('1990-01-01'))],
35+
['name' => 'John Doe', 'birthday' => new DateTimeImmutable('1989-01-01')],
36+
['name' => 'Jane Doe', 'birthday' => new DateTimeImmutable('1990-01-01')],
3837
]);
3938

4039
// Create the aggregation pipeline from the query builder

tests/Query/BuilderTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,12 @@ function (Builder $builder) {
566566
fn (Builder $builder) => $builder->whereBetween('id', [[1], [2, 3]]),
567567
];
568568

569+
$date = new DateTimeImmutable('2018-09-30 15:00:00 +02:00');
570+
yield 'where $lt DateTimeInterface' => [
571+
['find' => [['created_at' => ['$lt' => new UTCDateTime($date)]], []]],
572+
fn (Builder $builder) => $builder->where('created_at', '<', $date),
573+
];
574+
569575
$period = now()->toPeriod(now()->addMonth());
570576
yield 'whereBetween CarbonPeriod' => [
571577
[

tests/QueryBuilderTest.php

+8-4
Original file line numberDiff line numberDiff line change
@@ -1053,16 +1053,20 @@ public function testIncrementEach()
10531053
#[TestWith(['id', 'id'])]
10541054
#[TestWith(['id', '_id'])]
10551055
#[TestWith(['_id', 'id'])]
1056+
#[TestWith(['_id', '_id'])]
10561057
public function testIdAlias($insertId, $queryId): void
10571058
{
1058-
DB::collection('items')->insert([$insertId => 'abc', 'name' => 'Karting']);
1059-
$item = DB::collection('items')->where($queryId, '=', 'abc')->first();
1059+
DB::table('items')->insert([$insertId => 'abc', 'name' => 'Karting']);
1060+
$item = DB::table('items')->where($queryId, '=', 'abc')->first();
10601061
$this->assertNotNull($item);
10611062
$this->assertSame('abc', $item['id']);
10621063
$this->assertSame('Karting', $item['name']);
10631064

1064-
DB::collection('items')->where($insertId, '=', 'abc')->update(['name' => 'Bike']);
1065-
$item = DB::collection('items')->where($queryId, '=', 'abc')->first();
1065+
DB::table('items')->where($insertId, '=', 'abc')->update(['name' => 'Bike']);
1066+
$item = DB::table('items')->where($queryId, '=', 'abc')->first();
10661067
$this->assertSame('Bike', $item['name']);
1068+
1069+
$result = DB::table('items')->where($queryId, '=', 'abc')->delete();
1070+
$this->assertSame(1, $result);
10671071
}
10681072
}

0 commit comments

Comments
 (0)