You are here

dc_ajax_add_cart.module in Commerce Ajax Add to Cart 7.2

Same filename and directory in other branches
  1. 8 dc_ajax_add_cart.module
  2. 7 dc_ajax_add_cart.module

Ajax add to cart module.

Allows you to add products AJAX-ically to cart. You can remove products AJAX-ically from cart.

File

dc_ajax_add_cart.module
View source
<?php

/**
 * @file
 * Ajax add to cart module.
 *
 * Allows you to add products AJAX-ically to cart. You can remove products
 * AJAX-ically from cart.
 */

// Variable constants.
define('DC_AJAX_ADD_CART_CHECKOUT_REDIRECT', 'dc_ajax_add_cart_checkout_redirect');
define('DC_AJAX_ADD_CART_SHOW_LABELS', 'dc_ajax_add_cart_show_labels');
define('DC_AJAX_ADD_CART_EMPTY_CART_MESSAGE', 'dc_ajax_add_cart_empty_cart_message');
define('DC_AJAX_ADD_CART_REMOVE_CART', 'dc_ajax_add_cart_remove_cart');
define('DC_AJAX_ADD_CART_HIDE_EMPTY_CART', 'dc_ajax_add_cart_hide_empty_cart');
define('DC_AJAX_ADD_CART_EMPTY_CART_TEASER_MESSAGE', 'dc_ajax_add_cart_empty_cart_teaser_message');
define('DC_AJAX_ADD_CART_ITEM_SUFFIX_TEXT_SINGULAR', 'dc_ajax_add_cart_item_suffix_text_singular');
define('DC_AJAX_ADD_CART_ITEM_SUFFIX_TEXT_PLURAL', 'dc_ajax_add_cart_item_suffix_text_plural');
define('DC_AJAX_ADD_CART_DISPLAY_POPUP', 'dc_ajax_add_cart_display_popup');
define('DC_AJAX_ADD_CART_SUCCESS_MESSAGE', 'dc_ajax_add_cart_success_message');
define('DC_AJAX_ADD_CART_POPUP_PRODUCT_NAME_DISPLAY', 'dc_ajax_add_cart_popup_product_name_display');
define('DC_AJAX_ADD_CART_POPUP_PRODUCT_NAME_LABEL', 'dc_ajax_add_cart_popup_product_name_label');
define('DC_AJAX_ADD_CART_POPUP_PRODUCT_QUANTITY_DISPLAY', 'dc_ajax_add_cart_popup_product_quantity_display');
define('DC_AJAX_ADD_CART_POPUP_PRODUCT_QUANTITY_LABEL', 'dc_ajax_add_cart_popup_product_quantity_label');
define('DC_AJAX_ADD_CART_POPUP_PRODUCT_PRICE_DISPLAY', 'dc_ajax_add_cart_popup_product_price_display');
define('DC_AJAX_ADD_CART_POPUP_PRODUCT_PRICE_LABEL', 'dc_ajax_add_cart_popup_product_price_label');
define('DC_AJAX_ADD_CART_POPUP_PRODUCT_TOTAL_DISPLAY', 'dc_ajax_add_cart_popup_product_total_display');
define('DC_AJAX_ADD_CART_POPUP_PRODUCT_TOTAL_LABEL', 'dc_ajax_add_cart_popup_product_total_label');
define('DC_AJAX_ADD_CART_POPUP_CHECKOUT', 'dc_ajax_add_cart_popup_checkout');
define('DC_AJAX_ADD_CART_POPUP_CONTINUE_SHOPPING', 'dc_ajax_add_cart_popup_continue_shopping');

/**
 * Implements hook_permission().
 */
