Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
44 / 44 |
|
100.00% |
6 / 6 |
CRAP | |
100.00% |
1 / 1 |
PolymorphicEntityStrategy | |
100.00% |
44 / 44 |
|
100.00% |
6 / 6 |
26 | |
100.00% |
1 / 1 |
supports | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getModificationMetadata | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
7 | |||
getCreationMetadata | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
7 | |||
getResultMetadata | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
7 | |||
mergeChildClass | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | namespace Apie\Core\Metadata\Strategy; |
3 | |
4 | use Apie\Core\Context\ApieContext; |
5 | use Apie\Core\Context\MetadataFieldHashmap; |
6 | use Apie\Core\Entities\PolymorphicEntityInterface; |
7 | use Apie\Core\Metadata\CompositeMetadata; |
8 | use Apie\Core\Metadata\Fields\DiscriminatorColumn; |
9 | use Apie\Core\Metadata\Fields\FieldInterface; |
10 | use Apie\Core\Metadata\Fields\OptionalField; |
11 | use Apie\Core\Metadata\StrategyInterface; |
12 | use Apie\Core\Other\DiscriminatorConfig; |
13 | use Apie\Core\Other\DiscriminatorMapping; |
14 | use Apie\Core\Utils\EntityUtils; |
15 | use ReflectionClass; |
16 | |
17 | final class PolymorphicEntityStrategy implements StrategyInterface |
18 | { |
19 | public static function supports(ReflectionClass $class): bool |
20 | { |
21 | return EntityUtils::isPolymorphicEntity($class); |
22 | } |
23 | |
24 | /** |
25 | * @param ReflectionClass<PolymorphicEntityInterface> $class |
26 | */ |
27 | public function __construct(private ReflectionClass $class) |
28 | { |
29 | } |
30 | |
31 | public function getModificationMetadata(ApieContext $context): CompositeMetadata |
32 | { |
33 | $list = []; |
34 | |
35 | $class = $this->class; |
36 | |
37 | while ($class) { |
38 | $method = $class->getMethod('getDiscriminatorMapping'); |
39 | if (!$method->isAbstract() && $method->getDeclaringClass()->name === $class->name) { |
40 | /** @var DiscriminatorMapping $mapping */ |
41 | $mapping = $method->invoke(null); |
42 | foreach ($mapping->getConfigs() as $config) { |
43 | if ($method->getDeclaringClass()->name === $this->class->name || $config->getClassName() === $this->class->name) { |
44 | $this->mergeChildClass($context, $config, $list, 'getModificationMetadata'); |
45 | } |
46 | } |
47 | } |
48 | $class = $class->getParentClass(); |
49 | } |
50 | |
51 | return new CompositeMetadata(new MetadataFieldHashmap($list), $this->class); |
52 | } |
53 | |
54 | public function getCreationMetadata(ApieContext $context): CompositeMetadata |
55 | { |
56 | /** @var array<string, FieldInterface> $list */ |
57 | $list = []; |
58 | |
59 | $class = $this->class; |
60 | |
61 | while ($class) { |
62 | $method = $class->getMethod('getDiscriminatorMapping'); |
63 | if (!$method->isAbstract() && $method->getDeclaringClass()->name === $class->name) { |
64 | /** @var DiscriminatorMapping $mapping */ |
65 | $mapping = $method->invoke(null); |
66 | $list[$mapping->getPropertyName()] = new DiscriminatorColumn($mapping); |
67 | foreach ($mapping->getConfigs() as $config) { |
68 | if ($method->getDeclaringClass()->name === $this->class->name || $config->getClassName() === $this->class->name) { |
69 | $this->mergeChildClass($context, $config, $list, 'getCreationMetadata'); |
70 | } |
71 | } |
72 | } |
73 | $class = $class->getParentClass(); |
74 | } |
75 | |
76 | return new CompositeMetadata(new MetadataFieldHashmap($list), $this->class); |
77 | } |
78 | |
79 | public function getResultMetadata(ApieContext $context): CompositeMetadata |
80 | { |
81 | /** @var array<string, FieldInterface> $list */ |
82 | $list = []; |
83 | |
84 | $class = $this->class; |
85 | |
86 | while ($class) { |
87 | $method = $class->getMethod('getDiscriminatorMapping'); |
88 | if (!$method->isAbstract() && $method->getDeclaringClass()->name === $class->name) { |
89 | /** @var DiscriminatorMapping $mapping */ |
90 | $mapping = $method->invoke(null); |
91 | $list[$mapping->getPropertyName()] = new DiscriminatorColumn($mapping); |
92 | foreach ($mapping->getConfigs() as $config) { |
93 | if ($method->getDeclaringClass()->name === $this->class->name || $config->getClassName() === $this->class->name) { |
94 | $this->mergeChildClass($context, $config, $list, 'getResultMetadata'); |
95 | } |
96 | } |
97 | } |
98 | $class = $class->getParentClass(); |
99 | } |
100 | |
101 | return new CompositeMetadata(new MetadataFieldHashmap($list), $this->class); |
102 | } |
103 | |
104 | /** |
105 | * @param array<string, FieldInterface> $list |
106 | */ |
107 | private function mergeChildClass( |
108 | ApieContext $context, |
109 | DiscriminatorConfig $config, |
110 | array& $list, |
111 | string $method |
112 | ): void { |
113 | $refl = new ReflectionClass($config->getClassName()); |
114 | $tmp = new RegularObjectStrategy($refl); |
115 | $mapping = $tmp->$method($context); |
116 | foreach ($mapping->getHashmap() as $propertyName => $declaration) { |
117 | /** @var string $propertyName */ |
118 | if (isset($list[$propertyName])) { |
119 | $list[$propertyName] = new OptionalField($declaration, $list[$propertyName]); |
120 | } else { |
121 | $list[$propertyName] = new OptionalField($declaration); |
122 | } |
123 | } |
124 | } |
125 | } |