'USPS', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_usps_admin_settings'), 'access arguments' => array('configure quotes'), 'type' => MENU_LOCAL_TASK, 'file' => 'uc_usps.admin.inc', ); return $items; } /** * Implements hook_theme(). */ function uc_usps_theme() { return array( 'uc_usps_option_label' => array( 'variables' => array( 'service' => NULL, 'packages' => NULL, ), 'file' => 'uc_usps.theme.inc', ), ); } /** * Implements hook_form_alter(). * * Adds package type to products. * * @see uc_product_form() */ function uc_usps_form_alter(&$form, &$form_state, $form_id) { if (uc_product_is_product_form($form)) { $node = $form['#node']; $enabled = variable_get('uc_quote_enabled', array()) + array('usps' => FALSE, 'usps_intl' => FALSE); $weight = variable_get('uc_quote_method_weight', array()) + array('usps' => 0, 'usps_intl' => 1); $form['shipping']['usps'] = array( '#type' => 'fieldset', '#title' => t('USPS product description'), '#collapsible' => TRUE, '#collapsed' => ($enabled['usps'] == FALSE || uc_product_get_shipping_type($node) != 'small_package'), '#weight' => $weight['usps'], '#tree' => TRUE, ); $form['shipping']['usps']['container'] = array( '#type' => 'select', '#title' => t('Package type'), '#options' => _uc_usps_pkg_types(), '#default_value' => isset($node->usps['container']) ? $node->usps['container'] : 'VARIABLE', ); } } /** * Implements hook_node_insert(). */ function uc_usps_node_insert($node) { uc_usps_node_update($node); } /** * Implements hook_node_update(). */ function uc_usps_node_update($node) { if (uc_product_is_product($node->type)) { if (isset($node->usps)) { $usps_values = $node->usps; if (empty($node->revision)) { db_delete('uc_usps_products') ->condition('vid', $node->vid) ->execute(); } db_insert('uc_usps_products') ->fields(array( 'vid' => $node->vid, 'nid' => $node->nid, 'container' => $usps_values['container'], )) ->execute(); } } } /** * Implements hook_node_load(). */ function uc_usps_node_load($nodes, $types) { $product_types = array_intersect(uc_product_types(), $types); if (empty($product_types)) { return; } $vids = array(); $shipping_type = variable_get('uc_store_shipping_type', 'small_package'); $shipping_types = db_query("SELECT id, shipping_type FROM {uc_quote_shipping_types} WHERE id_type = :type AND id IN (:ids)", array(':type' => 'product', ':ids' => array_keys($nodes)))->fetchAllKeyed(); foreach ($nodes as $nid => $node) { if (!in_array($node->type, $product_types)) { continue; } if (isset($shipping_types[$nid])) { $node->shipping_type = $shipping_types[$nid]; } else { $node->shipping_type = $shipping_type; } if ($node->shipping_type == 'small_package') { $vids[$nid] = $node->vid; } } if ($vids) { $result = db_query("SELECT * FROM {uc_usps_products} WHERE vid IN (:vids)", array(':vids' => $vids), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $usps) { $nodes[$usps['nid']]->usps = $usps; } } } /** * Implements hook_node_delete(). */ function uc_usps_node_delete($node) { db_delete('uc_usps_products') ->condition('nid', $node->nid) ->execute(); } /** * Implements hook_node_revision_delete(). */ function uc_usps_node_revision_delete($node) { db_delete('uc_usps_products') ->condition('vid', $node->vid) ->execute(); } /****************************************************************************** * Ubercart Hooks * ******************************************************************************/ /** * Implements hook_uc_shipping_type(). */ function uc_usps_uc_shipping_type() { $weight = variable_get('uc_quote_type_weight', array('envelope' => -1, 'small_package' => 0)); $types = array( 'envelope' => array( 'id' => 'envelope', 'title' => t('Envelope'), 'weight' => isset($weight['envelope']) ? $weight['envelope'] : -1, ), 'small_package' => array( 'id' => 'small_package', 'title' => t('Small package'), 'weight' => isset($weight['small_package']) ? $weight['small_package'] : 0, ), ); return $types; } /** * Implements hook_uc_shipping_method(). */ function uc_usps_uc_shipping_method() { $operations = array( 'configure' => array( 'title' => t('configure'), 'href' => 'admin/store/settings/quotes/settings/usps', ), ); $methods = array( 'usps_env' => array( 'id' => 'usps_env', 'module' => 'uc_usps', 'title' => t('U.S. Postal Service (Envelope)'), 'operations' => $operations, 'quote' => array( 'type' => 'envelope', 'callback' => 'uc_usps_quote', 'accessorials' => _uc_usps_env_services(), ), ), 'usps' => array( 'id' => 'usps', 'module' => 'uc_usps', 'title' => t('U.S. Postal Service (Parcel)'), 'operations' => $operations, 'quote' => array( 'type' => 'small_package', 'callback' => 'uc_usps_quote', 'accessorials' => _uc_usps_services(), ), ), 'usps_intl_env' => array( 'id' => 'usps_intl_env', 'module' => 'uc_usps', 'title' => t('U.S. Postal Service (Intl., Envelope)'), 'operations' => $operations, 'quote' => array( 'type' => 'envelope', 'callback' => 'uc_usps_quote', 'accessorials' => _uc_usps_intl_env_services(), ), 'weight' => 1, ), 'usps_intl' => array( 'id' => 'usps_intl', 'module' => 'uc_usps', 'title' => t('U.S. Postal Service (Intl., Parcel)'), 'operations' => $operations, 'quote' => array( 'type' => 'small_package', 'callback' => 'uc_usps_quote', 'accessorials' => _uc_usps_intl_services(), ), 'weight' => 1, ), ); return $methods; } /****************************************************************************** * Module Functions * ******************************************************************************/ /** * Callback for retrieving USPS shipping quote. * * @param $products * Array of cart contents. * @param $details * Order details other than product information. * @param $method * The shipping method to create the quote. * * @return * JSON object containing rate, error, and debugging information. */ function uc_usps_quote($products, $details, $method) { // The uc_quote AJAX query can fire before the customer has completely // filled out the destination address, so check to see whether the address // has all needed fields. If not, abort. $destination = (object) $details; // Country code is always needed. if (empty($destination->country)) { // Skip this shipping method. return array(); } // Shipments to the US also need zone and postal_code. if (($destination->country == 840) && (empty($destination->zone) || empty($destination->postal_code))) { // Skip this shipping method. return array(); } // USPS Production server. $connection_url = 'http://production.shippingapis.com/ShippingAPI.dll'; // Initialize $debug_data to prevent PHP notices here and in uc_quote. $debug_data = array('debug' => NULL, 'error' => array()); $services = array(); $addresses = array(variable_get('uc_quote_store_default_address', new UcAddress())); $packages = _uc_usps_package_products($products, $addresses); if (!count($packages)) { return array(); } foreach ($packages as $key => $ship_packages) { $orig = $addresses[$key]; $orig->email = uc_store_email(); if (strpos($method['id'], 'intl') && ($destination->country != 840)) { // Build XML for international rate request. $request = uc_usps_intl_rate_request($ship_packages, $orig, $destination); } elseif ($destination->country == 840) { // Build XML for domestic rate request. $request = uc_usps_rate_request($ship_packages, $orig, $destination); } if (user_access('configure quotes') && variable_get('uc_quote_display_debug', FALSE)) { $debug_data['debug'] .= htmlentities(urldecode($request)) . "
\n"; } $result = drupal_http_request($connection_url, array( 'method' => 'POST', 'data' => $request, )); if (user_access('configure quotes') && variable_get('uc_quote_display_debug', FALSE)) { $debug_data['debug'] .= htmlentities($result->data) . "
\n"; } $rate_type = variable_get('uc_usps_online_rates', FALSE); $response = new SimpleXMLElement($result->data); // Map double-encoded HTML markup in service names to Unicode characters. $service_markup = array( '<sup>&reg;</sup>' => '®', '<sup>&trade;</sup>' => '™', '<sup>®</sup>' => '®', '<sup>™</sup>' => '™', '**' => '', ); // Use this map to fix USPS service names. if (strpos($method['id'], 'intl')) { // Find and replace markup in International service names. foreach ($response->xpath('//Service') as $service) { $service->SvcDescription = str_replace(array_keys($service_markup), $service_markup, $service->SvcDescription); } } else { // Find and replace markup in Domestic service names. foreach ($response->xpath('//Postage') as $postage) { $postage->MailService = str_replace(array_keys($service_markup), $service_markup, $postage->MailService); } } if (isset($response->Package)) { foreach ($response->Package as $package) { if (isset($package->Error)) { $debug_data['error'][] = (string) $package->Error[0]->Description . '
'; } else { if (strpos($method['id'], 'intl')) { foreach ($package->Service as $service) { $id = (string) $service['ID']; $services[$id]['label'] = t('U.S.P.S. @service', array('@service' => (string) $service->SvcDescription)); // Markup rate before customer sees it. if (!isset($services[$id]['rate'])) { $services[$id]['rate'] = 0; } $services[$id]['rate'] += uc_usps_rate_markup((string) $service->Postage); } } else { foreach ($package->Postage as $postage) { $classid = (string) $postage['CLASSID']; if ($classid === '0') { if ((string) $postage->MailService == "First-Class Mail® Parcel") { $classid = 'zeroParcel'; } elseif ((string) $postage->MailService == "First-Class Mail® Letter") { $classid = 'zeroFlat'; } else { $classid = 'zero'; } } if (!isset($services[$classid]['rate'])) { $services[$classid]['rate'] = 0; } $services[$classid]['label'] = t('U.S.P.S. @service', array('@service' => (string) $postage->MailService)); // Markup rate before customer sees it. // Rates are stored differently if ONLINE $rate_type is requested. // First Class doesn't have online rates, so if CommercialRate // is missing use Rate instead. if ($rate_type && !empty($postage->CommercialRate)) { $services[$classid]['rate'] += uc_usps_rate_markup((string) $postage->CommercialRate); } else { $services[$classid]['rate'] += uc_usps_rate_markup((string) $postage->Rate); } } } } } } } $method_services = 'uc_' . $method['id'] . '_services'; $usps_services = array_filter(variable_get($method_services, array_keys(call_user_func('_' . $method_services)))); foreach ($services as $service => $quote) { if (!in_array($service, $usps_services)) { unset($services[$service]); } } foreach ($services as $key => $quote) { if (isset($quote['rate'])) { $services[$key]['rate'] = $quote['rate']; $services[$key]['option_label'] = theme('uc_usps_option_label', array('service' => $quote['label'], 'packages' => $packages)); } } uasort($services, 'uc_quote_price_sort'); // Merge debug data into $services. This is necessary because // $debug_data is not sortable by a 'rate' key, so it has to be // kept separate from the $services data until this point. if (isset($debug_data['debug']) || (isset($debug_data['error']) && count($debug_data['error']))) { $services['data'] = $debug_data; } return $services; } /** * Constructs a quote request for domestic shipments. * * @param $packages * Array of packages received from the cart. * @param $origin * Delivery origin address information. * @param $destination * Delivery destination address information. * * @return * RateV4Request XML document to send to USPS. */ function uc_usps_rate_request($packages, $origin, $destination) { $request = ''; $request .= '2'; $rate_type = variable_get('uc_usps_online_rates', FALSE); $package_id = 0; foreach ($packages as $package) { $qty = $package->qty; for ($i = 0; $i < $qty; $i++) { $request .= '' . '' . ($rate_type ? 'ONLINE' : 'ALL') . '' . '' . substr(trim($origin->postal_code), 0, 5) . '' . '' . substr(trim($destination->postal_code), 0, 5) . '' . '' . intval($package->pounds) . '' . '' . number_format($package->ounces, 1, '.', '') . '' . '' . $package->container . '' . '' . $package->size . '' . '' . $package->width . '' . '' . $package->length . '' . '' . $package->height . '' . '' . $package->girth . '' . '' . $package->price . '' . '' . ($package->machinable ? 'TRUE' : 'FALSE') . '' . 'TRUE' . '' . format_date(time(), 'custom', 'd-M-Y', 'America/New_York', 'en') . ''; // Check if we need to add any special services to this package. if (variable_get('uc_usps_insurance', FALSE) || variable_get('uc_usps_delivery_confirmation', FALSE) || variable_get('uc_usps_signature_confirmation', FALSE) ) { $request .= ''; if (variable_get('uc_usps_insurance', FALSE)) { $request .= '1'; } if (variable_get('uc_usps_delivery_confirmation', FALSE)) { $request .= '13'; } if (variable_get('uc_usps_signature_confirmation', FALSE)) { $request .= '15'; } $request .= ''; } // Close off Package tag. $request .= ''; $package_id++; } } $request .= ''; return 'API=RateV4&XML=' . drupal_encode_path($request); } /** * Constructs a quote request for international shipments. * * @param $packages * Array of packages received from the cart. * @param $origin * Delivery origin address information. * @param $destination * Delivery destination address information. * * @return * IntlRateRequest XML document to send to USPS. */ function uc_usps_intl_rate_request($packages, $origin, $destination) { module_load_include('inc', 'uc_usps', 'uc_usps.countries'); $request = ''; $request .= '2'; // USPS does not use ISO 3166 country name in some cases so we // need to transform ISO country name into one USPS understands. $shipto_country = uc_usps_country_map($destination->country); $package_id = 0; foreach ($packages as $package) { $qty = $package->qty; for ($i = 0; $i < $qty; $i++) { $request .= '' . '' . intval($package->pounds) . '' . '' . ceil($package->ounces) . '' . 'All' . '' . $package->price . '' . '' . $shipto_country . '' . '' . 'RECTANGULAR' . '' . '' . 'REGULAR' . '' . '' . '' . '' . '' . '' . '' . '' . '' . '' . substr(trim($origin->postal_code), 0, 5) . ''; // Check if we need to add any special services to this package. if (variable_get('uc_usps_insurance', FALSE)) { $request .= '1'; } // Close off Package tag. $request .= ''; $package_id++; } } $request .= ''; $request = 'API=IntlRateV2&XML=' . drupal_encode_path($request); return $request; } /** * Modifies the rate received from USPS before displaying to the customer. * * @param $rate * Shipping rate without any rate markup. * * @return * Shipping rate after markup. */ function uc_usps_rate_markup($rate) { $markup = trim(variable_get('uc_usps_rate_markup', '0')); $type = variable_get('uc_usps_rate_markup_type', 'percentage'); if (is_numeric($markup)) { switch ($type) { case 'percentage': return $rate + $rate * floatval($markup) / 100; case 'multiplier': return $rate * floatval($markup); case 'currency': return $rate + floatval($markup); } } else { return $rate; } } /** * Modifies the weight of shipment before sending to USPS for a quote. * * @param $weight * Shipping weight without any weight markup. * * @return * Shipping weight after markup. */ function uc_usps_weight_markup($weight) { $markup = trim(variable_get('uc_usps_weight_markup', '0')); $type = variable_get('uc_usps_weight_markup_type', 'percentage'); if (is_numeric($markup)) { switch ($type) { case 'percentage': return $weight + $weight * floatval($markup) / 100; case 'multiplier': return $weight * floatval($markup); case 'mass': return $weight + floatval($markup); } } else { return $weight; } } /** * Organizes products into packages for shipment. * * @param $products * An array of product objects as they are represented in the cart or order. * @param &$addresses * Reference to an array of addresses which are the pickup locations of each * package. They are determined from the shipping addresses of their * component products. * * @return * Array of packaged products. Packages are separated by shipping address and * weight or quantity limits imposed by the shipping method or the products. */ function _uc_usps_package_products($products, &$addresses) { $last_key = 0; $packages = array(); if (variable_get('uc_usps_all_in_one', TRUE) && count($products) > 1) { // "All in one" packaging strategy. // Only need to do this if more than one product line item in order. $packages[$last_key] = array(0 => _uc_usps_new_package()); foreach ($products as $product) { if ($product->nid) { // Packages are grouped by the address from which they will be // shipped. We will keep track of the different addresses in an array // and use their keys for the array of packages. $key = NULL; $address = uc_quote_get_default_shipping_address($product->nid); foreach ($addresses as $index => $value) { if ($address->isSamePhysicalLocation($value)) { // This is an existing address. $key = $index; break; } } if (!isset($key)) { // This is a new address. Increment the address counter $last_key // instead of using [] so that it can be used in $packages and // $addresses. $addresses[++$last_key] = $address; $key = $last_key; $packages[$key] = array(0 => _uc_usps_new_package()); } } // Grab some product properties directly from the (cached) product // data. They are not normally available here because the $product // object is being read out of the $order object rather than from // the database, and the $order object only carries around a limited // number of product properties. $temp = node_load($product->nid); $product->length = $temp->length; $product->width = $temp->width; $product->height = $temp->height; $product->length_units = $temp->length_units; $product->usps['container'] = isset($temp->usps['container']) ? $temp->usps['container'] : 'VARIABLE'; $packages[$key][0]->price += $product->price * $product->qty; $packages[$key][0]->weight += $product->weight * $product->qty * uc_weight_conversion($product->weight_units, 'lb'); } foreach ($packages as $key => $package) { $packages[$key][0]->pounds = floor($package[0]->weight); $packages[$key][0]->ounces = LB_TO_OZ * ($package[0]->weight - $packages[$key][0]->pounds); $packages[$key][0]->container = 'VARIABLE'; $packages[$key][0]->size = 'REGULAR'; // Packages are "machinable" if heavier than 6oz. and less than 35lbs. $packages[$key][0]->machinable = ( ($packages[$key][0]->pounds == 0 ? $packages[$key][0]->ounces >= 6 : TRUE) && $packages[$key][0]->pounds <= 35 && ($packages[$key][0]->pounds == 35 ? $packages[$key][0]->ounces == 0 : TRUE) ); $packages[$key][0]->qty = 1; } } else { // !variable_get('uc_usps_all_in_one', TRUE) || count($products) = 1 // "Each in own" packaging strategy, or only one product line item in order. foreach ($products as $product) { if ($product->nid) { $address = uc_quote_get_default_shipping_address($product->nid); if (in_array($address, $addresses)) { // This is an existing address. foreach ($addresses as $index => $value) { if ($address == $value) { $key = $index; break; } } } else { // This is a new address. $addresses[++$last_key] = $address; $key = $last_key; } } if (!isset($product->pkg_qty) || !$product->pkg_qty) { $product->pkg_qty = 1; } $num_of_pkgs = (int) ($product->qty / $product->pkg_qty); if ($num_of_pkgs) { $package = clone $product; $package->description = $product->model; $weight = $product->weight * $product->pkg_qty; switch ($product->weight_units) { case 'g': // Convert to kg and fall through. $weight = $weight * G_TO_KG; case 'kg': // Convert to lb and fall through. $weight = $weight * KG_TO_LB; case 'lb': $package->pounds = floor($weight); $package->ounces = LB_TO_OZ * ($weight - $package->pounds); break; case 'oz': $package->pounds = floor($weight * OZ_TO_LB); $package->ounces = $weight - $package->pounds * LB_TO_OZ; break; } // Grab some product properties directly from the (cached) product // data. They are not normally available here because the $product // object is being read out of the $order object rather than from // the database, and the $order object only carries around a limited // number of product properties. $temp = node_load($product->nid); $product->length = $temp->length; $product->width = $temp->width; $product->height = $temp->height; $product->length_units = $temp->length_units; $product->usps['container'] = isset($temp->usps['container']) ? $temp->usps['container'] : 'VARIABLE'; $package->container = $product->usps['container']; $length_conversion = uc_length_conversion($product->length_units, 'in'); $package->length = max($product->length, $product->width) * $length_conversion; $package->width = min($product->length, $product->width) * $length_conversion; $package->height = $product->height * $length_conversion; if ($package->length < $package->height) { list($package->length, $package->height) = array($package->height, $package->length); } $package->girth = 2 * $package->width + 2 * $package->height; $package->size = $package->length <= 12 ? 'REGULAR' : 'LARGE'; $package->machinable = ( $package->length >= 6 && $package->length <= 34 && $package->width >= 0.25 && $package->width <= 17 && $package->height >= 3.5 && $package->height <= 17 && ($package->pounds == 0 ? $package->ounces >= 6 : TRUE) && $package->pounds <= 35 && ($package->pounds == 35 ? $package->ounces == 0 : TRUE) ); $package->price = $product->price * $product->pkg_qty; $package->qty = $num_of_pkgs; $packages[$key][] = $package; } $remaining_qty = $product->qty % $product->pkg_qty; if ($remaining_qty) { $package = clone $product; $package->description = $product->model; $weight = $product->weight * $remaining_qty; switch ($product->weight_units) { case 'g': // Convert to kg and fall through. $weight = $weight * G_TO_KG; case 'kg': // Convert to lb and fall through. $weight = $weight * KG_TO_LB; case 'lb': $package->pounds = floor($weight); $package->ounces = LB_TO_OZ * ($weight - $package->pounds); break; case 'oz': $package->pounds = floor($weight * OZ_TO_LB); $package->ounces = $weight - $package->pounds * LB_TO_OZ; break; } $package->container = $product->usps['container']; $length_conversion = uc_length_conversion($product->length_units, 'in'); $package->length = max($product->length, $product->width) * $length_conversion; $package->width = min($product->length, $product->width) * $length_conversion; $package->height = $product->height * $length_conversion; if ($package->length < $package->height) { list($package->length, $package->height) = array($package->height, $package->length); } $package->girth = 2 * $package->width + 2 * $package->height; $package->size = $package->length <= 12 ? 'REGULAR' : 'LARGE'; $package->machinable = ( $package->length >= 6 && $package->length <= 34 && $package->width >= 0.25 && $package->width <= 17 && $package->height >= 3.5 && $package->height <= 17 && ($package->pounds == 0 ? $package->ounces >= 6 : TRUE) && $package->pounds <= 35 && ($package->pounds == 35 ? $package->ounces == 0 : TRUE) ); $package->price = $product->price * $remaining_qty; $package->qty = 1; $packages[$key][] = $package; } } } return $packages; } /** * Convenience function for select form elements. */ function _uc_usps_pkg_types() { return array( 'VARIABLE' => t('Variable'), 'FLAT RATE ENVELOPE' => t('Flat rate envelope'), 'PADDED FLAT RATE ENVELOPE' => t('Padded flat rate envelope'), 'LEGAL FLAT RATE ENVELOPE' => t('Legal flat rate envelope'), 'SMALL FLAT RATE ENVELOPE' => t('Small flat rate envelope'), 'WINDOW FLAT RATE ENVELOPE' => t('Window flat rate envelope'), 'GIFT CARD FLAT RATE BOX' => t('Gift card flat rate box'), 'FLAT RATE BOX' => t('Flat rate box'), 'SM FLAT RATE BOX' => t('Small flat rate box'), 'MD FLAT RATE BOX' => t('Medium flat rate box'), 'LG FLAT RATE BOX' => t('Large flat rate box'), 'REGIONALRATEBOXA' => t('Regional rate box A'), 'REGIONALRATEBOXB' => t('Regional rate box B'), 'RECTANGULAR' => t('Rectangular'), 'NONRECTANGULAR' => t('Non-rectangular'), ); } /** * Maps envelope shipment services to their IDs. */ function _uc_usps_env_services() { return array( 'zero' => t('U.S.P.S. First-Class Mail Postcard'), 'zeroFlat' => t('U.S.P.S. First-Class Mail Letter'), 12 => t('U.S.P.S. First-Class Postcard Stamped'), 1 => t('U.S.P.S. Priority Mail'), 16 => t('U.S.P.S. Priority Mail Flat-Rate Envelope'), 3 => t('U.S.P.S. Express Mail'), 13 => t('U.S.P.S. Express Mail Flat-Rate Envelope'), 23 => t('U.S.P.S. Express Mail Sunday/Holiday Guarantee'), 25 => t('U.S.P.S. Express Mail Flat-Rate Envelope Sunday/Holiday Guarantee'), ); } /** * Maps parcel shipment services to their IDs. */ function _uc_usps_services() { return array( 'zeroFlat' => t('U.S.P.S. First-Class Mail Letter'), 'zeroParcel' => t('U.S.P.S. First-Class Mail Parcel'), 1 => t('U.S.P.S. Priority Mail'), 28 => t('U.S.P.S. Priority Mail Small Flat-Rate Box'), 17 => t('U.S.P.S. Priority Mail Regular/Medium Flat-Rate Box'), 22 => t('U.S.P.S. Priority Mail Large Flat-Rate Box'), 3 => t('U.S.P.S. Express Mail'), 23 => t('U.S.P.S. Express Mail Sunday/Holiday Guarantee'), 4 => t('U.S.P.S. Parcel Post'), 5 => t('U.S.P.S. Bound Printed Matter'), 6 => t('U.S.P.S. Media Mail'), 7 => t('U.S.P.S. Library'), ); } /** * Maps international envelope services to their IDs. */ function _uc_usps_intl_env_services() { return array( 13 => t('First Class Mail International Letter'), 14 => t('First Class Mail International Large Envelope'), 2 => t('Priority Mail International'), 8 => t('Priority Mail International Flat Rate Envelope'), 4 => t('Global Express Guaranteed'), 12 => t('GXG Envelopes'), 1 => t('Express Mail International (EMS)'), 10 => t('Express Mail International (EMS) Flat Rate Envelope'), ); } /** * Maps international parcel services to their IDs. */ function _uc_usps_intl_services() { return array( 15 => t('First Class Mail International Package'), 2 => t('Priority Mail International'), 16 => t('Priority Mail International Small Flat-Rate Box'), 9 => t('Priority Mail International Regular/Medium Flat-Rate Box'), 11 => t('Priority Mail International Large Flat-Rate Box'), 4 => t('Global Express Guaranteed'), 6 => t('Global Express Guaranteed Non-Document Rectangular'), 7 => t('Global Express Guaranteed Non-Document Non-Rectangular'), 1 => t('Express Mail International (EMS)'), ); } /** * Pseudo-constructor to set default values of a package. */ function _uc_usps_new_package() { $package = new stdClass(); $package->price = 0; $package->qty = 1; $package->pounds = 0; $package->ounces = 0; $package->container = 0; $package->size = 0; $package->machinable = TRUE; $package->length = 0; $package->width = 0; $package->height = 0; $package->girth = 0; // $package->length_units = 'in'; // $package->weight_units = 'lb'; return $package; }