You are here

commerce_pricing_attributes.module in Commerce Pricing Attributes 7

Same filename and directory in other branches
  1. 7.2 commerce_pricing_attributes.module

File

commerce_pricing_attributes.module
View source
<?php

/**
 * Implements hook_enable
 *
 * This is required to ensure that this module
 * hooks are executed after the ones of commerce_product_bundle.
 */
function commerce_pricing_attributes_enable() {
  $weight = db_select('system', 's')
    ->fields('s', array(
    'weight',
  ))
    ->condition('name', 'commerce_product_bundle', '=')
    ->execute()
    ->fetchField();
  if (isset($weight)) {
    db_update('system')
      ->fields(array(
      'weight' => $weight + 1,
    ))
      ->condition('name', 'commerce_pricing_attributes', '=')
      ->execute();
  }
}

/**
 * Implements hook_theme().
 */
function commerce_pricing_attributes_theme($existing, $type, $theme, $path) {
  return array(
    'commerce_pricing_attributes_details' => array(
      'render element' => 'element',
    ),
  );
}

/**
 * Implements hook_field_info();
 */
function commerce_pricing_attributes_field_info() {
  return array(
    'commerce_pricing_attributes' => array(
      'label' => t('Pricing Attributes'),
      'description' => t('This field stores the ID of the option and the price calculation rules.'),
      'settings' => array(),
      'instance_settings' => array(),
      'default_widget' => 'commerce_pricing_attributes_custom_widget',
      'default_formatter' => 'commerce_pricing_attributes_form',
      'property_type' => 'commerce_pricing_attributes',
      'property_callbacks' => array(
        'commerce_pricing_attributes_property_info_callback',
      ),
    ),
  );
}

/**
 * Callback to alter the property info of commerce_pricing_attributes fields.
 *
 * @see commerce_pricing_attributes_field_info().
 */
function commerce_pricing_attributes_property_info_callback(&$info, $entity_type, $field, $instance, $field_type) {
  $name = $field['field_name'];
  $property =& $info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name];
  $property['type'] = $field['cardinality'] != 1 ? 'list<commerce_pricing_attributes>' : 'commerce_pricing_attributes';
  $property['getter callback'] = 'entity_metadata_field_verbatim_get';
  $property['setter callback'] = 'entity_metadata_field_verbatim_set';
  $property['auto creation'] = 'commerce_pricing_attributes_field_data_auto_creation';
  $property['property info'] = commerce_pricing_attributes_field_data_property_info();
  unset($property['query callback']);
}

/**
 * Returns the default array structure for a commerce_pricing_attributes
 * field for use when creating new data arrays through an entity
 * metadata wrapper.
 */
function commerce_pricing_attributes_field_data_auto_creation() {
  return array(
    'set_id' => '',
    'set_details' => array(),
  );
}

/**
 * Defines info for the properties of the commerce_pricing_attributes
 * field data structure.
 */
function commerce_pricing_attributes_field_data_property_info($name = NULL) {
  return array(
    'set_id' => array(
      'label' => t('Option Set'),
      'description' => !empty($name) ? t('Option Set ID of field %name', array(
        '%name' => $name,
      )) : '',
      'type' => 'text',
      'getter callback' => 'entity_property_verbatim_get',
      'setter callback' => 'entity_property_verbatim_set',
      'options list' => 'commerce_pricing_attributes_option_set_list',
    ),
  );
}

/**
 * Returns an array list of option sets.
 */
function commerce_pricing_attributes_option_set_list() {

  // Retrieve the option sets.
  $list = commerce_option_get_sets();

  // Iterate through the option sets.
  $options = array();
  foreach ($list as $item) {
    $options[$item->set_id] = $item->name;
  }
  return $options;
}

/**
 * Returns an array of commerce_pricing_attributes field names from a
 * specific entity.
 */
function _commerce_pricing_attributes_get_fields($entity_type, $entity) {
  $commerce_pricing_attibutes_fields = array();

  // Determine the list of instances to iterate on.
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
  $instances = field_info_instances($entity_type, $bundle);
  $fields = field_info_fields();

  // Iterate through the instances and collect results.
  foreach ($instances as $instance) {
    $field_name = $instance['field_name'];

    // If the instance is a commerce_pricing_attributes field with data.
    if ($fields[$field_name]['type'] == 'commerce_pricing_attributes' && isset($entity->{$field_name})) {
      $commerce_pricing_attibutes_fields[] = $field_name;
    }
  }
  return $commerce_pricing_attibutes_fields;
}

/**
 * Converts commerce_pricing_attributes field data to a serialized array.
 */
function _commerce_pricing_attributes_serialize_set_details($entity_type, $entity) {

  // Loop over all the commerce_pricing_attributes fields attached to this entity.
  foreach (_commerce_pricing_attributes_get_fields($entity_type, $entity) as $field_name) {

    // Iterate over the items arrays for each language.
    foreach (array_keys($entity->{$field_name}) as $langcode) {
      $items = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();

      // Serialize data arrays before saving.
      foreach ($items as $delta => $item) {

        // Serialize an existing data array.
        if (!empty($item['set_details']) && is_array($item['set_details'])) {
          $entity->{$field_name}[$langcode][$delta]['set_details'] = serialize($item['set_details']);
        }
      }
    }
  }
}

/**
 * Converts saved commerce_pricin_attributes field data columns back to arrays
 * for use in the rest of the current page request execution.
 */
function _commerce_pricing_attributes_unserialize_set_details($entity_type, $entity) {

  // Loop over all the commerce_pricing_attributes fields attached to this entity.
  foreach (_commerce_pricing_attributes_get_fields($entity_type, $entity) as $field_name) {

    // Iterate over the items arrays for each language.
    foreach (array_keys($entity->{$field_name}) as $langcode) {
      $items = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();

      // For each item in the array, unserialize or initialize its data array.
      foreach ($items as $delta => $item) {

        // If we have a non-array $item['data'], unserialize it.
        if (!empty($item['set_details']) && !is_array($item['set_details'])) {
          $entity->{$field_name}[$langcode][$delta]['set_details'] = unserialize($item['set_details']);
        }
        elseif (empty($item['set_details'])) {
          $entity->{$field_name}[$langcode][$delta]['set_details'] = array();
        }
      }
    }
  }
}

/**
 * Implements hook_field_presave().
 */
function commerce_pricing_attributes_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {

  // If the instance is a commerce_pricing_attributes field.
  if ($field['type'] == 'commerce_pricing_attributes') {
    foreach ($items as $delta => &$value) {

      // Iterate through the set_details if isset.
      if (!empty($value['set_details'])) {
        foreach ($value['set_details'] as $field_name => &$field) {

          // If the field is not enabled remove from list.
          if (!$field['enabled']) {
            unset($value['set_details'][$field_name]);
          }
        }
      }
    }
  }
}

/**
 * Implements hook_field_storage_pre_insert().
 */
