/** * 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']; } } } }