UPGRADE NOTE:
   Do not edit or add to this file if you wish to upgrade AbanteCart to newer
   versions in the future. If you wish to customize AbanteCart for your
   needs please refer to http://www.AbanteCart.com for more information.
------------------------------------------------------------------------------*/
if ( !defined ( 'DIR_CORE' )) {
	header ( 'Location: static_pages/' );
}
class ModelExtensionDefaultUps extends Model {
	function getQuote($address) {
		$this->load->language('default_ups/default_ups');
		
		if ($this->config->get('default_ups_status')) {
      		if (!$this->config->get('default_ups_location_id')) {
        		$status = TRUE;
      		}else {
		        $query = $this->db->query("SELECT *
                                            FROM " . $this->db->table('zones_to_locations') . "
                                            WHERE location_id = '" . (int)$this->config->get('default_ups_location_id') . "'
                                                AND country_id = '" . (int)$address['country_id'] . "'
                                                AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");
                if ($query->num_rows) {
                    $status = TRUE;
                } else {
                    $status = FALSE;
                }
      		}
		} else { 
			$status = FALSE;
		}
		$method_data = array();
		if (!$status) {
			return $method_data;
		}
        $basic_products = $this->cart->basicShippingProducts();
        foreach($basic_products as $product){
           $product_ids[] = $product['product_id'];
        }
		$weight = $this->weight->convert($this->cart->getWeight($product_ids), $this->config->get('config_weight_class'), $this->config->get('default_ups_weight_class'));
		$weight = ($weight < 0.1 ? 0.1 : $weight);
		$length = $this->length->convert($this->config->get('default_ups_length'), $this->config->get('config_length_class'), $this->config->get('default_ups_length_class'));
		$width = $this->length->convert($this->config->get('default_ups_width'), $this->config->get('config_length_class'), $this->config->get('default_ups_length_class'));
		$height = $this->length->convert($this->config->get('default_ups_height'), $this->config->get('config_length_class'), $this->config->get('default_ups_length_class'));
		$request = $this->_buildRequest($address, $weight, $length, $width, $height);
        $quote_data = $this->_processRequest($request);
		$error_msg =  $quote_data['error_msg'];
        $quote_data =  $quote_data['quote_data'];
        $special_ship_products = $this->cart->specialShippingProducts();
        foreach ($special_ship_products as $product) {
            $weight = $this->weight->convert($this->cart->getWeight( array($product['product_id']) ), $this->config->get('config_weight_class'), $this->config->get('default_usps_weight_class'));
            if ( $product['width'] ) {
                $length_class_id = $this->length->getClassID($this->config->get('default_ups_length_class'));
                $use_width = $this->length->convertByID($product['length'], $product['length_class'], $length_class_id);
                $use_length = $this->length->convertByID($product['width'], $product['length_class'], $length_class_id);
                $use_height = $this->length->convertByID($product['height'], $product['length_class'], $length_class_id);
            }
            //check if free or fixed shipping
            $fixed_cost = -1;
            $new_quote_data = array();
            if ($product['free_shipping']) {
                $fixed_cost = 0;
            } else if($product['shipping_price'] > 0) {
                $fixed_cost = $product['shipping_price'];
                //If ship individually count every quintaty
                if ($product['ship_individually']) {
                    $fixed_cost = $fixed_cost * $product['quantity'];
                }
                $fixed_cost = $this->currency->convert($fixed_cost, $this->config->get('config_currency'), $this->currency->getCode());
            } else {
                $request = $this->_buildRequest($address, $weight, $use_width, $use_length, $use_height);
                if ($request) {
                    $new_quote_data = $this->_processRequest( $request );
                    $error_msg =  $new_quote_data['error_msg'];
                    $new_quote_data =  $new_quote_data['quote_data'];
                }
            }
            //merge data and accumulate shipping cost
            if ( $quote_data) {
                foreach ($quote_data as $key => $value) {
                    if ($fixed_cost >= 0){
                        $quote_data[$key]['cost'] = (float)$quote_data[$key]['cost'] + $fixed_cost;
                    } else {
                        $quote_data[$key]['cost'] =  (float)$quote_data[$key]['cost'] + $new_quote_data[$key]['cost'];
                    }
                    $quote_data[$key]['text'] = $this->currency->format(
                                                                        $this->tax->calculate(
                                                                                            $quote_data[$key]['cost'],
                                                                                            $this->config->get('default_usps_tax_class_id'),
                                                                                            $this->config->get('config_tax')
                                                                                        ) ,
                                                                        $this->currency->getCode(),
                                                                        1
                    );
                }
            } else if ( $new_quote_data ) {
                $quote_data = $new_quote_data;
            }
        }
		$title = $this->language->get('text_title');
		if ($this->config->get('default_ups_display_weight')) {
			$title .= ' (' . $this->language->get('text_weight') . ' ' . $this->weight->format($weight, $this->config->get('config_weight_class')) . ')';
		}
		$method_data = array(
			'id'         => 'default_ups',
			'title'      => $title,
			'quote'      => $quote_data,
			'sort_order' => $this->config->get('default_ups_sort_order'),
			'error'      => $error_msg
		);
		
		return $method_data;
	}
    private function _buildRequest($address, $weight,$length,$width,$height){
        $length_code = strtoupper( $this->length->getUnit($this->config->get('default_ups_length_class') ) );
        $weight_code = strtoupper( $this->length->getUnit($this->config->get('default_ups_weight') ) );
        $xml  = '';
        $xml .= '';
        $xml .= '	' . $this->config->get('default_ups_key') . '';
        $xml .= '	' . $this->config->get('default_ups_username') . '';
        $xml .= '	' . $this->config->get('default_ups_password') . '';
        $xml .= '';
        $xml .= '';
        $xml .= '';
        $xml .= '	';
        $xml .= '		';
        $xml .= '			Bare Bones Rate Request';
        $xml .= '			1.0001';
        $xml .= '		';
        $xml .= '		Rate';
        $xml .= '		shop';
        $xml .= '	';
        $xml .= '   ';
        $xml .= '       ' . $this->config->get('default_ups_pickup') . '';
        $xml .= '   ';
        if ($this->config->get('default_ups_country') == 'US' && $this->config->get('default_ups_pickup') == '11') {
            $xml .= '   ';
            $xml .= '       ' . $this->config->get('default_ups_classification') . '';
            $xml .= '   ';
        }
        $xml .= '	';
        $xml .= '		';
        $xml .= '			';
        $xml .= '				' . $this->config->get('default_ups_city') . '';
        $xml .= '				'. $this->config->get('default_ups_state') . '';
        $xml .= '				' . $this->config->get('default_ups_country') . '';
        $xml .= '				' . $this->config->get('default_ups_postcode') . '';
        $xml .= '			';
        $xml .= '		';
        $xml .= '		';
        $xml .= '			';
        $xml .= ' 				' . $address['city'] . '';
        $xml .= '				' . $address['zone_code'] . '';
        $xml .= '				' . $address['iso_code_2'] . '';
        $xml .= '				' . $address['postcode'] . '';
        if ($this->config->get('default_ups_quote_type') == 'residential') {
            $xml .= '				';
        }
        $xml .= '			';
        $xml .= '		';
        $xml .= '		';
        $xml .= '			';
        $xml .= '				' . $this->config->get('default_ups_city') . '';
        $xml .= '				'. $this->config->get('default_ups_state') . '';
        $xml .= '				' . $this->config->get('default_ups_country') . '';
        $xml .= '				' . $this->config->get('default_ups_postcode') . '';
        $xml .= '			';
        $xml .= '		';
        $xml .= '		';
        $xml .= '			';
        $xml .= '				' . $this->config->get('default_ups_packaging') . '';
        $xml .= '			';
        $xml .= '		    ';
        $xml .= '				';
        $xml .= '					' . $length_code . '';
        $xml .= '				';
        $xml .= '				' . $length . '';
        $xml .= '				' . $width . '';
        $xml .= '				' . $height . '';
        $xml .= '			';
        $xml .= '			';
        $xml .= '				';
        $xml .= '					' . $weight_code . '';
        $xml .= '				';
        $xml .= '				' . $weight . '';
        $xml .= '			';
        if ($this->config->get('default_ups_insurance')) {
            $xml .= '           ';
            $xml .= '               ';
            $xml .= '                   ' . $this->currency->getCode() . '';
            $xml .= '                   ' . $this->currency->format($this->cart->getTotal(), false, false, false) . '';
            $xml .= '               ';
            $xml .= '           ';
        }
        $xml .= '		';
        $xml .= '	';
        $xml .= '';
        return $xml;
    }
    private function _processRequest($request=''){
        if (!$this->config->get('default_ups_test')) {
            $url = 'https://www.ups.com/ups.app/xml/Rate';
        } else {
            $url = 'https://wwwcie.ups.com/ups.app/xml/Rate';
        }
        $service_code = array(
            // US Origin
            'US' => array(
                '01' => $this->language->get('text_us_origin_01'),
                '02' => $this->language->get('text_us_origin_02'),
                '03' => $this->language->get('text_us_origin_03'),
                '07' => $this->language->get('text_us_origin_07'),
                '08' => $this->language->get('text_us_origin_08'),
                '11' => $this->language->get('text_us_origin_11'),
                '12' => $this->language->get('text_us_origin_12'),
                '13' => $this->language->get('text_us_origin_13'),
                '14' => $this->language->get('text_us_origin_14'),
                '54' => $this->language->get('text_us_origin_54'),
                '59' => $this->language->get('text_us_origin_59'),
                '65' => $this->language->get('text_us_origin_65')
            ),
            // Canada Origin
            'CA' => array(
                '01' => $this->language->get('text_ca_origin_01'),
                '02' => $this->language->get('text_ca_origin_02'),
                '07' => $this->language->get('text_ca_origin_07'),
                '08' => $this->language->get('text_ca_origin_08'),
                '11' => $this->language->get('text_ca_origin_11'),
                '12' => $this->language->get('text_ca_origin_12'),
                '13' => $this->language->get('text_ca_origin_13'),
                '14' => $this->language->get('text_ca_origin_14'),
                '54' => $this->language->get('text_ca_origin_54'),
                '65' => $this->language->get('text_ca_origin_65')
            ),
            // European Union Origin
            'EU' => array(
                '07' => $this->language->get('text_eu_origin_07'),
                '08' => $this->language->get('text_eu_origin_08'),
                '11' => $this->language->get('text_eu_origin_11'),
                '54' => $this->language->get('text_eu_origin_54'),
                '65' => $this->language->get('text_eu_origin_65'),
                // next five services Poland domestic only
                '82' => $this->language->get('text_eu_origin_82'),
                '83' => $this->language->get('text_eu_origin_83'),
                '84' => $this->language->get('text_eu_origin_84'),
                '85' => $this->language->get('text_eu_origin_85'),
                '86' => $this->language->get('text_eu_origin_86')
            ),
            // Puerto Rico Origin
            'PR' => array(
                '01' => $this->language->get('text_eu_origin_01'),
                '02' => $this->language->get('text_eu_origin_02'),
                '03' => $this->language->get('text_eu_origin_03'),
                '07' => $this->language->get('text_ca_origin_07'),
                '08' => $this->language->get('text_ca_origin_08'),
                '14' => $this->language->get('text_eu_origin_14'),
                '54' => $this->language->get('text_other_origin_54'),
                '65' => $this->language->get('text_other_origin_65')
            ),
            // Mexico Origin
            'MX' => array(
                '07' => $this->language->get('text_mx_origin_07'),
                '08' => $this->language->get('text_mx_origin_08'),
                '54' => $this->language->get('text_mx_origin_54'),
                '65' => $this->language->get('text_mx_origin_65')
            ),
            // All other origins
            'other' => array(
                // service code 7 seems to be gone after January 2, 2007
                '07' => $this->language->get('text_other_origin_07'),
                '08' => $this->language->get('text_other_origin_08'),
                '11' => $this->language->get('text_other_origin_11'),
                '54' => $this->language->get('text_other_origin_54'),
                '65' => $this->language->get('text_other_origin_65')
            )
        );
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
        $result = curl_exec($ch);
        curl_close($ch);
        $quote_data = array();
        if ($result) {
            $dom = new DOMDocument('1.0', 'UTF-8');
            $dom->loadXml($result);
            $rating_service_selection_response = $dom->getElementsByTagName('RatingServiceSelectionResponse')->item(0);
            $response = $rating_service_selection_response->getElementsByTagName('Response')->item(0);
            $response_status_code = $response->getElementsByTagName('ResponseStatusCode');
            if ($response_status_code->item(0)->nodeValue != '1') {
                $error = $response->getElementsByTagName('Error')->item(0);
                $error_msg = $error->getElementsByTagName('ErrorCode')->item(0)->nodeValue;
                $error_msg .= ': ' . $error->getElementsByTagName('ErrorDescription')->item(0)->nodeValue;
            } else {
                $rated_shipments = $rating_service_selection_response->getElementsByTagName('RatedShipment');
                foreach ($rated_shipments as $rated_shipment) {
                    $service = $rated_shipment->getElementsByTagName('Service')->item(0);
                    $code = $service->getElementsByTagName('Code')->item(0)->nodeValue;
                    $total_charges = $rated_shipment->getElementsByTagName('TotalCharges')->item(0);
                    $cost = $total_charges->getElementsByTagName('MonetaryValue')->item(0)->nodeValue;
                    if (!($code && $cost)) {
                        continue;
                    }
                    if (!$this->config->get('default_ups_' . strtolower($this->config->get('default_ups_origin')) . '_' . $code)) {
                        $quote_data[$code] = array(
                            'id'           => 'default_ups.' . $code,
                            'title'        => $service_code[$this->config->get('default_ups_origin')][$code],
                            'cost'         => $this->currency->convert($cost, 'USD', $this->currency->getCode()),
                            'tax_class_id' => $this->config->get('default_ups_tax_class_id'),
                            'text'         => $this->currency->format($this->tax->calculate($this->currency->convert($cost, 'USD', $this->currency->getCode()), $this->config->get('default_ups_tax_class_id'), $this->config->get('config_tax')))
                        );
                    }
                }
            }
        }
        return array('quote_data'=>$quote_data, 'error_msg'=>$error_msg);
    }
}