ForeignKeyConstraint.php 10.4 KB
Newer Older
1 2 3 4
<?php

namespace Doctrine\DBAL\Schema;

5
use Doctrine\DBAL\Platforms\AbstractPlatform;
6 7 8 9 10 11 12 13
use function array_combine;
use function array_keys;
use function array_map;
use function end;
use function explode;
use function in_array;
use function strtolower;
use function strtoupper;
14

15 16 17
/**
 * An abstraction class for a foreign key constraint.
 */
18 19
class ForeignKeyConstraint extends AbstractAsset implements Constraint
{
20
    /**
Benjamin Morel's avatar
Benjamin Morel committed
21 22
     * Instance of the referencing table the foreign key constraint is associated with.
     *
23
     * @var Table
24
     */
25
    protected $_localTable;
26 27

    /**
28 29 30 31
     * Asset identifier instances of the referencing table column names the foreign key constraint is associated with.
     * array($columnName => Identifier)
     *
     * @var Identifier[]
32
     */
33
    protected $_localColumnNames;
34 35

    /**
36 37 38
     * Table or asset identifier instance of the referenced table name the foreign key constraint is associated with.
     *
     * @var Table|Identifier
39
     */
40
    protected $_foreignTableName;
41 42

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

50 51 52 53 54
    /**
     * Options associated with the foreign key constraint.
     *
     * @var mixed[]
     */
55
    protected $_options;
56 57

    /**
58
     * Initializes the foreign key constraint.
59
     *
60
     * @param string[]     $localColumnNames   Names of the referencing table columns.
61
     * @param Table|string $foreignTableName   Referenced table.
62
     * @param string[]     $foreignColumnNames Names of the referenced table columns.
63
     * @param string|null  $name               Name of the foreign key constraint.
64
     * @param mixed[]      $options            Options associated with the foreign key constraint.
65
     */
66
    public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name = null, array $options = [])
67 68
    {
        $this->_setName($name);
69
        $identifierConstructorCallback = static function ($column) {
70
            return new Identifier($column);
Steve Müller's avatar
Steve Müller committed
71
        };
72
        $this->_localColumnNames       = $localColumnNames
Steve Müller's avatar
Steve Müller committed
73
            ? array_combine($localColumnNames, array_map($identifierConstructorCallback, $localColumnNames))
74
            : [];
75 76 77 78 79 80 81

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

Steve Müller's avatar
Steve Müller committed
82 83
        $this->_foreignColumnNames = $foreignColumnNames
            ? array_combine($foreignColumnNames, array_map($identifierConstructorCallback, $foreignColumnNames))
84
            : [];
85
        $this->_options            = $options;
86 87
    }

88
    /**
89 90 91
     * Returns the name of the referencing table
     * the foreign key constraint is associated with.
     *
92 93 94 95
     * @return string
     */
    public function getLocalTableName()
    {
96
        return $this->_localTable->getName();
97 98 99
    }

    /**
100 101 102
     * Sets the Table instance of the referencing table
     * the foreign key constraint is associated with.
     *
103
     * @param Table $table Instance of the referencing table.
Benjamin Morel's avatar
Benjamin Morel committed
104 105
     *
     * @return void
106 107 108
     */
    public function setLocalTable(Table $table)
    {
109
        $this->_localTable = $table;
110 111
    }

112 113 114 115 116 117 118 119
    /**
     * @return Table
     */
    public function getLocalTable()
    {
        return $this->_localTable;
    }

120
    /**
121 122 123
     * Returns the names of the referencing table columns
     * the foreign key constraint is associated with.
     *
124
     * @return string[]
125
     */
126
    public function getLocalColumns()
