-
Notifications
You must be signed in to change notification settings - Fork 8
Enhance pricing logic for upsell order bump functionality #481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
WalkthroughUpdates pricing logic to use current price for discounts in frontend and PHP, refactors price handling for simple/variable products, normalizes IDs and categories, and adds hooks and cleanup logic to remove orphaned bump products when cart items are removed or quantities become zero. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant WC as WooCommerce Cart
participant OB as OrderBump
participant Cart as Cart Contents
WC->>OB: woocommerce_cart_item_removed(cart_item_key, cart)
OB->>OB: derive removed product_id/variation_id
OB->>Cart: inspect remaining cart items
OB->>OB: get_remaining_target_products(bump)
alt No remaining targets
OB->>Cart: remove bump product (handle_orphaned_bump_product)
else Targets remain
OB-->>WC: no action
end
sequenceDiagram
autonumber
participant WC as WooCommerce Cart
participant OB as OrderBump
participant View as Bump Frontend View
WC->>OB: woocommerce_after_cart_item_quantity_update(key, qty, oldQty, cart)
alt qty == 0
OB->>OB: validate_bump_products_after_removal()
else qty > 0
OB-->>WC: no cleanup
end
View->>OB: bump_product_frontend_view()
OB->>OB: collect product/variation IDs and category IDs (ints)
OB->>OB: compute current_price (sale or current), apply discount/fixed offer
OB-->>View: render data with normalized IDs and prices
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
- Updated discount calculation to use the current price (sale price if available) instead of the regular price. - Improved product data handling in the EnqueueScript class to reflect accurate pricing for both simple and variable products. - Added hooks to manage target product removal and cart quantity updates, ensuring proper cleanup of related bump products. - Implemented validation for bump products when target products are removed from the cart.
- Updated pricing logic to utilize the get_price() method for both simple and variable products, ensuring accurate current price representation. - Adjusted the formatting of price data to maintain consistency across product types. - Enhanced clarity in the code by removing redundant price calculations.
- Added validation for numeric price values to ensure accurate formatting for both simple and variable products. - Updated the retrieval of regular and sale prices to improve consistency and reliability in price representation. - Implemented checks for valid variation products to prevent errors during price processing.
- Replaced sale price retrieval with current price for accurate pricing representation. - Adjusted conditions to check for current price instead of regular price for simple products. - Removed redundant sale price calculations to streamline price data handling.
caca2f0 to
e9fe589
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (4)
modules/upsell-order-bump/assets/src/components/appearance/template/overview-area/OverViewArea.js (1)
59-63: Strike-through should reflect the same “base” price used for discountIf you discount from current price (sale), showing the regular price as the crossed-out anchor is misleading. Consider showing the current price as the struck-through “was” value, and format amounts instead of string-appending “.00”.
- <span style={{textDecoration:'line-through'}}> - ${createBumpData.offer_product_regular_price?createBumpData.offer_product_regular_price:999999999}.00 - </span> - <span style={{textDecoration:'underline'}}> - ${offerAmout}.00 - </span> + <span style={{textDecoration:'line-through'}}> + ${ (createBumpData.offer_product_current_price ?? createBumpData.current_price ?? createBumpData.offer_product_regular_price ?? 0) } + </span> + <span style={{textDecoration:'underline'}}> + ${ offerAmout } + </span>modules/upsell-order-bump/includes/EnqueueScript.php (1)
186-196: Avoid pre-escaping before wc_price and don’t hide zero-priced items
- Pass numeric to wc_price directly; wc_price handles escaping.
- Checking truthiness can drop “0” prices. Prefer is_numeric.
- $price = esc_html( $current_price ); - $price = wp_strip_all_tags( html_entity_decode( wc_price( $price ) ) ); + $price = wp_strip_all_tags( html_entity_decode( wc_price( (float) $current_price ) ) ); ... - if ( $_product->is_type( 'simple' ) && $current_price ) { + if ( $_product->is_type( 'simple' ) && is_numeric( $current_price ) ) {Also applies to: 209-217
modules/upsell-order-bump/includes/OrderBump.php (2)
51-74: Consider deduping product IDs as wellYou already array_unique category IDs; do the same for product/variation IDs to keep intersections lean.
} // Remove duplicate category IDs $all_cart_category_ids = array_unique( $all_cart_category_ids ); + // Remove duplicate product IDs (including variations) + $all_cart_product_ids = array_values( array_unique( $all_cart_product_ids, SORT_NUMERIC ) );Also applies to: 76-78
279-283: Normalize target product IDs before intersectionEnsures consistent comparisons with int cart/variation IDs.
- $target_products = ! empty( $bump_info->target_products ) ? wc_clean( $bump_info->target_products ) : array(); + $target_products = ! empty( $bump_info->target_products ) ? array_map( 'intval', (array) wc_clean( $bump_info->target_products ) ) : array();
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
modules/upsell-order-bump/assets/src/components/appearance/template/overview-area/OverViewArea.js(1 hunks)modules/upsell-order-bump/includes/EnqueueScript.php(5 hunks)modules/upsell-order-bump/includes/OrderBump.php(5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
modules/upsell-order-bump/includes/OrderBump.php (1)
modules/upsell-order-bump/includes/Ajax.php (1)
bump_list(81-103)
🔇 Additional comments (3)
modules/upsell-order-bump/includes/EnqueueScript.php (2)
262-276: Simple products: current/regular price retrieval looks correctUsing get_price()/get_regular_price with numeric guards aligns with the PR goal.
284-309: Variable products: robust current vs regular price handlingFetching the variation product and exposing both current_price and regular_price with numeric normalization looks good.
modules/upsell-order-bump/includes/OrderBump.php (1)
31-33: Hooks registered correctly with proper argument countsThe actions and accepted args match WooCommerce signatures.
| // Use the current price (sale price if available, otherwise regular price) for discount calculation | ||
| const currentPrice = createBumpData.offer_product_regular_price; | ||
| offerAmout = currentPrice - currentPrice*createBumpData.offer_amount/100; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use current price for discount calc and coerce/round numerics
Comment says “current price” but code still uses regular price. Also ensure numeric coercion and 2-decimal rounding to avoid float artifacts.
- // Use the current price (sale price if available, otherwise regular price) for discount calculation
- const currentPrice = createBumpData.offer_product_regular_price;
- offerAmout = currentPrice - currentPrice*createBumpData.offer_amount/100;
+ // Use the current price (sale if available) for discount calculation
+ const currentPrice = Number(
+ createBumpData.offer_product_current_price
+ ?? createBumpData.current_price
+ ?? createBumpData.offer_product_regular_price
+ ?? 0
+ );
+ const discountPct = Number(createBumpData.offer_amount ?? 0);
+ offerAmout = Math.round((currentPrice - (currentPrice * discountPct / 100)) * 100) / 100;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Use the current price (sale price if available, otherwise regular price) for discount calculation | |
| const currentPrice = createBumpData.offer_product_regular_price; | |
| offerAmout = currentPrice - currentPrice*createBumpData.offer_amount/100; | |
| // Use the current price (sale if available) for discount calculation | |
| const currentPrice = Number( | |
| createBumpData.offer_product_current_price | |
| ?? createBumpData.current_price | |
| ?? createBumpData.offer_product_regular_price | |
| ?? 0 | |
| ); | |
| const discountPct = Number(createBumpData.offer_amount ?? 0); | |
| offerAmout = Math.round((currentPrice - (currentPrice * discountPct / 100)) * 100) / 100; |
🤖 Prompt for AI Agents
In
modules/upsell-order-bump/assets/src/components/appearance/template/overview-area/OverViewArea.js
around lines 18-20, the code assigns currentPrice to the regular price but
should use the sale price when present, and it doesn’t coerce/round numeric
values; update currentPrice to use createBumpData.offer_product_sale_price if
truthy else createBumpData.offer_product_regular_price, coerce prices and
offer_amount to Number, compute the discounted amount as currentPrice -
(currentPrice * offer_amount / 100), and round the final offerAmount to two
decimals (e.g., Math.round(value * 100) / 100 or Number(value.toFixed(2))) so
there are no floating-point artifacts.
| $_product = wc_get_product( $offer_product_id ); | ||
| $regular_price = $_product->get_regular_price(); | ||
| // Use sale price if available, otherwise use regular price for discount calculation | ||
| $current_price = $_product->get_sale_price() ? $_product->get_sale_price() : $regular_price; | ||
| if ( 'discount' === $offer_type ) { | ||
| $offer_price = ( $current_price - ( $current_price * $offer_amount / 100 ) ); | ||
| } else { | ||
| $offer_price = $offer_amount; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use get_price() for “current” price (respects schedules/filters)
get_sale_price() ignores sale schedules and filter-based pricing. get_price() returns the effective “current” price.
- $_product = wc_get_product( $offer_product_id );
- $regular_price = $_product->get_regular_price();
- // Use sale price if available, otherwise use regular price for discount calculation
- $current_price = $_product->get_sale_price() ? $_product->get_sale_price() : $regular_price;
- if ( 'discount' === $offer_type ) {
- $offer_price = ( $current_price - ( $current_price * $offer_amount / 100 ) );
- } else {
- $offer_price = $offer_amount;
- }
+ $_product = wc_get_product( $offer_product_id );
+ $current_price = (float) $_product->get_price();
+ $regular_price = (float) $_product->get_regular_price();
+ if ( 'discount' === $offer_type ) {
+ $offer_price = round( $current_price - ( $current_price * ( (float) $offer_amount / 100 ) ), 2 );
+ } else {
+ $offer_price = (float) $offer_amount;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| $_product = wc_get_product( $offer_product_id ); | |
| $regular_price = $_product->get_regular_price(); | |
| // Use sale price if available, otherwise use regular price for discount calculation | |
| $current_price = $_product->get_sale_price() ? $_product->get_sale_price() : $regular_price; | |
| if ( 'discount' === $offer_type ) { | |
| $offer_price = ( $current_price - ( $current_price * $offer_amount / 100 ) ); | |
| } else { | |
| $offer_price = $offer_amount; | |
| } | |
| $_product = wc_get_product( $offer_product_id ); | |
| $current_price = (float) $_product->get_price(); | |
| $regular_price = (float) $_product->get_regular_price(); | |
| if ( 'discount' === $offer_type ) { | |
| $offer_price = round( $current_price - ( $current_price * ( (float) $offer_amount / 100 ) ), 2 ); | |
| } else { | |
| $offer_price = (float) $offer_amount; | |
| } |
🤖 Prompt for AI Agents
In modules/upsell-order-bump/includes/OrderBump.php around lines 90 to 98, the
code uses get_regular_price() and get_sale_price() to determine the current
price, which ignores sale schedules and filters; replace that logic to call
$_product->get_price() to obtain the effective current price, cast it to a float
for math safety, then compute $offer_price as before (if 'discount' calculate
current_price - (current_price * offer_amount / 100), else use the fixed
offer_amount). Ensure you handle an empty/non-numeric price by defaulting to 0.0
before the calculation.
| public function handle_target_product_removal( $cart_item_key, $cart ) { | ||
| $removed_item = $cart->removed_cart_contents[ $cart_item_key ]; | ||
| if ( ! $removed_item ) { | ||
| return; | ||
| } | ||
|
|
||
| $removed_product_id = $removed_item['product_id']; | ||
| $removed_variation_id = isset( $removed_item['variation_id'] ) ? $removed_item['variation_id'] : 0; | ||
|
|
||
| // For variable products, check both parent and variation IDs | ||
| $removed_item_ids = array( $removed_product_id ); | ||
| if ( $removed_variation_id > 0 ) { | ||
| $removed_item_ids[] = $removed_variation_id; | ||
| } | ||
|
|
||
| $this->validate_bump_products_after_removal( $removed_item_ids ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Guard against undefined index on removed_cart_contents
Directly indexing can emit notices. Check with isset/empty first.
- public function handle_target_product_removal( $cart_item_key, $cart ) {
- $removed_item = $cart->removed_cart_contents[ $cart_item_key ];
- if ( ! $removed_item ) {
- return;
- }
+ public function handle_target_product_removal( $cart_item_key, $cart ) {
+ if ( empty( $cart->removed_cart_contents[ $cart_item_key ] ) ) {
+ return;
+ }
+ $removed_item = $cart->removed_cart_contents[ $cart_item_key ];📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public function handle_target_product_removal( $cart_item_key, $cart ) { | |
| $removed_item = $cart->removed_cart_contents[ $cart_item_key ]; | |
| if ( ! $removed_item ) { | |
| return; | |
| } | |
| $removed_product_id = $removed_item['product_id']; | |
| $removed_variation_id = isset( $removed_item['variation_id'] ) ? $removed_item['variation_id'] : 0; | |
| // For variable products, check both parent and variation IDs | |
| $removed_item_ids = array( $removed_product_id ); | |
| if ( $removed_variation_id > 0 ) { | |
| $removed_item_ids[] = $removed_variation_id; | |
| } | |
| $this->validate_bump_products_after_removal( $removed_item_ids ); | |
| } | |
| public function handle_target_product_removal( $cart_item_key, $cart ) { | |
| - $removed_item = $cart->removed_cart_contents[ $cart_item_key ]; | |
| - if ( ! $removed_item ) { | |
| - return; | |
| if ( empty( $cart->removed_cart_contents[ $cart_item_key ] ) ) { | |
| return; | |
| } | |
| $removed_item = $cart->removed_cart_contents[ $cart_item_key ]; | |
| $removed_product_id = $removed_item['product_id']; | |
| $removed_variation_id = isset( $removed_item['variation_id'] ) ? $removed_item['variation_id'] : 0; | |
| // For variable products, check both parent and variation IDs | |
| $removed_item_ids = array( $removed_product_id ); | |
| if ( $removed_variation_id > 0 ) { | |
| $removed_item_ids[] = $removed_variation_id; | |
| } | |
| $this->validate_bump_products_after_removal( $removed_item_ids ); | |
| } |
🤖 Prompt for AI Agents
In modules/upsell-order-bump/includes/OrderBump.php around lines 162-178, the
code directly accesses $cart->removed_cart_contents[$cart_item_key], which can
raise undefined index notices; first verify that removed_cart_contents exists
and that the specific key is set (e.g., use isset($cart->removed_cart_contents)
&& isset($cart->removed_cart_contents[$cart_item_key]) or empty checks) and
return early if not; then proceed to read product_id/variation_id and build
$removed_item_ids as before.
| public function handle_cart_quantity_update( $cart_item_key, $quantity, $old_quantity, $cart ) { | ||
| // If quantity was reduced to 0, the item is effectively removed | ||
| if ( $quantity === 0 && $old_quantity > 0 ) { | ||
| $cart_item = $cart->cart_contents[ $cart_item_key ]; | ||
| if ( $cart_item ) { | ||
| $product_id = $cart_item['product_id']; | ||
| $variation_id = isset( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : 0; | ||
|
|
||
| // For variable products, check both parent and variation IDs | ||
| $item_ids = array( $product_id ); | ||
| if ( $variation_id > 0 ) { | ||
| $item_ids[] = $variation_id; | ||
| } | ||
|
|
||
| $this->validate_bump_products_after_removal( $item_ids ); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Also guard cart_contents access on quantity update
Prevents notices when key is absent.
- if ( $quantity === 0 && $old_quantity > 0 ) {
- $cart_item = $cart->cart_contents[ $cart_item_key ];
- if ( $cart_item ) {
+ if ( $quantity === 0 && $old_quantity > 0 ) {
+ if ( isset( $cart->cart_contents[ $cart_item_key ] ) ) {
+ $cart_item = $cart->cart_contents[ $cart_item_key ];
$product_id = $cart_item['product_id'];
$variation_id = isset( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : 0;
// For variable products, check both parent and variation IDs
$item_ids = array( $product_id );
if ( $variation_id > 0 ) {
$item_ids[] = $variation_id;
}
$this->validate_bump_products_after_removal( $item_ids );
- }
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public function handle_cart_quantity_update( $cart_item_key, $quantity, $old_quantity, $cart ) { | |
| // If quantity was reduced to 0, the item is effectively removed | |
| if ( $quantity === 0 && $old_quantity > 0 ) { | |
| $cart_item = $cart->cart_contents[ $cart_item_key ]; | |
| if ( $cart_item ) { | |
| $product_id = $cart_item['product_id']; | |
| $variation_id = isset( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : 0; | |
| // For variable products, check both parent and variation IDs | |
| $item_ids = array( $product_id ); | |
| if ( $variation_id > 0 ) { | |
| $item_ids[] = $variation_id; | |
| } | |
| $this->validate_bump_products_after_removal( $item_ids ); | |
| } | |
| } | |
| } | |
| public function handle_cart_quantity_update( $cart_item_key, $quantity, $old_quantity, $cart ) { | |
| // If quantity was reduced to 0, the item is effectively removed | |
| if ( $quantity === 0 && $old_quantity > 0 ) { | |
| if ( isset( $cart->cart_contents[ $cart_item_key ] ) ) { | |
| $cart_item = $cart->cart_contents[ $cart_item_key ]; | |
| $product_id = $cart_item['product_id']; | |
| $variation_id = isset( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : 0; | |
| // For variable products, check both parent and variation IDs | |
| $item_ids = array( $product_id ); | |
| if ( $variation_id > 0 ) { | |
| $item_ids[] = $variation_id; | |
| } | |
| $this->validate_bump_products_after_removal( $item_ids ); | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In modules/upsell-order-bump/includes/OrderBump.php around lines 188 to 205, the
code accesses $cart->cart_contents[$cart_item_key] without ensuring that key
exists which can raise notices; before reading $cart_item, add a guard using
isset($cart->cart_contents[$cart_item_key]) (or empty check) and return early if
missing so the function only proceeds when the cart item is present, then
continue with the existing product/variation ID logic and call to
validate_bump_products_after_removal.
| $bump_type = ! empty( $bump_info->bump_type ) ? esc_html( $bump_info->bump_type ) : 'products'; | ||
| $offer_product_id = $bump_info->offer_product; | ||
|
|
||
| // Check if the removed item was a target for this bump offer | ||
| $was_target = false; | ||
|
|
||
| if ( $bump_type === 'products' ) { | ||
| $target_products = ! empty( $bump_info->target_products ) ? wc_clean( $bump_info->target_products ) : array(); | ||
| $was_target = ! empty( array_intersect( $removed_item_ids, $target_products ) ); | ||
| } else { | ||
| // For category-based bumps, check if removed product was in target categories | ||
| $was_target = false; | ||
| foreach ( $removed_item_ids as $removed_item_id ) { | ||
| $removed_product_categories = wp_get_post_terms( $removed_item_id, 'product_cat', array( 'fields' => 'ids' ) ); | ||
| $target_categories = ! empty( $bump_info->target_categories ) ? wc_clean( $bump_info->target_categories ) : array(); | ||
| if ( ! empty( array_intersect( $removed_product_categories, $target_categories ) ) ) { | ||
| $was_target = true; | ||
| break; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Category-based cleanup misses variation removals (parent categories)
Variations don’t carry product_cat terms; you need to resolve to the parent product before checking categories. Otherwise orphaned bumps can persist.
- } else {
- // For category-based bumps, check if removed product was in target categories
- $was_target = false;
- foreach ( $removed_item_ids as $removed_item_id ) {
- $removed_product_categories = wp_get_post_terms( $removed_item_id, 'product_cat', array( 'fields' => 'ids' ) );
- $target_categories = ! empty( $bump_info->target_categories ) ? wc_clean( $bump_info->target_categories ) : array();
- if ( ! empty( array_intersect( $removed_product_categories, $target_categories ) ) ) {
- $was_target = true;
- break;
- }
- }
- }
+ } else {
+ // For category-based bumps, check parent categories for variations
+ $was_target = false;
+ $target_categories = ! empty( $bump_info->target_categories ) ? wc_clean( $bump_info->target_categories ) : array();
+ foreach ( $removed_item_ids as $removed_item_id ) {
+ $prod = wc_get_product( $removed_item_id );
+ $term_source_id = ( $prod && $prod->is_type( 'variation' ) ) ? $prod->get_parent_id() : $removed_item_id;
+ $removed_product_categories = wp_get_post_terms( $term_source_id, 'product_cat', array( 'fields' => 'ids' ) );
+ if ( ! empty( array_intersect( $removed_product_categories, $target_categories ) ) ) {
+ $was_target = true;
+ break;
+ }
+ }
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| $bump_type = ! empty( $bump_info->bump_type ) ? esc_html( $bump_info->bump_type ) : 'products'; | |
| $offer_product_id = $bump_info->offer_product; | |
| // Check if the removed item was a target for this bump offer | |
| $was_target = false; | |
| if ( $bump_type === 'products' ) { | |
| $target_products = ! empty( $bump_info->target_products ) ? wc_clean( $bump_info->target_products ) : array(); | |
| $was_target = ! empty( array_intersect( $removed_item_ids, $target_products ) ); | |
| } else { | |
| // For category-based bumps, check if removed product was in target categories | |
| $was_target = false; | |
| foreach ( $removed_item_ids as $removed_item_id ) { | |
| $removed_product_categories = wp_get_post_terms( $removed_item_id, 'product_cat', array( 'fields' => 'ids' ) ); | |
| $target_categories = ! empty( $bump_info->target_categories ) ? wc_clean( $bump_info->target_categories ) : array(); | |
| if ( ! empty( array_intersect( $removed_product_categories, $target_categories ) ) ) { | |
| $was_target = true; | |
| break; | |
| } | |
| } | |
| } | |
| } else { | |
| // For category-based bumps, check parent categories for variations | |
| $was_target = false; | |
| $target_categories = ! empty( $bump_info->target_categories ) | |
| ? wc_clean( $bump_info->target_categories ) | |
| : array(); | |
| foreach ( $removed_item_ids as $removed_item_id ) { | |
| $prod = wc_get_product( $removed_item_id ); | |
| $term_source_id = ( $prod && $prod->is_type( 'variation' ) ) | |
| ? $prod->get_parent_id() | |
| : $removed_item_id; | |
| $removed_product_categories = wp_get_post_terms( | |
| $term_source_id, | |
| 'product_cat', | |
| array( 'fields' => 'ids' ) | |
| ); | |
| if ( ! empty( array_intersect( $removed_product_categories, $target_categories ) ) ) { | |
| $was_target = true; | |
| break; | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
modules/upsell-order-bump/includes/OrderBump.php lines 224-244: category-based
removal check fails for product variations because variations don’t have
product_cat terms; update the loop so for each $removed_item_id you resolve the
parent product ID (use the variation’s post_parent or WooCommerce product API to
get_parent_id) and then fetch categories from the parent product ID before
intersecting with $target_categories; ensure $target_categories is normalized to
an array of ints and use the parent ID only when it exists so category-based
bumps are correctly detected and cleaned up.
Summary by CodeRabbit
New Features
Bug Fixes
Refactor