|
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