127
    {
128 129 130 131 132 133 134 135 136 137 138
        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.
     *
139
     * @param AbstractPlatform $platform The platform to use for quotation.
140
     *
141
     * @return string[]
142 143 144
     */
    public function getQuotedLocalColumns(AbstractPlatform $platform)
    {
145
        $columns = [];
146 147 148 149 150 151

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

        return $columns;
152 153
    }

154 155 156
    /**
     * Returns unquoted representation of local table column names for comparison with other FK
     *
157
     * @return string[]
158 159 160
     */
    public function getUnquotedLocalColumns()
    {
161
        return array_map([$this, 'trimQuotes'], $this->getLocalColumns());
162 163 164 165 166
    }

    /**
     * Returns unquoted representation of foreign table column names for comparison with other FK
     *
167
     * @return string[]
168 169 170
     */
    public function getUnquotedForeignColumns()
    {
171
        return array_map([$this, 'trimQuotes'], $this->getForeignColumns());
172 173
    }

174
    /**
Benjamin Morel's avatar
Benjamin Morel committed
175
     * {@inheritdoc}
176
     *
177
     * @see getLocalColumns
178
     */
179 180
    public function getColumns()
    {
181 182 183 184 185 186 187 188 189 190 191 192 193
        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.
     *
     * @see getQuotedLocalColumns
     *
194 195
     * @param AbstractPlatform $platform The platform to use for quotation.
     *
196
     * @return string[]
197 198 199 200
     */
    public function getQuotedColumns(AbstractPlatform $platform)
    {
        return $this->getQuotedLocalColumns($platform);
201 202
    }

203
    /**
204 205 206
     * Returns the name of the referenced table
     * the foreign key constraint is associated with.
     *
207 208 209 210
     * @return string
     */
    public function getForeignTableName()
    {
211
        return $this->_foreignTableName->getName();
212 213
    }

214
    /**
Benjamin Morel's avatar
Benjamin Morel committed
215
     * Returns the non-schema qualified foreign table name.
216 217 218 219 220
     *
     * @return string
     */
    public function getUnqualifiedForeignTableName()
    {
221
        $parts = explode('.', $this->_foreignTableName->getName());
222

223 224 225
        return strtolower(end($parts));
    }

226
    /**
227 228 229 230 231 232
     * 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.
233
     *
234
     * @param AbstractPlatform $platform The platform to use for quotation.
235
     *
236 237 238 239
     * @return string
     */
    public function getQuotedForeignTableName(AbstractPlatform $platform)
    {
240
        return $this->_foreignTableName->getQuotedName($platform);
241 242
    }

243
    /**
244 245 246
     * Returns the names of the referenced table columns
     * the foreign key constraint is associated with.
     *
247
     * @return string[]
248
     */
249
    public function getForeignColumns()
250
    {
251 252 253 254 255 256 257 258 259 260 261
        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.
     *
262
     * @param AbstractPlatform $platform The platform to use for quotation.
263
     *
264
     * @return string[]
265 266 267
     */
    public function getQuotedForeignColumns(AbstractPlatform $platform)
    {
268
        $columns = [];
269 270 271 272 273 274

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

        return $columns;
275 276
    }

277 278 279 280 281 282
    /**
     * Returns whether or not a given option
     * is associated with the foreign key constraint.
     *
     * @param string $name Name of the option to check.
     *
283
     * @return bool
284
     */
285 286
    public function hasOption($name)
    {
287
        return isset($this->_options[$name]);
288 289
    }

290 291 292 293 294 295 296
    /**
     * 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
     */
297 298
    public function getOption($name)
    {
299
        return $this->_options[$name];
300
    }
301

302
    /**
303
     * Returns the options associated with the foreign key constraint.
304
     *
305
     * @return mixed[]
306 307 308
     */
    public function getOptions()
    {
309
        return $this->_options;
310 311
    }

312
    /**
313 314
     * Returns the referential action for UPDATE operations
     * on the referenced table the foreign key constraint is associated with.
315 316 317 318 319
     *
     * @return string|null
     */
    public function onUpdate()
    {
320
        return $this->onEvent('onUpdate');
321 322 323
    }

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

    /**
335 336 337 338 339
     * 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.
     *
340 341
     * @return string|null
     */
342
    private function onEvent($event)
343
    {
344 345
        if (isset($this->_options[$event])) {
            $onEvent = strtoupper($this->_options[$event]);
346

347
            if (! in_array($onEvent, ['NO ACTION', 'RESTRICT'])) {
348 349 350
                return $onEvent;
            }
        }
351

352 353
        return false;
    }
354 355 356 357 358 359 360 361 362

    /**
     * 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.
     *
363
     * @return bool
364 365 366 367 368 369 370 371 372 373 374 375 376
     */
    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;
    }
377
}