1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
4
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
5
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
6
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
7
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
8
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
9
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
10
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
11
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
12
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
13
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
14
|
|
|
* |
15
|
|
|
* This software consists of voluntary contributions made by many individuals |
16
|
|
|
* and is licensed under the MIT license. For more information, see |
17
|
|
|
* <http://www.doctrine-project.org>. |
18
|
|
|
*/ |
19
|
|
|
|
20
|
|
|
namespace Doctrine\ORM\Mapping\Driver; |
21
|
|
|
|
22
|
|
|
use Doctrine\Common\Inflector\Inflector; |
23
|
|
|
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; |
24
|
|
|
use Doctrine\Common\Persistence\Mapping\ClassMetadata; |
25
|
|
|
use Doctrine\DBAL\Schema\AbstractSchemaManager; |
26
|
|
|
use Doctrine\DBAL\Schema\SchemaException; |
27
|
|
|
use Doctrine\DBAL\Schema\Table; |
28
|
|
|
use Doctrine\DBAL\Schema\Column; |
29
|
|
|
use Doctrine\DBAL\Types\Type; |
30
|
|
|
use Doctrine\ORM\Mapping\ClassMetadataInfo; |
31
|
|
|
use Doctrine\ORM\Mapping\MappingException; |
32
|
|
|
use function preg_replace; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* The DatabaseDriver reverse engineers the mapping metadata from a database. |
36
|
|
|
* |
37
|
|
|
* @link www.doctrine-project.org |
38
|
|
|
* @since 2.0 |
39
|
|
|
* @author Guilherme Blanco <[email protected]> |
40
|
|
|
* @author Jonathan Wage <[email protected]> |
41
|
|
|
* @author Benjamin Eberlei <[email protected]> |
42
|
|
|
*/ |
43
|
|
|
class DatabaseDriver implements MappingDriver |
|
|
|
|
44
|
|
|
{ |
45
|
|
|
/** |
46
|
|
|
* @var AbstractSchemaManager |
47
|
|
|
*/ |
48
|
|
|
private $_sm; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var array|null |
52
|
|
|
*/ |
53
|
|
|
private $tables = null; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @var array |
57
|
|
|
*/ |
58
|
|
|
private $classToTableNames = []; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @var array |
62
|
|
|
*/ |
63
|
|
|
private $manyToManyTables = []; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* @var array |
67
|
|
|
*/ |
68
|
|
|
private $classNamesForTables = []; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @var array |
72
|
|
|
*/ |
73
|
|
|
private $fieldNamesForColumns = []; |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* The namespace for the generated entities. |
77
|
|
|
* |
78
|
|
|
* @var string|null |
79
|
|
|
*/ |
80
|
|
|
private $namespace; |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @param AbstractSchemaManager $schemaManager |
84
|
|
|
*/ |
85
|
2 |
|
public function __construct(AbstractSchemaManager $schemaManager) |
86
|
|
|
{ |
87
|
2 |
|
$this->_sm = $schemaManager; |
88
|
2 |
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Set the namespace for the generated entities. |
92
|
|
|
* |
93
|
|
|
* @param string $namespace |
94
|
|
|
* |
95
|
|
|
* @return void |
96
|
|
|
*/ |
97
|
|
|
public function setNamespace($namespace) |
98
|
|
|
{ |
99
|
|
|
$this->namespace = $namespace; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* {@inheritDoc} |
104
|
|
|
*/ |
105
|
|
|
public function isTransient($className) |
106
|
|
|
{ |
107
|
|
|
return true; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* {@inheritDoc} |
112
|
|
|
*/ |
113
|
2 |
|
public function getAllClassNames() |
114
|
|
|
{ |
115
|
2 |
|
$this->reverseEngineerMappingFromDatabase(); |
116
|
|
|
|
117
|
2 |
|
return array_keys($this->classToTableNames); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* Sets class name for a table. |
122
|
|
|
* |
123
|
|
|
* @param string $tableName |
124
|
|
|
* @param string $className |
125
|
|
|
* |
126
|
|
|
* @return void |
127
|
|
|
*/ |
128
|
|
|
public function setClassNameForTable($tableName, $className) |
129
|
|
|
{ |
130
|
|
|
$this->classNamesForTables[$tableName] = $className; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Sets field name for a column on a specific table. |
135
|
|
|
* |
136
|
|
|
* @param string $tableName |
137
|
|
|
* @param string $columnName |
138
|
|
|
* @param string $fieldName |
139
|
|
|
* |
140
|
|
|
* @return void |
141
|
|
|
*/ |
142
|
|
|
public function setFieldNameForColumn($tableName, $columnName, $fieldName) |
143
|
|
|
{ |
144
|
|
|
$this->fieldNamesForColumns[$tableName][$columnName] = $fieldName; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Sets tables manually instead of relying on the reverse engineering capabilities of SchemaManager. |
149
|
|
|
* |
150
|
|
|
* @param array $entityTables |
151
|
|
|
* @param array $manyToManyTables |
152
|
|
|
* |
153
|
|
|
* @return void |
154
|
|
|
*/ |
155
|
2 |
|
public function setTables($entityTables, $manyToManyTables) |
156
|
|
|
{ |
157
|
2 |
|
$this->tables = $this->manyToManyTables = $this->classToTableNames = []; |
158
|
|
|
|
159
|
2 |
|
foreach ($entityTables as $table) { |
160
|
2 |
|
$className = $this->getClassNameForTable($table->getName()); |
161
|
|
|
|
162
|
2 |
|
$this->classToTableNames[$className] = $table->getName(); |
163
|
2 |
|
$this->tables[$table->getName()] = $table; |
164
|
|
|
} |
165
|
|
|
|
166
|
2 |
|
foreach ($manyToManyTables as $table) { |
167
|
1 |
|
$this->manyToManyTables[$table->getName()] = $table; |
168
|
|
|
} |
169
|
2 |
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* {@inheritDoc} |
173
|
|
|
*/ |
174
|
2 |
|
public function loadMetadataForClass($className, ClassMetadata $metadata) |
175
|
|
|
{ |
176
|
2 |
|
$this->reverseEngineerMappingFromDatabase(); |
177
|
|
|
|
178
|
2 |
|
if ( ! isset($this->classToTableNames[$className])) { |
179
|
|
|
throw new \InvalidArgumentException("Unknown class " . $className); |
180
|
|
|
} |
181
|
|
|
|
182
|
2 |
|
$tableName = $this->classToTableNames[$className]; |
183
|
|
|
|
184
|
2 |
|
$metadata->name = $className; |
|
|
|
|
185
|
2 |
|
$metadata->table['name'] = $tableName; |
|
|
|
|
186
|
|
|
|
187
|
2 |
|
$this->buildIndexes($metadata); |
188
|
2 |
|
$this->buildFieldMappings($metadata); |
189
|
2 |
|
$this->buildToOneAssociationMappings($metadata); |
190
|
|
|
|
191
|
2 |
|
foreach ($this->manyToManyTables as $manyTable) { |
192
|
1 |
|
foreach ($manyTable->getForeignKeys() as $foreignKey) { |
193
|
|
|
// foreign key maps to the table of the current entity, many to many association probably exists |
194
|
1 |
|
if ( ! (strtolower($tableName) === strtolower($foreignKey->getForeignTableName()))) { |
195
|
1 |
|
continue; |
196
|
|
|
} |
197
|
|
|
|
198
|
1 |
|
$myFk = $foreignKey; |
199
|
1 |
|
$otherFk = null; |
200
|
|
|
|
201
|
1 |
|
foreach ($manyTable->getForeignKeys() as $foreignKey) { |
|
|
|
|
202
|
1 |
|
if ($foreignKey != $myFk) { |
203
|
|
|
$otherFk = $foreignKey; |
204
|
|
|
break; |
205
|
|
|
} |
206
|
|
|
} |
207
|
|
|
|
208
|
1 |
|
if ( ! $otherFk) { |
209
|
|
|
// the definition of this many to many table does not contain |
210
|
|
|
// enough foreign key information to continue reverse engineering. |
211
|
1 |
|
continue; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
$localColumn = current($myFk->getColumns()); |
215
|
|
|
|
216
|
|
|
$associationMapping = []; |
217
|
|
|
$associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current($otherFk->getColumns()), true); |
218
|
|
|
$associationMapping['targetEntity'] = $this->getClassNameForTable($otherFk->getForeignTableName()); |
219
|
|
|
|
220
|
|
|
if (current($manyTable->getColumns())->getName() == $localColumn) { |
221
|
|
|
$associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true); |
222
|
|
|
$associationMapping['joinTable'] = [ |
223
|
|
|
'name' => strtolower($manyTable->getName()), |
224
|
|
|
'joinColumns' => [], |
225
|
|
|
'inverseJoinColumns' => [], |
226
|
|
|
]; |
227
|
|
|
|
228
|
|
|
$fkCols = $myFk->getForeignColumns(); |
229
|
|
|
$cols = $myFk->getColumns(); |
230
|
|
|
|
231
|
|
|
for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) { |
232
|
|
|
$associationMapping['joinTable']['joinColumns'][] = [ |
233
|
|
|
'name' => $cols[$i], |
234
|
|
|
'referencedColumnName' => $fkCols[$i], |
235
|
|
|
]; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
$fkCols = $otherFk->getForeignColumns(); |
239
|
|
|
$cols = $otherFk->getColumns(); |
240
|
|
|
|
241
|
|
|
for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) { |
242
|
|
|
$associationMapping['joinTable']['inverseJoinColumns'][] = [ |
243
|
|
|
'name' => $cols[$i], |
244
|
|
|
'referencedColumnName' => $fkCols[$i], |
245
|
|
|
]; |
246
|
|
|
} |
247
|
|
|
} else { |
248
|
|
|
$associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true); |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
$metadata->mapManyToMany($associationMapping); |
252
|
|
|
|
253
|
|
|
break; |
254
|
|
|
} |
255
|
|
|
} |
256
|
2 |
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* @return void |
260
|
|
|
* |
261
|
|
|
* @throws \Doctrine\ORM\Mapping\MappingException |
262
|
|
|
*/ |
263
|
2 |
|
private function reverseEngineerMappingFromDatabase() |
264
|
|
|
{ |
265
|
2 |
|
if ($this->tables !== null) { |
266
|
2 |
|
return; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
$tables = []; |
270
|
|
|
|
271
|
|
|
foreach ($this->_sm->listTableNames() as $tableName) { |
272
|
|
|
$tables[$tableName] = $this->_sm->listTableDetails($tableName); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
$this->tables = $this->manyToManyTables = $this->classToTableNames = []; |
276
|
|
|
|
277
|
|
|
foreach ($tables as $tableName => $table) { |
278
|
|
|
$foreignKeys = ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) |
279
|
|
|
? $table->getForeignKeys() |
280
|
|
|
: []; |
281
|
|
|
|
282
|
|
|
$allForeignKeyColumns = []; |
283
|
|
|
|
284
|
|
|
foreach ($foreignKeys as $foreignKey) { |
285
|
|
|
$allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns()); |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
if ( ! $table->hasPrimaryKey()) { |
289
|
|
|
throw new MappingException( |
290
|
|
|
"Table " . $table->getName() . " has no primary key. Doctrine does not ". |
291
|
|
|
"support reverse engineering from tables that don't have a primary key." |
292
|
|
|
); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
$pkColumns = $table->getPrimaryKey()->getColumns(); |
296
|
|
|
|
297
|
|
|
sort($pkColumns); |
298
|
|
|
sort($allForeignKeyColumns); |
299
|
|
|
|
300
|
|
|
if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) { |
301
|
|
|
$this->manyToManyTables[$tableName] = $table; |
302
|
|
|
} else { |
303
|
|
|
// lower-casing is necessary because of Oracle Uppercase Tablenames, |
304
|
|
|
// assumption is lower-case + underscore separated. |
305
|
|
|
$className = $this->getClassNameForTable($tableName); |
306
|
|
|
|
307
|
|
|
$this->tables[$tableName] = $table; |
308
|
|
|
$this->classToTableNames[$className] = $tableName; |
309
|
|
|
} |
310
|
|
|
} |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
/** |
314
|
|
|
* Build indexes from a class metadata. |
315
|
|
|
* |
316
|
|
|
* @param \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata |
317
|
|
|
*/ |
318
|
2 |
|
private function buildIndexes(ClassMetadataInfo $metadata) |
319
|
|
|
{ |
320
|
2 |
|
$tableName = $metadata->table['name']; |
321
|
2 |
|
$indexes = $this->tables[$tableName]->getIndexes(); |
322
|
|
|
|
323
|
2 |
|
foreach ($indexes as $index) { |
324
|
2 |
|
if ($index->isPrimary()) { |
325
|
2 |
|
continue; |
326
|
|
|
} |
327
|
|
|
|
328
|
1 |
|
$indexName = $index->getName(); |
329
|
1 |
|
$indexColumns = $index->getColumns(); |
330
|
1 |
|
$constraintType = $index->isUnique() |
331
|
|
|
? 'uniqueConstraints' |
332
|
1 |
|
: 'indexes'; |
333
|
|
|
|
334
|
1 |
|
$metadata->table[$constraintType][$indexName]['columns'] = $indexColumns; |
335
|
|
|
} |
336
|
2 |
|
} |
337
|
|
|
|
338
|
|
|
/** |
339
|
|
|
* Build field mapping from class metadata. |
340
|
|
|
* |
341
|
|
|
* @param \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata |
342
|
|
|
*/ |
343
|
2 |
|
private function buildFieldMappings(ClassMetadataInfo $metadata) |
344
|
|
|
{ |
345
|
2 |
|
$tableName = $metadata->table['name']; |
346
|
2 |
|
$columns = $this->tables[$tableName]->getColumns(); |
347
|
2 |
|
$primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]); |
348
|
2 |
|
$foreignKeys = $this->getTableForeignKeys($this->tables[$tableName]); |
349
|
2 |
|
$allForeignKeys = []; |
350
|
|
|
|
351
|
2 |
|
foreach ($foreignKeys as $foreignKey) { |
352
|
|
|
$allForeignKeys = array_merge($allForeignKeys, $foreignKey->getLocalColumns()); |
353
|
|
|
} |
354
|
|
|
|
355
|
2 |
|
$ids = []; |
356
|
2 |
|
$fieldMappings = []; |
357
|
|
|
|
358
|
2 |
|
foreach ($columns as $column) { |
359
|
2 |
|
if (in_array($column->getName(), $allForeignKeys)) { |
360
|
|
|
continue; |
361
|
|
|
} |
362
|
|
|
|
363
|
2 |
|
$fieldMapping = $this->buildFieldMapping($tableName, $column); |
364
|
|
|
|
365
|
2 |
|
if ($primaryKeys && in_array($column->getName(), $primaryKeys)) { |
366
|
2 |
|
$fieldMapping['id'] = true; |
367
|
2 |
|
$ids[] = $fieldMapping; |
368
|
|
|
} |
369
|
|
|
|
370
|
2 |
|
$fieldMappings[] = $fieldMapping; |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
// We need to check for the columns here, because we might have associations as id as well. |
374
|
2 |
|
if ($ids && count($primaryKeys) == 1) { |
375
|
2 |
|
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); |
376
|
|
|
} |
377
|
|
|
|
378
|
2 |
|
foreach ($fieldMappings as $fieldMapping) { |
379
|
2 |
|
$metadata->mapField($fieldMapping); |
380
|
|
|
} |
381
|
2 |
|
} |
382
|
|
|
|
383
|
|
|
/** |
384
|
|
|
* Build field mapping from a schema column definition |
385
|
|
|
* |
386
|
|
|
* @param string $tableName |
387
|
|
|
* @param \Doctrine\DBAL\Schema\Column $column |
388
|
|
|
* |
389
|
|
|
* @return array |
390
|
|
|
*/ |
391
|
2 |
|
private function buildFieldMapping($tableName, Column $column) |
392
|
|
|
{ |
393
|
|
|
$fieldMapping = [ |
394
|
2 |
|
'fieldName' => $this->getFieldNameForColumn($tableName, $column->getName(), false), |
395
|
2 |
|
'columnName' => $column->getName(), |
396
|
2 |
|
'type' => $column->getType()->getName(), |
397
|
2 |
|
'nullable' => ( ! $column->getNotnull()), |
398
|
|
|
]; |
399
|
|
|
|
400
|
|
|
// Type specific elements |
401
|
2 |
|
switch ($fieldMapping['type']) { |
402
|
|
|
case Type::TARRAY: |
|
|
|
|
403
|
|
|
case Type::BLOB: |
|
|
|
|
404
|
|
|
case Type::GUID: |
|
|
|
|
405
|
|
|
case Type::JSON_ARRAY: |
|
|
|
|
406
|
|
|
case Type::OBJECT: |
|
|
|
|
407
|
|
|
case Type::SIMPLE_ARRAY: |
|
|
|
|
408
|
|
|
case Type::STRING: |
|
|
|
|
409
|
|
|
case Type::TEXT: |
|
|
|
|
410
|
1 |
|
$fieldMapping['length'] = $column->getLength(); |
411
|
1 |
|
$fieldMapping['options']['fixed'] = $column->getFixed(); |
412
|
1 |
|
break; |
413
|
|
|
|
414
|
|
|
case Type::DECIMAL: |
|
|
|
|
415
|
|
|
case Type::FLOAT: |
|
|
|
|
416
|
|
|
$fieldMapping['precision'] = $column->getPrecision(); |
417
|
|
|
$fieldMapping['scale'] = $column->getScale(); |
418
|
|
|
break; |
419
|
|
|
|
420
|
|
|
case Type::INTEGER: |
|
|
|
|
421
|
|
|
case Type::BIGINT: |
|
|
|
|
422
|
|
|
case Type::SMALLINT: |
|
|
|
|
423
|
2 |
|
$fieldMapping['options']['unsigned'] = $column->getUnsigned(); |
424
|
2 |
|
break; |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
// Comment |
428
|
2 |
|
if (($comment = $column->getComment()) !== null) { |
429
|
|
|
$fieldMapping['options']['comment'] = $comment; |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
// Default |
433
|
2 |
|
if (($default = $column->getDefault()) !== null) { |
434
|
|
|
$fieldMapping['options']['default'] = $default; |
435
|
|
|
} |
436
|
|
|
|
437
|
2 |
|
return $fieldMapping; |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
/** |
441
|
|
|
* Build to one (one to one, many to one) association mapping from class metadata. |
442
|
|
|
* |
443
|
|
|
* @param \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata |
444
|
|
|
*/ |
445
|
2 |
|
private function buildToOneAssociationMappings(ClassMetadataInfo $metadata) |
446
|
|
|
{ |
447
|
2 |
|
$tableName = $metadata->table['name']; |
448
|
2 |
|
$primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]); |
449
|
2 |
|
$foreignKeys = $this->getTableForeignKeys($this->tables[$tableName]); |
450
|
|
|
|
451
|
2 |
|
foreach ($foreignKeys as $foreignKey) { |
452
|
|
|
$foreignTableName = $foreignKey->getForeignTableName(); |
453
|
|
|
$fkColumns = $foreignKey->getColumns(); |
454
|
|
|
$fkForeignColumns = $foreignKey->getForeignColumns(); |
455
|
|
|
$localColumn = current($fkColumns); |
456
|
|
|
$associationMapping = [ |
457
|
|
|
'fieldName' => $this->getFieldNameForColumn($tableName, $localColumn, true), |
458
|
|
|
'targetEntity' => $this->getClassNameForTable($foreignTableName), |
459
|
|
|
]; |
460
|
|
|
|
461
|
|
|
if (isset($metadata->fieldMappings[$associationMapping['fieldName']])) { |
462
|
|
|
$associationMapping['fieldName'] .= '2'; // "foo" => "foo2" |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
if ($primaryKeys && in_array($localColumn, $primaryKeys)) { |
466
|
|
|
$associationMapping['id'] = true; |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
for ($i = 0, $fkColumnsCount = count($fkColumns); $i < $fkColumnsCount; $i++) { |
470
|
|
|
$associationMapping['joinColumns'][] = [ |
471
|
|
|
'name' => $fkColumns[$i], |
472
|
|
|
'referencedColumnName' => $fkForeignColumns[$i], |
473
|
|
|
]; |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
// Here we need to check if $fkColumns are the same as $primaryKeys |
477
|
|
|
if ( ! array_diff($fkColumns, $primaryKeys)) { |
478
|
|
|
$metadata->mapOneToOne($associationMapping); |
479
|
|
|
} else { |
480
|
|
|
$metadata->mapManyToOne($associationMapping); |
481
|
|
|
} |
482
|
|
|
} |
483
|
2 |
|
} |
484
|
|
|
|
485
|
|
|
/** |
486
|
|
|
* Retrieve schema table definition foreign keys. |
487
|
|
|
* |
488
|
|
|
* @param \Doctrine\DBAL\Schema\Table $table |
489
|
|
|
* |
490
|
|
|
* @return array |
491
|
|
|
*/ |
492
|
2 |
|
private function getTableForeignKeys(Table $table) |
493
|
|
|
{ |
494
|
2 |
|
return ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) |
495
|
|
|
? $table->getForeignKeys() |
496
|
2 |
|
: []; |
497
|
|
|
} |
498
|
|
|
|
499
|
|
|
/** |
500
|
|
|
* Retrieve schema table definition primary keys. |
501
|
|
|
* |
502
|
|
|
* @param \Doctrine\DBAL\Schema\Table $table |
503
|
|
|
* |
504
|
|
|
* @return array |
505
|
|
|
*/ |
506
|
2 |
|
private function getTablePrimaryKeys(Table $table) |
507
|
|
|
{ |
508
|
|
|
try { |
509
|
2 |
|
return $table->getPrimaryKey()->getColumns(); |
510
|
|
|
} catch (SchemaException $e) { |
511
|
|
|
// Do nothing |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
return []; |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
/** |
518
|
|
|
* Returns the mapped class name for a table if it exists. Otherwise return "classified" version. |
519
|
|
|
* |
520
|
|
|
* @param string $tableName |
521
|
|
|
* |
522
|
|
|
* @return string |
523
|
|
|
*/ |
524
|
2 |
|
private function getClassNameForTable($tableName) |
525
|
|
|
{ |
526
|
2 |
|
if (isset($this->classNamesForTables[$tableName])) { |
527
|
|
|
return $this->namespace . $this->classNamesForTables[$tableName]; |
528
|
|
|
} |
529
|
|
|
|
530
|
2 |
|
return $this->namespace . Inflector::classify(strtolower($tableName)); |
531
|
|
|
} |
532
|
|
|
|
533
|
|
|
/** |
534
|
|
|
* Return the mapped field name for a column, if it exists. Otherwise return camelized version. |
535
|
|
|
* |
536
|
|
|
* @param string $tableName |
537
|
|
|
* @param string $columnName |
538
|
|
|
* @param boolean $fk Whether the column is a foreignkey or not. |
539
|
|
|
* |
540
|
|
|
* @return string |
541
|
|
|
*/ |
542
|
2 |
|
private function getFieldNameForColumn($tableName, $columnName, $fk = false) |
543
|
|
|
{ |
544
|
2 |
|
if (isset($this->fieldNamesForColumns[$tableName]) && isset($this->fieldNamesForColumns[$tableName][$columnName])) { |
545
|
|
|
return $this->fieldNamesForColumns[$tableName][$columnName]; |
546
|
|
|
} |
547
|
|
|
|
548
|
2 |
|
$columnName = strtolower($columnName); |
549
|
|
|
|
550
|
|
|
// Replace _id if it is a foreignkey column |
551
|
2 |
|
if ($fk) { |
552
|
|
|
$columnName = preg_replace('/_id$/', '', $columnName); |
553
|
|
|
} |
554
|
|
|
|
555
|
2 |
|
return Inflector::camelize($columnName); |
556
|
|
|
} |
557
|
|
|
} |
558
|
|
|
|
This interface has been deprecated. The supplier of the interface has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.