Skip to content

Commit ee4369b

Browse files
committed
Extract Collection findAndModify methods to operation classes
1 parent 8fea8b4 commit ee4369b

File tree

5 files changed

+546
-254
lines changed

5 files changed

+546
-254
lines changed

src/Collection.php

Lines changed: 40 additions & 254 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
use MongoDB\Operation\CreateIndexes;
2020
use MongoDB\Operation\Count;
2121
use MongoDB\Operation\Distinct;
22+
use MongoDB\Operation\FindOneAndDelete;
23+
use MongoDB\Operation\FindOneAndReplace;
24+
use MongoDB\Operation\FindOneAndUpdate;
2225
use Traversable;
2326

2427
class Collection
@@ -452,103 +455,63 @@ public function findOne(array $filter = array(), array $options = array())
452455
/**
453456
* Finds a single document and deletes it, returning the original.
454457
*
455-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
456-
* @see Collection::getFindOneAndDelete() for supported $options
458+
* The document to return may be null.
457459
*
458-
* @param array $filter The $filter criteria to search for
459-
* @param array $options Additional options
460-
* @return array The original document
460+
* @see FindOneAndDelete::__construct() for supported options
461+
* @param array|object $filter Query by which to filter documents
462+
* @param array $options Command options
463+
* @return array|null
461464
*/
462-
public function findOneAndDelete(array $filter, array $options = array())
465+
public function findOneAndDelete($filter, array $options = array())
463466
{
464-
$options = array_merge($this->getFindOneAndDeleteOptions(), $options);
465-
$options = $this->_massageFindAndModifyOptions($options);
466-
$cmd = array(
467-
"findandmodify" => $this->collname,
468-
"query" => $filter,
469-
) + $options;
470-
471-
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray());
472-
if ($doc["ok"]) {
473-
return is_object($doc["value"]) ? (array) $doc["value"] : $doc["value"];
474-
}
467+
$operation = new FindOneAndDelete($this->dbname, $this->collname, $filter, $options);
468+
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
475469

476-
throw $this->_generateCommandException($doc);
470+
return $operation->execute($server);
477471
}
478472

479473
/**
480-
* Finds a single document and replaces it, returning either the original or the replaced document
481-
* By default, returns the original document.
482-
* To return the new document set:
483-
* $options = array("returnDocument" => Collection::FIND_ONE_AND_RETURN_AFTER);
474+
* Finds a single document and replaces it, returning either the original or
475+
* the replaced document.
484476
*
485-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
486-
* @see Collection::getFindOneAndReplace() for supported $options
477+
* The document to return may be null. By default, the original document is
478+
* returned. Specify FindOneAndReplace::RETURN_DOCUMENT_AFTER for the
479+
* "returnDocument" option to return the updated document.
487480
*
488-
* @param array $filter The $filter criteria to search for
489-
* @param array $replacement The document to replace with
490-
* @param array $options Additional options
491-
* @return array
481+
* @see FindOneAndReplace::__construct() for supported options
482+
* @param array|object $filter Query by which to filter documents
483+
* @param array|object $replacement Replacement document
484+
* @param array $options Command options
485+
* @return array|null
492486
*/
493-
public function findOneAndReplace(array $filter, array $replacement, array $options = array())
487+
public function findOneAndReplace($filter, $replacement, array $options = array())
494488
{
495-
$firstKey = key($replacement);
496-
if (isset($firstKey[0]) && $firstKey[0] == '$') {
497-
throw new InvalidArgumentException("First key in \$replacement must NOT be a \$operator");
498-
}
499-
500-
$options = array_merge($this->getFindOneAndReplaceOptions(), $options);
501-
$options = $this->_massageFindAndModifyOptions($options, $replacement);
502-
503-
$cmd = array(
504-
"findandmodify" => $this->collname,
505-
"query" => $filter,
506-
) + $options;
507-
508-
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray());
509-
if ($doc["ok"]) {
510-
return $this->_massageFindAndModifyResult($doc, $options);
511-
}
489+
$operation = new FindOneAndReplace($this->dbname, $this->collname, $filter, $replacement, $options);
490+
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
512491

