ForeignKeyConstraint.php 11.5 KB
Newer Older
1
<?php
2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
Benjamin Eberlei's avatar
Benjamin Eberlei committed
16
 * and is licensed under the MIT license. For more information, see
17 18
 * <http://www.doctrine-project.org>.
 */
19 20 21

namespace Doctrine\DBAL\Schema;

22
use Doctrine\DBAL\Platforms\AbstractPlatform;
23

24 25 26 27
/**
 * An abstraction class for a foreign key constraint.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
28
 * @author Steve Müller <st.mueller@dzh-online.de>
29 30 31
 * @link   www.doctrine-project.org
 * @since  2.0
 */
32 33
class ForeignKeyConstraint extends AbstractAsset implements Constraint
{
34
    /**
Benjamin Morel's avatar
Benjamin Morel committed
35 36 37
     * Instance of the referencing table the foreign key constraint is associated with.
     *
     * @var \Doctrine\DBAL\Schema\Table
38
     */
39
    protected $_localTable;
40 41

    /**
42 43 44 45
     * Asset identifier instances of the referencing table column names the foreign key constraint is associated with.
     * array($columnName => Identifier)
     *
     * @var Identifier[]
46
     */
47
    protected $_localColumnNames;
48 49

    /**
50 51 52
     * Table or asset identifier instance of the referenced table name the foreign key constraint is associated with.
     *
     * @var Table|Identifier
53
     */
54
    protected $_foreignTableName;
55 56

    /**
57 58 59 60
     * Asset identifier instances of the referenced table column names the foreign key constraint is associated with.
     * array($columnName => Identifier)
     *
     * @var Identifier[]
61
     */
62
    protected $_foreignColumnNames;
63 64

    /**
65
     * @var array Options associated with the foreign key constraint.
66
     */
67
    protected $_options;
68 69

    /**
70
     * Initializes the foreign key constraint.
71
     *
72 73 74 75 76
     * @param array        $localColumnNames   Names of the referencing table columns.
     * @param Table|string $foreignTableName   Referenced table.
     * @param array        $foreignColumnNames Names of the referenced table columns.
     * @param string|null  $name               Name of the foreign key constraint.
     * @param array        $options            Options associated with the foreign key constraint.
77
     */
78
    public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name = null, array $options = array())
79 80
    {
        $this->_setName($name);
Steve Müller's avatar
Steve Müller committed
81
        $identifierConstructorCallback = function ($column) {
82
            return new Identifier($column);
Steve Müller's avatar
Steve Müller committed
83 84 85 86
        };
        $this->_localColumnNames = $localColumnNames
            ? array_combine($localColumnNames, array_map($identifierConstructorCallback, $localColumnNames))
            : array();
87 88 89 90 91 92 93

        if ($foreignTableName instanceof Table) {
            $this->_foreignTableName = $foreignTableName;
        } else {
            $this->_foreignTableName = new Identifier($foreignTableName);
        }

Steve Müller's avatar
Steve Müller committed
94 95 96
        $this->_foreignColumnNames = $foreignColumnNames
            ? array_combine($foreignColumnNames, array_map($identifierConstructorCallback, $foreignColumnNames))
            : array();
97
        $this->_options = $options;
98 99
    }

100
    /**
101 102 103
     * Returns the name of the referencing table
     * the foreign key constraint is associated with.
     *
104 105 106 107
     * @return string
     */
    public function getLocalTableName()
    {
108
        return $this->_localTable->getName();
109 110 111
    }

    /**
112 113 114
     * Sets the Table instance of the referencing table
     * the foreign key constraint is associated with.
     *
Benjamin Morel's avatar
Benjamin Morel committed
115 116 117
     * @param \Doctrine\DBAL\Schema\Table $table Instance of the referencing table.
     *
     * @return void
118 119 120
     */
    public function setLocalTable(Table $table)
    {
121
        $this->_localTable = $table;
122 123
    }

124 125 126 127 128 129 130 131
    /**
     * @return Table
     */
    public function getLocalTable()
    {
        return $this->_localTable;
    }

132
    /**
133 134 135
     * Returns the names of the referencing table columns
     * the foreign key constraint is associated with.
     *
136 137
     * @return array
     */
138
    public function getLocalColumns()
139
    {
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
        return array_keys($this->_localColumnNames);
    }

    /**
     * Returns the quoted representation of the referencing table column names
     * the foreign key constraint is associated with.
     *
     * But only if they were defined with one or the referencing table column name
     * is a keyword reserved by the platform.
     * Otherwise the plain unquoted value as inserted is returned.
     *
     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation.
     *
     * @return array
     */
    public function getQuotedLocalColumns(AbstractPlatform $platform)
    {
        $columns = array();

        foreach ($this->_localColumnNames as $column) {
            $columns[] = $column->getQuotedName($platform);
        }

        return $columns;
164 165
    }

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
    /**
     * Returns unquoted representation of local table column names for comparison with other FK
     *
     * @return array
     */
    public function getUnquotedLocalColumns()
    {
        return array_map(array($this, 'trimQuotes'), $this->getLocalColumns());
    }

    /**
     * Returns unquoted representation of foreign table column names for comparison with other FK
     *
     * @return array
     */
    public function getUnquotedForeignColumns()
    {
        return array_map(array($this, 'trimQuotes'), $this->getForeignColumns());
    }

