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

https://github.com/esimionato/Propel2 · PHP · 268 lines · 223 code · 22 blank · 23 comment · 28 complexity · 7ae616ab27a4af4f1eb5d216753b8b75 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
  33. $versionTable,
  34. $objectBuilderModifier,
  35. $queryBuilderModifier,
  36. $peerBuilderModifier;
  37. protected $tableModificationOrder = 80;
  38. public function modifyDatabase()
  39. {
  40. foreach ($this->getDatabase()->getTables() as $table) {
  41. if ($table->hasBehavior($this->getName())) {
  42. // don't add the same behavior twice
  43. continue;
  44. }
  45. if (property_exists($table, 'isVersionTable')) {
  46. // don't add the behavior to version tables
  47. continue;
  48. }
  49. $b = clone $this;
  50. $table->addBehavior($b);
  51. }
  52. }
  53. public function modifyTable()
  54. {
  55. $this->addVersionColumn();
  56. $this->addLogColumns();
  57. $this->addVersionTable();
  58. $this->addForeignKeyVersionColumns();
  59. }
  60. protected function addVersionColumn()
  61. {
  62. $table = $this->getTable();
  63. // add the version column
  64. if(!$table->containsColumn($this->getParameter('version_column'))) {
  65. $table->addColumn(array(
  66. 'name' => $this->getParameter('version_column'),
  67. 'type' => 'INTEGER',
  68. 'default' => 0
  69. ));
  70. }
  71. }
  72. protected function addLogColumns()
  73. {
  74. $table = $this->getTable();
  75. if ($this->getParameter('log_created_at') == 'true' && !$table->containsColumn($this->getParameter('version_created_at_column'))) {
  76. $table->addColumn(array(
  77. 'name' => $this->getParameter('version_created_at_column'),
  78. 'type' => 'TIMESTAMP'
  79. ));
  80. }
  81. if ($this->getParameter('log_created_by') == 'true' && !$table->containsColumn($this->getParameter('version_created_by_column'))) {
  82. $table->addColumn(array(
  83. 'name' => $this->getParameter('version_created_by_column'),
  84. 'type' => 'VARCHAR',
  85. 'size' => 100
  86. ));
  87. }
  88. if ($this->getParameter('log_comment') == 'true' && !$table->containsColumn($this->getParameter('version_comment_column'))) {
  89. $table->addColumn(array(
  90. 'name' => $this->getParameter('version_comment_column'),
  91. 'type' => 'VARCHAR',
  92. 'size' => 255
  93. ));
  94. }
  95. }
  96. protected function addVersionTable()
  97. {
  98. $table = $this->getTable();
  99. $database = $table->getDatabase();
  100. $versionTableName = $this->getParameter('version_table') ? $this->getParameter('version_table') : ($table->getName() . '_version');
  101. if (!$database->hasTable($versionTableName)) {
  102. // create the version table
  103. $versionTable = $database->addTable(array(
  104. 'name' => $versionTableName,
  105. 'phpName' => $this->getVersionTablePhpName(),
  106. 'package' => $table->getPackage(),
  107. 'schema' => $table->getSchema(),
  108. 'namespace' => $table->getNamespace() ? '\\' . $table->getNamespace() : null,
  109. ));
  110. $versionTable->isVersionTable = true;
  111. // every behavior adding a table should re-execute database behaviors
  112. foreach ($database->getBehaviors() as $behavior) {
  113. $behavior->modifyDatabase();
  114. }
  115. // copy all the columns
  116. foreach ($table->getColumns() as $column) {
  117. $columnInVersionTable = clone $column;
  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. $table = $this->getTable();
  149. $versionTable = $this->versionTable;
  150. foreach ($this->getVersionableFks() as $fk) {
  151. $fkVersionColumnName = $fk->getLocalColumnName() . '_version';
  152. if (!$versionTable->containsColumn($fkVersionColumnName)) {
  153. $versionTable->addColumn(array(
  154. 'name' => $fkVersionColumnName,
  155. 'type' => 'INTEGER',
  156. 'default' => 0
  157. ));
  158. }
  159. }
  160. foreach ($this->getVersionableReferrers() as $fk) {
  161. $fkTableName = $fk->getTable()->getName();
  162. $fkIdsColumnName = $fkTableName . '_ids';
  163. if (!$versionTable->containsColumn($fkIdsColumnName)) {
  164. $versionTable->addColumn(array(
  165. 'name' => $fkIdsColumnName,
  166. 'type' => 'ARRAY'
  167. ));
  168. }
  169. $fkVersionsColumnName = $fkTableName . '_versions';
  170. if (!$versionTable->containsColumn($fkVersionsColumnName)) {
  171. $versionTable->addColumn(array(
  172. 'name' => $fkVersionsColumnName,
  173. 'type' => 'ARRAY'
  174. ));
  175. }
  176. }
  177. }
  178. public function getVersionTable()
  179. {
  180. return $this->versionTable;
  181. }
  182. public function getVersionTablePhpName()
  183. {
  184. return $this->getTable()->getPhpName() . 'Version';
  185. }
  186. public function getVersionableFks()
  187. {
  188. $versionableFKs = array();
  189. if ($fks = $this->getTable()->getForeignKeys()) {
  190. foreach ($fks as $fk) {
  191. if ($fk->getForeignTable()->hasBehavior('versionable') && ! $fk->isComposite()) {
  192. $versionableFKs []= $fk;
  193. }
  194. }
  195. }
  196. return $versionableFKs;
  197. }
  198. public function getVersionableReferrers()
  199. {
  200. $versionableReferrers = array();
  201. if ($fks = $this->getTable()->getReferrers()) {
  202. foreach ($fks as $fk) {
  203. if ($fk->getTable()->hasBehavior('versionable') && ! $fk->isComposite()) {
  204. $versionableReferrers []= $fk;
  205. }
  206. }
  207. }
  208. return $versionableReferrers;
  209. }
  210. public function getReferrerIdsColumn(ForeignKey $fk)
  211. {
  212. $fkTableName = $fk->getTable()->getName();
  213. $fkIdsColumnName = $fkTableName . '_ids';
  214. return $this->versionTable->getColumn($fkIdsColumnName);
  215. }
  216. public function getReferrerVersionsColumn(ForeignKey $fk)
  217. {
  218. $fkTableName = $fk->getTable()->getName();
  219. $fkIdsColumnName = $fkTableName . '_versions';
  220. return $this->versionTable->getColumn($fkIdsColumnName);
  221. }
  222. public function getObjectBuilderModifier()
  223. {
  224. if (is_null($this->objectBuilderModifier))
  225. {
  226. $this->objectBuilderModifier = new VersionableBehaviorObjectBuilderModifier($this);
  227. }
  228. return $this->objectBuilderModifier;
  229. }
  230. public function getQueryBuilderModifier()
  231. {
  232. if (is_null($this->queryBuilderModifier))
  233. {
  234. $this->queryBuilderModifier = new VersionableBehaviorQueryBuilderModifier($this);
  235. }
  236. return $this->queryBuilderModifier;
  237. }
  238. public function getPeerBuilderModifier()
  239. {
  240. if (is_null($this->peerBuilderModifier))
  241. {
  242. $this->peerBuilderModifier = new VersionableBehaviorPeerBuilderModifier($this);
  243. }
  244. return $this->peerBuilderModifier;
  245. }
  246. }