You are here

uc_weightquote.module in Ubercart 5

Shipping quote module that defines a shipping rate for each product based on weight.

Coded by Lyle Mantooth.

File

shipping/uc_weightquote/uc_weightquote.module
View source
<?php

/**
 * @file
 * Shipping quote module that defines a shipping rate for each product based on weight.
 *
 * Coded by Lyle Mantooth.
 */

/******************************************************************************
 * Drupal Hooks                                                               *
 ******************************************************************************/

/**
 * Implementation of hook_menu().
 */
function uc_weightquote_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/store/settings/quotes/methods/weightquote',
      'access' => user_access('configure quotes'),
      'title' => t('Weight quote'),
      'callback' => 'uc_weightquote_admin_methods',
      'type' => MENU_LOCAL_TASK,
    );
  }
  else {
    $items[] = array(
      'path' => 'admin/store/settings/quotes/methods/weightquote/' . arg(6),
      'access' => user_access('configure quotes'),
      'title' => t('Edit weight quote method'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'uc_weightquote_admin_method_edit_form',
        arg(6),
      ),
      'type' => MENU_CALLBACK,
    );
    $items[] = array(
      'path' => 'admin/store/settings/quotes/methods/weightquote/' . arg(6) . '/delete',
      'access' => user_access('configure quotes'),
      'title' => t('Delete weight quote method'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'uc_weightquote_admin_method_confirm_delete',
        arg(6),
      ),
      'type' => MENU_CALLBACK,
    );
  }
  return $items;
}

/**
 * Implementation of hook_form_alter().
 *
 * Add a form element for the shipping rate of a product.
 *
 * @see uc_product_form
 */
