77use MongoDB \Client ;
88use MongoDB \Collection ;
99use MongoDB \Database ;
10+ use MongoDB \Driver \BulkWriteCommand ;
1011use MongoDB \Driver \ClientEncryption ;
1112use MongoDB \Driver \Cursor ;
1213use MongoDB \Driver \Server ;
@@ -88,7 +89,6 @@ final class Operation
8889 'createEntities ' => 'createEntities is not implemented (PHPC-1760) ' ,
8990 ],
9091 Client::class => [
91- 'clientBulkWrite ' => 'clientBulkWrite is not implemented (PHPLIB-847) ' ,
9292 'listDatabaseObjects ' => 'listDatabaseObjects is not implemented ' ,
9393 ],
9494 Cursor::class => ['iterateOnce ' => 'iterateOnce is not implemented (PHPC-1760) ' ],
@@ -257,6 +257,18 @@ private function executeForClient(Client $client)
257257 Util::assertArgumentsBySchema (Client::class, $ this ->name , $ args );
258258
259259 switch ($ this ->name ) {
260+ case 'clientBulkWrite ' :
261+ assertArrayHasKey ('models ' , $ args );
262+ assertIsArray ($ args ['models ' ]);
263+
264+ // Options for BulkWriteCommand and Server::executeBulkWriteCommand() will be mixed
265+ $ options = array_diff_key ($ args , ['models ' => 1 ]);
266+
267+ return $ client ->bulkWrite (
268+ self ::prepareBulkWriteCommand ($ args ['models ' ], $ options ),
269+ $ options ,
270+ );
271+
260272 case 'createChangeStream ' :
261273 assertArrayHasKey ('pipeline ' , $ args );
262274 assertIsArray ($ args ['pipeline ' ]);
@@ -1001,6 +1013,82 @@ private function skipIfOperationIsNotSupported(string $executingObjectName): voi
10011013 Assert::markTestSkipped ($ skipReason );
10021014 }
10031015
1016+ private static function prepareBulkWriteCommand (array $ models , array $ options ): BulkWriteCommand
1017+ {
1018+ $ bulk = new BulkWriteCommand ($ options );
1019+
1020+ foreach ($ models as $ model ) {
1021+ $ model = (array ) $ model ;
1022+ assertCount (1 , $ model );
1023+
1024+ $ type = key ($ model );
1025+ $ args = current ($ model );
1026+ assertIsObject ($ args );
1027+ $ args = (array ) $ args ;
1028+
1029+ assertArrayHasKey ('namespace ' , $ args );
1030+ assertIsString ($ args ['namespace ' ]);
1031+
1032+ switch ($ type ) {
1033+ case 'deleteMany ' :
1034+ case 'deleteOne ' :
1035+ assertArrayHasKey ('filter ' , $ args );
1036+ assertInstanceOf (stdClass::class, $ args ['filter ' ]);
1037+
1038+ $ bulk ->{$ type }(
1039+ $ args ['namespace ' ],
1040+ $ args ['filter ' ],
1041+ array_diff_key ($ args , ['namespace ' => 1 , 'filter ' => 1 ]),
1042+ );
1043+ break ;
1044+
1045+ case 'insertOne ' :
1046+ assertArrayHasKey ('document ' , $ args );
1047+ assertInstanceOf (stdClass::class, $ args ['document ' ]);
1048+
1049+ $ bulk ->insertOne (
1050+ $ args ['namespace ' ],
1051+ $ args ['document ' ],
1052+ );
1053+ break ;
1054+
1055+ case 'replaceOne ' :
1056+ assertArrayHasKey ('filter ' , $ args );
1057+ assertArrayHasKey ('replacement ' , $ args );
1058+ assertInstanceOf (stdClass::class, $ args ['filter ' ]);
1059+ assertInstanceOf (stdClass::class, $ args ['replacement ' ]);
1060+
1061+ $ bulk ->replaceOne (
1062+ $ args ['namespace ' ],
1063+ $ args ['filter ' ],
1064+ $ args ['replacement ' ],
1065+ array_diff_key ($ args , ['namespace ' => 1 , 'filter ' => 1 , 'replacement ' => 1 ]),
1066+ );
1067+ break ;
1068+
1069+ case 'updateMany ' :
1070+ case 'updateOne ' :
1071+ assertArrayHasKey ('filter ' , $ args );
1072+ assertArrayHasKey ('update ' , $ args );
1073+ assertInstanceOf (stdClass::class, $ args ['filter ' ]);
1074+ assertThat ($ args ['update ' ], logicalOr (new IsType ('array ' ), new IsType ('object ' )));
1075+
1076+ $ bulk ->{$ type }(
1077+ $ args ['namespace ' ],
1078+ $ args ['filter ' ],
1079+ $ args ['update ' ],
1080+ array_diff_key ($ args , ['namespace ' => 1 , 'filter ' => 1 , 'update ' => 1 ]),
1081+ );
1082+ break ;
1083+
1084+ default :
1085+ Assert::fail ('Unsupported bulk write model: ' . $ type );
1086+ }
1087+ }
1088+
1089+ return $ bulk ;
1090+ }
1091+
10041092 private static function prepareBulkWriteRequest (stdClass $ request ): array
10051093 {
10061094 $ request = (array ) $ request ;
@@ -1026,6 +1114,7 @@ private static function prepareBulkWriteRequest(stdClass $request): array
10261114
10271115 case 'insertOne ' :
10281116 assertArrayHasKey ('document ' , $ args );
1117+ assertInstanceOf (stdClass::class, $ args ['document ' ]);
10291118
10301119 return ['insertOne ' => [$ args ['document ' ]]];
10311120
0 commit comments