Projet

Général

Profil

Paste
Télécharger (15,8 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / commerce / modules / order / commerce_order.rules.inc @ b858700c

1
<?php
2

    
3
/**
4
 * @file
5
 * Rules integration for orders.
6
 *
7
 * @addtogroup rules
8
 * @{
9
 */
10

    
11
/**
12
 * Implements hook_rules_condition_info().
13
 */
14
function commerce_order_rules_condition_info() {
15
  $conditions = array();
16

    
17
  $conditions['commerce_order_compare_address'] = array(
18
    'label' => t('Order address component comparison'),
19
    'parameter' => array(
20
      'commerce_order' => array(
21
        'type' => 'commerce_order',
22
        'label' => t('Order'),
23
        'description' => t('The order containing the profile reference with the address in question.'),
24
      ),
25
      'address_field' => array(
26
        'type' => 'text',
27
        'label' => t('Address'),
28
        'options list' => 'commerce_order_address_field_options_list',
29
        'description' => t('The address associated with this order whose component you want to compare.'),
30
        'restriction' => 'input',
31
      ),
32
      'address_component' => array(
33
        'type' => 'text',
34
        'label' => t('Address component'),
35
        'options list' => 'commerce_order_address_component_options_list',
36
        'description' => t('The actual address component you want to compare. Common names of address components are given in parentheses.'),
37
        'restriction' => 'input',
38
      ),
39
      'operator' => array(
40
        'type' => 'text',
41
        'label' => t('Operator'),
42
        'description' => t('The comparison operator.'),
43
        'optional' => TRUE,
44
        'default value' => 'equals',
45
        'options list' => 'commerce_order_address_comparison_operator_options_list',
46
        'restriction' => 'input',
47
      ),
48
      'value' => array(
49
        'type' => 'text',
50
        'label' => t('Value'),
51
        'description' => t('The value to compare against the address component. Bear in mind that addresses using select lists for various components may use a value different from the option you select. For example, countries are selected by name, but the value is the two letter abbreviation. For comparisons with multiple possible values, place separate values on new lines.'),
52
      ),
53
    ),
54
    'group' => t('Commerce Order'),
55
    'callbacks' => array(
56
      'execute' => 'commerce_order_rules_compare_address',
57
    ),
58
  );
59

    
60
  $conditions['commerce_order_contains_product'] = array(
61
    'label' => t('Order contains a particular product'),
62
    'parameter' => array(
63
      'commerce_order' => array(
64
        'type' => 'commerce_order',
65
        'label' => t('Order'),
66
        'description' => t('The order whose line items should be checked for the specified product. If the specified order does not exist, the comparison will act as if it is against a quantity of 0.'),
67
      ),
68
      'product_id' => array(
69
        'type' => 'text',
70
        'label' => t('Product SKU'),
71
        'description' => t('The SKU of the product to look for on the order.'),
72
      ),
73
      'operator' => array(
74
        'type' => 'text',
75
        'label' => t('Operator'),
76
        'description' => t('The operator used with the quantity value below to compare the quantity of the specified product on the order.'),
77
        'default value' => '>=',
78
        'options list' => 'commerce_numeric_comparison_operator_options_list',
79
        'restriction' => 'input',
80
      ),
81
      'value' => array(
82
        'type' => 'text',
83
        'label' => t('Quantity'),
84
        'default value' => '1',
85
        'description' => t('The value to compare against the quantity of the specified product on the order.'),
86
      ),
87
    ),
88
    'group' => t('Commerce Order'),
89
    'callbacks' => array(
90
      'execute' => 'commerce_order_rules_contains_product',
91
    ),
92
  );
93

    
94
  $conditions['commerce_order_contains_product_type'] = array(
95
    'label' => t('Order contains products of particular product types'),
96
    'parameter' => array(
97
      'commerce_order' => array(
98
        'label' => t('Order'),
99
        'type' => 'commerce_order',
100
        'description' => t('The order whose line items should be checked for the specified product type. If the specified order does not exist, the comparison will act as if it is against a quantity of 0.'),
101
      ),
102
      'product_type' => array(
103
        'label' => t('Product type(s)'),
104
        'type' => 'list<text>',
105
        'description' => t('The product type(s) to look for in the order.'),
106
        'options list' => 'commerce_product_type_options_list',
107
      ),
108
      'operator' => array(
109
        'label' => t('Operator'),
110
        'type' => 'text',
111
        'description' => t('The operator used with the quantity value below to compare against the quantity of products matching the specified product type(s) on the order.'),
112
        'default value' => '>=',
113
        'options list' => 'commerce_numeric_comparison_operator_options_list',
114
        'restriction' => 'input',
115
      ),
116
      'value' => array(
117
        'label' => t('Quantity'),
118
        'type' => 'text',
119
        'default value' => '1',
120
        'description' => t('The value to compare against the quantity of products of the specified product type(s) on the order.'),
121
      ),
122
    ),
123
    'group' => t('Commerce Order'),
124
    'callbacks' => array(
125
      'execute' => 'commerce_order_rules_contains_product_type',
126
    ),
127
  );
128

    
129
  $conditions['commerce_order_compare_total_product_quantity'] = array(
130
    'label' => t('Total product quantity comparison'),
131
    'parameter' => array(
132
      'commerce_order' => array(
133
        'type' => 'commerce_order',
134
        'label' => t('Order'),
135
        'description' => t('The order whose product line item quantities should be totalled. If the specified order does not exist, the comparison will act as if it is against a quantity of 0.'),
136
      ),
137
      'operator' => array(
138
        'type' => 'text',
139
        'label' => t('Operator'),
140
        'description' => t('The comparison operator to use against the total number of products on the order.'),
141
        'default value' => '>=',
142
        'options list' => 'commerce_numeric_comparison_operator_options_list',
143
        'restriction' => 'input',
144
      ),
145
      'value' => array(
146
        'type' => 'text',
147
        'label' => t('Quantity'),
148
        'default value' => 1,
149
        'description' => t('The value to compare against the total quantity of products on the order.'),
150
      ),
151
    ),
152
    'group' => t('Commerce Order'),
153
    'callbacks' => array(
154
      'execute' => 'commerce_order_rules_compare_total_quantity',
155
    ),
156
  );
157

    
158
  return $conditions;
159
}
160

    
161
/**
162
 * Options list callback: address fields for the address comparison condition.
163
 */
164
function commerce_order_address_field_options_list() {
165
  $options = array();
166

    
167
  // Retrieve a list of all address fields on customer profile bundles.
168
  $address_fields = commerce_info_fields('addressfield', 'commerce_customer_profile');
169

    
170
  // Loop over every customer profile reference field on orders.
171
  foreach (commerce_info_fields('commerce_customer_profile_reference', 'commerce_order') as $field_name => $field) {
172
    // Retrieve the type of customer profile referenced by this field.
173
    $type = $field['settings']['profile_type'];
174

    
175
    // Loop over every address field looking for any attached to this bundle.
176
    foreach ($address_fields as $address_field_name => $address_field) {
177
      if (in_array($type, $address_field['bundles']['commerce_customer_profile'])) {
178
        // Add it to the options list.
179
        $instance = field_info_instance('commerce_customer_profile', 'commerce_customer_address', $type);
180
        $translated_instance = commerce_i18n_object('field_instance', $instance);
181

    
182
        $options[commerce_customer_profile_type_get_name($type)][$field_name . '|' . $address_field_name] = check_plain($translated_instance['label']);
183
      }
184
    }
185
  }
186

    
187
  if (empty($options)) {
188
    drupal_set_message(t('No order addresses could be found for comparison.'), 'error');
189
  }
190

    
191
  return $options;
192
}
193

    
194
/**
195
 * Options list callback: components for the address comparison condition.
196
 */
197
function commerce_order_address_component_options_list() {
198
  return array(
199
    'country' => t('Country'),
200
    'name_line' => t('Full name'),
201
    'first_name' => t('First name'),
202
    'last_name' => t('Last name'),
203
    'organisation_name' => t('Company name'),
204
    'thoroughfare' => t('Thoroughfare (Street address)'),
205
    'premise' => t('Premise (Building)'),
206
    'sub_premise' => t('Sub-premise (Suite)'),
207
    'locality' => t('Locality (City)'),
208
    'dependent_locality' => t('Dependent locality (Town)'),
209
    'administrative_area' => t('Administrative area (State / Province)'),
210
    'sub_administrative_area' => t('Sub-administrative area (District)'),
211
    'postal_code' => t('Postal code'),
212
  );
213
}
214

    
215
/**
216
 * Options list callback: operators for the address comparison condition.
217
 */
218
function commerce_order_address_comparison_operator_options_list() {
219
  return array(
220
    'equals' => t('equals'),
221
    'begins with' => t('begins with'),
222
    'contains' => t('contains'),
223
    'is one of' => t('is one of'),
224
    'begins with one of' => t('begins with one of'),
225
  );
226
}
227

    
228
/**
229
 * Condition callback: compares an address component against the given value.
230
 */
231
function commerce_order_rules_compare_address($order, $address_field, $component, $operator, $value) {
232
  list($field_name, $address_field_name) = explode('|', $address_field);
233

    
234
  // If we actually received a valid order...
235
  if (!empty($order)) {
236
    $wrapper = entity_metadata_wrapper('commerce_order', $order);
237

    
238
    // And if we can actually find the requested address data...
239
    if (!empty($wrapper->{$field_name}) && !empty($wrapper->{$field_name}->{$address_field_name})) {
240
      $address = $wrapper->{$field_name}->{$address_field_name}->value();
241

    
242
      // Perform the comparison in upper case.
243
      $address_component = drupal_strtoupper($address[$component]);
244
      $value = drupal_strtoupper($value);
245

    
246
      // Make a comparison based on the operator.
247
      switch ($operator) {
248
        case 'equals':
249
          return $address_component == $value;
250
        case 'begins with':
251
          return strpos($address_component, $value) === 0;
252
        case 'contains':
253
          return strpos($address_component, $value) !== FALSE;
254
        case 'is one of':
255
          $list = preg_split('/[\n\r]+/', $value);
256
          return array_search($address_component, $list) !== FALSE;
257
        case 'begins with one of':
258
          $list = preg_split('/[\n\r]+/', $value);
259
          foreach ($list as $item) {
260
            if (strpos($address_component, $item) === 0) {
261
              return TRUE;
262
            }
263
          }
264
          break;
265
      }
266
    }
267
  }
268

    
269
  return FALSE;
270
}
271

    
272
/**
273
 * Condition callback: checks to see if a particular product exists on an order
274
 * in the specified quantity.
275
 */
276
function commerce_order_rules_contains_product($order, $sku, $operator, $value) {
277
  $products = array($sku => 0);
278

    
279
  // If we actually received a valid order...
280
  if (!empty($order)) {
281
    $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
282

    
283
    // Populate the array of the quantities of the products on the order.
284
    foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
285
      if (in_array($line_item_wrapper->type->value(), commerce_product_line_item_types())) {
286
        // Extract a product ID and quantity from the line item.
287
        $line_item_sku = $line_item_wrapper->commerce_product->sku->value();
288
        $quantity = $line_item_wrapper->quantity->value();
289

    
290
        // Update the product's quantity value.
291
        if (empty($products[$line_item_sku])) {
292
          $products[$line_item_sku] = $quantity;
293
        }
294
        else {
295
          $products[$line_item_sku] += $quantity;
296
        }
297
      }
298
    }
299
  }
300

    
301
  // Make a quantity comparison based on the operator.
302
  switch ($operator) {
303
    case '<':
304
      return $products[$sku] < $value;
305
    case '<=':
306
      return $products[$sku] <= $value;
307
    case '=':
308
      return $products[$sku] == $value;
309
    case '>=':
310
      return $products[$sku] >= $value;
311
    case '>':
312
      return $products[$sku] > $value;
313
  }
314

    
315
  return FALSE;
316
}
317

    
318
/**
319
 * Condition callback: checks to see if one or more particular product types exist on an order
320
 * in the specified quantity.
321
 */
