From 22e5e0e8814975ac3da97c2576b57463fc92f4be Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Fri, 18 Aug 2023 21:58:42 +0200 Subject: [PATCH] Refactor all methods to receive options varargs --- src/main/php/com/mongodb/Collection.class.php | 78 +++++++++---------- src/main/php/com/mongodb/Database.class.php | 20 ++--- .../php/com/mongodb/MongoConnection.class.php | 26 +++---- src/main/php/com/mongodb/Options.class.php | 20 +++++ src/main/php/com/mongodb/Session.class.php | 2 +- .../php/com/mongodb/io/Commands.class.php | 8 +- .../php/com/mongodb/result/Cursor.class.php | 12 +-- .../mongodb/unittest/CollectionTest.class.php | 53 ++++++++++++- .../mongodb/unittest/SessionsTest.class.php | 2 +- 9 files changed, 146 insertions(+), 75 deletions(-) create mode 100755 src/main/php/com/mongodb/Options.class.php diff --git a/src/main/php/com/mongodb/Collection.class.php b/src/main/php/com/mongodb/Collection.class.php index bcffa57..94487e7 100755 --- a/src/main/php/com/mongodb/Collection.class.php +++ b/src/main/php/com/mongodb/Collection.class.php @@ -32,12 +32,12 @@ public function namespace() { return $this->database.'.'.$this->name; } * @deprecated Use `run()` instead! * @param string $name * @param [:var] $params - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return var * @throws com.mongodb.Error */ - public function command($name, array $params= [], Session $session= null) { - return $this->proto->write($session, [$name => $this->name] + $params + ['$db' => $this->database])['body']; + public function command($name, array $params= [], Options... $options) { + return $this->proto->write($options, [$name => $this->name] + $params + ['$db' => $this->database])['body']; } /** @@ -46,16 +46,16 @@ public function command($name, array $params= [], Session $session= null) { * @param string $name * @param [:var] $params * @param string $semantics one of `read` or `write` - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return com.mongodb.result.Run * @throws com.mongodb.Error */ - public function run($name, array $params= [], $semantics= 'write', Session $session= null) { + public function run($name, array $params= [], $semantics= 'write', Options... $options) { $commands= Commands::using($this->proto, $semantics); return new Run( $commands, - $session, - $commands->send($session, [$name => $this->name] + $params + ['$db' => $this->database]) + $options, + $commands->send($options, [$name => $this->name] + $params + ['$db' => $this->database]) ); } @@ -64,11 +64,11 @@ public function run($name, array $params= [], $semantics= 'write', Session $sess * passed documents. * * @param com.mongodb.Document|com.mongodb.Document[] $arg - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return com.mongodb.result.Insert * @throws com.mongodb.Error */ - public function insert($arg, Session $session= null): Insert { + public function insert($arg, Options... $options): Insert { $documents= is_array($arg) ? $arg : [$arg]; // See https://docs.mongodb.com/manual/reference/method/db.collection.insert/#id-field: @@ -78,7 +78,7 @@ public function insert($arg, Session $session= null): Insert { $ids[]= $document['_id'] ?? $document['_id']= ObjectId::create(); } - $result= $this->proto->write($session, [ + $result= $this->proto->write($options, [ 'insert' => $this->name, 'documents' => $documents, 'ordered' => true, @@ -92,12 +92,12 @@ public function insert($arg, Session $session= null): Insert { * * @param string|com.mongodb.ObjectId|[:var] $query * @param [:var]|com.mongodb.Document $arg Update operator expressions or document - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return com.mongodb.result.Update * @throws com.mongodb.Error */ - public function upsert($query, $arg, Session $session= null): Update { - $result= $this->proto->write($session, [ + public function upsert($query, $arg, Options... $options): Update { + $result= $this->proto->write($options, [ 'update' => $this->name, 'updates' => [[ 'q' => $query instanceof ObjectId ? ['_id' => $query] : $query, @@ -115,12 +115,12 @@ public function upsert($query, $arg, Session $session= null): Update { * * @param string|com.mongodb.ObjectId|[:var] $query * @param [:var] $statements Update operator expressions - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return com.mongodb.result.Update * @throws com.mongodb.Error */ - public function update($query, $statements, Session $session= null): Update { - $result= $this->proto->write($session, [ + public function update($query, $statements, Options... $options): Update { + $result= $this->proto->write($options, [ 'update' => $this->name, 'updates' => [['u' => $statements] + (is_array($query) ? ['q' => $query, 'multi' => true] @@ -136,12 +136,12 @@ public function update($query, $statements, Session $session= null): Update { * Delete documents * * @param string|com.mongodb.ObjectId|[:var] $query - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return com.mongodb.result.Delete * @throws com.mongodb.Error */ - public function delete($query, Session $session= null): Delete { - $result= $this->proto->write($session, [ + public function delete($query, Options... $options): Delete { + $result= $this->proto->write($options, [ 'delete' => $this->name, 'deletes' => [is_array($query) ? ['q' => $query, 'limit' => 0] @@ -157,31 +157,31 @@ public function delete($query, Session $session= null): Delete { * Find documents in this collection * * @param string|com.mongodb.ObjectId|[:var] $query - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return com.mongodb.result.Cursor * @throws com.mongodb.Error */ - public function find($query= [], Session $session= null): Cursor { + public function find($query= [], Options... $options): Cursor { $commands= Commands::reading($this->proto); - $result= $commands->send($session, [ + $result= $commands->send($options, [ 'find' => $this->name, 'filter' => is_array($query) ? ($query ?: (object)[]) : ['_id' => $query], '$db' => $this->database, ]); - return new Cursor($commands, $session, $result['body']['cursor']); + return new Cursor($commands, $options, $result['body']['cursor']); } /** * Count documents in this collection * * @param [:var] $filter - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return int * @throws com.mongodb.Error */ - public function count($filter= [], Session $session= null): int { + public function count($filter= [], Options... $options): int { $count= ['$count' => 'n']; - $result= $this->proto->read($session, [ + $result= $this->proto->read($options, [ 'aggregate' => $this->name, 'pipeline' => $filter ? [['$match' => $filter], $count] : [$count], 'cursor' => (object)[], @@ -195,13 +195,13 @@ public function count($filter= [], Session $session= null): int { * * @param string $key * @param [:var] $filter - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return var[] * @throws com.mongodb.Error */ - public function distinct($key, $filter= [], Session $session= null): array { + public function distinct($key, $filter= [], Options... $options): array { $distinct= ['$group' => ['_id' => 1, 'values' => ['$addToSet' => '$'.$key]]]; - $result= $this->proto->read($session, [ + $result= $this->proto->read($options, [ 'aggregate' => $this->name, 'pipeline' => $filter ? [['$match' => $filter], $distinct] : [$distinct], 'cursor' => (object)[], @@ -214,11 +214,11 @@ public function distinct($key, $filter= [], Session $session= null): array { * Perfom aggregation over documents this collection * * @param [:var][] $pipeline - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return com.mongodb.result.Cursor * @throws com.mongodb.Error */ - public function aggregate(array $pipeline= [], Session $session= null): Cursor { + public function aggregate(array $pipeline= [], Options... $options): Cursor { $sections= [ 'aggregate' => $this->name, 'pipeline' => $pipeline, @@ -239,30 +239,30 @@ public function aggregate(array $pipeline= [], Session $session= null): Cursor { $commands= Commands::reading($this->proto); } - $result= $commands->send($session, $sections); - return new Cursor($commands, $session, $result['body']['cursor']); + $result= $commands->send($options, $sections); + return new Cursor($commands, $options, $result['body']['cursor']); } /** * Watch for changes in this collection * * @param [:var][] $pipeline - * @param [:var] $options - * @param ?com.mongodb.Session $session + * @param [:var] $params + * @param com.mongodb.Options... $options * @return com.mongodb.result.ChangeStream * @throws com.mongodb.Error */ - public function watch(array $pipeline= [], array $options= [], Session $session= null): ChangeStream { - array_unshift($pipeline, ['$changeStream' => (object)$options]); + public function watch(array $pipeline= [], array $params= [], Options... $options): ChangeStream { + array_unshift($pipeline, ['$changeStream' => (object)$params]); $commands= Commands::reading($this->proto); - $result= $commands->send($session, [ + $result= $commands->send($options, [ 'aggregate' => $this->name, 'pipeline' => $pipeline, 'cursor' => (object)[], '$db' => $this->database, ]); - return new ChangeStream($commands, $session, $result['body']['cursor']); + return new ChangeStream($commands, $options, $result['body']['cursor']); } /** @return string */ diff --git a/src/main/php/com/mongodb/Database.class.php b/src/main/php/com/mongodb/Database.class.php index c62ef33..dff3301 100755 --- a/src/main/php/com/mongodb/Database.class.php +++ b/src/main/php/com/mongodb/Database.class.php @@ -30,39 +30,39 @@ public function collection(string $name): Collection { /** * Returns a list of database information objects * - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return [:var][] * @throws com.mongodb.Error */ - public function collections(Session $session= null) { + public function collections(Options... $options) { $commands= Commands::reading($this->proto); - $result= $commands->send($session, [ + $result= $commands->send($options, [ 'listCollections' => (object)[], '$db' => $this->name ]); - return new Cursor($commands, $session, $result['body']['cursor']); + return new Cursor($commands, $options, $result['body']['cursor']); } /** * Watch for changes in this database * * @param [:var][] $pipeline - * @param [:var] $options - * @param ?com.mongodb.Session $session + * @param [:var] $params + * @param com.mongodb.Options... $options * @return com.mongodb.result.ChangeStream * @throws com.mongodb.Error */ - public function watch(array $pipeline= [], array $options= [], Session $session= null): ChangeStream { - array_unshift($pipeline, ['$changeStream' => (object)$options]); + public function watch(array $pipeline= [], array $params= [], Options... $options): ChangeStream { + array_unshift($pipeline, ['$changeStream' => (object)$params]); $commands= Commands::reading($this->proto); - $result= $commands->send($session, [ + $result= $commands->send($options, [ 'aggregate' => 1, 'pipeline' => $pipeline, 'cursor' => (object)[], '$db' => $this->name, ]); - return new ChangeStream($commands, $session, $result['body']['cursor']); + return new ChangeStream($commands, $options, $result['body']['cursor']); } /** @return string */ diff --git a/src/main/php/com/mongodb/MongoConnection.class.php b/src/main/php/com/mongodb/MongoConnection.class.php index 43b88fa..349c0fe 100755 --- a/src/main/php/com/mongodb/MongoConnection.class.php +++ b/src/main/php/com/mongodb/MongoConnection.class.php @@ -55,18 +55,18 @@ public function connect(): self { * @param string $name * @param [:var] $arguments * @param string $semantics one of `read` or `write` - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options... $options * @return com.mongodb.result.Run * @throws com.mongodb.Error */ - public function run($name, array $arguments= [], $semantics= 'write', Session $session= null) { + public function run($name, array $arguments= [], $semantics= 'write', Options... $options) { $this->proto->connect(); $commands= Commands::using($this->proto, $semantics); return new Run( $commands, - $session, - $commands->send($session, [$name => 1] + $params + ['$db' => 'admin']) + $options, + $commands->send($options, [$name => 1] + $params + ['$db' => 'admin']) ); } @@ -120,11 +120,11 @@ public function collection(... $args): Collection { * * @see https://docs.mongodb.com/manual/reference/command/listDatabases/ * @param ?string|com.mongodb.Regex|[:string|com.mongodb.Regex] $filter - * @return ?com.mongodb.Session $session + * @return com.mongodb.Options... $options * @return iterable * @throws com.mongodb.Error */ - public function databases($filter= null, $session= null) { + public function databases($filter= null, $options= null) { $this->proto->connect(); $request= ['listDatabases' => 1, '$db' => 'admin']; @@ -136,7 +136,7 @@ public function databases($filter= null, $session= null) { $request+= ['filter' => ['name' => $filter]]; } - foreach ($this->proto->read($session, $request)['body']['databases'] as $d) { + foreach ($this->proto->read($options, $request)['body']['databases'] as $d) { yield $d['name'] => [ 'name' => $d['name'], 'sizeOnDisk' => $d['sizeOnDisk'] instanceof Int64 ? $d['sizeOnDisk'] : new Int64($d['sizeOnDisk']), @@ -150,24 +150,24 @@ public function databases($filter= null, $session= null) { * Watch for changes in all databases. * * @param [:var][] $pipeline - * @param [:var] $options - * @param ?com.mongodb.Session $session + * @param [:var] $params + * @param com.mongodb.Options... $options * @return com.mongodb.result.ChangeStream * @throws com.mongodb.Error */ - public function watch(array $pipeline= [], array $options= [], Session $session= null): ChangeStream { + public function watch(array $pipeline= [], array $params= [], Options... $options): ChangeStream { $this->proto->connect(); - array_unshift($pipeline, ['$changeStream' => ['allChangesForCluster' => true] + $options]); + array_unshift($pipeline, ['$changeStream' => ['allChangesForCluster' => true] + $params]); $commands= Commands::reading($this->proto); - $result= $commands->send($session, [ + $result= $commands->send($options, [ 'aggregate' => 1, 'pipeline' => $pipeline, 'cursor' => (object)[], '$db' => 'admin', ]); - return new ChangeStream($commands, $session, $result['body']['cursor']); + return new ChangeStream($commands, $options, $result['body']['cursor']); } /** @return string */ diff --git a/src/main/php/com/mongodb/Options.class.php b/src/main/php/com/mongodb/Options.class.php new file mode 100755 index 0000000..92c5b19 --- /dev/null +++ b/src/main/php/com/mongodb/Options.class.php @@ -0,0 +1,20 @@ +pairs= $pairs; + } + + /** + * Returns fields to be sent along with the command. Used by Protocol class. + * + * @param com.mongodb.io.Protocol + * @return [:var] + */ + public function send($proto) { + return $this->pairs; + } +} \ No newline at end of file diff --git a/src/main/php/com/mongodb/Session.class.php b/src/main/php/com/mongodb/Session.class.php index 40ef771..dd64a58 100755 --- a/src/main/php/com/mongodb/Session.class.php +++ b/src/main/php/com/mongodb/Session.class.php @@ -13,7 +13,7 @@ * @test com.mongodb.unittest.SessionTest * @test com.mongodb.unittest.SessionsTest */ -class Session implements Value, Closeable { +class Session extends Options implements Value, Closeable { private $proto, $id; private $closed= false; private $transaction= ['n' => 0]; diff --git a/src/main/php/com/mongodb/io/Commands.class.php b/src/main/php/com/mongodb/io/Commands.class.php index 84a67a2..e1a80a5 100755 --- a/src/main/php/com/mongodb/io/Commands.class.php +++ b/src/main/php/com/mongodb/io/Commands.class.php @@ -54,13 +54,15 @@ public static function using($proto, $semantics) { /** * Sends a message * - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options $options * @param [:var] $sections * @return var * @throws com.mongodb.Error */ - public function send($session, $sections) { - $session && $sections+= $session->send($this->proto); + public function send($options, $sections) { + foreach ($options as $option) { + $sections+= $option->send($this->proto); + } return $this->conn->message($sections, $this->proto->readPreference); } } \ No newline at end of file diff --git a/src/main/php/com/mongodb/result/Cursor.class.php b/src/main/php/com/mongodb/result/Cursor.class.php index b87dc2c..84fd20b 100755 --- a/src/main/php/com/mongodb/result/Cursor.class.php +++ b/src/main/php/com/mongodb/result/Cursor.class.php @@ -7,18 +7,18 @@ /** @test com.mongodb.unittest.result.CursorTest */ class Cursor implements Value, IteratorAggregate { - protected $commands, $session, $current; + protected $commands, $options, $current; /** * Creates a new cursor * * @param com.mongodb.io.Commands $commands - * @param ?com.mongodb.Session $session + * @param com.mongodb.Options[] $options * @param [:var] $current */ - public function __construct($commands, $session, $current) { + public function __construct($commands, $options, $current) { $this->commands= $commands; - $this->session= $session; + $this->options= $options; $this->current= $current; } @@ -34,7 +34,7 @@ public function getIterator(): Traversable { // Fetch subsequent batches sscanf($this->current['ns'], "%[^.].%[^\r]", $database, $collection); while ($this->current['id']->number() > 0) { - $result= $this->commands->send($this->session, [ + $result= $this->commands->send($this->options, [ 'getMore' => $this->current['id'], 'collection' => $collection, '$db' => $database, @@ -93,7 +93,7 @@ public function close() { if (0 === $this->current['id']->number()) return; sscanf($this->current['ns'], "%[^.].%[^\r]", $database, $collection); - $this->commands->send($this->session, [ + $this->commands->send($this->options, [ 'killCursors' => $collection, 'cursors' => [$this->current['id']], '$db' => $database, diff --git a/src/test/php/com/mongodb/unittest/CollectionTest.class.php b/src/test/php/com/mongodb/unittest/CollectionTest.class.php index c68d4d3..941b37c 100755 --- a/src/test/php/com/mongodb/unittest/CollectionTest.class.php +++ b/src/test/php/com/mongodb/unittest/CollectionTest.class.php @@ -1,11 +1,14 @@ connect(), 'testing', 'tests'); } + #[Before] + public function sessionId() { + $this->sessionId= new UUID('5f375bfe-af78-4af8-bb03-5d441a66a5fb'); + } + #[Test] public function name() { Assert::equals('tests', $this->newFixture([])->name()); @@ -250,4 +258,45 @@ public function string_representation() { $this->newFixture([])->toString() ); } + + #[Test] + public function find_with_session() { + $replies= [self::$PRIMARY => [$this->hello(self::$PRIMARY), $this->cursor([]), $this->ok()]]; + $proto= $this->protocol($replies, 'primary')->connect(); + + $session= new Session($proto, $this->sessionId); + try { + $coll= new Collection($proto, 'test', 'tests'); + $coll->find([], $session); + } finally { + $session->close(); + } + + $find= [ + 'find' => 'tests', + 'filter' => (object)[], + '$db' => 'test', + 'lsid' => ['id' => $this->sessionId], + '$readPreference' => ['mode' => 'primary'] + ]; + Assert::equals($find, $proto->connections()[self::$PRIMARY]->command(-2)); + } + + #[Test] + public function find_with_options() { + $replies= [self::$PRIMARY => [$this->hello(self::$PRIMARY), $this->cursor([])]]; + $proto= $this->protocol($replies, 'primary')->connect(); + + $coll= new Collection($proto, 'test', 'tests'); + $coll->find([], new Options(['sort' => ['name' => -1]])); + + $find= [ + 'find' => 'tests', + 'filter' => (object)[], + '$db' => 'test', + 'sort' => ['name' => -1], + '$readPreference' => ['mode' => 'primary'] + ]; + Assert::equals($find, $proto->connections()[self::$PRIMARY]->command(-1)); + } } \ No newline at end of file diff --git a/src/test/php/com/mongodb/unittest/SessionsTest.class.php b/src/test/php/com/mongodb/unittest/SessionsTest.class.php index 111d87e..8412d9a 100755 --- a/src/test/php/com/mongodb/unittest/SessionsTest.class.php +++ b/src/test/php/com/mongodb/unittest/SessionsTest.class.php @@ -1,6 +1,6 @@