/** * Modify the 'add to cart' url for pricing calculator products to simply link to * the product page, just like a variable product. This is because the * customer must supply whatever product measurements they require. * * @since 3.3 * @param string $tag the 'add to cart' button tag html * @param WC_Product $product the product * @return string the Add to Cart tag */ public function loop_add_to_cart_link($tag, $product) { if (WC_Price_Calculator_Product::pricing_calculator_enabled($product)) { // otherwise, for simple type products, the page javascript would take over and // try to do an ajax add-to-cart, when really we need the customer to visit the // product page to supply whatever input fields they require $tag = sprintf('<a href="%s" rel="nofollow" data-product_id="%s" data-product_sku="%s" class="button add_to_cart_button product_type_%s">%s</a>', get_permalink($product->id), esc_attr($product->id), esc_attr($product->get_sku()), 'variable', __('Select options', WC_Measurement_Price_Calculator::TEXT_DOMAIN)); } return $tag; }
/** * Returns an array of measurements for the given product * * @since 3.0 * @param WC_Product $product the product * @return array of WC_Price_Calculator_Measurement objects for the product */ public static function get_product_measurements($product) { if (WC_Price_Calculator_Product::pricing_calculator_enabled($product)) { $settings = new WC_Price_Calculator_Settings($product); return $settings->get_calculator_measurements(); } }
/** * Render the price calculator on the product page * * @since 3.0 */ public function render_price_calculator() { global $product, $wc_measurement_price_calculator; // is the calculator enabled for this product? if (!$product || !WC_Price_Calculator_Product::calculator_enabled($product)) { return; } $settings = new WC_Price_Calculator_Settings($product); if (WC_Price_Calculator_Product::pricing_calculator_enabled($product)) { // Pricing calculator with custom dimensions and a price "per unit" // get the product total measurement (ie Area or Volume, etc) $product_measurement = WC_Price_Calculator_Product::get_product_measurement($product, $settings); $product_measurement->set_unit($settings->get_pricing_unit()); // get the product measurements, get a measurement, and set the product total measurement common unit based on the measurements common unit $measurements = $settings->get_calculator_measurements(); list($measurement) = $measurements; $product_measurement->set_common_unit($measurement->get_unit_common()); // pricing calculator enabled, get the template wc_get_template('single-product/price-calculator.php', array('product_measurement' => $product_measurement, 'settings' => $settings, 'measurements' => $measurements), '', $wc_measurement_price_calculator->get_plugin_path() . '/templates/'); // need an element to contain the price for simple pricing rule products if ($product->is_type('simple') && $settings->pricing_rules_enabled()) { echo '<div class="single_variation"></div>'; } } else { // quantity calculator. where the quantity of product needed is based on the configured product dimensions. This is a actually bit more complex // get the starting quantity, max quantity, and total product measurement in product units $quantity_range = WC_Price_Calculator_Product::get_quantity_range($product); // set the product measurement based on the minimum quantity value, and set the unit to the frontend calculator unit $measurements = $settings->get_calculator_measurements(); // The product measurement will be used to create the 'amount actual' field. $product_measurement = WC_Price_Calculator_Product::get_product_measurement($product, $settings); // see whether all calculator measurements are defined in the same units (ie 'in', 'sq. in.' are considered the same) $measurements_unit = null; foreach ($measurements as $measurement) { if (!$measurements_unit) { $measurements_unit = $measurement->get_unit(); } else { if (!WC_Price_Calculator_Measurement::compare_units($measurements_unit, $measurement->get_unit())) { $measurements_unit = false; break; } } } // All calculator measurements use the same base units, so lets use those for the 'amount actual' field // area/volume product measurement can have a calculator measurement defined in units of length, so it // will need to be converted to units of area or volume respectively if ($measurements_unit) { switch ($product_measurement->get_type()) { case 'area': $measurements_unit = WC_Price_Calculator_Measurement::to_area_unit($measurements_unit); break; case 'volume': $measurements_unit = WC_Price_Calculator_Measurement::to_volume_unit($measurements_unit); break; } } // if the price per unit is displayed for this product, default to the pricing units for the 'amount actual' field if (WC_Price_Calculator_Product::pricing_per_unit_enabled($product)) { $measurements_unit = $settings->get_pricing_unit(); } // if a measurement unit other than the default was determined, set it if ($measurements_unit) { $product_measurement->set_unit($measurements_unit); } $total_price = ''; if ($product->is_type('simple')) { // If the product type is simple we can set an initial 'Amount Actual' and 'total price' // we can't do this for variable products because we don't know which will be configured // initially (actually I guess a default product can be configured, so maybe we can do something here) // not enough product physical attributes defined to get our measurement, so bail if (!$product_measurement->get_value()) { return; } // figure out the starting measurement amount // multiply the starting quantity by the measurement value $product_measurement->set_value(round($quantity_range['min_value'] * $product_measurement->get_value(), 2)); $total_price = wc_price($quantity_range['min_value'] * $product->get_price(), 2); } elseif ($product->is_type('variable')) { // clear the product measurement value for variable products, since we can't really know what it is ahead of time (except for when a default is set) $product_measurement->set_value(''); } // pricing calculator enabled, get the template wc_get_template('single-product/quantity-calculator.php', array('calculator_type' => $settings->get_calculator_type(), 'product_measurement' => $product_measurement, 'measurements' => $measurements, 'total_price' => $total_price), '', $wc_measurement_price_calculator->get_plugin_path() . '/templates/'); } }
/** * Returns the cart item data for the given item being re-ordered. This is * a somewhat complex process of re-configuring the product based on the * original measurements, taking into account unit changes. We do not handle * calculator type changes at the moment; in fact there's probably no way * of accounting for this. (actually we could handle calculator changes as * long as the calculator type was simplified, ie Area (L x W) -> Area, * but aside from that there's nothing we can do) * * @since 3.0 * @param array $cart_item_data the cart item data * @param array $item the item * @param WC_Order $order the original order * @return array the cart item data */ public function order_again_cart_item_data($cart_item_data, $item, $order) { $product = wc_get_product($item['product_id']); if (WC_Price_Calculator_Product::pricing_calculator_enabled($product) && isset($item['item_meta']['_measurement_data'][0]) && $item['item_meta']['_measurement_data'][0]) { $measurement_data = maybe_unserialize($item['item_meta']['_measurement_data'][0]); $settings = new WC_Price_Calculator_Settings($product); $measurements = $settings->get_calculator_measurements(); // get the old product measurements, converting to the new measurement units as needed foreach ($measurements as $measurement) { if (isset($measurement_data[$measurement->get_name()])) { $current_unit = $measurement->get_unit(); $measurement->set_value($measurement_data[$measurement->get_name()]['value']); $measurement->set_unit($measurement_data[$measurement->get_name()]['unit']); $cart_item_data['pricing_item_meta_data'][$measurement->get_name()] = $measurement->get_value($current_unit); } } // the product total measurement $measurement_needed = new WC_Price_Calculator_Measurement($measurement_data['_measurement_needed_unit'], $measurement_data['_measurement_needed']); // 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; } // set the product price based on the price per unit and the total measurement $cart_item_data['pricing_item_meta_data']['_price'] = $price; // save the total measurement (length, area, volume, etc) in pricing units $cart_item_data['pricing_item_meta_data']['_measurement_needed'] = $measurement_needed->get_value(); $cart_item_data['pricing_item_meta_data']['_measurement_needed_unit'] = $measurement_needed->get_unit(); // pick up the item quantity which we set in order_again_item_set_quantity() if (isset($item['item_meta']['_quantity'][0])) { $cart_item_data['pricing_item_meta_data']['_quantity'] = $item['item_meta']['_quantity'][0]; } } return $cart_item_data; }