HydratorFactory   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 69
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 35
dl 0
loc 69
rs 10
c 0
b 0
f 0
wmc 9

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
B get() 0 53 8
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ApiSkeletons\Doctrine\GraphQL\Hydrator;
6
7
use ApiSkeletons\Doctrine\GraphQL\AbstractContainer;
8
use ApiSkeletons\Doctrine\GraphQL\Hydrator\Filter\Password;
9
use ApiSkeletons\Doctrine\GraphQL\Type\Entity;
10
use ApiSkeletons\Doctrine\GraphQL\Type\TypeManager;
11
use Doctrine\Laminas\Hydrator\DoctrineObject;
12
use Doctrine\ORM\EntityManager;
13
use GraphQL\Error\Error;
14
use Laminas\Hydrator\Filter;
15
use Laminas\Hydrator\NamingStrategy\NamingStrategyEnabledInterface;
16
use Laminas\Hydrator\NamingStrategy\NamingStrategyInterface;
17
use Laminas\Hydrator\Strategy\StrategyEnabledInterface;
18
use Laminas\Hydrator\Strategy\StrategyInterface;
19
20
use function assert;
21
use function class_implements;
22
use function in_array;
23
24
/**
25
 * This factory is used in the Metadata\Entity class to create a hydrator
26
 * for the current entity
27
 */
28
class HydratorFactory extends AbstractContainer
29
{
30
    public function __construct(protected EntityManager $entityManager, protected TypeManager $typeManager)
31
    {
32
        // Register project defaults
33
        $this
34
            ->set(Strategy\AssociationDefault::class, new Strategy\AssociationDefault())
35
            ->set(Strategy\FieldDefault::class, new Strategy\FieldDefault())
36
            ->set(Strategy\NullifyOwningAssociation::class, new Strategy\NullifyOwningAssociation())
37
            ->set(Strategy\ToBoolean::class, new Strategy\ToBoolean())
38
            ->set(Strategy\ToFloat::class, new Strategy\ToFloat())
39
            ->set(Strategy\ToInteger::class, new Strategy\ToInteger())
40
            ->set(Password::class, new Password());
41
    }
42
43
    /** @throws Error */
44
    public function get(string $id): mixed
45
    {
46
        // Custom hydrators should already be registered
47
        if ($this->has($id)) {
48
            return parent::get($id);
49
        }
50
51
        $entity   = $this->typeManager->build(Entity::class, $id);
52
        $config   = $entity->getMetadata();
53
        $hydrator = new DoctrineObject($this->entityManager, $config['byValue']);
54
55
        // Create field strategy and assign to hydrator
56
        if ($hydrator instanceof StrategyEnabledInterface) {
57
            foreach ($config['fields'] as $fieldName => $fieldMetadata) {
58
                assert(
59
                    in_array(StrategyInterface::class, class_implements($fieldMetadata['strategy'])),
60
                    'Strategy must implement ' . StrategyInterface::class,
61
                );
62
63
                $hydrator->addStrategy($fieldName, $this->get($fieldMetadata['strategy']));
64
            }
65
        }
66
67
        // Create filters and assign to hydrator
68
        if ($hydrator instanceof Filter\FilterEnabledInterface) {
69
            foreach ($config['filters'] as $name => $filterConfig) {
70
                // Default filters to AND
71
                $condition   = $filterConfig['condition'] ?? Filter\FilterComposite::CONDITION_AND;
72
                $filterClass = $filterConfig['filter'];
73
                assert(
74
                    in_array(Filter\FilterInterface::class, class_implements($filterClass)),
75
                    'Filter must implement ' . StrategyInterface::class,
76
                );
77
78
                $hydrator->addFilter($name, $this->get($filterClass), $condition);
79
            }
80
        }
81
82
        // Create naming strategy and assign to hydrator
83
        if ($hydrator instanceof NamingStrategyEnabledInterface && $config['namingStrategy']) {
84
            $namingStrategyClass = $config['namingStrategy'];
85
86
            assert(
87
                in_array(NamingStrategyInterface::class, class_implements($namingStrategyClass)),
88
                'Naming Strategy must implement ' . NamingStrategyInterface::class,
89
            );
90
91
            $hydrator->setNamingStrategy($this->get($namingStrategyClass));
92
        }
93
94
        $this->set($id, $hydrator);
95
96
        return $hydrator;
97
    }
98
}
99