migrate.install 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. <?php
  2. /**
  3. * @file
  4. * Migrate module installation
  5. */
  6. function migrate_schema() {
  7. $schema = array();
  8. $schema['migrate_status'] = migrate_schema_status();
  9. $schema['migrate_log'] = migrate_schema_log();
  10. return $schema;
  11. }
  12. function migrate_schema_status() {
  13. return array(
  14. 'description' => 'Status information for migrations',
  15. 'fields' => array(
  16. 'machine_name' => array(
  17. 'type' => 'varchar',
  18. 'length' => 255,
  19. 'not null' => TRUE,
  20. 'description' => 'Unique machine name for migration',
  21. ),
  22. 'class_name' => array(
  23. 'type' => 'varchar',
  24. 'length' => 255,
  25. 'not null' => TRUE,
  26. 'description' => 'Name of class to instantiate for this migration',
  27. ),
  28. 'status' => array(
  29. 'type' => 'int',
  30. 'size' => 'tiny',
  31. 'unsigned' => TRUE,
  32. 'not null' => TRUE,
  33. 'default' => 0,
  34. 'description' => 'Current status of migration',
  35. ),
  36. 'highwater' => array(
  37. 'type' => 'varchar',
  38. 'length' => 255,
  39. 'not null' => TRUE,
  40. 'default' => '',
  41. 'description' => 'Highwater mark for detecting updated content',
  42. ),
  43. 'arguments' => array(
  44. 'type' => 'blob',
  45. 'not null' => FALSE,
  46. 'size' => 'big',
  47. 'serialize' => TRUE,
  48. 'description' => 'A serialized array of arguments to the migration constructor',
  49. ),
  50. ),
  51. 'primary key' => array('machine_name'),
  52. );
  53. }
  54. function migrate_schema_log() {
  55. return array(
  56. 'description' => 'History of migration processes',
  57. 'fields' => array(
  58. 'mlid' => array(
  59. 'type' => 'serial',
  60. 'unsigned' => TRUE,
  61. 'not null' => TRUE,
  62. 'description' => 'Primary key for migrate_log table',
  63. ),
  64. 'machine_name' => array(
  65. 'type' => 'varchar',
  66. 'length' => 255,
  67. 'not null' => TRUE,
  68. 'description' => 'Unique machine name for migration',
  69. ),
  70. 'process_type' => array(
  71. 'type' => 'int',
  72. 'size' => 'tiny',
  73. 'unsigned' => TRUE,
  74. 'not null' => TRUE,
  75. 'description' => 'Type of migration process - 1 for import, 2 for rollback',
  76. ),
  77. 'starttime' => array(
  78. 'type' => 'int',
  79. 'size' => 'big',
  80. 'unsigned' => TRUE,
  81. 'not null' => TRUE,
  82. 'description' => 'Begin time of a migration process, times 1000',
  83. ),
  84. 'endtime' => array(
  85. 'type' => 'int',
  86. 'size' => 'big',
  87. 'unsigned' => TRUE,
  88. 'not null' => FALSE,
  89. 'description' => 'End time of a migration process, times 1000',
  90. ),
  91. 'initialhighwater' => array(
  92. 'type' => 'varchar',
  93. 'length' => 255,
  94. 'not null' => TRUE,
  95. 'description' => 'Initial highwater mark',
  96. ),
  97. 'finalhighwater' => array(
  98. 'type' => 'varchar',
  99. 'length' => 255,
  100. 'not null' => FALSE,
  101. 'description' => 'Final highwater mark',
  102. ),
  103. 'numprocessed' => array(
  104. 'type' => 'int',
  105. 'unsigned' => TRUE,
  106. 'not null' => FALSE,
  107. 'description' => 'Number of items processed',
  108. ),
  109. ),
  110. 'primary key' => array('mlid'),
  111. );
  112. }
  113. /**
  114. * Implements hook_uninstall().
  115. * Drop map/message tables, in case implementing classes did not.
  116. */
  117. function migrate_uninstall() {
  118. // Note: If a derived Migration class defined its own map or message
  119. // table name not fitting this pattern, that class is solely responsible for
  120. // cleaning up
  121. // TODO: Prefix table names (db_find_tables does not do it)
  122. foreach (db_find_tables('migrate_map_%') as $tablename) {
  123. db_drop_table($tablename);
  124. }
  125. foreach (db_find_tables('migrate_message_%') as $tablename) {
  126. db_drop_table($tablename);
  127. }
  128. // Remove any file_usage entries we've written
  129. if (db_table_exists('file_usage')) {
  130. db_delete('file_usage')
  131. ->condition('module', 'migrate')
  132. ->execute();
  133. }
  134. }
  135. /**
  136. * Add highwater mark
  137. */
  138. function migrate_update_7001() {
  139. $ret = array();
  140. if (!db_field_exists('migrate_status', 'highwater')) {
  141. db_add_field('migrate_status', 'highwater', array(
  142. 'type' => 'varchar',
  143. 'length' => 255,
  144. 'not null' => TRUE,
  145. 'default' => '',
  146. 'description' => 'Highwater mark for detecting updated content',
  147. )
  148. );
  149. }
  150. $ret[] = t('Added highwater column to migrate_status table');
  151. return $ret;
  152. }
  153. /**
  154. * Add last_imported field to all map tables
  155. */
  156. function migrate_update_7002() {
  157. $ret = array();
  158. foreach (db_find_tables('migrate_map_%') as $tablename) {
  159. if (!db_field_exists($tablename, 'last_imported')) {
  160. db_add_field($tablename, 'last_imported', array(
  161. 'type' => 'int',
  162. 'unsigned' => TRUE,
  163. 'not null' => TRUE,
  164. 'default' => 0,
  165. 'description' => 'UNIX timestamp of the last time this row was imported',
  166. ));
  167. }
  168. }
  169. $ret[] = t('Added last_imported column to all map tables');
  170. return $ret;
  171. }
  172. /**
  173. * Add lastthroughput column to migrate_status
  174. */
  175. function migrate_update_7003() {
  176. $ret = array();
  177. if (!db_field_exists('migrate_status', 'lastthroughput')) {
  178. db_add_field('migrate_status', 'lastthroughput', array(
  179. 'type' => 'int',
  180. 'length' => 11,
  181. 'not null' => FALSE,
  182. 'description' => 'Rate of success during most recent completed import (# per minute)',
  183. )
  184. );
  185. }
  186. $ret[] = t('Added lastthroughput column to migrate_status table');
  187. return $ret;
  188. }
  189. /**
  190. * Convert lastimported datetime field to lastimportedtime int field.
  191. */
  192. function migrate_update_7004() {
  193. $ret = array();
  194. if (!db_field_exists('migrate_status', 'lastimportedtime')) {
  195. db_add_field('migrate_status', 'lastimportedtime', array(
  196. 'type' => 'int',
  197. 'unsigned' => TRUE,
  198. 'not null' => FALSE,
  199. 'description' => 'Date and time of last completed import',
  200. )
  201. );
  202. if (!db_field_exists('migrate_status', 'lastimported')) {
  203. $result = db_select('migrate_status', 'ms')
  204. ->fields('ms', array('machine_name', 'lastimported'))
  205. ->execute();
  206. foreach ($result as $row) {
  207. $lastimportedtime = strtotime($row->lastimported);
  208. db_update('migrate_status')
  209. ->fields(array('lastimportedtime' => $lastimportedtime))
  210. ->condition('machine_name', $row->machine_name)
  211. ->execute();
  212. }
  213. db_drop_field('migrate_status', 'lastimported');
  214. $ret[] = t('Converted lastimported datetime field to lastimportedtime int field');
  215. }
  216. }
  217. return $ret;
  218. }
  219. /**
  220. * Add support for history logging
  221. */
  222. function migrate_update_7005() {
  223. $ret = array();
  224. if (!db_table_exists('migrate_log')) {
  225. $ret[] = t('Create migrate_log table');
  226. db_create_table('migrate_log', migrate_schema_log());
  227. $ret[] = t('Remove historic columns from migrate_status table');
  228. db_drop_field('migrate_status', 'lastthroughput');
  229. db_drop_field('migrate_status', 'lastimportedtime');
  230. }
  231. return $ret;
  232. }
  233. /**
  234. * Add and populate class_name field. Any existing migration code using
  235. * dependencies or sourceMigration() must be changed! See CHANGELOG.txt.
  236. */
  237. function migrate_update_7006() {
  238. $ret = array();
  239. if (!db_field_exists('migrate_status', 'class_name')) {
  240. db_add_field('migrate_status', 'class_name', array(
  241. 'type' => 'varchar',
  242. 'length' => 255,
  243. 'not null' => TRUE,
  244. 'default' => '',
  245. 'description' => 'Name of class to instantiate for this migration',
  246. )
  247. );
  248. db_query("UPDATE {migrate_status}
  249. SET class_name = CONCAT(machine_name, 'Migration')
  250. ");
  251. $ret[] = t('Added class_name column to migrate_status table');
  252. }
  253. return $ret;
  254. }
  255. /**
  256. * Add arguments field to migrate_status table.
  257. */
  258. function migrate_update_7007() {
  259. $ret = array();
  260. if (!db_field_exists('migrate_status', 'arguments')) {
  261. db_add_field('migrate_status', 'arguments', array(
  262. 'type' => 'blob',
  263. 'not null' => FALSE,
  264. 'size' => 'big',
  265. 'serialize' => TRUE,
  266. 'description' => 'A serialized array of arguments to the migration constructor',
  267. )
  268. );
  269. $ret[] = t('Added arguments column to migrate_status table');
  270. }
  271. return $ret;
  272. }
  273. /**
  274. * Update map tables to reflect change of needs_update to a status column.
  275. */
  276. function migrate_update_7008() {
  277. // Updates can be run when the module is disabled, which would mean the
  278. // call to migrate_migrations() will fail. Just bail in that case...
  279. if (!module_exists('migrate')) {
  280. throw new DrupalUpdateException(t('This update cannot be run while the Migrate ' .
  281. 'module is disabled - you must enable Migrate to run this update.'));
  282. }
  283. $ret = array();
  284. foreach (migrate_migrations() as $migration) {
  285. if (is_a($migration, 'Migration')) {
  286. // Since we're now tracking failed/ignored rows in the map table,
  287. // destination keys need to be nullable
  288. $map = $migration->getMap();
  289. $map_connection = $map->getConnection();
  290. $map_table = $map->getMapTable();
  291. $destination = $migration->getDestination();
  292. $key_schema = $destination->getKeySchema();
  293. $index = 1;
  294. foreach ($key_schema as $field_schema) {
  295. $field = 'destid' . $index++;
  296. $field_schema['not null'] = FALSE;
  297. $map_connection->schema()->changeField($map_table, $field, $field,
  298. $field_schema);
  299. $ret[] = t('Changed !table.!field to be non-null',
  300. array('!table' => $map_table, '!field' => $field));
  301. }
  302. // Add any existing failures to the map table
  303. $msg_table = $map->getMessageTable();
  304. $msg_marked = FALSE;
  305. $result = $map_connection->select($msg_table, 'msg')
  306. ->fields('msg')
  307. ->condition('level', Migration::MESSAGE_INFORMATIONAL, '<>')
  308. ->execute();
  309. foreach ($result as $row) {
  310. $keys = array();
  311. $index = 1;
  312. foreach ($row as $field => $value) {
  313. if (drupal_substr($field, 0, 8) == 'sourceid') {
  314. $keys['sourceid' . $index++] = $value;
  315. }
  316. }
  317. $map_connection->merge($map_table)
  318. ->key($keys)
  319. ->fields(array('needs_update' => MigrateMap::STATUS_FAILED))
  320. ->execute();
  321. $msg_marked = TRUE;
  322. }
  323. if ($msg_marked) {
  324. $ret[] = t('Marked failures in !table', array('!table' => $map_table));
  325. }
  326. }
  327. }
  328. return $ret;
  329. }
  330. /**
  331. * Warn that there have been incompatible changes to file handling.
  332. */
  333. function migrate_update_7201() {
  334. return t('File field and destination handling has been completely refactored
  335. - if you are migrating files, you will need to change your migration
  336. implementation to reflect these changes. Please see
  337. <a href="@doc">Handling files in Drupal 7</a> for more information',
  338. array('@doc' => 'http://drupal.org/node/1540106'));
  339. }