/* ----------------------------------*/ /* Single product template hooks. */ /*----------------------------------*/ /** * We wrap the auto-injection in a check. * This prevents "Bleed" on live pages but allows * the shortcode to manually trigger the builder. */ if ( ! is_admin() ) { // This function only runs the builder if it's called via shortcode // OR if we are on a specific test page. function duff_tuff_check_for_shortcode_display() { if ( ! has_shortcode( get_the_content(), 'woocommerce_composite_product' ) && ! has_shortcode( get_the_content(), 'product_page' ) ) { // If NO shortcode is found, we unhook the auto-display to prevent bleed remove_action( 'woocommerce_composite_add_to_cart', 'wc_cp_add_to_cart' ); remove_action( 'woocommerce_after_single_product_summary', 'wc_cp_add_to_cart_after_summary', -1000 ); } } add_action( 'wp', 'duff_tuff_check_for_shortcode_display' ); } // Keep the standard hooks defined so the shortcode can still find them add_action( 'woocommerce_composite_add_to_cart', 'wc_cp_add_to_cart' ); add_action( 'woocommerce_after_single_product_summary', 'wc_cp_add_to_cart_after_summary', -1000 ); // Single product add-to-cart button template add_action( 'woocommerce_composite_add_to_cart_button', 'wc_cp_add_to_cart_button' ); // Before and After components: Fire layout-specific actions. add_action( 'woocommerce_composite_before_components', 'wc_cp_before_components', 10, 2 ); add_action( 'woocommerce_composite_after_components', 'wc_cp_after_components', 10, 2 ); // After components: Status Messages. add_action( 'woocommerce_composite_after_components', 'wc_cp_status', 10, 2 ); // After components: Display no-JS notice regardless of layout. add_action( 'woocommerce_composite_after_components', 'wc_cp_no_js_msg', 15, 2 ); /* ----------------------------------------*/ /* Single product summary widget hooks. */ /*----------------------------------------*/ // Validation message for fixed-display widgets. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_message_fixed', 0, 3 ); // Selections wrapper start. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_details_wrapper_start', 5, 3 ); // Content. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_content', 10, 3 ); // Selections wrapper end. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_details_wrapper_end', 15, 3 ); // UI wrapper start. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_ui_wrapper_start', 15, 3 ); // Price. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_price', 20, 2 ); // Validation message for default-display widgets. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_message_default', 30, 3 ); // Availability. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_availability', 40, 2 ); // Button. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_button', 50, 2 ); // UI wrapper end. add_action( 'woocommerce_composite_summary_widget_content', 'wc_cp_summary_widget_ui_wrapper_end', 100, 3 ); /* ---------------------------*/ /* Stacked layout hooks. */ /*---------------------------*/ /* * After components: */ // Add-to-cart section. add_action( 'woocommerce_composite_after_components_single', 'wc_cp_add_to_cart_section', 10, 2 ); /* * Component options: */ // Sorting and filtering. add_action( 'woocommerce_composite_component_selections_single', 'wc_cp_component_options_sorting', 10, 2 ); add_action( 'woocommerce_composite_component_selections_single', 'wc_cp_component_options_filtering', 20, 2 ); // Component options title. add_action( 'woocommerce_composite_component_selections_single', 'wc_cp_component_options_title', 30, 2 ); // Top Pagination. add_action( 'woocommerce_composite_component_selections_single', 'wc_cp_component_options_pagination_top', 39, 2 ); // Component options: Dropdowns / Thumbnails / ... add_action( 'woocommerce_composite_component_selections_single', 'wc_cp_component_options', 40, 2 ); // Pagination. add_action( 'woocommerce_composite_component_selections_single', 'wc_cp_component_options_pagination_bottom', 41, 2 ); // Current selection in single-page mode. add_action( 'woocommerce_composite_component_selections_single', 'wc_cp_component_selection', 50, 2 ); /* -----------------------------*/ /* Progressive layout hooks. */ /*-----------------------------*/ /* * After components: */ // Add-to-cart section. add_action( 'woocommerce_composite_after_components_progressive', 'wc_cp_add_to_cart_section', 10, 2 ); // Previous / Next buttons. add_action( 'woocommerce_composite_after_components_progressive', 'wc_cp_navigation_bottom', 15, 2 ); /* * Component options: */ // Current selections block wrapper in progressive mode -- start. add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_options_progressive_start', 0, 2 ); // Sorting and filtering. add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_options_sorting', 10, 2 ); add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_options_filtering', 20, 2 ); // Component options title. add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_options_title', 30, 2 ); // Top Pagination. add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_options_pagination_top', 39, 2 ); // Dropdowns / Thumbnails / ... add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_options', 40, 2 ); // Bottom Pagination. add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_options_pagination_bottom', 41, 2 ); // Current selections block wrapper in progressive mode -- end. add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_options_progressive_end', 45, 2 ); // Current selection in single-page mode. add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_selection', 50, 2 ); // Component notices container. add_action( 'woocommerce_composite_component_selections_progressive', 'wc_cp_component_selection_message_progressive', 60, 2 ); /* -------------------------------------------*/ /* Stepped and Componentized layout hooks. */ /*-------------------------------------------*/ /* * Before components: */ // Auto-scroll target at top of page when transitioning to a new component. /* * Note: * * When component options loaded via ajax are appended instead of paginated (@see WC_Component::paginate_options), * the selected product details are relocated below the selected product thumbnail row. * * In this case, when transitioning back to a component with relocated selected product details, the relocated container will be moved back to the original position * and the viewport will auto-scroll to the target defined here. * * Alternatively, the 'woocommerce_composite_front_end_params' filter ('relocated_content_reset_on_return' key) can be used to prevent resetting the position of the relocated container. * In this case, the viewport will always auto-scroll to the relocated container. */ add_action( 'woocommerce_composite_before_components_paged', 'wc_cp_component_transition_scroll_target', 10, 2 ); // Component blocker div (blocks input during transitions). add_action( 'woocommerce_composite_before_components_paged', 'wc_cp_component_blocker', 10, 2 ); // Composite pagination (anchors to components at top of page). add_action( 'woocommerce_composite_before_components_paged', 'wc_cp_pagination', 15, 2 ); // Previous / Next buttons added on top of page when component options are viewed as thumbnails. add_action( 'woocommerce_composite_before_components_paged', 'wc_cp_navigation_top', 20, 2 ); // Previous / Next buttons relocated by JS into the current selection details when component options are viewed as thumbnails and appended. add_action( 'woocommerce_composite_before_components_paged', 'wc_cp_navigation_movable', 20, 2 ); /* * After components: */ // Add-to-cart section. /* * Note: * * If 'wc_cp_add_to_cart_section' is moved to a later priority, the add-to-cart and summary section will no longer be part of the step-based process * In this case, use 'wc_cp_final_step_scroll_target' to define the auto-scroll target after clicking on the "Next" button of the final component, like so: * add_action( 'woocommerce_composite_after_components_paged', 'wc_cp_final_step_scroll_target', 9, 2 ); */ add_action( 'woocommerce_composite_after_components_paged', 'wc_cp_add_to_cart_section', 10, 2 ); // Previous / Next buttons at bottom of page. add_action( 'woocommerce_composite_after_components_paged', 'wc_cp_navigation_bottom', 15, 2 ); /* * Component options: */ // Component details scroll target. add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_selection_scroll_target_paged_top', -20, 2 ); // Component notices container (thumbnails). add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_selection_message_paged_top', -10, 2 ); // Component options: Current selection details in paged mode - before thumbnails. add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_selection_paged_top', 0, 2 ); // Component options: Sorting and filtering. add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_options_sorting', 10, 2 ); add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_options_filtering', 20, 2 ); // Component options title. add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_options_title', 30, 2 ); // Component options: Top Pagination. add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_options_pagination_top', 39, 2 ); // Component options: Dropdowns / Thumbnails / ... add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_options', 40, 2 ); // Component options: Bottom Pagination. add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_options_pagination_bottom', 41, 2 ); // Component options: Current selection in paged mode - after dropdown. add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_selection_paged_bottom', 50, 2 ); // Component notices container (dropdowns and radios). add_action( 'woocommerce_composite_component_selections_paged', 'wc_cp_component_selection_message_paged_bottom', 60, 2 ); // Summary added inside the composite-add-to-cart.php template. add_action( 'woocommerce_before_add_to_cart_button', 'wc_cp_before_add_to_cart_button', 5 ); /* --------------------------------------*/ /* Component options template hooks. */ /*--------------------------------------*/ add_action( 'woocommerce_composite_component_options_dropdowns', 'wc_cp_component_options_dropdown', 10, 2 ); add_action( 'woocommerce_composite_component_options_thumbnails', 'wc_cp_component_options_thumbnails', 10, 2 ); add_action( 'woocommerce_composite_component_options_radios', 'wc_cp_component_options_radios', 10, 2 ); /* --------------------------------------*/ /* Composited product template hooks. */ /*--------------------------------------*/ // Composited product title. add_action( 'woocommerce_composited_product_single', 'wc_cp_composited_product_title', 5 ); // Composited product details wrapper open. add_action( 'woocommerce_composited_product_single', 'wc_cp_composited_product_wrapper_open', 10 ); // Composited product thumbnail. add_action( 'woocommerce_composited_product_single', 'wc_cp_composited_product_thumbnail', 20 ); // Composited product details. add_action( 'woocommerce_composited_product_single', 'wc_cp_composited_product_single', 30 ); // Composited product details wrapper close. add_action( 'woocommerce_composited_product_single', 'wc_cp_composited_product_wrapper_close', 100 ); // Composited product - Simple product template data. add_action( 'woocommerce_composited_product_simple', 'wc_cp_composited_product_simple', 10 ); // Composited product - Variable product template data. add_action( 'woocommerce_composited_product_variable', 'wc_cp_composited_product_variable', 10 ); // Composited product - Excerpt. add_action( 'woocommerce_composited_product_details', 'wc_cp_composited_product_excerpt', 10, 3 ); // Composited Simple product - Price. add_action( 'woocommerce_composited_product_add_to_cart', 'wc_cp_composited_product_price', 8, 3 ); // Composited Variable product - Selected variation. add_action( 'woocommerce_composited_single_variation', 'wc_cp_composited_single_variation', 10, 3 ); add_action( 'woocommerce_composited_single_variation', 'wc_cp_composited_single_variation_template', 20, 3 ); /** * Shortcode to display the Composite Builder for the current product. * Usage: [duff_builder] */ add_shortcode( 'duff_builder', function() { // Detect the current product ID automatically global $product; if ( ! is_product() && ! $product ) { return 'Please use this shortcode on a Single Product page.'; } $product_id = $product->get_id(); // Check if it's actually a composite product before rendering if ( $product->is_type( 'composite' ) ) { return do_shortcode( '[woocommerce_composite_product id="' . $product_id . '"]' ); } return 'This product is not a Composite Product.'; }); Scheduled Maintenance | Duff Tuff
Duff Tuff Logo

Scheduled Maintenance

Our digital catalog is currently offline for scheduled maintenance and performance optimizations. We will be back online shortly.

Text or Call our Sales Department 865-938-6696