Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.33% covered (success)
93.33%
28 / 30
60.00% covered (warning)
60.00%
3 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
EntityIdentifierOptionProvider
93.33% covered (success)
93.33%
28 / 30
60.00% covered (warning)
60.00%
3 / 5
13.05
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 supportsField
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBoundedContext
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
5.03
 createDropdownList
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
3
 determineDisplayValue
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
1<?php
2namespace Apie\CmsApiDropdownOption\DropdownOptionProvider;
3
4use Apie\CmsApiDropdownOption\Dtos\DropdownOption;
5use Apie\CmsApiDropdownOption\Lists\DropdownOptionList;
6use Apie\Core\BoundedContext\BoundedContext;
7use Apie\Core\BoundedContext\BoundedContextHashmap;
8use Apie\Core\BoundedContext\BoundedContextId;
9use Apie\Core\Context\ApieContext;
10use Apie\Core\ContextConstants;
11use Apie\Core\Datalayers\ApieDatalayer;
12use Apie\Core\Datalayers\Search\QuerySearch;
13use Apie\Core\Entities\EntityInterface;
14use Apie\Core\Exceptions\InvalidTypeException;
15use Apie\Core\Identifiers\IdentifierInterface;
16use Apie\Core\Metadata\Fields\FieldInterface;
17use Apie\Core\ValueObjects\Utils;
18use ReflectionClass;
19use ReflectionNamedType;
20
21final class EntityIdentifierOptionProvider extends BaseDropdownOptionProvider
22{
23    public function __construct(
24        private readonly BoundedContextHashmap $boundedContextHashmap,
25        private readonly ApieDatalayer $apieDatalayer
26    ) {
27    }
28
29    protected function supportsField(FieldInterface $fieldMetadata, ApieContext $apieContext): bool
30    {
31        return null !== $this->getBoundedContext($fieldMetadata, $apieContext);
32    }
33
34    private function getBoundedContext(FieldInterface $fieldMetadata, ApieContext $apieContext): ?BoundedContext
35    {
36        $typehint = $fieldMetadata->getTypehint();
37        if (!$typehint instanceof ReflectionNamedType || $typehint->isBuiltin()) {
38            return null;
39        }
40        /**  @var ReflectionClass<IdentifierInterface<EntityInterface>> $class */
41        $class = new ReflectionClass($typehint->getName());
42        if (!in_array(IdentifierInterface::class, $class->getInterfaceNames())) {
43            return null;
44        }
45        $boundedContextId = $apieContext->hasContext(ContextConstants::BOUNDED_CONTEXT_ID)
46            ? new BoundedContextId($apieContext->getContext(ContextConstants::BOUNDED_CONTEXT_ID))
47            : null;
48        return $this->boundedContextHashmap->getBoundedContextFromClassName($class, $boundedContextId);
49    }
50
51    protected function createDropdownList(
52        string $property,
53        FieldInterface $fieldMetadata,
54        string $searchTerm,
55        ApieContext $apieContext
56    ): DropdownOptionList {
57        $boundedContext = $this->getBoundedContext($fieldMetadata, $apieContext);
58        assert($boundedContext instanceof BoundedContext);
59        $typehint = $fieldMetadata->getTypehint();
60        assert($typehint instanceof ReflectionNamedType);
61        $class = new ReflectionClass($typehint->getName());
62        if (in_array(IdentifierInterface::class, $class->getInterfaceNames())) {
63            $class = $class->getMethod('getReferenceFor')->invoke(null);
64        }
65        $result = $this->apieDatalayer->all($class, $boundedContext->getId())
66            ->toPaginatedResult(new QuerySearch(0, textSearch: $searchTerm, apieContext: $apieContext));
67        $list = [];
68        foreach ($result as $entity) {
69            $list[] = new DropdownOption($entity->getId(), $this->determineDisplayValue($entity));
70        }
71
72        return new DropdownOptionList($list);
73    }
74
75    private function determineDisplayValue(EntityInterface $entity): string
76    {
77        $methods = ['getName', 'getDescription', '__toString', 'getId'];
78        foreach ($methods as $method) {
79            if (is_callable([$entity, $method])) {
80                return Utils::toString($entity->$method());
81            }
82        }
83
84        throw new InvalidTypeException($entity, 'EntityInterface');
85    }
86}