513-
throw $this->_generateCommandException($doc);
492+
return $operation->execute($server);
514493
}
515494

516495
/**
517-
* Finds a single document and updates it, returning either the original or the updated document
518-
* By default, returns the original document.
519-
* To return the new document set:
520-
* $options = array("returnDocument" => Collection::FIND_ONE_AND_RETURN_AFTER);
496+
* Finds a single document and updates it, returning either the original or
497+
* the updated document.
521498
*
499+
* The document to return may be null. By default, the original document is
500+
* returned. Specify FindOneAndUpdate::RETURN_DOCUMENT_AFTER for the
501+
* "returnDocument" option to return the updated document.
522502
*
523-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
524-
* @see Collection::getFindOneAndUpdate() for supported $options
525-
*
526-
* @param array $filter The $filter criteria to search for
527-
* @param array $update An array of update operators to apply to the document
528-
* @param array $options Additional options
529-
* @return array
503+
* @see FindOneAndReplace::__construct() for supported options
504+
* @param array|object $filter Query by which to filter documents
505+
* @param array|object $update Update to apply to the matched document
506+
* @param array $options Command options
507+
* @return array|null
530508
*/
531-
public function findOneAndUpdate(array $filter, array $update, array $options = array())
509+
public function findOneAndUpdate($filter, $update, array $options = array())
532510
{
533-
$firstKey = key($update);
534-
if (!isset($firstKey[0]) || $firstKey[0] != '$') {
535-
throw new InvalidArgumentException("First key in \$update must be a \$operator");
536-
}
537-
538-
$options = array_merge($this->getFindOneAndUpdateOptions(), $options);
539-
$options = $this->_massageFindAndModifyOptions($options, $update);
540-
541-
$cmd = array(
542-
"findandmodify" => $this->collname,
543-
"query" => $filter,
544-
) + $options;
545-
546-
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray());
547-
if ($doc["ok"]) {
548-
return $this->_massageFindAndModifyResult($doc, $options);
549-
}
511+
$operation = new FindOneAndUpdate($this->dbname, $this->collname, $filter, $update, $options);
512+
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
550513

551-
throw $this->_generateCommandException($doc);
514+
return $operation->execute($server);
552515
}
553516

