table.inc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. /**
  3. * @file
  4. * Support for tables defined through the Schema API.
  5. */
  6. /**
  7. * Destination class implementing migration into a single table defined through
  8. * the Schema API.
  9. */
  10. class MigrateDestinationTable extends MigrateDestination {
  11. /**
  12. * The schema of the current table.
  13. *
  14. * @var array
  15. */
  16. protected $schema = NULL;
  17. /**
  18. * The name of the current table.
  19. *
  20. * @var string
  21. */
  22. protected $tableName = NULL;
  23. public function __construct($table_name) {
  24. $this->schema = drupal_get_schema($table_name);
  25. $this->tableName = $table_name;
  26. }
  27. static public function getKeySchema($table_name = NULL) {
  28. if (empty($table_name)) {
  29. return array();
  30. }
  31. $schema = drupal_get_schema($table_name);
  32. $keys = array();
  33. foreach ($schema['primary key'] as $primary_key) {
  34. // We can't have any form of serial fields here, since the mapping table
  35. // already has it's own.
  36. $schema['fields'][$primary_key]['auto_increment'] = FALSE;
  37. if ($schema['fields'][$primary_key]['type'] == 'serial') {
  38. $schema['fields'][$primary_key]['type'] = 'int';
  39. }
  40. $keys[$primary_key] = $schema['fields'][$primary_key];
  41. }
  42. return $keys;
  43. }
  44. public function __toString() {
  45. $output = t('Table !name', array('!name' => $this->tableName));
  46. return $output;
  47. }
  48. /**
  49. * Delete a single row.
  50. *
  51. * @param $id
  52. * Primary key values.
  53. */
  54. public function rollback(array $id) {
  55. migrate_instrument_start('table rollback');
  56. $delete = db_delete($this->tableName);
  57. $keys = array_keys(self::getKeySchema($this->tableName));
  58. $i = 0;
  59. foreach ($id as $value) {
  60. $key = $keys[$i++];
  61. $delete->condition($key, $value);
  62. }
  63. $delete->execute();
  64. migrate_instrument_stop('table rollback');
  65. }
  66. /**
  67. * Import a single row.
  68. *
  69. * @param $entity
  70. * Object object to build. Prefilled with any fields mapped in the Migration.
  71. * @param $row
  72. * Raw source data object - passed through to prepare/complete handlers.
  73. * @return array
  74. * Array of key fields of the object that was saved if
  75. * successful. FALSE on failure.
  76. */
  77. public function import(stdClass $entity, stdClass $row) {
  78. if (empty($this->schema['primary key'])) {
  79. throw new MigrateException(t("The destination table has no primary key defined."));
  80. }
  81. // Only filled when doing an update.
  82. $primary_key = array();
  83. $migration = Migration::currentMigration();
  84. // Updating previously-migrated content?
  85. if (isset($row->migrate_map_destid1)) {
  86. $i = 1;
  87. foreach ($this->schema['primary key'] as $key) {
  88. $primary_key[] = $key;
  89. $destination_id = $row->{'migrate_map_destid' . $i};
  90. if (isset($entity->{$key})) {
  91. if ($entity->{$key} != $destination_id) {
  92. throw new MigrateException(t("Incoming id !id and map destination id !destid don't match",
  93. array('!id' => $entity->{$key}, '!destid' => $destination_id)));
  94. }
  95. }
  96. else {
  97. $entity->{$key} = $destination_id;
  98. }
  99. $i++;
  100. }
  101. }
  102. if ($migration->getSystemOfRecord() == Migration::DESTINATION) {
  103. foreach ($this->schema['primary key'] as $key) {
  104. $primary_key[] = $key;
  105. if (!isset($entity->{$key})) {
  106. throw new MigrateException(t('System-of-record is DESTINATION, but no destination id provided'));
  107. }
  108. }
  109. $select = db_select($this->tableName)
  110. ->fields($this->tableName);
  111. foreach ($this->schema['primary key'] as $key) {
  112. $select->condition($key, $entity->{$key});
  113. }
  114. $old_entity = $select->execute()->fetchObject();
  115. if (empty($old_entity)) {
  116. throw new MigrateException(t('System-of-record is DESTINATION, but the destination entity does not exist'));
  117. }
  118. foreach ($entity as $field => $value) {
  119. $old_entity->$field = $entity->$field;
  120. }
  121. $entity = $old_entity;
  122. }
  123. $this->prepare($entity, $row);
  124. $status = drupal_write_record($this->tableName, $entity, $primary_key);
  125. $this->complete($entity, $row);
  126. if ($status) {
  127. $id = array();
  128. foreach ($this->schema['primary key'] as $key) {
  129. $id[] = $entity->{$key};
  130. }
  131. // Increment the number of updated or inserted records by checking the
  132. // result of drupal_write_record.
  133. ($status == SAVED_NEW) ? $this->numCreated++ : $this->numUpdated++;
  134. return $id;
  135. }
  136. }
  137. /**
  138. * Returns a list of fields available to be mapped.
  139. *
  140. * @param Migration $migration
  141. * Optionally, the migration containing this destination.
  142. * @return array
  143. * Keys: machine names of the fields (to be passed to addFieldMapping)
  144. * Values: Human-friendly descriptions of the fields.
  145. */
  146. public function fields($migration = NULL) {
  147. $fields = array();
  148. foreach ($this->schema['fields'] as $column => $schema) {
  149. $fields[$column] = t('Type: !type', array('!type' => $schema['type']));
  150. }
  151. return $fields;
  152. }
  153. /**
  154. * Give handlers a shot at modifying the object before saving it.
  155. *
  156. * @param $entity
  157. * Entity object to build. Prefilled with any fields mapped in the Migration.
  158. * @param $source_row
  159. * Raw source data object - passed through to prepare handlers.
  160. */
  161. public function prepare($entity, stdClass $source_row) {
  162. $migration = Migration::currentMigration();
  163. $entity->migrate = array(
  164. 'machineName' => $migration->getMachineName(),
  165. );
  166. // Call any prepare handler for this specific Migration.
  167. if (method_exists($migration, 'prepare')) {
  168. $migration->prepare($entity, $source_row);
  169. }
  170. }
  171. /**
  172. * Give handlers a shot at modifying the object (or taking additional action)
  173. * after saving it.
  174. *
  175. * @param $object
  176. * Entity object to build. This is the complete object after saving.
  177. * @param $source_row
  178. * Raw source data object - passed through to complete handlers.
  179. */
  180. public function complete($entity, stdClass $source_row) {
  181. $migration = Migration::currentMigration();
  182. // Call any complete handler for this specific Migration.
  183. if (method_exists($migration, 'complete')) {
  184. $migration->complete($entity, $source_row);
  185. }
  186. }
  187. }