Skip to content

Commit c1c6fab

Browse files
committed
PHPLIB-157: Improve _id extraction for Serializable objects
1 parent 6663cf7 commit c1c6fab

File tree

7 files changed

+55
-14
lines changed

7 files changed

+55
-14
lines changed

src/Operation/BulkWrite.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,7 @@ public function execute(Server $server)
239239
if ($insertedId !== null) {
240240
$insertedIds[$i] = $insertedId;
241241
} else {
242-
// TODO: This may be removed if PHPC-382 is implemented
243-
$insertedIds[$i] = is_array($args[0]) ? $args[0]['_id'] : $args[0]->_id;
242+
$insertedIds[$i] = \MongoDB\extract_id_from_inserted_document($args[0]);
244243
}
245244

246245
break;

src/Operation/InsertMany.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,7 @@ public function execute(Server $server)
109109
if ($insertedId !== null) {
110110
$insertedIds[$i] = $insertedId;
111111
} else {
112-
// TODO: This may be removed if PHPC-382 is implemented
113-
$insertedIds[$i] = is_array($document) ? $document['_id'] : $document->_id;
112+
$insertedIds[$i] = \MongoDB\extract_id_from_inserted_document($document);
114113
}
115114
}
116115

src/Operation/InsertOne.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ public function execute(Server $server)
7979
$insertedId = $bulk->insert($this->document);
8080

8181
if ($insertedId === null) {
82-
// TODO: This may be removed if PHPC-382 is implemented
83-
$insertedId = is_array($this->document) ? $this->document['_id'] : $this->document->_id;
82+
$insertedId = \MongoDB\extract_id_from_inserted_document($this->document);
8483
}
8584

8685
$writeConcern = isset($this->options['writeConcern']) ? $this->options['writeConcern'] : null;

src/functions.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,33 @@
22

33
namespace MongoDB;
44

5+
use MongoDB\BSON\Serializable;
56
use MongoDB\Driver\ReadConcern;
67
use MongoDB\Driver\Server;
78
use MongoDB\Exception\InvalidArgumentTypeException;
89
use stdClass;
910

