ForeignKeyConstraint.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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. namespace Doctrine\DBAL\Schema;
  20. use Doctrine\DBAL\Platforms\AbstractPlatform;
  21. /**
  22. * An abstraction class for a foreign key constraint.
  23. *
  24. * @author Benjamin Eberlei <kontakt@beberlei.de>
  25. * @author Steve Müller <st.mueller@dzh-online.de>
  26. * @link www.doctrine-project.org
  27. * @since 2.0
  28. */
  29. class ForeignKeyConstraint extends AbstractAsset implements Constraint
  30. {
  31. /**
  32. * Instance of the referencing table the foreign key constraint is associated with.
  33. *
  34. * @var \Doctrine\DBAL\Schema\Table
  35. */
  36. protected $_localTable;
  37. /**
  38. * Asset identifier instances of the referencing table column names the foreign key constraint is associated with.
  39. * array($columnName => Identifier)
  40. *
  41. * @var Identifier[]
  42. */
  43. protected $_localColumnNames;
  44. /**
  45. * Table or asset identifier instance of the referenced table name the foreign key constraint is associated with.
  46. *
  47. * @var Table|Identifier
  48. */
  49. protected $_foreignTableName;
  50. /**
  51. * Asset identifier instances of the referenced table column names the foreign key constraint is associated with.
  52. * array($columnName => Identifier)
  53. *
  54. * @var Identifier[]
  55. */
  56. protected $_foreignColumnNames;
  57. /**
  58. * @var array Options associated with the foreign key constraint.
  59. */
  60. protected $_options;
  61. /**
  62. * Initializes the foreign key constraint.
  63. *
  64. * @param array $localColumnNames Names of the referencing table columns.
  65. * @param Table|string $foreignTableName Referenced table.
  66. * @param array $foreignColumnNames Names of the referenced table columns.
  67. * @param string|null $name Name of the foreign key constraint.
  68. * @param array $options Options associated with the foreign key constraint.
  69. */
  70. public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name = null, array $options = array())
  71. {
  72. $this->_setName($name);
  73. $identifierConstructorCallback = function ($column) {
  74. return new Identifier($column);
  75. };
  76. $this->_localColumnNames = $localColumnNames
  77. ? array_combine($localColumnNames, array_map($identifierConstructorCallback, $localColumnNames))
  78. : array();
  79. if ($foreignTableName instanceof Table) {
  80. $this->_foreignTableName = $foreignTableName;
  81. } else {
  82. $this->_foreignTableName = new Identifier($foreignTableName);
  83. }
  84. $this->_foreignColumnNames = $foreignColumnNames
  85. ? array_combine($foreignColumnNames, array_map($identifierConstructorCallback, $foreignColumnNames))
  86. : array();
  87. $this->_options = $options;
  88. }
  89. /**
  90. * Returns the name of the referencing table
  91. * the foreign key constraint is associated with.
  92. *
  93. * @return string
  94. */
  95. public function getLocalTableName()
  96. {
  97. return $this->_localTable->getName();
  98. }
  99. /**
  100. * Sets the Table instance of the referencing table
  101. * the foreign key constraint is associated with.
  102. *
  103. * @param \Doctrine\DBAL\Schema\Table $table Instance of the referencing table.
  104. *
  105. * @return void
  106. */
  107. public function setLocalTable(Table $table)
  108. {
  109. $this->_localTable = $table;
  110. }
  111. /**
  112. * @return Table
  113. */
  114. public function getLocalTable()
  115. {
  116. return $this->_localTable;
  117. }
  118. /**
  119. * Returns the names of the referencing table columns
  120. * the foreign key constraint is associated with.
  121. *
  122. * @return array
  123. */
  124. public function getLocalColumns()
  125. {
  126. return array_keys($this->_localColumnNames);
  127. }
  128. /**
  129. * Returns the quoted representation of the referencing table column names
  130. * the foreign key constraint is associated with.
  131. *
  132. * But only if they were defined with one or the referencing table column name
  133. * is a keyword reserved by the platform.
  134. * Otherwise the plain unquoted value as inserted is returned.
  135. *
  136. * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation.
  137. *
  138. * @return array
  139. */
  140. public function getQuotedLocalColumns(AbstractPlatform $platform)
  141. {
  142. $columns = array();
  143. foreach ($this->_localColumnNames as $column) {
  144. $columns[] = $column->getQuotedName($platform);
  145. }
  146. return $columns;
  147. }
  148. /**
  149. * Returns unquoted representation of local table column names for comparison with other FK
  150. *
  151. * @return array
  152. */
  153. public function getUnquotedLocalColumns()
  154. {
  155. return array_map(array($this, 'trimQuotes'), $this->getLocalColumns());
  156. }
  157. /**
  158. * Returns unquoted representation of foreign table column names for comparison with other FK
  159. *
  160. * @return array
  161. */
  162. public function getUnquotedForeignColumns()
  163. {
  164. return array_map(array($this, 'trimQuotes'), $this->getForeignColumns());
  165. }
  166. /**
  167. * {@inheritdoc}
  168. *
  169. * @see getLocalColumns
  170. */
  171. public function getColumns()
  172. {
  173. return $this->getLocalColumns();
  174. }
  175. /**
  176. * Returns the quoted representation of the referencing table column names
  177. * the foreign key constraint is associated with.
  178. *
  179. * But only if they were defined with one or the referencing table column name
  180. * is a keyword reserved by the platform.
  181. * Otherwise the plain unquoted value as inserted is returned.
  182. *
  183. * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation.
  184. *
  185. * @see getQuotedLocalColumns
  186. *
  187. * @return array
  188. */
  189. public function getQuotedColumns(AbstractPlatform $platform)
  190. {
  191. return $this->getQuotedLocalColumns($platform);
  192. }
  193. /**
  194. * Returns the name of the referenced table
  195. * the foreign key constraint is associated with.
  196. *
  197. * @return string
  198. */
  199. public function getForeignTableName()
  200. {
  201. return $this->_foreignTableName->getName();
  202. }
  203. /**
  204. * Returns the non-schema qualified foreign table name.
  205. *
  206. * @return string
  207. */
  208. public function getUnqualifiedForeignTableName()
  209. {
  210. $parts = explode(".", $this->_foreignTableName->getName());
  211. return strtolower(end($parts));
  212. }
  213. /**
  214. * Returns the quoted representation of the referenced table name
  215. * the foreign key constraint is associated with.
  216. *
  217. * But only if it was defined with one or the referenced table name
  218. * is a keyword reserved by the platform.
  219. * Otherwise the plain unquoted value as inserted is returned.
  220. *
  221. * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation.
  222. *
  223. * @return string
  224. */
  225. public function getQuotedForeignTableName(AbstractPlatform $platform)
  226. {
  227. return $this->_foreignTableName->getQuotedName($platform);
  228. }
  229. /**
  230. * Returns the names of the referenced table columns
  231. * the foreign key constraint is associated with.
  232. *
  233. * @return array
  234. */
  235. public function getForeignColumns()
  236. {
  237. return array_keys($this->_foreignColumnNames);
  238. }
  239. /**
  240. * Returns the quoted representation of the referenced table column names
  241. * the foreign key constraint is associated with.
  242. *
  243. * But only if they were defined with one or the referenced table column name
  244. * is a keyword reserved by the platform.
  245. * Otherwise the plain unquoted value as inserted is returned.
  246. *
  247. * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform The platform to use for quotation.
  248. *
  249. * @return array
  250. */
  251. public function getQuotedForeignColumns(AbstractPlatform $platform)
  252. {
  253. $columns = array();
  254. foreach ($this->_foreignColumnNames as $column) {
  255. $columns[] = $column->getQuotedName($platform);
  256. }
  257. return $columns;
  258. }
  259. /**
  260. * Returns whether or not a given option
  261. * is associated with the foreign key constraint.
  262. *
  263. * @param string $name Name of the option to check.
  264. *
  265. * @return boolean
  266. */
  267. public function hasOption($name)
  268. {
  269. return isset($this->_options[$name]);
  270. }
  271. /**
  272. * Returns an option associated with the foreign key constraint.
  273. *
  274. * @param string $name Name of the option the foreign key constraint is associated with.
  275. *
  276. * @return mixed
  277. */
  278. public function getOption($name)
  279. {
  280. return $this->_options[$name];
  281. }
  282. /**
  283. * Returns the options associated with the foreign key constraint.
  284. *
  285. * @return array
  286. */
  287. public function getOptions()
  288. {
  289. return $this->_options;
  290. }
  291. /**
  292. * Returns the referential action for UPDATE operations
  293. * on the referenced table the foreign key constraint is associated with.
  294. *
  295. * @return string|null
  296. */
  297. public function onUpdate()
  298. {
  299. return $this->onEvent('onUpdate');
  300. }
  301. /**
  302. * Returns the referential action for DELETE operations
  303. * on the referenced table the foreign key constraint is associated with.
  304. *
  305. * @return string|null
  306. */
  307. public function onDelete()
  308. {
  309. return $this->onEvent('onDelete');
  310. }
  311. /**
  312. * Returns the referential action for a given database operation
  313. * on the referenced table the foreign key constraint is associated with.
  314. *
  315. * @param string $event Name of the database operation/event to return the referential action for.
  316. *
  317. * @return string|null
  318. */
  319. private function onEvent($event)
  320. {
  321. if (isset($this->_options[$event])) {
  322. $onEvent = strtoupper($this->_options[$event]);
  323. if ( ! in_array($onEvent, array('NO ACTION', 'RESTRICT'))) {
  324. return $onEvent;
  325. }
  326. }
  327. return false;
  328. }
  329. /**
  330. * Checks whether this foreign key constraint intersects the given index columns.
  331. *
  332. * Returns `true` if at least one of this foreign key's local columns
  333. * matches one of the given index's columns, `false` otherwise.
  334. *
  335. * @param Index $index The index to be checked against.
  336. *
  337. * @return boolean
  338. */
  339. public function intersectsIndexColumns(Index $index)
  340. {
  341. foreach ($index->getColumns() as $indexColumn) {
  342. foreach ($this->_localColumnNames as $localColumn) {
  343. if (strtolower($indexColumn) === strtolower($localColumn->getName())) {
  344. return true;
  345. }
  346. }
  347. }
  348. return false;
  349. }
  350. }