Architecture at a glance
- Bootstrap:
weight-based-products.php - Core orchestrator:
includes/class-lf-wbpw.php - Product model:
includes/class-wc-product-weight-based.php - Frontend/cart/order flow:
public/class-lf-wbpw-public.php - Stock transitions:
includes/class-lf-wbpw-order-handler.php - Settings:
includes/class-lf-wbpw-settings.php - Central pricing engine:
includes/class-lf-wbpw-pricing.php - REST:
includes/class-lf-wbpw-rest.php - Pack marketing badges:
includes/class-lf-wbpw-pack-badges.php(LF_WBPW_Pack_Badges)
Extension units (custom kg/lb families, ml/L, etc.): hook lf_wbpw_register_units, LF_WBPW_Unit_Family_Interface::get_js_config(), and filters for meta conversion and REST.
Pricing engine contract
Main API:
LF_WBPW_Pricing::compute_line_pricing(array $context): array
Expected keys in $context:
product_id,mode,weight,price_per_unit,quantitywbpw_options,wbpw_sidesinclude_options,include_sides
Returns:
weight_total,options_total,sides_total,line_totalunit_price_effectiveregular_reference_totaldiscount_flags.sale_active,tier_applied,role_applied
Order meta contracts
| Meta key | Where set | Purpose |
|---|---|---|
_weight_data | checkout item creation | Structured payload for rendering and reporting |
_selected_packages | packs mode checkout | Stock reduce/restore source data |
_total_weight | packs and free mode checkout | Total weight snapshot; free mode drives inventory reduction |
_wbpw_display_unit_at_order | checkout item creation | Locks stock writes to order-time unit bucket |
_wbpw_sides | checkout item creation | Structured sides payload for grouped/separate modes |
_wbpw_weight_line_total | checkout item creation | Weight + paid options split for reporting |
_wbpw_sides_total | checkout item creation | Sides split for reporting |
_weight_based_pack_badges | product save (Fixed Packs) | Map of pack weight key → marketing slug (recommended, best_seller); empty = no badge |
_wbpw_package_card_style | product save | Optional per-product override: list | grid; omitted/inherit uses global lf_wbpw_package_card_style |
Free-weight inventory (product meta)
When set, remaining weight is stored per base unit bucket:
_weight_based_fw_total_available_kg/_weight_based_fw_total_available_lb— remaining weight pool (empty = unlimited)._weight_based_fw_low_weight_threshold_kg/_weight_based_fw_low_weight_threshold_lb— threshold for the low-stock badge.
Cart-aware helpers: LF_WBPW_Public::get_cart_adjusted_fw_remaining($product), LF_WBPW_Public::get_fw_effective_max_weight($product).
Hooks and filters
Actions
lf_wbpw_register_units— passLF_WBPW_Unit_Registry; register customLF_WBPW_Unit_Family_Interfaceimplementationslf_wbpw_before_weight_options_panellf_wbpw_after_weight_options_panellf_wbpw_before_weight_inputlf_wbpw_after_weight_input
Filters
lf_wbpw_product_type_labellf_wbpw_available_weightslf_wbpw_min_order_weightlf_wbpw_max_order_weightlf_wbpw_active_pricelf_wbpw_tiered_pricelf_wbpw_weight_optionslf_wbpw_cart_item_pricelf_wbpw_cart_price_htmllf_wbpw_cart_item_datalf_wbpw_price_htmllf_wbpw_rest_weight_options_responself_wbpw_rest_product_responself_wbpw_rest_product_weight_based_datalf_wbpw_js_unit_config,lf_wbpw_js_unit_configslf_wbpw_rest_units_responself_wbpw_effective_package_card_style— resolvedlist|gridfor storefront (after per-product meta and global Appearance)lf_wbpw_convert_weight_to_meta_base,lf_wbpw_convert_weight_from_meta_base— extension input units vs stored kg/lb for custom display familieslf_wbpw_hidden_order_itemmeta_keys— hide internal line item meta in admin order screen
REST (wc-wbp/v1)
GET /units— registered families withjs_configGET /products/{id},GET /products/{id}/weight-options— includeunit_config
WooCommerce GET /wp-json/wc/v3/products/{id} responses include a weight_based object for weight-based products: ordering_mode, unit_config, package_card_style (resolved list/grid), packs weights, etc. Filter: lf_wbpw_rest_product_weight_based_data.
Public methods developers commonly call
WC_Product_Weight_Based
get_ordering_mode()get_available_weights()get_weight_options($target_weight, $adjusted_weights = null)get_active_price()get_price_for_weight($weight)get_min_order_weight(),get_max_order_weight()get_fw_min(),get_fw_max(),get_fw_step(),get_fw_presets()get_fw_total_weight_available_remaining(),get_fw_low_weight_threshold(),is_fw_low_weight_stock($adjusted_remaining = null)get_effective_package_card_style()—list|gridfor Fixed Packs (per-product meta; Free Weight mode ignores override and uses global)
LF_WBPW_Public (static)
get_cart_adjusted_fw_remaining($product)get_fw_effective_max_weight($product)
LF_WBPW_Units
get_display_unit($product_id = 0)format_weight($value, $product_id = 0)format_weight_raw($value, $product_id = 0)normalize_preset_to_base($value, $product_id = 0)
REST API
GET /wp-json/wc-wbp/v1/products/{id}GET /wp-json/wc-wbp/v1/products/{id}/weight-options?target_weight=X
WooCommerce REST product responses are also extended via woocommerce_rest_prepare_product_object.
Suggestion mode semantics
closest: minimal absolute difference from target.round_up: prefer combinations at or above target.round_down: prefer combinations at or below target.- If strict mode has no valid result, runtime falls back to closest.
Desired-weight / preset cap (Fixed Packs JS): Global option lf_wbpw_combo_max_items (default 25, range 1–500) limits total number of pack lines in the bestCombo() search in assets/js/lf-wbpw-public.js. Passed to the storefront as lf_wbpw_front_params.combo_max_items. Raise when many small packs are needed to approximate a target weight.
Pack marketing badges (Fixed Packs)
Slugs are defined in LF_WBPW_Pack_Badges::get_slugs() (e.g. recommended, best_seller). Stored in _weight_based_pack_badges. Admin saves pack rows as JSON triples [weight, stock, badge_slug] in the hidden lf_wbpw_weights field. Storefront: .pkg-marketing-badge next to the pack name; admin pack pills show optional small labels.
Admin vs storefront: pack stock colouring
Product editor pack “pills” use CSS classes lf_wbpw_weight_tag--stock-ok|stock-low|stock-out against the global low-stock threshold. Row-level inventory tint on the storefront was intentionally not tied to this (stock text badges remain).
Stock consistency note
Stock reduce/restore uses order item key _wbpw_display_unit_at_order to prevent unit-switch drift after an order is created.
Compatibility notes
- HPOS compatibility declared.
- Blocks cart/checkout support via Store API extensions and custom cart-item data.
Product editor (Fixed Packs)
- Available Weight Packages — Define weights, stock, drag to reorder; marketing badges per pack (e.g. Recommended, Best seller) via the package edit dialog.
- Pack list display (below the package list, Fixed Packs only) — Sort packages by (store default, ascending, descending, catalog order) and Package card style (inherit, list, grid). Hidden when Free Weight ordering mode is selected.
- Admin pack “pills” can show stock-tier colours (green / amber / red) using the global low-stock threshold; storefront rows do not use the same row background tint.