uuid_commerce_product.features.inc 7.15 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
/**
 * @file
 * Features hooks for the uuid_commerce_product features component.
 */

/**
 * Implements hook_features_export_options().
 */
function uuid_commerce_product_features_export_options() {
  $options = array();

  // Check what content types are enabled for uuid features export.
  $enabled_types = variable_get('uuid_features_entity_commerce_product', FALSE);
  if (!empty($enabled_types)) {
    $types = commerce_product_types();
    $query = db_select('commerce_product', 'cp');
    $query->fields('cp', array('product_id', 'title', 'type', 'uuid'))
      ->condition('type', $enabled_types)
      ->orderBy('type')
21
22
      ->orderBy('title')
      ->addTag('uuid_commerce_product_features_export_options');
23
24
25
26
27
28
29
30
31
32
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
    $products = $query->execute()->fetchAll();
    foreach ($products as $product) {
      $options[$product->uuid] = t('@type: @title', array(
        '@type' => $types[$product->type]['name'],
        '@title' => $product->title,
      ));
    }
  }

  drupal_alter('uuid_commerce_product_features_export_options', $options);
  return $options;
}

/**
 * Implements hook_features_export().
 */
function uuid_commerce_product_features_export($data, &$export, $module_name = '') {
  $pipe = array();

  $export['dependencies']['uuid_features'] = 'uuid_features';

  $product_ids = entity_get_id_by_uuid('commerce_product', $data);
  foreach ($product_ids as $uuid => $product_id) {
    // Load the existing commerce product, with a fresh cache.
    $product = commerce_product_load($product_id, NULL, TRUE);

    $export['features']['uuid_commerce_product'][$uuid] = $uuid;
    $pipe['commerce_product'][$product->type] = $product->type;

    // drupal_alter() normally supports just one byref parameter. Using
    // the __drupal_alter_by_ref key, we can store any additional parameters
    // that need to be altered, and they'll be split out into additional params
    // for the hook_*_alter() implementations.
    $data = &$export;
    $data['__drupal_alter_by_ref']['pipe'] = &$pipe;
    $entity_type = 'commerce_product';
    drupal_alter('uuid_entity_features_export', $entity_type, $data, $product, $module);
    drupal_alter('uuid_commerce_product_features_export', $data, $product, $module);
    unset($data['__drupal_alter_by_ref']);
  }

  return $pipe;
}

/**
 * Implements hook_features_export_render().
 */
function uuid_commerce_product_features_export_render($module, $data) {
  $translatables = $code = array();

  $code[] = '  $products = array();';
  $code[] = '';
  $product_ids = entity_get_id_by_uuid('commerce_product', $data);
76
77
  // Always sort by the uuid to ensure the order is maintained.
  ksort($product_ids);
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  foreach ($product_ids as $uuid => $product_id) {
    // Only export the node if it exists.
    if ($product_id === FALSE) {
      continue;
    }
    // Attempt to load the product, using a fresh cache.
    $products = commerce_product_load_multiple(array($product_id), NULL, TRUE);
    if (empty($products)) {
      continue;
    }
    $product = reset($products);
    if (!empty($product->path)) {
      $product->pathauto_perform_alias = FALSE;
    }
    // Clone entity to avoid changes by reference.
    $export = clone $product;

    // Don't cause conflicts with product_id/vid/revision_timestamp/changed
    // fields.
    uuid_features_file_field_export($export, 'commerce_product');

    $entity_type = 'commerce_product';
    drupal_alter('uuid_entity_features_export_render', $entity_type, $export, $product, $module);
    drupal_alter('uuid_commerce_product_features_export_render', $export, $product, $module);

    unset($export->changed);
    unset($export->revision_uid);
    unset($export->revision_timestamp);
    unset($export->product_id);
    unset($export->revision_id);
    unset($export->cid);

    $code[] = '  $products[] = ' . features_var_export($export) . ';';
  }

  if (!empty($translatables)) {
    $code[] = features_translatables_export($translatables, '  ');
  }
  $code[] = '  return $products;';
  $code = implode("\n", $code);
  return array('uuid_features_default_commerce_product' => $code);
}

/**
 * Implements hook_features_revert().
 */
function uuid_commerce_product_features_revert($module) {
  uuid_commerce_product_features_rebuild($module);
}

/**
 * Implements hook_features_rebuild().
 *
 * Rebuilds products based on UUID from code defaults.
 */
function uuid_commerce_product_features_rebuild($module) {
  $return = TRUE;

  if (function_exists('uuid_term_features_rebuild')) {
    // Import the terms first.
    uuid_term_features_rebuild($module);
  }

141
  $products = features_get_default('uuid_commerce_product', $module);
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  if (!empty($products)) {
    $return = uuid_commerce_product_features_rebuild_products($products, $module);
    $entity_type = 'commerce_product';
    module_invoke_all('uuid_entity_features_rebuild_complete', $entity_type, $products, $module);
  }
  return $return;
}

/**
 * Runs the product import multiple times to resolve dependencies.
 *
 * We might need several runs of ths function to resolve the dependencies
 * created by reference fields. Those can only be resolved if the target product
 * already exists.
 *
 * @param array $products
 *   The products to process.
 * @param string $module
 *   The module to rebuild for.
 * @param int $max_nesting
 *   Maximal nesting level.
 * @param int $nesting_level
 *   Current nesting level.
 *
 * @return bool
 *   TRUE if all products could be restored.
 */
function uuid_commerce_product_features_rebuild_products($products, $module, $max_nesting = 5, $nesting_level = 0) {
  // Max nesting level hit.
  if ($max_nesting < $nesting_level) {
    watchdog('UUID Features', 'Unable to restore commerce products. Max nesting level reached.', array(), WATCHDOG_ERROR);
    return FALSE;
  }
  $second_run_products = array();
  $entity_info = entity_get_info('commerce_product');
  foreach ($products as $data) {
    try {

      // Double-check that bean can be created/reverted.
      if (!isset($entity_info['bundles'][$data['type']])) {
        drupal_set_message('Bundle not found for commerce product of type ' . $data['type'] . '. Product was not created/reverted.', 'warning');
      }
      else {
        // If this is an update, there will be a by-UUID matching product.
        $existing = entity_get_id_by_uuid('commerce_product', array($data['uuid']));
        if (!empty($existing)) {
          $product = entity_load_single('commerce_product', $existing[$data['uuid']]);
          foreach ($data as $key => $value) {
            $product->$key = $value;
          }
        }
        else {
          // Create a new product.
          $product = entity_create('commerce_product', $data);
        }

        $entity_type = 'commerce_product';
        drupal_alter('uuid_entity_features_rebuild', $entity_type, $product, $data, $module);
        drupal_alter('uuid_commerce_product_features_rebuild', $product, $module);

        uuid_features_file_field_import($product, 'commerce_product');
        commerce_product_save($product);
      }
    }
    catch (Exception $e) {
      $second_run_products[] = $data;
    }
  }
  if (!empty($second_run_products)) {
    return uuid_commerce_product_features_rebuild_products($second_run_products, $module, $max_nesting, ++$nesting_level);
  }
  return TRUE;
}