Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.55% covered (success)
96.55%
28 / 29
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
PolymorphicEntityComponentProvider
96.55% covered (success)
96.55%
28 / 29
50.00% covered (danger)
50.00%
1 / 2
10
0.00% covered (danger)
0.00%
0 / 1
 supports
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
5
 createComponentFor
95.83% covered (success)
95.83%
23 / 24
0.00% covered (danger)
0.00%
0 / 1
5
1<?php
2namespace Apie\HtmlBuilders\Factories\Concrete;
3
4use Apie\Core\Entities\PolymorphicEntityInterface;
5use Apie\Core\Other\DiscriminatorMapping;
6use Apie\HtmlBuilders\Components\Forms\FormSplit;
7use Apie\HtmlBuilders\FormBuildContext;
8use Apie\HtmlBuilders\Interfaces\ComponentInterface;
9use Apie\HtmlBuilders\Interfaces\FormComponentProviderInterface;
10use Apie\HtmlBuilders\Lists\ComponentHashmap;
11use ReflectionClass;
12use ReflectionNamedType;
13use ReflectionType;
14
15class PolymorphicEntityComponentProvider implements FormComponentProviderInterface
16{
17    public function supports(ReflectionType $type, FormBuildContext $context): bool
18    {
19        if ($type instanceof ReflectionNamedType && !$type->isBuiltin() && class_exists($type->getName())) {
20            $refl = new ReflectionClass($type->getName());
21            return $refl->implementsInterface(PolymorphicEntityInterface::class)
22                && $refl->getMethod('getDiscriminatorMapping')->getDeclaringClass()->name === $refl->name;
23        }
24        return false;
25    }
26
27    /**
28     * @param ReflectionNamedType $type
29     */
30    public function createComponentFor(ReflectionType $type, FormBuildContext $context): ComponentInterface
31    {
32        $formComponentFactory = $context->getComponentFactory();
33        $refl = new ReflectionClass($type->getName());
34        $method = $refl->getMethod('getDiscriminatorMapping');
35        /** @var DiscriminatorMapping $mapping */
36        $mapping = $method->invoke(null);
37        $propertyName = $mapping->getPropertyName();
38        $configs = $mapping->getConfigs();
39        $value = $context->createChildContext($propertyName)->getFilledInValue(
40            ($type->allowsNull() || empty($configs))
41            ? null
42            : reset($configs)->getDiscriminator()
43        );
44        $components = [];
45        foreach ($configs as $config) {
46            $components[$config->getDiscriminator()] = $formComponentFactory->createFromClass(
47                new ReflectionClass($config->getClassName()),
48                $context->withApieContext('not-root', true)
49            );
50        }
51
52        return new FormSplit(
53            $context->getFormName()->createChildForm($propertyName),
54            isRootObject: !$context->getFormName()->hasChildFormFieldName() && !$context->getApieContext()->getContext('not-root', false),
55            isPolymorphic: true,
56            value: $value,
57            tabComponents: new ComponentHashmap($components)
58        );
59    }
60}