You are here

function commerce_order_commerce_customer_profile_presave in Commerce Core 7

Implements hook_commerce_customer_profile_presave().

The Order module prevents customer profile deletion for any profile that is referenced by a non-cart order via hook_commerce_customer_profile_can_delete(). The same logic applies when updating a customer profile to determine whether or not the update should be allowed on the same profile or if it should be handled as a clone of the original profile. This ensures that editing a profile on a separate order or through the admin UI after completing an order will not cause the original order to lose essential data.

File

modules/order/commerce_order.module, line 509
Defines the core Commerce order entity and API functions to manage orders and interact with them.

Code

function commerce_order_commerce_customer_profile_presave($profile) {

  // Only perform this check when updating an existing profile.
  if (!empty($profile->profile_id)) {
    $original_profile = $profile->original;
    $field_change = FALSE;

    // Compare against the field values.
    foreach (field_info_instances('commerce_customer_profile', $profile->type) as $field_name => $instance) {
      $langcode = field_language('commerce_customer_profile', $profile, $field_name);

      // Make sure that empty fields have a consistent structure.
      if (empty($profile->{$field_name})) {
        $profile->{$field_name}[$langcode] = array();
      }
      if (empty($original_profile->{$field_name})) {
        $original_profile->{$field_name}[$langcode] = array();
      }

      // Extract the items from the field value that need to be compared.
      $items = $profile->{$field_name}[$langcode];
      $original_items = $original_profile->{$field_name}[$langcode];

      // If the number of items has changed, mark the field change.
      if (count($items) != count($original_items)) {
        $field_change = TRUE;
        break;
      }

      // Loop over each item in the field value.
      foreach ($items as $delta => $item) {

        // Find the supposedly matching original item.
        $original_item = $original_items[$delta];

        // Compare columns common to both arrays.
        $item = array_intersect_key($item, $original_item);
        $original_item = array_intersect_key($original_item, $item);
        if ($item != $original_item) {
          $field_change = TRUE;
          break;
        }

        // Provide special handling for the addressfield to accommodate the fact
        // that the field as loaded from the database may contain additional
        // keys that aren't included in the profile being saved because their
        // corresponding form elements weren't included on the edit form.
        // If those additional keys contain data, the field needs to be
        // marked as changed.
        if ($field_name == 'commerce_customer_address') {
          foreach ($original_items[$delta] as $key => $value) {
            if (!array_key_exists($key, $item) && !empty($value)) {
              $field_change = TRUE;
              break 2;
            }
          }
        }
      }
    }

    // If we did in fact detect significant changes and this profile has been
    // referenced by a non-cart order...
    if ($field_change && !commerce_order_commerce_customer_profile_can_delete($profile)) {

      // Update various properties of the profile so it gets saved as new.
      $profile->profile_id = '';
      $profile->revision_id = '';
      $profile->created = REQUEST_TIME;
      $profile->log = '';
    }
  }
}