322
function commerce_order_rules_contains_product_type($order, $product_types, $operator, $value) {
323
  $quantity = 0;
324

    
325
  // If we actually received a valid order...
326
  if (!empty($order)) {
327
    $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
328

    
329
    // Look for product line items on the order whose products match the
330
    // specified product types and increment the quantity count accordingly.
331
    foreach ($order_wrapper->commerce_line_items as $line_item_wrapper) {
332
      if (in_array($line_item_wrapper->type->value(), commerce_product_line_item_types())) {
333
        // Extract the product type from the line item.
334
        $line_item_product_type = $line_item_wrapper->commerce_product->type->value();
335

    
336
        // If the line item product type matches, update the total quantity.
337
        if (in_array($line_item_product_type, $product_types)) {
338
          $quantity += $line_item_wrapper->quantity->value();
339
        }
340
      }
341
    }
342
  }
343

    
344
  // Make a quantity comparison based on the operator.
345
  switch ($operator) {
346
    case '<':
347
      return $quantity < $value;
348
    case '<=':
349
      return $quantity <= $value;
350
    case '=':
351
      return $quantity == $value;
352
    case '>=':
353
      return $quantity >= $value;
354
    case '>':
355
      return $quantity > $value;
356
  }
357

    
358
  return FALSE;
359
}
360

    
361
/**
362
 * Condition callback: compares the total quantity of products on an order
363
 * against the specified quantity.
364
 */
