Failed Conditions
Push — 3.0.x ( 655b6b...430dce )
by Grégoire
16:57 queued 12:22
created

SchemaDiff::getNewTablesSortedByDependencies()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 23
ccs 13
cts 13
cp 1
rs 9.5555
c 0
b 0
f 0
cc 5
nc 8
nop 0
crap 5
1
<?php
2
3
namespace Doctrine\DBAL\Schema;
4
5
use Doctrine\DBAL\Internal\DependencyOrderCalculator;
6
use Doctrine\DBAL\Platforms\AbstractPlatform;
7
use function array_merge;
8
9
/**
10
 * Schema Diff.
11
 */
12
class SchemaDiff
13
{
14
    /** @var Schema|null */
15
    public $fromSchema;
16
17
    /**
18
     * All added namespaces.
19
     *
20
     * @var string[]
21
     */
22
    public $newNamespaces = [];
23
24
    /**
25
     * All removed namespaces.
26
     *
27
     * @var string[]
28
     */
29
    public $removedNamespaces = [];
30
31
    /**
32
     * All added tables.
33
     *
34
     * @var Table[]
35
     */
36
    public $newTables = [];
37
38
    /**
39
     * All changed tables.
40
     *
41
     * @var TableDiff[]
42
     */
43
    public $changedTables = [];
44
45
    /**
46
     * All removed tables.
47
     *
48
     * @var Table[]
49
     */
50
    public $removedTables = [];
51
52
    /** @var Sequence[] */
53
    public $newSequences = [];
54
55
    /** @var Sequence[] */
56
    public $changedSequences = [];
57
58
    /** @var Sequence[] */
59
    public $removedSequences = [];
60
61
    /** @var ForeignKeyConstraint[] */
62
    public $orphanedForeignKeys = [];
63
64
    /**
65
     * Constructs an SchemaDiff object.
66
     *
67
     * @param Table[]     $newTables
68
     * @param TableDiff[] $changedTables
69
     * @param Table[]     $removedTables
70
     */
71 691
    public function __construct($newTables = [], $changedTables = [], $removedTables = [], ?Schema $fromSchema = null)
72
    {
73 691
        $this->newTables     = $newTables;
74 691
        $this->changedTables = $changedTables;
75 691
        $this->removedTables = $removedTables;
76 691
        $this->fromSchema    = $fromSchema;
77 691
    }
78
79
    /**
80
     * The to save sql mode ensures that the following things don't happen:
81
     *
82
     * 1. Tables are deleted
83
     * 2. Sequences are deleted
84
     * 3. Foreign Keys which reference tables that would otherwise be deleted.
85
     *
86
     * This way it is ensured that assets are deleted which might not be relevant to the metadata schema at all.
87
     *
88
     * @return string[]
89
     */
90 22
    public function toSaveSql(AbstractPlatform $platform)
91
    {
92 22
        return $this->_toSql($platform, true);
93
    }
94
95
    /**
96
     * @return string[]
97
     */
98 97
    public function toSql(AbstractPlatform $platform)
99
    {
100 97
        return $this->_toSql($platform, false);
101
    }
102
103
    /**
104
     * @param bool $saveMode
105
     *
106
     * @return string[]
107
     */
108 119
    protected function _toSql(AbstractPlatform $platform, $saveMode = false)
109
    {
110 119
        $sql = [];
111
112 119
        if ($platform->supportsSchemas()) {
113 58
            foreach ($this->newNamespaces as $newNamespace) {
114 51
                $sql[] = $platform->getCreateSchemaSQL($newNamespace);
115
            }
116
        }
117
118 119
        if ($platform->supportsForeignKeyConstraints() && $saveMode === false) {
119 97
            foreach ($this->orphanedForeignKeys as $orphanedForeignKey) {
120 22
                $sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTable());
121
            }
122
        }
123
124 119
        if ($platform->supportsSequences() === true) {
0 ignored issues
show
introduced by
The condition $platform->supportsSequences() === true is always false.
Loading history...
125 59
            foreach ($this->changedSequences as $sequence) {
126 44
                $sql[] = $platform->getAlterSequenceSQL($sequence);
127
            }
128
129 59
            if ($saveMode === false) {
130 37
                foreach ($this->removedSequences as $sequence) {
131 22
                    $sql[] = $platform->getDropSequenceSQL($sequence);
132
                }
133
            }
134
135 59
            foreach ($this->newSequences as $sequence) {
136 44
                $sql[] = $platform->getCreateSequenceSQL($sequence);
137
            }
138
        }
139
140 119
        $foreignKeySql = [];
141 119
        $createFlags   = AbstractPlatform::CREATE_INDEXES;
142
143 119
        if (! $platform->supportsCreateDropForeignKeyConstraints()) {
144 23
            $createFlags |= AbstractPlatform::CREATE_FOREIGNKEYS;
145
        }
146
147 119
        foreach ($this->getNewTablesSortedByDependencies() as $table) {
148 88
            $sql = array_merge($sql, $platform->getCreateTableSQL($table, $createFlags));
149
150 88
            if (! $platform->supportsCreateDropForeignKeyConstraints()) {
151 23
                continue;
152
            }
153
154 65
            foreach ($table->getForeignKeys() as $foreignKey) {
155 65
                $foreignKeySql[] = $platform->getCreateForeignKeySQL($foreignKey, $table);
156
            }
157
        }
158
159 119
        $sql = array_merge($sql, $foreignKeySql);
160
161 119
        if ($saveMode === false) {
162 97
            foreach ($this->removedTables as $table) {
163 22
                $sql[] = $platform->getDropTableSQL($table);
164
            }
165
        }
166
167 119
        foreach ($this->changedTables as $tableDiff) {
168 68
            $sql = array_merge($sql, $platform->getAlterTableSQL($tableDiff));
169
        }
170
171 119
        return $sql;
172
    }
173
174
    /**
175
     * Sorts tables by dependencies so that they are created in the right order.
176
     *
177
     * This is necessary when one table depends on another while creating foreign key
178
     * constraints directly during CREATE TABLE.
179
     *
180
     * @return array<Table>
181
     */
182 119
    private function getNewTablesSortedByDependencies()
183
    {
184 119
        $calculator = new DependencyOrderCalculator();
185 119
        $newTables  = [];
186
187 119
        foreach ($this->newTables as $table) {
188 88
            $newTables[$table->getName()] = true;
189 88
            $calculator->addNode($table->getName(), $table);
190
        }
191
192 119
        foreach ($this->newTables as $table) {
193 88
            foreach ($table->getForeignKeys() as $foreignKey) {
194 66
                $foreignTableName = $foreignKey->getForeignTableName();
195
196 66
                if (! isset($newTables[$foreignTableName])) {
197 44
                    continue;
198
                }
199
200 22
                $calculator->addDependency($foreignTableName, $table->getName());
201
            }
202
        }
203
204 119
        return $calculator->sort();
205
    }
206
}
207