11+
/**
12+
* Extracts an ID from an inserted document.
13+
*
14+
* This function is used when BulkWrite::insert() does not return a generated
15+
* ID, which means that the ID should be fetched from an array offset, public
16+
* property, or in the data returned by bsonSerialize().
17+
*
18+
* @internal
19+
* @see https://jira.mongodb.org/browse/PHPC-382
20+
* @param array|object $document Inserted document
21+
* @return mixed
22+
*/
23+
function extract_id_from_inserted_document($document)
24+
{
25+
if ($document instanceof Serializable) {
26+
return extract_id_from_inserted_document($document->bsonSerialize());
27+
}
28+
29+
return is_array($document) ? $document['_id'] : $document->_id;
30+
}
31+
1032
/**
1133
* Generate an index name from a key specification.
1234
*

tests/Operation/BulkWriteFunctionalTest.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use MongoDB\BulkWriteResult;
66
use MongoDB\Driver\BulkWrite as Bulk;
77
use MongoDB\Driver\WriteConcern;
8+
use MongoDB\Model\BSONDocument;
89
use MongoDB\Operation\BulkWrite;
910

1011
class BulkWriteFunctionalTest extends FunctionalTestCase
@@ -23,21 +24,27 @@ public function testInserts()
2324
$ops = [
2425
['insertOne' => [['_id' => 1, 'x' => 11]]],
2526
['insertOne' => [['x' => 22]]],
27+
['insertOne' => [(object) ['_id' => 'foo', 'x' => 33]]],
28+
['insertOne' => [new BSONDocument(['_id' => 'bar', 'x' => 44])]],
2629
];
2730

2831
$operation = new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), $ops);
2932
$result = $operation->execute($this->getPrimaryServer());
3033

3134
$this->assertInstanceOf('MongoDB\BulkWriteResult', $result);
32-
$this->assertSame(2, $result->getInsertedCount());
35+
$this->assertSame(4, $result->getInsertedCount());
3336

3437
$insertedIds = $result->getInsertedIds();
3538
$this->assertSame(1, $insertedIds[0]);
3639
$this->assertInstanceOf('MongoDB\BSON\ObjectId', $insertedIds[1]);
40+
$this->assertSame('foo', $insertedIds[2]);
41+
$this->assertSame('bar', $insertedIds[3]);
3742

3843
$expected = [
39-
['_id' => $insertedIds[0], 'x' => 11],
44+
['_id' => 1, 'x' => 11],
4045
['_id' => $insertedIds[1], 'x' => 22],
46+
['_id' => 'foo', 'x' => 33],
47+
['_id' => 'bar', 'x' => 44],
4148
];
4249

4350
$this->assertSameDocuments($expected, $this->collection->find());

tests/Operation/InsertManyFunctionalTest.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use MongoDB\InsertManyResult;
66
use MongoDB\Driver\WriteConcern;
7+
use MongoDB\Model\BSONDocument;
78
use MongoDB\Operation\InsertMany;
89

910
class InsertManyFunctionalTest extends FunctionalTestCase
@@ -13,24 +14,27 @@ public function testInsertMany()
1314
$documents = [
1415
['_id' => 'foo', 'x' => 11],
1516
['x' => 22],
16-
['_id' => 'bar', 'x' => 22],
17+
(object) ['_id' => 'bar', 'x' => 33],
18+
new BSONDocument(['_id' => 'baz', 'x' => 44]),
1719
];
1820

1921
$operation = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), $documents);
2022
$result = $operation->execute($this->getPrimaryServer());
2123

2224
$this->assertInstanceOf('MongoDB\InsertManyResult', $result);
23-
$this->assertSame(3, $result->getInsertedCount());
25+
$this->assertSame(4, $result->getInsertedCount());
2426

2527
$insertedIds = $result->getInsertedIds();
2628
$this->assertSame('foo', $insertedIds[0]);
2729
$this->assertInstanceOf('MongoDB\BSON\ObjectId', $insertedIds[1]);
2830
$this->assertSame('bar', $insertedIds[2]);
31+
$this->assertSame('baz', $insertedIds[3]);
2932

3033
$expected = [
3134
['_id' => 'foo', 'x' => 11],
3235
['_id' => $insertedIds[1], 'x' => 22],
33-
['_id' => 'bar', 'x' => 22],
36+
['_id' => 'bar', 'x' => 33],
37+
['_id' => 'baz', 'x' => 44],
3438
];
3539

3640
$this->assertSameDocuments($expected, $this->collection->find());

tests/Operation/InsertOneFunctionalTest.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44

55
use MongoDB\InsertOneResult;
66
use MongoDB\Driver\WriteConcern;
7+
use MongoDB\Model\BSONDocument;
78
use MongoDB\Operation\InsertOne;
89

910
class InsertOneFunctionalTest extends FunctionalTestCase
1011
{
11-
public function testInsertOneWithExistingId()
12+
/**
13+
* @dataProvider provideDocumentWithExistingId
14+
*/
15+
public function testInsertOneWithExistingId($document)
1216
{
13-
$document = ['_id' => 'foo', 'x' => 11];
14-
1517
$operation = new InsertOne($this->getDatabaseName(), $this->getCollectionName(), $document);
1618
$result = $operation->execute($this->getPrimaryServer());
1719

@@ -26,6 +28,15 @@ public function testInsertOneWithExistingId()
2628
$this->assertSameDocuments($expected, $this->collection->find());
2729
}
2830

31+
public function provideDocumentWithExistingId()
32+
{
33+
return [
34+
[['_id' => 'foo', 'x' => 11]],
35+
[(object) ['_id' => 'foo', 'x' => 11]],
36+
[new BSONDocument(['_id' => 'foo', 'x' => 11])],
37+
];
38+
}
39+
2940
public function testInsertOneWithGeneratedId()
3041
{
3142
$document = ['x' => 11];

0 commit comments

Comments
 (0)