function commerce_pricing_attributes_field_storage_pre_insert($entity_type, $entity) {
  _commerce_pricing_attributes_serialize_set_details($entity_type, $entity);
}

/**
 * Implements hook_field_storage_pre_update().
 */
function commerce_pricing_attributes_field_storage_pre_update($entity_type, $entity) {
  _commerce_pricing_attributes_serialize_set_details($entity_type, $entity);
}

/**
 * Implements hook_field_attach_insert().
 */
function commerce_pricing_attributes_field_attach_insert($entity_type, $entity) {
  _commerce_pricing_attributes_unserialize_set_details($entity_type, $entity);
}

/**
 * Implements hook_field_attach_update().
 */
function commerce_pricing_attributes_field_attach_update($entity_type, $entity) {
  _commerce_pricing_attributes_unserialize_set_details($entity_type, $entity);
}

/**
 * Implements hook_field_load().
 */
function commerce_pricing_attributes_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {

  // Convert amounts to their floating point values and deserialize data arrays.
  foreach ($entities as $id => $entity) {
    foreach ($items[$id] as $delta => $item) {

      // Unserialize the data array if necessary.
      if (!empty($items[$id][$delta]['set_details']) && !is_array($items[$id][$delta]['set_details'])) {
        $items[$id][$delta]['set_details'] = unserialize($items[$id][$delta]['set_details']);
      }
      else {
        $items[$id][$delta]['set_details'] = array();
      }
    }
  }
}

/**
 * Implements hook_field_is_empty().
 */
function commerce_pricing_attributes_field_is_empty($item, $field) {

  // set_id = 0 is empty too, which is exactly what we want.
  return empty($item['set_id']) or empty($item['set_details']);
}

/*
 * Implements hook_form_FORM_ID_alter().
 *
 * This is used to remove cardinality from commererce_pricing_attributes fields.
 */
function commerce_pricing_attributes_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
  if ($form['#field']['type'] == 'commerce_pricing_attributes') {
    $form['field']['cardinality']['#default_value'] = 1;
    $form['field']['cardinality']['#access'] = FALSE;
  }
  if ($form['#instance']['entity_type'] == 'commerce_option' and $form['#field']['module'] == 'list') {
    array_unshift($form['#submit'], 'commerce_pricing_attributes_field_ui_field_edit_form_submit');
  }
}

/**
 * Form submission handler for field_ui_field_edit_form().
 */
function commerce_pricing_attributes_field_ui_field_edit_form_submit($form, &$form_state) {
  $instance = $form_state['build_info']['args'][0];
  $_GET['destination'] = 'admin/commerce/products/option-sets/manage/' . $instance['bundle'] . '/fields/' . $instance['field_name'] . '/pricing_attribute_settings';
  if (!isset($instance['settings']['commerce_pricing_attributes'])) {
    $instance['settings']['commerce_pricing_attributes'] = array();
    $form_state['values']['instance']['settings']['commerce_pricing_attributes'] = array();
    $form_state['values']['instance']['settings']['commerce_pricing_attributes']['_none']['weight'] = -100;
  }
  $i = 0;
  foreach ($form_state['values']['field']['settings']['allowed_values'] as $option_value => $option_label) {
    if (array_key_exists($option_value, $instance['settings']['commerce_pricing_attributes'])) {
      $form_state['values']['instance']['settings']['commerce_pricing_attributes'][$option_value] = $instance['settings']['commerce_pricing_attributes'][$option_value];
    }
    else {
      $form_state['values']['instance']['settings']['commerce_pricing_attributes'][$option_value] = array(
        'enabled' => TRUE,
        'price_op' => 'plus',
        'price' => 0,
        'calculate' => 'per_item',
        'weight' => 100,
      );
      $i++;
    }
  }
}

/**
 * Implements hook_field_widget_info().
 */
function commerce_pricing_attributes_field_widget_info() {
  return array(
    'commerce_pricing_attributes_custom_widget' => array(
      'label' => t('Pricing Attributes Widget'),
      'description' => t('Display the list of option sets in a way that you can customize the settings and define pricing rules.'),
      'field types' => array(
        'commerce_pricing_attributes',
      ),
    ),
  );
}

/**
 * Implements hook_field_widget_form().
 */
function commerce_pricing_attributes_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  if ($instance['widget']['type'] == 'commerce_pricing_attributes_custom_widget') {

    // Get the option set list.
    $option_sets = commerce_option_get_sets();
    $options = array(
      '' => t('none'),
    );
    foreach ($option_sets as $set) {
      $options[$set->set_id] = $set->name;
    }
    $element_replacement = drupal_html_class(implode('-', array(
      'commerce-pricing-attributes-set-details',
      $element['#field_name'],
      $delta,
    )));

    // Element to select option set.
    $element['set_id'] = $element + array(
      '#type' => 'select',
      '#default_value' => isset($items[$delta]['set_id']) ? $items[$delta]['set_id'] : NULL,
      '#attributes' => array(
        'class' => array(
          'commerce-pricing-attributes',
        ),
      ),
      '#options' => $options,
      '#ajax' => array(
        'callback' => 'commerce_pricing_attributes_widget_set_form_callback',
        'wrapper' => $element_replacement,
        'method' => 'html',
      ),
    );

    // The container of the set details.
    $element['set_details'] = array(
      '#type' => 'container',
      '#attributes' => array(
        'id' => $element_replacement,
        'class' => array(
          'commerce-pricing-attributes-set-details',
        ),
      ),
      '#weight' => 999,
    );
    if (isset($form_state['triggering_element']) and isset($form_state['triggering_element']['#field_name']) and $form_state['triggering_element']['#field_name'] == $element['#field_name']) {

      // Get submitted values from the ajax request.
      $element_state = drupal_array_get_nested_value($form_state['values'], $element['#field_parents']);

      // Get the selected set_id.
      $items[$delta] = array();
      if (!empty($element_state[$element['#field_name']][$langcode][$delta]['set_id'])) {
        $items[$delta]['set_id'] = $element_state[$element['#field_name']][$langcode][$delta]['set_id'];
        $items[$delta]['set_details'] = array();
      }

      // Get the selected set_details.
      if (!empty($element_state[$element['#field_name']][$langcode][$delta]['set_details'])) {
        $items[$delta]['set_details'] = $element_state[$element['#field_name']][$langcode][$delta]['set_details'];
      }
    }

    // If set_id is selected.
    if (isset($items[$delta]) and !empty($items[$delta]['set_id'])) {

      // Retrieve the fields of the selected option set.
      $option_fields = field_info_instances('commerce_option', $items[$delta]['set_id']);

      // Iterate through the fields of the selected option set.
      foreach ($option_fields as $option_field_name => $option_field_instance) {

        // Get field settings.
        $option_field = field_info_field($option_field_name);
        $element['set_details'][$option_field_name] = array(
          '#type' => 'container',
          '#attributes' => array(
            'class' => array(
              'commerce-pricing-attributes-set-details-item',
            ),
          ),
        );
        $option_replacement = drupal_html_class(implode('-', array(
          $element['#field_name'],
          $delta,
          $option_field_instance['id'],
        )));
        $element['set_details'][$option_field_name]['enabled'] = array(
          '#type' => 'checkbox',
          '#title' => $option_field_instance['label'],
          '#title_display' => 'after',
          '#return_value' => 1,
          '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['enabled']) ? $items[$delta]['set_details'][$option_field_name]['enabled'] : 0,
          '#attributes' => array(
            'class' => array(
              'commerce-pricing-attributes-set-details-item-enabled',
            ),
          ),
          '#field_name' => $element['#field_name'],
          '#ajax' => array(
            'callback' => 'commerce_pricing_attributes_widget_set_form_option_callback',
            'wrapper' => 'commerce-pricing-attributes-set-details-options-' . $option_replacement,
            'method' => 'replace',
            'progress' => 'none',
          ),
        );
        $element['set_details'][$option_field_name]['required'] = array(
          '#type' => 'checkbox',
          '#title' => t('Required'),
          '#title_display' => 'after',
          '#return_value' => 1,
          '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['required']) ? $items[$delta]['set_details'][$option_field_name]['required'] : 0,
        );
        $element['set_details'][$option_field_name]['show_values'] = array(
          '#type' => 'checkbox',
          '#title' => t('Show price values in the attributes list'),
          '#title_display' => 'after',
          '#return_value' => 1,
          '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['show_values']) ? $items[$delta]['set_details'][$option_field_name]['show_values'] : 0,
        );

        // If field type is list, we need to enable option selection.
        if ($option_field['module'] == 'list') {

          // Get the default settings for this field.
          $defaults = $option_field_instance['settings']['commerce_pricing_attributes'];
          $element['set_details'][$option_field_name]['show_hide'] = array(
            '#type' => 'container',
            'markup' => array(
              '#markup' => '<span class="commerce-pricing-attributes-set-details-item-show">' . t('Show Advanced Settings') . '</span><span class="commerce-pricing-attributes-set-details-item-hide" style="display:none;">' . t('Hide Advanced Settings') . '</span>',
            ),
            '#attributes' => array(
              'class' => array(
                'form-item',
              ),
            ),
            '#id' => 'commerce-pricing-attributes-set-details-show-hide-' . $option_replacement,
          );
          $element['set_details'][$option_field_name]['options'] = array(
            '#type' => 'container',
            '#attributes' => array(
              'class' => array(
                'commerce-pricing-attributes-set-details-options',
              ),
              'id' => 'commerce-pricing-attributes-set-details-options-' . $option_replacement,
            ),
          );

          // If the field is enabled then remove show/hide links.
          if ($element['set_details'][$option_field_name]['enabled']['#default_value'] == 0) {

            //$element['set_details'][$option_field_name]['show_values']['style'] = 'display:none';
            $element['set_details'][$option_field_name]['show_hide']['#attributes']['style'] = 'display:none';
            continue;
          }
          $element['set_details'][$option_field_name]['options']['#theme'] = 'commerce_pricing_attributes_details';

          // Get the field options.
          $options = list_allowed_values($option_field, $option_field_instance);

          // Add default value.
          $options = array(
            '_none' => t('- Select -'),
          ) + $options;

          // Iterate over default field options.
          foreach ($options as $option_value => $option_key) {
            $option_value = (string) $option_value;
            $option_value_replacement = drupal_html_class(implode('-', array(
              $element['#field_name'],
              $delta,
              $option_field_instance['id'],
              $option_value,
            )));

            // If the field type is boolean list and doesn't have labels defined.
            if (empty($option_key)) {
              $option_key = $option_value;
            }

            // If option is _none then handle it in adifferent way.
            if ($option_value === '_none') {
              $element['set_details'][$option_field_name]['options'][$option_value]['enabled'] = array(
                '#markup' => $option_key,
              );
            }
            else {
              $element['set_details'][$option_field_name]['options'][$option_value]['enabled'] = array(
                '#type' => 'checkbox',
                '#title' => $option_key,
                '#title_display' => 'after',
                '#return_value' => 1,
                '#id' => 'commerce-pricing-attributes-set-details-options-' . $option_value_replacement . '-enabled',
                '#attributes' => array(
                  'class' => array(
                    'commerce-pricing-attributes-set-details-options-enabled',
                  ),
                ),
                '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['options'][$option_value]['enabled']) ? $items[$delta]['set_details'][$option_field_name]['options'][$option_value]['enabled'] : $defaults[$option_value]['enabled'],
              );
            }

            // The element that handles the default option value.
            // for various cardinality settings.
            if ($option_field['cardinality'] == 1) {

              // If deafult_value is array then unset it.
              if (isset($items[$delta]['set_details'][$option_field_name]['default']) and is_array($items[$delta]['set_details'][$option_field_name]['default'])) {
                $items[$delta]['set_details'][$option_field_name]['default'] = NULL;
              }
              $element['set_details'][$option_field_name]['options'][$option_value]['default'] = array(
                '#type' => 'radio',
                '#parents' => array_merge($element['#field_parents'], array(
                  $element['#field_name'],
                  $element['#language'],
                  $element['#delta'],
                  'set_details',
                  $option_field_name,
                  'default',
                )),
                '#return_value' => $option_value,
                '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['default']) ? $items[$delta]['set_details'][$option_field_name]['default'] : NULL,
                '#id' => 'commerce-pricing-attributes-set-details-options-' . $option_value_replacement . '-default',
              );
              if ($option_value === '_none' and !isset($items[$delta]['set_details'][$option_field_name]['options'][$option_value]['default'])) {
                $element['set_details'][$option_field_name]['options'][$option_value]['default']['#default_value'] = TRUE;
              }
            }
            else {
              if ($option_value !== '_none') {
                $element['set_details'][$option_field_name]['options'][$option_value]['default'] = array(
                  '#type' => 'checkbox',
                  '#parents' => array_merge($element['#field_parents'], array(
                    $element['#field_name'],
                    $element['#language'],
                    $element['#delta'],
                    'set_details',
                    $option_field_name,
                    'default',
                    $option_value,
                  )),
                  '#return_value' => 1,
                  '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['default'][$option_value]) ? $items[$delta]['set_details'][$option_field_name]['default'][$option_value] : NULL,
                  '#id' => 'commerce-pricing-attributes-set-details-options-' . $option_value_replacement . '-default',
                );
              }
              else {

                // If the field's cardinality is not 1 then hide _none option's
                // default value selection element.
                $element['set_details'][$option_field_name]['options'][$option_value]['default']['#access'] = FALSE;
                $element['set_details'][$option_field_name]['options'][$option_value]['default']['#default_value'] = FALSE;
              }
            }

            // If the option is disabled then it cannot be default option.
            if ($option_value !== '_none' and $element['set_details'][$option_field_name]['options'][$option_value]['enabled']['#default_value'] == 0) {
              $element['set_details'][$option_field_name]['options'][$option_value]['default']['#disabled'] = TRUE;
            }

            // If the option is the default then price and price_op elements are
            // not needed.
            if ($option_value === '_none') {
              $element['set_details'][$option_field_name]['options'][$option_value]['price_op'] = array();
              $element['set_details'][$option_field_name]['options'][$option_value]['price'] = array();
            }
            else {
              $element['set_details'][$option_field_name]['options'][$option_value]['price_op'] = array(
                '#type' => 'select',
                '#options' => array(
                  'plus' => '+',
                  'minus' => '-',
                ),
                '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['options'][$option_value]['price_op']) ? $items[$delta]['set_details'][$option_field_name]['options'][$option_value]['price_op'] : $defaults[$option_value]['price_op'],
              );

              // Load the default currency for this instance.
              $default_currency_code = commerce_default_currency();
              $element['set_details'][$option_field_name]['options'][$option_value]['price'] = array(
                '#type' => 'textfield',
                '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['options'][$option_value]['price']) ? commerce_currency_amount_to_decimal($items[$delta]['set_details'][$option_field_name]['options'][$option_value]['price'], $default_currency_code) : commerce_currency_amount_to_decimal($defaults[$option_value]['price'], $default_currency_code),
                '#required' => TRUE,
                '#size' => 10,
              );

              // Build a currency options list from all enabled currencies.
              $options = array();
              foreach (commerce_currencies(TRUE) as $currency_code => $currency) {
                $options[$currency_code] = check_plain($currency['code']);
              }

              // If only one currency option is available, don't use a select list.
              if (count($options) == 1) {
                $currency_code = key($options);
                $element['set_details'][$option_field_name]['options'][$option_value]['price']['#field_suffix'] = $currency_code;
                $element['set_details'][$option_field_name]['options'][$option_value]['currency_code'] = array(
                  '#type' => 'value',
                  '#default_value' => $currency_code,
                );
              }
              else {
                $element['set_details'][$option_field_name]['options'][$option_value]['currency_code'] = array(
                  '#type' => 'select',
                  '#options' => $options,
                  '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['options'][$option_value]['currency_code']) ? $items[$delta]['set_details'][$option_field_name]['options'][$option_value]['currency_code'] : $default_currency_code,
                );
              }

              // Initiate calculate setting if not set.
              if (!isset($defaults[$option_value]['calculate'])) {
                $defaults[$option_value]['calculate'] = 'per_item';
              }
              $element['set_details'][$option_field_name]['options'][$option_value]['calculate'] = array(
                '#type' => 'select',
                '#options' => array(
                  'per_order' => t('per order'),
                  'per_item' => t('per item'),
                ),
                '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['options'][$option_value]['calculate']) ? $items[$delta]['set_details'][$option_field_name]['options'][$option_value]['calculate'] : $defaults[$option_value]['calculate'],
              );
            }
            $element['set_details'][$option_field_name]['options'][$option_value]['weight'] = array(
              '#type' => 'item',
              '#input' => TRUE,
              '#delta' => 100,
              '#default_value' => isset($items[$delta]['set_details'][$option_field_name]['options'][$option_value]['weight']) ? $items[$delta]['set_details'][$option_field_name]['options'][$option_value]['weight'] : 0,
              '#process' => array(
                'form_process_weight',
              ),
              '#attributes' => array(
                'class' => array(
                  'commerce-pricing-attributes-set-details-options-weight',
                ),
              ),
            );
          }
        }
      }
    }

    // Add css and js for the widget.
    $element['#attached']['css'][] = drupal_get_path('module', 'commerce_pricing_attributes') . '/commerce_pricing_attributes.css';
    $element['#attached']['js'][] = drupal_get_path('module', 'commerce_pricing_attributes') . '/commerce_pricing_attributes.js';

    // Custom validation over the submitted element values.
    $element['#element_validate'][] = 'commerce_pricing_attributes_widget_validate';
  }
  return $element;
}

/**
 * Form validation handler for commerce_pricing_attributes_field_widget_form().
 */
function commerce_pricing_attributes_widget_validate($element, &$form_state) {

  // If set_id is not empty.
  if (!empty($element['set_id']['#value'])) {
    $enabled_fields = 0;

    // If set_details is not empty.
    if (!empty($element['set_details'])) {

      // Iterate through the fields of the option set.
      foreach (element_children($element['set_details']) as $field_name) {

        // If field is enabled increment count variable.
        if ($element['set_details'][$field_name]['enabled']['#value']) {
          $enabled_fields++;
        }

        // If field options exists then validate.
        if (!empty($element['set_details'][$field_name]['options'])) {
          foreach (element_children($element['set_details'][$field_name]['options']) as $option) {
            if ($option === '_none') {
              continue;
            }

            // An option can not be disables and deafult value at the same time.
            if (!$element['set_details'][$field_name]['options'][$option]['enabled']['#value'] and ($element['set_details'][$field_name]['options'][$option]['default']['#value'] == $option and $element['set_details'][$field_name]['options'][$option]['default']['#type'] == 'radio' or $element['set_details'][$field_name]['options'][$option]['default']['#value'] == 1 and $element['set_details'][$field_name]['options'][$option]['default']['#type'] == 'checkbox')) {
              form_error($element['set_id'], t('You have selected as default value of the option set "%option_set" a disabled option. Please enable the option or change the default option.', array(
                '%option_set' => $element['set_id']['#options'][$element['set_id']['#value']],
              )));
            }

            // Price value must be numeric.
            if (!is_numeric($element['set_details'][$field_name]['options'][$option]['price']['#value'])) {
              form_error($element['set_details'][$field_name]['options'][$option]['price'], t('%title: you must enter a numeric value for the price amount.', array(
                '%title' => $element['set_id']['#options'][$element['set_id']['#value']],
              )));
            }
            else {
              form_set_value($element['set_details'][$field_name]['options'][$option]['price'], commerce_currency_decimal_to_amount($element['set_details'][$field_name]['options'][$option]['price']['#value'], $element['set_details'][$field_name]['options'][$option]['currency_code']['#value']), $form_state);
            }
          }
        }
      }
    }

    // If all fields are disabled then throw an error.
    if (!$enabled_fields) {
      form_error($element['set_id'], t('Option set "%option_set" must have at least one field eneabled.', array(
        '%option_set' => $element['set_id']['#options'][$element['set_id']['#value']],
      )));
    }
  }
}

/**
 * Ajax callback for commerce_pricing_attributes_field_widget_form options().
 */
function commerce_pricing_attributes_widget_set_form_option_callback($form, $form_state) {

  // Get the submitted values.
  $parents = array_slice($form_state['triggering_element']['#array_parents'], 0, -1);
  $element_state = drupal_array_get_nested_value($form_state['values'], $parents);

  // Get the form elements "options" and "show_hide" in order to use them later.
  $options = drupal_array_get_nested_value($form, array_merge($parents, array(
    'options',
  )));
  $show_hide_id = drupal_array_get_nested_value($form, array_merge($parents, array(
    'show_hide',
    '#id',
  )));
  $commands = array();

  // Replace command of the curren't field set_details area.
  $commands[] = ajax_command_replace('#' . $form_state['triggering_element']['#ajax']['wrapper'], drupal_render($options));

  // If enabling a field then display show/hide buttons and open by default the details setttings.
  if ($element_state['enabled'] == 1) {
    $commands[] = ajax_command_css('#' . $show_hide_id, array(
      'display' => 'inline',
    ));
    $commands[] = ajax_command_css('#' . $show_hide_id . ' .commerce-pricing-attributes-set-details-item-hide', array(
      'display' => 'inline',
    ));
    $commands[] = ajax_command_css('#' . $show_hide_id . ' .commerce-pricing-attributes-set-details-item-show', array(
      'display' => 'none',
    ));
    $commands[] = ajax_command_css('#' . $form_state['triggering_element']['#ajax']['wrapper'], array(
      'display' => 'block',
    ));
  }
  else {
    $commands[] = ajax_command_css('#' . $show_hide_id, array(
      'display' => 'none',
    ));
  }
  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

/**
 * Ajax callback for commerce_pricing_attributes_field_widget_form().
 */
function commerce_pricing_attributes_widget_set_form_callback($form, $form_state) {
  $parents = array_slice($form_state['triggering_element']['#array_parents'], 0, -1);
  return drupal_array_get_nested_value($form, array_merge($parents, array(
    'set_details',
  )));
}

/**
 * Theme function of set_details sortable table.
 */
function theme_commerce_pricing_attributes_details($variables) {
  $output = '';
  $rows = array();
  $i = 0;
  $display_default = isset($variables['element']['#display_default']) ? $variables['element']['#display_default'] : TRUE;
  foreach (element_children($variables['element']) as $item) {
    $cells = array(
      render($variables['element'][$item]['enabled']),
      render($variables['element'][$item]['default']),
      render($variables['element'][$item]['price_op']) . render($variables['element'][$item]['price']) . render($variables['element'][$item]['currency_code']) . render($variables['element'][$item]['calculate']),
      render($variables['element'][$item]['weight']),
    );
    if (!$display_default) {
      unset($cells[1]);
    }
    $rows[$i] = array(
      'data' => $cells,
      'class' => array(),
      'weight' => $variables['element'][$item]['weight']['#default_value'],
    );
    if ($item !== '_none') {
      $rows[$i]['class'][] = 'draggable';
    }
    else {
      $rows[$i]['weight'] = -999999;
    }
    $i++;
  }
  uasort($rows, 'drupal_sort_weight');
  $header = array(
    t('Default'),
    t('Price Calculation'),
    '',
  );
  if (!$display_default) {
    unset($header[1]);
  }

  // Support for table select all/none.
  drupal_add_js('misc/tableselect.js');
  array_unshift($header, array(
    'class' => array(
      'select-all',
    ),
    'data' => t('Options'),
  ));
  $output .= theme('table', array(
    'header' => $header,
    'rows' => $rows,
    'attributes' => array(
      'id' => $variables['element']['#id'] . '-table',
    ),
  ));
  drupal_add_tabledrag($variables['element']['#id'] . '-table', 'order', 'sibling', 'commerce-pricing-attributes-set-details-options-weight');
  return $output;
}

/**
 * Implements hook_field_formatter_info().
 */
function commerce_pricing_attributes_field_formatter_info() {
  return array(
    'commerce_pricing_attributes_form' => array(
      'label' => t('Option Set: Form'),
      'description' => t('Display a form for the customer to enter the options.'),
      'field types' => array(
        'commerce_pricing_attributes',
      ),
    ),
    'commerce_pricing_attributes_attribute_view' => array(
      'label' => t('Option Set: Attribute View'),
      'description' => t('Display the options as attribute view..'),
      'field types' => array(
        'commerce_pricing_attributes',
      ),
    ),
  );
}

/**
 * Empty formatter of commerce_pricing_attributes field.
 *
 * @todo create a field formatter with a table of available options.
 */
function commerce_pricing_attributes_field_formatter_view($entity_type, $object, $field, $instance, $langcode, $items, $display) {
  $result = array();
  return $result;
}

/**
 * Implementation of hook_form_alter()
 *
 * Here we modify the add to cart form.
 */
function commerce_pricing_attributes_form_alter(&$form, &$form_state, $form_id) {
  if (strstr($form_id, 'commerce_cart_add_to_cart_form')) {
    if (isset($form_state['default_product'])) {
      $current_product = $form_state['default_product'];
    }
    elseif (isset($form_state['products'])) {
      $current_product = reset($form_state['products']);
    }
    else {
      return;
    }
    $someFieldIsAdded = false;
    $options = array();
    if (isset($form_state['line_item']->line_item_id) && $form_state['line_item']->line_item_id > 0 && commerce_product_attributes_access_to_line_item($form_state['line_item']->line_item_id)) {

      // We need to reduce the number of options. We can only have one option per product
      // and per product field and line item. This limits us only in the fact that we can
      // have one option set per one option set reference field.
      foreach (commerce_option_load_by_line_item($form_state['line_item']->line_item_id) as $key => $option) {
        $options[$option->set_id][$option->product_id][$option->field_name][$option->field_delta] = $option;
      }
    }

    // Iterates of the fields of this product. We search for
    // option set reference fields.
    foreach ($current_product as $field_name => $field) {
      $field_info = field_info_field($field_name);
      $type = $field_info['type'];
      if ($type == 'commerce_pricing_attributes') {
        $form[$field_name] = array(
          '#tree' => TRUE,
        );
        $lang_code = field_language('commerce_product', $current_product, $field_name);
        if (isset($field[$lang_code])) {
          foreach ($field[$lang_code] as $delta => $set_id) {
            if (count($options) > 0 && isset($options[$set_id['set_id']][$current_product->product_id][$field_name][$delta])) {
              $option = $options[$set_id['set_id']][$current_product->product_id][$field_name][$delta];
            }
            else {
              $option = entity_create('commerce_option', $set_id);
            }
            $form_state['commerce_option'][$field_name][$delta]['option'] = $option;
            $form[$field_name][$delta] = array(
              '#parents' => array(
                $field_name,
                $delta,
              ),
            );
            field_attach_form('commerce_option', $option, $form[$field_name][$delta], $form_state);
            $someFieldIsAdded = true;
          }
        }
      }
    }

    // TODO: Implement the multi options functionality to the bundle integration
    if (isset($form_state['bundle'])) {
      foreach ($form_state['bundle'] as $id => &$bundle_set) {
        $sub_product = $form_state['bundle'][$id]['default_product'];
        $sub_product_wrapper = entity_metadata_wrapper('commerce_product', $sub_product);
        $form[$id] = array(
          '#tree' => TRUE,
        );

        // Iterates of the fields of this product. We search for
        // option set reference fields.
        foreach ($sub_product as $field_name => $field) {
          $field_info = field_info_field($field_name);
          $type = $field_info['type'];
          $form[$id][$field_name] = array(
            '#tree' => TRUE,
          );
          if ($type == 'commerce_pricing_attributes') {
            $lang_code = field_language('commerce_product', $sub_product, $field_name);
            if (isset($field[$lang_code])) {
              foreach ($field[$lang_code] as $delta => $set_id) {
                if (count($options) > 0 && isset($options[$set_id['set_id']][$current_product->product_id][$field_name][$delta])) {
                  $option = $options[$set_id['set_id']][$sub_product->product_id][$field_name][$delta];
                }
                else {
                  $option = entity_create('commerce_option', $set_id);
                }
                $form_state[$id]['commerce_option'][$field_name][$delta]['option'] = $option;
                $form[$id][$field_name][$delta] = array(
                  '#parents' => array(
                    $id,
                    $field_name,
                    $delta,
                  ),
                );
                field_attach_form('commerce_option', $option, $form[$id][$field_name][$delta], $form_state);
                $someFieldIsAdded = true;
              }
            }
          }
        }
      }
    }
    if ($someFieldIsAdded) {
      $form['#submit'][] = 'commerce_pricing_attributes_add_to_cart_submit';
    }
  }
}

/**
 * Cart submit callback function. This is required to create / update
 * the option related to the line item.
 *
 * @param $form Form array
 * @param $form_state The form state array.
 * @return void
 */
function commerce_pricing_attributes_add_to_cart_submit($form, $form_state) {
  if (isset($form_state['default_product'])) {
    $current_product = $form_state['default_product'];
  }
  elseif (isset($form_state['products'])) {
    $current_product = reset($form_state['products']);
  }
  else {
    return;
  }
  $options = array();
  if (isset($form_state['line_item']->line_item_id) && $form_state['line_item']->line_item_id > 0 && commerce_product_attributes_access_to_line_item($form_state['line_item']->line_item_id)) {

    // We need to reduce the number of options. We can only have one option per product
    // and per product field and line item. This limits us only in the fact that we can
    // have one option set per one option set reference field.
    foreach (commerce_option_load_by_line_item($form_state['line_item']->line_item_id) as $key => $option) {
      $options[$option->set_id][$option->product_id][$option->field_name][$option->field_delta] = $option;
    }
  }
  foreach ($current_product as $field_name => $field) {
    $field_info = field_info_field($field_name);
    $type = $field_info['type'];
    if (isset($form_state['bundle'])) {
      foreach ($form_state['bundle'] as $id => &$bundle_set) {
        $sub_product = $form_state['bundle'][$id]['default_product'];
        $sub_product_wrapper = entity_metadata_wrapper('commerce_product', $sub_product);

        // Iterates of the fields of this product. We search for
        // option set reference fields.
        foreach ($sub_product as $field_name => $field) {
          $field_info = field_info_field($field_name);
          $type = $field_info['type'];
          if ($type == 'commerce_pricing_attributes') {
            $lang_code = field_language('commerce_product', $sub_product, $field_name);
            foreach ($field[$lang_code] as $delta => $set_id) {
              if (count($options) > 0 && isset($options[$set_id['set_id']][$current_product->product_id][$field_name][$delta])) {
                $option = $options[$set_id['set_id']][$sub_product->product_id][$field_name][$delta];
              }
              else {
                $option = $form_state[$id]['commerce_option'][$field_name][$delta];
              }

              // Notify field widgets.
              field_attach_submit('commerce_option', $option, $form[$id][$field_name][$delta], $form_state);

              //$option->line_item_id = $form_state['bundle_product_line_items'][$sub_product_wrapper->product_id->value()]->line_item_id;
              $option->line_item_id = $form_state['line_item']->line_item_id;
              $option->field_name = $field_name;
              $option->field_delta = $delta;
              $option->product_id = $sub_product->product_id;

              // Save the product.
              commerce_option_save($option);
            }
          }
        }
      }
    }
    else {
      if ($type == 'commerce_pricing_attributes') {
        $lang_code = field_language('commerce_product', $current_product, $field_name);
        foreach ($field[$lang_code] as $delta => $set_id) {
          if (count($options) > 0 && isset($options[$set_id['set_id']][$current_product->product_id][$field_name][$delta])) {
            $option = $options[$set_id['set_id']][$current_product->product_id][$field_name][$delta];
          }
          else {
            $option = $form_state['commerce_option'][$field_name][$delta]['option'];
          }

          // Notify field widgets. // entity_form_submit_build_entity
          field_attach_submit('commerce_option', $option, $form[$field_name][$delta], $form_state);
          $option->line_item_id = $form_state['line_item']->line_item_id;
          $option->field_name = $field_name;
          $option->field_delta = $delta;
          $option->product_id = $current_product->product_id;

          // Save the product.
          commerce_option_save($option);
        }
      }
    }
  }
}

/**
 * Implements hook_field_attach_form().
 */
function commerce_pricing_attributes_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {

  // If the field is of type "commerce_pricing_attributes".
  if ($entity_type == 'commerce_option' and isset($entity->set_details)) {

    // If there are more than one product reset the form value on product change.
    if (isset($form_state['triggering_element']) and $form_state['triggering_element']['#name'] == 'product_id') {
      $form_state['values'][$form['#parents'][0]] = array();
      $form_state['input'][$form['#parents'][0]] = array();
    }

    // Iterate through the fields of the form.
    foreach (element_children($form) as $field_name) {
      $langcode = $form[$field_name]['#language'];

      // If the field is enabled for this product.
      if (isset($entity->set_details[$field_name]) and $entity->set_details[$field_name]['enabled']) {
        $form[$field_name][$langcode]['#required'] = (bool) $entity->set_details[$field_name]['required'];
        $display = (bool) $entity->set_details[$field_name]['show_values'];

        // If the field has options.
        if (isset($entity->set_details[$field_name]['options']) and !empty($entity->set_details[$field_name]['options'])) {
          $options = array();

          // If - None - value is deafult.
          if ($entity->set_details[$field_name]['default'] === '_none' || $entity->set_details[$field_name]['default'] == '') {
            $options['_none'] = t('- None -');
          }

          // sort the field's options.
          uasort($entity->set_details[$field_name]['options'], 'drupal_sort_weight');

          // Iterate through the field's options.
          foreach ($entity->set_details[$field_name]['options'] as $option_value => $option) {
            if ($option_value === '_none') {
              continue;
            }

            // If the option is enabled.
            if ($option['enabled']) {

              // switch the price operator sign.
              switch ($option['price_op']) {
                case 'plus':
                  $sign = '+';
                  break;
                case 'minus':
                  $sign = '-';
                  break;
                default:
                  $sign = '';
                  break;
              }
              $default_currency_code = commerce_default_currency();

              // If the currency of the option price is not set then set the deafult currency.
              if (!isset($option['currency_code']) or empty($option['currency_code'])) {
                $option['currency_code'] = $default_currency_code;
              }

              // Display the price inside the option item.
              if (isset($form[$field_name][$langcode]['#options'])) {
                $options[$option_value] = $form[$field_name][$langcode]['#options'][$option_value];
                if ($option['price'] > 0 and $display) {
                  $options[$option_value] .= ' (' . $sign . commerce_currency_format($option['price'], $option['currency_code']) . ')';
                }
              }
            }
          }

          // Set the options after processed if are set.
          if (isset($form[$field_name][$langcode]['#options'])) {
            $form[$field_name][$langcode]['#options'] = $options;
          }
        }

        // Se the default value if isset.
        if (!isset($entity->set_details[$field_name]['default'])) {
          $entity->set_details[$field_name]['default'] = NULL;
        }
        if (is_array($entity->set_details[$field_name]['default'])) {
          $default_value = array();
          foreach ($entity->set_details[$field_name]['default'] as $key => $value) {
            if ($value) {
              $default_value[] = $key;
            }
          }
          $form[$field_name][$langcode]['#default_value'] = $default_value;
        }
        else {
          $form[$field_name][$langcode]['#default_value'] = $entity->set_details[$field_name]['default'];
        }

        // If a default value is selected then increment.
        if (!empty($form[$field_name][$langcode]['#default_value']) and $form[$field_name][$langcode]['#default_value'] !== '_none') {
          $form[$field_name][$langcode]['#attributes']['class'][] = 'force-refresh';
        }
        $form[$field_name][$langcode]['#ajax'] = array(
          'callback' => 'commerce_pricing_attributes_add_to_cart_form_attributes_refresh',
        );
        $form[$field_name][$langcode]['#attributes']['class'][] = 'commerce-pricing-attributes-item';
      }
      else {
        $form[$field_name]['#access'] = FALSE;
        $form[$field_name][$langcode]['#default_value'] = '';
      }
    }

    // If at least one attribute has default value then update the price.
    $form['#attached']['js'][] = array(
      'data' => '
      (function($){
        Drupal.behaviors.commerce_pricing_attributes_add_to_cart_form = {
          attach: function (context, settings) {
            if($(context).hasClass("commerce-add-to-cart")){
              element = $(context);
            }
            else{
              element = $(context).find(".commerce-add-to-cart");
            }
            element.once(function(){
              $(".commerce-pricing-attributes-item.force-refresh:first", $(this)).trigger("change");
            });
          }
        };
      })(jQuery);
      ',
      'type' => 'inline',
    );
  }
}

/**
 * Ajax callback: returns AJAX commands when an attribute widget is changed.
 */
function commerce_pricing_attributes_add_to_cart_form_attributes_refresh($form, $form_state) {
  $commands = array();
  if (!empty($form_state['default_product']) and !empty($form_state['context'])) {
    $product = $form_state['default_product'];
    $commerce_option_list = array();
    foreach ($form_state['commerce_option'] as $field_name => $field) {
      foreach ($field as $delta => $item) {
        $option = $item['option'];
        field_attach_submit('commerce_option', $option, $form[$field_name][$delta], $form_state);
        $option->field_name = $field_name;
        $option->field_delta = $delta;
        $option->product_id = $product->product_id;
        $commerce_option_list[] = $option;
      }
    }

    // First create a pseudo product line item that we will pass to Rules.
    $line_item = commerce_product_line_item_new($product);
    $line_item->data['commerce_option_list'] = $commerce_option_list;

    // Allow modules to prepare this as necessary.
    drupal_alter('commerce_product_calculate_sell_price_line_item', $line_item);

    // Pass the line item to Rules.
    rules_invoke_event('commerce_product_calculate_sell_price', $line_item);
    $product->commerce_price = $line_item->commerce_unit_price;
    $product->display_context = $form_state['context'];

    // Rebuild the same array of classes used when the field was first rendered.
    $replacement_class = drupal_html_class(implode('-', array(
      $form_state['context']['class_prefix'],
      'product',
      'commerce_price',
      'wrapper',
    )));
    $entity_type = $form_state['context']['entity_type'];
    if (isset($form_state['context']['entity'])) {
      $entity = $form_state['context']['entity'];
    }
    $classes = array();
    foreach (commerce_info_fields('commerce_product_reference', $entity_type) as $field_name => $field) {
      if ($field['cardinality'] != 1) {

        // Construct an array of classes that will be used to theme and
        // target the rendered field for AJAX replacement.
        $classes = array(
          'commerce-product-field',
          drupal_html_class('commerce-product-field-commerce-price'),
          drupal_html_class('field-commerce-price'),
          drupal_html_class(implode('-', array(
            $form_state['context']['class_prefix'],
            'product',
            'commerce_price',
          ))),
        );
      }
    }

    // Set the product as prepared to prevend price recalculation.
    $product->_field_view_prepared = TRUE;

    // Render the commerce price field.
    $element = field_view_field('commerce_product', $product, 'commerce_price', $form_state['context']['view_mode']);
    $element += array(
      '#prefix' => '<div class="' . $replacement_class . '">',
      '#suffix' => '</div>',
    );
    if (!empty($classes)) {
      $element['#prefix'] .= '<div class="' . implode(' ', $classes) . '">';
      $element['#suffix'] .= '</div>';
    }
    $commands[] = ajax_command_replace(' .' . $replacement_class, drupal_render($element));
  }
  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

/**
 * Implements hook_entity_view().
 *
 * Wrap commerce_price elements with a div to achieve ajax refresh on
 * attribute widget change.
 */
function commerce_pricing_attributes_entity_view($entity, $entity_type, $view_mode, $langcode) {
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);

  // If the entity has commerce_price rendered.
  if (isset($entity->content['product:commerce_price'])) {
    $entity->content['product:commerce_price'] += array(
      '#prefix' => '',
      '#suffix' => '',
    );
    $class = drupal_html_class(implode('-', array(
      $entity_type,
      $id,
      'product',
      'commerce_price',
      'wrapper',
    )));
    $entity->content['product:commerce_price']['#prefix'] = '<div class="' . $class . '">' . $entity->content['product:commerce_price']['#prefix'];
    $entity->content['product:commerce_price']['#suffix'] .= '</div>';
  }
}

/**
 * Implements hook_entity_property_info() on top of node module.
 */
function commerce_pricing_attributes_entity_property_info_alter(&$info) {
  $info['commerce_line_item']['properties']['commerce_pricing_attributes'] = array(
    'label' => t('Commerce Pricing Attributes'),
    'type' => 'text',
  );
}

/**
 * Implements hook_entity_load().
 *
 * Create an alias od commerce_pricing_attributes property in line item on load.
 * We need it to use it at card combines.
 */
function commerce_pricing_attributes_entity_load(&$entities, $type) {
  if ($type == 'commerce_line_item') {
    foreach ($entities as &$entity) {
      $entity->commerce_pricing_attributes = array();
      $commerce_options = commerce_option_load_by_line_item($entity->line_item_id);
      foreach ($commerce_options as $commerce_option) {
        $commerce_option_wrapper = entity_metadata_wrapper('commerce_option', $commerce_option);
        $fields = field_info_instances('commerce_option', $commerce_option->set_id);
        foreach ($fields as $field_name => $field) {
          $entity->commerce_pricing_attributes[$commerce_option->set_id][$field_name] = $commerce_option_wrapper->{$field_name}
            ->value();
          asort($entity->commerce_pricing_attributes[$commerce_option->set_id]);
        }
      }
      asort($entity->commerce_pricing_attributes);
      $entity->commerce_pricing_attributes = serialize($entity->commerce_pricing_attributes);
    }
  }
}

/**
 * Implements hook_field_attach_submit().
 *
 * Create an alias od commerce_pricing_attributes property in line item on
 * product add to cart. We need it to use it at card combines.
 */
function commerce_pricing_attributes_field_attach_submit($entity_type, &$entity, $form, &$form_state) {
  if ($entity_type == 'commerce_line_item') {
    if (isset($form_state['default_product'])) {
      $current_product = $form_state['default_product'];
    }
    elseif (isset($form_state['products'])) {
      $current_product = reset($form_state['products']);
    }
    else {
      return;
    }
    $entity->commerce_pricing_attributes = array();
    foreach ($current_product as $field_name => $field) {
      $field_info = field_info_field($field_name);
      $type = $field_info['type'];
      if ($type == 'commerce_pricing_attributes') {
        $lang_code = field_language('commerce_product', $current_product, $field_name);
        if (isset($field[$lang_code])) {
          foreach ($field[$lang_code] as $delta => $set_id) {
            if (!empty($form_state['values'][$field_name])) {
              foreach ($form_state['values'][$field_name][$delta] as $field_name => $values) {
                $entity->commerce_pricing_attributes[$set_id['set_id']][$field_name] = isset($values[$lang_code][0]['value']) ? $values[$lang_code][0]['value'] : '';
              }
              asort($entity->commerce_pricing_attributes[$set_id['set_id']]);
            }
          }
        }
      }
    }
    asort($entity->commerce_pricing_attributes);
    $entity->commerce_pricing_attributes = serialize($entity->commerce_pricing_attributes);
  }
}

/**
 * Implements hook_commerce_cart_product_comparison_properties_alter().
 */
function commerce_pricing_attributes_commerce_cart_product_comparison_properties_alter(&$comparison_properties) {
  $comparison_properties[] = 'commerce_pricing_attributes';
}

/**
 * Implements hook_menu().
 */
function commerce_pricing_attributes_menu() {
  $items = array();
  $items['admin/commerce/products/option-sets/manage/%entity_object/fields/%field_ui_menu/pricing_attribute_settings'] = array(
    'title' => 'Pricing Attributes',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'commerce_pricing_attributes_default_setting_form',
      5,
      7,
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 5,
    'file' => 'commerce_pricing_attributes.admin.inc',
    'access callback' => 'commerce_pricing_attributes_default_setting_access',
    'access arguments' => array(
      'administer option sets',
      5,
      7,
    ),
  );
  return $items;
}
function commerce_pricing_attributes_default_setting_access($access, $entity, $field_instance) {
  if (user_access($access)) {
    $field_info = field_info_field($field_instance['field_name']);
    if ($field_info['module'] == 'list') {
      $options = list_allowed_values($field_info, $field_instance);
      return !empty($options);
    }
  }
  return FALSE;
}

Functions

Namesort descending Description
commerce_pricing_attributes_add_to_cart_form_attributes_refresh Ajax callback: returns AJAX commands when an attribute widget is changed.
commerce_pricing_attributes_add_to_cart_submit Cart submit callback function. This is required to create / update the option related to the line item.
commerce_pricing_attributes_commerce_cart_product_comparison_properties_alter Implements hook_commerce_cart_product_comparison_properties_alter().
commerce_pricing_attributes_default_setting_access
commerce_pricing_attributes_enable Implements hook_enable
commerce_pricing_attributes_entity_load Implements hook_entity_load().
commerce_pricing_attributes_entity_property_info_alter Implements hook_entity_property_info() on top of node module.
commerce_pricing_attributes_entity_view Implements hook_entity_view().
commerce_pricing_attributes_field_attach_form Implements hook_field_attach_form().
commerce_pricing_attributes_field_attach_insert Implements hook_field_attach_insert().
commerce_pricing_attributes_field_attach_submit Implements hook_field_attach_submit().
commerce_pricing_attributes_field_attach_update Implements hook_field_attach_update().
commerce_pricing_attributes_field_data_auto_creation Returns the default array structure for a commerce_pricing_attributes field for use when creating new data arrays through an entity metadata wrapper.
commerce_pricing_attributes_field_data_property_info Defines info for the properties of the commerce_pricing_attributes field data structure.
commerce_pricing_attributes_field_formatter_info Implements hook_field_formatter_info().
commerce_pricing_attributes_field_formatter_view Empty formatter of commerce_pricing_attributes field.
commerce_pricing_attributes_field_info Implements hook_field_info();
commerce_pricing_attributes_field_is_empty Implements hook_field_is_empty().
commerce_pricing_attributes_field_load Implements hook_field_load().
commerce_pricing_attributes_field_presave Implements hook_field_presave().
commerce_pricing_attributes_field_storage_pre_insert Implements hook_field_storage_pre_insert().
commerce_pricing_attributes_field_storage_pre_update Implements hook_field_storage_pre_update().
commerce_pricing_attributes_field_ui_field_edit_form_submit Form submission handler for field_ui_field_edit_form().
commerce_pricing_attributes_field_widget_form Implements hook_field_widget_form().
commerce_pricing_attributes_field_widget_info Implements hook_field_widget_info().
commerce_pricing_attributes_form_alter Implementation of hook_form_alter()
commerce_pricing_attributes_form_field_ui_field_edit_form_alter
commerce_pricing_attributes_menu Implements hook_menu().
commerce_pricing_attributes_option_set_list Returns an array list of option sets.
commerce_pricing_attributes_property_info_callback Callback to alter the property info of commerce_pricing_attributes fields.
commerce_pricing_attributes_theme Implements hook_theme().
commerce_pricing_attributes_widget_set_form_callback Ajax callback for commerce_pricing_attributes_field_widget_form().
commerce_pricing_attributes_widget_set_form_option_callback Ajax callback for commerce_pricing_attributes_field_widget_form options().
commerce_pricing_attributes_widget_validate Form validation handler for commerce_pricing_attributes_field_widget_form().
theme_commerce_pricing_attributes_details Theme function of set_details sortable table.
_commerce_pricing_attributes_get_fields Returns an array of commerce_pricing_attributes field names from a specific entity.
_commerce_pricing_attributes_serialize_set_details Converts commerce_pricing_attributes field data to a serialized array.
_commerce_pricing_attributes_unserialize_set_details Converts saved commerce_pricin_attributes field data columns back to arrays for use in the rest of the current page request execution.