Skip to content

Commit 809a92e

Browse files
committed
BulkWriteCommandBuilder
1 parent 3354fc9 commit 809a92e

File tree

2 files changed

+225
-0
lines changed

2 files changed

+225
-0
lines changed

src/BulkWriteCommandBuilder.php

+215
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
<?php
2+
3+
namespace MongoDB;
4+
5+
use MongoDB\Codec\DocumentCodec;
6+
use MongoDB\Codec\Encoder;
7+
use MongoDB\Driver\BulkWriteCommand;
8+
use MongoDB\Exception\InvalidArgumentException;
9+
10+
use function is_array;
11+
use function is_bool;
12+
use function is_string;
13+
14+
class BulkWriteCommandBuilder
15+
{
16+
private BulkWriteCommand $bulkWriteCommand;
17+
18+
private function __construct(
19+
private string $namespace,
20+
private Encoder $builderEncoder,
21+
private ?DocumentCodec $codec,
22+
array $options,
23+
) {
24+
$options += ['ordered' => true];
25+
26+
if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) {
27+
throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean');
28+
}
29+
30+
if (isset($options['let']) && ! is_document($options['let'])) {
31+
throw InvalidArgumentException::expectedDocumentType('"let" option', $options['let']);
32+
}
33+
34+
if (! is_bool($options['ordered'])) {
35+
throw InvalidArgumentException::invalidType('"ordered" option', $options['ordered'], 'boolean');
36+
}
37+
38+
if (isset($options['verboseResults']) && ! is_bool($options['verboseResults'])) {
39+
throw InvalidArgumentException::invalidType('"verboseResults" option', $options['verboseResults'], 'boolean');
40+
}
41+
42+
$this->bulkWriteCommand = new BulkWriteCommand($options);
43+
}
44+
45+
public static function createWithCollection(Collection $collection, array $options): self
46+
{
47+
return new self(
48+
$collection->getNamespace(),
49+
$collection->getBuilderEncoder(),
50+
$collection->getCodec(),
51+
$options,
52+
);
53+
}
54+
55+
public function withCollection(Collection $collection): self
56+
{
57+
$this->namespace = $collection->getNamespace();
58+
$this->builderEncoder = $collection->getBuilderEncoder();
59+
$this->codec = $collection->getCodec();
60+
61+
return $this;
62+
}
63+
64+
public function deleteOne(array|object $filter, ?array $options = null): self
65+
{
66+
$filter = $this->builderEncoder->encodeIfSupported($filter);
67+
68+
if (isset($options['collation']) && ! is_document($options['collation'])) {
69+
throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']);
70+
}
71+
72+
if (isset($options['hint']) && ! is_string($options['hint']) && ! is_document($options['hint'])) {
73+
throw InvalidArgumentException::expectedDocumentOrStringType('"hint" option', $options['hint']);
74+
}
75+
76+
$this->bulkWriteCommand->deleteOne($this->namespace, $filter, $options);
77+
78+
return $this;
79+
}
80+
81+
public function deleteMany(array|object $filter, ?array $options = null): self
82+
{
83+
$filter = $this->builderEncoder->encodeIfSupported($filter);
84+
85+
if (isset($options['collation']) && ! is_document($options['collation'])) {
86+
throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']);
87+
}
88+
89+
if (isset($options['hint']) && ! is_string($options['hint']) && ! is_document($options['hint'])) {
90+
throw InvalidArgumentException::expectedDocumentOrStringType('"hint" option', $options['hint']);
91+
}
92+
93+
$this->bulkWriteCommand->deleteMany($this->namespace, $filter, $options);
94+
95+
return $this;
96+
}
97+
98+
public function insertOne(array|object $document, mixed &$id = null): self
99+
{
100+
if ($this->codec) {
101+
$document = $this->codec->encode($document);
102+
}
103+
104+
// Capture the document's _id, which may have been generated, in an optional output variable
105+
$id = $this->bulkWriteCommand->insertOne($this->namespace, $document);
106+
107+
return $this;
108+
}
109+
110+
public function replaceOne(array|object $filter, array|object $replacement, ?array $options = null): self
111+
{
112+
$filter = $this->builderEncoder->encodeIfSupported($filter);
113+
114+
if ($this->codec) {
115+
$replacement = $this->codec->encode($replacement);
116+
}
117+
118+
// Treat empty arrays as replacement documents for BC
119+
if ($replacement === []) {
120+
$replacement = (object) $replacement;
121+
}
122+
123+
if (is_first_key_operator($replacement)) {
124+
throw new InvalidArgumentException('First key in $replacement is an update operator');
125+
}
126+
127+
if (is_pipeline($replacement, true)) {
128+
throw new InvalidArgumentException('$replacement is an update pipeline');
129+
}
130+
131+
if (isset($options['collation']) && ! is_document($options['collation'])) {
132+
throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']);
133+
}
134+
135+
if (isset($options['hint']) && ! is_string($options['hint']) && ! is_document($options['hint'])) {
136+
throw InvalidArgumentException::expectedDocumentOrStringType('"hint" option', $options['hint']);
137+
}
138+
139+
if (isset($options['sort']) && ! is_document($options['sort'])) {
140+
throw InvalidArgumentException::expectedDocumentType('"sort" option', $options['sort']);
141+
}
142+
143+
if (isset($options['upsert']) && ! is_bool($options['upsert'])) {
144+
throw InvalidArgumentException::invalidType('"upsert" option', $options['upsert'], 'boolean');
145+
}
146+
147+
$this->bulkWriteCommand->replaceOne($this->namespace, $filter, $replacement, $options);
148+
149+
return $this;
150+
}
151+
152+
public function updateOne(array|object $filter, array|object $update, ?array $options = null): self
153+
{
154+
$filter = $this->builderEncoder->encodeIfSupported($filter);
155+
$update = $this->builderEncoder->encodeIfSupported($update);
156+
157+
if (! is_first_key_operator($update) && ! is_pipeline($update)) {
158+
throw new InvalidArgumentException('Expected update operator(s) or non-empty pipeline for $update');
159+
}
160+
161+
if (isset($options['arrayFilters']) && ! is_array($options['arrayFilters'])) {
162+
throw InvalidArgumentException::invalidType('"arrayFilters" option', $options['arrayFilters'], 'array');
163+
}
164+
165+
if (isset($options['collation']) && ! is_document($options['collation'])) {
166+
throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']);
167+
}
168+
169+
if (isset($options['hint']) && ! is_string($options['hint']) && ! is_document($options['hint'])) {
170+
throw InvalidArgumentException::expectedDocumentOrStringType('"hint" option', $options['hint']);
171+
}
172+
173+
if (isset($options['sort']) && ! is_document($options['sort'])) {
174+
throw InvalidArgumentException::expectedDocumentType('"sort" option', $options['sort']);
175+
}
176+
177+
if (isset($options['upsert']) && ! is_bool($options['upsert'])) {
178+
throw InvalidArgumentException::invalidType('"upsert" option', $options['upsert'], 'boolean');
179+
}
180+
181+
$this->bulkWriteCommand->updateOne($this->namespace, $filter, $update, $options);
182+
183+
return $this;
184+
}
185+
186+
public function updateMany(array|object $filter, array|object $update, ?array $options = null): self
187+
{
188+
$filter = $this->builderEncoder->encodeIfSupported($filter);
189+
$update = $this->builderEncoder->encodeIfSupported($update);
190+
191+
if (! is_first_key_operator($update) && ! is_pipeline($update)) {
192+
throw new InvalidArgumentException('Expected update operator(s) or non-empty pipeline for $update');
193+
}
194+
195+
if (isset($options['arrayFilters']) && ! is_array($options['arrayFilters'])) {
196+
throw InvalidArgumentException::invalidType('"arrayFilters" option', $options['arrayFilters'], 'array');
197+
}
198+
199+
if (isset($options['collation']) && ! is_document($options['collation'])) {
200+
throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']);
201+
}
202+
203+
if (isset($options['hint']) && ! is_string($options['hint']) && ! is_document($options['hint'])) {
204+
throw InvalidArgumentException::expectedDocumentOrStringType('"hint" option', $options['hint']);
205+
}
206+
207+
if (isset($options['upsert']) && ! is_bool($options['upsert'])) {
208+
throw InvalidArgumentException::invalidType('"upsert" option', $options['upsert'], 'boolean');
209+
}
210+
211+
$this->bulkWriteCommand->updateMany($this->namespace, $filter, $update, $options);
212+
213+
return $this;
214+
}
215+
}

src/Collection.php

+10
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,16 @@ public function findOneAndUpdate(array|object $filter, array|object $update, arr
753753
return $operation->execute(select_server_for_write($this->manager, $options));
754754
}
755755

756+
public function getBuilderEncoder(): BuilderEncoder
757+
{
758+
return $this->builderEncoder;
759+
}
760+
761+
public function getCodec(): ?DocumentCodec
762+
{
763+
return $this->codec;
764+
}
765+
756766
/**
757767
* Return the collection name.
758768
*/

0 commit comments

Comments
 (0)