186
    /**
Benjamin Morel's avatar
Benjamin Morel committed
187
     * {@inheritdoc}
188
     *
189
     * @see getLocalColumns
190
     */
191 192
    public function getColumns()
    {
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
        return $this->getLocalColumns();
    }

    /**
     * Returns the quoted representation of the referencing table column names
     * the foreign key constraint is associated with.
     *
     * But only if they were defined with one or the referencing table column name
     * is a keyword reserved by the platform.
     * Otherwise the plain unquoted value as inserted is returned.
     *
     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation.
     *
     * @see getQuotedLocalColumns
     *
     * @return array
     */
    public function getQuotedColumns(AbstractPlatform $platform)
    {
        return $this->getQuotedLocalColumns($platform);
213 214
    }

215
    /**
216 217 218
     * Returns the name of the referenced table
     * the foreign key constraint is associated with.
     *
219 220 221 222
     * @return string
     */
    public function getForeignTableName()
    {
223
        return $this->_foreignTableName->getName();
224 225
    }

226
    /**
Benjamin Morel's avatar
Benjamin Morel committed
227
     * Returns the non-schema qualified foreign table name.
228 229 230 231 232
     *
     * @return string
     */
    public function getUnqualifiedForeignTableName()
    {
233
        $parts = explode(".", $this->_foreignTableName->getName());
234

235 236 237
        return strtolower(end($parts));
    }

238
    /**
239 240 241 242 243 244
     * Returns the quoted representation of the referenced table name
     * the foreign key constraint is associated with.
     *
     * But only if it was defined with one or the referenced table name
     * is a keyword reserved by the platform.
     * Otherwise the plain unquoted value as inserted is returned.
245
     *
246
     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation.
247
     *
248 249 250 251
     * @return string
     */
    public function getQuotedForeignTableName(AbstractPlatform $platform)
    {
252
        return $this->_foreignTableName->getQuotedName($platform);
253 254
    }

255
    /**
256 257 258
     * Returns the names of the referenced table columns
     * the foreign key constraint is associated with.
     *
259 260
     * @return array
     */
261
    public function getForeignColumns()
262
    {
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
        return array_keys($this->_foreignColumnNames);
    }

    /**
     * Returns the quoted representation of the referenced table column names
     * the foreign key constraint is associated with.
     *
     * But only if they were defined with one or the referenced table column name
     * is a keyword reserved by the platform.
     * Otherwise the plain unquoted value as inserted is returned.
     *
     * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation.
     *
     * @return array
     */
    public function getQuotedForeignColumns(AbstractPlatform $platform)
    {
        $columns = array();

        foreach ($this->_foreignColumnNames as $column) {
            $columns[] = $column->getQuotedName($platform);
        }

        return $columns;
287 288
    }

289 290 291 292 293 294 295 296
    /**
     * Returns whether or not a given option
     * is associated with the foreign key constraint.
     *
     * @param string $name Name of the option to check.
     *
     * @return boolean
     */
297 298
    public function hasOption($name)
    {
299
        return isset($this->_options[$name]);
300 301
    }

302 303 304 305 306 307 308
    /**
     * Returns an option associated with the foreign key constraint.
     *
     * @param string $name Name of the option the foreign key constraint is associated with.
     *
     * @return mixed
     */
309 310
    public function getOption($name)
    {
311
        return $this->_options[$name];
312
    }
313

314
    /**
315
     * Returns the options associated with the foreign key constraint.
316 317 318 319 320
     *
     * @return array
     */
    public function getOptions()
    {
321
        return $this->_options;
322 323
    }

324
    /**
325 326
     * Returns the referential action for UPDATE operations
     * on the referenced table the foreign key constraint is associated with.
327 328 329 330 331
     *
     * @return string|null
     */
    public function onUpdate()
    {
332
        return $this->onEvent('onUpdate');
333 334 335
    }

    /**
336 337
     * Returns the referential action for DELETE operations
     * on the referenced table the foreign key constraint is associated with.
338 339 340 341 342
     *
     * @return string|null
     */
    public function onDelete()
    {
343
        return $this->onEvent('onDelete');
344 345 346
    }

    /**
347 348 349 350 351
     * Returns the referential action for a given database operation
     * on the referenced table the foreign key constraint is associated with.
     *
     * @param string $event Name of the database operation/event to return the referential action for.
     *
352 353
     * @return string|null
     */
354
    private function onEvent($event)
355
    {
356 357
        if (isset($this->_options[$event])) {
            $onEvent = strtoupper($this->_options[$event]);
358 359

            if ( ! in_array($onEvent, array('NO ACTION', 'RESTRICT'))) {
360 361 362
                return $onEvent;
            }
        }
363

364 365
        return false;
    }
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388

    /**
     * Checks whether this foreign key constraint intersects the given index columns.
     *
     * Returns `true` if at least one of this foreign key's local columns
     * matches one of the given index's columns, `false` otherwise.
     *
     * @param Index $index The index to be checked against.
     *
     * @return boolean
     */
    public function intersectsIndexColumns(Index $index)
    {
        foreach ($index->getColumns() as $indexColumn) {
            foreach ($this->_localColumnNames as $localColumn) {
                if (strtolower($indexColumn) === strtolower($localColumn->getName())) {
                    return true;
                }
            }
        }

        return false;
    }
389
}