Issues (590)

src/Mapper/SingleTableInheritanceMapper.php (4 issues)

1
<?php
2
3
namespace Bdf\Prime\Mapper;
4
5
use Bdf\Prime\Platform\PlatformInterface;
6
use Bdf\Prime\Relations\Relation;
7
8
/**
9
 * SingleTableInheritanceMapper
10
 *
11
 * @package Bdf\Prime\Mapper
12
 */
13
abstract class SingleTableInheritanceMapper extends Mapper implements MapperFactoryAwareInterface
14
{
15
    /**
16
     * The mapper factory
17
     *
18
     * @var MapperFactory
19
     */
20
    protected $mapperFactory;
21
22
    /**
23
     * The discriminator column
24
     *
25
     * @var string
26
     */
27
    protected $discriminatorColumn;
28
29
    /**
30
     * The discriminator map of mappers
31
     *
32
     * @var array<string, class-string<Mapper>>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, class-string<Mapper>> at position 4 could not be parsed: Unknown type name 'class-string' at position 4 in array<string, class-string<Mapper>>.
Loading history...
33
     */
34
    protected $discriminatorMap = [];
35
36
37
    /**
38
     * @todo voir pour retirer le mapper factory: passer par les depots
39
     * {@inheritdoc}
40
     * @final
41
     */
42 70
    public function setMapperFactory(MapperFactory $mapperFactory): void
43
    {
44 70
        $this->mapperFactory = $mapperFactory;
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 36
    public function relation(string $relationName): array
51
    {
52 36
        $relation = parent::relation($relationName);
53
54 36
        if ($this->isDiscriminatedMapper() && $relation['type'] == Relation::BY_INHERITANCE) {
55
            throw new \RuntimeException('Relation type not allowed from relation "' . $relationName . '" in ' . $this->getEntityClass());
56
        }
57
58 36
        return $relation;
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64 71
    public function customConstraints(): array
65
    {
66 71
        if ($this->isDiscriminatedMapper()) {
67 60
            return [$this->discriminatorColumn => array_search(static::class, $this->discriminatorMap)];
68
        }
69
70 49
        return parent::customConstraints();
71
    }
72
73
    /**
74
     * {@inheritDoc}
75
     */
76 46
    public function prepareFromRepository(array $data, PlatformInterface $platform)
77
    {
78 46
        if ($this->isDiscriminatedMapper()) {
79 44
            return parent::prepareFromRepository($data, $platform);
80
        }
81
82 43
        return $this->getMapperByDiscriminatorValue($this->getDiscriminatorValueByRawData($data))->prepareFromRepository($data, $platform);
83
    }
84
85
    /**
86
     * Get the discriminator map of mappers
87
     *
88
     * @return array
89
     * @final
90
     */
91 24
    public function getDiscriminatorMap(): array
92
    {
93 24
        return $this->discriminatorMap;
94
    }
95
96
    /**
97
     * Get the discriminator map of entities
98
     *
99
     * @return array<string, class-string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, class-string> at position 4 could not be parsed: Unknown type name 'class-string' at position 4 in array<string, class-string>.
Loading history...
100
     * @final
101
     */
102 40
    public function getEntityMap(): array
103
    {
104 40
        $map = [];
105 40
        $resolver = $this->mapperFactory->getNameResolver();
106
107 40
        foreach ($this->discriminatorMap as $key => $mapperClass) {
108 40
            $map[$key] = $resolver->reverse($mapperClass);
109
        }
110
111 40
        return $map;
112
    }
113
114
    /**
115
     * Get the discriminator column
116
     *
117
     * @return string
118
     * @final
119
     */
120 31
    public function getDiscriminatorColumn(): string
121
    {
122 31
        return $this->discriminatorColumn;
123
    }
124
125
    /**
126
     * Get the mapper by a discriminator value
127
     *
128
     * @param mixed $value
129
     *
130
     * @return Mapper
131
     * @psalm-suppress InvalidNullableReturnType
132
     * @final
133
     */
134 43
    public function getMapperByDiscriminatorValue($value): Mapper
135
    {
136
        /** @psalm-suppress NullableReturnStatement */
137 43
        return $this->mapperFactory->createMapper(
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->mapperFact...criminatorType($value)) could return the type null which is incompatible with the type-hinted return Bdf\Prime\Mapper\Mapper. Consider adding an additional type-check to rule them out.
Loading history...
138 43
            $this->serviceLocator,
139 43
            $this->getDiscriminatorType($value)
140 43
        );
141
    }
142
143
    /**
144
     * Get the discriminator value from array of data
145
     *
146
     * @param array $data
147
     *
148
     * @return mixed
149
     *
150
     * @throws \Exception if discriminator field not present in $data
151
     * @final
152
     */
153 45
    public function getDiscriminatorValueByRawData(array $data)
154
    {
155 45
        $discriminatorField = $this->metadata()->attributes[$this->discriminatorColumn]['field'];
156
157 45
        if (empty($data[$discriminatorField])) {
158 2
            throw new \Exception('Discriminator field "' . $discriminatorField . '" not found');
159
        }
160
161 43
        return $data[$discriminatorField];
162
    }
163
164
    /**
165
     * Get the mapper class from discriminator value
166
     *
167
     * @param mixed $discriminatorValue
168
     *
169
     * @return class-string<Mapper>
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<Mapper> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<Mapper>.
Loading history...
170
     *
171
     * @throws \Exception if discriminator value is unknown
172
     * @final
173
     */
174 45
    public function getDiscriminatorType($discriminatorValue): string
175
    {
176 45
        if (empty($this->discriminatorMap[$discriminatorValue])) {
177 2
            throw new \Exception('Unknown discriminator type "' . $discriminatorValue . '"');
178
        }
179
180 43
        return $this->discriminatorMap[$discriminatorValue];
181
    }
182
183
    /**
184
     * Check whether the class is a discriminated mapper
185
     *
186
     * @return boolean
187
     * @final
188
     */
189 72
    protected function isDiscriminatedMapper(): bool
190
    {
191 72
        return in_array(static::class, $this->discriminatorMap);
192
    }
193
}
194