Failed Conditions
Pull Request — master (#7867)
by
unknown
10:32
created

DatabaseDriver   F

Complexity

Total Complexity 77

Size/Duplication

Total Lines 511
Duplicated Lines 0 %

Test Coverage

Coverage 52.53%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 214
c 1
b 0
f 0
dl 0
loc 511
ccs 114
cts 217
cp 0.5253
rs 2.24
wmc 77

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A isTransient() 0 3 1
A setNamespace() 0 3 1
A setFieldNameForColumn() 0 3 1
A setClassNameForTable() 0 3 1
A getAllClassNames() 0 5 1
A setTables() 0 13 3
B buildFieldMappings() 0 41 9
C loadMetadataForClass() 0 100 15
C convertColumnAnnotationToFieldMetadata() 0 54 17
A getFieldNameForColumn() 0 14 3
A getTableForeignKeys() 0 5 2
A getTablePrimaryKeys() 0 9 2
B reverseEngineerMappingFromDatabase() 0 46 9
A buildTable() 0 24 3
A getClassNameForTable() 0 5 1
B buildToOneAssociationMappings() 0 38 7

How to fix   Complexity   

Complex Class

Complex classes like DatabaseDriver often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DatabaseDriver, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Mapping\Driver;
6
7
use Doctrine\Common\Inflector\Inflector;
8
use Doctrine\DBAL\Schema\AbstractSchemaManager;
9
use Doctrine\DBAL\Schema\Column;
10
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
11
use Doctrine\DBAL\Schema\Identifier;
12
use Doctrine\DBAL\Schema\Index;
13
use Doctrine\DBAL\Schema\SchemaException;
14
use Doctrine\DBAL\Schema\Table;
15
use Doctrine\DBAL\Types\Type;
16
use Doctrine\ORM\Mapping;
17
use Doctrine\ORM\Sequencing\Generator;
18
use InvalidArgumentException;
19
use function array_diff;
20
use function array_keys;
21
use function array_merge;
22
use function count;
23
use function current;
24
use function in_array;
25
use function reset;
26
use function sort;
27
use function str_replace;
28
use function strtolower;
29
30
/**
31
 * The DatabaseDriver reverse engineers the mapping metadata from a database.
32
 */
33
class DatabaseDriver implements MappingDriver
34
{
35
    /** @var AbstractSchemaManager */
36
    private $sm;
37
38
    /** @var Table[]|null */
39
    private $tables;
40
41
    /** @var string[] */
42
    private $classToTableNames = [];
43
44
    /** @var Table[] */
45
    private $manyToManyTables = [];
46
47
    /** @var Table[] */
48
    private $classNamesForTables = [];
49
50
    /** @var Table[][] */
51
    private $fieldNamesForColumns = [];
52
53
    /**
54
     * The namespace for the generated entities.
55
     *
56
     * @var string|null
57
     */
58
    private $namespace;
59
60 2
    public function __construct(AbstractSchemaManager $schemaManager)
61
    {
62 2
        $this->sm = $schemaManager;
63 2
    }
64
65
    /**
66
     * Set the namespace for the generated entities.
67
     *
68
     * @param string $namespace
69
     */
70
    public function setNamespace($namespace)
71
    {
72
        $this->namespace = $namespace;
73
    }
74
75
    /**
76
     * {@inheritDoc}
77
     */
78
    public function isTransient($className) : bool
79
    {
80
        return true;
81
    }
82
83
    /**
84
     * {@inheritDoc}
85
     */
86 2
    public function getAllClassNames() : array
87
    {
88 2
        $this->reverseEngineerMappingFromDatabase();
89
90 2
        return array_keys($this->classToTableNames);
91
    }
92
93
    /**
94
     * Sets class name for a table.
95
     *
96
     * @param string $tableName
97
     * @param string $className
98
     */
99
    public function setClassNameForTable($tableName, $className)
100
    {
101
        $this->classNamesForTables[$tableName] = $className;
102
    }
103
104
    /**
105
     * Sets field name for a column on a specific table.
106
     *
107
     * @param string $tableName
108
     * @param string $columnName
109
     * @param string $fieldName
110
     */
111
    public function setFieldNameForColumn($tableName, $columnName, $fieldName)
112
    {
113
        $this->fieldNamesForColumns[$tableName][$columnName] = $fieldName;
114
    }
115
116
    /**
117
     * Sets tables manually instead of relying on the reverse engineering capabilities of SchemaManager.
118
     *
119
     * @param Table[] $entityTables
120
     * @param Table[] $manyToManyTables
121
     */
122 2
    public function setTables($entityTables, $manyToManyTables)
123
    {
124 2
        $this->tables = $this->manyToManyTables = $this->classToTableNames = [];
125
126 2
        foreach ($entityTables as $table) {
127 2
            $className = $this->getClassNameForTable($table->getName());
128
129 2
            $this->classToTableNames[$className] = $table->getName();
130 2
            $this->tables[$table->getName()]     = $table;
131
        }
132
133 2
        foreach ($manyToManyTables as $table) {
134 1
            $this->manyToManyTables[$table->getName()] = $table;
135
        }
136 2
    }
137
138
    /**
139
     * {@inheritDoc}
140
     */
141 2
    public function loadMetadataForClass(
142
        string $className,
143
        ?Mapping\ComponentMetadata $parent,
144
        Mapping\ClassMetadataBuildingContext $metadataBuildingContext
145
    ) : Mapping\ComponentMetadata {
146 2
        $this->reverseEngineerMappingFromDatabase();
147
148 2
        if (! isset($this->classToTableNames[$className])) {
149
            throw new InvalidArgumentException('Unknown class ' . $className);
150
        }
151
152 2
        $metadata = new Mapping\ClassMetadata($className, $parent);
153
154 2
        $this->buildTable($metadata);
155 2
        $this->buildFieldMappings($metadata);
156 2
        $this->buildToOneAssociationMappings($metadata);
157
158 2
        $loweredTableName = strtolower($metadata->getTableName());
159
160 2
        foreach ($this->manyToManyTables as $manyTable) {
161 1
            foreach ($manyTable->getForeignKeys() as $foreignKey) {
162
                // foreign key maps to the table of the current entity, many to many association probably exists
163 1
                if ($loweredTableName !== strtolower($foreignKey->getForeignTableName())) {
164 1
                    continue;
165
                }
166
167 1
                $myFk    = $foreignKey;
168 1
                $otherFk = null;
169
170 1
                foreach ($manyTable->getForeignKeys() as $manyTableForeignKey) {
171 1
                    if ($manyTableForeignKey !== $myFk) {
172
                        $otherFk = $manyTableForeignKey;
173
174
                        break;
175
                    }
176
                }
177
178 1
                if (! $otherFk) {
179
                    // the definition of this many to many table does not contain
180
                    // enough foreign key information to continue reverse engineering.
181 1
                    continue;
182
                }
183
184
                $localColumn = current($myFk->getColumns());
185
186
                $associationMapping                 = [];
187
                $associationMapping['fieldName']    = $this->getFieldNameForColumn($manyTable->getName(), current($otherFk->getColumns()), true);
188
                $associationMapping['targetEntity'] = $this->getClassNameForTable($otherFk->getForeignTableName());
189
190
		if (isset($metadata->fieldMappings[$associationMapping['fieldName']])
0 ignored issues
show
Bug introduced by
The property fieldMappings does not seem to exist on Doctrine\ORM\Mapping\ClassMetadata.
Loading history...
191
                        || isset($metadata->associationMappings[$associationMapping['fieldName']])) {
0 ignored issues
show
Bug introduced by
The property associationMappings does not seem to exist on Doctrine\ORM\Mapping\ClassMetadata.
Loading history...
192
                        $ii=2;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 0 spaces
Loading history...
193
                        while ( isset($metadata->fieldMappings[$associationMapping['fieldName'].(string)$ii]) ||
0 ignored issues
show
Coding Style introduced by
Concat operator must be surrounded by a single space
Loading history...
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
194
                                isset($metadata->associationMappings[$associationMapping['fieldName'].(string)$ii])) {
0 ignored issues
show
Coding Style introduced by
Concat operator must be surrounded by a single space
Loading history...
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
195
                                $ii++;
196
                        }
197
                        $associationMapping['fieldName'] .= (string)$ii; 
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
198
                }
0 ignored issues
show
Coding Style introduced by
Closing brace indented incorrectly; expected 8 spaces, found 16
Loading history...
199
200
                if (current($manyTable->getColumns())->getName() === $localColumn) {
201
                    $associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true);
202
                    $associationMapping['joinTable']  = new Mapping\JoinTableMetadata();
203
204
                    $joinTable = $associationMapping['joinTable'];
205
                    $joinTable->setName(strtolower($manyTable->getName()));
206
207
                    $fkCols = $myFk->getForeignColumns();
208
                    $cols   = $myFk->getColumns();
209
210
                    for ($i = 0, $l = count($cols); $i < $l; $i++) {
211
                        $joinColumn = new Mapping\JoinColumnMetadata();
212
213
                        $joinColumn->setColumnName($cols[$i]);
214
                        $joinColumn->setReferencedColumnName($fkCols[$i]);
215
216
                        $joinTable->addJoinColumn($joinColumn);
217
                    }
218
219
                    $fkCols = $otherFk->getForeignColumns();
220
                    $cols   = $otherFk->getColumns();
221
222
                    for ($i = 0, $l = count($cols); $i < $l; $i++) {
223
                        $joinColumn = new Mapping\JoinColumnMetadata();
224
225
                        $joinColumn->setColumnName($cols[$i]);
226
                        $joinColumn->setReferencedColumnName($fkCols[$i]);
227
228
                        $joinTable->addInverseJoinColumn($joinColumn);
229
                    }
230
                } else {
231
                    $associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true);
232
                }
233
234
                $metadata->addProperty($associationMapping);
0 ignored issues
show
Bug introduced by
$associationMapping of type array is incompatible with the type Doctrine\ORM\Mapping\Property expected by parameter $property of Doctrine\ORM\Mapping\ClassMetadata::addProperty(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

234
                $metadata->addProperty(/** @scrutinizer ignore-type */ $associationMapping);
Loading history...
235
236
                break;
237
            }
238
        }
239
240 2
        return $metadata;
241
    }
242
243
    /**
244
     * @throws Mapping\MappingException
245
     */
246 2
    private function reverseEngineerMappingFromDatabase()
247
    {
248 2
        if ($this->tables !== null) {
249 2
            return;
250
        }
251
252
        $tables = [];
253
254
        foreach ($this->sm->listTableNames() as $tableName) {
255
            $tables[$tableName] = $this->sm->listTableDetails($tableName);
256
        }
257
258
        $this->tables = $this->manyToManyTables = $this->classToTableNames = [];
259
260
        foreach ($tables as $tableName => $table) {
261
            $foreignKeys = $this->sm->getDatabasePlatform()->supportsForeignKeyConstraints()
262
                ? $table->getForeignKeys()
263
                : [];
264
265
            $allForeignKeyColumns = [];
266
267
            foreach ($foreignKeys as $foreignKey) {
268
                $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
269
            }
270
271
            if (! $table->hasPrimaryKey()) {
272
                throw new Mapping\MappingException(
273
                    'Table ' . $table->getName() . ' has no primary key. Doctrine does not ' .
274
                    "support reverse engineering from tables that don't have a primary key."
275
                );
276
            }
277
278
            $pkColumns = $table->getPrimaryKey()->getColumns();
279
280
            sort($pkColumns);
281
            sort($allForeignKeyColumns);
282
283
            if ($pkColumns === $allForeignKeyColumns && count($foreignKeys) === 2) {
284
                $this->manyToManyTables[$tableName] = $table;
285
            } else {
286
                // lower-casing is necessary because of Oracle Uppercase Tablenames,
287
                // assumption is lower-case + underscore separated.
288
                $className = $this->getClassNameForTable($tableName);
289
290
                $this->tables[$tableName]            = $table;
291
                $this->classToTableNames[$className] = $tableName;
292
            }
293
        }
294
    }
295
296
    /**
297
     * Build table from a class metadata.
298
     */
299 2
    private function buildTable(Mapping\ClassMetadata $metadata)
300
    {
301 2
        $tableName     = $this->classToTableNames[$metadata->getClassName()];
302 2
        $indexes       = $this->tables[$tableName]->getIndexes();
303 2
        $tableMetadata = new Mapping\TableMetadata();
304
305 2
        $tableMetadata->setName($this->classToTableNames[$metadata->getClassName()]);
306
307 2
        foreach ($indexes as $index) {
308
            /** @var Index $index */
309 2
            if ($index->isPrimary()) {
310 2
                continue;
311
            }
312
313 1
            $tableMetadata->addIndex([
314 1
                'name'    => $index->getName(),
315 1
                'columns' => $index->getColumns(),
316 1
                'unique'  => $index->isUnique(),
317 1
                'options' => $index->getOptions(),
318 1
                'flags'   => $index->getFlags(),
319
            ]);
320
        }
321
322 2
        $metadata->setTable($tableMetadata);
323 2
    }
324
325
    /**
326
     * Build field mapping from class metadata.
327
     */
328 2
    private function buildFieldMappings(Mapping\ClassMetadata $metadata)
329
    {
330 2
        $tableName      = $metadata->getTableName();
331 2
        $columns        = $this->tables[$tableName]->getColumns();
332 2
        $primaryKeys    = $this->getTablePrimaryKeys($this->tables[$tableName]);
333 2
        $foreignKeys    = $this->getTableForeignKeys($this->tables[$tableName]);
334 2
        $allForeignKeys = [];
335
336 2
        foreach ($foreignKeys as $foreignKey) {
337
            $allForeignKeys = array_merge($allForeignKeys, $foreignKey->getLocalColumns());
338
        }
339
340 2
        $ids = [];
341
342 2
        foreach ($columns as $column) {
343 2
            if (in_array($column->getName(), $allForeignKeys, true)) {
344
                continue;
345
            }
346
347 2
            $fieldName     = $this->getFieldNameForColumn($tableName, $column->getName(), false);
348 2
            $fieldMetadata = $this->convertColumnAnnotationToFieldMetadata($tableName, $column, $fieldName);
0 ignored issues
show
Bug introduced by
It seems like $tableName can also be of type null; however, parameter $tableName of Doctrine\ORM\Mapping\Dri...tationToFieldMetadata() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

348
            $fieldMetadata = $this->convertColumnAnnotationToFieldMetadata(/** @scrutinizer ignore-type */ $tableName, $column, $fieldName);
Loading history...
349
350 2
            if ($primaryKeys && in_array($column->getName(), $primaryKeys, true)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $primaryKeys of type Doctrine\DBAL\Schema\Identifier[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
351 2
                $fieldMetadata->setPrimaryKey(true);
352
353 2
                $ids[] = $fieldMetadata;
354
            }
355
356 2
            $metadata->addProperty($fieldMetadata);
357
        }
358
359
        // We need to check for the columns here, because we might have associations as id as well.
360 2
        if ($ids && count($primaryKeys) === 1) {
361 2
            $fieldMetadata = reset($ids);
362 2
            $generator     = $fieldMetadata->getTypeName() === 'bigint'
363
                ? new Generator\BigIntegerIdentityGenerator()
364 2
                : new Generator\IdentityGenerator();
365
366 2
            $valueGenerator = new Mapping\ValueGeneratorMetadata(Mapping\GeneratorType::IDENTITY, $generator);
367
368 2
            $ids[0]->setValueGenerator($valueGenerator);
369
        }
370 2
    }
371
372
    /**
373
     * Parse the given Column as FieldMetadata
374
     *
375
     * @return Mapping\FieldMetadata
376
     */
377 2
    private function convertColumnAnnotationToFieldMetadata(string $tableName, Column $column, string $fieldName)
378
    {
379 2
        $options       = [];
380 2
        $fieldMetadata = new Mapping\FieldMetadata($fieldName);
381
382 2
        $fieldMetadata->setType($column->getType());
383 2
        $fieldMetadata->setTableName($tableName);
384 2
        $fieldMetadata->setColumnName($column->getName());
385
386
        // Type specific elements
387 2
        switch ($column->getType()->getName()) {
388
            case Type::TARRAY:
389
            case Type::BLOB:
390
            case Type::GUID:
391
            case Type::JSON_ARRAY:
392
            case Type::OBJECT:
393
            case Type::SIMPLE_ARRAY:
394
            case Type::STRING:
395
            case Type::TEXT:
396 1
                if ($column->getLength()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $column->getLength() of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
397
                    $fieldMetadata->setLength($column->getLength());
398
                }
399
400 1
                $options['fixed'] = $column->getFixed();
401 1
                break;
402
403
            case Type::DECIMAL:
404
            case Type::FLOAT:
405
                $fieldMetadata->setScale($column->getScale());
406
                $fieldMetadata->setPrecision($column->getPrecision());
407
                break;
408
409
            case Type::INTEGER:
410
            case Type::BIGINT:
411
            case Type::SMALLINT:
412 2
                $options['unsigned'] = $column->getUnsigned();
413 2
                break;
414
        }
415
416
        // Comment
417 2
        $comment = $column->getComment();
418 2
        if ($comment !== null) {
419
            $options['comment'] = $comment;
420
        }
421
422
        // Default
423 2
        $default = $column->getDefault();
424 2
        if ($default !== null) {
425
            $options['default'] = $default;
426
        }
427
428 2
        $fieldMetadata->setOptions($options);
429
430 2
        return $fieldMetadata;
431
    }
432
433
    /**
434
     * Build to one (one to one, many to one) association mapping from class metadata.
435
     */
436 2
    private function buildToOneAssociationMappings(Mapping\ClassMetadata $metadata)
437
    {
438 2
        $tableName   = $metadata->getTableName();
439 2
        $primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]);
440 2
        $foreignKeys = $this->getTableForeignKeys($this->tables[$tableName]);
441
442 2
        foreach ($foreignKeys as $foreignKey) {
443
            $foreignTableName   = $foreignKey->getForeignTableName();
444
            $fkColumns          = $foreignKey->getColumns();
445
            $fkForeignColumns   = $foreignKey->getForeignColumns();
446
            $localColumn        = current($fkColumns);
447
            $associationMapping = [
448
                'fieldName'    => $this->getFieldNameForColumn($tableName, $localColumn, true),
449
                'targetEntity' => $this->getClassNameForTable($foreignTableName),
450
            ];
451
452
            if ($metadata->getProperty($associationMapping['fieldName'])) {
453
                $associationMapping['fieldName'] .= '2'; // "foo" => "foo2"
454
            }
455
456
            if ($primaryKeys && in_array($localColumn, $primaryKeys, true)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $primaryKeys of type Doctrine\DBAL\Schema\Identifier[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
457
                $associationMapping['id'] = true;
458
            }
459
460
            for ($i = 0, $l = count($fkColumns); $i < $l; $i++) {
461
                $joinColumn = new Mapping\JoinColumnMetadata();
462
463
                $joinColumn->setColumnName($fkColumns[$i]);
464
                $joinColumn->setReferencedColumnName($fkForeignColumns[$i]);
465
466
                $associationMapping['joinColumns'][] = $joinColumn;
467
            }
468
469
            // Here we need to check if $fkColumns are the same as $primaryKeys
470
            if (! array_diff($fkColumns, $primaryKeys)) {
471
                $metadata->addProperty($associationMapping);
0 ignored issues
show
Bug introduced by
$associationMapping of type array<string,string> is incompatible with the type Doctrine\ORM\Mapping\Property expected by parameter $property of Doctrine\ORM\Mapping\ClassMetadata::addProperty(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

471
                $metadata->addProperty(/** @scrutinizer ignore-type */ $associationMapping);
Loading history...
472
            } else {
473
                $metadata->addProperty($associationMapping);
474
            }
475
        }
476 2
    }
477
478
    /**
479
     * Retrieve schema table definition foreign keys.
480
     *
481
     * @return ForeignKeyConstraint[]
482
     */
483 2
    private function getTableForeignKeys(Table $table)
484
    {
485 2
        return $this->sm->getDatabasePlatform()->supportsForeignKeyConstraints()
486
            ? $table->getForeignKeys()
487 2
            : [];
488
    }
489
490
    /**
491
     * Retrieve schema table definition primary keys.
492
     *
493
     * @return Identifier[]
494
     */
495 2
    private function getTablePrimaryKeys(Table $table)
496
    {
497
        try {
498 2
            return $table->getPrimaryKey()->getColumns();
499
        } catch (SchemaException $e) {
500
            // Do nothing
501
        }
502
503
        return [];
504
    }
505
506
    /**
507
     * Returns the mapped class name for a table if it exists. Otherwise return "classified" version.
508
     *
509
     * @param string $tableName
510
     *
511
     * @return string
512
     */
513 2
    private function getClassNameForTable($tableName)
514
    {
515 2
        return $this->namespace . (
516 2
            $this->classNamesForTables[$tableName]
0 ignored issues
show
Bug introduced by
Are you sure $this->classNamesForTabl...strtolower($tableName)) of type Doctrine\DBAL\Schema\Table|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

516
            /** @scrutinizer ignore-type */ $this->classNamesForTables[$tableName]
Loading history...
517 2
                ?? Inflector::classify(strtolower($tableName))
518
        );
519
    }
520
521
    /**
522
     * Return the mapped field name for a column, if it exists. Otherwise return camelized version.
523
     *
524
     * @param string $tableName
525
     * @param string $columnName
526
     * @param bool   $fk         Whether the column is a foreignkey or not.
527
     *
528
     * @return string
529
     */
530 2
    private function getFieldNameForColumn($tableName, $columnName, $fk = false)
531
    {
532 2
        if (isset($this->fieldNamesForColumns[$tableName], $this->fieldNamesForColumns[$tableName][$columnName])) {
533
            return $this->fieldNamesForColumns[$tableName][$columnName];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->fieldNames...tableName][$columnName] returns the type Doctrine\DBAL\Schema\Table which is incompatible with the documented return type string.
Loading history...
534
        }
535
536 2
        $columnName = strtolower($columnName);
537
538
        // Replace _id if it is a foreignkey column
539 2
        if ($fk) {
540
            $columnName = str_replace('_id', '', $columnName);
541
        }
542
543 2
        return Inflector::camelize($columnName);
544
    }
545
}
546