/src/Propel/Generator/Behavior/Versionable/VersionableBehavior.php

https://github.com/fabienpomerol/Propel2 · PHP · 276 lines · 219 code · 34 blank · 23 comment · 25 complexity · c0c6944b1a0143c305a7f74b023a2ca4 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. namespace Propel\Generator\Behavior\Versionable;
  10. use Propel\Generator\Model\Behavior;
  11. use Propel\Generator\Model\ForeignKey;
  12. /**
  13. * Keeps tracks of all the modifications in an ActiveRecord object
  14. *
  15. * @author Francois Zaninotto
  16. * @version $Revision$
  17. * @package propel.generator.behavior.versionable
  18. */
  19. class VersionableBehavior extends Behavior
  20. {
  21. // default parameters value
  22. protected $parameters = array(
  23. 'version_column' => 'version',
  24. 'version_table' => '',
  25. 'log_created_at' => 'false',
  26. 'log_created_by' => 'false',
  27. 'log_comment' => 'false',
  28. 'version_created_at_column' => 'version_created_at',
  29. 'version_created_by_column' => 'version_created_by',
  30. 'version_comment_column' => 'version_comment'
  31. );
  32. protected $versionTable;
  33. protected $objectBuilderModifier;
  34. protected $queryBuilderModifier;
  35. protected $peerBuilderModifier;
  36. protected $tableModificationOrder = 80;
  37. public function modifyDatabase()
  38. {
  39. foreach ($this->getDatabase()->getTables() as $table) {
  40. if ($table->hasBehavior($this->getName())) {
  41. // don't add the same behavior twice
  42. continue;
  43. }
  44. if (property_exists($table, 'isVersionTable')) {
  45. // don't add the behavior to version tables
  46. continue;
  47. }
  48. $b = clone $this;
  49. $table->addBehavior($b);
  50. }
  51. }
  52. public function modifyTable()
  53. {
  54. $this->addVersionColumn();
  55. $this->addLogColumns();
  56. $this->addVersionTable();
  57. $this->addForeignKeyVersionColumns();
  58. }
  59. protected function addVersionColumn()
  60. {
  61. $table = $this->getTable();
  62. // add the version column
  63. if (!$table->hasColumn($this->getParameter('version_column'))) {
  64. $table->addColumn(array(
  65. 'name' => $this->getParameter('version_column'),
  66. 'type' => 'INTEGER',
  67. 'default' => 0
  68. ));
  69. }
  70. }
  71. protected function addLogColumns()
  72. {
  73. $table = $this->getTable();
  74. if ('true' === $this->getParameter('log_created_at') && !$table->hasColumn($this->getParameter('version_created_at_column'))) {
  75. $table->addColumn(array(
  76. 'name' => $this->getParameter('version_created_at_column'),
  77. 'type' => 'TIMESTAMP'
  78. ));
  79. }
  80. if ('true' === $this->getParameter('log_created_by') && !$table->hasColumn($this->getParameter('version_created_by_column'))) {
  81. $table->addColumn(array(
  82. 'name' => $this->getParameter('version_created_by_column'),
  83. 'type' => 'VARCHAR',
  84. 'size' => 100
  85. ));
  86. }
  87. if ('true' === $this->getParameter('log_comment') && !$table->hasColumn($this->getParameter('version_comment_column'))) {
  88. $table->addColumn(array(
  89. 'name' => $this->getParameter('version_comment_column'),
  90. 'type' => 'VARCHAR',
  91. 'size' => 255
  92. ));
  93. }
  94. }
  95. protected function addVersionTable()
  96. {
  97. $table = $this->getTable();
  98. $database = $table->getDatabase();
  99. $versionTableName = $this->getParameter('version_table') ? $this->getParameter('version_table') : ($table->getName() . '_version');
  100. if (!$database->hasTable($versionTableName)) {
  101. // create the version table
  102. $versionTable = $database->addTable(array(
  103. 'name' => $versionTableName,
  104. 'phpName' => $this->getVersionTablePhpName(),
  105. 'package' => $table->getPackage(),
  106. 'schema' => $table->getSchema(),
  107. 'namespace' => $table->getNamespace() ? '\\' . $table->getNamespace() : null,
  108. ));
  109. $versionTable->isVersionTable = true;
  110. // every behavior adding a table should re-execute database behaviors
  111. foreach ($database->getBehaviors() as $behavior) {
  112. $behavior->modifyDatabase();
  113. }
  114. // copy all the columns
  115. foreach ($table->getColumns() as $column) {
  116. $columnInVersionTable = clone $column;
  117. $columnInVersionTable->clearInheritanceList();
  118. if ($columnInVersionTable->hasReferrers()) {
  119. $columnInVersionTable->clearReferrers();
  120. }
  121. if ($columnInVersionTable->isAutoincrement()) {
  122. $columnInVersionTable->setAutoIncrement(false);
  123. }
  124. $versionTable->addColumn($columnInVersionTable);
  125. }
  126. // create the foreign key
  127. $fk = new ForeignKey();
  128. $fk->setForeignTableCommonName($table->getCommonName());
  129. $fk->setForeignSchemaName($table->getSchema());
  130. $fk->setOnDelete('CASCADE');
  131. $fk->setOnUpdate(null);
  132. $tablePKs = $table->getPrimaryKey();
  133. foreach ($versionTable->getPrimaryKey() as $key => $column) {
  134. $fk->addReference($column, $tablePKs[$key]);
  135. }
  136. $versionTable->addForeignKey($fk);
  137. // add the version column to the primary key
  138. $versionColumn = $versionTable->getColumn($this->getParameter('version_column'));
  139. $versionColumn->setNotNull(true);
  140. $versionColumn->setPrimaryKey(true);
  141. $this->versionTable = $versionTable;
  142. } else {
  143. $this->versionTable = $database->getTable($versionTableName);
  144. }
  145. }
  146. public function addForeignKeyVersionColumns()
  147. {
  148. $versionTable = $this->versionTable;
  149. foreach ($this->getVersionableFks() as $fk) {
  150. $fkVersionColumnName = $fk->getLocalColumnName() . '_version';
  151. if (!$versionTable->hasColumn($fkVersionColumnName)) {
  152. $versionTable->addColumn(array(
  153. 'name' => $fkVersionColumnName,
  154. 'type' => 'INTEGER',
  155. 'default' => 0
  156. ));
  157. }
  158. }
  159. foreach ($this->getVersionableReferrers() as $fk) {
  160. $fkTableName = $fk->getTable()->getName();
  161. $fkIdsColumnName = $fkTableName . '_ids';
  162. if (!$versionTable->hasColumn($fkIdsColumnName)) {
  163. $versionTable->addColumn(array(
  164. 'name' => $fkIdsColumnName,
  165. 'type' => 'ARRAY'
  166. ));
  167. }
  168. $fkVersionsColumnName = $fkTableName . '_versions';
  169. if (!$versionTable->hasColumn($fkVersionsColumnName)) {
  170. $versionTable->addColumn(array(
  171. 'name' => $fkVersionsColumnName,
  172. 'type' => 'ARRAY'
  173. ));
  174. }
  175. }
  176. }
  177. public function getVersionTable()
  178. {
  179. return $this->versionTable;
  180. }
  181. public function getVersionTablePhpName()
  182. {
  183. return $this->getTable()->getPhpName() . 'Version';
  184. }
  185. public function getVersionableFks()
  186. {
  187. $versionableFKs = array();
  188. if ($fks = $this->getTable()->getForeignKeys()) {
  189. foreach ($fks as $fk) {
  190. if ($fk->getForeignTable()->hasBehavior($this->getName()) && ! $fk->isComposite()) {
  191. $versionableFKs []= $fk;
  192. }
  193. }
  194. }
  195. return $versionableFKs;
  196. }
  197. public function getVersionableReferrers()
  198. {
  199. $versionableReferrers = array();
  200. if ($fks = $this->getTable()->getReferrers()) {
  201. foreach ($fks as $fk) {
  202. if ($fk->getTable()->hasBehavior($this->getName()) && ! $fk->isComposite()) {
  203. $versionableReferrers []= $fk;
  204. }
  205. }
  206. }
  207. return $versionableReferrers;
  208. }
  209. public function getReferrerIdsColumn(ForeignKey $fk)
  210. {
  211. $fkTableName = $fk->getTable()->getName();
  212. $fkIdsColumnName = $fkTableName . '_ids';
  213. return $this->versionTable->getColumn($fkIdsColumnName);
  214. }
  215. public function getReferrerVersionsColumn(ForeignKey $fk)
  216. {
  217. $fkTableName = $fk->getTable()->getName();
  218. $fkIdsColumnName = $fkTableName . '_versions';
  219. return $this->versionTable->getColumn($fkIdsColumnName);
  220. }
  221. public function getObjectBuilderModifier()
  222. {
  223. if (null === $this->objectBuilderModifier) {
  224. $this->objectBuilderModifier = new VersionableBehaviorObjectBuilderModifier($this);
  225. }
  226. return $this->objectBuilderModifier;
  227. }
  228. public function getQueryBuilderModifier()
  229. {
  230. if (null === $this->queryBuilderModifier) {
  231. $this->queryBuilderModifier = new VersionableBehaviorQueryBuilderModifier($this);
  232. }
  233. return $this->queryBuilderModifier;
  234. }
  235. public function getPeerBuilderModifier()
  236. {
  237. if (null === $this->peerBuilderModifier) {
  238. $this->peerBuilderModifier = new VersionableBehaviorPeerBuilderModifier($this);
  239. }
  240. return $this->peerBuilderModifier;
  241. }
  242. }