Skip to content

Commit 3cd7091

Browse files
authored
PHPLIB-1182: Support codec option in operation classes (#1140)
* Add Codec support to find operations * Add codec support to insert operations * Add codec support to replace operation * Add codec support to aggregate operation * Add codec support to BulkWrite operation * Add codec support to findAndModify operations * Add codec support to Watch operation * Support passing default codec to collection class * Remove temporary variable usage in operations * Enforce iterator type when creating ChangeStreamIterator * Remove unnecessary null-coalesce * Ensure operation-level type map gets precedence over collection-level codec * Reference psalm issue regarding unions and assert-if type annotations * Add iterator type in ReadableStream * Assume _id property will be present in change stream result document. * Prohibit specifying typeMap and codec options for operations This commit also refactors the logic of inheriting collection-level options to operations to reduce code duplication. * Defer server selection until executing operation * Remove useless assertion * Assert iterator type in ChangeStreamIterator::getInnerIterator * Make assertions on encoded result conditional * Extract factory to created decoded fixtures * Split document creation for legibility * Insert fixture through factory in test object * Trigger warning when calling CodecCursor::setTypeMap * Encode documents before type checks This commit also changes the behaviour to use encode() instead of encodeIfSupported(), requiring documents to be encodable by the given codec in order to be inserted/updated. * Use more descriptive value in failing tests * Add clarifying comment on skipping validation * Simplify double isset check * Split chained calls when inheriting options * Defer server selection in Collection::drop() * Split inheritReadOptions method * Use decode() instead of decodeIfSupported() * Add explanatory comment for ID filling behaviour * Handle null values in findAndModify responses * Update comment regarding missing identifiers in tests * Use intersection type for change streams * Prohibit specifying codec and typeMap options to Watch
1 parent 2fcce89 commit 3cd7091

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2161
-554
lines changed

psalm-baseline.xml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
<code><![CDATA[$reply->cursor->nextBatch]]></code>
102102
</MixedArgument>
103103
<MixedAssignment>
104+
<code>$resumeToken</code>
104105
<code><![CDATA[$this->postBatchResumeToken]]></code>
105106
</MixedAssignment>
106107
<MixedPropertyFetch>
@@ -170,6 +171,7 @@
170171
</file>
171172
<file src="src/Operation/Aggregate.php">
172173
<MixedArgument>
174+
<code><![CDATA[$this->options['codec']]]></code>
173175
<code><![CDATA[$this->options['typeMap']]]></code>
174176
</MixedArgument>
175177
<MixedAssignment>
@@ -191,6 +193,8 @@
191193
<code>$args[0]</code>
192194
<code>$args[0]</code>
193195
<code>$args[0]</code>
196+
<code>$args[0]</code>
197+
<code>$args[1]</code>
194198
<code>$args[1]</code>
195199
<code>$args[1]</code>
196200
<code>$args[1]</code>
@@ -205,6 +209,8 @@
205209
<code>$args[0]</code>
206210
<code>$args[0]</code>
207211
<code>$args[0]</code>
212+
<code>$args[0]</code>
213+
<code>$args[1]</code>
208214
<code>$args[1]</code>
209215
<code>$args[1]</code>
210216
<code>$args[1]</code>
@@ -244,6 +250,8 @@
244250
<code>$args[2]</code>
245251
<code><![CDATA[$args[2]['multi']]]></code>
246252
<code><![CDATA[$args[2]['multi']]]></code>
253+
<code>$operations[$i][$type][0]</code>
254+
<code>$operations[$i][$type][1]</code>
247255
<code>$operations[$i][$type][1]</code>
248256
<code>$operations[$i][$type][2]</code>
249257
<code>$operations[$i][$type][2]</code>
@@ -401,6 +409,7 @@
401409
</file>
402410
<file src="src/Operation/Find.php">
403411
<MixedArgument>
412+
<code><![CDATA[$this->options['codec']]]></code>
404413
<code><![CDATA[$this->options['typeMap']]]></code>
405414
</MixedArgument>
406415
<MixedArrayAccess>
@@ -427,18 +436,34 @@
427436
<code><![CDATA[$cmd['upsert']]]></code>
428437
<code><![CDATA[$options['session']]]></code>
429438
<code><![CDATA[$options['writeConcern']]]></code>
439+
<code>$value</code>
430440
</MixedAssignment>
431441
<MixedInferredReturnType>
432442
<code>array|object|null</code>
433443
</MixedInferredReturnType>
434444
<MixedMethodCall>
445+
<code>decode</code>
435446
<code>isInTransaction</code>
436447
</MixedMethodCall>
437448
<MixedReturnStatement>
449+
<code><![CDATA[$value === null ? $value : $this->options['codec']->decode($value)]]></code>
450+
<code><![CDATA[$value === null ? $value : $this->options['codec']->decode($value)]]></code>
438451
<code><![CDATA[is_object($result) ? ($result->value ?? null) : null]]></code>
439452
<code><![CDATA[is_object($result) ? ($result->value ?? null) : null]]></code>
440453
</MixedReturnStatement>
441454
</file>
455+
<file src="src/Operation/FindOne.php">
456+
<MixedAssignment>
457+
<code>$document</code>
458+
</MixedAssignment>
459+
<MixedInferredReturnType>
460+
<code>array|object|null</code>
461+
</MixedInferredReturnType>
462+
<MixedReturnStatement>
463+
<code>$document === false ? null : $document</code>
464+
<code>$document === false ? null : $document</code>
465+
</MixedReturnStatement>
466+
</file>
442467
<file src="src/Operation/FindOneAndDelete.php">
443468
<MixedAssignment>
444469
<code><![CDATA[$options['fields']]]></code>
@@ -448,6 +473,9 @@
448473
<MixedAssignment>
449474
<code><![CDATA[$options['fields']]]></code>
450475
</MixedAssignment>
476+
<PossiblyInvalidArgument>
477+
<code>$replacement</code>
478+
</PossiblyInvalidArgument>
451479
</file>
452480
<file src="src/Operation/FindOneAndUpdate.php">
453481
<MixedAssignment>
@@ -464,6 +492,9 @@
464492
<MixedMethodCall>
465493
<code>isInTransaction</code>
466494
</MixedMethodCall>
495+
<PossiblyInvalidArgument>
496+
<code>$document</code>
497+
</PossiblyInvalidArgument>
467498
</file>
468499
<file src="src/Operation/InsertOne.php">
469500
<MixedAssignment>
@@ -475,6 +506,9 @@
475506
<MixedMethodCall>
476507
<code>isInTransaction</code>
477508
</MixedMethodCall>
509+
<PossiblyInvalidArgument>
510+
<code>$document</code>
511+
</PossiblyInvalidArgument>
478512
</file>
479513
<file src="src/Operation/ListIndexes.php">
480514
<MixedAssignment>
@@ -522,6 +556,11 @@
522556
<code>isInTransaction</code>
523557
</MixedMethodCall>
524558
</file>
559+
<file src="src/Operation/ReplaceOne.php">
560+
<PossiblyInvalidArgument>
561+
<code>$replacement</code>
562+
</PossiblyInvalidArgument>
563+
</file>
525564
<file src="src/Operation/Update.php">
526565
<MixedArgument>
527566
<code><![CDATA[$this->options['writeConcern']]]></code>

src/ChangeStream.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
namespace MongoDB;
1919

2020
use Iterator;
21+
use MongoDB\BSON\Document;
22+
use MongoDB\Codec\DocumentCodec;
2123
use MongoDB\Driver\CursorId;
2224
use MongoDB\Driver\Exception\ConnectionException;
2325
use MongoDB\Driver\Exception\RuntimeException;
@@ -27,6 +29,7 @@
2729
use MongoDB\Model\ChangeStreamIterator;
2830
use ReturnTypeWillChange;
2931

32+
use function assert;
3033
use function call_user_func;
3134
use function in_array;
3235

@@ -82,15 +85,22 @@ class ChangeStream implements Iterator
8285
*/
8386
private bool $hasAdvanced = false;
8487

88+
private ?DocumentCodec $codec;
89+
8590
/**
8691
* @internal
8792
*
8893
* @param ResumeCallable $resumeCallable
8994
*/
90-
public function __construct(ChangeStreamIterator $iterator, callable $resumeCallable)
95+
public function __construct(ChangeStreamIterator $iterator, callable $resumeCallable, ?DocumentCodec $codec = null)
9196
{
9297
$this->iterator = $iterator;
9398
$this->resumeCallable = $resumeCallable;
99+
$this->codec = $codec;
100+
101+
if ($codec) {
102+
$this->iterator->getInnerIterator()->setTypeMap(['root' => 'bson']);
103+
}
94104
}
95105

96106
/**
@@ -100,7 +110,15 @@ public function __construct(ChangeStreamIterator $iterator, callable $resumeCall
100110
#[ReturnTypeWillChange]
101111
public function current()
102112
{
103-
return $this->iterator->current();
113+
$value = $this->iterator->current();
114+
115+
if (! $this->codec) {
116+
return $value;
117+
}
118+
119+
assert($value instanceof Document);
120+
121+
return $this->codec->decode($value);
104122
}
105123

106124
/** @return CursorId */
@@ -252,6 +270,10 @@ private function resume(): void
252270

253271
$this->iterator->rewind();
254272

273+
if ($this->codec) {
274+
$this->iterator->getInnerIterator()->setTypeMap(['root' => 'bson']);
275+
}
276+
255277
$this->onIteration($this->hasAdvanced);
256278
}
257279

0 commit comments

Comments
 (0)