SchemaNormalizer   A
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 94
c 1
b 0
f 0
dl 0
loc 164
rs 9.44
wmc 37

6 Methods

Rating   Name   Duplication   Size   Complexity  
A normalizeForeignReference() 0 18 4
A normalizeIndex() 0 19 5
A normalize() 0 15 3
B normalizeTable() 0 33 8
A normalizeForeignKeyConstraint() 0 14 3
F normalizeColumn() 0 46 14
1
<?php
2
3
namespace TheCodingMachine\TDBM\SchemaVersionControl;
4
5
use Doctrine\DBAL\Schema\Column;
6
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
7
use Doctrine\DBAL\Schema\Index;
8
use Doctrine\DBAL\Schema\Schema;
9
use Doctrine\DBAL\Schema\SchemaConfig;
10
use Doctrine\DBAL\Schema\Table;
11
12
/**
13
 * Database schema normalizer.
14
 *
15
 * Given an instance of Schema, it will construct a deep associative array to describe it. Such an array will then be
16
 * easy to serialize.
17
 */
18
class SchemaNormalizer
19
{
20
    protected Schema $schema;
21
    protected SchemaConfig $schemaConfig;
22
23
    /**
24
     * Normalize a Schema object into an array descriptor
25
     * @return array
26
     */
27
    public function normalize(Schema $schema, SchemaConfig $schemaConfig): array
28
    {
29
        $this->schema = $schema;
30
        $this->schemaConfig = $schemaConfig;
31
        $schemaDesc = [];
32
        if (!empty($this->schemaConfig->getDefaultTableOptions())) {
33
            $schemaDesc['default_table_options'] = $this->schemaConfig->getDefaultTableOptions();
34
        }
35
        $schemaDesc['tables'] = [];
36
        foreach ($schema->getTables() as $table) {
37
            $schemaDesc['tables'][$table->getName()] = $this->normalizeTable($table);
38
        }
39
        ksort($schemaDesc['tables']);
40
41
        return $schemaDesc;
42
    }
43
44
    protected function normalizeTable(Table $table)
45
    {
46
        $tableDesc = [];
47
48
        $primaryKey = $table->getPrimaryKey();
49
        if ($primaryKey) {
50
            $pk_columns = $primaryKey->getUnquotedColumns();
51
        } else {
52
            $pk_columns = [];
53
        }
54
55
        if ($table->hasOption('comment') && $table->getOption('comment')) {
56
            $tableDesc['comment'] = $table->getOption('comment');
57
        }
58
59
        // list columns
60
        foreach ($table->getColumns() as $columnName => $column) {
61
            $tableDesc['columns'][$column->getName()] = $this->normalizeColumn($column, in_array($column->getName(), $pk_columns));
62
        }
63
64
        // list indexes
65
        foreach ($table->getIndexes() as $index) {
66
            if (!$index->isPrimary()) {
67
                $tableDesc['indexes'][$index->getName()] = $this->normalizeIndex($index);
68
            }
69
        }
70
71
        // list foreign keys
72
        foreach ($table->getForeignKeys() as $foreignKey) {
73
            $tableDesc['foreign_keys'][$foreignKey->getName()] = $this->normalizeForeignKeyConstraint($foreignKey);
74
        }
75
76
        return $tableDesc;
77
    }
78
79
    protected function normalizeColumn(Column $column, bool $isPrimaryKey)
80
    {
81
        $columnDesc = [];
82
        if ($isPrimaryKey) {
83
            $columnDesc['primary_key'] = $isPrimaryKey;
84
        }
85
        $columnDesc['type'] = $column->getType()->getName();
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Types\Type::getName() has been deprecated: this method will be removed in Doctrine DBAL 4.0, use {@see TypeRegistry::lookupName()} instead. ( Ignorable by Annotation )

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

85
        $columnDesc['type'] = /** @scrutinizer ignore-deprecated */ $column->getType()->getName();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
86
        if ($column->getUnsigned()) {
87
            $columnDesc['unsigned'] = $column->getUnsigned();
88
        }
89
        if ($column->getFixed()) {
90
            $columnDesc['fixed'] = $column->getFixed();
91
        }
92
        if ($column->getLength() !== null) {
93
            $columnDesc['length'] = $column->getLength();
94
        }
95
        if ($column->getPrecision() !== 10) {
96
            $columnDesc['precision'] = $column->getPrecision();
97
        }
98
        if ($column->getScale() !== 0) {
99
            $columnDesc['scale'] = $column->getScale();
100
        }
101
        if ($column->getNotnull()) {
102
            $columnDesc['not_null'] = $column->getNotnull();
103
        }
104
        if ($column->getDefault() !== null) {
105
            $columnDesc['default'] = $column->getDefault();
106
        }
107
        if ($column->getAutoincrement()) {
108
            $columnDesc['auto_increment'] = $column->getAutoincrement();
109
        }
110
        if ($column->getComment() !== null) {
111
            $columnDesc['comment'] = $column->getComment();
112
        }
113
        if (!empty($column->getPlatformOptions())) {
114
            $custom = array_diff_assoc($column->getPlatformOptions(), $this->schemaConfig->getDefaultTableOptions());
115
            if (!empty($custom)) {
116
                $columnDesc['custom'] = $custom;
117
            }
118
        }
119
120
        if (count($columnDesc) > 1) {
121
            return $columnDesc;
122
        }
123
124
        return $columnDesc['type'];
125
    }
126
127
    protected function normalizeForeignKeyConstraint(ForeignKeyConstraint $foreignKeyConstraint)
128
    {
129
        $constraintDesc = [];
130
        if (count($foreignKeyConstraint->getLocalColumns()) > 1) {
131
            $constraintDesc['columns'] = $foreignKeyConstraint->getLocalColumns();
132
        } else {
133
            $constraintDesc['column'] = $foreignKeyConstraint->getLocalColumns()[0];
134
        }
135
136
        $constraintDesc['references'] = $this->normalizeForeignReference($foreignKeyConstraint);
137
        if (!empty($foreignKeyConstraint->getOptions())) {
138
            $constraintDesc = array_merge($constraintDesc, $foreignKeyConstraint->getOptions());
139
        }
140
        return $constraintDesc;
141
    }
142
143
    protected function normalizeForeignReference(ForeignKeyConstraint $foreignKeyConstraint)
144
    {
145
        $referenceDesc = [];
146
        $foreignTableName = $foreignKeyConstraint->getForeignTableName();
147
        $foreignTable = $this->schema->getTable($foreignTableName);
148
        $foreignPrimaryKey = $foreignTable->getPrimaryKey();
149
        if ($foreignPrimaryKey && $foreignPrimaryKey->getColumns() == $foreignKeyConstraint->getForeignColumns()) {
150
            $referenceDesc = $foreignKeyConstraint->getForeignTableName();
151
        } else {
152
            $referenceDesc['table'] = $foreignKeyConstraint->getForeignTableName();
153
            $fkColumns = $foreignKeyConstraint->getForeignColumns();
154
            if (count($fkColumns) > 1) {
155
                $referenceDesc['columns'] = $fkColumns;
156
            } else {
157
                $referenceDesc['column'] = $fkColumns[0];
158
            }
159
        }
160
        return $referenceDesc;
161
    }
162
163
    protected function normalizeIndex(Index $index)
164
    {
165
        $indexDesc = [];
166
        $columns = $index->getColumns();
167
        if (count($columns) > 1) {
168
            $indexDesc['columns'] = $index->getColumns();
169
        } else {
170
            $indexDesc['column'] = $index->getColumns()[0];
171
        }
172
        if ($index->isUnique()) {
173
            $indexDesc['unique'] = $index->isUnique();
174
        }
175
        if ($index->isPrimary()) {
176
            $indexDesc['primary'] = $index->isPrimary();
177
        }
178
        if (!empty($index->getOptions())) {
179
            $indexDesc = array_merge($indexDesc, $index->getOptions());
180
        }
181
        return $indexDesc;
182
    }
183
}
184