function dc_ajax_add_cart_permission() {
  return array(
    'administer commerce ajax add to cart' => array(
      'title' => t('Administer Commerce AJAX Add to Cart'),
      'description' => t('Administer Commerce AJAX Add to Cart'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function dc_ajax_add_cart_menu() {
  $items = array();
  $items['remove-product/nojs/%'] = array(
    'title' => 'Remove commerce line item',
    'description' => 'Remove commerce line item',
    'page callback' => 'dc_ajax_add_cart_remove_commerce_line_item',
    'page arguments' => array(
      1,
      2,
    ),
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $items['remove-product/ajax/%'] = array(
    'delivery callback' => 'ajax_deliver',
  ) + $items['remove-product/nojs/%'];
  $items['admin/commerce/config/ajax-cart'] = array(
    'title' => 'AJAX Shopping Cart',
    'description' => 'AJAX Shopping Cart',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'dc_ajax_add_cart_ajax_cart_settings_form',
    ),
    'access arguments' => array(
      'administer commerce ajax add to cart',
    ),
    'file' => 'dc_ajax_add_cart.admin.inc',
    'type' => MENU_NORMAL_ITEM,
    'weight' => 10,
  );
  $items['admin/commerce/config/ajax-cart/default'] = array(
    'title' => 'General settings',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'dc_ajax_add_cart.admin.inc',
  );
  $items['admin/commerce/config/ajax-cart/cart-teaser'] = array(
    'title' => 'Shopping cart teaser',
    'description' => 'Shopping cart teaser',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'dc_ajax_add_cart_cart_teaser_settings_form',
    ),
    'access arguments' => array(
      'administer commerce ajax add to cart',
    ),
    'file' => 'dc_ajax_add_cart.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 20,
  );
  $items['admin/commerce/config/ajax-cart/pop-up-message'] = array(
    'title' => 'Pop up Message',
    'description' => 'Pop up Message',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'dc_ajax_add_cart_popup_message_settings_form',
    ),
    'access arguments' => array(
      'administer commerce ajax add to cart',
    ),
    'file' => 'dc_ajax_add_cart.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 30,
  );
  return $items;
}

/**
 * Menu callback: Removes the product item from cart.
 *
 * @param string $ajax
 *   Page argument, ajaxifies the removal of product from cart.
 * @param int $line_item_id
 *   Line item ID.
 *
 * @return array
 *   Ajax command array for product removal.
 *
 * @see dc_ajax_add_cart_menu()
 */
function dc_ajax_add_cart_remove_commerce_line_item($ajax, $line_item_id) {
  global $user;
  $order = commerce_cart_order_load($user->uid);

  // Initially quantity of products in cart will be zero.
  $quantity = 0;

  // Check whether this is AJAX callback.
  $is_ajax = $ajax === 'ajax';

  // Delete the product line item from cart.
  commerce_cart_order_product_line_item_delete($order, $line_item_id);

  // Get the current status of cart and other information.
  $commerce_cart = dc_ajax_add_cart_get_commerce_cart_details();
  $line_items = $commerce_cart['wrapper']->commerce_line_items;
  $quantity = commerce_line_items_quantity($line_items, commerce_product_line_item_types());
  $total = commerce_line_items_total($line_items);
  if ($is_ajax) {

    // Update the cart content.
    $commands = array();

    // Check whether the user has any product in cart.
    if (variable_get(DC_AJAX_ADD_CART_HIDE_EMPTY_CART, 0) && $quantity == 0) {
      $content_cart = '';
    }
    else {
      $content_cart = theme('dc_ajax_shopping_cart', array(
        'order' => $commerce_cart['order'],
        'line_items' => $line_items,
        'quantity' => $quantity,
        'total' => $total,
      ));
    }
    $commands[] = dc_ajax_add_cart_command_html('div.ajax-shopping-cart-wrapper', $content_cart);
    $content_teaser = theme('dc_ajax_shopping_cart_teaser', array(
      'order' => $commerce_cart['order'],
      'quantity' => $quantity,
      'total' => $total,
    ));
    $commands[] = dc_ajax_add_cart_command_html('div.ajax-shopping-cart-teaser', $content_teaser);

    // Ajaxifies the updation of cart.
    return array(
      '#type' => 'ajax',
      '#commands' => $commands,
    );
  }
  else {
    drupal_set_message(t('Product removed from cart'));
    drupal_goto();
  }
}

/**
 * Implements hook_form_alter().
 */
function dc_ajax_add_cart_form_alter(&$form, &$form_state, $form_id) {
  if (strpos($form_id, 'commerce_cart_add_to_cart_form') !== FALSE) {
    $form['submit']['#ajax'] = array(
      'callback' => 'dc_ajax_add_cart_ajax_cart_form',
      'method' => 'replace',
      'effect' => 'slide',
    );
    if (variable_get(DC_AJAX_ADD_CART_DISPLAY_POPUP, 'display_popup_message') === 'display_popup_message') {
      $form['#attached']['library'][] = array(
        'dc_ajax_add_cart',
        'popup',
      );
    }

    // Rebuild form.
    $form['#submit'][] = 'dc_ajax_add_cart_rebuild_add_to_cart_form';
  }
}

/**
 * AJAX-ify the product add to cart.
 *
 * AJAX callback for all Commerce add to cart form.
 *
 * @ingroup callbacks
 */
function dc_ajax_add_cart_ajax_cart_form(&$form, &$form_state) {

  // AJAX commands array.
  $commands = array();
  $errors = form_get_errors();

  // Get the current status of commerce cart.
  $commerce_cart = dc_ajax_add_cart_get_commerce_cart_details();

  // If the user has ordered items.
  if ($commerce_cart['order'] && !$errors) {

    // Get the line items in cart with their quantity and total.
    $line_items = $commerce_cart['wrapper']->commerce_line_items;
    $quantity = commerce_line_items_quantity($line_items, commerce_product_line_item_types());
    $total = commerce_line_items_total($line_items);
    $ajax_shopping_cart_content = theme('dc_ajax_shopping_cart', array(
      'order' => $commerce_cart['order'],
      'line_items' => $line_items,
      'quantity' => $quantity,
      'total' => $total,
    ));
    $commands[] = dc_ajax_add_cart_command_html('div.ajax-shopping-cart-wrapper', $ajax_shopping_cart_content);

    // Update the contents of shopping cart.
    $ajax_shopping_cart_teaser_content = theme('dc_ajax_shopping_cart_teaser', array(
      'order' => $commerce_cart['order'],
      'quantity' => $quantity,
      'total' => $total,
    ));
    $commands[] = dc_ajax_add_cart_command_html('div.ajax-shopping-cart-teaser', $ajax_shopping_cart_teaser_content);

    // Display add to cart message.
    if (variable_get(DC_AJAX_ADD_CART_DISPLAY_POPUP, 'display_popup_message') == 'display_popup_message') {

      // Gather information to display product information in popup message.
      $last_line_item = dc_ajax_add_cart_get_last_line_item_wrapper($line_items);
      $last_line_item_product = commerce_product_load($last_line_item->commerce_product[LANGUAGE_NONE][0]['product_id']);
      $last_line_item_quantity = $form_state['values']['quantity'];
      $content = theme('dc_ajax_add_to_cart_message', array(
        'line_item' => $last_line_item,
        'product' => $last_line_item_product,
        'quantity' => $last_line_item_quantity,
      ));
      $commands[] = ajax_command_prepend('body', $content);
    }
  }

  // Clear status messages if any.
  $commands[] = ajax_command_remove('div.messages');

  // Show Drupal status message without page refresh.
  // @see https://www.drupal.org/node/1271004#comment-7205478
  // We are checking the textual status messages so that we can save double
  // calling of drupal_get_messages().
  $messages = theme('status_messages');
  if (!empty($messages)) {
    $commands[] = ajax_command_before('#main-content', $messages);
  }
  return array(
    '#type' => 'ajax',
    '#commands' => $commands,
  );
}

/**
 * Implements hook_block_info().
 */
function dc_ajax_add_cart_block_info() {
  $blocks['ajax_shopping_cart'] = array(
    'info' => t('AJAX shopping cart'),
    'cache' => DRUPAL_NO_CACHE,
  );
  $blocks['ajax_shopping_cart_teaser'] = array(
    'info' => t('AJAX shopping cart teaser'),
    'cache' => DRUPAL_NO_CACHE,
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function dc_ajax_add_cart_block_view($delta = '') {
  $block = array();
  switch ($delta) {
    case 'ajax_shopping_cart':

      // Get the current status of cart and other details.
      $commerce_cart = dc_ajax_add_cart_get_commerce_cart_details();
      $hide_empty_cart = FALSE;
      if ($commerce_cart['order']) {
        $line_items = $commerce_cart['wrapper']->commerce_line_items;
        $quantity = commerce_line_items_quantity($line_items, commerce_product_line_item_types());
        $total = commerce_line_items_total($line_items);
        if (variable_get(DC_AJAX_ADD_CART_HIDE_EMPTY_CART, 0) && $quantity == 0) {
          $hide_empty_cart = TRUE;
        }
      }
      else {
        $line_items = NULL;
        $quantity = 0;
        $total = NULL;
        if (variable_get(DC_AJAX_ADD_CART_HIDE_EMPTY_CART, 0)) {
          $hide_empty_cart = TRUE;
        }
      }

      // Hide cart if it is empty.
      if ($hide_empty_cart) {
        $block['content'] = theme('html_tag', array(
          'element' => array(
            '#tag' => 'div',
            '#value' => '',
            '#attributes' => array(
              'class' => 'ajax-shopping-cart-wrapper',
            ),
          ),
        ));
      }
      else {
        $block['content'] = '<div class="ajax-shopping-cart-wrapper">';
        $block['content'] .= theme('dc_ajax_shopping_cart', array(
          'order' => $commerce_cart['order'],
          'line_items' => $line_items,
          'quantity' => $quantity,
          'total' => $total,
        ));
        $block['content'] .= '</div>';
      }
      drupal_add_library('dc_ajax_add_cart', 'base', TRUE);
      break;
    case 'ajax_shopping_cart_teaser':

      // Get the current status of cart and other details.
      $commerce_cart = dc_ajax_add_cart_get_commerce_cart_details();
      if ($commerce_cart['order']) {
        $line_items = $commerce_cart['wrapper']->commerce_line_items;
        $quantity = commerce_line_items_quantity($line_items, commerce_product_line_item_types());
        $total = commerce_line_items_total($line_items);
      }
      else {
        $line_items = NULL;
        $quantity = 0;
        $total = NULL;
      }
      $block['content'] = '<div class="ajax-shopping-cart-teaser">';
      $block['content'] .= theme('dc_ajax_shopping_cart_teaser', array(
        'order' => $commerce_cart['order'],
        'quantity' => $quantity,
        'total' => $total,
      ));
      $block['content'] .= '</div>';
      drupal_add_library('dc_ajax_add_cart', 'base', TRUE);
      break;
  }
  return $block;
}

/**
 * This function returns the current status of cart.
 *
 * @return array
 *   Array containing the current status of cart.
 */
function dc_ajax_add_cart_get_commerce_cart_details() {
  global $user;
  $output = array();
  $order = commerce_cart_order_load($user->uid);
  if ($order) {
    $wrapper = entity_metadata_wrapper('commerce_order', $order);
    $output['order'] = $order;
    $output['wrapper'] = $wrapper;
  }
  else {
    $output['order'] = NULL;
    $output['wrapper'] = NULL;
  }
  return $output;
}

/**
 * Implements hook_theme().
 */
function dc_ajax_add_cart_theme() {
  return array(
    'dc_ajax_shopping_cart' => array(
      'variables' => array(
        'order' => NULL,
        'line_items' => NULL,
        'quantity' => NULL,
        'total' => NULL,
      ),
      'template' => 'templates/dc-ajax-shopping-cart',
    ),
    'dc_ajax_shopping_cart_teaser' => array(
      'variables' => array(
        'order' => NULL,
        'quantity' => NULL,
        'total' => NULL,
      ),
      'template' => 'templates/dc-ajax-shopping-cart-teaser',
    ),
    'dc_ajax_add_to_cart_message' => array(
      'variables' => array(
        'line_item' => NULL,
        'product' => NULL,
        'quantity' => NULL,
      ),
      'template' => 'templates/dc-ajax-add-to-cart-message',
    ),
  );
}

/**
 * Add more variables to shopping cart block.
 *
 * Default template: ajax-shopping-cart.tpl.php.
 *
 * @param array $variables
 *   An associative array containing:
 *   - order: Order object of the current user.
 *   - line_items: Line items wrapper.
 *   - quantity: Number of items in the cart.
 *   - total: Array containing the total amount and the default currency you
 *     are in the site.
 */
function template_preprocess_dc_ajax_shopping_cart(&$variables) {

  // Check whether order object exists.
  if ($variables['order']) {
    $header = array();
    $row = array();
    $image_remove_cart_path = drupal_get_path('module', 'dc_ajax_add_cart') . '/images/remove-from-cart.png';
    $image_remove_cart = theme('image', array(
      'path' => $image_remove_cart_path,
      'alt' => t('Remove from cart'),
      'title' => t('Remove from cart'),
    ));
    $currency = dc_ajax_add_cart_currency_load();

    // Output arrays.
    $line_item_list = array();
    $products = array();
    $product_prices = array();
    $shipping = array();
    $product_price_total = commerce_currency_format($variables['total']['amount'], $currency['code']);

    // Create the line item list and products array.
    foreach ($variables['line_items'] as $line_item_wrapper) {
      $line_item = $line_item_wrapper
        ->value();

      // If the line item is a product.
      if (property_exists($line_item, 'commerce_product')) {
        $products[$line_item->line_item_id] = commerce_product_load($line_item->commerce_product[LANGUAGE_NONE][0]['product_id']);
        $product_prices[$line_item->line_item_id] = commerce_currency_format($line_item->commerce_unit_price[LANGUAGE_NONE][0]['amount'], $currency['code']);
      }
      elseif (property_exists($line_item, 'commerce_shipping_service')) {
        $shipping['service'] = $line_item->line_item_label;
        $shipping['price'] = commerce_currency_format($line_item->commerce_unit_price[LANGUAGE_NONE][0]['amount'], $currency['code']);
      }
      $line_item_list[$line_item->line_item_id] = $line_item;
    }

    // Create checkout url.
    if (variable_get(DC_AJAX_ADD_CART_CHECKOUT_REDIRECT, 'cart_page') == 'cart_page') {
      $variables['checkout_link'] = array(
        'text' => t('Checkout'),
        'path' => 'cart',
        'attributes' => array(
          'class' => array(
            'dc-ajax-add-cart-checkout-link',
            'dc-ajax-add-cart-checkout-cart',
          ),
        ),
        'query' => array(),
        'fragment' => '',
        'html' => FALSE,
      );
    }
    else {
      $variables['checkout_link'] = array(
        'text' => t('Checkout'),
        'path' => 'checkout',
        'attributes' => array(
          'class' => array(
            'dc-ajax-add-cart-checkout-link',
            'dc-ajax-add-cart-checkout-checkout',
          ),
        ),
        'query' => array(),
        'fragment' => '',
        'html' => FALSE,
      );
    }

    // Shopping cart.
    if (variable_get(DC_AJAX_ADD_CART_SHOW_LABELS, 'label') == 'label') {
      $variables['products_list']['header'][] = array(
        'data' => t('Quantity'),
        'header_classes' => 'quantity-label',
      );
      $variables['products_list']['header'][] = array(
        'data' => t('Items'),
        'header_classes' => 'item-label',
      );
      $variables['products_list']['header'][] = array(
        'data' => t('Price'),
        'header_classes' => 'price-label',
      );
      $variables['products_list']['header'][] = array(
        'data' => '',
      );
    }
    foreach ($line_item_list as $line_item) {
      if (property_exists($line_item, 'commerce_product')) {
        $product = commerce_product_load($line_item->commerce_product[LANGUAGE_NONE][0]['product_id']);
        if (variable_get('dc_ajax_add_cart_update_quantity', 0) == 1) {
          $updateable_quantity = drupal_get_form('dc_ajax_add_cart_update_quantity_' . $line_item->line_item_id, $line_item);
          $quantity = drupal_render($updateable_quantity);
        }
        else {
          $quantity = intval($line_item->quantity);
        }
        $variables['products_list']['row'][$line_item->line_item_id]['quantity'] = array(
          'data' => $quantity,
          'field_classes' => 'quantity',
        );
        $variables['products_list']['row'][$line_item->line_item_id]['title'] = array(
          'data' => $product->title,
          'field_classes' => 'name',
        );
        $variables['products_list']['row'][$line_item->line_item_id]['price'] = array(
          'data' => $product_prices[$line_item->line_item_id],
          'field_classes' => 'price',
        );
        $variables['products_list']['row'][$line_item->line_item_id]['remove'] = array(
          'data' => l(variable_get(DC_AJAX_ADD_CART_REMOVE_CART, 'link') == 'link' ? t('Remove from cart') : $image_remove_cart, 'remove-product/nojs/' . $line_item->line_item_id, array(
            'attributes' => array(
              'class' => array(
                'use-ajax',
              ),
            ),
            'html' => TRUE,
          )),
          'field_classes' => 'remove-from-cart',
        );
        $variables['products_list']['row_classes'][$line_item->line_item_id] = 'ajax-cart-row';
      }
    }

    // Create new theme variables.
    $variables['line_item_list'] = $line_item_list;
    $variables['products'] = $products;
    $variables['product_prices'] = $product_prices;
    $variables['product_price_total'] = $product_price_total;
    $variables['checkout_url'] = l($variables['checkout_link']['text'], $variables['checkout_link']['path'], array(
      'attributes' => $variables['checkout_link']['attributes'],
      'query' => $variables['checkout_link']['query'],
      'fragment' => $variables['checkout_link']['fragment'],
      'html' => $variables['checkout_link']['html'],
    ));
    $variables['products_list']['classes'] = 'ajax-shopping-cart-table';
    if (!empty($shipping)) {
      $variables['shipping'] = $shipping;
    }
  }

  // Create new theme variables related to configuration.
  $variables['configuration']['show_labels'] = variable_get(DC_AJAX_ADD_CART_SHOW_LABELS, 'label');
  $variables['configuration']['remove_cart'] = variable_get(DC_AJAX_ADD_CART_REMOVE_CART, 'link');
  $variables['configuration']['empty_cart_message'] = check_plain(variable_get(DC_AJAX_ADD_CART_EMPTY_CART_MESSAGE, t('Shopping cart is empty')));
}

/**
 * Add more variables to shopping cart teaser.
 *
 * Default template: ajax-shopping-cart-teaser.tpl.php.
 *
 * @param array $variables
 *   An associative array containing:
 *   - order: Order object for the current user.
 *   - quantity: Number of items present in the cart.
 *   - total: Array containing the total amount and default currency code used
 *     in the site.
 */
function template_preprocess_dc_ajax_shopping_cart_teaser(&$variables) {
  $currency = dc_ajax_add_cart_currency_load();
  $image_cart_icon_path = drupal_get_path('module', 'dc_ajax_add_cart') . '/images/shopping-cart.png';
  $variables['total_amount'] = commerce_currency_format($variables['total']['amount'], $currency['code']);
  $variables['cart_icon'] = theme('image', array(
    'path' => $image_cart_icon_path,
  ));

  // Create new theme variables related to configuration.
  $variables['configuration']['empty_cart_teaser_message'] = variable_get(DC_AJAX_ADD_CART_EMPTY_CART_TEASER_MESSAGE, t('Empty'));
  $cart_link_text = format_plural($variables['quantity'], '1 ' . variable_get(DC_AJAX_ADD_CART_ITEM_SUFFIX_TEXT_SINGULAR, t('item')), '@count ' . variable_get(DC_AJAX_ADD_CART_ITEM_SUFFIX_TEXT_PLURAL, t('items')));
  $variables['cart_link'] = l($cart_link_text, 'cart', array(
    'attributes' => array(
      'class' => array(
        'quantity',
      ),
    ),
  ));
}

/**
 * Add more variables to add to cart message popup message.
 *
 * Default template: add-to-cart-message.tpl.php.
 *
 * @param array $variables
 *   An associative array containing:
 *   - order: Order object for the current user.
 *   - quantity: Number of items present in the cart.
 *   - total: Array containing the total amount and default currency code used
 *     in the site.
 */
function template_preprocess_dc_ajax_add_to_cart_message(&$variables) {
  $currency = dc_ajax_add_cart_currency_load();
  $product_price = $variables['line_item']->commerce_unit_price[LANGUAGE_NONE][0]['amount'];
  $variables['product_per_unit_price'] = commerce_currency_format($product_price, $currency['code']);
  $variables['product_price_total'] = commerce_currency_format($variables['quantity'] * $product_price, $currency['code']);

  // Create new theme variables related to configuration.
  $variables['configuration']['success_message'] = check_plain(variable_get(DC_AJAX_ADD_CART_SUCCESS_MESSAGE, t('Item successfully added to cart')));
  $variables['configuration']['popup_checkout'] = check_plain(variable_get(DC_AJAX_ADD_CART_POPUP_CHECKOUT, t('Go to checkout')));
  $variables['checkout_link'] = l(variable_get(DC_AJAX_ADD_CART_POPUP_CHECKOUT, t('Go to checkout')), 'cart');
  $variables['configuration']['popup_continue_shopping'] = check_plain(variable_get(DC_AJAX_ADD_CART_POPUP_CONTINUE_SHOPPING, t('Continue shopping')));
  $variables['configuration']['popup_product_name_display'] = variable_get(DC_AJAX_ADD_CART_POPUP_PRODUCT_NAME_DISPLAY, 1);
  $variables['configuration']['popup_product_name_label'] = variable_get(DC_AJAX_ADD_CART_POPUP_PRODUCT_NAME_LABEL, 'no_display_label');
  $variables['product_name'] = check_plain($variables['product']->title);
  $variables['configuration']['popup_product_price_display'] = variable_get(DC_AJAX_ADD_CART_POPUP_PRODUCT_PRICE_DISPLAY, 1);
  $variables['configuration']['popup_product_price_label'] = variable_get(DC_AJAX_ADD_CART_POPUP_PRODUCT_PRICE_LABEL, 'display_label');
  $variables['configuration']['popup_product_quantity_display'] = variable_get(DC_AJAX_ADD_CART_POPUP_PRODUCT_QUANTITY_DISPLAY, 1);
  $variables['configuration']['popup_product_quantity_label'] = variable_get(DC_AJAX_ADD_CART_POPUP_PRODUCT_QUANTITY_LABEL, 'display_label');
  $variables['configuration']['popup_product_total_display'] = variable_get(DC_AJAX_ADD_CART_POPUP_PRODUCT_TOTAL_DISPLAY, 1);
  $variables['configuration']['popup_product_total_label'] = variable_get(DC_AJAX_ADD_CART_POPUP_PRODUCT_TOTAL_LABEL, 'display_label');
}

/**
 * Rebuild add to cart form.
 *
 * @ingroup forms
 */
function dc_ajax_add_cart_rebuild_add_to_cart_form($form, &$form_state) {
  $form_state['rebuild'] = TRUE;
}

/**
 * Update line item quantity.
 *
 * @param object $line_item
 *   Line item.
 *
 * @see dc_ajax_add_cart_update_quantity_refresh()
 *
 * @ingroup forms
 */
function dc_ajax_add_cart_update_quantity($form, &$form_state, $line_item) {
  $form = array();
  $form['quantity_' . $line_item->line_item_id] = array(
    '#type' => 'textfield',
    '#size' => 3,
    '#maxlength' => 3,
    '#default_value' => intval($line_item->quantity),
  );
  $form['submit_' . $line_item->line_item_id] = array(
    '#type' => 'submit',
    '#value' => t('Update'),
    '#line_item_id' => $line_item->line_item_id,
    '#ajax' => array(
      'callback' => 'dc_ajax_add_cart_update_quantity_refresh',
      'method' => 'replace',
    ),
  );
  $form['#submit'][] = 'dc_ajax_add_cart_rebuild_update_quantity_form';
  return $form;
}

/**
 * Callback that will update the quantity of line item.
 *
 * @ingroup callbacks
 */
function dc_ajax_add_cart_update_quantity_refresh($form, &$form_state) {
  global $user;
  $order = commerce_cart_order_load($user->uid);

  // AJAX commands array.
  $commands = array();

  // If altered quantity is not zero, then update line item's quantity.
  // Otherwise delete line item.
  if ($form_state['values']['quantity_' . $form_state['triggering_element']['#line_item_id']] != 0) {
    $line_item = commerce_line_item_load($form_state['triggering_element']['#line_item_id']);
    $line_item->quantity = $form_state['values']['quantity_' . $form_state['triggering_element']['#line_item_id']];
    commerce_line_item_save($line_item);
  }
  else {
    commerce_cart_order_product_line_item_delete($order, $form_state['triggering_element']['#line_item_id']);
  }

  // Get the current status of commerce cart.
  $commerce_cart = dc_ajax_add_cart_get_commerce_cart_details();

  // If the user has ordered items.
  if ($commerce_cart['order']) {

    // Get the line items in cart with their quantity and total.
    $line_items = $commerce_cart['wrapper']->commerce_line_items;
    $quantity = commerce_line_items_quantity($line_items, commerce_product_line_item_types());
    $total = commerce_line_items_total($line_items);

    // Check whether the user has any product in cart.
    if (variable_get(DC_AJAX_ADD_CART_HIDE_EMPTY_CART, 0) && $quantity == 0) {
      $ajax_shopping_cart_content = '';
    }
    else {
      $ajax_shopping_cart_content = theme('dc_ajax_shopping_cart', array(
        'order' => $commerce_cart['order'],
        'line_items' => $line_items,
        'quantity' => $quantity,
        'total' => $total,
      ));
    }
    $commands[] = dc_ajax_add_cart_command_html('div.ajax-shopping-cart-wrapper', $ajax_shopping_cart_content);

    // Update the contents of shopping cart.
    $ajax_shopping_cart_teaser_content = theme('dc_ajax_shopping_cart_teaser', array(
      'order' => $commerce_cart['order'],
      'quantity' => $quantity,
      'total' => $total,
    ));
    $commands[] = dc_ajax_add_cart_command_html('div.ajax-shopping-cart-teaser', $ajax_shopping_cart_teaser_content);
    return array(
      '#type' => 'ajax',
      '#commands' => $commands,
    );
  }
}

/**
 * Rebuild update quantity form.
 *
 * @ingroup forms
 */
function dc_ajax_add_cart_rebuild_update_quantity_form($form, &$form_state) {
  $form_state['rebuild'] = TRUE;
}

/**
 * Implements hook_forms().
 */
function dc_ajax_add_cart_forms($form_id, $args) {
  $forms = array();
  if (strpos($form_id, 'dc_ajax_add_cart_update_quantity_') !== FALSE) {
    $forms[$form_id] = array(
      'callback' => 'dc_ajax_add_cart_update_quantity',
    );
  }
  return $forms;
}

/**
 * Creates a Ajax 'replace' command.
 *
 * This command is specifically for dc_ajax_add_cart module.
 * Unlike `ajax_command_replace()`, this command will not produce extra div
 * wrapper with 'display: block' style.
 *
 * This command is implemented by
 * Drupal.ajax.prototype.commands.dc_ajax_add_cart_html () defined in
 * js/dc_ajax_add_cart_html.js.
 *
 * @param string $selector
 *   A jQuery selector string. If the command is a response to a request from
 *   an #ajax form element then this value can be NULL.
 * @param string $html
 *   The data to use with the jQuery replaceWith() method.
 *
 * @return array
 *   An array suitable for use with the ajax_render() function.
 */
function dc_ajax_add_cart_command_html($selector, $html) {
  return array(
    'command' => 'dc_ajax_add_cart_html',
    'selector' => $selector,
    'data' => $html,
  );
}

/**
 * Implements hook_variable_info().
 */
function dc_ajax_add_cart_variable_info($options) {
  $variables[DC_AJAX_ADD_CART_EMPTY_CART_MESSAGE] = array(
    'type' => 'string',
    'title' => t('Empty cart message', array(), $options),
    'default' => 'Shopping cart is empty',
    'localize' => TRUE,
  );
  $variables[DC_AJAX_ADD_CART_EMPTY_CART_TEASER_MESSAGE] = array(
    'type' => 'string',
    'title' => t('Empty cart teaser message', array(), $options),
    'default' => 'Empty',
    'localize' => TRUE,
  );
  $variables[DC_AJAX_ADD_CART_SUCCESS_MESSAGE] = array(
    'type' => 'string',
    'title' => t('Cart success message', array(), $options),
    'default' => 'Item successfully added to cart',
    'localize' => TRUE,
  );
  $variables[DC_AJAX_ADD_CART_POPUP_CHECKOUT] = array(
    'type' => 'string',
    'title' => t('Go to checkout Label', array(), $options),
    'default' => 'Go to checkout',
    'localize' => TRUE,
  );
  $variables[DC_AJAX_ADD_CART_POPUP_CONTINUE_SHOPPING] = array(
    'type' => 'string',
    'title' => t('Continue shopping Label', array(), $options),
    'default' => 'Continue shopping',
    'localize' => TRUE,
  );
  return $variables;
}

/**
 * Returns the default/user-based currency.
 *
 * @return array
 *   Commerce currency info array.
 *
 * @see https://www.drupal.org/node/2846386
 */
function dc_ajax_add_cart_currency_load() {
  if (module_exists('commerce_multicurrency')) {
    return commerce_currency_load(commerce_multicurrency_get_user_currency_code());
  }
  else {
    return commerce_currency_load(commerce_default_currency());
  }
}

/**
 * Returns the last line item that was added to cart.
 *
 * @param object $line_items_wrapper
 *   Entity list wrapper of line items.
 *
 * @return object
 *   The last line item.
 */
function dc_ajax_add_cart_get_last_line_item_wrapper($line_items_wrapper) {
  $line_items = dc_ajax_add_cart_filter_commerce_line_item_by_commerce_product($line_items_wrapper
    ->value());
  $changed = 0;

  // By default it will return the last line item in the array.
  $keys = array_keys($line_items);
  $last_changed_key = end($keys);
  foreach ($line_items as $key => $line_item) {
    if ($line_item->changed >= $changed) {
      $last_changed_key = $key;
      $changed = $line_item->changed;
    }
  }
  return $line_items[$last_changed_key];
}

/**
 * Filters line items by products.
 *
 * @param array $line_items
 *   Line items to be filtered from.
 *
 * @return array
 *   Filtered line items.
 */
function dc_ajax_add_cart_filter_commerce_line_item_by_commerce_product($line_items) {
  $product_types = array_keys(commerce_product_types());
  $filtered_line_items = array();
  foreach ($line_items as $line_item) {
    if (in_array($line_item->type, $product_types)) {
      $filtered_line_items[] = $line_item;
    }
  }
  return $filtered_line_items;
}

/**
 * Implements hook_library().
 */
function dc_ajax_add_cart_library() {
  $module_path = drupal_get_path('module', 'dc_ajax_add_cart');
  $libraries['base'] = array(
    'title' => 'Drupal Commerce Ajax Add Cart Base',
    'version' => '1.0.0',
    'js' => array(
      $module_path . '/js/dc_ajax_add_cart_html.js' => array(
        'group' => JS_DEFAULT,
      ),
    ),
    'css' => array(
      $module_path . '/css/dc_ajax_add_cart.css' => array(),
    ),
    'dependencies' => array(
      array(
        'system',
        'drupal.ajax',
      ),
      array(
        'system',
        'jquery',
      ),
    ),
  );
  $libraries['popup'] = array(
    'title' => 'Drupal Commerce Ajax Add Cart Popup',
    'version' => '1.0.0',
    'js' => array(
      $module_path . '/js/dc_ajax_add_cart.js' => array(
        'group' => JS_DEFAULT,
      ),
    ),
    'css' => array(
      $module_path . '/css/dc_ajax_add_cart.css' => array(),
    ),
    'dependencies' => array(
      array(
        'system',
        'jquery',
      ),
    ),
  );
  return $libraries;
}

Functions

Namesort descending Description
dc_ajax_add_cart_ajax_cart_form AJAX-ify the product add to cart.
dc_ajax_add_cart_block_info Implements hook_block_info().
dc_ajax_add_cart_block_view Implements hook_block_view().
dc_ajax_add_cart_command_html Creates a Ajax 'replace' command.
dc_ajax_add_cart_currency_load Returns the default/user-based currency.
dc_ajax_add_cart_filter_commerce_line_item_by_commerce_product Filters line items by products.
dc_ajax_add_cart_forms Implements hook_forms().
dc_ajax_add_cart_form_alter Implements hook_form_alter().
dc_ajax_add_cart_get_commerce_cart_details This function returns the current status of cart.
dc_ajax_add_cart_get_last_line_item_wrapper Returns the last line item that was added to cart.
dc_ajax_add_cart_library Implements hook_library().
dc_ajax_add_cart_menu Implements hook_menu().
dc_ajax_add_cart_permission Implements hook_permission().
dc_ajax_add_cart_rebuild_add_to_cart_form Rebuild add to cart form.
dc_ajax_add_cart_rebuild_update_quantity_form Rebuild update quantity form.
dc_ajax_add_cart_remove_commerce_line_item Menu callback: Removes the product item from cart.
dc_ajax_add_cart_theme Implements hook_theme().
dc_ajax_add_cart_update_quantity Update line item quantity.
dc_ajax_add_cart_update_quantity_refresh Callback that will update the quantity of line item.
dc_ajax_add_cart_variable_info Implements hook_variable_info().
template_preprocess_dc_ajax_add_to_cart_message Add more variables to add to cart message popup message.
template_preprocess_dc_ajax_shopping_cart Add more variables to shopping cart block.
template_preprocess_dc_ajax_shopping_cart_teaser Add more variables to shopping cart teaser.

Constants