|
29 | 29 | use MongoDB\Codec\Encoder;
|
30 | 30 | use MongoDB\Exception\UnsupportedValueException;
|
31 | 31 | use stdClass;
|
| 32 | +use WeakReference; |
32 | 33 |
|
33 | 34 | use function array_key_exists;
|
34 | 35 | use function is_object;
|
35 |
| -use function is_string; |
36 | 36 |
|
37 | 37 | /** @template-implements Encoder<Type|stdClass|array|string|int, Pipeline|StageInterface|ExpressionInterface|QueryInterface> */
|
38 | 38 | final class BuilderEncoder implements Encoder
|
39 | 39 | {
|
40 | 40 | /** @template-use EncodeIfSupported<Type|stdClass|array|string|int, Pipeline|StageInterface|ExpressionInterface|QueryInterface> */
|
41 | 41 | use EncodeIfSupported;
|
42 | 42 |
|
43 |
| - /** @var array<class-string, class-string<Encoder>> */ |
44 |
| - private array $defaultEncoders = [ |
45 |
| - Pipeline::class => PipelineEncoder::class, |
46 |
| - Variable::class => VariableEncoder::class, |
47 |
| - DictionaryInterface::class => DictionaryEncoder::class, |
48 |
| - FieldPathInterface::class => FieldPathEncoder::class, |
49 |
| - CombinedFieldQuery::class => CombinedFieldQueryEncoder::class, |
50 |
| - QueryObject::class => QueryEncoder::class, |
51 |
| - OutputWindow::class => OutputWindowEncoder::class, |
52 |
| - OperatorInterface::class => OperatorEncoder::class, |
53 |
| - DateTimeInterface::class => DateTimeEncoder::class, |
54 |
| - ]; |
| 43 | + /** @var array<class-string, Encoder> */ |
| 44 | + private array $encoders; |
55 | 45 |
|
56 | 46 | /** @var array<class-string, Encoder|null> */
|
57 | 47 | private array $cachedEncoders = [];
|
58 | 48 |
|
59 |
| - /** @param array<class-string, Encoder> $customEncoders */ |
60 |
| - public function __construct(private readonly array $customEncoders = []) |
| 49 | + /** @param array<class-string, Encoder> $encoders */ |
| 50 | + public function __construct(array $encoders = []) |
61 | 51 | {
|
| 52 | + $self = WeakReference::create($this); |
| 53 | + |
| 54 | + $this->encoders = $encoders + [ |
| 55 | + Pipeline::class => new PipelineEncoder($self), |
| 56 | + Variable::class => new VariableEncoder(), |
| 57 | + DictionaryInterface::class => new DictionaryEncoder(), |
| 58 | + FieldPathInterface::class => new FieldPathEncoder(), |
| 59 | + CombinedFieldQuery::class => new CombinedFieldQueryEncoder($self), |
| 60 | + QueryObject::class => new QueryEncoder($self), |
| 61 | + OutputWindow::class => new OutputWindowEncoder($self), |
| 62 | + OperatorInterface::class => new OperatorEncoder($self), |
| 63 | + DateTimeInterface::class => new DateTimeEncoder(), |
| 64 | + ]; |
62 | 65 | }
|
63 | 66 |
|
64 | 67 | /** @psalm-assert-if-true object $value */
|
@@ -89,25 +92,14 @@ private function getEncoderFor(object $value): Encoder|null
|
89 | 92 | return $this->cachedEncoders[$valueClass];
|
90 | 93 | }
|
91 | 94 |
|
92 |
| - $encoderList = $this->customEncoders + $this->defaultEncoders; |
93 |
| - |
94 | 95 | // First attempt: match class name exactly
|
95 |
| - if (isset($encoderList[$valueClass])) { |
96 |
| - $encoder = $encoderList[$valueClass]; |
97 |
| - if (is_string($encoder)) { |
98 |
| - $encoder = new $encoder($this); |
99 |
| - } |
100 |
| - |
101 |
| - return $this->cachedEncoders[$valueClass] = $encoder; |
| 96 | + if (isset($this->encoders[$valueClass])) { |
| 97 | + return $this->cachedEncoders[$valueClass] = $this->encoders[$valueClass]; |
102 | 98 | }
|
103 | 99 |
|
104 | 100 | // Second attempt: catch child classes
|
105 |
| - foreach ($encoderList as $className => $encoder) { |
| 101 | + foreach ($this->encoders as $className => $encoder) { |
106 | 102 | if ($value instanceof $className) {
|
107 |
| - if (is_string($encoder)) { |
108 |
| - $encoder = new $encoder($this); |
109 |
| - } |
110 |
| - |
111 | 103 | return $this->cachedEncoders[$valueClass] = $encoder;
|
112 | 104 | }
|
113 | 105 | }
|
|
0 commit comments