Skip to content

Commit 703401d

Browse files
committed
Merge pull request #658
2 parents 5e503d0 + 502bb85 commit 703401d

13 files changed

+273
-293
lines changed

docs/includes/apiargs-MongoDBCollection-method-distinct-option.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,10 @@ source:
1919
ref: session
2020
post: |
2121
.. versionadded:: 1.3
22+
---
23+
source:
24+
file: apiargs-MongoDBCollection-common-option.yaml
25+
ref: typeMap
26+
post: |
27+
.. versionadded:: 1.5
2228
...

src/Model/TypeMapArrayIterator.php

Lines changed: 0 additions & 172 deletions
This file was deleted.

src/Operation/Aggregate.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
use MongoDB\Exception\InvalidArgumentException;
2828
use MongoDB\Exception\UnexpectedValueException;
2929
use MongoDB\Exception\UnsupportedException;
30-
use MongoDB\Model\TypeMapArrayIterator;
3130
use ArrayIterator;
3231
use stdClass;
3332
use Traversable;
@@ -280,16 +279,16 @@ public function execute(Server $server)
280279
return $cursor;
281280
}
282281

282+
if (isset($this->options['typeMap'])) {
283+
$cursor->setTypeMap(\MongoDB\create_field_path_type_map($this->options['typeMap'], 'result.$'));
284+
}
285+
283286
$result = current($cursor->toArray());
284287

285288
if ( ! isset($result->result) || ! is_array($result->result)) {
286289
throw new UnexpectedValueException('aggregate command did not return a "result" array');
287290
}
288291

289-
if (isset($this->options['typeMap'])) {
290-
return new TypeMapArrayIterator($result->result, $this->options['typeMap']);
291-
}
292-
293292
return new ArrayIterator($result->result);
294293
}
295294

src/Operation/Distinct.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class Distinct implements Executable, Explainable
6969
*
7070
* Sessions are not supported for server versions < 3.6.
7171
*
72+
* * typeMap (array): Type map for BSON deserialization.
73+
*
7274
* @param string $databaseName Database name
7375
* @param string $collectionName Collection name
7476
* @param string $fieldName Field for which to return distinct values
@@ -102,6 +104,10 @@ public function __construct($databaseName, $collectionName, $fieldName, $filter
102104
throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class);
103105
}
104106

107+
if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
108+
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
109+
}
110+
105111
if (isset($options['readConcern']) && $options['readConcern']->isDefault()) {
106112
unset($options['readConcern']);
107113
}
@@ -139,6 +145,11 @@ public function execute(Server $server)
139145
}
140146

141147
$cursor = $server->executeReadCommand($this->databaseName, new Command($this->createCommandDocument()), $this->createOptions());
148+
149+
if (isset($this->options['typeMap'])) {
150+
$cursor->setTypeMap(\MongoDB\create_field_path_type_map($this->options['typeMap'], 'values.$'));
151+
}
152+
142153
$result = current($cursor->toArray());
143154

144155
if ( ! isset($result->values) || ! is_array($result->values)) {

src/Operation/FindAndModify.php

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -216,21 +216,14 @@ public function execute(Server $server)
216216
}
217217

218218
$cursor = $server->executeWriteCommand($this->databaseName, new Command($this->createCommandDocument($server)), $this->createOptions());
219-
$result = current($cursor->toArray());
220-
221-
if ( ! isset($result->value)) {
222-
return null;
223-
}
224-
225-
if ( ! is_object($result->value)) {
226-
throw new UnexpectedValueException('findAndModify command did not return a "value" document');
227-
}
228219

229220
if (isset($this->options['typeMap'])) {
230-
return \MongoDB\apply_type_map_to_document($result->value, $this->options['typeMap']);
221+
$cursor->setTypeMap(\MongoDB\create_field_path_type_map($this->options['typeMap'], 'value'));
231222
}
232223

233-
return $result->value;
224+
$result = current($cursor->toArray());
225+
226+
return isset($result->value) ? $result->value : null;
234227
}
235228

236229
public function getCommandDocument(Server $server)

src/Operation/MapReduce.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
use MongoDB\Exception\InvalidArgumentException;
2929
use MongoDB\Exception\UnexpectedValueException;
3030
use MongoDB\Exception\UnsupportedException;
31-
use MongoDB\Model\TypeMapArrayIterator;
3231
use MongoDB\MapReduceResult;
3332
use ArrayIterator;
3433
use stdClass;
@@ -267,6 +266,10 @@ public function execute(Server $server)
267266
? $server->executeReadWriteCommand($this->databaseName, $command, $options)
268267
: $server->executeReadCommand($this->databaseName, $command, $options);
269268

269+
if (isset($this->options['typeMap']) && ! $hasOutputCollection) {
270+
$cursor->setTypeMap(\MongoDB\create_field_path_type_map($this->options['typeMap'], 'results.$'));
271+
}
272+
270273
$result = current($cursor->toArray());
271274

272275
$getIterator = $this->createGetIteratorCallable($result, $server);
@@ -326,10 +329,6 @@ private function createGetIteratorCallable(stdClass $result, Server $server)
326329
$results = $result->results;
327330

328331
return function() use ($results) {
329-
if (isset($this->options['typeMap'])) {
330-
return new TypeMapArrayIterator($results, $this->options['typeMap']);
331-
}
332-
333332
return new ArrayIterator($results);
334333
};
335334
}

src/functions.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,46 @@ function recursive_copy($element) {
241241

242242
return clone $element;
243243
}
244+
245+
/**
246+
* Creates a type map to apply to a field type
247+
*
248+
* This is used in the Aggregate, Distinct, and FindAndModify operations to
249+
* apply the root-level type map to the document that will be returned. It also
250+
* replaces the root type with object for consistency within these operations
251+
*
252+
* An existing type map for the given field path will not be overwritten
253+
*
254+
* @internal
255+
* @param array $typeMap The existing typeMap
256+
* @param string $fieldPath The field path to apply the root type to
257+
* @return array
258+
*/
259+
function create_field_path_type_map(array $typeMap, $fieldPath)
260+
{
261+
// If some field paths already exist, we prefix them with the field path we are assuming as the new root
262+
if (isset($typeMap['fieldPaths']) && is_array($typeMap['fieldPaths'])) {
263+
$fieldPaths = $typeMap['fieldPaths'];
264+
265+
$typeMap['fieldPaths'] = [];
266+
foreach ($fieldPaths as $existingFieldPath => $type) {
267+
$typeMap['fieldPaths'][$fieldPath . '.' . $existingFieldPath] = $type;
268+
}
269+
}
270+
271+
// If a root typemap was set, apply this to the field object
272+
if (isset($typeMap['root'])) {
273+
$typeMap['fieldPaths'][$fieldPath] = $typeMap['root'];
274+
}
275+
276+
/* Special case if we want to convert an array, in which case we need to
277+
* ensure that the field containing the array is exposed as an array,
278+
* instead of the type given in the type map's array key. */
279+
if (substr($fieldPath, -2, 2) === '.$') {
280+
$typeMap['fieldPaths'][substr($fieldPath, 0, -2)] = 'array';
281+
}
282+
283+
$typeMap['root'] = 'object';
284+
285+
return $typeMap;
286+
}

0 commit comments

Comments
 (0)