: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Upsells class
* The ET_Builder_Module_Woocommerce_Upsells Class is responsible for rendering the
* Upsells markup using the WooCommerce template.
* Class representing WooCommerce Upsells component.
class ET_Builder_Module_Woocommerce_Upsells extends ET_Builder_Module {
* Holds Prop values across static methods.
public static $static_props;
$this->name = esc_html__( 'Woo Upsell', 'et_builder' );
$this->plural = esc_html__( 'Woo Upsells', 'et_builder' );
// Use `et_pb_wc_{module}` for all WooCommerce modules.
$this->slug = 'et_pb_wc_upsells';
$this->vb_support = 'on';
$this->main_css_element = '%%order_class%%';
$this->settings_modal_toggles = array(
'main_content' => et_builder_i18n( 'Content' ),
'overlay' => et_builder_i18n( 'Overlay' ),
'image' => et_builder_i18n( 'Image' ),
// Avoid Text suffix by manually defining the `star` toggle slug.
'star' => esc_html__( 'Star Rating', 'et_builder' ),
$this->advanced_fields = array(
'label' => et_builder_i18n( 'Title' ),
'main' => '%%order_class%% section.products > h1, %%order_class%% section.products > h2, %%order_class%% section.products > h3, %%order_class%% section.products > h4, %%order_class%% section.products > h5, %%order_class%% section.products > h6',
'label' => esc_html__( 'Star Rating', 'et_builder' ),
'main' => '%%order_class%% ul.products li.product .star-rating',
'color' => '%%order_class%% li.product .star-rating > span:before',
'letter_spacing_hover' => '%%order_class%% ul.products li.product:hover .star-rating',
'hide_line_height' => true,
'hide_text_shadow' => true,
'label' => esc_html__( 'Star Rating Alignment', 'et_builder' ),
'label' => esc_html__( 'Star Rating Size', 'et_builder' ),
'label' => esc_html__( 'Star Rating Color', 'et_builder' ),
'product_title' => array(
'label' => esc_html__( 'Product Title', 'et_builder' ),
'main' => "{$this->main_css_element} ul.products li.product h3, {$this->main_css_element} ul.products li.product h1, {$this->main_css_element} ul.products li.product h2, {$this->main_css_element} ul.products li.product h4, {$this->main_css_element} ul.products li.product h5, {$this->main_css_element} ul.products li.product h6",
'label' => esc_html__( 'Price', 'et_builder' ),
'main' => "{$this->main_css_element} ul.products li.product .price, {$this->main_css_element} ul.products li.product .price .amount",
'range_settings' => array(
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
'label' => esc_html__( 'Sale Badge', 'et_builder' ),
'main' => "{$this->main_css_element} ul.products li.product .onsale",
'important' => array( 'line-height', 'font', 'text-shadow' ),
'hide_text_align' => true,
'letter_spacing' => array(
'label' => esc_html__( 'Sale Price', 'et_builder' ),
'main' => "{$this->main_css_element} ul.products li.product .price ins .amount",
'hide_text_align' => true,
'default' => '|700|||||||',
'range_settings' => array(
'border_radii' => '%%order_class%%.et_pb_wc_upsells .product',
'border_styles' => '%%order_class%%.et_pb_wc_upsells .product',
'border_radii' => '%%order_class%%.et_pb_module .et_shop_image',
'border_styles' => '%%order_class%%.et_pb_module .et_shop_image',
'label_prefix' => et_builder_i18n( 'Image' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'main' => '%%order_class%% .product',
'label' => esc_html__( 'Image Box Shadow', 'et_builder' ),
'option_category' => 'layout',
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'main' => '%%order_class%% .et_shop_image',
'default_on_fronts' => array(
'margin_padding' => array(
'main' => '%%order_class%%',
// Needed to overwrite last module margin-bottom styling.
'important' => array( 'custom_margin' ),
'text_shadow' => implode(
"{$this->main_css_element} ul.products h3",
"{$this->main_css_element} ul.products h1",
"{$this->main_css_element} ul.products h2",
"{$this->main_css_element} ul.products h4",
"{$this->main_css_element} ul.products h5",
"{$this->main_css_element} ul.products h6",
"{$this->main_css_element} ul.products .price",
"{$this->main_css_element} ul.products .price .amount",
'child_filters_target' => array(
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'main' => '%%order_class%% .et_shop_image',
$this->custom_css_fields = array(
'label' => esc_html__( 'Product', 'et_builder' ),
'selector' => 'li.product',
'label' => esc_html__( 'Onsale', 'et_builder' ),
'selector' => 'li.product .onsale',
'label' => et_builder_i18n( 'Image' ),
'selector' => '.et_shop_image',
'label' => et_builder_i18n( 'Overlay' ),
'selector' => '.et_overlay',
'label' => et_builder_i18n( 'Title' ),
'selector' => ET_Builder_Module_Helper_Woocommerce_Modules::get_title_selector(),
'label' => esc_html__( 'Star Rating', 'et_builder' ),
'selector' => '.star-rating',
'label' => esc_html__( 'Price', 'et_builder' ),
'selector' => 'li.product .price',
'label' => esc_html__( 'Old Price', 'et_builder' ),
'selector' => 'li.product .price del span.amount',
$this->help_videos = array(
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
public function get_fields() {
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'computed_affects' => array(
'posts_number' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_columns_posts_default(),
'computed_affects' => array(
'columns_number' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_columns_posts_default(),
'computed_affects' => array(
'orderby' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'default' => esc_html__( 'Random Order', 'et_builder' ),
'menu_order' => esc_html__( 'Sort by Menu Order', 'et_builder' ),
'popularity' => esc_html__( 'Sort By Popularity', 'et_builder' ),
'date' => esc_html__( 'Sort By Date: Oldest To Newest', 'et_builder' ),
'date-desc' => esc_html__( 'Sort By Date: Newest To Oldest', 'et_builder' ),
'price' => esc_html__( 'Sort By Price: Low To High', 'et_builder' ),
'price-desc' => esc_html__( 'Sort By Price: High To Low', 'et_builder' ),
'computed_affects' => array(
'sale_badge_color' => array(
'label' => esc_html__( 'Sale Badge Color', 'et_builder' ),
'description' => esc_html__( 'Pick a color to use for the sales bade that appears on products that are on sale.', 'et_builder' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'sale_badge',
'mobile_options' => true,
'icon_hover_color' => array(
'label' => esc_html__( 'Overlay Icon Color', 'et_builder' ),
'description' => esc_html__( 'Pick a color to use for the icon that appears when hovering over a product.', 'et_builder' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'hover_overlay_color' => array(
'label' => esc_html__( 'Overlay Background Color', 'et_builder' ),
'description' => esc_html__( 'Here you can define a custom color for the overlay', 'et_builder' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'label' => esc_html__( 'Overlay Icon', 'et_builder' ),
'description' => esc_html__( 'Here you can define a custom icon for the overlay', 'et_builder' ),
'option_category' => 'configuration',
'class' => array( 'et-pb-font-icon' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Upsells',
'computed_depends_on' => array(
'computed_minimum' => array(
public function get_transition_fields_css_props() {
$fields = parent::get_transition_fields_css_props();
$fields['rating_letter_spacing'] = array(
'width' => '%%order_class%% .star-rating',
'letter-spacing' => '%%order_class%% .star-rating',
* Gets the Upsells Products.
* Used as a callback to the __upsells computed prop.
* @param array $args Arguments from Computed Prop AJAX call.
* @param array $conditional_tags Conditional Tags.
* @param array $current_page Current page args.
public static function get_upsells( $args = array(), $conditional_tags = array(), $current_page = array() ) {
self::$static_props = $args;
// Force set product's class to ET_Theme_Builder_Woocommerce_Product_Variable_Placeholder
// in TB so related product can outputs visible content based on pre-filled value in TB
if ( 'true' === et_()->array_get( $conditional_tags, 'is_tb', false ) ) {
// Set upsells id; adjust it with module's arguments. This is specifically needed if
// the module fetched the value via computed callback due to some fields no longer uses
ET_Theme_Builder_Woocommerce_Product_Variable_Placeholder::set_tb_upsells_ids( array(
'limit' => et_()->array_get( $args, 'posts_number', 4 ),
add_filter( 'woocommerce_product_class', 'et_theme_builder_wc_product_class' );
'woocommerce_upsell_display_args',
'ET_Builder_Module_Woocommerce_Upsells',
'set_upsell_display_args',
if ( isset( $args['orderby'] ) ) {
$orderby = $args['orderby'];
if ( in_array( $orderby, array( 'price', 'date' ), true ) ) {
* For the list of all allowed Orderby values, refer
* @see wc_products_array_orderby
$output = et_builder_wc_render_module_template( 'woocommerce_upsell_display', $args );
'woocommerce_upsell_display_args',
'ET_Builder_Module_Woocommerce_Upsells',
'set_upsell_display_args',
* Returns the User selected Posts per page, columns and Order by values to WooCommerce.
* @param array $args Documented at
* {@see woocommerce_upsell_display()}.
public static function set_upsell_display_args( $args ) {
$selected_args = self::get_selected_upsell_display_args();
return wp_parse_args( $selected_args, $args );
* Gets the User set Posts per page, columns and Order by values.
* The static variable used in this method is set by
* @see ET_Builder_Module_Woocommerce_Upsells::get_upsells()