365
function commerce_order_rules_compare_total_quantity($order, $operator, $value) {
366
  $quantity = 0;
367

    
368
  // If we received an order, get the total quantity of products on it.
369
  if (!empty($order)) {
370
    $wrapper = entity_metadata_wrapper('commerce_order', $order);
371

    
372
    if (!empty($wrapper->commerce_line_items)) {
373
      $quantity = commerce_line_items_quantity($wrapper->commerce_line_items, commerce_product_line_item_types());
374
    }
375
  }
376

    
377
  // Make a quantity comparison based on the operator.
378
  switch ($operator) {
379
    case '<':
380
      return $quantity < $value;
381
    case '<=':
382
      return $quantity <= $value;
383
    case '=':
384
      return $quantity == $value;
385
    case '>=':
386
      return $quantity >= $value;
387
    case '>':
388
      return $quantity > $value;
389
  }
390

    
391
  return FALSE;
392
}
393

    
394
/**
395
 * Implements hook_rules_action_info().
396
 */
397
function commerce_order_rules_action_info() {
398
  $actions = array();
399

    
400
  $actions['commerce_order_update_state'] = array(
401
    'label' => t('Update the order state'),
402
    'parameter' => array(
403
      'commerce_order' => array(
404
        'type' => 'commerce_order',
405
        'label' => t('Order to update'),
406
      ),
407
      'order_state' => array(
408
        'type' => 'text',
409
        'label' => t('Order state'),
410
        'description' => t('Select the order state whose default status the order will be updated to.'),
411
        'options list' => 'commerce_order_state_options_list',
412
      ),
413
    ),
414
    'group' => t('Commerce Order'),
415
    'callbacks' => array(
416
      'execute' => 'commerce_order_rules_update_state',
417
    ),
418
  );
419

    
420
  $actions['commerce_order_update_status'] = array(
421
    'label' => t('Update the order status'),
422
    'parameter' => array(
423
      'commerce_order' => array(
424
        'type' => 'commerce_order',
425
        'label' => t('Order to update'),
426
      ),
427
      'order_status' => array(
428
        'type' => 'text',
429
        'label' => t('Order status'),
430
        'options list' => 'commerce_order_status_options_list',
431
      ),
432
    ),
433
    'group' => t('Commerce Order'),
434
    'callbacks' => array(
435
      'execute' => 'commerce_order_rules_update_status',
436
    ),
437
  );
438

    
439
  return $actions;
440
}
441

    
442
/**
443
 * Rules action: updates an order's status to the default status of the given
444
 *   order state.
445
 */
446
function commerce_order_rules_update_state($order, $name) {
447
  $order_state = commerce_order_state_load($name);
448
  commerce_order_status_update($order, $order_state['default_status'], FALSE, NULL, t('Order state updated via Rules.'));
449
}
450

    
451
/**
452
 * Rules action: updates an order's status using the Order API.
453
 */
454
function commerce_order_rules_update_status($order, $name) {
455
  commerce_order_status_update($order, $name, FALSE, NULL, t('Order status updated via Rules.'));
456
}
457

    
458
/**
459
 * @}
460
 */