getDefaultSettings( $parentProductID ) );
// If the product is variable, but no specific variation is passed - check for default
if ( ! $variationID && TierPricingTablePlugin::isVariableProductSupported( $parentProduct ) ) {
$variationID = $this->getDefaultVariation( $parentProduct );
}
$ajaxVariationsThreshold = apply_filters( 'tiered_pricing_table/ajax_variations_threshold', 10 );
// Use variation if exists, otherwise the parent product is used
$productId = $variationID ? $variationID : $parentProduct->get_id();
$product = wc_get_product( $productId );
$supportedTypes = array_merge( TierPricingTablePlugin::getSupportedSimpleProductTypes(),
TierPricingTablePlugin::getSupportedVariableProductTypes() );
// Exit if product is not valid
if ( ! $product || ! in_array( $parentProduct->get_type(), $supportedTypes ) ) {
return;
}
$settings = apply_filters( 'tiered_pricing_table/display_settings', $settings, $productId );
if ( 'tooltip' === $settings['display_type'] ) {
wp_enqueue_script( 'jquery-ui-tooltip' );
}
$hidden = ( 'tooltip' === $settings['display_type'] || ! $settings['display'] );
do_action( 'tiered_pricing_table/before_rendering_tiered_pricing', $parentProduct, $variationID, $settings );
$loadVariationByAjax = true;
?>
get_children() ) > $ajaxVariationsThreshold;
$variableProductSamePrices = AdvanceOptionsForVariableProduct::isVariableProductSamePrices( $parentProduct->get_id() );
?>
data-load-variation-by-ajax=""
data-variable-product-same-prices=""
>
renderPricingTableHTML( $parentProduct, $product, $settings ); ?>
get_available_variations( 'objects' ) as $childProduct ) : ?>
renderPricingTableHTML( $parentProduct, $childProduct, $settings ); ?>
getDefaultSettings( $parentProduct->get_id() ) );
// Don't get rules from variable product when variation is empty
if ( in_array( $parentProduct->get_type(),
TierPricingTablePlugin::getSupportedVariableProductTypes() ) && ! ( $product instanceof WC_Product_Variation ) ) {
// Empty rule
$priceRule = new PricingRule( $product->get_id() );
} else {
$priceRule = PriceManager::getPricingRule( $product->get_id() );
}
// If rules are not empty
if ( ! empty( $priceRule->getRules() ) ) {
$displayType = $settings['display_type'];
$availableTemplates = TierPricingTablePlugin::getAvailablePricingLayouts();
$templateType = array_key_exists( $settings['display_type'], $availableTemplates ) ? $displayType : 'table';
if ( 'tooltip' === $displayType ) {
$templateType = 'table';
}
if ( 'table' === $displayType ) {
$style = $settings['table_style'];
if ( $style !== 'default' ) {
$templateType = 'table-' . $style;
} else {
$templateType = 'table';
}
}
if ( 'blocks' === $displayType ) {
$style = $settings['blocks_style'];
if ( $style !== 'default' ) {
$templateType = 'blocks-' . $style;
} else {
$templateType = 'blocks';
}
}
if ( 'options' === $displayType ) {
$style = $settings['options_style'];
if ( $style !== 'default' ) {
$templateType = 'options-' . $style;
} else {
$templateType = 'options';
}
}
$template = "tiered-pricing-$templateType.php";
do_action( 'tiered_pricing_table/before_rendering_tiered_pricing/inner', $priceRule, $product, $settings );
$this->checkForDuplicateQuantities( $priceRule );
$this->getContainer()->getFileManager()->includeTemplate( 'frontend/' . $template, array(
'pricing_rule' => $priceRule,
'price_rules' => $priceRule->getRules(),
'real_price' => $product->get_price(),
'product_name' => $product->get_name(),
'product_id' => $product->get_id(),
'product' => $product,
'minimum' => $priceRule->getMinimum( true ),
'settings' => $settings,
'pricing_type' => $priceRule->getType(),
'id' => $this->getUniqueTieredPricingId(),
) );
} else {
// Provide fallback data for products without pricing rules,
// which allows the frontend JS (e.g. dynamic totals, you save, etc.)
// to function for all products via the 'tiered_price_update' event.
$price_incl_taxes = wc_get_price_including_tax( $product, array(
'price' => $product->get_price(),
) );
$price_excl_taxes = wc_get_price_excluding_tax( $product, array(
'price' => $product->get_price(),
) );
?>
productHasPricingRules( $product );
}
}
$showTotalPrice = $hasRules ? $this->getContainer()->getSettings()->get( 'show_total_price',
'no' ) === 'yes' : $this->getContainer()->getSettings()->get( 'show_total_price_non_tiered',
'no' ) === 'yes';
$settings = array(
'display_context' => 'product-page',
'display' => $this->getContainer()->getSettings()->get( 'display', 'yes' ) === 'yes',
'display_type' => $this->getContainer()->getSettings()->get( 'display_type', 'table' ),
'title' => $this->getContainer()->getSettings()->get( 'table_title', '' ),
'table_class' => $this->getContainer()->getSettings()->get( 'table_css_class', '' ),
'quantity_column_title' => $this->getContainer()->getSettings()->get( 'head_quantity_text',
__( 'Quantity', 'tier-pricing-table' ) ),
'price_column_title' => $this->getContainer()->getSettings()->get( 'head_price_text',
__( 'Price', 'tier-pricing-table' ) ),
'discount_column_title' => $this->getContainer()->getSettings()->get( 'head_discount_text',
__( 'Discount (%)', 'tier-pricing-table' ) ),
'quantity_type' => $this->getContainer()->getSettings()->get( 'quantity_type', 'range' ),
'show_discount_column' => $this->getContainer()->getSettings()->get( 'show_discount_column',
'yes' ) === 'yes',
'clickable_rows' => $this->getContainer()->getSettings()->get( 'clickable_table_rows',
'yes' ) === 'yes',
'active_tier_color' => $this->getContainer()->getSettings()->get( 'selected_quantity_color',
'#3858e9' ),
'tooltip_border' => $this->getContainer()->getSettings()->get( 'tooltip_border',
'yes' ) === 'yes',
'table_style' => GeneralSection::getPricingTableStyle(),
'compact_layout' => $this->getContainer()->getSettings()->get( 'compact_layout', 'no' ),
'blocks_style' => GeneralSection::getPricingBlocksStyle(),
'options_style' => GeneralSection::getPricingOptionsStyle(),
'options_show_total' => GeneralSection::isShowOptionTotal(),
'options_show_original_product_price' => GeneralSection::isShowOriginalProductPrice(),
'options_show_default_option' => GeneralSection::isDefaultOptionEnabled(),
'options_default_option_text' => GeneralSection::getDefaultOptionText(),
'options_option_text' => GeneralSection::getOptionText(),
'plain_text_show_default_option' => GeneralSection::isPlainTextFirstTierEnabled(),
'plain_text_option_text' => GeneralSection::getPlainTextTemplate(),
'plain_text_default_option_text' => GeneralSection::getPlainTextFirstTierTemplate(),
'update_price_on_product_page' => $this->getContainer()->getSettings()->get( 'update_price_on_product_page',
'yes' ) === 'yes',
'show_tiered_price_as_discount' => $this->getContainer()->getSettings()->get( 'show_tiered_price_as_discount',
'yes' ) === 'yes',
'show_total_price' => $showTotalPrice,
);
$default_quantity_measurement = array(
'singular' => '',
'plural' => '',
);
$quantity_measurement = $default_quantity_measurement;
if ( in_array( $settings['display_type'], array( 'table', 'horizontal-table', 'tooltip' ) ) ) {
$quantity_measurement = $this->getContainer()->getSettings()->get( 'table_quantity_measurement',
$default_quantity_measurement );
}
if ( 'blocks' === $settings['display_type'] ) {
$quantity_measurement = $this->getContainer()->getSettings()->get( 'blocks_quantity_measurement', array(
'singular' => _n( 'piece', 'pieces', 1, 'tier-pricing-table' ),
'plural' => _n( 'piece', 'pieces', 2, 'tier-pricing-table' ),
) );
}
$settings['quantity_measurement_singular'] = $quantity_measurement['singular'];
$settings['quantity_measurement_plural'] = $quantity_measurement['plural'];
if ( $productId ) {
$template = TieredPricingTab::getProductTemplate( $productId );
if ( 'default' !== $template ) {
$settings['display_type'] = $template;
}
$baseUnitName = TieredPricingTab::getProductBaseUnitName( $productId );
if ( $baseUnitName['singular'] && $baseUnitName['plural'] ) {
$settings['quantity_measurement_singular'] = $baseUnitName['singular'];
$settings['quantity_measurement_plural'] = $baseUnitName['plural'];
}
}
return $settings;
}
protected function getUniqueTieredPricingId() {
return preg_replace( '/[0-9]+/', '', strtolower( wp_generate_password( 20, false ) ) );
}
protected function getDefaultVariation( WC_Product_Variable $product ): ?int {
$defaultVariation = AdvanceOptionsForVariableProduct::getDefaultVariation( $product->get_id() );
if ( $defaultVariation ) {
return $defaultVariation->get_id();
}
$defaultAttributes = $product->get_default_attributes();
if ( ! empty( $defaultAttributes ) ) {
$defaultAttributesKeys = array_map( function ( $attribute ) {
return 'attribute_' . $attribute;
}, array_keys( $defaultAttributes ) );
$defaultAttributes = array_combine( $defaultAttributesKeys, $defaultAttributes );
return ( new WC_Product_Data_Store_CPT() )->find_matching_product_variation( $product, $defaultAttributes );
}
return null;
}
public function productHasPricingRules( WC_Product $product ): bool {
if ( TierPricingTablePlugin::isSimpleProductSupported( $product ) ) {
$pricingRule = PriceManager::getPricingRule( $product->get_id() );
return ! empty( $pricingRule->getRules() );
}
if ( TierPricingTablePlugin::isVariableProductSupported( $product ) && $product instanceof WC_Product_Variable ) {
// Do not check if product has tiered pricing for variable product by default.
// If a variable product has many variations, it can take many resources to check every variation for rules existing.
// The downside is that the plugin will send an AJAX request for each variant selection on the product page even if a product does not have any tiered pricing
if ( ! apply_filters( 'tiered_pricing_table/check_if_variable_product_has_rules', false, $product ) ) {
return true;
}
$hasTieredPricing = $this->getContainer()->getCache()->getProductData( $product, 'product_has_rules' );
if ( 'no' === $hasTieredPricing ) {
return false;
}
if ( 'yes' === $hasTieredPricing ) {
return true;
}
foreach ( $product->get_available_variations() as $productVariation ) {
$pricingRule = PriceManager::getPricingRule( $productVariation['variation_id'] );
if ( ! empty( $pricingRule->getRules() ) ) {
$this->getContainer()->getCache()->setProductData( $product, 'product_has_rules', 'yes' );
return true;
}
}
$this->getContainer()->getCache()->setProductData( $product, 'product_has_rules', 'no' );
}
return false;
}
public function checkForDuplicateQuantities( PricingRule $pricingRule ) {
// Show notice only for admin users
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$minimum = $pricingRule->getMinimum( true );
$pricingRules = $pricingRule->getRules();
$firstRuleQuantity = ! empty( $pricingRules ) ? array_keys( $pricingRules )[0] : false;
if ( $firstRuleQuantity && $firstRuleQuantity <= $minimum ) {
?>