@@ -18,6 +18,9 @@ class Collection {
18
18
const UPDATE = 0x02 ;
19
19
const DELETE = 0x04 ;
20
20
21
+ const FIND_ONE_AND_RETURN_BEFORE = 0x01 ;
22
+ const FIND_ONE_AND_RETURN_AFTER = 0x02 ;
23
+
21
24
protected $ manager ;
22
25
protected $ rp ;
23
26
protected $ wc ;
@@ -364,6 +367,88 @@ protected function _massageAggregateOptions($options) { /* {{{ */
364
367
return $ options ;
365
368
} /* }}} */
366
369
370
+ /* {{{ findAndModify */
371
+
372
+ function findOneAndReplace (array $ filter , array $ replacement , array $ options = array ()) { /* {{{ */
373
+ if (key ($ replacement )[0 ] == '$ ' ) {
374
+ throw new \RuntimeException ("First key in \$replacement must NOT be a \$operator " );
375
+ }
376
+
377
+ $ options = array_merge ($ this ->getFindOneAndReplaceOptions (), $ options );
378
+ $ options = $ this ->_massageFindAndModifyOptions ($ options , $ replacement );
379
+
380
+ $ cmd = array (
381
+ "findandmodify " => $ this ->collname ,
382
+ "query " => $ filter ,
383
+ ) + $ options ;
384
+
385
+ $ doc = $ this ->_runCommand ($ this ->dbname , $ cmd )->getResponseDocument ();
386
+ if ($ doc ["ok " ]) {
387
+ return $ doc ["value " ];
388
+ }
389
+
390
+ throw $ this ->_generateCommandException ($ doc );
391
+ } /* }}} */
392
+ function getFindOneAndReplaceOptions () { /* {{{ */
393
+ return array (
394
+
395
+ /**
396
+ * The maximum amount of time to allow the query to run.
397
+ *
398
+ * @see http://docs.mongodb.org/manual/reference/command/findAndModify/
399
+ */
400
+ "maxTimeMS " => 0 ,
401
+
402
+ /**
403
+ * Limits the fields to return for all matching documents.
404
+ *
405
+ * @see http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results
406
+ */
407
+ "projection " => array (),
408
+
409
+ /**
410
+ * When ReturnDocument.After, returns the replaced or inserted document rather than the original.
411
+ * Defaults to ReturnDocument.Before.
412
+ *
413
+ * @see http://docs.mongodb.org/manual/reference/command/findAndModify/
414
+ */
415
+ "returnDocument " => self ::FIND_ONE_AND_RETURN_BEFORE ,
416
+
417
+ /**
418
+ * Determines which document the operation modifies if the query selects multiple documents.
419
+ *
420
+ * @see http://docs.mongodb.org/manual/reference/command/findAndModify/
421
+ */
422
+ "sort " => array (),
423
+
424
+ /**
425
+ * When true, findAndModify creates a new document if no document matches the query. The
426
+ * default is false.
427
+ *
428
+ * @see http://docs.mongodb.org/manual/reference/command/findAndModify/
429
+ */
430
+ "upsert " => false ,
431
+ );
432
+
433
+ } /* }}} */
434
+
435
+
436
+ protected function _massageFindAndModifyOptions ($ options , $ update = array ()) { /* {{{ */
437
+ $ ret = array (
438
+ "sort " => $ options ["sort " ],
439
+ "new " => isset ($ options ["returnDocument " ]) ? $ options ["returnDocument " ] == self ::FIND_ONE_AND_RETURN_AFTER : false ,
440
+ "fields " => $ options ["projection " ],
441
+ "upsert " => isset ($ options ["upsert " ]) ? $ options ["upsert " ] : false ,
442
+ );
443
+ if ($ update ) {
444
+ $ ret ["update " ] = $ update ;
445
+ } else {
446
+ $ ret ["remove " ] = true ;
447
+ }
448
+
449
+ return $ ret ;
450
+ } /* }}} */
451
+ /* }}} */
367
452
368
453
protected function _generateCommandException ($ doc ) { /* {{{ */
369
454
if ($ doc ["errmsg " ]) {
0 commit comments