/**
  * Construct and initialize the price calculator settings
  *
  * @param mixed $settings optional product or product id to load settings from.  Otherwise, default settings object is instantiated
  */
 public function __construct($product = null)
 {
     $settings = null;
     // product id
     if (is_numeric($product)) {
         $product = SV_WC_Plugin_Compatibility::wc_get_product($product);
     }
     // have a product
     if ($product) {
         $this->product = $product;
         $settings = WC_Price_Calculator_Product::get_product_meta($product, 'wc_price_calculator');
     }
     $this->set_raw_settings($settings);
 }
 /**
  * Get the most reviewed products
  *
  * @since 1.0.0
  * @return array
  */
 public function get_products()
 {
     global $wpdb;
     $reviewed_products = array();
     $results = $wpdb->get_results("\n\t\t\tSELECT p.ID, c.review_count, c2.highest_rating, c2.lowest_rating\n\t\t\tFROM {$wpdb->posts} AS p\n\t\t\tLEFT JOIN ( SELECT comment_post_ID, COUNT(comment_ID) AS review_count\n\t\t\t\tFROM {$wpdb->comments}\n\t\t\t\tWHERE comment_type = 'review'\n\t\t\t\tAND comment_approved = '1'\n\t\t\t\tGROUP BY comment_post_ID\n\t\t\t) AS c ON ( c.comment_post_ID = p.ID )\n\t\t\tJOIN ( SELECT comment_post_ID, MAX(meta_value) AS highest_rating, MIN(meta_value) AS lowest_rating\n\t\t\t\tFROM {$wpdb->comments} c\n\t\t\t\tLEFT JOIN {$wpdb->commentmeta} cm\n\t\t\t\tON cm.comment_id = c.comment_ID\n\t\t\t\tWHERE comment_type = 'review'\n\t\t\t\tAND meta_key = 'rating'\n\t\t\t\tAND comment_approved = '1'\n\t\t\t\tGROUP BY comment_post_ID\n\t\t\t) AS c2 ON( c2.comment_post_ID = p.ID )\n\t\t\tWHERE p.post_type = 'product'\n\t\t\tAND c.review_count > 0\n\t\t\tGROUP BY p.ID\n\t\t\tORDER BY c.review_count DESC\n\t\t");
     if (!empty($results)) {
         foreach ($results as $key => $result) {
             $product = SV_WC_Plugin_Compatibility::wc_get_product($result->ID);
             $reviewed_products[$key] = $product;
             $reviewed_products[$key]->review_count = $result->review_count;
             $reviewed_products[$key]->highest_rating = $result->highest_rating;
             $reviewed_products[$key]->lowest_rating = $result->lowest_rating;
             $reviewed_products[$key]->average_rating = $product->get_average_rating();
         }
     }
     return $reviewed_products;
 }
 /**
  * Output a pricing table
  *
  * * product_id/product_sku - id or sku of product.  Defaults to current product, if any
  *
  * Usage:
  * [wc_measurement_price_calculator_pricing_table]
  *
  * @param array $atts associative array of shortcode parameters
  */
 public static function output($atts)
 {
     global $product, $wpdb;
     extract(shortcode_atts(array('product_id' => '', 'product_sku' => ''), $atts));
     // product by sku?
     if ($product_sku) {
         $product_id = $wpdb->get_var($wpdb->prepare("SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='_sku' AND meta_value=%s LIMIT 1", $product_sku));
     }
     // product by id?
     if ($product_id) {
         $product = SV_WC_Plugin_Compatibility::wc_get_product($product_id);
     }
     // product ?
     if (!$product) {
         return;
     }
     // pricing rules?
     $settings = new WC_Price_Calculator_Settings($product);
     if (!$settings->pricing_rules_enabled() || !$settings->has_pricing_rules()) {
         return;
     }
     // the countdown element with a unique identifier to allow multiple countdowns on the same page, and common class for ease of styling
     echo self::get_pricing_rules_table($settings->get_pricing_rules($settings->get_pricing_unit()), $settings);
 }
 /**
  * Sync variable product prices with the children lowest/highest price per
  * unit.
  *
  * Code based on WC_Product_Variable version 2.0.0
  * @see WC_Product_Variable::variable_product_sync()
  * @see WC_Price_Calculator_Product::variable_product_unsync()
  *
  * @since 3.0
  * @param WC_Product_Variable $product the variable product
  * @param WC_Price_Calculator_Settings $settings the calculator settings
  */
 public static function variable_product_sync($product, $settings)
 {
     // save the original values so we can restore the product
     $product->wcmpc_min_variation_price = $product->min_variation_price;
     $product->wcmpc_min_variation_regular_price = $product->min_variation_regular_price;
     $product->wcmpc_min_variation_sale_price = $product->min_variation_sale_price;
     $product->wcmpc_max_variation_price = $product->max_variation_price;
     $product->wcmpc_max_variation_regular_price = $product->max_variation_regular_price;
     $product->wcmpc_max_variation_sale_price = $product->max_variation_sale_price;
     $product->wcmpc_price = $product->price;
     $product->min_variation_price = $product->min_variation_regular_price = $product->min_variation_sale_price = $product->max_variation_price = $product->max_variation_regular_price = $product->max_variation_sale_price = '';
     foreach ($product->get_children() as $variation_product_id) {
         $variation_product = apply_filters('wc_measurement_price_calculator_variable_product_sync', SV_WC_Plugin_Compatibility::wc_get_product($variation_product_id), $product);
         $child_price = $variation_product->price;
         $child_regular_price = $variation_product->regular_price;
         $child_sale_price = $variation_product->sale_price;
         // get the product measurement
         $measurement = self::get_product_measurement($variation_product, $settings);
         $measurement->set_unit($settings->get_pricing_unit());
         if ('' === $child_price && '' === $child_regular_price || !$measurement->get_value()) {
             continue;
         }
         // convert to price per unit
         if ('' !== $child_price) {
             $child_price /= $measurement->get_value();
         }
         // Regular prices
         if ($child_regular_price !== '') {
             // convert to price per unit
             $child_regular_price /= $measurement->get_value();
             if (!is_numeric($product->min_variation_regular_price) || $child_regular_price < $product->min_variation_regular_price) {
                 $product->min_variation_regular_price = $child_regular_price;
             }
             if (!is_numeric($product->max_variation_regular_price) || $child_regular_price > $product->max_variation_regular_price) {
                 $product->max_variation_regular_price = $child_regular_price;
             }
         }
         // Sale prices
         if ($child_sale_price !== '') {
             // convert to price per unit
             $child_sale_price /= $measurement->get_value();
             if ($child_price == $child_sale_price) {
                 if (!is_numeric($product->min_variation_sale_price) || $child_sale_price < $product->min_variation_sale_price) {
                     $product->min_variation_sale_price = $child_sale_price;
                 }
                 if (!is_numeric($product->max_variation_sale_price) || $child_sale_price > $product->max_variation_sale_price) {
                     $product->max_variation_sale_price = $child_sale_price;
                 }
             }
         }
         // Actual prices
         if ($child_price !== '') {
             if ($child_price > $product->max_variation_price) {
                 $product->max_variation_price = $child_price;
             }
             if ($product->min_variation_price === '' || $child_price < $product->min_variation_price) {
                 $product->min_variation_price = $child_price;
             }
         }
     }
     // as seen in WC_Product_Variable::get_price_html()
     $product->price = $product->min_variation_price;
 }
    /**
     * Add rating and media type dropdowns to reviews list screen filter
     */
    public function restrict_manage_reviews()
    {
        $rating_options = array('' => __('All ratings', 'wc-product-reviews-pro'), '5' => __('Perfect', 'wc-product-reviews-pro'), '4' => __('Good', 'wc-product-reviews-pro'), '3' => __('Average', 'wc-product-reviews-pro'), '2' => __('Mediocre', 'wc-product-reviews-pro'), '1' => __('Poor', 'wc-product-reviews-pro'));
        $current_rating = isset($_REQUEST['rating']) ? $_REQUEST['rating'] : '';
        ?>
		<select name="rating">
			<?php 
        foreach ($rating_options as $value => $label) {
            ?>
				<option value="<?php 
            echo $value;
            ?>
" <?php 
            selected($current_rating, $value);
            ?>
><?php 
            echo $label;
            ?>
</option>
			<?php 
        }
        ?>
		</select>

		<?php 
        $current_product = isset($_REQUEST['p']) ? $_REQUEST['p'] : '';
        $current_product_name = '';
        if ($current_product) {
            $product = SV_WC_Plugin_Compatibility::wc_get_product($current_product);
            $current_product_name = $product->get_formatted_name();
        }
        ?>

		<?php 
        if (SV_WC_Plugin_Compatibility::is_wc_version_gte_2_3()) {
            ?>

			<input type="hidden" class="wc-product-search" name="p" data-placeholder="<?php 
            _e('Search for a product&hellip;', 'wc-product-reviews-pro');
            ?>
" data-selected="<?php 
            echo esc_attr($current_product_name);
            ?>
" value="<?php 
            echo esc_attr($current_product);
            ?>
" data-action="woocommerce_json_search_products" data-allow_clear="true" >

		<?php 
        } else {
            ?>

			<select name="p" class="ajax_chosen_select_product">
				<option value=""><?php 
            _e('All Products', 'wc-product-reviews-pro');
            ?>
</option>
				<?php 
            if ($current_product) {
                echo '<option value="' . esc_attr($current_product) . '" ' . selected(1, 1, false) . '>' . esc_html($current_product_name) . '</option>';
            }
            ?>
			</select>

			<?php 
            // Ajax Chosen Customer Selectors JS
            wc_enqueue_js("\n\t\t\t\tjQuery('select.ajax_chosen_select_product').ajaxChosen({\n\t\t\t\t\tmethod:         'GET',\n\t\t\t\t\turl:            '" . admin_url('admin-ajax.php') . "',\n\t\t\t\t\tdataType:       'json',\n\t\t\t\t\tafterTypeDelay: 100,\n\t\t\t\t\tminTermLength:  1,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction:   'woocommerce_json_search_products',\n\t\t\t\t\t\tsecurity: '" . wp_create_nonce('search-products') . "'\n\t\t\t\t\t}\n\t\t\t\t}, function (data) {\n\n\t\t\t\t\tvar terms = {};\n\n\t\t\t\t\t\$.each(data, function (i, val) {\n\t\t\t\t\t\t\tterms[i] = val;\n\t\t\t\t\t});\n\n\t\t\t\t\treturn terms;\n\t\t\t\t});\n\t\t\t");
        }
    }
 /**
  * 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);
 }
 /**
  * Turn the cart item data into human-readable key/value pairs for
  * display in the cart
  *
  * @since 3.0
  * @param array $item cart item
  * @param array $cart_item_data the cart item data
  * @return array human-readable cart item data
  */
 private function humanize_cart_item_data($item, $cart_item_data)
 {
     $new_cart_item_data = array();
     // always need the actual parent product, not the useless variation product
     $product = isset($item['variation_id']) && $item['variation_id'] ? SV_WC_Plugin_Compatibility::wc_get_product($item['product_id']) : $item['data'];
     $settings = new WC_Price_Calculator_Settings($product);
     foreach ($settings->get_calculator_measurements() as $measurement) {
         if (isset($cart_item_data[$measurement->get_name()])) {
             // if the measurement has a set of available options, get the option label for display, if we can determine it
             //  (this way we display "1/8" rather than "0.125", etc)
             if (count($measurement->get_options()) > 0) {
                 foreach ($measurement->get_options() as $value => $label) {
                     if ($cart_item_data[$measurement->get_name()] === $value) {
                         $cart_item_data[$measurement->get_name()] = $label;
                     }
                 }
             }
             $label = $measurement->get_unit_label() ? sprintf("%s (%s)", $measurement->get_label(), __($measurement->get_unit_label(), WC_Measurement_Price_Calculator::TEXT_DOMAIN)) : __($measurement->get_label(), WC_Measurement_Price_Calculator::TEXT_DOMAIN);
             $new_cart_item_data[$label] = $cart_item_data[$measurement->get_name()];
         }
     }
     // render the total measurement if this is a derived calculator (ie "Area (sq. ft.): 10" if the calculator is Area (LxW))
     if ($settings->is_calculator_type_derived() && isset($cart_item_data['_measurement_needed'])) {
         // get the product total measurement (ie area or volume)
         $product_measurement = WC_Price_Calculator_Product::get_product_measurement($product, $settings);
         $product_measurement->set_unit($cart_item_data['_measurement_needed_unit']);
         $product_measurement->set_value($cart_item_data['_measurement_needed']);
         $total_amount_text = apply_filters('wc_measurement_price_calculator_total_amount_text', $product_measurement->get_unit_label() ? sprintf(__('Total %s (%s)', WC_Measurement_Price_Calculator::TEXT_DOMAIN), $product_measurement->get_label(), __($product_measurement->get_unit_label(), WC_Measurement_Price_Calculator::TEXT_DOMAIN)) : sprintf(__('Total %s', WC_Measurement_Price_Calculator::TEXT_DOMAIN), $product_measurement->get_label()), $item);
         $new_cart_item_data[$total_amount_text] = $product_measurement->get_value();
     }
     return $new_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 = SV_WC_Plugin_Compatibility::wc_get_order($order_id);
     $order_items = $order->get_items();
     $product = SV_WC_Plugin_Compatibility::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;
 }