Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
EntityQueryFilterFactory
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
1 / 1
10
100.00% covered (success)
100.00%
1 / 1
 createFilterList
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
1 / 1
10
1<?php
2
3namespace Apie\DoctrineEntityDatalayer\Factories;
4
5use Apie\Core\Attributes\ClassStoreOptions;
6use Apie\Core\BoundedContext\BoundedContextId;
7use Apie\Core\Context\ApieContext;
8use Apie\Core\Entities\RequiresRecalculatingInterface;
9use Apie\Core\Enums\ScalarType;
10use Apie\Core\Metadata\MetadataFactory;
11use Apie\Core\Permissions\RequiresPermissionsInterface;
12use Apie\DoctrineEntityDatalayer\DoctrineEntityDatalayer;
13use Apie\DoctrineEntityDatalayer\Query\DefaultOptionFilter;
14use Apie\DoctrineEntityDatalayer\Query\EntityQueryFilterInterface;
15use Apie\DoctrineEntityDatalayer\Query\FieldTextSearchFilter;
16use Apie\DoctrineEntityDatalayer\Query\FulltextSearchFilter;
17use Apie\DoctrineEntityDatalayer\Query\OrderBySearchFilter;
18use Apie\DoctrineEntityDatalayer\Query\RequiresPermissionFilter;
19use Apie\DoctrineEntityDatalayer\Query\SearchByInternalColumnFilter;
20use Apie\StorageMetadata\Attributes\GetMethodAttribute;
21use Apie\StorageMetadata\Attributes\GetSearchIndexAttribute;
22use Apie\StorageMetadata\Attributes\PropertyAttribute;
23use Apie\StorageMetadata\Interfaces\StorageDtoInterface;
24use Apie\TypeConverter\ReflectionTypeFactory;
25use ReflectionAttribute;
26use ReflectionClass;
27use ReflectionProperty;
28
29final class EntityQueryFilterFactory
30{
31    /**
32     * @param ReflectionClass<StorageDtoInterface> $doctrineClass
33     * @return EntityQueryFilterInterface[]
34     *
35     * @see DoctrineEntityDatalayer::getOrderByColumns()
36     */
37    public function createFilterList(ReflectionClass $doctrineClass, BoundedContextId $boundedContextId): array
38    {
39        $domainClass = $doctrineClass->getMethod('getClassReference')->invoke(null);
40        $filters = [];
41
42        if (in_array(RequiresRecalculatingInterface::class, $domainClass->getInterfaceNames())) {
43            $filters[] = new SearchByInternalColumnFilter(
44                'dateToRecalculate',
45                'requires_update'
46            );
47        }
48        $filters[] = new SearchByInternalColumnFilter(
49            'createdAt',
50            'created_at'
51        );
52        $filters[] = new SearchByInternalColumnFilter(
53            'updatedAt',
54            'updated_at'
55        );
56
57        foreach ($doctrineClass->getProperties(ReflectionProperty::IS_PUBLIC) as $publicProperty) {
58            if (str_starts_with($publicProperty->name, 'search_')) {
59                foreach ($publicProperty->getAttributes(GetSearchIndexAttribute::class) as $publicPropertyAttribute) {
60                    $filters[] = new FieldTextSearchFilter(
61                        substr($publicProperty->name, strlen('search_')),
62                        $publicPropertyAttribute->newInstance()->arrayValueType ?? (string) $publicProperty->getType()
63                    );
64                }
65            } else {
66                foreach ($publicProperty->getAttributes(GetMethodAttribute::class) as $publicPropertyAttribute) {
67                    $filters[] = new FieldTextSearchFilter(
68                        $publicPropertyAttribute->newInstance()->methodName,
69                        $publicProperty->name
70                    );
71                }
72                $metadata = MetadataFactory::getModificationMetadata(
73                    $publicProperty->getType() ?? ReflectionTypeFactory::createReflectionType('mixed'),
74                    new ApieContext()
75                );
76                if (in_array($metadata->toScalarType(true), ScalarType::PRIMITIVES)) {
77                    foreach ($publicProperty->getAttributes(PropertyAttribute::class, ReflectionAttribute::IS_INSTANCEOF) as $publicPropertyAttribute) {
78                        $filters[] = new OrderBySearchFilter(
79                            $publicPropertyAttribute->newInstance()->propertyName,
80                            $publicProperty->getName()
81                        );
82                    }
83                }
84            }
85        }
86        $filters[] = new FulltextSearchFilter(
87            $domainClass,
88            $boundedContextId
89        );
90        foreach ($domainClass->getAttributes(ClassStoreOptions::class) as $classStoreOptionsAttribute) {
91            $classStoreOptions = $classStoreOptionsAttribute->newInstance();
92            $filters[] = new DefaultOptionFilter($classStoreOptions);
93        }
94
95        if (in_array(RequiresPermissionsInterface::class, $domainClass->getInterfaceNames())) {
96            $filters[] = new RequiresPermissionFilter($domainClass, $boundedContextId);
97        }
98
99        return $filters;
100    }
101}