PageRenderTime 882ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/phpBB/phpbb/db/migration/schema_generator.php

https://github.com/Jipem/phpbb
PHP | 235 lines | 175 code | 21 blank | 39 comment | 25 complexity | 78dac84855250060a46ac7ab75afe675 MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. *
  4. * This file is part of the phpBB Forum Software package.
  5. *
  6. * @copyright (c) phpBB Limited <https://www.phpbb.com>
  7. * @license GNU General Public License, version 2 (GPL-2.0)
  8. *
  9. * For full copyright and license information, please see
  10. * the docs/CREDITS.txt file.
  11. *
  12. */
  13. namespace phpbb\db\migration;
  14. /**
  15. * The schema generator generates the schema based on the existing migrations
  16. */
  17. class schema_generator
  18. {
  19. /** @var \phpbb\config\config */
  20. protected $config;
  21. /** @var \phpbb\db\driver\driver_interface */
  22. protected $db;
  23. /** @var \phpbb\db\tools */
  24. protected $db_tools;
  25. /** @var array */
  26. protected $class_names;
  27. /** @var string */
  28. protected $table_prefix;
  29. /** @var string */
  30. protected $phpbb_root_path;
  31. /** @var string */
  32. protected $php_ext;
  33. /** @var array */
  34. protected $tables;
  35. /** @var array */
  36. protected $dependencies = array();
  37. /**
  38. * Constructor
  39. */
  40. public function __construct(array $class_names, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix)
  41. {
  42. $this->config = $config;
  43. $this->db = $db;
  44. $this->db_tools = $db_tools;
  45. $this->class_names = $class_names;
  46. $this->phpbb_root_path = $phpbb_root_path;
  47. $this->php_ext = $php_ext;
  48. $this->table_prefix = $table_prefix;
  49. }
  50. /**
  51. * Loads all migrations and their application state from the database.
  52. *
  53. * @return array
  54. */
  55. public function get_schema()
  56. {
  57. if (!empty($this->tables))
  58. {
  59. return $this->tables;
  60. }
  61. $migrations = $this->class_names;
  62. $tree = array();
  63. $check_dependencies = true;
  64. while (!empty($migrations))
  65. {
  66. foreach ($migrations as $migration_class)
  67. {
  68. $open_dependencies = array_diff($migration_class::depends_on(), $tree);
  69. if (empty($open_dependencies))
  70. {
  71. $migration = new $migration_class($this->config, $this->db, $this->db_tools, $this->phpbb_root_path, $this->php_ext, $this->table_prefix);
  72. $tree[] = $migration_class;
  73. $migration_key = array_search($migration_class, $migrations);
  74. foreach ($migration->update_schema() as $change_type => $data)
  75. {
  76. if ($change_type === 'add_tables')
  77. {
  78. foreach ($data as $table => $table_data)
  79. {
  80. $this->tables[$table] = $table_data;
  81. }
  82. }
  83. else if ($change_type === 'drop_tables')
  84. {
  85. foreach ($data as $table)
  86. {
  87. unset($this->tables[$table]);
  88. }
  89. }
  90. else if ($change_type === 'add_columns')
  91. {
  92. foreach ($data as $table => $add_columns)
  93. {
  94. foreach ($add_columns as $column => $column_data)
  95. {
  96. if (isset($column_data['after']))
  97. {
  98. $columns = $this->tables[$table]['COLUMNS'];
  99. $offset = array_search($column_data['after'], array_keys($columns));
  100. unset($column_data['after']);
  101. if ($offset === false)
  102. {
  103. $this->tables[$table]['COLUMNS'][$column] = array_values($column_data);
  104. }
  105. else
  106. {
  107. $this->tables[$table]['COLUMNS'] = array_merge(array_slice($columns, 0, $offset + 1, true), array($column => array_values($column_data)), array_slice($columns, $offset));
  108. }
  109. }
  110. else
  111. {
  112. $this->tables[$table]['COLUMNS'][$column] = $column_data;
  113. }
  114. }
  115. }
  116. }
  117. else if ($change_type === 'change_columns')
  118. {
  119. foreach ($data as $table => $change_columns)
  120. {
  121. foreach ($change_columns as $column => $column_data)
  122. {
  123. $this->tables[$table]['COLUMNS'][$column] = $column_data;
  124. }
  125. }
  126. }
  127. else if ($change_type === 'drop_columns')
  128. {
  129. foreach ($data as $table => $drop_columns)
  130. {
  131. if (is_array($drop_columns))
  132. {
  133. foreach ($drop_columns as $column)
  134. {
  135. unset($this->tables[$table]['COLUMNS'][$column]);
  136. }
  137. }
  138. else
  139. {
  140. unset($this->tables[$table]['COLUMNS'][$drop_columns]);
  141. }
  142. }
  143. }
  144. else if ($change_type === 'add_unique_index')
  145. {
  146. foreach ($data as $table => $add_index)
  147. {
  148. foreach ($add_index as $key => $index_data)
  149. {
  150. $this->tables[$table]['KEYS'][$key] = array('UNIQUE', $index_data);
  151. }
  152. }
  153. }
  154. else if ($change_type === 'add_index')
  155. {
  156. foreach ($data as $table => $add_index)
  157. {
  158. foreach ($add_index as $key => $index_data)
  159. {
  160. $this->tables[$table]['KEYS'][$key] = array('INDEX', $index_data);
  161. }
  162. }
  163. }
  164. else if ($change_type === 'drop_keys')
  165. {
  166. foreach ($data as $table => $drop_keys)
  167. {
  168. foreach ($drop_keys as $key)
  169. {
  170. unset($this->tables[$table]['KEYS'][$key]);
  171. }
  172. }
  173. }
  174. else
  175. {
  176. var_dump($change_type);
  177. }
  178. }
  179. unset($migrations[$migration_key]);
  180. }
  181. else if ($check_dependencies)
  182. {
  183. $this->dependencies = array_merge($this->dependencies, $open_dependencies);
  184. }
  185. }
  186. // Only run this check after the first run
  187. if ($check_dependencies)
  188. {
  189. $this->check_dependencies();
  190. $check_dependencies = false;
  191. }
  192. }
  193. ksort($this->tables);
  194. return $this->tables;
  195. }
  196. /**
  197. * Check if one of the migrations files' dependencies can't be resolved
  198. * by the supplied list of migrations
  199. *
  200. * @throws \UnexpectedValueException If a dependency can't be resolved
  201. */
  202. protected function check_dependencies()
  203. {
  204. // Strip duplicate values from array
  205. $this->dependencies = array_unique($this->dependencies);
  206. foreach ($this->dependencies as $dependency)
  207. {
  208. if (!in_array($dependency, $this->class_names))
  209. {
  210. throw new \UnexpectedValueException("Unable to resolve the dependency '$dependency'");
  211. }
  212. }
  213. }
  214. }