isCartUpsellEnabled() ) { return; } $nextPriceData = $this->getNextPriceData( $cartItem ); $upsellString = $this->formatUpsellString( $cartItem, $nextPriceData, $cartItemKey ); if ( !$upsellString ) { return; } // the link carries the target quantity for the cart script $allowed = wp_kses_allowed_html( 'post' ); $allowed['a']['data-tpt-cart-item'] = true; $allowed['a']['data-tpt-quantity'] = true; $current = (int) $this->getTotalProductCountInCart( $cartItem ); $target = $current + (int) $nextPriceData['next_quantity']; ?>
isProgressBarEnabled() && $target > 0 ) { ?>
isCartUpsellEnabled() ) { return $itemData; } $isStoreApi = false; if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { $requestUri = ( isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' ); if ( strpos( $requestUri, '/wc/store/' ) !== false ) { $isStoreApi = true; } } $isBlockPage = function_exists( 'has_block' ) && (has_block( 'woocommerce/cart' ) || has_block( 'woocommerce/checkout' )); // If it's NOT the Store API and NOT a block page, it's the classic cart. Bail out. if ( !$isStoreApi && !$isBlockPage ) { return $itemData; } $upsellString = $this->formatUpsellString( $cartItem ); if ( !$upsellString ) { return $itemData; } $itemData[] = array( 'key' => '', 'value' => wp_strip_all_tags( $upsellString ), ); return $itemData; } /** * @param array $cartItem * @param array|null $nextPriceData The next tier's figures, when already computed. * @param string $cartItemKey Set for the classic cart: the required quantity becomes a link that * moves the line to the next tier. * * @return string|false */ protected function formatUpsellString( $cartItem, $nextPriceData = null, $cartItemKey = '' ) { if ( null === $nextPriceData ) { $nextPriceData = $this->getNextPriceData( $cartItem ); } if ( empty( $nextPriceData ) ) { return false; } $template = $this->getTemplate(); $quantity = (string) $nextPriceData['next_quantity']; if ( $cartItemKey && $this->isQuantityLinkEnabled() ) { $target = (int) $cartItem['quantity'] + (int) $nextPriceData['next_quantity']; $quantity = '' . $quantity . ''; } return strtr( $template, array( '{tp_required_quantity}' => $quantity, '{tp_next_price}' => wc_price( $nextPriceData['next_price'] ), '{tp_next_discount}' => number_format( $nextPriceData['next_discount'], wc_get_price_decimals(), wc_get_price_decimal_separator(), wc_get_price_thousand_separator() ), '{tp_actual_discount}' => number_format( $nextPriceData['actual_discount'], wc_get_price_decimals(), wc_get_price_decimal_separator(), wc_get_price_thousand_separator() ), ) ); } protected function getNextPriceData( $cartItem ) { $pricingRule = $this->getPricingRule( $cartItem ); if ( !empty( $pricingRule->getRules() ) ) { $iterator = new ArrayIterator(array_reverse( $pricingRule->getRules(), true )); $currentQuantity = $this->getTotalProductCountInCart( $cartItem ); while ( $iterator->valid() ) { if ( $currentQuantity < $iterator->key() ) { $prevQuantity = $iterator->key(); $prevPrice = $iterator->current(); $iterator->next(); if ( $iterator->valid() && $currentQuantity >= $iterator->key() ) { $product = wc_get_product( $this->getProductId( $cartItem ) ); if ( $pricingRule->isFixed() ) { $nextPrice = $prevPrice; $currentPrice = $iterator->current(); } else { $nextPrice = PriceManager::getProductPriceWithPercentageDiscount( $product, $prevPrice ); $currentPrice = PriceManager::getProductPriceWithPercentageDiscount( $product, $iterator->current() ); } $currentPrice = PriceManager::getPriceToDisplay( $currentPrice, $product, 'cart' ); $nextPrice = PriceManager::getPriceToDisplay( $nextPrice, $product, 'cart' ); return array( 'next_price' => $nextPrice, 'next_discount' => PriceManager::calculateDiscount( $currentPrice, $nextPrice ), 'actual_discount' => ( $pricingRule->isPercentage() ? $prevPrice : PriceManager::calculateDiscount( $product->get_price( 'edit' ), $currentPrice ) ), 'next_quantity' => $prevQuantity - $currentQuantity, ); } elseif ( !$iterator->valid() ) { $product = wc_get_product( $this->getProductId( $cartItem ) ); if ( $pricingRule->isFixed() ) { $nextPrice = $prevPrice; $currentPrice = $product->get_price(); } else { $nextPrice = PriceManager::getProductPriceWithPercentageDiscount( $product, $prevPrice ); $currentPrice = $product->get_price(); } $nextPrice = PriceManager::getPriceToDisplay( $nextPrice, $product, 'cart' ); return array( 'next_price' => $nextPrice, 'next_discount' => PriceManager::calculateDiscount( $currentPrice, $nextPrice ), 'actual_discount' => ( $pricingRule->isPercentage() ? $prevPrice : PriceManager::calculateDiscount( $currentPrice, $product->get_price( 'edit' ) ) ), 'next_quantity' => $prevQuantity - $currentQuantity, ); } } else { $iterator->next(); } } } return array(); } public function getTotalProductCountInCart( $cartItem ) { return ( !empty( $cartItem['tiered_pricing_data']['total_item_quantity'] ) ? $cartItem['tiered_pricing_data']['total_item_quantity'] : $cartItem['quantity'] ); } /** * Get pricing rules from cart item * * @param array $cartItem * * @return PricingRule|false */ protected function getPricingRule( $cartItem ) { $productId = $this->getProductId( $cartItem ); if ( $productId ) { return PriceManager::getPricingRule( $productId ); } return false; } protected function getProductId( $cartItem ) { return ( !empty( $cartItem['variation_id'] ) ? $cartItem['variation_id'] : $cartItem['product_id'] ); } protected function getTemplate() { return $this->getContainer()->getSettings()->get( 'cart_upsell_template', __( 'Add {tp_required_quantity} more to get {tp_next_price} each', 'tier-pricing-table' ) ); } protected function getUpsellColor() { return $this->getContainer()->getSettings()->get( 'cart_upsell_color', '#059669' ); } protected function isCartUpsellEnabled() { return $this->getContainer()->getSettings()->get( 'cart_upsell_enabled', 'no' ) === 'yes'; } protected function isQuantityLinkEnabled() : bool { return $this->getContainer()->getSettings()->get( 'cart_upsell_link', 'yes' ) !== 'no'; } protected function isProgressBarEnabled() : bool { return $this->getContainer()->getSettings()->get( 'cart_upsell_progress', 'no' ) === 'yes'; } }