public function __construct()
        {
            //Global variable for accessing post data
            global $post;
            //get shipment data for this order
            $shipment = get_post_meta($post->ID, '_shipment', true);
            //create instance of WooCommerce order for accessing order data
            $order = wc_get_order($post->ID);
            //Update shipment structure for version compatibility
            $shipment = cleanse_shipment($order, $shipment);
            if ($shipment['_shipment_status'] !== 'Not Shipped' && $shipment['_shipment_status'] !== 'DELIVERED') {
                if ((bool) @fsockopen('www.canyonwerks.com', 80)) {
                    $shipment = slp_ajax_functions::track_shipment($order, $shipment);
                } else {
                    ?>
				<script type="text/javascript">
					$('<div id="message" class="error fade"><p><strong>Connection Error. Please check internet connection.</strong>').insertAfter('#wpbody-content > .wrap > h2');	

				</script><?php 
                }
            }
            //display SLP meta box
            $this->get_meta_box($order, $shipment);
        }
function cleanse_shipment($order, $shipment = array())
{
    //Check if version number is present and is current, return if is upto date
    if (isset($shipment['_version']) && $shipment['_version'] === SLP_VERSION) {
        return $shipment;
    }
    //Check if shipping cost has been calculated
    if (!isset($shipment['_shipping_cost'])) {
        //Check for shipping cost in order meta first
        if ($shipping_total = get_post_meta($order->id, '_shipping_cost', true)) {
            //set shipping cost
            $shipping_cost = $shipping_total;
        } else {
            //set inital shipment status
            $shipment['_shipment_status'] = 'Not Shipped';
            //set shipping cost text
            $shipping_cost = '<span>Shipping Cost Not Calculated</span>';
        }
        //add to shipment
        $shipment['_shipping_cost'] = $shipping_cost;
    }
    //Get shipment package data
    $shipment = slp_ajax_functions::get_packages($order, $shipment);
    //cleanse shipment if not compatible
    if (!isset($shipment['_shipment_status']) || $shipment['_shipment_status'] != 'Not Shipped') {
        //parse through packages
        foreach ($shipment['_packages'] as $key => $package) {
            //try to find tracking number if set in packages
            if (!isset($package->id)) {
                //set tracking number if exists
                if (array_key_exists('_tracking_numbers', $shipment)) {
                    $package->id = $shipment['_tracking_numbers'][$key];
                    //check older versions
                } else {
                    if ($tracking_number = get_post_meta($order->id, '_tracking_number', true)) {
                        $package->id = $tracking_number;
                    } else {
                        if ($tracking_number = get_post_meta($order->id, '_tracking_numbers', true)) {
                            $package->id = $tracking_number[$key];
                            //default if no tracking number found
                        } else {
                            $package->id = 'Not Trackable';
                        }
                    }
                }
            }
            //remove tracking_status after update to package data
            if (isset($package->tracking_status)) {
                unset($package->tracking_status);
            }
            //store shipping labels shipping labels if they exists
            if (array_key_exists('_shipping_labels', $shipment)) {
                //check if shipping label is base 64 gif code and format otherwise store as is
                $package->ShippingLabel = preg_match('/^[a-zA-Z0-9\\/\\r\\n+]*={0,2}$/', $shipment['_shipping_labels'][$key]) ? 'data:image/gif;base64,' . $shipment['_shipping_labels'][$key] : $shipment['_shipping_labels'][$key];
            }
        }
        //array of keys that will be removed from shipment and post for normalization
        $cleanse = array('_shipment_id', '_tracking_numbers', '_shipping_labels', '_total_weight', '_package_count', '_service_code', '_country_code', '_pickup_date', '_no_pickup', '_number_of_packages', '_total_weight', '_shipping_cost', '_shipping_digest', '_tracking_number', '_shipment_status', '_pickup_date', '_shipping_label', '_shipment_status');
        //remove specified items from shipment and order
        foreach ($cleanse as $index) {
            if (array_key_exists($index, $shipment)) {
                if (!$index === '_shipping_cost' || !$index === '_shipment_status') {
                    unset($shipment[$index]);
                }
            }
            delete_post_meta($order->id, $index);
        }
    }
    //update shipment verision
    $shipment['_version'] = SLP_VERSION;
    //save changes to DB
    update_post_meta($order->id, '_shipment', $shipment);
    //return shipment for further processing
    return $shipment;
}
 /**
  * Retrieves order items and packs them into boxes by dimensions
  *
  * @params mixed $order for order we are working with
  * @params array $shipment for order we are working with
  *
  * @return mixed array
  */
 public static function get_packages($order, $shipment)
 {
     global $woocommerce;
     //load box packer if not already loaded
     if (!class_exists('WC_Boxpack')) {
         include_once WP_CONTENT_DIR . '/plugins/woocommerce-shipping-usps/includes/box-packer/class-wc-boxpack.php';
     }
     //pack items if not set
     if (!isset($shipment['_packages'])) {
         $boxpack = new WC_Boxpack();
         self::$shipper = self::get_shipper($order);
         //get boxes from shipper class settings
         $boxes = self::$shipper->get_boxes();
         //Add Standard and Custom Boxes
         if (!empty($boxes)) {
             foreach ($boxes as $key => $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']);
                 $newbox->set_max_weight($box['max_weight']);
                 $newbox->set_id = $key;
             }
         }
         //retrieve order items for packing
         $items = $order->get_items();
         //add order items
         foreach ($items as $key => $item) {
             $product = $order->get_product_from_item($item);
             $item_key = $key;
             $dim = explode(' ', str_replace(' x ', ' ', $product->get_dimensions()));
             for ($i = 0; $i < $item['qty']; ++$i) {
                 $boxpack->add_item(number_format(wc_get_dimension($dim[0], 'in'), 2), number_format(wc_get_dimension($dim[1], 'in'), 2), number_format(wc_get_dimension($dim[2], 'in'), 2), number_format(wc_get_weight($product->get_weight(), 'lbs'), 2), $product->get_price(), array('id' => $item['variation_id'] ? $item['variation_id'] : $item['product_id']));
             }
         }
         //Pack Items into boxes & return
         $boxpack->pack();
         //get packed items
         $shipment['_packages'] = $boxpack->get_packages();
     }
     //normalize array for later use
     if (!is_array($shipment['_packages'][0]->packed[0])) {
         //Parse through items and convert std objects to arrays
         foreach ($shipment['_packages'] as $package) {
             //if no tracking number set
             if (!isset($package->id) || empty($package->id)) {
                 $package->id = 'No Tracking# Assigned';
             }
             //remove unnecessay data
             unset($package->unpacked);
             //convert WC_Item to array
             foreach ($package->packed as $key => $line) {
                 $line = (array) $line;
                 array_shift($line);
                 $package->packed[$key] = $line;
             }
         }
         //save changes to DB
         //self::update_shipment( $order->id, $shipment );
     }
     //return shipment for further processing
     return $shipment;
 }
	public function error_handler( $order, $shipment, $function, $line, $error ) {
		
		switch( $error->faultstring ) {
			case 'Expired Authenticator':
			case 'Invalid Conversation Token':
			case 'Conversation Out-of-Sync':
				$this->get_auth();
				break;
			case 'Insufficient Postage':
				$this->check_postage_balance( $order, $shipment );
			default:
				slp_ajax_functions::error_handler( $function, __CLASS__, $line, $error->faultstring, $error );
		}
		
		return;
	}
	public function error_handler( $error, $order ) {	
		
		switch( $error->Response->Error->ErrorCode ) {
			case '120802':
				//$this->verify_address( $order, false );
				break;
			//case '151018':
			case '151062':
			case '154030':
			case '151019':
			case '150023':
			case '150022':
			case '151044':
				return $error;
				break;
			default:
				$error_msg  = (string)$error->Response->Error->ErrorDescription;
				$error_code = (string)$error->Response->Error->ErrorCode; 
				slp_ajax_functions::error_handler( __FUNCTION__, __CLASS__, __LINE__, $order, 'UPS Error: ' . $error_code, $error_msg  );
		}
	
	}