PageRenderTime 26ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/generator/lib/model/diff/PropelTableComparator.php

https://github.com/1989gaurav/Propel
PHP | 315 lines | 187 code | 33 blank | 95 comment | 22 complexity | 33bad77a2bd35dfe06f8e148117d5650 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the Propel package.
  4. * For the full copyright and license information, please view the LICENSE
  5. * file that was distributed with this source code.
  6. *
  7. * @license MIT License
  8. */
  9. require_once dirname(__FILE__) . '/../Table.php';
  10. require_once dirname(__FILE__) . '/PropelTableDiff.php';
  11. require_once dirname(__FILE__) . '/PropelColumnComparator.php';
  12. require_once dirname(__FILE__) . '/PropelColumnDiff.php';
  13. require_once dirname(__FILE__) . '/PropelIndexComparator.php';
  14. require_once dirname(__FILE__) . '/PropelForeignKeyComparator.php';
  15. /**
  16. * Service class for comparing Table objects
  17. * Heavily inspired by Doctrine2's Migrations
  18. * (see http://github.com/doctrine/dbal/tree/master/lib/Doctrine/DBAL/Schema/)
  19. *
  20. * @package propel.generator.model.diff
  21. */
  22. class PropelTableComparator
  23. {
  24. protected $tableDiff;
  25. public function __construct($tableDiff = null)
  26. {
  27. $this->tableDiff = (null === $tableDiff) ? new PropelTableDiff() : $tableDiff;
  28. }
  29. public function getTableDiff()
  30. {
  31. return $this->tableDiff;
  32. }
  33. /**
  34. * Set the table the comparator starts from
  35. *
  36. * @param Table $fromTable
  37. */
  38. public function setFromTable(Table $fromTable)
  39. {
  40. $this->tableDiff->setFromTable($fromTable);
  41. }
  42. /**
  43. * Get the table the comparator starts from
  44. *
  45. * @return Table
  46. */
  47. public function getFromTable()
  48. {
  49. return $this->tableDiff->getFromTable();
  50. }
  51. /**
  52. * Set the table the comparator goes to
  53. *
  54. * @param Table $toTable
  55. */
  56. public function setToTable(Table $toTable)
  57. {
  58. $this->tableDiff->setToTable($toTable);
  59. }
  60. /**
  61. * Get the table the comparator goes to
  62. *
  63. * @return Table
  64. */
  65. public function getToTable()
  66. {
  67. return $this->tableDiff->getToTable();
  68. }
  69. /**
  70. * Compute and return the difference between two table objects
  71. *
  72. * @param Column $fromTable
  73. * @param Column $toTable
  74. * @param boolean $caseInsensitive Whether the comparison is case insensitive.
  75. * False by default.
  76. *
  77. * @return PropelTableDiff|boolean return false if the two tables are similar
  78. */
  79. public static function computeDiff(Table $fromTable, Table $toTable, $caseInsensitive = false)
  80. {
  81. $tc = new self();
  82. $tc->setFromTable($fromTable);
  83. $tc->setToTable($toTable);
  84. $differences = 0;
  85. $differences += $tc->compareColumns($caseInsensitive);
  86. $differences += $tc->comparePrimaryKeys($caseInsensitive);
  87. $differences += $tc->compareIndices($caseInsensitive);
  88. $differences += $tc->compareForeignKeys($caseInsensitive);
  89. return ($differences > 0) ? $tc->getTableDiff() : false;
  90. }
  91. /**
  92. * Compare the columns of the fromTable and the toTable,
  93. * and modifies the inner tableDiff if necessary.
  94. * Returns the number of differences.
  95. *
  96. * @param boolean $caseInsensitive Whether the comparison is case insensitive.
  97. * False by default.
  98. *
  99. * @return integer The number of column differences
  100. */
  101. public function compareColumns($caseInsensitive = false)
  102. {
  103. $fromTableColumns = $this->getFromTable()->getColumns();
  104. $toTableColumns = $this->getToTable()->getColumns();
  105. $columnDifferences = 0;
  106. // check for new columns in $toTable
  107. foreach ($toTableColumns as $column) {
  108. if (!$this->getFromTable()->hasColumn($column->getName(), $caseInsensitive)) {
  109. $this->tableDiff->addAddedColumn($column->getName(), $column);
  110. $columnDifferences++;
  111. }
  112. }
  113. // check for removed columns in $toTable
  114. foreach ($fromTableColumns as $column) {
  115. if (!$this->getToTable()->hasColumn($column->getName(), $caseInsensitive)) {
  116. $this->tableDiff->addRemovedColumn($column->getName(), $column);
  117. $columnDifferences++;
  118. }
  119. }
  120. // check for column differences
  121. foreach ($fromTableColumns as $fromColumn) {
  122. if ($this->getToTable()->hasColumn($fromColumn->getName(), $caseInsensitive)) {
  123. $toColumn = $this->getToTable()->getColumn($fromColumn->getName(), $caseInsensitive);
  124. $columnDiff = PropelColumnComparator::computeDiff($fromColumn, $toColumn, $caseInsensitive);
  125. if ($columnDiff) {
  126. $this->tableDiff->addModifiedColumn($fromColumn->getName(), $columnDiff);
  127. $columnDifferences++;
  128. }
  129. }
  130. }
  131. // check for column renamings
  132. foreach ($this->tableDiff->getAddedColumns() as $addedColumnName => $addedColumn) {
  133. foreach ($this->tableDiff->getRemovedColumns() as $removedColumnName => $removedColumn) {
  134. if (!PropelColumnComparator::computeDiff($addedColumn, $removedColumn, $caseInsensitive)) {
  135. // no difference except the name, that's probably a renaming
  136. $this->tableDiff->addRenamedColumn($removedColumn, $addedColumn);
  137. $this->tableDiff->removeAddedColumn($addedColumnName);
  138. $this->tableDiff->removeRemovedColumn($removedColumnName);
  139. $columnDifferences--;
  140. }
  141. }
  142. }
  143. return $columnDifferences;
  144. }
  145. /**
  146. * Compare the primary keys of the fromTable and the toTable,
  147. * and modifies the inner tableDiff if necessary.
  148. * Returns the number of differences.
  149. *
  150. * @param boolean $caseInsensitive Whether the comparison is case insensitive.
  151. * False by default.
  152. *
  153. * @return integer The number of primary key differences
  154. */
  155. public function comparePrimaryKeys($caseInsensitive = false)
  156. {
  157. $pkDifferences = 0;
  158. $fromTablePk = $this->getFromTable()->getPrimaryKey();
  159. $toTablePk = $this->getToTable()->getPrimaryKey();
  160. // check for new pk columns in $toTable
  161. foreach ($toTablePk as $column) {
  162. if (!$this->getFromTable()->hasColumn($column->getName(), $caseInsensitive) ||
  163. !$this->getFromTable()->getColumn($column->getName(), $caseInsensitive)->isPrimaryKey()) {
  164. $this->tableDiff->addAddedPkColumn($column->getName(), $column);
  165. $pkDifferences++;
  166. }
  167. }
  168. // check for removed pk columns in $toTable
  169. foreach ($fromTablePk as $column) {
  170. if (!$this->getToTable()->hasColumn($column->getName(), $caseInsensitive) ||
  171. !$this->getToTable()->getColumn($column->getName(), $caseInsensitive)->isPrimaryKey()) {
  172. $this->tableDiff->addRemovedPkColumn($column->getName(), $column);
  173. $pkDifferences++;
  174. }
  175. }
  176. // check for column renamings
  177. foreach ($this->tableDiff->getAddedPkColumns() as $addedColumnName => $addedColumn) {
  178. foreach ($this->tableDiff->getRemovedPkColumns() as $removedColumnName => $removedColumn) {
  179. if (!PropelColumnComparator::computeDiff($addedColumn, $removedColumn, $caseInsensitive)) {
  180. // no difference except the name, that's probably a renaming
  181. $this->tableDiff->addRenamedPkColumn($removedColumn, $addedColumn);
  182. $this->tableDiff->removeAddedPkColumn($addedColumnName);
  183. $this->tableDiff->removeRemovedPkColumn($removedColumnName);
  184. $pkDifferences--;
  185. }
  186. }
  187. }
  188. return $pkDifferences;
  189. }
  190. /**
  191. * Compare the indices and unique indices of the fromTable and the toTable,
  192. * and modifies the inner tableDiff if necessary.
  193. * Returns the number of differences.
  194. *
  195. * @param boolean $caseInsensitive Whether the comparison is case insensitive.
  196. * False by default.
  197. *
  198. * @return integer The number of index differences
  199. */
  200. public function compareIndices($caseInsensitive = false)
  201. {
  202. $indexDifferences = 0;
  203. $fromTableIndices = array_merge($this->getFromTable()->getIndices(), $this->getFromTable()->getUnices());
  204. $toTableIndices = array_merge($this->getToTable()->getIndices(), $this->getToTable()->getUnices());
  205. foreach ($toTableIndices as $toTableIndexPos => $toTableIndex) {
  206. foreach ($fromTableIndices as $fromTableIndexPos => $fromTableIndex) {
  207. if (PropelIndexComparator::computeDiff($fromTableIndex, $toTableIndex, $caseInsensitive) === false) {
  208. unset($fromTableIndices[$fromTableIndexPos]);
  209. unset($toTableIndices[$toTableIndexPos]);
  210. } else {
  211. $test = $caseInsensitive ?
  212. strtolower($fromTableIndex->getName()) == strtolower($toTableIndex->getName()) :
  213. $fromTableIndex->getName() == $toTableIndex->getName();
  214. if ($test) {
  215. // same name, but different columns
  216. $this->tableDiff->addModifiedIndex($fromTableIndex->getName(), $fromTableIndex, $toTableIndex);
  217. unset($fromTableIndices[$fromTableIndexPos]);
  218. unset($toTableIndices[$toTableIndexPos]);
  219. $indexDifferences++;
  220. }
  221. }
  222. }
  223. }
  224. foreach ($fromTableIndices as $fromTableIndexPos => $fromTableIndex) {
  225. $this->tableDiff->addRemovedIndex($fromTableIndex->getName(), $fromTableIndex);
  226. $indexDifferences++;
  227. }
  228. foreach ($toTableIndices as $toTableIndexPos => $toTableIndex) {
  229. $this->tableDiff->addAddedIndex($toTableIndex->getName(), $toTableIndex);
  230. $indexDifferences++;
  231. }
  232. return $indexDifferences;
  233. }
  234. /**
  235. * Compare the foreign keys of the fromTable and the toTable,
  236. * and modifies the inner tableDiff if necessary.
  237. * Returns the number of differences.
  238. *
  239. * @param boolean $caseInsensitive Whether the comparison is case insensitive.
  240. * False by default.
  241. *
  242. * @return integer The number of foreign key differences
  243. */
  244. public function compareForeignKeys($caseInsensitive = false)
  245. {
  246. $fkDifferences = 0;
  247. $fromTableFks = $this->getFromTable()->getForeignKeys();
  248. $toTableFks = $this->getToTable()->getForeignKeys();
  249. foreach ($fromTableFks as $fromTableFkPos => $fromTableFk) {
  250. foreach ($toTableFks as $toTableFkPos => $toTableFk) {
  251. if (PropelForeignKeyComparator::computeDiff($fromTableFk, $toTableFk, $caseInsensitive) === false) {
  252. unset($fromTableFks[$fromTableFkPos]);
  253. unset($toTableFks[$toTableFkPos]);
  254. } else {
  255. $test = $caseInsensitive ?
  256. strtolower($fromTableFk->getName()) == strtolower($toTableFk->getName()) :
  257. $fromTableFk->getName() == $toTableFk->getName();
  258. if ($test) {
  259. // same name, but different columns
  260. $this->tableDiff->addModifiedFk($fromTableFk->getName(), $fromTableFk, $toTableFk);
  261. unset($fromTableFks[$fromTableFkPos]);
  262. unset($toTableFks[$toTableFkPos]);
  263. $fkDifferences++;
  264. }
  265. }
  266. }
  267. }
  268. foreach ($fromTableFks as $fromTableFkPos => $fromTableFk) {
  269. if (!$fromTableFk->isSkipSql() && !in_array($fromTableFk, $toTableFks)) {
  270. $this->tableDiff->addRemovedFk($fromTableFk->getName(), $fromTableFk);
  271. $fkDifferences++;
  272. }
  273. }
  274. foreach ($toTableFks as $toTableFkPos => $toTableFk) {
  275. if (!$toTableFk->isSkipSql() && !in_array($toTableFk, $fromTableFks)) {
  276. $this->tableDiff->addAddedFk($toTableFk->getName(), $toTableFk);
  277. $fkDifferences++;
  278. }
  279. }
  280. return $fkDifferences;
  281. }
  282. }