diff --git a/src/Attribute/ObjectType/Slots.php b/src/Attribute/ObjectType/Slots.php index 8e6e617..5bb8550 100644 --- a/src/Attribute/ObjectType/Slots.php +++ b/src/Attribute/ObjectType/Slots.php @@ -118,9 +118,8 @@ public static function lateBindObjectToBuild(mixed $build, mixed $definition, ob foreach ($definition->slots as $slot) { if (true === $build->pintoHas($slot->name)) { $slotValue = $build->pintoGet($slot->name); - if (\is_object($slotValue) && ($invokerMethod = $context->getBuildInvoker($slotValue::class)) !== null) { - // @phpstan-ignore-next-line - $build->set($slot->name, $slotValue->{$invokerMethod}()); + if (\is_object($slotValue) && ($builder = $context->getBuilder($slotValue)) !== null) { + $build->set($slot->name, $builder()); } } } diff --git a/src/ObjectType/LateBindObjectContext.php b/src/ObjectType/LateBindObjectContext.php index 2bdce7e..772bc75 100644 --- a/src/ObjectType/LateBindObjectContext.php +++ b/src/ObjectType/LateBindObjectContext.php @@ -8,8 +8,6 @@ use Pinto\PintoMapping; /** - * Discovers ObjectTypeInterface attributes on a class, on a class or its methods. - * * @internal */ final class LateBindObjectContext @@ -27,13 +25,10 @@ public static function create(PintoMapping $pintoMapping): static return new static($pintoMapping); } - /** - * @param class-string $objectClassName - */ - public function getBuildInvoker(string $objectClassName): ?string + public function getBuilder(object $component): ?\Closure { try { - return $this->pintoMapping->getBuildInvoker($objectClassName); + return $this->pintoMapping->getBuilder($component); } catch (PintoMissingObjectMapping) { return null; } diff --git a/src/PintoMapping.php b/src/PintoMapping.php index bdbbd50..f748d0b 100644 --- a/src/PintoMapping.php +++ b/src/PintoMapping.php @@ -69,6 +69,17 @@ public function getBuildInvoker(string $objectClassName): string return $this->buildInvokers[$objectClassName] ?? throw new PintoMissingObjectMapping($objectClassName); } + /** + * @throws PintoMissingObjectMapping + */ + public function getBuilder(object $component): \Closure + { + $method = $this->buildInvokers[$component::class] ?? throw new PintoMissingObjectMapping($component::class); + + // @phpstan-ignore-next-line + return $component->{$method}(...); + } + public function getResources(): ResourceCollectionInterface { return $this->resources; diff --git a/tests/PintoMappingTest.php b/tests/PintoMappingTest.php index eba18fe..f6368d8 100644 --- a/tests/PintoMappingTest.php +++ b/tests/PintoMappingTest.php @@ -45,4 +45,35 @@ public function testGetBuildInvokerException(): void static::expectException(PintoMissingObjectMapping::class); $pintoMapping->getBuildInvoker(fixtures\Objects\PintoObject::class); } + + public function testGetBuilderException(): void + { + $pintoMapping = new PintoMapping([], [], [], [], []); + static::expectException(PintoMissingObjectMapping::class); + $component = fixtures\Objects\PintoObject::create('Foo'); + $pintoMapping->getBuilder($component); + } + + /** + * @covers \Pinto\PintoMapping::getBuilder + */ + public function testGetBuilder(): void + { + $pintoMapping = new PintoMapping( + resources: [], + definitions: [], + buildInvokers: [ + fixtures\Objects\PintoObject::class => '__invoke', + ], + types: [], + lsbFactoryCanonicalObjectClasses: [], + ); + + $component = fixtures\Objects\PintoObject::create('Foo'); + $builder = $pintoMapping->getBuilder($component); + static::assertIsCallable($builder); + + $result = $builder(); + static::assertEquals('Foo', $result['#test_variable']); + } }