Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
65.22% covered (warning)
65.22%
30 / 46
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
FromGetters
65.22% covered (warning)
65.22%
30 / 46
33.33% covered (danger)
33.33%
1 / 3
42.37
0.00% covered (danger)
0.00%
0 / 1
 support
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 getIndexes
95.45% covered (success)
95.45%
21 / 22
0.00% covered (danger)
0.00%
0 / 1
11
 getPrio
34.78% covered (danger)
34.78%
8 / 23
0.00% covered (danger)
0.00%
0 / 1
31.47
1<?php
2namespace Apie\Core\Indexing;
3
4use Apie\Core\Attributes\SearchFilterOption;
5use Apie\Core\Context\ApieContext;
6use Apie\Core\Dto\DtoInterface;
7use Apie\Core\Entities\EntityInterface;
8use Apie\Core\Metadata\Fields\FieldInterface;
9use Apie\Core\Metadata\GetterInterface;
10use Apie\Core\Metadata\MetadataFactory;
11use Apie\Core\ValueObjects\Interfaces\ValueObjectInterface;
12use LogicException;
13use ReflectionClass;
14use ReflectionNamedType;
15
16class FromGetters implements IndexingStrategyInterface
17{
18    public function support(object $object): bool
19    {
20        return $object instanceof EntityInterface || $object instanceof DtoInterface;
21    }
22
23    /**
24     * @return array<string, int>
25     */
26    public function getIndexes(object $object, ApieContext $context, Indexer $indexer): array
27    {
28        $metadata = MetadataFactory::getResultMetadata(new ReflectionClass($object), $context);
29        $result = [];
30        foreach ($metadata->getHashmap() as $propertyName => $fieldMetadata) {
31            if (!$fieldMetadata->isField() || !$fieldMetadata instanceof GetterInterface) {
32                continue;
33            }
34            assert($fieldMetadata instanceof FieldInterface);
35            foreach ($fieldMetadata->getAttributes(SearchFilterOption::class) as $searchFilterOption) {
36                if (!$searchFilterOption->enabled) {
37                    continue 2;
38                }
39            }
40            /** @var GetterInterface&FieldInterface $fieldMetadata */
41            $typehint = $fieldMetadata->getTypehint();
42            if (!$typehint instanceof ReflectionNamedType) {
43                continue;
44            }
45            try {
46                $value = $fieldMetadata->getValue($object, $context);
47            } catch (LogicException) { // see GetterMethod::getValue
48                $value = null;
49            }
50            if (is_object($value)) {
51                $embeddedObjectResult = $indexer->getIndexesForObject($value, $context);
52                $result = Indexer::merge($result, $embeddedObjectResult);
53            } elseif (is_string($value) || is_numeric($value)) {
54                $value = (string) $value;
55                $result[$value] = $this->getPrio($propertyName, $typehint, $fieldMetadata, $value, $result[$value] ?? 0);
56            }
57        }
58        return $result;
59    }
60
61    private function getPrio(
62        string $propertyName,
63        ReflectionNamedType $typehint,
64        FieldInterface&GetterInterface $fieldMetadata,
65        string $value,
66        int $currentPrio
67    ): int {
68        if (in_array($typehint->getName(), ['string', 'int', 'float'])) {
69            return max(
70                match ($propertyName) {
71                    'id' => 1,
72                    'name' => 5,
73                    'description' => 4,
74                    default => 2,
75                },
76                $currentPrio
77            );
78        } elseif (!$typehint->isBuiltin() && class_exists($typehint->getName())) {
79            $refl = new ReflectionClass($typehint->getName());
80            if ($refl->implementsInterface(ValueObjectInterface::class)) {
81                $returnType = $refl->getMethod('toNative')->getReturnType();
82                assert($returnType instanceof ReflectionNamedType);
83                return $this->getPrio(
84                    $propertyName,
85                    $returnType,
86                    $fieldMetadata,
87                    $value,
88                    $currentPrio
89                );
90            }
91        }
92        return 0;
93    }
94}