The FlowInterface contract
Every flow must implementUTB\ProductBuilder\Flows\FlowInterface. The interface enforces the following methods:
validate_cart_data returns true on success or a localized error string on failure. The AbstractFlow wrapper catches this value and calls wc_add_notice() automatically, so concrete flows never interact with WooCommerce notices directly.FlowRegistry
FlowRegistry is a static service that holds all registered flows and their product assignments in memory.
Registration
Flows are registered duringPlugin::register_flows(), which runs on the plugins_loaded hook:
FlowRegistry::register(FlowInterface $flow) stores the flow instance keyed by $flow->get_id().
Loading product assignments
After registration,FlowRegistry::load_assignments() reads product→flow mappings from wp_utb_form_configs:
FlowRegistry::$product_assignments.
Routing a product to its flow
null and the plugin leaves the WooCommerce product page untouched.
Initialization
FlowRegistry::init_all() iterates every registered flow and calls $flow->init(), which in turn registers shortcodes, AJAX endpoints, and WooCommerce hooks.
AbstractFlow lifecycle
AbstractFlow implements the common hook wiring so concrete flows only need to provide business logic.
Hook registration (init)
WhenAbstractFlow::init() is called it registers:
- Shortcodes — from
get_shortcodes(). Each entry in the returned array maps a shortcode tag to a method name on the flow. - AJAX endpoints — from
get_ajax_endpoints(). Each action is registered for bothwp_ajax_{action}andwp_ajax_nopriv_{action}. - WooCommerce hooks — hard-wired in
AbstractFlow::init():
Product page takeover
AbstractFlow::maybe_setup_landing() fires on wp. If the current page is a product and the flow owns it, setup_product_landing() removes all default WooCommerce output and injects the flow’s own HTML:
Remove standard WooCommerce elements
Strips breadcrumbs, title, price, excerpt, meta, sharing, add-to-cart button, product tabs, upsells, and related products from the WooCommerce action queue.
Inject flow wrapper
Adds
render_flow_wrapper() to woocommerce_single_product_summary at priority 30. This outputs <div class="utb-product-flow-container"> and calls the abstract render_custom_content() method that each concrete flow implements.Suppress duplicate content
Hooks
suppress_detail_content onto the_content and remove_product_tabs onto woocommerce_product_tabs to prevent theme content duplication.Cart pipeline
| Hook | AbstractFlow method | What it does |
|---|---|---|
woocommerce_add_to_cart_validation | validate_add_to_cart | Calls validate_cart_data($_POST); converts errors to WC notices |
woocommerce_add_cart_item_data | add_cart_item_data_filter | Calls prepare_cart_metadata($_POST); appends _utb_flow_id and a unique key |
woocommerce_before_calculate_totals | apply_dynamic_pricing | Iterates cart items owned by this flow and sets price via calculate_dynamic_price() |
woocommerce_checkout_create_order_line_item | save_order_item_meta | Persists all _utb_* prefixed keys from cart item data to order line item meta |
Extension point: utb_pb_register_flows
Third-party plugins and themes can register custom flows by hooking into utb_pb_register_flows:
FlowInterface. Extending AbstractFlow is recommended so WooCommerce hook wiring is inherited automatically.
Built-in flows
CEPFlow
Flow ID:
utb_cep_programsHandles continuing education program enrollments. Renders a student data form with a program selector populated from wp_utb_cep_programs. Integrates with the Banner API via ApiConnectionManager('cep_integrator') to validate student identity and apply role-based discounts.Shortcode: [utb_cep_form]AJAX actions: cep_calculate_discount, utb_cep_priceCertificadosFlow
Flow ID:
certificados_academicosHandles academic certificate requests with pricing that varies by certificate type, delivery format (digital/physical), and academic level (undergraduate/graduate). Reads certificate catalog and price matrix from wp_utb_certificates and wp_utb_certificate_prices.Shortcodes: [utb_cert_form], [utb_cert_catalog_modal]AJAX actions: utb_get_certs, utb_cert_price