false, 'hidden_default' => false, 'product_id' => null, 'should_render' => true ); public $settings = array(); public $product_settings = array(); public function __construct() { } public function init($product = null) { if ( !class_exists('WooCommerce')) return; if ( !get_option('xstore_sales_booster_settings_'.self::$option_name) ) return; $this->args['tab_prefix'] = 'et_'.self::$option_name; $this->args['product'] = $product; if ( $this->args['product'] ) $this->args['product_id'] = $this->args['product']->get_ID(); $this->args['is_admin'] = is_admin(); $this->args['spb'] = !!get_option( 'etheme_single_product_builder', false ); add_action('wp', array($this, 'add_actions')); /** * Fix quantity discount not applied on ajax request. */ add_filter( 'woocommerce_cart_subtotal', array( $this, 'get_cart_subtotal_filter' ), 100, 1 ); add_filter('woocommerce_get_cart_contents', array($this, 'get_cart_contents'), 20, 1); add_filter('woocommerce_cart_get_total', array($this, 'get_cart_total_filter'), 20, 1); add_filter('woocommerce_cart_item_price', array($this, 'calculate_price_discounts_filter'), 20, 3); add_filter('woocommerce_cart_item_subtotal', array($this, 'calculate_price_discounts_subtotal_filter'), 20, 3); add_filter('woocommerce_get_cart_item_from_session', array($this, 'filter_cart_item_from_session'), 20, 3); if ( $this->args['is_admin'] ) { add_action( 'woocommerce_product_write_panel_tabs', array($this, 'panel_tab') ); add_action( 'woocommerce_product_data_panels', array($this, 'panel_data') ); add_action( 'woocommerce_process_product_meta', array($this, 'save_panel_data') ); } } /** * Add global actions/filters. */ public function add_actions() { if( $this->args['product'] ){ $this->args['is_local_product'] = true; } elseif ( is_singular('product') ) { $this->args['product'] = wc_get_product(); $this->args['product_id'] = $this->args['product']->get_ID(); } else { return; } if ( $this->args['product']->is_sold_individually() || !$this->args['product']->is_purchasable() || !$this->args['product']->is_in_stock() ) { $this->args['should_render'] = false; return; } if ( in_array($this->args['product']->get_type(), array('variable'))) { $this->args['hidden_default'] = true; // if ( !get_theme_mod( 'enable_swatch', 1 ) ) { // $this->args['should_render'] = false; // return; // } } // prevent showing quantity discounts on product which does not support ajax add to cart (it means the product is // external/grouped/etc) elseif ( !$this->args['product']->supports( 'ajax_add_to_cart' ) ) { $this->args['should_render'] = false; return; } if ( etheme_is_catalog() ) return; $this->set_settings(array(), $this->args['product_id']); if ( !$this->args['is_local_product']) { $action = 'woocommerce_after_add_to_cart_button'; $priority = 15; $apply_action = true; if ( $this->args['spb'] ) { $action = 'etheme_woocommerce_template_single_excerpt'; $priority = 5; } switch ( $this->settings['position'] ) { case 'before_cart_form': $action = 'woocommerce_before_add_to_cart_form'; $priority = 5; break; case 'after_cart_form': $action = 'woocommerce_after_add_to_cart_form'; $priority = 15; break; case 'before_woocommerce_share': $action = 'woocommerce_share'; $priority = - 999; break; case 'after_woocommerce_share': $action = 'woocommerce_share'; $priority = 999; break; case 'before_product_meta': $this->args['tag'] = 'span'; $action = 'woocommerce_product_meta_start'; $priority = 5; break; case 'after_product_meta': $this->args['tag'] = 'span'; $action = 'woocommerce_product_meta_end'; $priority = 15; break; case 'shortcode': $apply_action = false; break; default: if ( $this->args['spb'] ) { switch ( $this->settings['position'] ) { case 'before_atc': $action = 'etheme_woocommerce_template_single_add_to_cart'; $priority = 5; break; case 'after_atc': $action = 'etheme_woocommerce_template_single_add_to_cart'; $priority = 15; break; case 'before_excerpt': $action = 'etheme_woocommerce_template_single_excerpt'; $priority = 5; break; case 'after_excerpt': $action = 'etheme_woocommerce_template_single_excerpt'; $priority = 15; break; } } break; } if ( $apply_action ) { add_action( $action, array( $this, 'output' ), $priority ); if ( has_action('after_page_wrapper', 'etheme_sticky_add_to_cart') ) { add_action( 'after_page_wrapper', function () use ($action, $priority) { remove_action( $action, array( $this, 'output' ), $priority ); }, -1 ); add_action( 'after_page_wrapper', function () use ($action, $priority) { add_action( $action, array( $this, 'output' ), $priority ); }, 2 ); } } } } /** * Filter product price which are loaded from session (cache) * @param $session_data * @param $values * @param $key * @return mixed */ public function filter_cart_item_from_session($session_data, $values, $key) { $product = $session_data['data']; if ( isset($session_data['et_discount_price']) ) { unset($session_data['et_discount_price']); } if ( isset($session_data['et_discount_price_done']) ) { unset($session_data['et_discount_price_done']); } // $origin_settings = $this->set_settings(); // $local_settings = $origin_settings; // if ( get_post_meta( $session_data['product_id'], $this->args['tab_prefix'].'_settings', true ) != '' ) { $local_settings = $this->set_settings(array(), $session_data['product_id']); // } if (!count($local_settings)) return $session_data; $type = $local_settings['type']; // percentage/fixed price $steps_intervals = $local_settings[$local_settings['rules'].'_ready']; $simple_price = $product->get_price(); switch ($local_settings['rules']) { case 'intervals': foreach ($steps_intervals as $step_interval) { if ( $session_data['quantity'] >= $step_interval['min'] && (empty($step_interval['max']) || $session_data['quantity'] <= $step_interval['max']) ) { if ( $type == 'percentage') $price = $simple_price - ($simple_price / 100 * $step_interval['percentage']); else $price = $simple_price >= $step_interval['percentage'] ? $simple_price - $step_interval['percentage'] : $simple_price; // in case product price is less than discount - leave origin price for product $session_data['et_discount_price'] = $price; $session_data['et_origin_price'] = $simple_price; $product->set_price($price); } } break; case 'steps': foreach ($steps_intervals as $step_interval) { if ( $session_data['quantity'] == $step_interval['every'] ) { if ( $type == 'percentage') $price = $simple_price - ($simple_price / 100 * $step_interval['percentage']); else $price = $simple_price >= $step_interval['percentage'] ? $simple_price - $step_interval['percentage'] : $simple_price; $session_data['et_discount_price'] = $price; $session_data['et_origin_price'] = $simple_price; $product->set_price($price); } } break; } $session_data['data'] = $product; return $session_data; } /** * Filter global total with products have discounts * @param $total * @return float|int */ public function get_cart_total_filter($total) { $new_total = $total; $items = WC()->cart->get_cart_contents(); foreach ( $items as $item => $values ) { /** * @var \WC_Product $product_obj */ $quantity = $values['quantity']; if ( isset($values['et_discount_price'])) $new_total -= ($values['data']->get_price() - $values['et_discount_price']) * $quantity; // else // $new_total += $values['data']->get_price() * $quantity; } return $new_total; } /** * Filter global subtotal with products have discounts * @param $subtotal * @return mixed */ public function get_cart_subtotal_filter( $subtotal ) { $new_subtotal = 0; $items = WC()->cart->get_cart_contents(); $had_taxable = false; foreach ( $items as $item => $values ) { /** * @var \WC_Product $product_obj */ $quantity = $values['quantity']; $local_price = $values['data']->get_price(); if ( isset($values['et_discount_price'])) { if ( $local_price > $values['et_discount_price']) $local_price = $values['et_discount_price']; } if ( $values['data']->is_taxable() ) { $had_taxable = true; if ( WC()->cart->display_prices_including_tax() ) { $row_price = wc_get_price_including_tax( $values['data'], array( 'qty' => $values['quantity'], 'price' => $local_price ) ); $new_subtotal += $row_price; // if ( ! wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0 ) { // $new_price .= ' ' . WC()->countries->inc_tax_or_vat() . ''; // } // return $new_price; } else { $row_price = wc_get_price_excluding_tax( $values['data'], array( 'qty' => $values['quantity'], 'price' => $local_price ) ); $new_subtotal += $row_price; // if ( wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0 ) { // $new_price .= ' ' . WC()->countries->ex_tax_or_vat() . ''; // } // return $new_price; } } else { $new_subtotal += $local_price * $quantity; } } $subtotal = wc_price( $new_subtotal ); if ( $had_taxable ) { if ( WC()->cart->display_prices_including_tax() ) { if ( ! wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0 ) { $subtotal .= ' ' . WC()->countries->inc_tax_or_vat() . ''; } } else { if ( wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0 ) { $subtotal .= ' ' . WC()->countries->ex_tax_or_vat() . ''; } } } return $subtotal; } /** * Set product price with discount if all conditions are met * @param $contents * @return mixed */ public function get_cart_contents($contents) { // return $contents; $new_contents = $contents; // $origin_settings = $this->set_settings(); foreach ( $contents as $item => $values ) { if ( isset($values['et_discount_price_done'])) continue; // if ( isset($values['et_discount_price']) ) { // unset($values['et_discount_price']); // } // if ( isset($values['et_discount_price_done']) ) { // unset($values['et_discount_price_done']); // } // $local_settings = $origin_settings; // if ( get_post_meta( $values['product_id'], $this->args['tab_prefix'].'_settings', true ) == 'custom' ) { $local_settings = $this->set_settings(array(), $values['product_id']); // } if (!count($local_settings)) continue; $type = $local_settings['type']; // percentage/fixed price $steps_intervals = $local_settings[$local_settings['rules'].'_ready']; if (!count($steps_intervals)) continue; // Use it to prevent server error "The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later." // Method "get_price" causes server error in "WC_Product_Subscription" object // Can be removed after solution from "WooCommerce Memberships" plugin - By SkyVerge if ( class_exists('WC_Product_Subscription') && $values['data'] instanceof WC_Product_Subscription ) { $values['data'] = new WC_product($values['data']->get_ID()); } $simple_price = isset($values['et_origin_price']) ? $values['et_origin_price'] : $values['data']->get_price(); switch ($local_settings['rules']) { case 'intervals': foreach ($steps_intervals as $step_interval) { if ( $values['quantity'] >= $step_interval['min'] && (empty($step_interval['max']) || $values['quantity'] <= $step_interval['max']) ) { if ( $type == 'percentage') { $price = $simple_price - ($simple_price / 100 * $step_interval['percentage']); } else $price = $simple_price >= $step_interval['percentage'] ? $simple_price - $step_interval['percentage'] : $simple_price; $values['et_discount_price'] = $price; $values['et_origin_price'] = $simple_price; $values['et_discount_price_done'] = true; } } break; case 'steps': foreach ($steps_intervals as $step_interval) { if ( $values['quantity'] == $step_interval['every'] ) { if ( $type == 'percentage') $price = $simple_price - ($simple_price / 100 * $step_interval['percentage']); else $price = $simple_price >= $step_interval['percentage'] ? $simple_price - $step_interval['percentage'] : $simple_price; $values['et_discount_price'] = $price; $values['et_origin_price'] = $simple_price; $values['et_discount_price_done'] = true; } } break; } $new_contents[$item] = $values; } return $new_contents; } /** * Filter product price from discounted if such one exists * @param $price * @param $cart_item * @param $cart_item_key * @return mixed */ public function calculate_price_discounts_filter($price, $cart_item, $cart_item_key) { $local_price = $cart_item['data']->get_price(); if ( isset($cart_item['et_discount_price']) ) { $local_price = $cart_item['et_discount_price']; } if ( $cart_item['data']->is_taxable() ) { if ( WC()->cart->display_prices_including_tax() ) { $row_price = wc_get_price_including_tax( $cart_item['data'], array( 'price' => $local_price ) ); $new_price = wc_price( $row_price ); if ( ! wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0 ) { $new_price .= ' ' . WC()->countries->inc_tax_or_vat() . ''; } return $new_price; } else { $row_price = wc_get_price_excluding_tax( $cart_item['data'], array( 'price' => $local_price ) ); $new_price = wc_price( $row_price ); if ( wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0 ) { $new_price .= ' ' . WC()->countries->ex_tax_or_vat() . ''; } return $new_price; } } else { return wc_price($local_price); } } /** * Filter product price with discount if all conditions are passed and quantities are in the ones set in options * @param $product_subtotal * @param $cart_item * @param $cart_item_key * @return string */ public function calculate_price_discounts_subtotal_filter($product_subtotal, $cart_item, $cart_item_key) { $local_price = $cart_item['data']->get_price(); if ( isset($cart_item['et_discount_price']) ) $local_price = $cart_item['et_discount_price']; if ( $cart_item['data']->is_taxable() ) { if ( WC()->cart->display_prices_including_tax() ) { $row_price = wc_get_price_including_tax( $cart_item['data'], array( 'qty' => $cart_item['quantity'], 'price' => $local_price ) ); $product_subtotal = wc_price( $row_price ); if ( ! wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0 ) { $product_subtotal .= ' ' . WC()->countries->inc_tax_or_vat() . ''; } } else { $row_price = wc_get_price_excluding_tax( $cart_item['data'], array( 'qty' => $cart_item['quantity'], 'price' => $local_price ) ); $product_subtotal = wc_price( $row_price ); if ( wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0 ) { $product_subtotal .= ' ' . WC()->countries->ex_tax_or_vat() . ''; } } } else { $row_price = (float) $local_price * (float) $cart_item['quantity']; $product_subtotal = wc_price( $row_price ); } // } return $product_subtotal; } /** * Setting settings globally or for specific product if $product_id param is set * @param array $custom_settings * @param null $product_id * @return array|mixed */ public function set_settings($custom_settings = array(), $product_id = null) { if ( !$product_id && count($this->settings)) return $this->settings; if ( $product_id && isset($this->product_settings[$product_id]) && count($this->product_settings[$product_id])) return $this->product_settings[$product_id]; $this->settings = array( 'type' => 'percentage', // fixed 'rules' => 'intervals', // steps 'intervals' => [], 'intervals_ready' => [], 'steps' => [], 'steps_ready' => [], 'title' => esc_html__('Buy more save more!', 'xstore'), 'title_tag' => 'h4', 'discount_title_tag' => 'h5', 'button_icon' => 'et_icon-shopping-bag', 'custom_icon' => false, 'icon_position' => 'left', 'button_text' => esc_html__('Add', 'xstore'), 'add_quantity' => false, 'shown_on_quick_view' => false, 'position' => $this->args['spb'] ? 'after_excerpt' : 'after_summary', 'force_load_assets' => true ); $local_settings = $this->settings; $settings = (array)get_option('xstore_sales_booster_settings', array()); if (count($settings) && isset($settings[self::$option_name])) { $local_settings = wp_parse_args( $settings[ self::$option_name ], $this->settings ); } // single product page backend custom options $product_custom_options = array(); $local_product_id = $product_id ? $product_id : $this->args['product_id']; $product_discount_type = get_post_meta( $local_product_id, $this->args['tab_prefix'].'_settings', true ); if ( $product_discount_type == 'none' ) return $this->settings; if ( $product_discount_type == 'custom' ) { $rules = get_post_meta( $local_product_id, $this->args['tab_prefix'].'_rules', true ); $option_value = get_post_meta($local_product_id, $this->args['tab_prefix'] . '_' . $rules, true); if ($option_value) { $local_settings['rules'] = $rules; $local_settings['type'] = get_post_meta( $local_product_id, $this->args['tab_prefix'].'_type', true ); $steps_intervals_ready = array(); $local_settings[$rules.'_ready'] = array(); foreach ($option_value as $option) { $prefixed_rules = $this->args['tab_prefix'] . '_' . $rules; $steps_intervals_ready['percentage'] = $option[$prefixed_rules . '_percentage']; if ( !$steps_intervals_ready['percentage'] ) continue; if ( $rules == 'intervals' ) { $steps_intervals_ready['min'] = $option[$prefixed_rules . '_min']; $steps_intervals_ready['max'] = $option[$prefixed_rules . '_max']; } else { $steps_intervals_ready['every'] = $option[$prefixed_rules . '_every']; } if ( array_filter($steps_intervals_ready ) ) $local_settings[$rules.'_ready'][] = $steps_intervals_ready; } } } else { if ( !isset($local_settings[$local_settings['rules']]) || !$local_settings[$local_settings['rules']] ) return $this->settings; $steps_intervals = explode(',', $local_settings[$local_settings['rules']]); if ( count($steps_intervals) < 1) return $this->settings; $local_settings[$local_settings['rules'].'_ready'] = array(); foreach ($steps_intervals as $steps_interval) { $steps_intervals_ready = array(); $steps_intervals_ready['percentage'] = $local_settings[$steps_interval . '_percentage']; if ( !$steps_intervals_ready['percentage'] ) continue; if ( $local_settings['rules'] == 'intervals' ) { $steps_intervals_ready['min'] = $local_settings[$steps_interval . '_min']; $steps_intervals_ready['max'] = $local_settings[$steps_interval . '_max']; } else { $steps_intervals_ready['every'] = $local_settings[$steps_interval . '_every']; } if ( array_filter($steps_intervals_ready ) ) $local_settings[$local_settings['rules'].'_ready'][] = $steps_intervals_ready; } // empty all values if ( !array_filter($local_settings[$local_settings['rules'].'_ready'])) return $this->settings; } $this->settings = wp_parse_args( $product_custom_options, $local_settings ); $this->settings = wp_parse_args( $custom_settings, $this->settings ); if ( $product_id ) $this->product_settings[$product_id] = $this->settings; return $this->settings; } /** * Output quantity discounts block if all conditions are passed */ public function output() { if ( !apply_filters('etheme_sales_booster_quantity_discounts', true) ) return; if ( !$this->args['should_render']) return; $settings = apply_filters($this->args['tab_prefix'].'_settings', isset($this->product_settings[$this->args['product_id']]) ? $this->product_settings[$this->args['product_id']] : $this->settings, $this->args); if ( !isset($settings[$settings['rules'].'_ready']) || !count($settings[$settings['rules'].'_ready'])) return; if ( !isset($this->args['product_id']) || !$this->args['product_id']) return; ob_start(); $this->calculated_discounts($settings); $discounts = ob_get_clean(); if ( !$discounts) { $this->args['hidden_default'] = true; // return; } if ( $settings['force_load_assets'] ) etheme_enqueue_style( 'sale-booster-quantity-discounts', true ); ?>
'.$settings['title'].'' : ''; ?> ' . $discounts . '
'; ?> args['product']->get_stock_quantity(); foreach ($settings[$settings['rules'].'_ready'] as $discount) { $intervals = $settings['rules'] == 'intervals'; if ( ($intervals && !$this->args['product']->has_enough_stock( $discount['min'] )) || ( !$intervals && !$this->args['product']->has_enough_stock( $discount['every'] ) ) ) continue; $max_quantity = ''; if ( $intervals ) { if ($discount['max']) { $max_quantity = $discount['max']; if ($stock_quantity && $stock_quantity <= $max_quantity) { $max_quantity = $stock_quantity; } } } else { if ($discount['every']) { $max_quantity = $discount['every']; if ($stock_quantity && $stock_quantity <= $max_quantity) { $max_quantity = $stock_quantity; } } } $should_display_qty = $intervals && !($max_quantity && $max_quantity == $discount['min']); ?>
', $discount['min'], ($settings['type'] == 'percentage' ? $discount['percentage'] . '%' : wc_price($discount['percentage'])), '', '', ''); } else { echo sprintf(__('%1s Buy from %2s to %3s items and get %4s OFF %5s %6s on each product %7s', 'xstore'), '<' . $settings['discount_title_tag'] . ' class="quantity-discount-name">', $discount['min'], ($max_quantity ? $max_quantity : '∞'), ($settings['type'] == 'percentage' ? $discount['percentage'] . '%' : wc_price($discount['percentage'])), '', '', ''); } } else echo sprintf(__('%1s Buy %2s items get %3s OFF %4s %5s on each product %6s', 'xstore'), '<'.$settings['discount_title_tag'].' class="quantity-discount-name">', $discount['every'], ($settings['type'] == 'percentage' ? $discount['percentage'].'%' : wc_price($discount['percentage']) ), '', '', ''); ?>
$discount['min'], 'max_value' => $max_quantity, 'min_value' => $discount['min'], 'quantity_type' => 'input', ) ); remove_filter('woocommerce_quantity_input_classes', array($this, 'quantity_input_classes'), 10, 2); remove_action( 'woocommerce_before_quantity_input_field', 'et_quantity_minus_icon' ); remove_action( 'woocommerce_after_quantity_input_field', 'et_quantity_plus_icon' ); endif; ?>
args['product_id'] = $atts['product_id']; if ( count($this->settings) < 1) $this->set_settings(array(), $this->args['product_id']); } else { wc_print_notice( wp_kses_post( sprintf(esc_html__('Product with id "%s" does not exists or was permanently removed.', 'xstore'), $atts['product_id']) ), 'error'); return; } } else { if (count($this->settings) < 1) $this->set_settings(); } $this->settings = wp_parse_args($atts, $this->settings); ob_start(); $this->output(); return ob_get_clean(); } /** * Add settings panel list item on Single product editor */ public function panel_tab() { ?>
  • '.apply_filters('etheme_theme_label', 'XStore').''; ?>
  • $this->args['tab_prefix'].'_settings', 'label' => __( 'Quantity discounts', 'xstore' ), 'options' => [ 'inherit' => __('Inherit', 'xstore'), 'none' => __('None', 'xstore'), 'custom' => __('Custom', 'xstore'), ], ] ); woocommerce_wp_radio([ 'id' => $this->args['tab_prefix'].'_type', 'label' => __( 'Discount Type', 'xstore' ), 'options' => [ 'percentage' => esc_html__('By percentage (example: 10% OFF)', 'xstore'), 'fixed' => str_replace('{{currency_symbol}}', get_woocommerce_currency_symbol( get_woocommerce_currency() ), esc_html__( 'By fixed price (example: 10{{currency_symbol}} OFF)', 'xstore' )), ], ] ); woocommerce_wp_radio([ 'id' => $this->args['tab_prefix'].'_rules', 'label' => __( 'Discount Rules', 'xstore' ), 'options' => [ 'intervals' => __('Intervals', 'xstore'), 'steps' => __('Steps', 'xstore'), ], ]); $this->sortable_options([ 'id' => $this->args['tab_prefix'].'_intervals', 'label' => __( 'Intervals', 'xstore' ), 'option_key' => 'intervals' ]); $this->sortable_options([ 'id' => $this->args['tab_prefix'].'_steps', 'label' => __( 'Steps', 'xstore' ), 'option_key' => 'steps' ]); ?>

    100) // $(this).val(100); // return false; // } // ) } });", 'after' ); } /** * Save settings from quantity discount panel on Single product editor * @param $post_id */ public function save_panel_data( $post_id ) { $quantity_discount_settings = isset( $_POST[$this->args['tab_prefix'].'_settings'] ) ? $_POST[$this->args['tab_prefix'].'_settings'] : ''; if ( $quantity_discount_settings ) update_post_meta( $post_id, $this->args['tab_prefix'].'_settings', $quantity_discount_settings ); else delete_post_meta( $post_id, $this->args['tab_prefix'].'_settings' ); $quantity_discount_type = isset( $_POST[$this->args['tab_prefix'].'_type'] ) ? $_POST[$this->args['tab_prefix'].'_type'] : ''; if ( $quantity_discount_type ) update_post_meta( $post_id, $this->args['tab_prefix'].'_type', $quantity_discount_type ); else delete_post_meta( $post_id, $this->args['tab_prefix'].'_type' ); $quantity_discount_rules = isset( $_POST[$this->args['tab_prefix'].'_rules'] ) ? $_POST[$this->args['tab_prefix'].'_rules'] : ''; if ( $quantity_discount_rules ) update_post_meta( $post_id, $this->args['tab_prefix'].'_rules', $quantity_discount_rules ); else delete_post_meta( $post_id, $this->args['tab_prefix'].'_rules' ); $this->sortable_options_save($post_id, 'intervals'); $this->sortable_options_save($post_id, 'steps'); } /** * New type of field - sortable (adding/removing rows) * @param $field * @param WC_Data|null $data */ public function sortable_options($field, WC_Data $data = null) { global $post; $field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : ''; $options = get_post_meta($post->ID, $field['id'], true); echo '
    ' . wp_kses_post( $field['label'] ) . ''; if ( ! empty( $field['description'] ) && false !== $field['desc_tip'] ) { echo wc_help_tip( $field['description'] ); } ?> ' : '') . ''; if ($options) : foreach ($options as $option) { ?> '.$empty_table_columns.''; endif; ?> '.$empty_table_columns.''; ?>
    '.esc_html__('Remove', 'xstore').'

    '; } /** * Saving action for new sortable field option type * @param $post_id * @param string $type */ public function sortable_options_save($post_id, $type='intervals') { $previous_value = get_post_meta($post_id, $this->args['tab_prefix'].'_'.$type, true); $prefix = $this->args['tab_prefix'] . '_' . $type; if ( $type == 'intervals' ) { $intervals_new = array(); $interval_min = isset($_POST[$prefix . '_min']) ? $_POST[$prefix . '_min'] : 0; $interval_max = isset($_POST[$prefix . '_max']) ? $_POST[$prefix . '_max'] : 0; $interval_percentage = isset($_POST[$prefix . '_percentage']) ? $_POST[$prefix . '_percentage'] : 0; for ($i = 0; $i < count(max($interval_min, $interval_max, $interval_percentage)); $i++) { $_min = stripslashes($interval_min[$i]); // and however you want to sanitize $_max = stripslashes($interval_max[$i]); // and however you want to sanitize $_percentage = stripslashes($interval_percentage[$i]); // and however you want to sanitize if ( $_min || $_max || $_percentage) { $intervals_new[$i][$prefix . '_min'] = $_min; $intervals_new[$i][$prefix . '_max'] = $_max; $intervals_new[$i][$prefix . '_percentage'] = $_percentage; } } if (!empty($intervals_new) && $intervals_new != $previous_value) update_post_meta($post_id, $prefix, $intervals_new); elseif (empty($intervals_new) && $previous_value) delete_post_meta($post_id, $prefix); } else { $steps_new = array(); $steps_every = isset($_POST[$prefix . '_every']) ? $_POST[$prefix . '_every'] : 0; $interval_percentage = isset($_POST[$prefix . '_percentage']) ? $_POST[$prefix . '_percentage'] : 0; for ($i = 0; $i < count(max($steps_every, $interval_percentage)); $i++) { $_every = stripslashes($steps_every[$i]); // and however you want to sanitize $_percentage = stripslashes($interval_percentage[$i]); // and however you want to sanitize if ( $_every || $_percentage ) { $steps_new[$i][$prefix . '_every'] = $_every; $steps_new[$i][$prefix . '_percentage'] = $_percentage; } } if (!empty($steps_new) && $steps_new != $previous_value) update_post_meta($post_id, $prefix, $steps_new); elseif (empty($steps_new) && $previous_value) delete_post_meta($post_id, $prefix); } } /** * Returns the instance. * * @return object * @since 9.0 */ public static function get_instance( $shortcodes = array() ) { if ( null == self::$instance ) { self::$instance = new self( $shortcodes ); } return self::$instance; } }