/**
  * Calculate the item price based on the given measurements
  *
  * @since 3.1.3
  * @param WC_Product $product the product
  * @param float $measurement_needed_value the total measurement needed
  * @param string $measurement_needed_value_unit the unit of $measurement_needed_value
  * @return float the calculated price
  */
 public static function calculate_price($product, $measurement_needed_value, $measurement_needed_value_unit)
 {
     $price = $product->get_price();
     // get the parent product if there is one
     $_product = 'WC_Product_Variation' == get_class($product) ? $product->parent : $product;
     if (self::pricing_calculator_enabled($_product)) {
         $settings = new WC_Price_Calculator_Settings($_product);
         $measurement_needed = new WC_Price_Calculator_Measurement($measurement_needed_value_unit, (double) $measurement_needed_value);
         // if this calculator uses pricing rules, retrieve the price based on the product measurements
         if ($settings->pricing_rules_enabled()) {
             $product->price = $settings->get_pricing_rules_price($measurement_needed);
         }
         // calculate the price
         $price = $product->get_price() * $measurement_needed->get_value($settings->get_pricing_unit());
         // is there a minimum price to use?
         if (WC_Price_Calculator_Product::get_product_meta($product, 'wc_measurement_price_calculator_min_price') > $price) {
             $price = WC_Price_Calculator_Product::get_product_meta($product, 'wc_measurement_price_calculator_min_price');
         }
     }
     // return the final price
     return $price;
 }
 /**
  * Calculate the item price based on the given measurements
  *
  * @since 3.1.3
  * @param WC_Product $product the product
  * @param float $measurement_needed_value the total measurement needed
  * @param string $measurement_needed_value_unit the unit of $measurement_needed_value
  * @param bool $round Optional. If true the returned price will be rounded to two decimal places. Default true.
  * @return float the calculated price
  */
 public static function calculate_price($product, $measurement_needed_value, $measurement_needed_value_unit, $round = true)
 {
     $price = $product->get_price();
     // get the parent product if there is one
     $_product = 'WC_Product_Variation' == get_class($product) ? $product->parent : $product;
     if (self::pricing_calculator_enabled($_product)) {
         $settings = new WC_Price_Calculator_Settings($_product);
         $measurement_needed = new WC_Price_Calculator_Measurement($measurement_needed_value_unit, (double) $measurement_needed_value);
         // if this calculator uses pricing rules, retrieve the price based on the product measurements
         if ($settings->pricing_rules_enabled()) {
             $product->price = $settings->get_pricing_rules_price($measurement_needed);
         }
         // calculate the price
         $price = $product->get_price() * $measurement_needed->get_value($settings->get_pricing_unit());
         // is there a minimum price to use?
         if ($product->wc_measurement_price_calculator_min_price > $price) {
             $price = $product->wc_measurement_price_calculator_min_price;
         }
     }
     if ($round) {
         $price = round($price, absint(get_option('woocommerce_price_num_decimals', 2)));
     }
     // return the final price
     return $price;
 }
 /**
  * Append the dimension unit to the weight unit option value
  *
  * @since 3.7.00
  * @param string $weight_unit The value of woocommerce_weight_unit option
  * @return string The weight per unit label
  */
 public function add_weight_per_unit_label($weight_unit)
 {
     global $product;
     // bail if the calculator isn't enabled for this product
     if (!$product || !WC_Price_Calculator_Product::calculator_enabled($product)) {
         return;
     }
     // bail if the calculator isn't enabled for this product
     if (!WC_Price_Calculator_Product::pricing_calculated_weight_enabled($product)) {
         return;
     }
     $settings = new WC_Price_Calculator_Settings($product);
     return $weight_unit . ' / ' . $settings->get_pricing_unit();
 }
 /**
  * Add a measurement product to the cart.  This allows for the programmatic
  * addition of measurement pricing calculator products to the cart.
  *
  * This method expects the single total measurement needed, given by
  * $measurement_needed, this would be the dimension, area, volume or weight
  * depending on the type of calculator.
  *
  * This method also expects the full set of product measurements, given by
  * $measurements.  For calculators with a single measurement like the dimension
  * calculator or simple area, this will contain the same value as
  * $measurement_needed.  For more complex calculators, like Area (w x l)
  * this is how the width and length measurements are specified.  For
  * convenience use <code>WC_Price_Calculator_Product::get_product_measurements( $product )</code>
  * to get the set of dimensions for your product, along with the correct
  * units, and set whatever values you need.
  *
  * @since 3.0
  * @param string $product_id contains the id of the product to add to the cart
  * @param WC_Price_Calculator_Measurement $measurement_needed the total
  *        measurement desired, ie 1 m, 3 sq. ft., etc
  * @param array $measurements array of WC_Price_Calculator_Measurement product
  *        measurements, ie 1 m or 1.5 ft, 1.5 ft.  Defaults to $measurement_needed
  *        for convenience for calculators with a single measurement like dimension,
  *        simple area, etc.
  * @param string $quantity contains the quantity of the item to add
  * @param int $variation_id optional variation id
  * @param array $variation optional attribute values
  * @param array $cart_item_data optional extra cart item data we want to pass into the item
  * @return bool true on success
  */
 public function add_to_cart($product_id, $measurement_needed, $measurements = array(), $quantity = 1, $variation_id = '', $variation = '', $cart_item_data = array())
 {
     // if measurements is empty just use the provided $measurement_needed (this is a shortcut for calculators with only one measurement, ie 'length', 'area', etc)
     if (empty($measurements)) {
         $measurements[] = $measurement_needed;
     }
     // build up the cart item data with the required values that would normally come in over the add to cart post request
     $cart_item_data['pricing_item_meta_data']['_measurement_needed_internal'] = $measurement_needed->get_value();
     $cart_item_data['pricing_item_meta_data']['_measurement_needed_unit_internal'] = $measurement_needed->get_unit();
     $cart_item_data['pricing_item_meta_data']['_quantity'] = $quantity;
     $product = wc_get_product($product_id);
     $settings = new WC_Price_Calculator_Settings($product);
     if (WC_Price_Calculator_Product::pricing_calculator_inventory_enabled($product)) {
         // pricing calculator product with inventory enabled, means we need to take the item quantity (ie 2) and determine the unit quantity (ie 2 * 3 ft = 6)
         $quantity *= $measurement_needed->get_value($settings->get_pricing_unit());
     }
     foreach ($measurements as $measurement) {
         $cart_item_data['pricing_item_meta_data'][$measurement->get_name()] = $measurement->get_value();
     }
     // initialize the cart_contents member if needed to avoid a warning from cart::find_product_in_cart()
     if (is_null(WC()->cart->cart_contents)) {
         WC()->cart->cart_contents = array();
     }
     return WC()->cart->add_to_cart($product_id, $quantity, $variation_id, $variation, $cart_item_data);
 }
 /**
  * Manage the order stock (whether restore or reduce) from the order admin
  * returning the true product stock change if this is for a pricing calculator
  * product/item with inventory enabled.  Ie 2 pieces of cloth at 3 ft each
  * we'd want to return 6
  *
  * @since 3.0
  * @param numeric $quantity the new quantity
  * @param string $item_id the order item identifier
  * @return numeric $quantity the measurement quantity
  */
 public function admin_manage_order_stock($quantity, $item_id)
 {
     $order_id = absint($_POST['order_id']);
     $order = wc_get_order($order_id);
     $order_items = $order->get_items();
     $product = wc_get_product($order_items[$item_id]['product_id']);
     if (WC_Price_Calculator_Product::pricing_calculator_inventory_enabled($product) && isset($order_items[$item_id]['measurement_data'])) {
         $settings = new WC_Price_Calculator_Settings($product);
         $measurement_data = maybe_unserialize($order_items[$item_id]['measurement_data']);
         $total_amount = new WC_Price_Calculator_Measurement($measurement_data['_measurement_needed_unit'], $measurement_data['_measurement_needed']);
         // this is a pricing calculator product so we want to return the
         //  quantity in terms of units, ie 2 pieces of cloth at 3 ft each = 6
         $quantity *= $total_amount->get_value($settings->get_pricing_unit());
     }
     return $quantity;
 }