/**
 * Filter the product retruned by `WC_Order::woocommerce_get_product_from_item()`
 * to re-calculate a Measurement Price Calculator product's weight based on the
 * selected measurements. This function ensures that the "Weight" calculator
 * type is handled appropriately as well.
 *
 * @param \WC_Product $product The product.
 * @param array $item The order item.
 * @param \WC_Order $order The order.
 * @return \WC_Product The filtered product
 */
function sv_wc_mpc_shipstation_get_product_from_item_weight($product, $item, $order)
{
    if (WC_Price_Calculator_Product::pricing_calculated_weight_enabled($product)) {
        $settings = new WC_Price_Calculator_Settings($product);
        if ('weight' == $settings->get_calculator_type()) {
            // Now, the weight calculator products have to be handled specially
            // since the customer is actually supplying the weight, but it will
            // be in pricing units which may not be the same as the globally
            // configured WooCommerce Weight Unit expected by other plugins and code
            if (isset($item['item_meta']['_measurement_data'][0])) {
                $measurement_data = maybe_unserialize($item['item_meta']['_measurement_data'][0]);
                if (isset($measurement_data['_measurement_needed_unit']) && isset($measurement_data['_measurement_needed'])) {
                    $supplied_weight = new WC_Price_Calculator_Measurement($measurement_data['_measurement_needed_unit'], $measurement_data['_measurement_needed']);
                    // set the product weight as supplied by the customer, in WC Weight Units
                    $product->weight = $supplied_weight->get_value(get_option('woocommerce_weight_unit'));
                }
            }
        } elseif ($product->get_weight()) {
            if (isset($item['item_meta']['_measurement_data'][0])) {
                $measurement_data = maybe_unserialize($item['item_meta']['_measurement_data'][0]);
                // record the configured weight per unit for future reference
                if (!isset($measurement_data['_weight'])) {
                    $measurement_data['_weight'] = $product->get_weight();
                }
                // calculate the product weight = unit weight * total measurement (both will be in the same pricing units so we have say lbs/sq. ft. * sq. ft. = lbs)
                $product->weight = $measurement_data['_weight'] * $measurement_data['_measurement_needed'];
            }
        }
    }
    return $product;
}
 /**
  * Gets the total physical property measurement for the given product
  * that is the product length/width/height, area, volume or weight, depending
  * on the current calculator type.
  *
  * So for instance, if the calculator type is Area or Area (LxW) the returned
  * measurment will be an area measurement, with the area value taken from the
  * product configuration dimensions (length x width) or area.
  *
  * @since 3.0
  * @param WC_Product $product the product
  * @param WC_Price_Calculator_Settings $settings the measurement price calculator settings
  * @return WC_Price_Calculator_Measurement physical property measurement or null
  */
 public static function get_product_measurement($product, $settings)
 {
     switch ($settings->get_calculator_type()) {
         case 'dimension':
             return self::get_dimension_measurement($product, $settings->get_calculator_measurements());
         case 'area':
         case 'area-dimension':
             return self::get_area_measurement($product);
         case 'area-linear':
             return self::get_perimeter_measurement($product);
         case 'area-surface':
             return self::get_surface_area_measurement($product);
         case 'volume':
         case 'volume-dimension':
         case 'volume-area':
             return self::get_volume_measurement($product);
         case 'weight':
             return self::get_weight_measurement($product);
             // just a specially presented area calculator
         // just a specially presented area calculator
         case 'wall-dimension':
             return self::get_area_measurement($product);
     }
     // should never happen
     return null;
 }
 /**
  * Register/queue frontend scripts.
  *
  * @since 3.0
  */
 public function enqueue_frontend_scripts()
 {
     global $post, $wc_measurement_price_calculator;
     $product = null;
     if (is_product()) {
         $product = SV_WC_Plugin_Compatibility::wc_get_product($post->ID);
     }
     // is the calculator enabled for this product?
     if (!$product || !WC_Price_Calculator_Product::calculator_enabled($product)) {
         return;
     }
     $settings = new WC_Price_Calculator_Settings($product);
     wp_enqueue_script('wc-price-calculator', $wc_measurement_price_calculator->get_plugin_url() . '/assets/js/frontend/wc-measurement-price-calculator.min.js');
     // Variables for JS scripts
     $wc_price_calculator_params = array('woocommerce_currency_symbol' => get_woocommerce_currency_symbol(), 'woocommerce_price_num_decimals' => (int) get_option('woocommerce_price_num_decimals'), 'woocommerce_currency_pos' => get_option('woocommerce_currency_pos'), 'woocommerce_price_decimal_sep' => stripslashes(get_option('woocommerce_price_decimal_sep')), 'woocommerce_price_thousand_sep' => stripslashes(get_option('woocommerce_price_thousand_sep')), 'woocommerce_price_trim_zeros' => get_option('woocommerce_price_trim_zeros'), 'unit_normalize_table' => WC_Price_Calculator_Measurement::get_normalize_table(), 'unit_conversion_table' => WC_Price_Calculator_Measurement::get_conversion_table(), 'measurement_precision' => apply_filters('wc_measurement_price_calculator_measurement_precision', 3), 'minimum_price' => WC_Price_Calculator_Product::get_product_meta($product, 'wc_measurement_price_calculator_min_price'), 'measurement_type' => $settings->get_calculator_type());
     // information required for either pricing or quantity calculator to function
     $wc_price_calculator_params['product_price'] = $product->is_type('variable') ? '' : $product->get_price();
     // get the product total measurement (ie Area), get a measurement (ie length), and determine the product total measurement common unit based on the measurements common unit
     $product_measurement = WC_Price_Calculator_Product::get_product_measurement($product, $settings);
     $measurements = $settings->get_calculator_measurements();
     list($measurement) = $measurements;
     $product_measurement->set_common_unit($measurement->get_unit_common());
     // this is the unit that the product total measurement will be in, ie it's how we know what unit we get for the Volume (AxH) calculator after multiplying A * H
     $wc_price_calculator_params['product_total_measurement_common_unit'] = $product_measurement->get_unit_common();
     if (WC_Price_Calculator_Product::pricing_calculator_enabled($product)) {
         // product information required for the pricing calculator javascript to function
         $wc_price_calculator_params['calculator_type'] = 'pricing';
         $wc_price_calculator_params['product_price_unit'] = $settings->get_pricing_unit();
         // if there are pricing rules, include them on the page source
         if ($settings->pricing_rules_enabled()) {
             $wc_price_calculator_params['pricing_rules'] = $settings->get_pricing_rules();
             // generate the pricing html
             foreach ($wc_price_calculator_params['pricing_rules'] as $index => $rule) {
                 $price_html = $settings->get_pricing_rule_price_html($rule);
                 $wc_price_calculator_params['pricing_rules'][$index]['price_html'] = '<span class="price">' . $price_html . '</span>';
             }
         }
     } else {
         // product information required for the quantity calculator javascript to function
         $wc_price_calculator_params['calculator_type'] = 'quantity';
         $quantity_range = WC_Price_Calculator_Product::get_quantity_range($product);
         $wc_price_calculator_params['quantity_range_min_value'] = $quantity_range['min_value'];
         $wc_price_calculator_params['quantity_range_max_value'] = $quantity_range['max_value'];
         if ($product->is_type('simple')) {
             // product_measurement represents one quantity of the product, bail if missing required product physical attributes
             if (!$product_measurement->get_value()) {
                 return;
             }
             $wc_price_calculator_params['product_measurement_value'] = $product_measurement->get_value();
             $wc_price_calculator_params['product_measurement_unit'] = $product_measurement->get_unit();
         } else {
             // provided by the available_variation() method
             $wc_price_calculator_params['product_measurement_value'] = '';
             $wc_price_calculator_params['product_measurement_unit'] = '';
         }
     }
     wp_localize_script('wc-price-calculator', 'wc_price_calculator_params', $wc_price_calculator_params);
 }
 /**
  * Pricing calculator calculated weight handling
  *
  * This method is responsible for the Pricing Calculator
  * products calculated weight handling.  By default, a pricing calculator product's
  * weight will be defined as would any other, non-customizable product.  Meaning
  * that if you have a weight of '10 lbs' for custom-sized tiling, an item could
  * be of any area and still weigh 10 lbs, which probably isn't very realistic.
  *
  * With calculated weight enabled, that same weight of '10' would repesent
  * '10 lbs / sq ft' meaning that the total weight of an item is calculated based
  * on its weight ratio and total measurement.
  *
  * The implementation strategy used to achieve this is to hook into some critical
  * actions in the WC_Cart class, loop through the cart items and calculate and
  * set a weight on the relevant products.  Then when the various shipping
  * methods call the $product->get_weight() the correct, calculated weight will
  * be returned.
  *
  * @since 3.0
  * @param WC_Cart $cart the cart object
  */
 public function calculate_product_weights($cart)
 {
     // Loop through the cart items calculating the total weight for any pricing
     //  calculator calculated weight products
     foreach ($cart->cart_contents as $cart_item_key => &$values) {
         $product = $_product = $values['data'];
         // need the parent product to retrieve the calculator settings from
         if (isset($_product->variation_id) && $_product->variation_id) {
             $product = wc_get_product($_product->id);
         }
         if (WC_Price_Calculator_Product::pricing_calculated_weight_enabled($_product)) {
             $settings = new WC_Price_Calculator_Settings($product);
             if ('weight' == $settings->get_calculator_type()) {
                 // Now, the weight calculator products have to be handled specially
                 //  since the customer is actually supplying the weight, but it will
                 //  be in pricing units which may not be the same as the globally
                 //  configured WooCommerce Weight Unit expected by other plugins and code
                 $supplied_weight = new WC_Price_Calculator_Measurement($values['pricing_item_meta_data']['_measurement_needed_unit'], $values['pricing_item_meta_data']['_measurement_needed']);
                 // set the product weight as supplied by the customer, in WC Weight Units
                 $_product->weight = $supplied_weight->get_value(get_option('woocommerce_weight_unit'));
             } elseif ($_product->get_weight()) {
                 // record the configured weight per unit for future reference
                 if (!isset($values['pricing_item_meta_data']['_weight'])) {
                     $values['pricing_item_meta_data']['_weight'] = $_product->get_weight();
                 }
                 // calculate the product weight = unit weight * total measurement (both will be in the same pricing units so we have say lbs/sq. ft. * sq. ft. = lbs)
                 $_product->weight = $values['pricing_item_meta_data']['_weight'] * $values['pricing_item_meta_data']['_measurement_needed'];
             }
         }
     }
 }