You are here

function commerce_line_item_field_attach_delete in Commerce Core 7

Implements hook_field_attach_delete().

When an entity is deleted, this hook is invoked so any attached fields can do necessary clean-up. Because line items can't exist apart from a line item reference field, this function checks the entity being deleted for any referenced line items that are orphaned and deletes them.

File

modules/line_item/commerce_line_item.module, line 353
Defines the core Commerce line item entity and API functions interact with line items on orders.

Code

function commerce_line_item_field_attach_delete($entity_type, $entity) {
  $wrapper = entity_metadata_wrapper($entity_type, $entity);
  $entity_info = entity_get_info($entity_type);

  // If the entity being deleted has a bundle...
  if (!empty($entity_info['entity keys']['bundle'])) {

    // Extract the bundle name using the specified property.
    $property = $entity_info['entity keys']['bundle'];
    $bundle = $entity->{$property};
  }
  else {

    // Otherwise use the entity type as the bundle name.
    $bundle = $entity_type;
  }

  // Find any line item reference fields on this entity and delete any orphan
  // referenced line items.
  $line_item_ids = array();
  foreach (field_info_instances($entity_type, $bundle) as $field_name => $field) {

    // Only examine line item reference fields using the manager widget.
    if ($field['widget']['type'] == 'commerce_line_item_manager') {

      // Build an array containing the line item IDs referenced by this field,
      // accommodating both single and multi-value fields.
      $referenced_line_item_ids = array();
      if ($wrapper->{$field_name} instanceof EntityListWrapper) {
        foreach ($wrapper->{$field_name} as $delta => $line_item_wrapper) {
          try {
            $referenced_line_item_ids[] = $line_item_wrapper->line_item_id
              ->value();
          } catch (EntityMetadataWrapperException $e) {

            // Do nothing, this was a bad reference value.
          }
        }
      }
      elseif (!is_null($wrapper->{$field_name}
        ->value())) {
        try {
          $referenced_line_item_ids[] = $wrapper->{$field_name}->line_item_id
            ->value();
        } catch (EntityMetadataWrapperException $e) {

          // Do nothing, this was a bad reference value.
        }
      }

      // Loop over each line item referenced on this field...
      foreach ($referenced_line_item_ids as $line_item_id) {

        // To determine if it's still an orphan (i.e. no other entities reference
        // this line item through any line item reference field).
        $orphan = TRUE;

        // Loop over each line item reference field to look for references.
        foreach (commerce_info_fields('commerce_line_item_reference') as $key => $value) {
          $query = new EntityFieldQuery();
          $query
            ->fieldCondition($key, 'line_item_id', $line_item_id, '=')
            ->count();

          // If some entity still references this line item through this field...
          if ($query
            ->execute() > 0) {

            // It is not an orphan.
            $orphan = FALSE;
          }
        }

        // If this line item is an orphan, add it to the array of line items to
        // be deleted.
        if ($orphan) {
          $line_item_ids[] = $line_item_id;
        }
      }
    }
  }

  // Delete the line items if any were found.
  if (!empty($line_item_ids)) {
    commerce_line_item_delete_multiple($line_item_ids);
  }
}