You are here

commerce_free_shipping.module in Commerce Free Shipping 7

Implements hook_commerce_shipping_service_info_alter() to change the price of the shipping service, when it's needed.

File

commerce_free_shipping.module
View source
<?php

/**
 * @file
 * Implements hook_commerce_shipping_service_info_alter() to change
 * the price of the shipping service, when it's needed.
 */

/**
 * Implements hook_menu().
 */
function commerce_free_shipping_menu() {
  $items['admin/commerce/config/free-shipping'] = array(
    'title' => 'Free Shipping',
    'description' => 'Manage free shipping.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'commerce_free_shipping_admin_form',
    ),
    'access arguments' => array(
      'administer shipping',
    ),
    'file' => 'commerce_free_shipping.admin.inc',
  );

  // Loop over every shipping method and define a rule to collect rates for
  // shipping services assigned to that method.
  $shipping_services = commerce_shipping_services();
  foreach ($shipping_services as $service) {
    $base = $service['base'];

    // Check if free shipping is enabled for this services.
    if (variable_get($base . '_free_shipping_additionnal_rules', FALSE)) {
      $items['admin/commerce/config/free-shipping/' . $base] = array(
        'title' => 'Free Shipping rules conditions for ' . $service['display_title'],
        'description' => 'Manage free shipping rules conditions.',
        'page callback' => 'drupal_get_form',
        'page arguments' => array(
          'commerce_free_shipping_rules_admin_form',
        ),
        'access arguments' => array(
          'administer shipping',
        ),
        'file' => 'commerce_free_shipping.admin.inc',
      );

      // Add the menu items for the various Rules forms.
      $controller = new RulesUIController();
      $items += $controller
        ->config_menu('admin/commerce/config/free-shipping/' . $base);
    }
  }
  return $items;
}

/**
 * Implements hook_commerce_shipping_service_info_alter().
 */
function commerce_free_shipping_commerce_shipping_service_info_alter(&$shipping_services) {
  if (empty($shipping_services)) {
    return;
  }
  foreach ($shipping_services as $name => $shipping_service) {
    $base = $shipping_service['base'];

    // Check if free shipping is enabled for this services.
    if (variable_get($base . '_free_shipping_enabled', FALSE)) {
      $shipping_service['callbacks']['original_rate'] = $shipping_service['callbacks']['rate'];
      $shipping_service['callbacks']['rate'] = 'commerce_free_shipping_rate_callback';
      $shipping_services[$name] = $shipping_service;
    }
  }
}

/**
 * Implements hook_variable_group_info().
 */
function commerce_free_shipping_variable_group_info() {
  $groups['variable_commerce'] = array(
    'title' => t('Commerce Free Shipping'),
    'description' => t('Variables for Commerce Free Shipping.'),
    'access' => 'administer site configuration',
    'path' => array(
      'admin/commerce/config/free-shipping',
    ),
  );
  return $groups;
}

/**
 * Implements hook_variable_info().
 */
function commerce_free_shipping_variable_info($options) {
  $shipping_services = commerce_shipping_services();
  foreach ($shipping_services as $service) {
    $base = $service['base'];
    $variables[$base . '_free_shipping_gift_message'] = array(
      'type' => 'text',
      'title' => t('%base Free shipping message.', array(
        '%base' => $service['display_title'],
      ), $options),
      'description' => t('Display a message when the user get free shipping price for %base.', array(
        '%base' => $service['display_title'],
      ), $options),
      'default' => 'You have got free pricing on ' . $service['display_title'] . ', because your order total has raise %rate !',
      'group' => 'variable_commerce',
    );
    $variables[$base . '_free_shipping_rules_reject_message_display'] = array(
      'type' => 'text',
      'title' => t('%base Message if free shipping rules conditions failed.', array(
        '%base' => $service['display_title'],
      ), $options),
      'description' => t('Display a message when the user don\'t get free shipping price because of the rules conditions for %base.', array(
        '%base' => $service['display_title'],
      ), $options),
      'default' => 'You have got free pricing on ' . $service['display_title'] . ', because your order total has raise %rate !',
      'group' => 'variable_commerce',
    );
    $variables[$base . '_free_shipping_reject_message'] = array(
      'type' => 'text',
      'title' => t('%base Message if price threshold condition failed.', array(
        '%base' => $service['display_title'],
      ), $options),
      'description' => t('Display a message when the user don\'t get free shipping price because the order amount is below the price threshold for %base.', array(
        '%base' => $service['display_title'],
      ), $options),
      'default' => 'You have got free pricing on ' . $service['display_title'] . ', because your order total has raise %rate !',
      'group' => 'variable_commerce',
    );
  }
  return $variables;
}

/**
 * Override default rate callback of the shipping services.
 */
function commerce_free_shipping_rate_callback($shipping_service, $order) {
  $base = $shipping_service['base'];
  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  $order_currency_code = $order_wrapper->commerce_order_total->currency_code
    ->value();
  $rate_callback = $shipping_service['callbacks']['original_rate'];
  if (!function_exists($rate_callback)) {
    return FALSE;
  }

  // Call the original rate callback,
  // and keep the normal shipping rate for this service / order.
  $rate = $rate_callback($shipping_service, $order);

  // If callback return false, that means this shipping method is non available.
  // If callback return an amount of 0 for this shipping service do nothing.
  if ($rate === FALSE || is_array($rate) && $rate['amount'] === 0) {
    return $rate;
  }

  // Check if free shipping is enabled for this services.
  if (!variable_get($base . '_free_shipping_enabled', FALSE)) {
    return $rate;
  }

  // Get the total amount of the products.
  $total = 0;
  $price_threshold_currency_code = variable_get($base . '_free_shipping_rate_limit_currency', 'default');
  if ($price_threshold_currency_code == 'default') {
    $price_threshold_currency_code = commerce_default_currency();
  }
  foreach ($order_wrapper->commerce_line_items as $line_item) {
    if (in_array($line_item->type
      ->value(), variable_get($base . '_free_shipping_excluded_line_item_types', array(
      'shipping' => 'shipping',
    )))) {

      // This line item type is configured to be excluded from the calcul.
      continue;
    }
    if (in_array($line_item->type
      ->value(), commerce_product_line_item_types()) && isset($line_item->commerce_product)) {
      if (in_array($line_item->commerce_product->type
        ->value(), variable_get($base . '_free_shipping_excluded_line_item_product_types', array(
        'shipping' => 'shipping',
      )))) {
        continue;
      }
    }

    // Add this line item total amount to the calcul.
    if ($line_item->commerce_total->currency_code
      ->value() == $price_threshold_currency_code) {
      $total += $line_item->commerce_total->amount
        ->value();
    }
    else {

      // Convert the current line item total price to the price
      // threshold currency before adding it to the total.
      $total += commerce_currency_convert($line_item->commerce_total->amount
        ->value(), $line_item->commerce_total->currency_code
        ->value(), $price_threshold_currency_code);
    }
  }

  // Check and apply free shipping.
  $limit_rate = variable_get($base . '_free_shipping_rate_limit', 6000);
  $apply_free_shipping_pricing = FALSE;

  // Test if the total are superior or egal to the threshold rate.
  if ($total >= $limit_rate) {
    $apply_free_shipping_pricing = TRUE;

    // Additionnal rule conditions check.
    if (variable_get($base . '_free_shipping_additionnal_rules', FALSE)) {
      $apply_free_shipping_pricing = rules_invoke_component('commerce_free_shipping_service_' . $base, $order);
    }

    // Apply free shipping price.
    if ($apply_free_shipping_pricing) {
      $rate['amount'] = 0;
      if (!empty($rate['data']['components'])) {
        $rate['data']['components'] = array();
      }

      // Message for the client.
      if (variable_get($base . '_free_shipping_gift_message_display', TRUE)) {
        if ($price_threshold_currency_code != $order_currency_code) {
          $limit_rate = commerce_currency_convert($limit_rate, $price_threshold_currency_code, $order_currency_code);
        }
        $message_rate = commerce_currency_format($limit_rate, $order_currency_code);
        $message = variable_get($base . '_free_shipping_gift_message');
        $message = str_replace('%rate', $message_rate, $message);
        drupal_set_message(filter_xss($message, array(
          'b',
          'strong',
          'i',
          'u',
          'em',
          'a',
        )), 'status', FALSE);
      }
    }
    else {

      // The shipping service are not for free,
      // Because of the rules conditions,
      // tell something to the customer ?
      if (variable_get($base . '_free_shipping_rules_reject_message_display', TRUE)) {
        $message = variable_get($base . '_free_shipping_rules_reject_message');
        drupal_set_message(filter_xss($message, array(
          'b',
          'strong',
          'i',
          'u',
          'em',
          'a',
        )), 'status', FALSE);
      }
    }
  }
  else {

    // The shipping service are not for free,
    // Because of the free shipping total price threshold.
    // tell something to the customer ?
    if (variable_get($base . '_free_shipping_reject_message_display', TRUE)) {

      // Get the amount left to obtain free shipping.
      $message_rate = $limit_rate - $total;
      if ($price_threshold_currency_code != $order_currency_code) {
        $message_rate = commerce_currency_convert($message_rate, $price_threshold_currency_code, $order_currency_code);
      }
      $message_rate = commerce_currency_format($message_rate, $order_currency_code);
      $message = variable_get($base . '_free_shipping_reject_message');
      $message = str_replace('%rate', $message_rate, $message);
      drupal_set_message(filter_xss($message, array(
        'b',
        'strong',
        'i',
        'u',
        'em',
        'a',
      )), 'status', FALSE);
    }
  }
  return $rate;
}

/**
 * Implements hook_module_implements_alter().
 */
function commerce_free_shipping_module_implements_alter(&$implementations, $hook) {

  // To allow the default rules defined by this module to be overridden by other
  // modules (such as Features produced modules), we need to ensure that this
  // module's hook_default_rules_configuration() is invoked before theirs.
  if ($hook == 'default_rules_configuration') {

    // Extract this module's entry from the hook implementations array.
    $group = $implementations['commerce_free_shipping'];
    unset($implementations['commerce_free_shipping']);

    // And re-add it by prepending it back onto the array.
    $implementations = array(
      'commerce_free_shipping' => $group,
    ) + $implementations;
  }
}