function uc_weightquote_form_alter($form_id, &$form) {
  $node = $form['#node'];
  $product_types = module_invoke_all('product_types');
  if (is_object($node) && $form_id == $node->type . '_node_form' && isset($form['base']['dimensions']) && in_array($node->type, $product_types)) {
    $result = db_query("SELECT mid, title, unit_rate FROM {uc_weightquote_methods}");
    if (db_num_rows($result)) {
      $sign_flag = variable_get('uc_sign_after_amount', FALSE);
      $currency_sign = variable_get('uc_currency_sign', '$');
      $enabled = variable_get('uc_quote_enabled', array());
      $weight = variable_get('uc_quote_method_weight', array());
      $form['shipping']['weightquote'] = array(
        '#type' => 'fieldset',
        '#title' => t('Weight quote shipping rates'),
        '#description' => t('Override the default shipping rate per !unit for each weight quote shipping method here. Enter -1 to revert to the default value.', array(
          '!unit' => variable_get('uc_weight_unit', 'lb'),
        )),
        '#tree' => true,
        '#collapsible' => true,
        '#collapsed' => false,
        '#weight' => 0,
      );
      while ($method = db_fetch_object($result)) {
        $form['shipping']['weightquote'][$method->mid] = array(
          '#type' => 'textfield',
          '#title' => $method->title,
          '#default_value' => $form['#node']->weightquote[$method->mid],
          '#description' => t('Default rate per !unit: %price', array(
            '!unit' => variable_get('uc_weight_unit', 'lb'),
            '%price' => uc_currency_format($method->unit_rate),
          )),
          '#size' => 16,
          '#field_prefix' => $sign_flag ? '' : $currency_sign,
          '#field_suffix' => t('!sign per !unit', array(
            '!sign' => $sign_flag ? $currency_sign : '',
            '!unit' => variable_get('uc_weight_unit', 'lb'),
          )),
          '#weight' => $weight['weightquote_' . $method->mid],
        );
      }
    }
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function uc_weightquote_nodeapi(&$node, $op) {
  if (in_array($node->type, module_invoke_all('product_types'))) {
    switch ($op) {
      case 'insert':
      case 'update':
        if (is_array($node->weightquote)) {
          if (!$node->revision) {
            db_query("DELETE FROM {uc_weightquote_products} WHERE vid = %d", $node->vid);
          }
          foreach ($node->weightquote as $mid => $rate) {
            if ($rate !== '') {
              db_query("INSERT INTO {uc_weightquote_products} (vid, nid, mid, rate) VALUES (%d, %d, %d, %f)", $node->vid, $node->nid, $mid, $rate);
            }
          }
        }
        break;
      case 'load':
        $return = array(
          'weightquote' => array(),
        );
        $result = db_query("SELECT mid, rate FROM {uc_weightquote_products} WHERE vid = %d", $node->vid);
        while ($rate = db_fetch_object($result)) {
          $return['weightquote'][$rate->mid] = $rate->rate;
        }
        $result = db_query("SELECT mid, unit_rate FROM {uc_weightquote_methods}");
        while ($method = db_fetch_object($result)) {
          $rate = $return['weightquote'][$method->mid];
          if ($rate === null || $rate < 0) {
            $return['weightquote'][$method->mid] = $method->unit_rate;
          }
        }
        return $return;
        break;
      case 'delete':
        db_query("DELETE FROM {uc_weightquote_products} WHERE nid = %d", $node->nid);
        break;
      case 'delete revision':
        db_query("DELETE FROM {uc_weightquote_products} WHERE vid = %d", $node->vid);
        break;
    }
  }
}

/******************************************************************************
 * Workflow-ng Hooks                                                          *
 ******************************************************************************/

/**
 * Implementation of hook_configuration().
 *
 * Connect the weightquote action and event.
 */
function uc_weightquote_configuration() {
  $enabled = variable_get('uc_quote_enabled', array());
  $configurations = array();
  $action = workflow_ng_use_action('uc_quote_action_get_quote', array(
    '#label' => t('Fetch a shipping quote'),
  ));
  $result = db_query("SELECT mid, title FROM {uc_weightquote_methods}");
  while ($method = db_fetch_object($result)) {
    $configurations['uc_weightquote_get_quote_' . $method->mid] = array(
      '#label' => t('Shipping quote via @method', array(
        '@method' => $method->title,
      )),
      '#event' => 'get_quote_from_weightquote_' . $method->mid,
      '#module' => 'uc_weightquote',
      '#active' => $enabled['weightquote_' . $method->mid],
    );
    $configurations['uc_weightquote_get_quote_' . $method->mid] = workflow_ng_configure($configurations['uc_weightquote_get_quote_' . $method->mid], $action);
  }
  return $configurations;
}

/******************************************************************************
 * Übercart Hooks                                                             *
 ******************************************************************************/

/**
 * Implementation of Übercart's hook_shipping_method().
 */
function uc_weightquote_shipping_method() {
  $methods = array();
  $enabled = variable_get('uc_quote_enabled', array());
  $weight = variable_get('uc_quote_method_weight', array());
  $result = db_query("SELECT mid, title, label FROM {uc_weightquote_methods}");
  while ($method = db_fetch_object($result)) {
    $methods['weightquote_' . $method->mid] = array(
      'id' => 'weightquote_' . $method->mid,
      'module' => 'uc_weightquote',
      'title' => $method->title,
      'enabled' => $enabled['weightquote_' . $method->mid],
      'quote' => array(
        'type' => 'order',
        'callback' => 'uc_weightquote_quote',
        'accessorials' => array(
          $method->label,
        ),
      ),
      'weight' => $weight['weightquote_' . $method->mid],
    );
  }
  return $methods;
}

/******************************************************************************
 * Menu Callbacks                                                             *
 ******************************************************************************/

/**
 * List and compare all weight quote shipping quote methods.
 */
function uc_weightquote_admin_methods() {
  $output = '';
  $rows = array();
  $enabled = variable_get('uc_quote_enabled', array());
  $weight = variable_get('uc_quote_method_weight', array());
  $result = db_query("SELECT mid, title, label, base_rate, unit_rate FROM {uc_weightquote_methods}");
  while ($method = db_fetch_object($result)) {
    $row = array();
    $row[] = check_plain($method->title);
    $row[] = check_plain($method->label);
    $row[] = uc_currency_format($method->base_rate);
    $row[] = uc_currency_format($method->unit_rate);
    $row[] = l(t('edit'), 'admin/store/settings/quotes/methods/weightquote/' . $method->mid . '/edit');
    $rows[] = $row;
  }
  if (count($rows)) {
    $header = array(
      t('Title'),
      t('Label'),
      t('Base rate'),
      t('Rate per !unit', array(
        '!unit' => variable_get('uc_weight_unit', 'lb'),
      )),
      t('Actions'),
    );
    $output .= theme('table', $header, $rows);
  }
  $output .= l(t('Add a new weight quote shipping method.'), 'admin/store/settings/quotes/methods/weightquote/add');
  return $output;
}

/**
 * Configure the store default product shipping rates.
 */
function uc_weightquote_admin_method_edit_form($mid = 0) {
  $form = array();
  $sign_flag = variable_get('uc_sign_after_amount', FALSE);
  $currency_sign = variable_get('uc_currency_sign', '$');
  if (is_numeric($mid) && ($method = db_fetch_object(db_query("SELECT * FROM {uc_weightquote_methods} WHERE mid = %d", $mid)))) {
    $form['mid'] = array(
      '#type' => 'value',
      '#value' => $mid,
    );
  }
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Shipping method title'),
    '#description' => t('The name shown to distinguish it from other weight quote methods.'),
    '#default_value' => $method->title,
  );
  $form['label'] = array(
    '#type' => 'textfield',
    '#title' => t('Line item label'),
    '#description' => t('The name shown to the customer when they choose a shipping method at checkout.'),
    '#default_value' => $method->label,
  );
  $form['base_rate'] = array(
    '#type' => 'textfield',
    '#title' => t('Base price'),
    '#description' => t('The starting price for shipping costs.'),
    '#default_value' => $method->base_rate,
    '#size' => 16,
    '#field_prefix' => $sign_flag ? '' : $currency_sign,
    '#field_suffix' => $sign_flag ? $currency_sign : '',
  );
  $form['unit_rate'] = array(
    '#type' => 'textfield',
    '#title' => t('Default cost adjustment per !unit', array(
      '!unit' => variable_get('uc_weight_unit', 'lb'),
    )),
    '#description' => t('The amount per weight unit to add to the shipping cost for an item.<br />Example: to add $5 per pound, put 5 in here.'),
    '#default_value' => $method->unit_rate,
    '#size' => 16,
    '#field_prefix' => $sign_flag ? '' : $currency_sign,
    '#field_suffix' => t('!sign per !unit', array(
      '!sign' => $sign_flag ? $currency_sign : '',
      '!unit' => variable_get('uc_weight_unit', 'lb'),
    )),
  );
  $form['buttons']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  $form['buttons']['delete'] = array(
    '#type' => 'submit',
    '#value' => t('Delete'),
  );
  return $form;
}
function uc_weightquote_admin_method_edit_form_validate($form_id, $form_values) {
  if ($form_values['op'] == t('Submit')) {
    if (!empty($form_values['base_rate']) && !is_numeric($form_values['base_rate'])) {
      form_set_error('base_rate', t('The base rate must be a numeric amount.'));
    }
    if (!empty($form_values['unit_rate']) && !is_numeric($form_values['unit_rate'])) {
      form_set_error('unit_rate', t('The adjustment per unit must be a numeric amount.'));
    }
  }
}
function uc_weightquote_admin_method_edit_form_submit($form_id, $form_values) {
  if ($form_values['op'] == t('Delete')) {
    drupal_goto('admin/store/settings/quotes/methods/weightquote/' . $form_values['mid'] . '/delete');
  }
  if ($form_values['mid']) {
    db_query("UPDATE {uc_weightquote_methods} SET title = '%s', label = '%s', base_rate = %f, unit_rate = %f WHERE mid = %d", $form_values['title'], $form_values['label'], $form_values['base_rate'], $form_values['unit_rate'], $form_values['mid']);
    drupal_set_message("Weight quote shipping method was updated.");
  }
  else {
    $mid = db_next_id("{uc_weightquote_methods}_mid");
    db_query("INSERT INTO {uc_weightquote_methods} (mid, title, label, base_rate, unit_rate) VALUES (%d, '%s', '%s', %f, %f)", $mid, $form_values['title'], $form_values['label'], $form_values['base_rate'], $form_values['unit_rate']);
    $enabled = variable_get('uc_quote_enabled', array());
    $enabled['weightquote_' . $mid] = true;
    variable_set('uc_quote_enabled', $enabled);
    $weight = variable_get('uc_quote_method_weight', array());
    $weight['weightquote_' . $mid] = 0;
    variable_set('uc_quote_method_weight', $weight);
    drupal_set_message("Created and enabled new weight quote shipping method.");
  }
  return 'admin/store/settings/quotes/methods/weightquote';
}
function uc_weightquote_admin_method_confirm_delete($mid) {
  $form = array();
  $form['mid'] = array(
    '#type' => 'value',
    '#value' => $mid,
  );
  return confirm_form($form, t('Do you want to delete this shipping method?'), 'admin/store/settings/quotes/methods/weightquote', t('This will remove the shipping method, workflow-ng configuration, and the
      product-specific overrides (if applicable). This action can not be undone.'), t('Delete'));
}
function uc_weightquote_admin_method_confirm_delete_submit($form_id, $form_values) {
  db_query("DELETE FROM {uc_weightquote_methods} WHERE mid = %d", $form_values['mid']);
  db_query("DELETE FROM {uc_weightquote_products} WHERE mid = %d", $form_values['mid']);
  db_query("DELETE FROM {workflow_ng_cfgs} WHERE name = '%s'", 'uc_weightquote_get_quote_by_' . $form_values['type'] . '_rate_' . $form_values['mid']);
  workflow_ng_clear_cache();
  $enabled = variable_get('uc_quote_enabled', array());
  unset($enabled['weightquote_' . $form_values['mid']]);
  variable_set('uc_quote_enabled', $enabled);
  $weight = variable_get('uc_quote_method_weight', array());
  unset($weight['weightquote_' . $form_values['mid']]);
  variable_set('uc_quote_method_weight', $weight);
  drupal_set_message('Weight quote shipping method deleted.');
  return 'admin/store/settings/quotes/methods/weightquote';
}

/******************************************************************************
 * Module Functions                                                           *
 ******************************************************************************/

/**
 * Standard callback to return a shipping rate via the weightquote method.
 *
 * @param $products
 *   The order's products.
 * @param $details
 *   Other order details including a shipping address.
 * @return
 *   A JSON object containing the shipping quote for the order.
 */
function uc_weightquote_quote($products, $details, $method) {
  $method = explode('_', $method['id']);
  $mid = $method[1];
  if ($method = db_fetch_object(db_query("SELECT * FROM {uc_weightquote_methods} WHERE mid = %d", $mid))) {
    $rate = $method->base_rate;
    foreach ($products as $product) {
      $product_weight = $product->weight * uc_weight_conversion($product->weight_units, variable_get('uc_weight_unit', 'lb'));
      if (is_null($product->weightquote)) {
        $rate += $method->unit_rate * $product->qty * $product_weight;
      }
      else {
        $rate += $product->weightquote[$mid] * $product->qty * $product_weight;
      }
    }
    $quotes[] = array(
      'rate' => $rate,
      'format' => uc_currency_format($rate),
      'option_label' => check_plain($method->label),
    );
  }
  return $quotes;
}

Functions

Namesort descending Description
uc_weightquote_admin_methods List and compare all weight quote shipping quote methods.
uc_weightquote_admin_method_confirm_delete
uc_weightquote_admin_method_confirm_delete_submit
uc_weightquote_admin_method_edit_form Configure the store default product shipping rates.
uc_weightquote_admin_method_edit_form_submit
uc_weightquote_admin_method_edit_form_validate
uc_weightquote_configuration Implementation of hook_configuration().
uc_weightquote_form_alter Implementation of hook_form_alter().
uc_weightquote_menu Implementation of hook_menu().
uc_weightquote_nodeapi Implementation of hook_nodeapi().
uc_weightquote_quote Standard callback to return a shipping rate via the weightquote method.
uc_weightquote_shipping_method Implementation of Übercart's hook_shipping_method().