Skip to content

Commit

Permalink
Add Collection::remove()
Browse files Browse the repository at this point in the history
  • Loading branch information
thekid committed Dec 30, 2023
1 parent 1663c2c commit 30865fe
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 17 deletions.
21 changes: 21 additions & 0 deletions src/main/php/com/mongodb/Collection.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,27 @@ public function delete($query, Options... $options): Delete {
return new Delete($result['body']);
}

/**
* Modifies collection and returns a `Modification` instance with the removed
* document.
*
* @param string|com.mongodb.ObjectId|[:var] $query
* @param [:var]|com.mongodb.Document $arg Update operator expressions or document
* @param bool $upsert
* @param com.mongodb.Options... $options
* @return com.mongodb.result.Modification
* @throws com.mongodb.Error
*/
public function remove($query, Options... $options): Modification {
$result= $this->proto->write($options, [
'findAndModify' => $this->name,
'query' => is_array($query) ? $query : ['_id' => $query],
'remove' => true,
'$db' => $this->database,
]);
return new Modification($result['body']);
}

/**
* Find documents in this collection
*
Expand Down
15 changes: 12 additions & 3 deletions src/main/php/com/mongodb/result/Modification.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@

/** @test com.mongodb.unittest.result.ModificationTest */
class Modification extends Result {
const REMOVED= 'removed';
const CREATED= 'created';
const UPDATED= 'updated';

/** Returns number of modified documents */
public function modified(): int { return $this->result['lastErrorObject']['n']; }

/** Returns whether an existing document was updated */
public function updatedExisting(): bool {
return $this->result['lastErrorObject']['updatedExisting'];
/** Returns kind of modification: created, updated or removed. */
public function kind(): string {
if (isset($this->result['lastErrorObject']['upserted'])) {
return self::CREATED;
} else if (isset($this->result['lastErrorObject']['updatedExisting'])) {
return self::UPDATED;
} else {
return self::REMOVED;
}
}

/**
Expand Down
34 changes: 31 additions & 3 deletions src/test/php/com/mongodb/unittest/CollectionTest.class.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php namespace com\mongodb\unittest;

use com\mongodb\result\Modification;
use com\mongodb\{Collection, Document, Int64, ObjectId, Options, Session, Error};
use test\{Assert, Before, Expect, Test, Values};
use util\UUID;
Expand Down Expand Up @@ -147,7 +148,7 @@ public function modify_none() {
]);
$result= $this->newFixture($body)->modify(ObjectId::create(), ['$set' => ['test' => true]]);

Assert::equals([false, 0], [$result->updatedExisting(), $result->modified()]);
Assert::equals([Modification::UPDATED, 0], [$result->kind(), $result->modified()]);
Assert::null($result->upserted());
Assert::null($result->document());
}
Expand All @@ -161,7 +162,7 @@ public function modify_existing() {
]);
$result= $this->newFixture($body)->modify($doc->id(), ['$set' => ['test' => true]]);

Assert::equals([true, 1], [$result->updatedExisting(), $result->modified()]);
Assert::equals([Modification::UPDATED, 1], [$result->kind(), $result->modified()]);
Assert::null($result->upserted());
Assert::equals($doc, $result->document());
}
Expand All @@ -175,7 +176,7 @@ public function create_new() {
]);
$result= $this->newFixture($body)->modify($doc->id(), ['$set' => ['test' => true]]);

Assert::equals([false, 1], [$result->updatedExisting(), $result->modified()]);
Assert::equals([Modification::CREATED, 1], [$result->kind(), $result->modified()]);
Assert::equals($doc->id(), $result->upserted());
Assert::equals($doc, $result->document());
}
Expand All @@ -194,6 +195,33 @@ public function delete_many() {
Assert::equals(2, $result->deleted());
}

#[Test]
public function remove() {
$doc= new Document(['_id' => ObjectId::create(), 'test' => true]);
$body= $this->ok([
'lastErrorObject' => ['n' => 1],
'value' => $doc->properties(),
]);
$result= $this->newFixture($body)->remove($doc->id());

Assert::equals([Modification::REMOVED, 1], [$result->kind(), $result->modified()]);
Assert::null($result->upserted());
Assert::equals($doc, $result->document());
}

#[Test]
public function not_removed() {
$body= $this->ok([
'lastErrorObject' => ['n' => 0],
'value' => null,
]);
$result= $this->newFixture($body)->remove(ObjectId::create());

Assert::equals([Modification::REMOVED, 0], [$result->kind(), $result->modified()]);
Assert::null($result->upserted());
Assert::null($result->document());
}

#[Test]
public function count_empty() {
$collection= $this->newFixture($this->cursor([]));
Expand Down
50 changes: 39 additions & 11 deletions src/test/php/com/mongodb/unittest/result/ModificationTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
class ModificationTest {
private $objectId;

/** Creates a result */
private function result(Document $document= null, $created= false) {
/** Creates a result from an update operation */
private function update(Document $document= null, $created= false) {
if (null === $document) {
$lastErrorObject= ['n' => 0, 'updatedExisting' => false];
$value= null;
Expand All @@ -22,59 +22,87 @@ private function result(Document $document= null, $created= false) {
return ['lastErrorObject' => $lastErrorObject, 'value' => $value, 'ok' => 1];
}

/** Creates a result from a remove operation */
private function remove(Document $document= null) {
if (null === $document) {
$lastErrorObject= ['n' => 0];
$value= null;
} else {
$lastErrorObject= ['n' => 1];
$value= $document->properties();
}
return ['lastErrorObject' => $lastErrorObject, 'value' => $value, 'ok' => 1];
}

#[Before]
public function objectId() {
$this->objectId= ObjectId::create();
}

#[Test]
public function can_create() {
new Modification($this->result());
new Modification($this->update());
}

#[Test]
public function none_modified() {
Assert::equals(0, (new Modification($this->result()))->modified());
Assert::equals(0, (new Modification($this->update()))->modified());
}

#[Test]
public function modified() {
$doc= new Document(['test' => true]);
Assert::equals(1, (new Modification($this->result($doc)))->modified());
Assert::equals(1, (new Modification($this->update($doc)))->modified());
}

#[Test]
public function updated_existing() {
$doc= new Document(['_id' => $this->objectId, 'test' => true]);
Assert::true((new Modification($this->result($doc)))->updatedExisting());
Assert::equals(Modification::UPDATED, ((new Modification($this->update($doc)))->kind()));
}

#[Test]
public function created_new() {
$doc= new Document(['_id' => $this->objectId, 'test' => true]);
Assert::false((new Modification($this->result($doc, true)))->updatedExisting());
Assert::equals(Modification::CREATED, (new Modification($this->update($doc, true)))->kind());
}

#[Test]
public function not_upserted() {
$doc= new Document(['_id' => $this->objectId, 'test' => true]);
Assert::null((new Modification($this->result($doc)))->upserted());
Assert::null((new Modification($this->update($doc)))->upserted());
}

#[Test]
public function upserted_id() {
$doc= new Document(['_id' => $this->objectId, 'test' => true]);
Assert::equals($this->objectId, (new Modification($this->result($doc, true)))->upserted());
Assert::equals($this->objectId, (new Modification($this->update($doc, true)))->upserted());
}

#[Test]
public function document() {
$doc= new Document(['_id' => $this->objectId, 'test' => true]);
Assert::equals($doc, (new Modification($this->result($doc)))->document());
Assert::equals($doc, (new Modification($this->update($doc)))->document());
}

#[Test]
public function no_document() {
Assert::null((new Modification($this->result()))->document());
Assert::null((new Modification($this->update()))->document());
}

#[Test]
public function removed() {
$doc= new Document(['_id' => $this->objectId, 'test' => true]);
Assert::equals($doc, (new Modification($this->remove($doc)))->document());
}

#[Test]
public function not_removed() {
Assert::null((new Modification($this->remove()))->document());
}

#[Test]
public function removal_kind() {
Assert::equals(Modification::REMOVED, (new Modification($this->remove()))->kind());
}
}

0 comments on commit 30865fe

Please sign in to comment.