Skip to content

PPOM legacy option prices skipped with Client-Side Validation enabled #651

Description

@pirate-bot

Summary

When PPOM Client-Side Validation is enabled and legacy price calculations are in use, paid options can appear correctly on the product page but fail to be included after adding the product to the cart if the option-price payload is missing.

Expected behavior: selected paid options are included in the cart and order totals.

Actual behavior: the cart can keep only the base or variation price for the inspected legacy-pricing path.

Impact: orders may be placed without charging for selected additional options.

Customer context

Product / area: PPOM Pro with PPOM base plugin, product option pricing and cart totals
Version: Reported after updating PPOM base plugin to 34.0.1 and then 34.0.4
Environment: WooCommerce site; exact WooCommerce, WordPress, PHP, and PPOM Pro versions not available from visible transcript
Integration / third party: PPOM Pro Client-Side Validation enabled
Reported error / symptom: Product page sometimes showed variation price plus option price, but cart/order pricing dropped the additional option price; options table sometimes showed only the additional option price
Impact: Customer disabled additional options because orders were placed without the option charges

Reproduction notes

Reported steps:

  1. Update PPOM base plugin to 34.0.1, then 34.0.4.
  2. Use PPOM Pro with Client-Side Validation enabled.
  3. Select a product variation and paid PPOM option.
  4. Add the product to cart.
  5. Observe that the product page may show the correct combined price, while the cart/order can omit the additional option charge.

Repository-confirmed reproduction path:

  1. Enable PPOM legacy price calculations.
  2. Enable PPOM Client-Side Validation.
  3. Submit a PPOM product with priced fields where ppom[ppom_option_price] is absent or empty.
  4. The add-to-cart validation fallback that computes the missing option-price payload is not registered, and legacy cart pricing exits without applying option pricing.

Missing to fully tie to this customer: confirmation that the customer site has legacy price calculations enabled and that the hidden option-price payload was empty during add to cart.

Diagnosis

Conclusion

The base PPOM plugin has a reachable defect in the legacy cart-pricing path when Client-Side Validation is enabled. Fact: WooCommerceCartLifecycleHooks::register() does not register the add-to-cart validation callback when ppom_is_client_validation_enabled() is true, and that skipped callback contains the fallback that computes ppom[ppom_option_price] when the browser does not submit it. Fact: legacy cart pricing then exits early when ppom_option_price is absent. Inference: this matches the reported symptom where the product page can show selected option prices, but the cart/order line can omit those charges.

Where this likely occurs

  • User-visible surface: single product add-to-cart flow for PPOM products using paid options, Client-Side Validation, and legacy price calculations.
  • src/Cart/WooCommerceCartLifecycleHooks.phpWooCommerceCartLifecycleHooks::register() lines 20–29: skips ppom_woocommerce_validate_product when client-side validation is enabled, then registers ppom_woocommerce_update_cart_fees for legacy pricing.
  • src/WooCommerce/Product/ProductHandler.phpProductHandler::validate_product() lines 213–246: contains the legacy fallback that detects priced posted fields with missing ppom_option_price and computes a JSON option-price payload. git blame attributes lines 220–238 to commit 4f6bfe0 (fix: handle legacy price validation (#586)).
  • src/WooCommerce/Cart/CartHandler.phpCartHandler::update_cart_fees() lines 380–388: returns the cart item unchanged when $values['ppom']['ppom_option_price'] is absent; lines 408–524 only calculate and apply option prices after that payload exists.
  • templates/frontend/component/form-data.php — form-data template lines 29–33: renders the hidden ppom[ppom_option_price] field that legacy cart pricing consumes.
  • js/price/ppom-price-v2.jsppomPrice.init() lines 512–556 and PPOM_Price_Table::init() lines 322–423: the inspected v2 preview path rebuilds the visible price table from selected fields; no write to #ppom_option_price was found during inspection of this file. This is relevant if the store uses the optimized price-table script or an integration path that leaves the hidden payload empty.
  • Version/history evidence: tags v34.0.1 and v34.0.4 are release/version bumps. The broad refactor landed before v34.0.0 in commit a8f17ea; the missing-payload legacy fallback landed in commit 4f6bfe0 before v34.0.0. The customer report after 34.0.1/34.0.4 aligns with the 34.x code path, but the exact customer previous version was not provided.

Engineering notes

  • The issue is anchored in the free/base plugin repo. PPOM Pro is still relevant because the reported store uses PPOM Pro and the Client-Side Validation setting is exposed under Pro-facing settings in backend/options.php lines 194–198.
  • Modern cart pricing is a separate path: src/Pricing/Engine.php lines 38–90 recalculates addon totals from ppom['fields'] via Engine::get_field_prices(). The confirmed defect is scoped to the inspected legacy fee/line calculation path that depends on ppom_option_price.
  • The transcript does not confirm whether the customer has ppom_legacy_price enabled. The source defect is still definite for that supported setting combination; customer reproduction would confirm whether this is the exact active path on the reported store.
  • Client-side validation currently affects more than validation in this path because it also prevents the pricing fallback in ProductHandler::validate_product() from running.
  • The visible price-table behavior and cart undercharge can diverge because the product-page preview and the cart pricing payload are separate data flows.

Test coverage status

Relevant coverage exists but misses the failing combination.

  • tests/unit/src/WooCommerce/test-product-handler.phpTest_Product_Handler::test_validate_product_legacy_mode_computes_price_server_side_when_js_price_missing() lines 80–124 covers the legacy fallback when ProductHandler::validate_product() is called directly.
  • tests/unit/src/WooCommerce/test-product-handler.phpTest_Product_Handler::test_validate_product_legacy_mode_leaves_existing_option_price_intact() lines 126–165 covers the existing-payload case.
  • tests/unit/src/Validation/test-validator-limits.phpTest_Validator_Limits::test_validation_product_limits_noop_when_client_validation_enabled() lines 160–191 covers a different client-validation behavior, not cart pricing.
  • No relevant coverage was found during inspection for WooCommerceCartLifecycleHooks::register() with both Client-Side Validation enabled and legacy pricing enabled, followed by add-to-cart/session pricing with a missing ppom_option_price payload.

What to verify or explore next

  • Reproduce on a PPOM product with legacy price calculations enabled, Client-Side Validation enabled, and a paid select/radio/checkbox option while submitting an add-to-cart request without ppom[ppom_option_price].
  • Run the focused PHPUnit suite around product validation and cart handlers, such as tests/unit/src/WooCommerce/test-product-handler.php and tests/unit/src/WooCommerce/test-cart-handler.php, after adding a reproduction case.
  • Confirm whether the customer site has ppom_legacy_price enabled and whether the hidden ppom[ppom_option_price] field is empty at add-to-cart time.
  • May be worth verifying the same workflow with the optimized price-table script enabled and disabled, because the inspected v2 script did not show a hidden-payload write.

Unknowns / follow-up

  • Customer site settings from the linked Site Health file were not inspected because external/customer links were treated as out of scope.
  • Exact previous working PPOM base version and PPOM Pro version are unknown from the visible transcript.
  • The customer’s exact field types and whether conditional logic hides any priced fields are unknown.

Confidence

Confidence: 88/100

Repository inspection shows the server fallback for missing legacy option-price payloads is only reached through a validation hook that is not registered when Client-Side Validation is enabled, matching the reported cart undercharge symptom for that pricing mode.


Source: HelpScout #3366910382
Generated by bug-report-triage (ID: bug-report-triage_6a3d0a482325e1.55016397)

Metadata

Metadata

Type

Fields

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions