You are here

commerce_views_display.module in Commerce Views Display 7

Provides a views display plugin to render an add to cart form

File

commerce_views_display.module
View source
<?php

/**
 * @file
 * Provides a views display plugin to render an add to cart form
 */

/**
 * Implements hook_views_api().
 */
function commerce_views_display_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'commerce_views_display') . '/includes/views',
  );
}

/**
 * Implement hook_theme().
 */
function commerce_views_display_theme($existing, $type, $theme, $path) {
  return array(
    'commerce_views_display_add_to_cart_form' => array(
      'variables' => array(
        'form' => array(),
        'product_display_id' => NULL,
        'view' => NULL,
        'settings' => array(),
      ),
      'file' => 'theme/commerce_views_display.theme.inc',
      'pattern' => 'commerce_views_display_add_to_cart_form__',
    ),
    'commerce_views_display_fields' => array(
      'variables' => array(
        'field_elements' => array(),
        'product_display_id' => NULL,
        'view' => NULL,
        'settings' => array(),
      ),
      'file' => 'theme/commerce_views_display.theme.inc',
      'pattern' => 'commerce_views_display_fields__',
    ),
  );
}

/**
 * Implements hook_form_FORM_ID_alter()
 */
function commerce_views_display_form_commerce_cart_add_to_cart_form_alter(&$form, $form_state, $form_id) {
  if (empty($form_state['context']['commerce_views_display'])) {
    return;
  }
  if (!empty($form['attributes'])) {
    foreach (element_children($form['attributes']) as $attr_key) {
      if (isset($form['attributes'][$attr_key]['#ajax']['callback'])) {
        $form['attributes'][$attr_key]['#ajax']['callback'] = 'commerce_views_display_add_to_cart_form_attributes_refresh';
      }
    }
  }
  if (!empty($form['product_id']) && $form['product_id']['#type'] == 'select' && isset($form['product_id']['#ajax']['callback'])) {
    $form['product_id']['#ajax']['callback'] = 'commerce_views_display_add_to_cart_form_attributes_refresh';
  }
}

/**
 * Ajax callback: returns AJAX commands when an attribute widget is changed.
 */
function commerce_views_display_add_to_cart_form_attributes_refresh($form, $form_state) {
  $commands = array();
  if (empty($form_state['context']['commerce_views_display']['field_displays'])) {
    return commerce_cart_add_to_cart_form_attributes_refresh($form, $form_state);
  }
  $field_displays = $form_state['context']['commerce_views_display']['field_displays'];

  // Render the form afresh to capture any changes to the available widgets
  // based on the latest selection.
  $commands[] = ajax_command_replace('.' . drupal_html_class($form['#form_id']), drupal_render($form));

  // Then render and return the various product fields that might need to be
  // updated on the page.
  if (!empty($form_state['context'])) {
    $product = $form_state['default_product'];
    $product->display_context = $form_state['context'];

    // First render the actual fields attached to the referenced product.
    $product_field_instances = field_info_instances('commerce_product', $product->type);
    foreach ($field_displays as $field_id => $field_display) {
      if (empty($field_display['is_field']) || empty($field_display['field_name'])) {
        continue;
      }
      $product_field_name = $field_display['field_name'];
      if (!isset($product_field_instances[$product_field_name])) {
        continue;
      }

      // Rebuild the same array of classes used when the field was first rendered.
      $replacement_class = commerce_views_display_field_wrapper_replacement_class('commerce_product', $product, $product_field_name, $field_display);
      $element = commerce_views_display_field_view_field('commerce_product', $product, $product_field_name, $field_display);
      $commands[] = ajax_command_replace('.' . $replacement_class, drupal_render($element));
    }

    // Then render the extra fields defined for the referenced product.
    foreach (field_info_extra_fields('commerce_product', $product->type, 'display') as $product_extra_field_name => $product_extra_field) {
      $display = field_extra_fields_get_display('commerce_product', $product->type, $form_state['context']['view_mode']);

      // Only include extra fields that specify a theme function and that
      // are visible on the current view mode.
      if (!empty($product_extra_field['theme']) && !empty($display[$product_extra_field_name]['visible'])) {

        // 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',
          $product_extra_field_name,
        )));
        $classes = array(
          'commerce-product-extra-field',
          drupal_html_class('commerce-product-extra-field-' . $product_extra_field_name),
          $replacement_class,
        );

        // Theme the product extra field to $element.
        $variables = array(
          $product_extra_field_name => $product->{$product_extra_field_name},
          'label' => $product_extra_field['label'] . ':',
          'product' => $product,
        );
        $element = array(
          '#markup' => theme($product_extra_field['theme'], $variables),
          '#attached' => array(
            'css' => array(
              drupal_get_path('module', 'commerce_product') . '/theme/commerce_product.theme.css',
            ),
          ),
          '#prefix' => '<div class="' . implode(' ', $classes) . '">',
          '#suffix' => '</div>',
        );
        $commands[] = ajax_command_replace('.' . $replacement_class, drupal_render($element));
      }
    }
  }

  // Allow other modules to add arbitrary AJAX commands on the refresh.
  drupal_alter('commerce_cart_attributes_refresh', $commands, $form, $form_state);
  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

/**
 * Render a field render array with wrapper using display info
 *
 * @param $display_info
 *   'field_id' => field id usually views field id,
 *   'field_name' => real field name,
 *   'is_field' => TRUE if a field field,
 *   'product_display_id' => unique id of product display / add to cart form wrapper,
 *   'default_view_mode' => fallback display view mode when no display is provided
 *   'display' => An array of display settings
 */
function commerce_views_display_field_view_field($entity_type, $entity, $field_name, $display_info, $value = NULL) {
  $element = array();

  // render field if no value was given
  if (!empty($display_info['is_field'])) {
    if (!empty($display_info['display'])) {
      $element = field_view_field($entity_type, $entity, $field_name, $display_info['display']);
    }
    if (empty($element) && !empty($display_info['default_view_mode'])) {
      $element = field_view_field($entity_type, $entity, $field_name, $display_info['default_view_mode']);
    }
  }
  if (empty($element)) {
    if (isset($value)) {
      $element = array(
        '#markup' => $value,
      );
    }
    else {
      return array();
    }
  }

  // build field wrapper classes
  $wrapper_classes = commerce_views_display_field_wrapper_classes($entity_type, $entity, $field_name, $display_info);

  // wrap element
  $element += array(
    '#prefix' => '<div class="' . implode(' ', $wrapper_classes) . '">',
    '#suffix' => '</div>',
  );
  return $element;
}

/**
 * Return the replacement class basaed on display info
 */
function commerce_views_display_field_wrapper_replacement_class($entity_type, $entity, $field_name, $display_info) {
  if (!empty($display_info['product_display_id']) && !empty($display_info['field_id'])) {
    return drupal_html_class(implode('-', array(
      $display_info['product_display_id'],
      'product',
      $display_info['field_id'],
    )));
  }
  return '';
}

/**
 * Return an array of wrapper classes based on display info
 */
function commerce_views_display_field_wrapper_classes($entity_type, $entity, $field_name, $display_info) {
  $replacement_class = commerce_views_display_field_wrapper_replacement_class($entity_type, $entity, $field_name, $display_info);
  $wrapper_classes = array(
    'commerce-product-field',
    drupal_html_class('commerce-product-field-' . $display_info['field_id']),
    drupal_html_class('field-' . $display_info['field_id']),
    $replacement_class,
  );
  return $wrapper_classes;
}

Functions

Namesort descending Description
commerce_views_display_add_to_cart_form_attributes_refresh Ajax callback: returns AJAX commands when an attribute widget is changed.
commerce_views_display_field_view_field Render a field render array with wrapper using display info
commerce_views_display_field_wrapper_classes Return an array of wrapper classes based on display info
commerce_views_display_field_wrapper_replacement_class Return the replacement class basaed on display info
commerce_views_display_form_commerce_cart_add_to_cart_form_alter Implements hook_form_FORM_ID_alter()
commerce_views_display_theme Implement hook_theme().
commerce_views_display_views_api Implements hook_views_api().