diff --git a/src/Builder/BuilderEncoder.php b/src/Builder/BuilderEncoder.php index 833409b07..e9121a7d0 100644 --- a/src/Builder/BuilderEncoder.php +++ b/src/Builder/BuilderEncoder.php @@ -32,7 +32,9 @@ use WeakReference; use function array_key_exists; +use function is_array; use function is_object; +use function iterator_to_array; /** @template-implements Encoder */ final class BuilderEncoder implements Encoder @@ -46,11 +48,15 @@ final class BuilderEncoder implements Encoder /** @var array */ private array $cachedEncoders = []; - /** @param array $encoders */ - public function __construct(array $encoders = []) + /** @param iterable $encoders */ + public function __construct(iterable $encoders = []) { $self = WeakReference::create($this); + if (! is_array($encoders)) { + $encoders = iterator_to_array($encoders); + } + $this->encoders = $encoders + [ Pipeline::class => new PipelineEncoder($self), Variable::class => new VariableEncoder(), diff --git a/tests/Builder/BuilderEncoderTest.php b/tests/Builder/BuilderEncoderTest.php index 5d80184c7..53080ab9e 100644 --- a/tests/Builder/BuilderEncoderTest.php +++ b/tests/Builder/BuilderEncoderTest.php @@ -423,6 +423,48 @@ public function encode(mixed $value): mixed $this->assertSamePipeline($expected, $pipeline, $codec); } + public function testCustomEncoderIterable(): void + { + $customEncoders = static function (): Generator { + yield FieldPathInterface::class => new class implements Encoder { + use EncodeIfSupported; + + public function canEncode(mixed $value): bool + { + return $value instanceof FieldPathInterface; + } + + public function encode(mixed $value): mixed + { + return '$prefix.' . $value->name; + } + }; + }; + + $codec = new BuilderEncoder($customEncoders()); + + $pipeline = new Pipeline( + Stage::project( + threeFavorites: Expression::slice( + Expression::arrayFieldPath('items'), + n: 3, + ), + ), + ); + + $expected = [ + [ + '$project' => [ + 'threeFavorites' => [ + '$slice' => ['$prefix.items', 3], + ], + ], + ], + ]; + + $this->assertSamePipeline($expected, $pipeline, $codec); + } + /** @param list> $expected */ private static function assertSamePipeline(array $expected, Pipeline $pipeline, $codec = new BuilderEncoder()): void {