1 | <?php |
||||||
2 | |||||||
3 | namespace Bdf\Prime\Schema; |
||||||
4 | |||||||
5 | use Bdf\Prime\Connection\ConnectionInterface; |
||||||
6 | use Bdf\Prime\Exception\DBALException; |
||||||
7 | use Bdf\Prime\Exception\PrimeException; |
||||||
8 | use Bdf\Prime\Schema\Adapter\ConstraintTable; |
||||||
9 | use Bdf\Prime\Schema\Adapter\MapperInfo\MapperInfoConstraintSet; |
||||||
10 | use Bdf\Prime\Schema\Adapter\MapperInfo\Resolver\MapperInfoForeignKeyResolver; |
||||||
11 | use Bdf\Prime\Schema\Adapter\Metadata\MetadataTable; |
||||||
12 | use Bdf\Prime\Schema\Builder\TableBuilder; |
||||||
13 | use Bdf\Prime\ServiceLocator; |
||||||
14 | use Bdf\Prime\Mapper\Metadata; |
||||||
15 | use Doctrine\DBAL\Exception\TableNotFoundException; |
||||||
16 | |||||||
17 | /** |
||||||
18 | * Handle structure migration of repository tables |
||||||
19 | * |
||||||
20 | * @todo gestion du renommage de champs dans le cas où d'autres attributs ont été changés |
||||||
21 | */ |
||||||
22 | class RepositoryUpgrader implements StructureUpgraderInterface |
||||||
23 | { |
||||||
24 | /** |
||||||
25 | * @var ServiceLocator |
||||||
26 | */ |
||||||
27 | protected $service; |
||||||
28 | |||||||
29 | /** |
||||||
30 | * @var Metadata |
||||||
31 | */ |
||||||
32 | protected $metadata; |
||||||
33 | |||||||
34 | /** |
||||||
35 | * @var SchemaManagerInterface |
||||||
36 | */ |
||||||
37 | protected $schema; |
||||||
38 | |||||||
39 | |||||||
40 | /** |
||||||
41 | * @param ServiceLocator $service Prime service |
||||||
42 | * @param Metadata $metadata The entity metadata |
||||||
43 | * @param SchemaManagerInterface|null $schema If given, force using this schema manager instead of resolving using the configured connection name |
||||||
44 | */ |
||||||
45 | 871 | public function __construct(ServiceLocator $service, Metadata $metadata, SchemaManagerInterface $schema = null) |
|||||
46 | { |
||||||
47 | 871 | $this->service = $service; |
|||||
48 | 871 | $this->metadata = $metadata; |
|||||
49 | 871 | $this->schema = $schema; |
|||||
50 | } |
||||||
51 | |||||||
52 | /** |
||||||
53 | * {@inheritdoc} |
||||||
54 | */ |
||||||
55 | 861 | public function migrate(bool $listDrop = true): void |
|||||
56 | { |
||||||
57 | 861 | $schema = $this->schema()->useDrop($listDrop); |
|||||
58 | 861 | $schema->add($this->table()); |
|||||
59 | |||||||
60 | 861 | if (($schemaSequence = $this->schemaSequence()) !== null) { |
|||||
61 | 524 | $schemaSequence->useDrop($listDrop); |
|||||
62 | 524 | $schemaSequence->add($this->sequence()); |
|||||
63 | |||||||
64 | 524 | $this->insertSequenceId(); |
|||||
65 | } |
||||||
66 | } |
||||||
67 | |||||||
68 | /** |
||||||
69 | * {@inheritdoc} |
||||||
70 | */ |
||||||
71 | 6 | public function diff(bool $listDrop = true): array |
|||||
72 | { |
||||||
73 | 6 | $queries = $this->schema() |
|||||
74 | 6 | ->simulate(function (SchemaManagerInterface $schema) use ($listDrop) { |
|||||
75 | 6 | $schema->useDrop($listDrop); |
|||||
76 | 6 | $schema->add($this->table()); |
|||||
77 | 6 | }) |
|||||
78 | 6 | ->pending(); |
|||||
79 | |||||||
80 | 6 | if (($schemaSequence = $this->schemaSequence()) === null) { |
|||||
81 | 5 | return $queries; |
|||||
82 | } |
||||||
83 | |||||||
84 | 1 | $sequenceQueries = $schemaSequence |
|||||
85 | 1 | ->simulate(function (SchemaManagerInterface $schema) use ($listDrop) { |
|||||
86 | 1 | $schema->useDrop($listDrop); |
|||||
87 | 1 | $schema->add($this->sequence()); |
|||||
88 | 1 | }) |
|||||
89 | 1 | ->pending(); |
|||||
90 | |||||||
91 | 1 | return array_merge($queries, $sequenceQueries); |
|||||
92 | } |
||||||
93 | |||||||
94 | /** |
||||||
95 | * Create table schema from meta |
||||||
96 | * |
||||||
97 | * @param bool $foreignKeys Add foreign key constraints to the schema ? |
||||||
98 | * |
||||||
99 | * @return TableInterface |
||||||
100 | * @throws PrimeException |
||||||
101 | */ |
||||||
102 | 867 | public function table(bool $foreignKeys = false): TableInterface |
|||||
103 | { |
||||||
104 | 867 | $table = new MetadataTable( |
|||||
105 | 867 | $this->metadata, |
|||||
106 | 867 | $this->connection()->platform()->types() |
|||||
107 | 867 | ); |
|||||
108 | |||||||
109 | 867 | if ($foreignKeys) { |
|||||
110 | 1 | $table = new ConstraintTable( |
|||||
111 | 1 | $table, |
|||||
112 | 1 | new MapperInfoConstraintSet( |
|||||
113 | 1 | $this->service->repository($this->metadata->entityName)->mapper()->info(), |
|||||
114 | 1 | [ |
|||||
115 | 1 | new MapperInfoForeignKeyResolver($this->service) |
|||||
116 | 1 | ] |
|||||
117 | 1 | ) |
|||||
118 | 1 | ); |
|||||
119 | } |
||||||
120 | |||||||
121 | 867 | return $table; |
|||||
122 | } |
||||||
123 | |||||||
124 | /** |
||||||
125 | * Create sequence schema from meta |
||||||
126 | * |
||||||
127 | * @return null|TableInterface The table or null if the current repository has no sequence |
||||||
128 | * @throws PrimeException |
||||||
129 | */ |
||||||
130 | 527 | public function sequence(): ?TableInterface |
|||||
131 | { |
||||||
132 | 527 | if (!$this->metadata->isSequencePrimaryKey()) { |
|||||
133 | 1 | return null; |
|||||
134 | } |
||||||
135 | |||||||
136 | 526 | $table = new TableBuilder($this->metadata->sequence['table']); |
|||||
137 | 526 | $table->options($this->metadata->sequence['options']); |
|||||
138 | 526 | $table->add( |
|||||
139 | 526 | $this->metadata->sequence['column'], |
|||||
140 | 526 | $this->connection($this->metadata->sequence['connection'])->platform()->types()->native('bigint') |
|||||
141 | 526 | ); |
|||||
142 | 526 | $table->primary($this->metadata->sequence['column']); |
|||||
143 | |||||||
144 | 526 | return $table->build(); |
|||||
145 | } |
||||||
146 | |||||||
147 | /** |
||||||
148 | * Insert sequence id into sequence table |
||||||
149 | * |
||||||
150 | * @throws PrimeException |
||||||
151 | * |
||||||
152 | * @return void |
||||||
153 | */ |
||||||
154 | 524 | public function insertSequenceId(): void |
|||||
155 | { |
||||||
156 | 524 | if (!$this->metadata->isSequencePrimaryKey()) { |
|||||
157 | return; |
||||||
158 | } |
||||||
159 | |||||||
160 | /** @var ConnectionInterface&\Doctrine\DBAL\Connection $connection */ |
||||||
161 | 524 | $connection = $this->connection($this->metadata->sequence['connection']); |
|||||
162 | 524 | $table = $this->metadata->sequence['table']; |
|||||
163 | |||||||
164 | /** @psalm-suppress UndefinedInterfaceMethod */ |
||||||
165 | 524 | $nb = $connection->from($table)->count(); |
|||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||||
166 | |||||||
167 | 524 | if ($nb == 0) { |
|||||
168 | 524 | $connection->insert($table, [$this->metadata->sequence['column'] => 0]); |
|||||
0 ignored issues
–
show
The method
insert() does not exist on Bdf\Prime\Connection\ConnectionInterface . Since it exists in all sub-types, consider adding an abstract or default implementation to Bdf\Prime\Connection\ConnectionInterface .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
169 | } |
||||||
170 | } |
||||||
171 | |||||||
172 | /** |
||||||
173 | * {@inheritdoc} |
||||||
174 | */ |
||||||
175 | 1 | public function truncate(bool $cascade = false): bool |
|||||
176 | { |
||||||
177 | 1 | $this->schema()->truncate($this->metadata->table, $cascade); |
|||||
178 | |||||||
179 | 1 | return true; |
|||||
180 | } |
||||||
181 | |||||||
182 | /** |
||||||
183 | * {@inheritdoc} |
||||||
184 | */ |
||||||
185 | 812 | public function drop(): bool |
|||||
186 | { |
||||||
187 | try { |
||||||
188 | 812 | $this->schema()->drop($this->metadata->table); |
|||||
189 | |||||||
190 | 808 | if (($schemaSequence = $this->schemaSequence()) !== null) { |
|||||
191 | 516 | $schemaSequence->drop($this->metadata->sequence['table']); |
|||||
192 | } |
||||||
193 | |||||||
194 | 808 | return true; |
|||||
195 | 61 | } catch (DBALException $e) { |
|||||
196 | 61 | if ($e->getPrevious() instanceof TableNotFoundException) { |
|||||
197 | 61 | return false; |
|||||
198 | } |
||||||
199 | |||||||
200 | throw $e; |
||||||
201 | } |
||||||
202 | } |
||||||
203 | |||||||
204 | /** |
||||||
205 | * Get the schema builder |
||||||
206 | * |
||||||
207 | * @return SchemaManagerInterface |
||||||
208 | * @throws PrimeException |
||||||
209 | */ |
||||||
210 | 865 | protected function schema() |
|||||
211 | { |
||||||
212 | 865 | if ($this->schema !== null) { |
|||||
213 | return $this->schema; |
||||||
214 | } |
||||||
215 | |||||||
216 | 865 | return $this->connection()->schema(); |
|||||
217 | } |
||||||
218 | |||||||
219 | /** |
||||||
220 | * Get the schema builder for sequence |
||||||
221 | * |
||||||
222 | * @return SchemaManagerInterface|null |
||||||
223 | * @throws PrimeException |
||||||
224 | */ |
||||||
225 | 863 | protected function schemaSequence() |
|||||
226 | { |
||||||
227 | 863 | if (!$this->metadata->isSequencePrimaryKey()) { |
|||||
228 | 855 | return null; |
|||||
229 | } |
||||||
230 | |||||||
231 | 525 | if ($this->schema !== null) { |
|||||
232 | return $this->schema; |
||||||
233 | } |
||||||
234 | |||||||
235 | 525 | return $this->connection($this->metadata->sequence['connection'])->schema(); |
|||||
236 | } |
||||||
237 | |||||||
238 | /** |
||||||
239 | * Get the connection |
||||||
240 | * |
||||||
241 | * @param string $profile |
||||||
242 | * |
||||||
243 | * @return ConnectionInterface |
||||||
244 | */ |
||||||
245 | 870 | protected function connection($profile = null) |
|||||
246 | { |
||||||
247 | 870 | return $this->service->connection($profile ?: $this->metadata->connection); |
|||||
248 | } |
||||||
249 | } |
||||||
250 |