From 7864b63a818294348c18964351207f96fcf5d19d Mon Sep 17 00:00:00 2001 From: fogelito Date: Mon, 29 Jun 2026 15:48:41 +0300 Subject: [PATCH 1/2] Greptile address list of dates --- src/Database/Document.php | 5 ++- tests/e2e/Adapter/Scopes/DocumentTests.php | 36 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/Database/Document.php b/src/Database/Document.php index d50a957ca..0099ddb65 100644 --- a/src/Database/Document.php +++ b/src/Database/Document.php @@ -46,7 +46,10 @@ public function __construct(array $input = []) } foreach ($value as $childKey => $child) { - if ((isset($child['$id']) || isset($child['$collection'])) && (!$child instanceof self)) { + // Only wrap array children that look like sub-documents. Non-array elements + // (e.g. MongoDB\BSON\UTCDateTime in a datetime array, scalars, other objects) + // are not array-accessible, so isset($child['$id']) would fatal on them. + if (\is_array($child) && (isset($child['$id']) || isset($child['$collection']))) { $value[$childKey] = new self($child); } } diff --git a/tests/e2e/Adapter/Scopes/DocumentTests.php b/tests/e2e/Adapter/Scopes/DocumentTests.php index 4f998372d..cf9b6919c 100644 --- a/tests/e2e/Adapter/Scopes/DocumentTests.php +++ b/tests/e2e/Adapter/Scopes/DocumentTests.php @@ -6123,6 +6123,42 @@ public function testDateTimeDocument(): void $database->deleteCollection($collection); } + public function testDateTimeArrayDocument(): void + { + /** @var Database $database */ + $database = $this->getDatabase(); + + $collection = 'datetime_array_doc'; + $database->createCollection($collection); + $this->assertEquals(true, $database->createAttribute($collection, 'dates', Database::VAR_DATETIME, 0, false, null, false, true, null, [], ['datetime'])); + + $d1 = '2000-01-01T10:00:00.000+00:00'; + $d2 = '2001-02-03T05:06:07.000+00:00'; + + $database->createDocument($collection, new Document([ + '$id' => 'doc1', + '$permissions' => [Permission::read(Role::any()), Permission::update(Role::any())], + 'dates' => [$d1, $d2], + ])); + + // Regression: reading a datetime (object) array used to throw in Mongo with + // "Cannot use object of type MongoDB\BSON\UTCDateTime as array" because the + // Document constructor tried to array-access non-array elements. + $doc = $database->getDocument($collection, 'doc1'); + $dates = $doc->getAttribute('dates'); + $this->assertIsArray($dates); + $this->assertCount(2, $dates); + $this->assertEquals($d1, $dates[0]); + $this->assertEquals($d2, $dates[1]); + + // Same values must round-trip through find() + $found = $database->find($collection, [Query::equal('$id', ['doc1'])]); + $this->assertCount(1, $found); + $this->assertEquals([$d1, $d2], $found[0]->getAttribute('dates')); + + $database->deleteCollection($collection); + } + public function testInvalidCreatedAndUpdatedAtThrowStructureException(): void { /** @var Database $database */ From c597ffaf56a3b2dd1acac276fb4255a26fe62952 Mon Sep 17 00:00:00 2001 From: fogelito Date: Mon, 29 Jun 2026 16:07:44 +0300 Subject: [PATCH 2/2] Message --- src/Database/Document.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Database/Document.php b/src/Database/Document.php index 0099ddb65..73bd458cd 100644 --- a/src/Database/Document.php +++ b/src/Database/Document.php @@ -46,9 +46,10 @@ public function __construct(array $input = []) } foreach ($value as $childKey => $child) { - // Only wrap array children that look like sub-documents. Non-array elements - // (e.g. MongoDB\BSON\UTCDateTime in a datetime array, scalars, other objects) - // are not array-accessible, so isset($child['$id']) would fatal on them. + // An array value is either a list of nested sub-documents or a list of + // plain items (dates, numbers, strings): wrap the former, leave the latter. + // is_array() tells them apart and avoids array-accessing a non-array + // value (e.g. a UTCDateTime), which would otherwise fatal. if (\is_array($child) && (isset($child['$id']) || isset($child['$collection']))) { $value[$childKey] = new self($child); }