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
20namespace Doctrine\DBAL\Schema;
21
22use \Doctrine\DBAL\Platforms\AbstractPlatform;
23
24/**
25 * Schema Diff.
26 *
27 * @link      www.doctrine-project.org
28 * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
29 * @license   http://ez.no/licenses/new_bsd New BSD License
30 * @since     2.0
31 * @author    Benjamin Eberlei <kontakt@beberlei.de>
32 */
33class SchemaDiff
34{
35    /**
36     * @var \Doctrine\DBAL\Schema\Schema
37     */
38    public $fromSchema;
39
40    /**
41     * All added namespaces.
42     *
43     * @var string[]
44     */
45    public $newNamespaces = array();
46
47    /**
48     * All removed namespaces.
49     *
50     * @var string[]
51     */
52    public $removedNamespaces = array();
53
54    /**
55     * All added tables.
56     *
57     * @var \Doctrine\DBAL\Schema\Table[]
58     */
59    public $newTables = array();
60
61    /**
62     * All changed tables.
63     *
64     * @var \Doctrine\DBAL\Schema\TableDiff[]
65     */
66    public $changedTables = array();
67
68    /**
69     * All removed tables.
70     *
71     * @var \Doctrine\DBAL\Schema\Table[]
72     */
73    public $removedTables = array();
74
75    /**
76     * @var \Doctrine\DBAL\Schema\Sequence[]
77     */
78    public $newSequences = array();
79
80    /**
81     * @var \Doctrine\DBAL\Schema\Sequence[]
82     */
83    public $changedSequences = array();
84
85    /**
86     * @var \Doctrine\DBAL\Schema\Sequence[]
87     */
88    public $removedSequences = array();
89
90    /**
91     * @var \Doctrine\DBAL\Schema\ForeignKeyConstraint[]
92     */
93    public $orphanedForeignKeys = array();
94
95    /**
96     * Constructs an SchemaDiff object.
97     *
98     * @param \Doctrine\DBAL\Schema\Table[]     $newTables
99     * @param \Doctrine\DBAL\Schema\TableDiff[] $changedTables
100     * @param \Doctrine\DBAL\Schema\Table[]     $removedTables
101     * @param \Doctrine\DBAL\Schema\Schema|null $fromSchema
102     */
103    public function __construct($newTables = array(), $changedTables = array(), $removedTables = array(), Schema $fromSchema = null)
104    {
105        $this->newTables     = $newTables;
106        $this->changedTables = $changedTables;
107        $this->removedTables = $removedTables;
108        $this->fromSchema    = $fromSchema;
109    }
110
111    /**
112     * The to save sql mode ensures that the following things don't happen:
113     *
114     * 1. Tables are deleted
115     * 2. Sequences are deleted
116     * 3. Foreign Keys which reference tables that would otherwise be deleted.
117     *
118     * This way it is ensured that assets are deleted which might not be relevant to the metadata schema at all.
119     *
120     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
121     *
122     * @return array
123     */
124    public function toSaveSql(AbstractPlatform $platform)
125    {
126        return $this->_toSql($platform, true);
127    }
128
129    /**
130     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
131     *
132     * @return array
133     */
134    public function toSql(AbstractPlatform $platform)
135    {
136        return $this->_toSql($platform, false);
137    }
138
139    /**
140     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
141     * @param boolean                                   $saveMode
142     *
143     * @return array
144     */
145    protected function _toSql(AbstractPlatform $platform, $saveMode = false)
146    {
147        $sql = array();
148
149        if ($platform->supportsSchemas()) {
150            foreach ($this->newNamespaces as $newNamespace) {
151                $sql[] = $platform->getCreateSchemaSQL($newNamespace);
152            }
153        }
154
155        if ($platform->supportsForeignKeyConstraints() && $saveMode == false) {
156            foreach ($this->orphanedForeignKeys as $orphanedForeignKey) {
157                $sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTable());
158            }
159        }
160
161        if ($platform->supportsSequences() == true) {
162            foreach ($this->changedSequences as $sequence) {
163                $sql[] = $platform->getAlterSequenceSQL($sequence);
164            }
165
166            if ($saveMode === false) {
167                foreach ($this->removedSequences as $sequence) {
168                    $sql[] = $platform->getDropSequenceSQL($sequence);
169                }
170            }
171
172            foreach ($this->newSequences as $sequence) {
173                $sql[] = $platform->getCreateSequenceSQL($sequence);
174            }
175        }
176
177        $foreignKeySql = array();
178        foreach ($this->newTables as $table) {
179            $sql = array_merge(
180                $sql,
181                $platform->getCreateTableSQL($table, AbstractPlatform::CREATE_INDEXES)
182            );
183
184            if ($platform->supportsForeignKeyConstraints()) {
185                foreach ($table->getForeignKeys() as $foreignKey) {
186                    $foreignKeySql[] = $platform->getCreateForeignKeySQL($foreignKey, $table);
187                }
188            }
189        }
190        $sql = array_merge($sql, $foreignKeySql);
191
192        if ($saveMode === false) {
193            foreach ($this->removedTables as $table) {
194                $sql[] = $platform->getDropTableSQL($table);
195            }
196        }
197
198        foreach ($this->changedTables as $tableDiff) {
199            $sql = array_merge($sql, $platform->getAlterTableSQL($tableDiff));
200        }
201
202        return $sql;
203    }
204}
205