'Shipping quote settings', 'description' => 'Configure the shipping quote settings.', 'page callback' => 'uc_quote_overview', 'access arguments' => array('configure quotes'), 'type' => MENU_NORMAL_ITEM, 'file' => 'uc_quote.admin.inc', ); $items['admin/store/settings/quotes/overview'] = array( 'title' => 'Overview', 'description' => 'View general shipping quote settings.', 'access arguments' => array('configure quotes'), 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['admin/store/settings/quotes/edit'] = array( 'title' => 'Quote settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_quote_admin_settings'), 'access arguments' => array('configure quotes'), 'weight' => -8, 'type' => MENU_LOCAL_TASK, 'file' => 'uc_quote.admin.inc', ); $items['admin/store/settings/quotes/methods'] = array( 'title' => 'Quote methods', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_quote_method_settings'), 'access arguments' => array('configure quotes'), 'weight' => -5, 'type' => MENU_LOCAL_TASK, 'file' => 'uc_quote.admin.inc', ); $items['admin/store/settings/quotes/methods/general'] = array( 'title' => 'General settings', 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['cart/checkout/shipping/quote'] = array( 'page callback' => 'uc_quote_request_quotes', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, 'file' => 'uc_quote.pages.inc', ); return $items; } /** * Implementation of hook_init(). */ function uc_quote_init() { drupal_add_css(drupal_get_path('module', 'uc_quote') .'/uc_quote.css', 'module'); global $conf; $conf['i18n_variables'][] = 'uc_quote_err_msg'; $conf['i18n_variables'][] = 'uc_quote_pane_description'; } /** * Implementation of hook_theme(). */ function uc_quote_theme() { return array( 'uc_quote_method_settings' => array( 'arguments' => array('form' => NULL), 'file' => 'uc_quote.admin.inc', ), 'uc_cart_pane_quotes' => array( 'arguments' => array('items' => NULL), ), ); } /** * Implementation of hook_nodeapi(). * * Load, save, and delete the shipping type and default shipping address of products. */ function uc_quote_nodeapi(&$node, $op, $arg3 = NULL, $arg4 = NULL) { if (uc_product_is_product($node->type)) { switch ($op) { case 'insert': case 'update': if (isset($node->shipping_type)) { uc_quote_set_shipping_type('product', $node->nid, $node->shipping_type); } db_query("DELETE FROM {uc_quote_product_locations} WHERE nid = %d", $node->nid); if ($node->street1) { db_query("INSERT INTO {uc_quote_product_locations} (nid, first_name, last_name, company, street1, street2, city, zone, postal_code, country, phone) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', %d, '%s')", $node->nid, $node->first_name, $node->last_name, $node->company, $node->street1, $node->street2, $node->city, $node->zone, $node->postal_code, $node->country, $node->phone ); } break; case 'load': $shipping_type = uc_product_get_shipping_type($node); $address = db_fetch_object(db_query("SELECT first_name, last_name, company, street1, street2, city, zone, postal_code, country, phone FROM {uc_quote_product_locations} WHERE nid = %d", $node->nid)); if ($address === FALSE) { $address = variable_get('uc_quote_store_default_address', new stdClass()); } return array('shipping_type' => $shipping_type, 'shipping_address' => $address); break; case 'delete': db_query("DELETE FROM {uc_quote_shipping_types} WHERE id_type = 'product' AND id = %d", $node->nid); db_query("DELETE FROM {uc_quote_product_locations} WHERE nid = %d", $node->nid); break; } } } /** * Implementation of hook_form_alter(). * * Add a default shipping address for products and manufacturers. If it is left * blank, products default to their manufacturers', which default to the store's. */ function uc_quote_form_alter(&$form, $form_state, $form_id) { // Alter the product node form. if (uc_product_is_product_form($form)) { // Get the shipping address. $address = $form['#node']->shipping_address; // Use the store default if the product does not have an address set. if (empty($address)) { $address = variable_get('uc_quote_store_default_address', new stdClass()); } // Store the country to use for the zone select based on $_POST. // TODO: Fix this for D6! Neither the $_POST or $form_state are available // when the node form is being processed. : ( if (isset($_POST['country'])) { $country = $_POST['country']; } else { $country = $address->country; } // Initialize the shipping fieldset array. if (!isset($form['shipping'])) { $form['shipping'] = array(); } $form['shipping'] += array( '#type' => 'fieldset', '#title' => t('Shipping settings'), '#collapsible' => TRUE, '#weight' => module_exists('content') ? content_extra_field_weight($form['#node']->type, 'shipping') : 0, '#attributes' => array('class' => 'product-shipping'), ); // Build the options for the default shipping type. $options = array('' => t('- Store default -')) + uc_quote_shipping_type_options(); $form['shipping']['shipping_type'] = array( '#type' => 'select', '#title' => t('Default product shipping type'), '#default_value' => uc_quote_get_shipping_type('product', $form['#node']->nid), '#options' => $options, '#weight' => -7, ); // Add the default pickup address fieldset. $form['shipping']['default_address'] = array( '#type' => 'fieldset', '#title' => t('Default product pickup address'), '#description' => t('When delivering products to customers, the original location of the product must be known in order to accurately quote the shipping cost and set up a delivery. If this pickup address is left blank, this product will default to the store pickup address.', array('!url' => url('admin/store/settings/quotes'))), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => -6, ); $form['shipping']['default_address']['first_name'] = uc_textfield(uc_get_field_name('first_name'), $address->first_name, FALSE); $form['shipping']['default_address']['last_name'] = uc_textfield(uc_get_field_name('last_name'), $address->last_name, FALSE); $form['shipping']['default_address']['company'] = uc_textfield(uc_get_field_name('company'), $address->company, FALSE); $form['shipping']['default_address']['street1'] = uc_textfield(uc_get_field_name('street1'), $address->street1, FALSE, NULL, 64); $form['shipping']['default_address']['street2'] = uc_textfield(uc_get_field_name('street2'), $address->street2, FALSE, NULL, 64); $form['shipping']['default_address']['city'] = uc_textfield(uc_get_field_name('city'), $address->city, FALSE); $form['shipping']['default_address']['zone'] = uc_zone_select(uc_get_field_name('zone'), $address->zone, NULL, $country); $form['shipping']['default_address']['postal_code'] = uc_textfield(uc_get_field_name('postal_code'), $address->postal_code, FALSE, NULL, 10, 10); $form['shipping']['default_address']['country'] = uc_country_select(uc_get_field_name('country'), $address->country); } // Add quote selection form handlers to the checkout form. if ($form_id == 'uc_cart_checkout_form' && isset($form['panes']['quotes'])) { $form['#validate'][] = 'uc_quote_save_choice'; $form['#pre_render'][] = 'uc_quote_cache_quotes'; } } /****************************************************************************** * CCK Hooks * ******************************************************************************/ /** * Implementation of hook_content_extra_fields(). */ function uc_quote_content_extra_fields($type_name) { $type = node_get_types('type', $type_name); $extra = array(); if ($type->module == 'uc_product') { $extra['shipping'] = array( 'label' => t('Shipping'), 'description' => t('Shipping settings form.'), 'weight' => 0, ); } return $extra; } /****************************************************************************** * Conditional Actions Hooks * ******************************************************************************/ /** * Implementation of hook_ca_trigger(). * * Register an event for each shipping method. Enabled methods have active * configurations. */ function uc_quote_ca_trigger() { $methods = module_invoke_all('shipping_method'); $triggers = array(); foreach ($methods as $id => $method) { $triggers['get_quote_from_'. $id] = array( '#title' => t('Getting shipping quote via !method', array('!method' => $method['title'])), '#category' => t('Quote'), '#hidden' => TRUE, '#arguments' => array( 'order' => array('#entity' => 'uc_order', '#title' => t('Order')), 'method' => array('#entity' => 'quote_method', '#title' => t('Quote method')), 'account' => array('#entity' => 'user', '#title' => t('User account')), ), ); } return $triggers; } /** * Implementation of hook_ca_condition(). */ function uc_quote_ca_condition() { return array( 'uc_quote_condition_product_shipping_type' => array( '#title' => t("Order has a product of a particular shipping type"), '#category' => t('Order: Product'), '#callback' => 'uc_quote_condition_product_shipping_type', '#arguments' => array( 'order' => array('#entity' => 'uc_order', '#title' => t('Order')), ), ), 'uc_quote_condition_order_shipping_method' => array( '#title' => t("Order has a shipping quote from a particular method"), '#category' => t('Order: Shipping Quote'), '#callback' => 'uc_quote_condition_order_shipping_method', '#arguments' => array( 'order' => array('#entity' => 'uc_order', '#title' => t('Order')), ), ), ); } /** * Return TRUE if the order has a product of the chosen shipping type. * * @see uc_quote_condition_product_shipping_type_form() */ function uc_quote_condition_product_shipping_type($order, $settings) { $result = FALSE; foreach ($order->products as $product) { if ($product->nid && uc_product_get_shipping_type($product) == $settings['type']) { $result = TRUE; break; } } return $result; } /** * Settings form for uc_quote_condition_product_shipping_type(). * * @ingroup forms * @see uc_quote_condition_product_shipping_type() */ function uc_quote_condition_product_shipping_type_form($form_state, $settings = array()) { $form = array(); $options = array(); $types = uc_quote_get_shipping_types(); foreach ($types as $id => $type) { $options[$id] = $type['title']; } $form['type'] = array('#type' => 'select', '#title' => t('Shipping type'), '#options' => $options, '#default_value' => $settings['type'], ); return $form; } /** * Check an order's shipping method. * * @see uc_quote_condition_order_shipping_method_form() */ function uc_quote_condition_order_shipping_method($order, $settings) { // Check the easy way first. if (is_array($order->quote)) { return $order->quote['method'] == $settings['method']; } // Otherwise, look harder. if (is_array($order->line_items)) { $methods = module_invoke_all('shipping_method'); $accessorials = $methods[$settings['method']]['quote']['accessorials']; foreach ($order->line_items as $line_item) { if ($line_item['type'] == 'shipping' && in_array($line_item['title'], $accessorials)) { return TRUE; } } } return FALSE; } /** * @ingroup forms * @see uc_quote_condition_order_shipping_method() */ function uc_quote_condition_order_shipping_method_form($form_state, $settings = array()) { $form = array(); $methods = module_invoke_all('shipping_method'); $enabled = variable_get('uc_quote_enabled', array()); $options = array(); foreach ($methods as $id => $method) { $options[$id] = $method['title']; if (!$enabled[$id]) { $options[$id] .= ' '. t('(disabled)'); } } $form['method'] = array( '#type' => 'select', '#title' => t('Shipping quote method'), '#default_value' => $settings['method'], '#options' => $options, ); return $form; } /** * Implementation of hook_ca_action(). */ function uc_quote_ca_action() { return array( 'uc_quote_action_get_quote' => array( '#title' => t('Fetch a shipping quote'), '#category' => t('Quote'), '#arguments' => array( 'order' => array('#entity' => 'uc_order', '#title' => t('Order')), 'method' => array('#entity' => 'quote_method', '#title' => t('Quote method')), ), ), ); } /** * Retrieve shipping quote. * * @param $order * The order the quote is for. * @param $method * The shipping method to generate the quote. * @return * Array of shipping quotes. */ function uc_quote_action_get_quote($order, $method) { $details = array(); foreach ($order as $key => $value) { if (substr($key, 0, 9) == 'delivery_') { $field = substr($key, 9); $details[$field] = $value; } } ob_start(); // Load include file containing quote callback, if there is one if (isset($method['quote']['file'])) { $inc_file = drupal_get_path('module', $method['module']) .'/'. $method['quote']['file']; if (is_file($inc_file)) { require_once($inc_file); } } if (function_exists($method['quote']['callback'])) { // This feels wrong, but it's the only way I can ensure that shipping // methods won't mess up the products in their methods. $products = array(); foreach ($order->products as $key => $item) { if (uc_cart_product_is_shippable($item)) { $products[$key] = drupal_clone($item); } } $quote_data = call_user_func($method['quote']['callback'], $products, $details, $method); } $messages = ob_get_contents(); ob_end_clean(); //drupal_set_message('
'. print_r($quote_data, TRUE) .'
'); if ($messages && variable_get('uc_quote_log_errors', FALSE)) { watchdog('quote', '!messages', array('!messages' => $messages), WATCHDOG_WARNING); watchdog('quote', '
@data
', array('@data' => print_r($quote_data, TRUE)), WATCHDOG_WARNING); } return $quote_data; } /****************************************************************************** * Ubercart Hooks * ******************************************************************************/ /** * Implementation of hook_cart_pane(). */ function uc_quote_cart_pane($items) { if (arg(0) == 'cart') { if (!variable_get('uc_cap_quotes_enabled', FALSE) || (variable_get('uc_cart_delivery_not_shippable', TRUE) && !uc_cart_is_shippable())) { return array(); } } $panes[] = array('id' => 'quotes', 'title' => t('Shipping quotes'), 'enabled' => FALSE, 'weight' => 5, 'body' => drupal_get_form('uc_cart_pane_quotes', $items), ); return $panes; } /** * Define the shipping quote checkout pane. */ function uc_quote_checkout_pane() { $panes[] = array('id' => 'quotes', 'callback' => 'uc_checkout_pane_quotes', 'title' => t('Calculate shipping cost'), 'desc' => t('Extra information necessary to ship.'), 'weight' => 5, 'shippable' => TRUE, ); return $panes; } /** * Defines the shipping quote order pane. */ function uc_quote_order_pane() { $panes = array(); $panes[] = array( 'id' => 'quotes', 'callback' => 'uc_order_pane_quotes', 'title' => t('Shipping quote'), 'desc' => t('Get a shipping quote for the order from a quoting module.'), 'class' => 'abs-left', 'weight' => 7, 'show' => array('edit'), ); return $panes; } /** * Implementation of hook_add_to_cart(). */ function uc_quote_add_to_cart() { unset($_SESSION['quote']); } /** * Implementation of hook_update_cart_item(). */ function uc_quote_update_cart_item() { unset($_SESSION['quote']); } /** * Implementation of hook_order(). */ function uc_quote_order($op, &$arg1, $arg2) { switch ($op) { case 'submit': unset($_SESSION['quote']); break; case 'save': db_query("DELETE FROM {uc_order_quotes} WHERE order_id = %d", $arg1->order_id); db_query("INSERT INTO {uc_order_quotes} (order_id, method, accessorials, rate, quote_form) VALUES (%d, '%s', '%s', %f, '%s')", $arg1->order_id, $arg1->quote['method'], $arg1->quote['accessorials'], $arg1->quote['rate'], $arg1->quote['quote_form']); break; case 'load': $quote = db_fetch_array(db_query("SELECT method, accessorials, rate, quote_form FROM {uc_order_quotes} WHERE order_id = %d", $arg1->order_id)); $arg1->quote = $quote; $arg1->quote['accessorials'] = strval($quote['accessorials']); break; case 'delete': db_query("DELETE FROM {uc_order_quotes} WHERE order_id = %d", $arg1->order_id); break; } } /** * Implementation of hook_line_item(). */ function uc_quote_line_item() { $items[] = array( 'id' => 'shipping', 'title' => t('Shipping'), 'weight' => 1, 'default' => FALSE, 'stored' => TRUE, 'calculated' => TRUE, 'display_only' => FALSE, 'add_list' => TRUE, ); return $items; } /** * Implementation of hook_shipping_type(). */ function uc_quote_shipping_type() { $weight = variable_get('uc_quote_type_weight', array('small_package' => 0)); $types = array(); $types['small_package'] = array( 'id' => 'small_package', 'title' => t('Small package'), 'weight' => $weight['small_package'], ); return $types; } /****************************************************************************** * Module Functions * ******************************************************************************/ /** * Store the shipping type of products and manufacturers. * * Fulfillment modules are invoked for products that match their shipping type. * This function stores the shipping type of a product or a manufacturer. * * @param $id_type * product | manufacturer * @param $id * Either the node id or term id of the object receiving the shipping type. * @param $shipping_type * The type of product that is fulfilled by various fulfillment modules. */ function uc_quote_set_shipping_type($id_type, $id, $shipping_type) { db_query("DELETE FROM {uc_quote_shipping_types} WHERE id_type = '%s' AND id = %d", $id_type, $id); if ($shipping_type !== '') { db_query("INSERT INTO {uc_quote_shipping_types} (id_type, id, shipping_type) VALUES ('%s', %d, '%s')", $id_type, $id, $shipping_type); } } /** * Retrieve a product's or manufacturer's shipping type from the database. * * @param $id_type * product | manufacturer * @param $id * Either the node id or term id of the object that was assigned the shipping type. * @return The shipping type. */ function uc_quote_get_shipping_type($id_type, $id) { static $types = array(); if (!isset($types[$id_type][$id])) { $types[$id_type][$id] = db_result(db_query("SELECT shipping_type FROM {uc_quote_shipping_types} WHERE id_type = '%s' AND id = %d", $id_type, $id)); } return $types[$id_type][$id]; } /** * Get a product's shipping type, defaulting to the store's if it doesn't exist. * * @param $product * The product object. * @return The shipping type. */ function uc_product_get_shipping_type($product) { $shipping_type = variable_get('uc_store_shipping_type', 'small_package'); if ($type = uc_quote_get_shipping_type('product', $product->nid)) { $shipping_type = $type; } return $shipping_type; } /** * Get a product's default shipping address. * * Load the default shipping address of a product, it's manufacturer's, or the * store's, whichever is available. * * @param $nid * A product node id. * @return * An address object. */ function uc_quote_get_default_shipping_address($nid) { $address = db_fetch_object(db_query("SELECT first_name, last_name, company, street1, street2, city, zone, postal_code, country, phone FROM {uc_quote_product_locations} WHERE nid = %d", $nid)); if (empty($address)) { $address = variable_get('uc_quote_store_default_address', new stdClass()); } return $address; } /** * Cart pane callback. * * @ingroup forms * @see theme_uc_cart_pane_quotes() */ function uc_cart_pane_quotes($items) { global $user; // Get all quote types neccessary to fulfill order. $shipping_types = array(); foreach ($items as $product) { $shipping_types[] = uc_product_get_shipping_type($product); } $shipping_types = array_unique($shipping_types); $all_types = uc_quote_get_shipping_types(); $shipping_type = ''; $type_weight = 1000; // arbitrary large number foreach ($shipping_types as $type) { if ($all_types[$type]['weight'] < $type_weight) { $shipping_type = $all_types[$type]['id']; $type_weight = $all_types[$type]['weight']; } } $methods = array_filter(module_invoke_all('shipping_method'), '_uc_quote_method_enabled'); uasort($methods, '_uc_quote_type_sort'); $method_choices = array(); foreach ($methods as $method) { if ($method['quote']['type'] == 'order' || $method['quote']['type'] == $shipping_type) { $method_choices[$method['id']] = $method['title']; } } $form['delivery_country'] = uc_country_select(uc_get_field_name('country'), uc_store_default_country(), NULL, 'name', TRUE); $country_id = isset($_POST['delivery_country']) ? intval($_POST['delivery_country']) : uc_store_default_country(); $form['delivery_zone'] = uc_zone_select(uc_get_field_name('zone'), NULL, NULL, $country_id, 'name', TRUE); $form['delivery_postal_code'] = uc_textfield(uc_get_field_name('postal_code'), '', TRUE, NULL, 10, 10); $form['quote_method'] = array('#type' => 'hidden', '#value' => key($method_choices), ); $form['get_quote'] = array('#type' => 'button', '#value' => t('Calculate'), ); $form['page'] = array('#type' => 'hidden', '#value' => 'cart', ); $form['uid'] = array('#type' => 'hidden', '#value' => $user->uid, ); $form['quote'] = array('#type' => 'markup', '#value' => '
', ); drupal_add_js(array( 'uc_quote' => array( 'progress_msg' => t('Receiving quotes:'), 'err_msg' => check_markup(variable_get('uc_quote_err_msg', t("There were problems getting a shipping quote. Please verify the delivery and product information and try again.\nIf this does not resolve the issue, please call in to complete your order.")), variable_get('uc_quote_msg_format', FILTER_FORMAT_DEFAULT), FALSE), ), 'ucURL' => array( 'shippingQuotes' => url('cart/checkout/shipping/quote'), ), ), 'setting'); drupal_add_js('misc/progress.js'); drupal_add_js(drupal_get_path('module', 'uc_quote') .'/uc_quote.js'); $prod_string = ''; foreach ($items as $item) { $prod_string .= '|'. $item->nid; $prod_string .= '^'. $item->title; $prod_string .= '^'. $item->model; $prod_string .= '^'. $item->manufacturer; $prod_string .= '^'. $item->qty; $prod_string .= '^'. $item->cost; $prod_string .= '^'. $item->price; $prod_string .= '^'. $item->weight; $prod_string .= '^'. serialize($item->data); } $prod_string = substr($prod_string, 1); // If a previous quote gets loaded, make sure it gets saved again. // Also, make sure the previously checked option is checked by default. drupal_add_js('$(function() { setQuoteCallbacks("'. drupal_urlencode($prod_string) .'"); $("#uc-cart-pane-quotes").submit(function() { quoteCallback("'. drupal_urlencode($prod_string) .'"); return false; }); })', 'inline'); return $form; } /** * Display the formatted quote cart pane. * * @ingroup themeable */ function theme_uc_cart_pane_quotes($form) { $output = '
'; $output .= ''. t('Estimated shipping cost:') .''; $output .= drupal_render($form['delivery_country']); $output .= drupal_render($form['delivery_zone']); $output .= drupal_render($form['delivery_postal_code']); $output .= drupal_render($form['get_quote']); $output .= drupal_render($form); $output .= '
'; return $output; } /** * Shipping quote checkout pane callback. * * Selects a quoting method based on the enabled methods' weight and the types * of products in the cart. The "Get Quotes" button fires a callback that returns * a form for the customer to select a rate based on their needs and preferences. * * Adds a line item to the order that records the chosen shipping quote. */ function uc_checkout_pane_quotes($op, &$arg1, $arg2) { global $user; switch ($op) { case 'view': $description = check_markup(variable_get('uc_quote_pane_description', t('Shipping quotes are generated automatically when you enter your address and may be updated manually with the button below.')), variable_get('uc_quote_desc_format', FILTER_FORMAT_DEFAULT), FALSE); // Let Javascript know where we are. $contents['page'] = array('#type' => 'hidden', '#value' => 'checkout', ); $contents['uid'] = array('#type' => 'hidden', '#value' => $user->uid, ); $contents['quote_button'] = array( '#type' => 'button', '#value' => t('Click to calculate shipping'), '#weight' => 0, ); drupal_add_js(array( 'uc_quote' => array( 'progress_msg' => t('Receiving quotes...'), 'err_msg' => check_markup(variable_get('uc_quote_err_msg', t("There were problems getting a shipping quote. Please verify the delivery address and product information and try again.\nIf this does not resolve the issue, please call @phone to complete your order.", array('@phone' => variable_get('uc_store_phone', NULL)))), variable_get('uc_quote_msg_format', FILTER_FORMAT_DEFAULT), FALSE), ), 'ucURL' => array( 'shippingQuotes' => url('cart/checkout/shipping/quote'), ), ), 'setting'); drupal_add_js('misc/progress.js'); drupal_add_js(drupal_get_path('module', 'uc_quote') .'/uc_quote.js'); $default = $arg1->quote['method'] .'---'. ($arg1->quote['accessorials'] ? $arg1->quote['accessorials'] : 0); $prod_string = ''; foreach (uc_cart_get_contents() as $item) { $prod_string .= '|'. $item->nid; $prod_string .= '^'. $item->title; $prod_string .= '^'. $item->model; $prod_string .= '^'. $item->manufacturer; $prod_string .= '^'. $item->qty; $prod_string .= '^'. $item->cost; $prod_string .= '^'. $item->price; $prod_string .= '^'. $item->weight; $prod_string .= '^'. serialize($item->data); } $prod_string = substr($prod_string, 1); // If a previous quote gets loaded, make sure it gets saved again. // Also, make sure the previously checked option is checked by default. drupal_add_js(' Drupal.behaviors.getQuotes = function (context) { setQuoteCallbacks("'. drupal_urlencode($prod_string) .'", context); }; $(function() { var quoteButton = $("input:radio[name=quote-option]").click(function() { var quoteButton = $(this); var label = quoteButton.parent("label").text().split(":", 2)[0]; var rate = $("input:hidden[name=\'rate[" + quoteButton.val() + "]\']").val(); set_line_item("shipping", label, rate, 1, 1, false); if (window.getTax) { getTax(); } else if (window.render_line_items) { render_line_items(); } }).filter("[value='. $default .']").click(); var quoteDiv = $("#quote"); if (quoteDiv.length && $("#quote input[name=quote-form]").length == 0) { quoteDiv.append(""); } });', 'inline'); return array('description' => $description, 'contents' => $contents); case 'process': if (!isset($_POST['quote-option'])) { if (variable_get('uc_quote_require_quote', TRUE)) { drupal_set_message(t('You must select a shipping option before continuing.'), 'error'); return FALSE; } else { return TRUE; } } $details = array(); foreach ($arg1 as $key => $value) { if (strpos($key, 'delivery_') !== FALSE) { $details[substr($key, 9)] = $value; } } $products = array(); foreach ($arg1->products as $id => $product) { $node = (array)node_load($product->nid); foreach ($node as $key => $value) { if (!isset($product->$key)) { $product->$key = $value; } } $arg1->products[$id] = $product; } $quote_option = explode('---', $_POST['quote-option']); $arg1->quote['method'] = $quote_option[0]; $arg1->quote['accessorials'] = $quote_option[1]; $_SESSION['quote']['quote_form'] = rawurldecode($_POST['quote-form']); $methods = array_filter(module_invoke_all('shipping_method'), '_uc_quote_method_enabled'); $method = $methods[$quote_option[0]]; $quote_data = array(); $arguments = array( 'order' => array( '#entity' => 'uc_order', '#title' => t('Order'), '#data' => $arg1, ), 'method' => array( '#entity' => 'quote_method', '#title' => t('Quote method'), '#data' => $method, ), 'account' => array( '#entity' => 'user', '#title' => t('User'), '#data' => $user, ), ); $predicates = ca_load_trigger_predicates('get_quote_from_'. $method['id']); $predicate = array_shift($predicates); if ($predicate && ca_evaluate_conditions($predicate, $arguments)) { $quote_data = uc_quote_action_get_quote($arg1, $method, $user); } if (!isset($quote_data[$quote_option[1]])) { drupal_set_message(t('Invalid option selected. Recalculate shipping quotes to continue.'), 'error'); return FALSE; } $label = $method['quote']['accessorials'][$quote_option[1]]; $arg1->quote['rate'] = $quote_data[$quote_option[1]]['rate']; $result = db_query("SELECT line_item_id FROM {uc_order_line_items} WHERE order_id = %d AND type = 'shipping'", $arg1->order_id); if ($lid = db_result($result)) { uc_order_update_line_item($lid, $label, $arg1->quote['rate'] ); } else { uc_order_line_item_add($arg1->order_id, 'shipping', $label, $arg1->quote['rate'] ); } return TRUE; case 'review': $context = array( 'revision' => 'themed', 'type' => 'line_item', 'subject' => array('order' => $arg1), ); $result = db_query("SELECT * FROM {uc_order_line_items} WHERE order_id = %d AND type = '%s'", $arg1->order_id, 'shipping'); if ($line_item = db_fetch_array($result)) { $context['subject']['line_item'] = $line_item; $review[] = array('title' => $line_item['title'], 'data' => uc_price($line_item['amount'], $context)); } return $review; } } /** * Shipping quote order pane callback. */ function uc_order_pane_quotes($op, $arg1) { switch ($op) { case 'edit-form': // Let Javascript know where we are. $form['quotes']['page'] = array( '#type' => 'hidden', '#value' => 'order-edit', ); $form['quotes']['quote_button'] = array( '#type' => 'submit', '#value' => t('Get shipping quotes'), ); $form['quotes']['add_quote'] = array( '#type' => 'submit', '#value' => t('Apply to order'), '#attributes' => array('class' => 'save-button'), '#disabled' => TRUE, ); $form['quotes']['quote'] = array( '#type' => 'markup', '#value' => '
', ); drupal_add_js(array( 'uc_quote' => array( 'progress_msg' => t('Receiving quotes...'), 'err_msg' => check_markup(variable_get('uc_quote_err_msg', t("There were problems getting a shipping quote. Please verify the delivery and product information and try again.\nIf this does not resolve the issue, please call in to complete your order.")), variable_get('uc_quote_msg_format', FILTER_FORMAT_DEFAULT), FALSE), ), 'ucURL' => array( 'shippingQuotes' => url('cart/checkout/shipping/quote'), ), ), 'setting'); drupal_add_js('misc/progress.js'); drupal_add_js(drupal_get_path('module', 'uc_quote') .'/uc_quote.js'); $default = $arg1->quote['accessorials'] ? $arg1->quote['accessorials'] : 0; // If a previous quote gets loaded, make sure it gets saved again. // Also, make sure the previously checked option is checked by default. drupal_add_js('$(function() { setQuoteCallbacks(); $("input:radio[name=quote-option]").filter("[value='. $default .']").attr("checked", "checked"); var quoteDiv = $("#quote"); if (quoteDiv.length && $("#quote input[name=quote-form]").length == 0) { quoteDiv.append(""); } })', 'inline'); return $form; case 'edit-theme': return drupal_render($arg1['quotes']); case 'edit-process': if (isset($_POST['quote-option'])) { list($changes['quote']['method'], $changes['quote']['accessorials']) = explode('---', $_POST['quote-option']); $changes['quote']['rate'] = $_POST['rate'][$_POST['quote-option']]; $changes['quote']['quote_form'] = rawurldecode($_POST['quote-form']); } return $changes; case 'edit-ops': return array(t('Apply to order')); case t('Apply to order'): if (isset($_POST['quote-option'])) { if ($order = uc_order_load($arg1['order_id'])) { $user = user_load(array('uid' => $order->uid)); $products = array(); foreach ($order->products as $product) { if ($product->nid) { $node = (array)node_load($product->nid); foreach ($node as $key => $value) { if (!isset($product->$key)) { $product->$key = $value; } } } $products[] = $product; } //drupal_set_message('
'. print_r($order, TRUE) .'
'); $quote_option = explode('---', $_POST['quote-option']); $order->quote['method'] = $quote_option[0]; $order->quote['accessorials'] = $quote_option[1]; $order->quote['quote_form'] = rawurldecode($_POST['quote-form']); $methods = array_filter(module_invoke_all('shipping_method'), '_uc_quote_method_enabled'); $method = $methods[$quote_option[0]]; $quote_data = array(); $predicate = ca_load_trigger_predicates('get_quote_from_'. $method['id']); $arguments = array( 'order' => array( '#entity' => 'uc_order', '#title' => t('Order'), '#data' => $arg1, ), 'method' => array( '#entity' => 'quote_method', '#title' => t('Quote method'), '#data' => $method, ), 'account' => array( '#entity' => 'user', '#title' => t('User'), '#data' => $user, ), ); if (ca_evaluate_conditions($predicate, $arguments)) { $quote_data = uc_quote_action_get_quote($order, $method, $user); } //drupal_set_message('Chosen quote method:
'. print_r($method, TRUE) .'
'); //drupal_set_message('Chosen quote data:
'. print_r($quote_data, TRUE) .'
'); if (!isset($quote_data[$quote_option[1]])) { drupal_set_message(t('Invalid option selected. Recalculate shipping quotes to continue.'), 'error'); break; } $label = $method['quote']['accessorials'][$quote_option[1]]; $order->quote['rate'] = $quote_data[$quote_option[1]]['rate']; $result = db_query("SELECT line_item_id FROM {uc_order_line_items} WHERE order_id = %d AND type = 'shipping'", $arg1['order_id']); if ($lid = db_result($result)) { uc_order_update_line_item($lid, $label, $order->quote['rate'] ); } else { uc_order_line_item_add($order->order_id, 'shipping', $label, $order->quote['rate'] ); } } } break; } } /** * Validate handler added to uc_cart_checkout_form(). * * Save the choice of shipping method in the customer's session. */ function uc_quote_save_choice($form, &$form_state) { $quote_option = explode('---', $_POST['quote-option']); $_SESSION['quote'] = array('method' => $quote_option[0], 'accessorials' => $quote_option[1], 'rate' => $_POST['rate'][$_POST['quote-option']], 'quote_form' => $_POST['quote-form'], ); } /** * Pre-render callback added to uc_cart_checkout_form(). * * Render the shipping quotes without an asynchronous call to create them if a * choice had been cached in the session. */ function uc_quote_cache_quotes($form) { if ($form['#id'] == 'uc-cart-checkout-form') { if (isset($_SESSION['quote']) && isset($_SESSION['quote']['rate'])) { $quote = $_SESSION['quote']; $form['panes']['quotes']['quote'] = array('#type' => 'markup', '#value' => '
'. rawurldecode($_SESSION['quote']['quote_form']) .'
', '#weight' => 1, ); $methods = module_invoke_all('shipping_method'); $method = $methods[$quote['method']]; drupal_add_js('if (Drupal.jsEnabled) { $(document).ready(function() { $("#quote").find("input:radio[value='. $quote['method'] .'---'. $quote['accessorials'] .']").eq(0).change().attr("checked", "checked"); if (window.set_line_item) { set_line_item("shipping", "'. $method['quote']['accessorials'][$quote['accessorials']] .'", '. $quote['rate'] .', 1, 1, false); } if (window.getTax) { getTax(); setTaxCallbacks(); } else if (window.render_line_items) { render_line_items(); } })};', 'inline'); } else { $form['panes']['quotes']['quote'] = array('#type' => 'markup', '#value' => '
', '#weight' => 1, ); } } return $form; } /** * Callback for array_filter(). */ function _uc_quote_method_enabled($method) { return $method['enabled']; } /** * Callback for uasort(). */ function _uc_quote_type_sort($a, $b) { $aw = $a['weight']; $bw = $b['weight']; if ($aw == $bw) { return strcasecmp($a['id'], $b['id']); } else { return ($aw < $bw) ? -1 : 1; } } /** * Callback for uasort(). * * Sort service rates by increasing price. */ function uc_quote_price_sort($a, $b) { $ar = $a['rate']; $br = $b['rate']; if ($ar == $br) { return 0; } else { return ($ar < $br) ? -1 : 1; } } /** * Return an array of quote types to be selected in a form. */ function uc_quote_type_options() { $methods = module_invoke_all('shipping_method'); foreach ($methods as $method) { if (isset($method['quote'])) { $types[$method['id']] = $method['title']; } } return $types; } /** * Return an options array of shipping types. */ function uc_quote_shipping_type_options() { $types = array(); $ship_types = uc_quote_get_shipping_types(); uasort($ship_types, '_uc_quote_type_sort'); foreach ($ship_types as $ship_type) { $types[$ship_type['id']] = $ship_type['title']; } if (empty($types)) { $types['small_package'] = t('Small package'); } return $types; } /** * Return an array of shipping types. */ function uc_quote_get_shipping_types() { $args = array(); $hook = 'shipping_type'; $return = array(); foreach (module_implements($hook) as $module) { $function = $module .'_'. $hook; $result = call_user_func_array($function, $args); if (isset($result) && is_array($result)) { $return = array_merge($return, $result); } elseif (isset($result)) { $return[] = $result; } } return $return; } /** * Return an options array of shipping methods. */ function uc_quote_shipping_method_options() { $methods = module_invoke_all('shipping_method'); uasort($methods, '_uc_quote_type_sort'); $types = array(); foreach ($methods as $method) { if (isset($method['quote'])) { $types[$method['id']] = $method['title']; } } return $types; }