554517
/**
@@ -583,133 +546,6 @@ public function getDatabaseName()
583546
return $this->dbname;
584547
}
585548

586-
/**
587-
* Retrieves all findOneDelete options with their default values.
588-
*
589-
* @return array of Collection::findOneAndDelete() options
590-
*/
591-
public function getFindOneAndDeleteOptions()
592-
{
593-
return array(
594-
595-
/**
596-
* The maximum amount of time to allow the query to run.
597-
*
598-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
599-
*/
600-
"maxTimeMS" => 0,
601-
602-
/**
603-
* Limits the fields to return for all matching documents.
604-
*
605-
* @see http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results
606-
*/
607-
"projection" => array(),
608-
609-
/**
610-
* Determines which document the operation modifies if the query selects multiple documents.
611-
*
612-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
613-
*/
614-
"sort" => array(),
615-
);
616-
}
617-
618-
/**
619-
* Retrieves all findOneAndReplace options with their default values.
620-
*
621-
* @return array of Collection::findOneAndReplace() options
622-
*/
623-
public function getFindOneAndReplaceOptions()
624-
{
625-
return array(
626-
627-
/**
628-
* The maximum amount of time to allow the query to run.
629-
*
630-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
631-
*/
632-
"maxTimeMS" => 0,
633-
634-
/**
635-
* Limits the fields to return for all matching documents.
636-
*
637-
* @see http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results
638-
*/
639-
"projection" => array(),
640-
641-
/**
642-
* When ReturnDocument.After, returns the replaced or inserted document rather than the original.
643-
* Defaults to ReturnDocument.Before.
644-
*
645-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
646-
*/
647-
"returnDocument" => self::FIND_ONE_AND_RETURN_BEFORE,
648-
649-
/**
650-
* Determines which document the operation modifies if the query selects multiple documents.
651-
*
652-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
653-
*/
654-
"sort" => array(),
655-
656-
/**
657-
* When true, findAndModify creates a new document if no document matches the query. The
658-
* default is false.
659-
*
660-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
661-
*/
662-
"upsert" => false,
663-
);
664-
}
665-
666-
/**
667-
* Retrieves all findOneAndUpdate options with their default values.
668-
*
669-
* @return array of Collection::findOneAndUpdate() options
670-
*/
671-
public function getFindOneAndUpdateOptions()
672-
{
673-
return array(
674-
675-
/**
676-
* The maximum amount of time to allow the query to run.
677-
*
678-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
679-
*/
680-
"maxTimeMS" => 0,
681-
682-
/**
683-
* Limits the fields to return for all matching documents.
684-
*
685-
* @see http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results
686-
*/
687-
"projection" => array(),
688-
689-
/**
690-
* When ReturnDocument.After, returns the updated or inserted document rather than the original.
691-
* Defaults to ReturnDocument.Before.
692-
*
693-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
694-
*/
695-
"returnDocument" => self::FIND_ONE_AND_RETURN_BEFORE,
696-
697-
/**
698-
* Determines which document the operation modifies if the query selects multiple documents.
699-
*
700-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
701-
*/
702-
"sort" => array(),
703-
704-
/**
705-
* When true, creates a new document if no document matches the query. The default is false.
706-
*
707-
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
708-
*/
709-
"upsert" => false,
710-
);
711-
}
712-
713549
/**
714550
* Retrieves all find options with their default values.
715551
*
@@ -1025,56 +861,6 @@ final protected function _generateCommandException($doc)
1025861
return new RuntimeException("FIXME: Unknown error");
1026862
}
1027863

1028-
/**
1029-
* Internal helper for massaging findandmodify options
1030-
* @internal
1031-
*/
1032-
final protected function _massageFindAndModifyOptions($options, $update = array())
1033-
{
1034-
$ret = array(
1035-
"sort" => $options["sort"],
1036-
"new" => isset($options["returnDocument"]) ? $options["returnDocument"] == self::FIND_ONE_AND_RETURN_AFTER : false,
1037-
"fields" => $options["projection"],
1038-
"upsert" => isset($options["upsert"]) ? $options["upsert"] : false,
1039-
);
1040-
if ($update) {
1041-
$ret["update"] = $update;
1042-
} else {
1043-
$ret["remove"] = true;
1044-
}
1045-
return $ret;
1046-
}
1047-
1048-
/**
1049-
* Internal helper for massaging the findAndModify result.
1050-
*
1051-
* @internal
1052-
* @param array $result
1053-
* @param array $options
1054-
* @return array|null
1055-
*/
1056-
final protected function _massageFindAndModifyResult(array $result, array $options)
1057-
{
1058-
if ($result['value'] === null) {
1059-
return null;
1060-
}
1061-
1062-
/* Prior to 3.0, findAndModify returns an empty document instead of null
1063-
* when an upsert is performed and the pre-modified document was
1064-
* requested.
1065-
*/
1066-
if ($options['upsert'] && ! $options['new'] &&
1067-
isset($result['lastErrorObject']->updatedExisting) &&
1068-
! $result['lastErrorObject']->updatedExisting) {
1069-
1070-
return null;
1071-
}
1072-
1073-
return is_object($result["value"])
1074-
? (array) $result['value']
1075-
: $result['value'];
1076-
}
1077-
1078864
/**
1079865
* Constructs the Query Wire Protocol field 'flags' based on $options
1080866
* provided to other helpers

0 commit comments

Comments
 (0)