/classes/Migration.php

https://github.com/OpenBuildings/timestamped-migrations · PHP · 279 lines · 143 code · 26 blank · 110 comment · 9 complexity · d268cbc1becc00167b185859feca8ed3 MD5 · raw file

  1. <?php defined('SYSPATH') OR die('No direct script access.');
  2. /**
  3. * Migration.
  4. */
  5. abstract class Migration
  6. {
  7. private $driver = null;
  8. private $config = null;
  9. private $dry_run = false;
  10. abstract public function up();
  11. abstract public function down();
  12. public function __construct($config = null)
  13. {
  14. $this->config = arr::merge(Kohana::$config->load('migrations')->as_array(), (array) $config);
  15. $this->driver(Migration_Driver::factory(Arr::get($this->config, 'database', 'default')));
  16. }
  17. /**
  18. * Get or set the current driver
  19. */
  20. public function driver(Migration_Driver $driver = NULL)
  21. {
  22. if ($driver !== NULL)
  23. {
  24. $this->driver = $driver;
  25. return $this;
  26. }
  27. return $this->driver;
  28. }
  29. public function log($message)
  30. {
  31. if ($this->config['log'])
  32. {
  33. call_user_func($this->config['log'], $message);
  34. }
  35. else
  36. {
  37. echo $message."\n";
  38. ob_flush();
  39. }
  40. }
  41. public function dry_run($dry_run = NULL)
  42. {
  43. if ($dry_run !== NULL)
  44. {
  45. $this->dry_run = $dry_run;
  46. return $this;
  47. }
  48. return $this->dry_run;
  49. }
  50. protected function run_driver($title, $method, $args, $will_return = FALSE)
  51. {
  52. if ($title)
  53. {
  54. $this->log("-- ".($this->dry_run ? "[dry-run]" : '')."$title");
  55. }
  56. $start = microtime(TRUE);
  57. $return = NULL;
  58. if ( ! $this->dry_run)
  59. {
  60. $return = call_user_func_array(array($this->driver, $method), $args);
  61. }
  62. $end = microtime(TRUE);
  63. if ($title)
  64. {
  65. $this->log(' --> '.number_format($end-$start, 4).'s'.($method == 'execute' ? ', affected rows: '.$this->driver->affected_rows() : ''));
  66. }
  67. return $will_return ? $return : $this;
  68. }
  69. public function execute($sql, $params = NULL, $display = NULL)
  70. {
  71. $args = func_get_args();
  72. if ($display === NULL)
  73. {
  74. $display = str_replace("\n", '↵', $sql);
  75. $display = preg_replace("/[\s]+/", " ", $display);
  76. $display = "execute( ".Text::limit_chars($display, 80)." )";
  77. }
  78. return $this->run_driver($display, __FUNCTION__, $args);
  79. }
  80. public function query($sql, $params = NULL)
  81. {
  82. $args = func_get_args();
  83. $display = str_replace("\n", '↵', $sql);
  84. $display = preg_replace("/[\s]+/", " ", $display);
  85. $display = Text::limit_chars($display, 60);
  86. return $this->run_driver("query( $display )", __FUNCTION__, $args, TRUE);
  87. }
  88. public function quote($value)
  89. {
  90. if (is_array($value))
  91. {
  92. return '('.join(', ', array_map(array($this->driver(), 'quote'), $value)).')';
  93. }
  94. else
  95. {
  96. return $this->driver()->quote($value);
  97. }
  98. }
  99. /**
  100. * Create Table
  101. *
  102. * Creates a new table
  103. *
  104. * $fields:
  105. *
  106. * Associative array containing the name of the field as a key and the
  107. * value could be either a string indicating the type of the field, or an
  108. * array containing the field type at the first position and any optional
  109. * arguments the field might require in the remaining positions.
  110. * Refer to the TYPES function for valid type arguments.
  111. * Refer to the FIELD_ARGUMENTS function for valid optional arguments for a
  112. * field.
  113. *
  114. * @code
  115. *
  116. * create_table (
  117. * 'blog',
  118. * array (
  119. * 'title' => array ( 'string[50]', default => "The blog's title." ),
  120. * 'date' => 'date',
  121. * 'content' => 'text'
  122. * ),
  123. * )
  124. * @endcode
  125. * @param string Name of the table to be created
  126. * @param array
  127. * @param array array of options - 'primary_key', false if not desired, not specified sets to 'id' column. Will be set to auto_increment, serial, etc. , 'if_not_exists' - bool, and all the others will be added as options to the end of the create table clause.
  128. * @param bool if_not_exists
  129. * @return boolean
  130. */
  131. public function create_table($table_name, $fields, $options = NULL)
  132. {
  133. $args = func_get_args();
  134. return $this->run_driver("create_table( $table_name, array(".join(", ", array_keys($fields)).") )", __FUNCTION__, $args);
  135. }
  136. /**
  137. * Drop a table
  138. *
  139. * @param string Name of the table
  140. * @return boolean
  141. */
  142. public function drop_table($table_name)
  143. {
  144. $args = func_get_args();
  145. return $this->run_driver("drop_table( $table_name )", __FUNCTION__, $args);
  146. }
  147. /**
  148. * Change table options (passed directly to alter table)
  149. *
  150. * @param string $table_name
  151. * @param array $options an array of options
  152. * @return boolean
  153. */
  154. public function change_table($table_name, $options)
  155. {
  156. $args = func_get_args();
  157. return $this->run_driver("change_table( $table_name , array(".join(", ", array_keys((array) $options))."))", __FUNCTION__, $args);
  158. }
  159. /**
  160. * Rename a table
  161. *
  162. * @param string Old table name
  163. * @param string New name
  164. * @return boolean
  165. */
  166. public function rename_table($old_name, $new_name)
  167. {
  168. $args = func_get_args();
  169. return $this->run_driver("rename_table( $old_name, $new_name )", __FUNCTION__, $args);
  170. }
  171. /**
  172. * Add a column to a table
  173. *
  174. * @code
  175. * add_column ( "the_table", "the_field", array('string', 'limit[25]', 'not_null') );
  176. * add_coumnn ( "the_table", "int_field", "integer" );
  177. * @endcode
  178. *
  179. * @param string Name of the table
  180. * @param string Name of the column
  181. * @param array Column arguments array
  182. * @return bool
  183. */
  184. public function add_column($table_name, $column_name, $params)
  185. {
  186. $args = func_get_args();
  187. return $this->run_driver("add_column( $table_name, $column_name )", __FUNCTION__, $args);
  188. }
  189. /**
  190. * Rename a column
  191. *
  192. * @param string Name of the table
  193. * @param string Name of the column
  194. * @param string New name
  195. * @return bool
  196. */
  197. public function rename_column($table_name, $column_name, $new_column_name)
  198. {
  199. $args = func_get_args();
  200. return $this->run_driver("rename_column( $table_name, $column_name, $new_column_name )", __FUNCTION__, $args);
  201. }
  202. /**
  203. * Alter a column
  204. *
  205. * @param string Table name
  206. * @param string Columnn ame
  207. * @param array Column arguments
  208. * @return bool
  209. */
  210. public function change_column($table_name, $column_name, $params)
  211. {
  212. $args = func_get_args();
  213. return $this->run_driver("change_column( $table_name, $column_name )", __FUNCTION__, $args);
  214. }
  215. /**
  216. * Remove a column from a table
  217. *
  218. * @param string Name of the table
  219. * @param string Name of the column
  220. * @return bool
  221. */
  222. public function remove_column($table_name, $column_name)
  223. {
  224. $args = func_get_args();
  225. return $this->run_driver("remove_column( $table_name, $column_name )", __FUNCTION__, $args);
  226. }
  227. /**
  228. * Add an index
  229. *
  230. * @param string Name of the table
  231. * @param string Name of the index
  232. * @param string|array Name(s) of the column(s)
  233. * @param string Type of the index (unique/normal/primary)
  234. * @return bool
  235. */
  236. public function add_index($table_name, $index_name, $columns, $index_type = 'normal')
  237. {
  238. $args = func_get_args();
  239. return $this->run_driver("add_index( $table_name, $index_name, array(".join(', ',(array) $columns)."), $index_type )", __FUNCTION__, $args);
  240. }
  241. /**
  242. * Remove an index
  243. *
  244. * @param string Name of the table
  245. * @param string Name of the index
  246. * @return bool
  247. */
  248. public function remove_index($table_name, $index_name)
  249. {
  250. $args = func_get_args();
  251. return $this->run_driver("remove_index( $table_name, $index_name )", __FUNCTION__, $args);
  252. }
  253. }