field_collection.migrate.inc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. /**
  3. * @file
  4. * Support for the Migrate API.
  5. *
  6. * Your field collection migration should be run after the host entity
  7. * migration. For example, if the collection is attached to nodes via a field
  8. * named 'field_attached_data', and if the nodes are being imported by
  9. * ArticleMigration, your collection migration class constructor should look
  10. * like:
  11. *
  12. * @code
  13. * $this->dependencies = array('Article');
  14. *
  15. * $this->destination = new MigrateDestinationFieldCollection(
  16. * 'field_attached_data',
  17. * array('host_entity_type' => 'node')
  18. * );
  19. *
  20. * $this->addFieldMapping('host_entity_id', 'source_article_id')
  21. * ->sourceMigration('Article');
  22. * @endcode
  23. *
  24. * @see http://drupal.org/node/1900640
  25. */
  26. /**
  27. * Destination class implementing migration into field_collection.
  28. */
  29. class MigrateDestinationFieldCollection extends MigrateDestinationEntity {
  30. /**
  31. * The type of entity hosting this collection field (e.g., node).
  32. *
  33. * @var string
  34. */
  35. protected $hostEntityType;
  36. static public function getKeySchema() {
  37. return array(
  38. 'item_id' => array(
  39. 'type' => 'int',
  40. 'unsigned' => TRUE,
  41. 'not null' => TRUE,
  42. 'description' => 'ID of field collection item',
  43. ),
  44. );
  45. }
  46. /**
  47. * Basic initialization.
  48. *
  49. * @param string $bundle
  50. * Bundle name.
  51. * @param array $options
  52. * (optional) Options applied to collections.
  53. */
  54. public function __construct($bundle, array $options = array()) {
  55. parent::__construct('field_collection_item', $bundle, $options);
  56. $this->hostEntityType = $options['host_entity_type'];
  57. }
  58. /**
  59. * Returns a list of fields available to be mapped for this collection
  60. * (bundle).
  61. *
  62. * @return array
  63. * Keys: machine names of the fields (to be passed to addFieldMapping).
  64. * Values: Human-friendly descriptions of the fields.
  65. */
  66. public function fields() {
  67. $fields = migrate_handler_invoke_all('Entity', 'fields', $this->entityType, $this->bundle);
  68. $fields['item_id'] = t('Field collection entity ID');
  69. $fields['host_entity_id'] = t('Field collection host ID');
  70. return $fields;
  71. }
  72. /**
  73. * Import a single field collection item.
  74. *
  75. * @param $collection
  76. * Collection object to build. Pre-filled with any fields mapped in the
  77. * migration.
  78. * @param $row
  79. * Raw source data object - passed through to prepare/complete handlers.
  80. *
  81. * @return array|false
  82. * Array of key fields (item_id only in this case) of the collection that
  83. * was saved or FALSE on failure.
  84. */
  85. public function import(stdClass $collection, stdClass $row) {
  86. $updating = FALSE;
  87. if (isset($row->migrate_map_destid1)) {
  88. // We're updated an existing entity - start from the previous data.
  89. // entity_load() returns an array, so we get the field collection entity
  90. // with array_shift().
  91. if ($entity = array_shift(entity_load('field_collection_item', array($row->migrate_map_destid1), array(), TRUE))) {
  92. $entity_old = clone $entity;
  93. $updating = TRUE;
  94. }
  95. }
  96. if (!$updating) {
  97. // Skip the collection if it has no host.
  98. if (empty($collection->host_entity_id)) {
  99. throw new MigrateException('Could not find host entity of the field collection to import.');
  100. }
  101. $entity = entity_create('field_collection_item', array('field_name' => $this->bundle));
  102. $updating = FALSE;
  103. $host_entity = entity_load_single($this->hostEntityType, $collection->host_entity_id);
  104. entity_get_controller($this->hostEntityType)->resetCache();
  105. if (isset($row->language)) {
  106. $entity->setHostEntity($this->hostEntityType, $host_entity, $row->language, TRUE);
  107. }
  108. else {
  109. $entity->setHostEntity($this->hostEntityType, $host_entity);
  110. }
  111. }
  112. unset($collection->host_entity_id);
  113. foreach ((array) $collection as $field => $value) {
  114. $entity->{$field} = $value;
  115. }
  116. $this->prepare($entity, $row);
  117. // Restore fields from original field_collection_item if updating
  118. if ($updating) {
  119. foreach ($entity as $field => $value) {
  120. if ('field_' != substr($field, 0, 6)) {
  121. continue;
  122. }
  123. elseif (property_exists($entity_old, $field) && !property_exists($collection, $field)) {
  124. $entity->$field = $entity_old->$field;
  125. }
  126. }
  127. }
  128. migrate_instrument_start('field_collection_save');
  129. $status = entity_save('field_collection_item', $entity);
  130. migrate_instrument_stop('field_collection_save');
  131. if (in_array($this->hostEntityType, array('node', 'field_collection_item')) || ($status !== FALSE)) {
  132. $this->complete($entity, $row);
  133. if ($updating) {
  134. $this->numUpdated++;
  135. }
  136. else {
  137. $this->numCreated++;
  138. }
  139. return array($entity->item_id);
  140. }
  141. else {
  142. return FALSE;
  143. }
  144. }
  145. /**
  146. * Delete a migrated collection.
  147. *
  148. * @param $key
  149. * Array of fields representing the key.
  150. */
  151. public function rollback(array $key) {
  152. $item_id = reset($key);
  153. $this->prepareRollback($item_id);
  154. $field_collection_item = field_collection_item_load($item_id);
  155. // If the collection wasn't imported then we can't roll it back, so check if
  156. // the loaded object is an instance of the FieldCollectionItemEntity class.
  157. if ($field_collection_item instanceof FieldCollectionItemEntity) {
  158. $field_collection_item->delete();
  159. }
  160. $this->completeRollback($item_id);
  161. return TRUE;
  162. }
  163. }
  164. /**
  165. * Implements migrate hook_migrate_api().
  166. */
  167. function field_collection_migrate_api() {
  168. $api = array(
  169. 'api' => 2,
  170. );
  171. return $api;
  172. }