protected function getProductDimensions($product)
 {
     if (!$product) {
         return array(1, 1, 1, 1);
     }
     return array($product->width ? max(1, ceil(woocommerce_get_dimension($product->width, 'in'))) : 1, $product->length ? max(1, ceil(woocommerce_get_dimension($product->length, 'in'))) : 1, $product->height ? max(1, ceil(woocommerce_get_dimension($product->height, 'in'))) : 1, $product->weight ? max(1, ceil(woocommerce_get_weight($product->weight, 'lbs'))) : 1);
 }
 protected function getDeclaredItems($order)
 {
     $items = array();
     $items['currency'] = strtoupper(get_woocommerce_currency());
     $order_items = $order->getWcOrder()->get_items();
     foreach ($order_items as $order_item) {
         $product = $order->getWcOrder()->get_product_from_item($order_item);
         $description = substr(get_post($product->id)->post_content, 0, 50);
         $items['ci_items'][] = array('product_name' => $product->get_title(), 'description' => !empty($description) ? $description : '', 'country_of_origin' => 'CA', 'quantity' => $order_item['qty'], 'unit_price' => $product->get_price(), 'unit_weight' => max(1, ceil(woocommerce_get_weight($product->get_weight(), 'kg'))), 'unit_of_measurement' => 'kilogram');
     }
     return $items;
 }
 /**
  * box_shipping function.
  *
  * @access private
  * @param mixed $package
  * @return void
  */
 private function box_shipping($package, $domestic)
 {
     global $woocommerce;
     $box_packages = $this->box_shipping_packages($package);
     if ($box_packages === false) {
         return;
     }
     $size = 'REGULAR';
     // Get weight of order
     foreach ($box_packages as $key => $box_package) {
         $dimensions = array(woocommerce_get_dimension($box_package->length, 'in'), woocommerce_get_dimension($box_package->height, 'in'), woocommerce_get_dimension($box_package->width, 'in'));
         sort($dimensions);
         $girth = $dimensions[0] + $dimensions[0] + $dimensions[1] + $dimensions[1];
         if (max($dimensions) > 12) {
             $size = 'LARGE';
         }
         if ($domestic) {
             $piece = file_get_contents(USPS_PATH . '/xml/package.xml');
         } else {
             $piece = file_get_contents(USPS_PATH . '/xml/package_intl.xml');
         }
         $pounds = woocommerce_get_weight($box_package->weight, 'lbs');
         $ounces = round(($pounds - floor($pounds)) * 16, 2);
         if ($ounces <= 0 && $pounds <= 0) {
             $ounces = 1;
         }
         $piece = str_replace('#ID#', $key . ':1', $piece);
         $piece = str_replace('#VALUE#', round($box_package->value, 2), $piece);
         $piece = str_replace('#SIZE#', $size, $piece);
         $piece = str_replace('#LENGTH#', $dimensions[2], $piece);
         $piece = str_replace('#WIDTH#', $dimensions[1], $piece);
         $piece = str_replace('#HEIGHT#', $dimensions[0], $piece);
         $piece = str_replace('#GIRTH#', round($girth), $piece);
         $piece = str_replace('#POUNDS#', floor($pounds), $piece);
         $piece = str_replace('#OUNCES#', $ounces, $piece);
         $this->package .= $piece;
     }
 }
 /**
  * Extracts the weight and dimensions from the package.
  *
  * @param array $package
  *
  * @return array
  */
 protected function get_package_data()
 {
     $count = 0;
     $height = array();
     $width = array();
     $length = array();
     $weight = array();
     // Shipping per item.
     foreach ($this->package['contents'] as $item_id => $values) {
         $product = $values['data'];
         $qty = $values['quantity'];
         if ($qty > 0 && $product->needs_shipping()) {
             if (version_compare(WOOCOMMERCE_VERSION, '2.1', '>=')) {
                 $_height = wc_get_dimension($this->fix_format($product->height), 'cm');
                 $_width = wc_get_dimension($this->fix_format($product->width), 'cm');
                 $_length = wc_get_dimension($this->fix_format($product->length), 'cm');
                 $_weight = wc_get_weight($this->fix_format($product->weight), 'kg');
             } else {
                 $_height = woocommerce_get_dimension($this->fix_format($product->height), 'cm');
                 $_width = woocommerce_get_dimension($this->fix_format($product->width), 'cm');
                 $_length = woocommerce_get_dimension($this->fix_format($product->length), 'cm');
                 $_weight = woocommerce_get_weight($this->fix_format($product->weight), 'kg');
             }
             $height[$count] = $_height;
             $width[$count] = $_width;
             $length[$count] = $_length;
             $weight[$count] = $_weight;
             if ($qty > 1) {
                 $n = $count;
                 for ($i = 0; $i < $qty; $i++) {
                     $height[$n] = $_height;
                     $width[$n] = $_width;
                     $length[$n] = $_length;
                     $weight[$n] = $_weight;
                     $n++;
                 }
                 $count = $n;
             }
             $count++;
         }
     }
     return array('height' => array_values($height), 'length' => array_values($length), 'width' => array_values($width), 'weight' => array_sum($weight));
 }
 /**
  * box_shipping function.
  *
  * @access private
  * @param mixed $package
  * @return void
  */
 private function box_shipping($package)
 {
     global $woocommerce;
     $this->packages = array();
     $box_packages = $this->box_shipping_packages($package);
     if ($box_packages === false) {
         return;
     }
     // Get weight of order
     foreach ($box_packages as $key => $box_package) {
         $piece = file_get_contents(UPS_PATH . '/xml/package.xml');
         $piece = str_replace('#LENGTH#', number_format(woocommerce_get_dimension($box_package->length, $this->units['woo_dimensions']), 2, '.', ''), $piece);
         $piece = str_replace('#WIDTH#', number_format(woocommerce_get_dimension($box_package->width, $this->units['woo_dimensions']), 2, '.', ''), $piece);
         $piece = str_replace('#HEIGHT#', number_format(woocommerce_get_dimension($box_package->height, $this->units['woo_dimensions']), 2, '.', ''), $piece);
         $weight = woocommerce_get_weight($box_package->weight, $this->units['woo_weight']);
         $piece = str_replace('#WEIGHT#', round($weight, 1) < 0.1 ? 0.1 : round($weight, 1), $piece);
         $piece = str_replace('#WEIGHTUNIT#', $this->units['method_weight'], $piece);
         $piece = str_replace('#DIMENSIONUNIT#', $this->units['method_dimensions'], $piece);
         if ($this->insurance) {
             $package_option = "<PackageServiceOptions>\n\t\t\t\t\t\t\t\t\t\t<InsuredValue>\n\t\t\t\t\t\t\t\t\t\t\t<CurrencyCode>" . get_woocommerce_currency() . "</CurrencyCode>\n\t\t\t\t\t\t\t\t\t\t\t<MonetaryValue>" . round($box_package->value, 2) . "</MonetaryValue>\n\t\t\t\t\t\t\t\t\t\t</InsuredValue>\n\t\t\t\t\t\t\t\t\t</PackageServiceOptions>";
             $piece = str_replace('#PACKAGESERVICEOPTIONS#', $package_option, $piece);
         } else {
             $piece = str_replace('#PACKAGESERVICEOPTIONS#', '', $piece);
         }
         if (!isset($this->packages[0])) {
             $this->packages[0] = null;
         }
         $this->packages[0] .= $piece;
     }
 }
 protected function frenet_calculate($package)
 {
     $values = array();
     $RecipientCEP = $package['destination']['postcode'];
     $RecipientCountry = $package['destination']['country'];
     // Checks if services and zipcode is empty.
     if (empty($RecipientCEP) && $RecipientCountry == 'BR') {
         if ('yes' == $this->debug) {
             $this->log->add($this->id, "ERRO: CEP destino não informado");
         }
         return $values;
     }
     if (empty($this->zip_origin)) {
         if ('yes' == $this->debug) {
             $this->log->add($this->id, "ERRO: CEP origem não configurado");
         }
         return $values;
     }
     // product array
     $shippingItemArray = array();
     $count = 0;
     // Shipping per item.
     foreach ($package['contents'] as $item_id => $values) {
         $product = $values['data'];
         $qty = $values['quantity'];
         if ('yes' == $this->debug) {
             $this->log->add($this->id, 'Product: ' . print_r($product, true));
         }
         $shippingItem = new stdClass();
         if ($qty > 0 && $product->needs_shipping()) {
             if (version_compare(WOOCOMMERCE_VERSION, '2.1', '>=')) {
                 $_height = wc_get_dimension($this->fix_format($product->height), 'cm');
                 $_width = wc_get_dimension($this->fix_format($product->width), 'cm');
                 $_length = wc_get_dimension($this->fix_format($product->length), 'cm');
                 $_weight = wc_get_weight($this->fix_format($product->weight), 'kg');
             } else {
                 $_height = woocommerce_get_dimension($this->fix_format($product->height), 'cm');
                 $_width = woocommerce_get_dimension($this->fix_format($product->width), 'cm');
                 $_length = woocommerce_get_dimension($this->fix_format($product->length), 'cm');
                 $_weight = woocommerce_get_weight($this->fix_format($product->weight), 'kg');
             }
             if (empty($_height)) {
                 $_height = $this->minimum_height;
             }
             if (empty($_width)) {
                 $_width = $this->minimum_width;
             }
             if (empty($_length)) {
                 $_length = $this->minimum_length;
             }
             if (empty($_weight)) {
                 $_weight = 1;
             }
             $shippingItem->Weight = $_weight * $qty;
             $shippingItem->Length = $_length;
             $shippingItem->Height = $_height;
             $shippingItem->Width = $_width;
             $shippingItem->Diameter = 0;
             $shippingItem->SKU = $product->get_sku();
             // wp_get_post_terms( your_id, 'product_cat' );
             $shippingItem->Category = '';
             $shippingItem->isFragile = false;
             if ('yes' == $this->debug) {
                 $this->log->add($this->id, 'shippingItem: ' . print_r($shippingItem, true));
             }
             $shippingItemArray[$count] = $shippingItem;
             $count++;
         }
     }
     if ('yes' == $this->debug) {
         $this->log->add($this->id, 'CEP ' . $package['destination']['postcode']);
     }
     $service_param = array('quoteRequest' => array('Username' => $this->login, 'Password' => $this->password, 'SellerCEP' => $this->zip_origin, 'RecipientCEP' => $RecipientCEP, 'RecipientDocument' => '', 'ShipmentInvoiceValue' => WC()->cart->cart_contents_total, 'ShippingItemArray' => $shippingItemArray, 'RecipientCountry' => $RecipientCountry));
     if ('yes' == $this->debug) {
         $this->log->add($this->id, 'Requesting the Frenet WebServices...');
         $this->log->add($this->id, print_r($service_param, true));
     }
     // Gets the WebServices response.
     $client = new SoapClient($this->webservice, array("soap_version" => SOAP_1_1, "trace" => 1));
     $response = $client->__soapCall("GetShippingQuote", array($service_param));
     if ('yes' == $this->debug) {
         $this->log->add($this->id, $client->__getLastRequest());
         $this->log->add($this->id, $client->__getLastResponse());
     }
     if (is_wp_error($response)) {
         if ('yes' == $this->debug) {
             $this->log->add($this->id, 'WP_Error: ' . $response->get_error_message());
         }
     } else {
         if (isset($response->GetShippingQuoteResult)) {
             if (count($response->GetShippingQuoteResult->ShippingSevicesArray->ShippingSevices) == 1) {
                 $servicosArray[0] = $response->GetShippingQuoteResult->ShippingSevicesArray->ShippingSevices;
             } else {
                 $servicosArray = $response->GetShippingQuoteResult->ShippingSevicesArray->ShippingSevices;
             }
             if (!empty($servicosArray)) {
                 foreach ($servicosArray as $servicos) {
                     if ('yes' == $this->debug) {
                         $this->log->add($this->id, 'Percorrendo os serviços retornados');
                     }
                     if (!isset($servicos->ServiceCode) || $servicos->ServiceCode . '' == '' || !isset($servicos->ShippingPrice)) {
                         continue;
                     }
                     $code = (string) $servicos->ServiceCode;
                     if ('yes' == $this->debug) {
                         $this->log->add($this->id, 'WebServices response [' . $servicos->ServiceDescription . ']: ' . print_r($servicos, true));
                     }
                     $values[$code] = $servicos;
                 }
             }
         }
     }
     return $values;
 }
 /**
  * calculate_flat_rate_box_rate function.
  *
  * @access private
  * @param mixed $package
  * @return void
  */
 private function calculate_flat_rate_box_rate($package, $box_type = 'priority')
 {
     global $woocommerce;
     $cost = 0;
     if (!class_exists('WC_Boxpack')) {
         include_once 'box-packer/class-wc-boxpack.php';
     }
     $boxpack = new WC_Boxpack();
     $domestic = in_array($package['destination']['country'], $this->domestic) ? true : false;
     $added = array();
     // Define boxes
     foreach ($this->flat_rate_boxes as $service_code => $box) {
         if ($box['box_type'] != $box_type) {
             continue;
         }
         $domestic_service = substr($service_code, 0, 1) == 'd' ? true : false;
         if ($domestic && $domestic_service || !$domestic && !$domestic_service) {
             $newbox = $boxpack->add_box($box['length'], $box['width'], $box['height']);
             $newbox->set_max_weight($box['weight']);
             $newbox->set_id($service_code);
             if (isset($box['volume']) && method_exists($newbox, 'set_volume')) {
                 $newbox->set_volume($box['volume']);
             }
             if (isset($box['type']) && method_exists($newbox, 'set_type')) {
                 $newbox->set_type($box['type']);
             }
             $added[] = $service_code . ' - ' . $box['name'] . ' (' . $box['length'] . 'x' . $box['width'] . 'x' . $box['height'] . ')';
         }
     }
     $this->debug('Calculating USPS Flat Rate with boxes: ' . implode(', ', $added));
     // Add items
     foreach ($package['contents'] as $item_id => $values) {
         if (!$values['data']->needs_shipping()) {
             continue;
         }
         if ($values['data']->length && $values['data']->height && $values['data']->width && $values['data']->weight) {
             $dimensions = array($values['data']->length, $values['data']->height, $values['data']->width);
         } else {
             $this->debug(sprintf(__('Product #%d is missing dimensions! Using 1x1x1.', 'woocommerce-shipping-usps'), $item_id), 'error');
             $dimensions = array(1, 1, 1);
         }
         for ($i = 0; $i < $values['quantity']; $i++) {
             $boxpack->add_item(woocommerce_get_dimension($dimensions[2], 'in'), woocommerce_get_dimension($dimensions[1], 'in'), woocommerce_get_dimension($dimensions[0], 'in'), woocommerce_get_weight($values['data']->get_weight(), 'lbs'), $values['data']->get_price());
         }
     }
     // Pack it
     $boxpack->pack();
     // Get packages
     $flat_packages = $boxpack->get_packages();
     if ($flat_packages) {
         foreach ($flat_packages as $flat_package) {
             if (isset($this->flat_rate_boxes[$flat_package->id])) {
                 $this->debug('Packed ' . $flat_package->id . ' - ' . $this->flat_rate_boxes[$flat_package->id]['name']);
                 // Get pricing
                 $box_pricing = $this->settings['shippingrates'] == 'ONLINE' && isset($this->flat_rate_pricing[$flat_package->id]['online']) ? $this->flat_rate_pricing[$flat_package->id]['online'] : $this->flat_rate_pricing[$flat_package->id]['retail'];
                 if (is_array($box_pricing)) {
                     if (isset($box_pricing[$package['destination']['country']])) {
                         $box_cost = $box_pricing[$package['destination']['country']];
                     } else {
                         $box_cost = $box_pricing['*'];
                     }
                 } else {
                     $box_cost = $box_pricing;
                 }
                 // Fees
                 if (!empty($this->flat_rate_fee)) {
                     $sym = substr($this->flat_rate_fee, 0, 1);
                     $fee = $sym == '-' ? substr($this->flat_rate_fee, 1) : $this->flat_rate_fee;
                     if (strstr($fee, '%')) {
                         $fee = str_replace('%', '', $fee);
                         if ($sym == '-') {
                             $box_cost = $box_cost - $box_cost * (floatval($fee) / 100);
                         } else {
                             $box_cost = $box_cost + $box_cost * (floatval($fee) / 100);
                         }
                     } else {
                         if ($sym == '-') {
                             $box_cost = $box_cost - $fee;
                         } else {
                             $box_cost += $fee;
                         }
                     }
                     if ($box_cost < 0) {
                         $box_cost = 0;
                     }
                 }
                 $cost += $box_cost;
             } else {
                 return;
                 // no match
             }
         }
         if ($box_type == 'express') {
             $label = !empty($this->settings['flat_rate_express_title']) ? $this->settings['flat_rate_express_title'] : ($domestic ? '' : 'International ') . 'Priority Mail Express Flat Rate&#0174;';
         } else {
             $label = !empty($this->settings['flat_rate_priority_title']) ? $this->settings['flat_rate_priority_title'] : ($domestic ? '' : 'International ') . 'Priority Mail Flat Rate&#0174;';
         }
         return array('id' => $this->id . ':flat_rate_box_' . $box_type, 'label' => $label, 'cost' => $cost, 'sort' => $box_type == 'express' ? -1 : -2);
     }
 }
 /**
  * box_shipping function.
  *
  * @access private
  * @param mixed $package
  * @return void
  */
 private function box_shipping($package)
 {
     global $woocommerce;
     $requests = array();
     if (!class_exists('WC_Boxpack')) {
         include_once 'box-packer/class-wc-boxpack.php';
     }
     $boxpack = new WC_Boxpack();
     // Define boxes
     foreach ($this->boxes + $this->default_boxes as $key => $box) {
         if (!is_numeric($key)) {
             continue;
         }
         $newbox = $boxpack->add_box($box['length'], $box['width'], $box['height'], $box['box_weight']);
         if (isset($box['id'])) {
             $newbox->set_id($box['id']);
         }
         if ($box['max_weight']) {
             $newbox->set_max_weight($box['max_weight']);
         }
     }
     // Add items
     foreach ($package['contents'] as $item_id => $values) {
         if ($values['data']->length && $values['data']->height && $values['data']->width && $values['data']->weight) {
             $dimensions = array($values['data']->length, $values['data']->height, $values['data']->width);
             for ($i = 0; $i < $values['quantity']; $i++) {
                 $boxpack->add_item(woocommerce_get_dimension($dimensions[2], 'in'), woocommerce_get_dimension($dimensions[1], 'in'), woocommerce_get_dimension($dimensions[0], 'in'), woocommerce_get_weight($values['data']->get_weight(), 'lbs'), $values['data']->get_price());
             }
         } else {
             $woocommerce->add_error(sprintf(__('Product # is missing dimensions. Aborting.', 'wc_fedex'), $item_id));
             return;
         }
     }
     // Pack it
     $boxpack->pack();
     // Get packages
     $packages = $boxpack->get_packages();
     $group = 1;
     foreach ($packages as $package) {
         $dimensions = array($package->length, $package->width, $package->height);
         sort($dimensions);
         $request = array();
         $request['GroupNumber'] = $group;
         $request['GroupPackageCount'] = 1;
         $request['Weight'] = array('Value' => max('0.5', round($package->weight, 2)), 'Units' => 'LB');
         if ($values['data']->length && $values['data']->height && $values['data']->width) {
             $request['Dimensions'] = array('Length' => max(1, round($dimensions[2], 2)), 'Width' => max(1, round($dimensions[1], 2)), 'Height' => max(1, round($dimensions[0], 2)), 'Units' => 'IN');
         }
         $request['InsuredValue'] = array('Amount' => round($package->value), 'Currency' => get_woocommerce_currency());
         $requests[] = $request;
         $group++;
     }
     return $requests;
 }
 /**
  * Generate the output for an individual item
  *
  * @access public
  * @param  object $feed_item The information about the item
  */
 function render_item($feed_item)
 {
     if (empty($feed_item->price_inc_tax)) {
         return;
     }
     //        print_r($feed_item); return;
     // MerchantProductID
     echo "woocommerce_gpf_" . $feed_item->ID . ",";
     // Title
     echo $this->csvescape(substr($feed_item->title, 0, 255)) . ",";
     // ProductURL
     echo $this->csvescape($feed_item->purchase_link) . ",";
     // Price
     $price = number_format($feed_item->price_ex_tax, 2, '.', '');
     echo $this->csvescape($price) . ",";
     // Description
     echo $this->csvescape(substr($feed_item->description, 0, 5000)) . ",";
     // ImageURL
     if (!empty($feed_item->image_link)) {
         echo $this->csvescape($feed_item->image_link) . ",";
     } else {
         echo ',';
     }
     // SKU
     if (!empty($feed_item->sku)) {
         echo $this->csvescape($feed_item->sku) . ",";
     } else {
         echo ',';
     }
     // MerchantCategory
     if (count($feed_item->categories)) {
         // Get the hierarchy of the first category
         $category = $feed_item->categories[0];
         $hierarchy = get_ancestors($category->term_id, 'product_cat');
         $hierarchy = array_reverse($hierarchy);
         $hierarchy[] = $category->term_id;
         foreach ($hierarchy as $cat) {
             $term = get_term($cat, 'product_cat');
             $merchant_categories[] = $term->name;
         }
         echo $this->csvescape(implode(' > ', $merchant_categories)) . ",";
     } else {
         echo ',';
     }
     // ShippingWeight - NOTE NO TRAILING COMMA
     if ($feed_item->shipping_weight) {
         if ($this->store_info->weight_units == 'lbs') {
             echo $this->csvescape($feed_item->shipping_weight);
         } else {
             // Convert and output
             $weight = woocommerce_get_weight($feed_item->shipping_weight, 'lbs');
             echo $this->csvescape($weight);
         }
     }
     $this->output_element($feed_item, 'brand');
     $this->output_element($feed_item, 'mpn');
     $this->output_element($feed_item, 'upc');
     $this->output_element($feed_item, 'isbn');
     if (isset($this->settings['product_fields']['availability'])) {
         if (!$feed_item->is_in_stock) {
             echo ',Out of Stock';
         } elseif (isset($feed_item->additional_elements['availability'][0])) {
             //  In Stock; Out of Stock; Pre-Order; Back-Order
             switch ($feed_item->additional_elements['availability'][0]) {
                 case 'in stock':
                     echo ',In Stock';
                     break;
                 case 'preorder':
                     echo ',Pre-Order';
                     break;
                 case 'available for order':
                     echo ',Back-Order';
                     break;
             }
         }
     }
     $this->output_element($feed_item, 'bing_category');
     if (isset($this->settings['product_fields']['condition'])) {
         if (isset($feed_item->additional_elements['condition'][0])) {
             switch ($feed_item->additional_elements['condition'][0]) {
                 case 'new':
                     echo ',';
                     break;
                 case 'refurbished':
                     echo ',' . $this->csvescape('Refurbished');
                     break;
                 case 'used':
                     echo ',' . $this->csvescape('Used');
                     break;
             }
         } else {
             echo ',';
         }
     }
     echo "\n";
 }
 /**
  * get_fedex_requests function.
  *
  * @access private
  * @param  $fedex_packages Array of packages to ship
  * @param  $package array the package passed from WooCommerce
  * @param  $request_type Used if making a certain type of request i.e. freight, smartpost
  * @return array
  */
 private function get_fedex_requests($fedex_packages, $package, $request_type = '')
 {
     $requests = array();
     // All reguests for this package get this data
     $package_request = $this->get_fedex_api_request($package);
     if ($fedex_packages) {
         // Fedex Supports a Max of 99 per request
         $parcel_chunks = array_chunk($fedex_packages, 99);
         foreach ($parcel_chunks as $parcels) {
             $request = $package_request;
             $total_value = 0;
             $total_packages = 0;
             $total_weight = 0;
             $commodoties = array();
             $freight_class = '';
             // Store parcels as line items
             $request['RequestedShipment']['RequestedPackageLineItems'] = array();
             foreach ($parcels as $key => $parcel) {
                 $parcel_request = $parcel;
                 $total_value += $parcel['InsuredValue']['Amount'] * $parcel['GroupPackageCount'];
                 $total_packages += $parcel['GroupPackageCount'];
                 $total_weight += $parcel['Weight']['Value'] * $total_packages;
                 if ('freight' === $request_type) {
                     // Get the highest freight class for shipment
                     if (isset($parcel['freight_class']) && $parcel['freight_class'] > $freight_class) {
                         $freight_class = $parcel['freight_class'];
                     }
                 } else {
                     // Work out the commodoties for CA shipments
                     if ($parcel_request['packed_products']) {
                         foreach ($parcel_request['packed_products'] as $product) {
                             if (isset($commodoties[$product->id])) {
                                 $commodoties[$product->id]['Quantity']++;
                                 $commodoties[$product->id]['CustomsValue']['Amount'] += round($product->get_price());
                                 continue;
                             }
                             $commodoties[$product->id] = array('Name' => sanitize_title($product->get_title()), 'NumberOfPieces' => 1, 'Description' => '', 'CountryOfManufacture' => ($country = get_post_meta($product->id, 'CountryOfManufacture', true)) ? $country : WC()->countries->get_base_country(), 'Weight' => array('Units' => 'LB', 'Value' => max('0.5', round(woocommerce_get_weight($product->get_weight(), 'lbs'), 2))), 'Quantity' => $parcel['GroupPackageCount'], 'UnitPrice' => array('Amount' => round($product->get_price()), 'Currency' => get_woocommerce_currency()), 'CustomsValue' => array('Amount' => $parcel['InsuredValue']['Amount'] * $parcel['GroupPackageCount'], 'Currency' => get_woocommerce_currency()));
                         }
                     }
                     // Is this valid for a ONE rate? Smart post does not support it
                     if ($this->fedex_one_rate && '' === $request_type && in_array($parcel_request['package_id'], $this->fedex_one_rate_package_ids) && 'US' === $package['destination']['country'] && 'US' === $this->origin_country) {
                         $request['RequestedShipment']['PackagingType'] = $parcel_request['package_id'];
                         $request['RequestedShipment']['SpecialServicesRequested']['SpecialServiceTypes'] = 'FEDEX_ONE_RATE';
                     }
                 }
                 // Remove temp elements
                 unset($parcel_request['freight_class']);
                 unset($parcel_request['packed_products']);
                 unset($parcel_request['package_id']);
                 if (!$this->insure_contents || 'smartpost' === $request_type) {
                     unset($parcel_request['InsuredValue']);
                 }
                 $parcel_request = array_merge(array('SequenceNumber' => $key + 1), $parcel_request);
                 $request['RequestedShipment']['RequestedPackageLineItems'][] = $parcel_request;
             }
             // Size
             $request['RequestedShipment']['PackageCount'] = $total_packages;
             // Smart post
             if ('smartpost' === $request_type) {
                 $request['RequestedShipment']['SmartPostDetail'] = array('Indicia' => 'PARCEL_SELECT', 'HubId' => $this->smartpost_hub, 'AncillaryEndorsement' => 'ADDRESS_CORRECTION', 'SpecialServices' => '');
                 $request['RequestedShipment']['ServiceType'] = 'SMART_POST';
                 // Smart post does not support insurance, but is insured up to $100
                 if ($this->insure_contents && round($total_value) > 100) {
                     return false;
                 }
             } elseif ($this->insure_contents) {
                 $request['RequestedShipment']['TotalInsuredValue'] = array('Amount' => round($total_value), 'Currency' => get_woocommerce_currency());
             }
             if ('freight' === $request_type) {
                 $request['RequestedShipment']['Shipper'] = array('Address' => array('StreetLines' => array(strtoupper($this->freight_shipper_street), strtoupper($this->freight_shipper_street_2)), 'City' => strtoupper($this->freight_shipper_city), 'StateOrProvinceCode' => strtoupper($this->freight_shipper_state), 'PostalCode' => strtoupper($this->freight_shipper_postcode), 'CountryCode' => strtoupper($this->freight_shipper_country), 'Residential' => $this->freight_shipper_residential));
                 $request['CarrierCodes'] = 'FXFR';
                 $request['RequestedShipment']['FreightShipmentDetail'] = array('FedExFreightAccountNumber' => strtoupper($this->freight_number), 'FedExFreightBillingContactAndAddress' => array('Address' => array('StreetLines' => array(strtoupper($this->freight_billing_street), strtoupper($this->freight_billing_street_2)), 'City' => strtoupper($this->freight_billing_city), 'StateOrProvinceCode' => strtoupper($this->freight_billing_state), 'PostalCode' => strtoupper($this->freight_billing_postcode), 'CountryCode' => strtoupper($this->freight_billing_country))), 'Role' => 'SHIPPER', 'PaymentType' => 'PREPAID');
                 // Format freight class
                 $freight_class = $freight_class ? $freight_class : $this->freight_class;
                 $freight_class = $freight_class < 100 ? '0' . $freight_class : $freight_class;
                 $freight_class = 'CLASS_' . str_replace('.', '_', $freight_class);
                 $request['RequestedShipment']['FreightShipmentDetail']['LineItems'] = array('FreightClass' => $freight_class, 'Packaging' => 'SKID', 'Weight' => array('Units' => 'LB', 'Value' => round($total_weight, 2)));
                 $request['RequestedShipment']['ShippingChargesPayment'] = array('PaymentType' => 'SENDER', 'Payor' => array('ResponsibleParty' => array('AccountNumber' => strtoupper($this->freight_number), 'CountryCode' => WC()->countries->get_base_country())));
             } else {
                 // Canada broker fees
                 if (($package['destination']['country'] == 'CA' || $package['destination']['country'] == 'US') && WC()->countries->get_base_country() !== $package['destination']['country']) {
                     $request['RequestedShipment']['CustomsClearanceDetail']['DutiesPayment'] = array('PaymentType' => 'SENDER', 'Payor' => array('ResponsibleParty' => array('AccountNumber' => strtoupper($this->account_number), 'CountryCode' => WC()->countries->get_base_country())));
                     $request['RequestedShipment']['CustomsClearanceDetail']['Commodities'] = array_values($commodoties);
                 }
             }
             // Add request
             $requests[] = $request;
         }
     }
     return $requests;
 }
 /**
  * per_item_shipping function.
  *
  * @access private
  * @param mixed $package
  * @return mixed $requests - an array of XML strings
  */
 private function per_item_shipping($package)
 {
     global $woocommerce;
     $requests = array();
     $ctr = 0;
     foreach ($package['contents'] as $item_id => $values) {
         $ctr++;
         if (!$values['data']->needs_shipping()) {
             $this->debug(sprintf(__('Product #%d is virtual. Skipping.', 'ups-woocommerce-shipping'), $ctr));
             continue;
         }
         if (!$values['data']->get_weight()) {
             $this->debug(sprintf(__('Product #%d is missing weight. Aborting.', 'ups-woocommerce-shipping'), $ctr), 'error');
             return;
         }
         // get package weight
         $weight = woocommerce_get_weight($values['data']->get_weight(), $this->weight_unit);
         // get package dimensions
         if ($values['data']->length && $values['data']->height && $values['data']->width) {
             $dimensions = array(number_format(woocommerce_get_dimension($values['data']->length, $this->dim_unit), 2, '.', ''), number_format(woocommerce_get_dimension($values['data']->height, $this->dim_unit), 2, '.', ''), number_format(woocommerce_get_dimension($values['data']->width, $this->dim_unit), 2, '.', ''));
             sort($dimensions);
         }
         // get quantity in cart
         $cart_item_qty = $values['quantity'];
         // get weight, or 1 if less than 1 lbs.
         // $_weight = ( floor( $weight ) < 1 ) ? 1 : $weight;
         $request = '<Package>' . "\n";
         $request .= '	<PackagingType>' . "\n";
         $request .= '		<Code>02</Code>' . "\n";
         $request .= '		<Description>Package/customer supplied</Description>' . "\n";
         $request .= '	</PackagingType>' . "\n";
         $request .= '	<Description>Rate</Description>' . "\n";
         if ($values['data']->length && $values['data']->height && $values['data']->width) {
             $request .= '	<Dimensions>' . "\n";
             $request .= '		<UnitOfMeasurement>' . "\n";
             $request .= '	 		<Code>' . $this->dim_unit . '</Code>' . "\n";
             $request .= '		</UnitOfMeasurement>' . "\n";
             $request .= '		<Length>' . $dimensions[2] . '</Length>' . "\n";
             $request .= '		<Width>' . $dimensions[1] . '</Width>' . "\n";
             $request .= '		<Height>' . $dimensions[0] . '</Height>' . "\n";
             $request .= '	</Dimensions>' . "\n";
         }
         $request .= '	<PackageWeight>' . "\n";
         $request .= '		<UnitOfMeasurement>' . "\n";
         $request .= '			<Code>' . $this->weight_unit . '</Code>' . "\n";
         $request .= '		</UnitOfMeasurement>' . "\n";
         $request .= '		<Weight>' . $weight . '</Weight>' . "\n";
         $request .= '	</PackageWeight>' . "\n";
         if ($this->insuredvalue) {
             $request .= '	<PackageServiceOptions>' . "\n";
             // InsuredValue
             if ($this->insuredvalue) {
                 $request .= '		<InsuredValue>' . "\n";
                 $request .= '			<CurrencyCode>' . get_woocommerce_currency() . '</CurrencyCode>' . "\n";
                 // WF: Calculating monetary value of cart item for insurance.
                 $request .= '			<MonetaryValue>' . (string) ($values['data']->get_price() * $cart_item_qty) . '</MonetaryValue>' . "\n";
                 $request .= '		</InsuredValue>' . "\n";
             }
             $request .= '	</PackageServiceOptions>' . "\n";
         }
         $request .= '</Package>' . "\n";
         for ($i = 0; $i < $cart_item_qty; $i++) {
             $requests[] = $request;
         }
     }
     return $requests;
 }
 protected function box_shipping_packages($package)
 {
     global $woocommerce;
     if (!class_exists('SYN_Packing')) {
         require_once 'packing/class-syn-packing.php';
     }
     $requests = array();
     $boxpack = new SYN_Packing();
     // Define boxes
     if (!empty($this->boxes)) {
         foreach ($this->boxes as $box) {
             $newbox = $boxpack->add_box($box);
         }
     }
     // Add items
     foreach ($package['contents'] as $item_id => $values) {
         if (!$values['data']->needs_shipping()) {
             $this->add_notice(sprintf(__('Product #%d is virtual. Skipping.', 'syn_shipping'), $values['product_id']));
             continue;
         }
         if (!$values['data']->get_weight() || !$values['data']->length || !$values['data']->height || !$values['data']->width) {
             $this->add_notice(sprintf(__('Product <a href="%s" target="_blank">#%d</a> is missing dimensions and / or weight. Aborting %s quotes.', 'syn_shipping'), get_edit_post_link($values['product_id']), $values['product_id'], $this->method_title), 'error');
             return false;
         }
         $dimensions = array($values['data']->length, $values['data']->height, $values['data']->width);
         for ($i = 0; $i < $values['quantity']; $i++) {
             $boxpack->add_item(number_format(woocommerce_get_dimension($dimensions[2], $this->dimension_unit), 2, '.', ''), number_format(woocommerce_get_dimension($dimensions[1], $this->dimension_unit), 2, '.', ''), number_format(woocommerce_get_dimension($dimensions[0], $this->dimension_unit), 2, '.', ''), number_format(woocommerce_get_weight($values['data']->get_weight(), $this->weight_unit), 2, '.', ''), $values['data']->get_price());
         }
     }
     // Pack it
     $boxpack->pack();
     // Return packages
     return $boxpack->get_packages();
 }
 /**
  * per_item_shipping function.
  *
  * @access private
  * @param mixed $package
  * @return mixed $requests - an array of XML strings
  */
 private function per_item_shipping($package, $params = array())
 {
     global $woocommerce;
     $requests = array();
     $ctr = 0;
     $this->cod = sizeof($package['contents']) > 1 ? false : $this->cod;
     // For multiple packages COD is turned off
     foreach ($package['contents'] as $item_id => $values) {
         $ctr++;
         if (!($values['quantity'] > 0 && $values['data']->needs_shipping())) {
             $this->debug(sprintf(__('Product #%d is virtual. Skipping.', 'ups-woocommerce-shipping'), $ctr));
             continue;
         }
         if (!$values['data']->get_weight()) {
             $this->debug(sprintf(__('Product #%d is missing weight. Aborting.', 'ups-woocommerce-shipping'), $ctr), 'error');
             return;
         }
         // get package weight
         $weight = woocommerce_get_weight($values['data']->get_weight(), $this->weight_unit);
         // get package dimensions
         if ($values['data']->length && $values['data']->height && $values['data']->width) {
             $dimensions = array(number_format(woocommerce_get_dimension($values['data']->length, $this->dim_unit), 2, '.', ''), number_format(woocommerce_get_dimension($values['data']->height, $this->dim_unit), 2, '.', ''), number_format(woocommerce_get_dimension($values['data']->width, $this->dim_unit), 2, '.', ''));
             sort($dimensions);
         }
         // get quantity in cart
         $cart_item_qty = $values['quantity'];
         $request = '<Package>' . "\n";
         $request .= '	<PackagingType>' . "\n";
         $request .= '		<Code>02</Code>' . "\n";
         $request .= '		<Description>Package/customer supplied</Description>' . "\n";
         $request .= '	</PackagingType>' . "\n";
         $request .= '	<Description>Rate</Description>' . "\n";
         if ($values['data']->length && $values['data']->height && $values['data']->width) {
             $request .= '	<Dimensions>' . "\n";
             $request .= '		<UnitOfMeasurement>' . "\n";
             $request .= '	 		<Code>' . $this->dim_unit . '</Code>' . "\n";
             $request .= '		</UnitOfMeasurement>' . "\n";
             $request .= '		<Length>' . $dimensions[2] . '</Length>' . "\n";
             $request .= '		<Width>' . $dimensions[1] . '</Width>' . "\n";
             $request .= '		<Height>' . $dimensions[0] . '</Height>' . "\n";
             $request .= '	</Dimensions>' . "\n";
         }
         if (isset($params['service_code']) && $params['service_code'] == 92) {
             if ($this->weight_unit == 'LBS') {
                 // make sure weight in pounds
                 $weight_ozs = $weight * 16;
             } else {
                 $weight_ozs = $weight * 35.274;
                 // From KG
             }
             $request .= '	<PackageWeight>' . "\n";
             $request .= '		<UnitOfMeasurement>' . "\n";
             $request .= '			<Code>OZS</Code>' . "\n";
             $request .= '		</UnitOfMeasurement>' . "\n";
             $request .= '		<Weight>' . $weight_ozs . '</Weight>' . "\n";
             $request .= '	</PackageWeight>' . "\n";
         } else {
             $request .= '	<PackageWeight>' . "\n";
             $request .= '		<UnitOfMeasurement>' . "\n";
             $request .= '			<Code>' . $this->weight_unit . '</Code>' . "\n";
             $request .= '		</UnitOfMeasurement>' . "\n";
             $request .= '		<Weight>' . $weight . '</Weight>' . "\n";
             $request .= '	</PackageWeight>' . "\n";
         }
         if ($this->insuredvalue || $this->cod) {
             $request .= '	<PackageServiceOptions>' . "\n";
             // InsuredValue
             if ($this->insuredvalue) {
                 $request .= '		<InsuredValue>' . "\n";
                 $request .= '			<CurrencyCode>' . get_woocommerce_currency() . '</CurrencyCode>' . "\n";
                 // WF: Calculating monetary value of cart item for insurance.
                 $request .= '			<MonetaryValue>' . (string) ($values['data']->get_price() * $cart_item_qty) . '</MonetaryValue>' . "\n";
                 $request .= '		</InsuredValue>' . "\n";
             }
             //Code
             if ($this->cod) {
                 $cod_value = $this->cod_total;
                 $request .= '<COD>' . "\n";
                 $request .= '<CODCode>3</CODCode>' . "\n";
                 $request .= '<CODFundsCode>0</CODFundsCode>' . "\n";
                 $request .= '<CODAmount>' . "\n";
                 $request .= '<CurrencyCode>' . get_woocommerce_currency() . '</CurrencyCode>' . "\n";
                 $request .= '<MonetaryValue>' . $cod_value . '</MonetaryValue>' . "\n";
                 $request .= '</CODAmount>' . "\n";
                 $request .= '</COD>' . "\n";
             }
             $request .= '	</PackageServiceOptions>' . "\n";
         }
         $request .= '</Package>' . "\n";
         for ($i = 0; $i < $cart_item_qty; $i++) {
             $requests[] = $request;
         }
     }
     return $requests;
 }
 private function get_fedex_requests($fedex_packages, $package, $request_type = '')
 {
     $requests = array();
     // All reguests for this package get this data
     $package_request = $this->get_fedex_api_request($package);
     if ($fedex_packages) {
         // Fedex Supports a Max of 99 per request
         $parcel_chunks = array_chunk($fedex_packages, 99);
         foreach ($parcel_chunks as $parcels) {
             $request = $package_request;
             $total_value = 0;
             $total_packages = 0;
             $total_weight = 0;
             $commodoties = array();
             $freight_class = '';
             // Store parcels as line items
             $request['RequestedShipment']['RequestedPackageLineItems'] = array();
             foreach ($parcels as $key => $parcel) {
                 $single_package_weight = $parcel['Weight']['Value'];
                 $parcel_request = $parcel;
                 $total_value += $parcel['InsuredValue']['Amount'] * $parcel['GroupPackageCount'];
                 $total_packages += $parcel['GroupPackageCount'];
                 $total_weight += $parcel['Weight']['Value'] * $total_packages;
                 // Work out the commodoties for CA shipments
                 if ($parcel_request['packed_products']) {
                     foreach ($parcel_request['packed_products'] as $product) {
                         if (isset($commodoties[$product->id])) {
                             $commodoties[$product->id]['Quantity']++;
                             $commodoties[$product->id]['CustomsValue']['Amount'] += round($product->get_price());
                             continue;
                         }
                         $commodoties[$product->id] = array('Name' => sanitize_title($product->get_title()), 'NumberOfPieces' => 1, 'Description' => '', 'CountryOfManufacture' => ($country = get_post_meta($product->id, 'CountryOfManufacture', true)) ? $country : WC()->countries->get_base_country(), 'Weight' => array('Units' => 'LB', 'Value' => max('0.5', round(woocommerce_get_weight($product->get_weight(), 'lbs'), 2))), 'Quantity' => $parcel['GroupPackageCount'], 'UnitPrice' => array('Amount' => round($product->get_price()), 'Currency' => $this->wf_get_fedex_currency()), 'CustomsValue' => array('Amount' => $parcel['InsuredValue']['Amount'] * $parcel['GroupPackageCount'], 'Currency' => $this->wf_get_fedex_currency()));
                     }
                 }
                 // Is this valid for a ONE rate? Smart post does not support it
                 if ($this->fedex_one_rate && '' === $request_type && isset($parcel_request['package_id']) && in_array($parcel_request['package_id'], $this->fedex_one_rate_package_ids)) {
                     $request['RequestedShipment']['PackagingType'] = $parcel_request['package_id'];
                     if ('US' === $package['destination']['country'] && 'US' === $this->origin_country) {
                         $request['RequestedShipment']['SpecialServicesRequested']['SpecialServiceTypes'] = 'FEDEX_ONE_RATE';
                     }
                 }
                 // Remove temp elements
                 unset($parcel_request['packed_products']);
                 unset($parcel_request['package_id']);
                 if (!$this->insure_contents || 'smartpost' === $request_type) {
                     unset($parcel_request['InsuredValue']);
                 }
                 $parcel_request = array_merge(array('SequenceNumber' => $key + 1), $parcel_request);
                 $request['RequestedShipment']['RequestedPackageLineItems'][] = $parcel_request;
             }
             // Size
             $request['RequestedShipment']['PackageCount'] = $total_packages;
             $indicia = $this->indicia;
             if ($indicia == 'AUTOMATIC' && $single_package_weight >= 1) {
                 $indicia = 'PARCEL_SELECT';
             } elseif ($indicia == 'AUTOMATIC' && $single_package_weight < 1) {
                 $indicia = 'PRESORTED_STANDARD';
             }
             // Smart post
             if ('smartpost' === $request_type) {
                 $request['RequestedShipment']['SmartPostDetail'] = array('Indicia' => $indicia, 'HubId' => $this->smartpost_hub, 'AncillaryEndorsement' => 'ADDRESS_CORRECTION', 'SpecialServices' => '');
                 $request['RequestedShipment']['ServiceType'] = 'SMART_POST';
                 // Smart post does not support insurance, but is insured up to $100
                 if ($this->insure_contents && round($total_value) > 100) {
                     return false;
                 }
             } elseif ($this->insure_contents) {
                 $request['RequestedShipment']['TotalInsuredValue'] = array('Amount' => round($total_value), 'Currency' => $this->wf_get_fedex_currency());
             }
             $core_countries = array('US', 'CA');
             if (WC()->countries->get_base_country() !== $package['destination']['country'] || !in_array(WC()->countries->get_base_country(), $core_countries)) {
                 $request['RequestedShipment']['CustomsClearanceDetail']['DutiesPayment'] = array('PaymentType' => 'SENDER', 'Payor' => array('ResponsibleParty' => array('AccountNumber' => strtoupper($this->account_number), 'CountryCode' => WC()->countries->get_base_country())));
                 $request['RequestedShipment']['CustomsClearanceDetail']['Commodities'] = array_values($commodoties);
                 if (!in_array(WC()->countries->get_base_country(), $core_countries)) {
                     $request['RequestedShipment']['CustomsClearanceDetail']['CommercialInvoice'] = array('Purpose' => 'SOLD');
                 }
             }
             // Add request
             $requests[] = $request;
         }
     }
     return $requests;
 }
 /**
  * box_shipping function.
  *
  * @access private
  * @param mixed $package
  * @return void
  */
 private function box_shipping($package)
 {
     global $woocommerce;
     $requests = array();
     if (!class_exists('WC_Boxpack')) {
         include_once 'box-packer/class-wc-boxpack.php';
     }
     $boxpack = new WC_Boxpack();
     // Define boxes
     foreach ($this->boxes as $box) {
         $newbox = $boxpack->add_box($box['outer_length'], $box['outer_width'], $box['outer_height'], $box['box_weight']);
         $newbox->set_inner_dimensions($box['inner_length'], $box['inner_width'], $box['inner_height']);
         if ($box['max_weight']) {
             $newbox->set_max_weight($box['max_weight']);
         }
         if ($box['name']) {
             $newbox->set_id($box['name']);
         }
     }
     // Add items
     foreach ($package['contents'] as $item_id => $values) {
         if (!$values['data']->needs_shipping()) {
             $this->debug(sprintf(__('Product #%d is virtual. Skipping.', 'wc_canada_post'), $item_id));
             continue;
         }
         if ($values['data']->length && $values['data']->height && $values['data']->width && $values['data']->weight) {
             $dimensions = array($values['data']->length, $values['data']->height, $values['data']->width);
             for ($i = 0; $i < $values['quantity']; $i++) {
                 $boxpack->add_item(woocommerce_get_dimension($dimensions[2], 'cm'), woocommerce_get_dimension($dimensions[1], 'cm'), woocommerce_get_dimension($dimensions[0], 'cm'), woocommerce_get_weight($values['data']->get_weight(), 'kg'), $values['data']->get_price());
             }
         } else {
             if (function_exists('wc_add_notice')) {
                 wc_add_notice(sprintf(__('Product # is missing dimensions. Aborting.', 'wc_canada_post'), $item_id), 'error');
             } else {
                 $woocommerce->add_error(sprintf(__('Product # is missing dimensions. Aborting.', 'wc_canada_post'), $item_id));
             }
             return;
         }
     }
     // Pack it
     $boxpack->pack();
     // Get packages
     $packages = $boxpack->get_packages();
     foreach ($packages as $package) {
         $dimensions = array($package->length, $package->width, $package->height);
         sort($dimensions);
         $request = '<parcel-characteristics>' . "\n";
         $request .= '	<weight>' . round($package->weight, 2) . '</weight>' . "\n";
         $request .= '	<dimensions>' . "\n";
         $request .= '		<height>' . round($dimensions[0], 1) . '</height>' . "\n";
         $request .= '		<width>' . round($dimensions[1], 1) . '</width>' . "\n";
         $request .= '		<length>' . round($dimensions[2], 1) . '</length>' . "\n";
         $request .= '	</dimensions>' . "\n";
         $request .= '</parcel-characteristics>' . "\n";
         // Package options
         if (!empty($this->options)) {
             $option_request = '';
             foreach ($this->options as $option) {
                 if ($package['destination']['country'] !== 'CA' && 'PA18' === $option) {
                     continue;
                 }
                 $option_request .= '		<option>' . "\n";
                 $option_request .= '			<option-code>' . $option . '</option-code>' . "\n";
                 if ($option == 'COV') {
                     $option_request .= '			<option-amount>' . $package->value . '</option-amount>' . "\n";
                 }
                 $option_request .= '		</option>' . "\n";
             }
             if ($option_request) {
                 $request .= '<options>' . "\n" . $option_request . '</options>' . "\n";
             }
         }
         $requests[] = $request;
     }
     return $requests;
 }
 /**
  * box_shipping function.
  *
  * @access private
  * @param mixed $package
  * @return void
  */
 private function box_shipping($package)
 {
     global $woocommerce;
     $requests = array();
     if (!class_exists('WC_Boxpack')) {
         include_once 'box-packer/class-wc-boxpack.php';
     }
     $boxpack = new WC_Boxpack();
     // Add Standard UPS boxes
     if (!empty($this->ups_packaging)) {
         foreach ($this->ups_packaging as $key => $box_code) {
             $box = $this->packaging[$box_code];
             $newbox = $boxpack->add_box($key, $box['length'], $box['width'], $box['height']);
             $newbox->set_inner_dimensions($box['length'], $box['width'], $box['height']);
             if ($box['weight']) {
                 $newbox->set_max_weight($box['weight']);
             }
         }
     }
     // Define boxes
     if (!empty($this->boxes)) {
         foreach ($this->boxes as $box) {
             $newbox = $boxpack->add_box($box['outer_length'], $box['outer_width'], $box['outer_height'], $box['box_weight']);
             $newbox->set_inner_dimensions($box['inner_length'], $box['inner_width'], $box['inner_height']);
             if ($box['max_weight']) {
                 $newbox->set_max_weight($box['max_weight']);
             }
         }
     }
     // Add items
     $ctr = 0;
     foreach ($package['contents'] as $item_id => $values) {
         $ctr++;
         if (!$values['data']->needs_shipping()) {
             if ($this->debug) {
                 $woocommerce->add_message(sprintf(__('Product #%d is virtual. Skipping.', 'wc_ups'), $ctr));
             }
             continue;
         }
         if ($values['data']->length && $values['data']->height && $values['data']->width && $values['data']->weight) {
             $dimensions = array($values['data']->length, $values['data']->height, $values['data']->width);
             for ($i = 0; $i < $values['quantity']; $i++) {
                 $boxpack->add_item(number_format(woocommerce_get_dimension($dimensions[2], 'in'), 2, '.', ''), number_format(woocommerce_get_dimension($dimensions[1], 'in'), 2, '.', ''), number_format(woocommerce_get_dimension($dimensions[0], 'in'), 2, '.', ''), number_format(woocommerce_get_weight($values['data']->get_weight(), 'lbs'), 2, '.', ''), $values['data']->get_price());
             }
         } else {
             if ($this->debug) {
                 $woocommerce->add_error(sprintf(__('Product #%d is missing dimensions. Aborting.', 'wc_ups'), $ctr));
             }
             return;
         }
     }
     // Pack it
     $boxpack->pack();
     // Get packages
     $box_packages = $boxpack->get_packages();
     $ctr = 0;
     foreach ($box_packages as $key => $box_package) {
         $ctr++;
         if ($this->debug) {
             $woocommerce->add_error("PACKAGE " . $ctr . " (" . $key . ")\n<pre>" . print_r($box_package, true) . "</pre>");
         }
         $weight = $box_package->weight;
         $dimensions = array($box_package->length, $box_package->width, $box_package->height);
         sort($dimensions);
         // get weight, or 1 if less than 1 lbs.
         $_weight = floor($weight) < 1 ? 1 : floor($weight);
         $request = '<Package>' . "\n";
         $request .= '	<PackagingType>' . "\n";
         $request .= '		<Code>02</Code>' . "\n";
         $request .= '		<Description>Package/customer supplied</Description>' . "\n";
         $request .= '	</PackagingType>' . "\n";
         $request .= '	<Description>Rate</Description>' . "\n";
         $request .= '	<Dimensions>' . "\n";
         $request .= '		<UnitOfMeasurement>' . "\n";
         $request .= '	 		<Code>IN</Code>' . "\n";
         $request .= '		</UnitOfMeasurement>' . "\n";
         $request .= '		<Length>' . $dimensions[2] . '</Length>' . "\n";
         $request .= '		<Width>' . $dimensions[1] . '</Width>' . "\n";
         $request .= '		<Height>' . $dimensions[0] . '</Height>' . "\n";
         $request .= '	</Dimensions>' . "\n";
         $request .= '	<PackageWeight>' . "\n";
         $request .= '		<UnitOfMeasurement>' . "\n";
         $request .= '			<Code>LBS</Code>' . "\n";
         $request .= '		</UnitOfMeasurement>' . "\n";
         $request .= '		<Weight>' . $_weight . '</Weight>' . "\n";
         $request .= '	</PackageWeight>' . "\n";
         $request .= '</Package>' . "\n";
         $requests[] = $request;
     }
     return $requests;
 }
 /**
  * Generate the output for an individual item
  *
  * @access public
  * @param  object $feed_item The information about the item
  */
 function render_item($feed_item)
 {
     if (empty($feed_item->price_inc_tax)) {
         return false;
     }
     // MPID
     echo 'woocommerce_gpf_' . $feed_item->ID . "\t";
     // Title
     echo $this->tsvescape(substr($feed_item->title, 0, 255)) . "\t";
     // ProductURL
     echo $this->tsvescape($feed_item->purchase_link) . "\t";
     // Price
     $price = number_format($feed_item->price_ex_tax, 2, '.', '');
     echo $this->tsvescape($price) . "\t";
     // Description - Bing doesn't allow HTML in descriptions
     $description = wp_filter_nohtml_kses($feed_item->description);
     $description = substr($description, 0, 5000);
     echo $this->tsvescape($description) . "\t";
     // ImageURL
     if (!empty($feed_item->image_link)) {
         echo $this->tsvescape($feed_item->image_link) . "\t";
     } else {
         echo "\t";
     }
     // MerchantCategory
     if (count($feed_item->categories)) {
         // Get the hierarchy of the first category
         $category = $feed_item->categories[0];
         $hierarchy = get_ancestors($category->term_id, 'product_cat');
         $hierarchy = array_reverse($hierarchy);
         $hierarchy[] = $category->term_id;
         foreach ($hierarchy as $cat) {
             $term = get_term($cat, 'product_cat');
             $merchant_categories[] = $term->name;
         }
         echo $this->tsvescape(implode(' > ', $merchant_categories)) . "\t";
     } else {
         echo "\t";
     }
     // SKU
     if (!empty($feed_item->sku)) {
         echo $this->tsvescape($feed_item->sku) . "\t";
     } else {
         echo "\t";
     }
     // ShippingWeight - NOTE NO TRAILING TAB
     if ($feed_item->shipping_weight) {
         if ('lbs' == $this->store_info->weight_units) {
             echo $this->tsvescape($feed_item->shipping_weight);
         } else {
             // Convert and output
             $weight = woocommerce_get_weight($feed_item->shipping_weight, 'lbs');
             echo $this->tsvescape($weight);
         }
     }
     $this->output_element($feed_item, 'brand');
     $this->output_element($feed_item, 'mpn');
     $this->output_element($feed_item, 'upc');
     $this->output_element($feed_item, 'isbn');
     if (isset($this->settings['product_fields']['availability'])) {
         if ($feed_item->is_in_stock) {
             if (isset($feed_item->additional_elements['availability'][0])) {
                 //  Out of Stock; Pre-Order; Back-Order
                 switch ($feed_item->additional_elements['availability'][0]) {
                     case 'out of stock':
                         echo "\tOut Of Stock";
                         break;
                     case 'preorder':
                         echo "\tPre-Order";
                         break;
                     case 'available for order':
                         echo "\tBack-Order";
                         break;
                     case 'in stock':
                         echo "\tIn Stock";
                         break;
                     default:
                         echo "\tIn Stock";
                         break;
                 }
             } else {
                 echo "\tIn Stock";
             }
         } else {
             echo "\tOut Of Stock";
         }
     }
     $this->output_element($feed_item, 'bing_category');
     if (isset($this->settings['product_fields']['condition'])) {
         if (isset($feed_item->additional_elements['condition'][0])) {
             switch ($feed_item->additional_elements['condition'][0]) {
                 case 'new':
                     echo "\t" . $this->tsvescape('New');
                     break;
                 case 'refurbished':
                     echo "\t" . $this->tsvescape('Refurbished');
                     break;
                 case 'used':
                     echo "\t" . $this->tsvescape('Used');
                     break;
             }
         } else {
             echo "\t";
         }
     }
     echo "\r\n";
     return true;
 }