ExternalFKSetup.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Setup;
  7. use Magento\Framework\DB\Adapter\AdapterInterface;
  8. /**
  9. * @codeCoverageIgnore
  10. */
  11. class ExternalFKSetup
  12. {
  13. /**
  14. * @var SchemaSetupInterface
  15. */
  16. protected $setup;
  17. /**
  18. * @var string
  19. */
  20. protected $entityTable;
  21. /**
  22. * @var string
  23. */
  24. protected $entityColumn;
  25. /**
  26. * @var string
  27. */
  28. protected $externalTable;
  29. /**
  30. * @var string
  31. */
  32. protected $externalColumn;
  33. /**
  34. * @var string
  35. */
  36. protected $onDelete;
  37. /**
  38. * Install external foreign key
  39. *
  40. * @param SchemaSetupInterface $setup
  41. * @param string $entityTable
  42. * @param string $entityColumn
  43. * @param string $externalTable
  44. * @param string $externalColumn
  45. * @param string $onDelete
  46. * @return void
  47. */
  48. public function install(
  49. SchemaSetupInterface $setup,
  50. $entityTable,
  51. $entityColumn,
  52. $externalTable,
  53. $externalColumn,
  54. $onDelete = AdapterInterface::FK_ACTION_CASCADE
  55. ) {
  56. $this->setup = $setup;
  57. $this->entityTable = $entityTable;
  58. $this->entityColumn = $entityColumn;
  59. $this->externalTable = $externalTable;
  60. $this->externalColumn = $externalColumn;
  61. $this->onDelete = $onDelete;
  62. $this->execute();
  63. }
  64. /**
  65. * Set external foreign key
  66. *
  67. * @return void
  68. */
  69. protected function execute()
  70. {
  71. $entityTableInfo = $this->setup->getConnection()->describeTable(
  72. $this->setup->getTable($this->entityTable)
  73. );
  74. if (!$entityTableInfo[$this->entityColumn]['PRIMARY']) {
  75. $this->dropOldForeignKey();
  76. $this->addForeignKeys();
  77. } else {
  78. $this->addDefaultForeignKey();
  79. }
  80. }
  81. /**
  82. * Get foreign keys for tables and columns
  83. *
  84. * @param string $refTable
  85. * @param string $refColumn
  86. * @param string $targetTable
  87. * @param string $targetColumn
  88. * @return array
  89. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  90. */
  91. protected function getForeignKeys(
  92. $targetTable,
  93. $targetColumn,
  94. $refTable,
  95. $refColumn
  96. ) {
  97. $foreignKeys = $this->setup->getConnection()->getForeignKeys(
  98. $this->setup->getTable($targetTable)
  99. );
  100. $foreignKeys = array_filter(
  101. $foreignKeys,
  102. function ($key) use ($targetColumn, $refTable, $refColumn) {
  103. return $key['COLUMN_NAME'] == $targetColumn
  104. && $key['REF_TABLE_NAME'] == $refTable;
  105. }
  106. );
  107. return $foreignKeys;
  108. }
  109. /**
  110. * Remove foreign key if exists
  111. *
  112. * @param string $targetTable
  113. * @param string $targetColumn
  114. * @param string $refTable
  115. * @param string $refColumn
  116. * @return void
  117. */
  118. protected function clearForeignKey(
  119. $targetTable,
  120. $targetColumn,
  121. $refTable,
  122. $refColumn
  123. ) {
  124. $foreignKeys = $this->getForeignKeys($targetTable, $targetColumn, $refTable, $refColumn);
  125. foreach ($foreignKeys as $foreignKey) {
  126. $this->setup->getConnection()->dropForeignKey(
  127. $foreignKey['TABLE_NAME'],
  128. $foreignKey['FK_NAME']
  129. );
  130. }
  131. }
  132. /**
  133. * Add default foreign key
  134. *
  135. * @return void
  136. */
  137. protected function addDefaultForeignKey()
  138. {
  139. if (!count($this->getForeignKeys(
  140. $this->externalTable,
  141. $this->externalColumn,
  142. $this->entityTable,
  143. $this->entityColumn
  144. ))) {
  145. $this->setup->getConnection()->addForeignKey(
  146. $this->setup->getFkName(
  147. $this->externalTable,
  148. $this->externalColumn,
  149. $this->entityTable,
  150. $this->entityColumn
  151. ),
  152. $this->setup->getTable($this->externalTable),
  153. $this->externalColumn,
  154. $this->setup->getTable($this->entityTable),
  155. $this->entityColumn,
  156. $this->onDelete
  157. );
  158. }
  159. }
  160. /**
  161. * Add foreign keys to entity table
  162. *
  163. * @return void
  164. */
  165. protected function addForeignKeys()
  166. {
  167. $foreignKeys = $this->setup->getConnection()->getForeignKeys(
  168. $this->setup->getTable($this->entityTable)
  169. );
  170. $foreignKeys = array_filter(
  171. $foreignKeys,
  172. function ($key) {
  173. return $key['COLUMN_NAME'] == $this->entityColumn;
  174. }
  175. );
  176. foreach ($foreignKeys as $foreignKeyInfo) {
  177. if (!count($this->getForeignKeys(
  178. $this->externalTable,
  179. $this->externalColumn,
  180. $this->setup->getTablePlaceholder($foreignKeyInfo['REF_TABLE_NAME']),
  181. $foreignKeyInfo['REF_COLUMN_NAME']
  182. ))) {
  183. $this->setup->getConnection()->addForeignKey(
  184. $this->setup->getFkName(
  185. $this->externalTable,
  186. $this->externalColumn,
  187. $this->setup->getTablePlaceholder($foreignKeyInfo['REF_TABLE_NAME']),
  188. $foreignKeyInfo['REF_COLUMN_NAME']
  189. ),
  190. $this->setup->getTable($this->externalTable),
  191. $this->externalColumn,
  192. $foreignKeyInfo['REF_TABLE_NAME'],
  193. $foreignKeyInfo['REF_COLUMN_NAME'],
  194. $this->onDelete
  195. );
  196. }
  197. }
  198. }
  199. /**
  200. * Drop old foreign key
  201. *
  202. * @return void
  203. */
  204. protected function dropOldForeignKey()
  205. {
  206. if (count($this->getForeignKeys(
  207. $this->externalTable,
  208. $this->externalColumn,
  209. $this->entityTable,
  210. $this->entityColumn
  211. ))) {
  212. $this->clearForeignKey(
  213. $this->externalTable,
  214. $this->externalColumn,
  215. $this->entityTable,
  216. $this->entityColumn
  217. );
  218. }
  219. }
  220. }