field_collection.migrate.inc 5.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

/**
 * @file
 * Support for the Migrate API.
 *
 * Your field collection migration should be run after the host entity
 * migration. For example, if the collection is attached to nodes via a field
 * named 'field_attached_data', and if the nodes are being imported by
 * ArticleMigration, your collection migration class constructor should look
 * like:
 *
 * @code
 *   $this->dependencies = array('Article');
 *
 *   $this->destination = new MigrateDestinationFieldCollection(
 *     'field_attached_data',
 *     array('host_entity_type' => 'node')
 *   );
 *
 *   $this->addFieldMapping('host_entity_id', 'source_article_id')
 *     ->sourceMigration('Article');
 * @endcode
 *
 * @see http://drupal.org/node/1900640
 */

28
29
30
31
32
// Avoid issues when migrate module is disabled.
if (!class_exists('MigrateDestinationEntity')) {
  return;
}

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
 * Destination class implementing migration into field_collection.
 */
class MigrateDestinationFieldCollection extends MigrateDestinationEntity {
  /**
   * The type of entity hosting this collection field (e.g., node).
   *
   * @var string
   */
  protected $hostEntityType;

  static public function getKeySchema() {
    return array(
      'item_id' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'description' => 'ID of field collection item',
      ),
    );
  }

  /**
   * Basic initialization.
   *
   * @param string $bundle
   *   Bundle name.
   * @param array $options
   *   (optional) Options applied to collections.
   */
  public function __construct($bundle, array $options = array()) {
    parent::__construct('field_collection_item', $bundle, $options);
    $this->hostEntityType = $options['host_entity_type'];
  }

  /**
   * Returns a list of fields available to be mapped for this collection
   * (bundle).
   *
   * @return array
   *   Keys: machine names of the fields (to be passed to addFieldMapping).
   *   Values: Human-friendly descriptions of the fields.
   */
  public function fields() {
    $fields = migrate_handler_invoke_all('Entity', 'fields', $this->entityType, $this->bundle);
78
    $fields['item_id'] = t('Field collection entity ID');
79
80
81
82
83
84
85
    $fields['host_entity_id'] = t('Field collection host ID');
    return $fields;
  }

  /**
   * Import a single field collection item.
   *
Ra Mänd's avatar
Ra Mänd committed
86
   * @param \stdClass $collection
87
88
   *   Collection object to build. Pre-filled with any fields mapped in the
   *   migration.
Ra Mänd's avatar
Ra Mänd committed
89
   * @param \stdClass $row
90
91
   *   Raw source data object - passed through to prepare/complete handlers.
   *
Ra Mänd's avatar
Ra Mänd committed
92
   * @return array|bool
93
94
95
96
   *   Array of key fields (item_id only in this case) of the collection that
   *   was saved or FALSE on failure.
   */
  public function import(stdClass $collection, stdClass $row) {
97
    $updating = FALSE;
98
99
100
    if (isset($row->migrate_map_destid1)) {
      // We're updated an existing entity - start from the previous data.
      // entity_load() returns an array, so we get the field collection entity
101
102
103
104
      // with reset().
      $result = entity_load('field_collection_item', array($row->migrate_map_destid1), array(), TRUE);
      $entity = reset($result);
      if ($entity) {
105
106
107
        $entity_old = clone $entity;
        $updating = TRUE;
      }
108
    }
109
110

    if (!$updating) {
111
112
113
114
115
116
117
118
      // Skip the collection if it has no host.
      if (empty($collection->host_entity_id)) {
        throw new MigrateException('Could not find host entity of the field collection to import.');
      }
      $entity = entity_create('field_collection_item', array('field_name' => $this->bundle));
      $updating = FALSE;
      $host_entity = entity_load_single($this->hostEntityType, $collection->host_entity_id);
      entity_get_controller($this->hostEntityType)->resetCache();
119
120
121
122
123
124
125

      if (isset($row->language)) {
        $entity->setHostEntity($this->hostEntityType, $host_entity, $row->language, TRUE);
      }
      else {
        $entity->setHostEntity($this->hostEntityType, $host_entity);
      }
126
127
128
129
130
131
132
133
134
135
    }

    unset($collection->host_entity_id);

    foreach ((array) $collection as $field => $value) {
      $entity->{$field} = $value;
    }

    $this->prepare($entity, $row);

Ra Mänd's avatar
Ra Mänd committed
136
    // Restore fields from original field_collection_item if updating.
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
    if ($updating) {
      foreach ($entity as $field => $value) {
        if ('field_' != substr($field, 0, 6)) {
          continue;
        }
        elseif (property_exists($entity_old, $field) && !property_exists($collection, $field)) {
          $entity->$field = $entity_old->$field;
        }
      }
    }

    migrate_instrument_start('field_collection_save');
    $status = entity_save('field_collection_item', $entity);
    migrate_instrument_stop('field_collection_save');

    if (in_array($this->hostEntityType, array('node', 'field_collection_item')) || ($status !== FALSE)) {
      $this->complete($entity, $row);
      if ($updating) {
        $this->numUpdated++;
      }
      else {
        $this->numCreated++;
      }
      return array($entity->item_id);
    }
    else {
      return FALSE;
    }
  }

  /**
   * Delete a migrated collection.
   *
   * @param $key
   *   Array of fields representing the key.
   */
  public function rollback(array $key) {
    $item_id = reset($key);

    $this->prepareRollback($item_id);
    $field_collection_item = field_collection_item_load($item_id);
    // If the collection wasn't imported then we can't roll it back, so check if
    // the loaded object is an instance of the FieldCollectionItemEntity class.
    if ($field_collection_item instanceof FieldCollectionItemEntity) {
      $field_collection_item->delete();
    }

    $this->completeRollback($item_id);
    return TRUE;
  }
Ra Mänd's avatar
Ra Mänd committed
187

188
189
190
191
192
193
194
195
196
197
198
}

/**
 * Implements migrate hook_migrate_api().
 */
function field_collection_migrate_api() {
  $api = array(
    'api' => 2,
  );
  return $api;
}