Skip to content

Commit 786025d

Browse files
committed
PHPLIB-95: Massage findAndModify null results before 3.0
Earlier server versions incorrectly return an empty document instead of null. Thankfully, we can detect this edge case given the command result and input options.
1 parent fed26a9 commit 786025d

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

src/Collection.php

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ public function findOneAndReplace(array $filter, array $replacement, array $opti
534534

535535
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray());
536536
if ($doc["ok"]) {
537-
return is_object($doc["value"]) ? (array) $doc["value"] : $doc["value"];
537+
return $this->_massageFindAndModifyResult($doc, $options);
538538
}
539539

540540
throw $this->_generateCommandException($doc);
@@ -572,7 +572,7 @@ public function findOneAndUpdate(array $filter, array $update, array $options =
572572

573573
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray());
574574
if ($doc["ok"]) {
575-
return is_object($doc["value"]) ? (array) $doc["value"] : $doc["value"];
575+
return $this->_massageFindAndModifyResult($doc, $options);
576576
}
577577

578578
throw $this->_generateCommandException($doc);
@@ -1179,6 +1179,36 @@ final protected function _massageFindAndModifyOptions($options, $update = array(
11791179
return $ret;
11801180
}
11811181

1182+
/**
1183+
* Internal helper for massaging the findAndModify result.
1184+
*
1185+
* @internal
1186+
* @param array $result
1187+
* @param array $options
1188+
* @return array|null
1189+
*/
1190+
final protected function _massageFindAndModifyResult(array $result, array $options)
1191+
{
1192+
if ($result['value'] === null) {
1193+
return null;
1194+
}
1195+
1196+
/* Prior to 3.0, findAndModify returns an empty document instead of null
1197+
* when an upsert is performed and the pre-modified document was
1198+
* requested.
1199+
*/
1200+
if ($options['upsert'] && ! $options['new'] &&
1201+
isset($result['lastErrorObject']->updatedExisting) &&
1202+
! $result['lastErrorObject']->updatedExisting) {
1203+
1204+
return null;
1205+
}
1206+
1207+
return is_object($result["value"])
1208+
? (array) $result['value']
1209+
: $result['value'];
1210+
}
1211+
11821212
/**
11831213
* Constructs the Query Wire Protocol field 'flags' based on $options
11841214
* provided to other helpers

0 commit comments

Comments
 (0)