version 4.13.0

This commit is contained in:
2021-12-07 11:08:05 +00:00
commit cb26d2c0c4
1285 changed files with 254735 additions and 0 deletions

View File

@ -0,0 +1,585 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Add_To_Cart class
*
* The ET_Builder_Module_Woocommerce_Add_To_Cart Class is responsible for rendering the
* Add To Cart markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Add to cart component.
*/
class ET_Builder_Module_Woocommerce_Add_To_Cart extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Add To Cart', 'et_builder' );
$this->plural = esc_html__( 'Woo Add To Cart', 'et_builder' );
$this->slug = 'et_pb_wc_add_to_cart';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
'elements' => et_builder_i18n( 'Elements' ),
),
),
'advanced' => array(
'toggles' => array(
'text' => array(
'title' => et_builder_i18n( 'Text' ),
'priority' => 45,
),
'header' => array(
'title' => esc_html__( 'Heading Text', 'et_builder' ),
'priority' => 49,
'tabbed_subtoggles' => true,
'sub_toggles' => array(
'h1' => array(
'name' => 'H1',
'icon' => 'text-h1',
),
'h2' => array(
'name' => 'H2',
'icon' => 'text-h2',
),
'h3' => array(
'name' => 'H3',
'icon' => 'text-h3',
),
'h4' => array(
'name' => 'H4',
'icon' => 'text-h4',
),
'h5' => array(
'name' => 'H5',
'icon' => 'text-h5',
),
'h6' => array(
'name' => 'H6',
'icon' => 'text-h6',
),
),
),
'width' => array(
'title' => et_builder_i18n( 'Sizing' ),
'priority' => 80,
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'body' => array(
'label' => et_builder_i18n( 'Text' ),
'css' => array(
'main' => '%%order_class%%, %%order_class%% a, %%order_class%% label, %%order_class%%.et_pb_module .et_pb_module_inner .stock',
'important' => 'all',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.3em',
),
'hide_text_align' => true,
'toggle_slug' => 'text',
'font' => array(
'default' => '|700|||||||',
),
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
'text' => array(
'use_background_layout' => true,
'options' => array(
'text_orientation' => array(
'default' => 'left',
),
'background_layout' => array(
'default' => 'light',
'hover' => 'tabs',
),
),
),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options.
'default' => false,
),
'button' => array(
'button' => array(
'label' => et_builder_i18n( 'Button' ),
'css' => array(
'main' => '%%order_class%% .button',
'limited_main' => '%%order_class%% .button',
'alignment' => '%%order_class%% .et_pb_module_inner > form',
// Setting to TRUE since it only checks for the value's existence.
'important' => 'all',
),
/*
* Button inside add to cart module is rendered from WooCommerce's default
* template which makes its positioning isn't flexible. Thus button alignment
* is removed.
*/
'use_alignment' => false,
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% .button',
'important' => true,
),
),
'use_icon' => false,
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
),
),
'form_field' => array(
'fields' => array(
'label' => esc_html__( 'Fields', 'et_builder' ),
'toggle_priority' => 67,
'css' => array(
'main' => '%%order_class%% input, %%order_class%% .quantity input.qty',
'background_color' => '%%order_class%% input, %%order_class%% .quantity input.qty',
'background_color_hover' => '%%order_class%% input:hover, %%order_class%% .quantity input.qty:hover',
'focus_background_color' => '%%order_class%% input:focus, %%order_class%% select:focus, %%order_class%% .quantity input.qty:focus',
'form_text_color' => '%%order_class%% input, %%order_class%% select, %%order_class%% .quantity input.qty',
'form_text_color_hover' => '%%order_class%% input[type="text"]:hover, %%order_class%% select:hover, %%order_class%% .quantity input.qty:hover',
'focus_text_color' => '%%order_class%% input:focus, %%order_class%% .quantity input.qty:focus',
'placeholder_focus' => '%%order_class%% input:focus::-webkit-input-placeholder, %%order_class%% input:focus::-moz-placeholder, %%order_class%% input:focus:-ms-input-placeholder, %%order_class%% textarea:focus::-webkit-input-placeholder, %%order_class%% textarea:focus::-moz-placeholder, %%order_class%% textarea:focus:-ms-input-placeholder',
'padding' => '%%order_class%% input',
'margin' => '%%order_class%%',
'important' => array(
'background_color',
'background_color_hover',
'focus_background_color',
'form_text_color',
'form_text_color_hover',
'text_color',
'focus_text_color',
'padding',
'margin',
),
),
'box_shadow' => array(
'name' => 'fields',
'css' => array(
'main' => '%%order_class%% input',
),
'default_on_fronts' => array(
'color' => '',
'position' => '',
),
),
'border_styles' => array(
'fields' => array(
'name' => 'fields',
'css' => array(
'main' => array(
'border_radii' => '%%order_class%% input, %%order_class%% .quantity input.qty',
'border_styles' => '%%order_class%% input, %%order_class%% .quantity input.qty',
'defaults' => array(
'border_radii' => 'on|3px|3px|3px|3px',
'border_styles' => array(
'width' => '0px',
'style' => 'none',
),
),
),
'important' => 'all',
),
'label_prefix' => esc_html__( 'Fields', 'et_builder' ),
),
'fields_focus' => array(
'name' => 'fields_focus',
'css' => array(
'main' => array(
'border_radii' => '%%order_class%% input:focus, %%order_class%% .quantity input.qty:focus',
'border_styles' => '%%order_class%% input:focus, %%order_class%% .quantity input.qty:focus',
),
'important' => 'all',
),
'label_prefix' => esc_html__( 'Fields Focus', 'et_builder' ),
),
),
'font_field' => array(
'css' => array(
'main' => array(
'%%order_class%% input, %%order_class%% .quantity input.qty',
),
'hover' => array(
'%%order_class%% input:hover',
'%%order_class%% input:hover::-webkit-input-placeholder',
'%%order_class%% input:hover::-moz-placeholder',
'%%order_class%% input:hover:-ms-input-placeholder',
),
'important' => 'all',
),
'font_size' => array(
'default' => '20px',
),
'line_height' => array(
'default' => '1em',
),
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations tr',
'important' => array( 'custom_padding' ),
),
),
),
'dropdown_menus' => array(
'label' => esc_html__( 'Dropdown Menus', 'et_builder' ),
'toggle_priority' => 67,
'css' => array(
'main' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select',
'background_color' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select',
'background_color_hover' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select:hover',
'focus_background_color' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select:focus',
'form_text_color' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select',
'form_text_color_hover' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select + label:hover, %%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select:hover',
'focus_text_color' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select option:focus, %%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select + label',
'placeholder_focus' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select:focus, %%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select + label:focus',
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% select',
'important' => array( 'all' ),
),
),
'important' => array(
'text_color',
'form_text_color',
'margin_padding',
),
),
'margin_padding' => array(
'use_padding' => false,
),
'box_shadow' => array(
'name' => 'dropdown_menus',
'css' => array(
'main' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select',
),
),
'border_styles' => array(
'dropdown_menus' => array(
'name' => 'dropdown_menus',
'css' => array(
'main' => array(
'border_styles' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select',
'border_radii' => '%%order_class%%.et_pb_module .et_pb_module_inner form.cart .variations td select',
),
'important' => 'all',
),
'label_prefix' => esc_html__( 'Dropdown Menus', 'et_builder' ),
'use_radius' => false,
),
),
'font_field' => array(
'css' => array(
'main' => array(
'%%order_class%% select',
),
'hover' => array(
'%%order_class%% select:hover',
),
'important' => 'all',
),
'font_size' => array(
'default' => '12px',
),
'hide_line_height' => true,
'hide_text_align' => true,
),
),
),
);
$this->custom_css_fields = array(
'fields' => array(
'label' => esc_html__( 'Fields', 'et_builder' ),
'selector' => 'input',
),
'dropdown_menus' => array(
'label' => esc_html__( 'Dropdown Menus', 'et_builder' ),
'selector' => 'select',
),
'buttons' => array(
'label' => esc_html__( 'Buttons', 'et_builder' ),
'selector' => '.button',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__add_to_cart',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__add_to_cart',
),
)
),
'show_quantity' => array(
'label' => esc_html__( 'Show Quantity Field', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether the quantity field should be added before the Add to Cart button.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'show_stock' => array(
'label' => esc_html__( 'Show Stock', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether the stock (displayed when product inventory is managed) should be visible or not', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'__add_to_cart' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Add_To_Cart',
'get_add_to_cart',
),
'computed_depends_on' => array(
'product',
'product_filter',
),
'computed_minimum' => array(
'product',
),
),
);
return $fields;
}
/**
* Get add to cart markup as string
*
* @since 4.4.0 Fixed compatibility w/ WooCommerce Product Add-ons
* @see https://github.com/elegantthemes/Divi/issues/19116
*
* @param array $args Additional arguments.
*
* @return string
*/
public static function get_add_to_cart( $args = array() ) {
return et_builder_wc_render_module_template(
'woocommerce_template_single_add_to_cart',
$args,
array( 'product', 'post' )
);
}
/**
* Gets the Button classname.
*
* @used-by ET_Builder_Module_Helper_Woocommerce_Modules::add_custom_button_icons()
*
* @return string
*/
public function get_button_classname() {
return 'single_add_to_cart_button';
}
/**
* Adds Multi view attributes to the Outer wrapper.
*
* Since we do not have control over the WooCommerce Breadcrumb markup, we inject Multi view
* attributes on to the Outer wrapper.
*
* @param array $outer_wrapper_attrs
*
* @return array
*/
public function add_multi_view_attrs( $outer_wrapper_attrs ) {
$multi_view = et_pb_multi_view_options( $this );
$multi_view_attrs = $multi_view->render_attrs(
array(
'classes' => array(
'et_pb_hide_input_quantity' => array(
'show_quantity' => 'off',
),
'et_pb_hide_stock' => array(
'show_stock' => 'off',
),
),
),
false,
null,
true
);
if ( $multi_view_attrs && is_array( $multi_view_attrs ) ) {
$outer_wrapper_attrs = array_merge( $outer_wrapper_attrs, $multi_view_attrs );
}
return $outer_wrapper_attrs;
}
/**
* Calculates any required additional CSS.
*
* Dropdown menu's Bottom & Left margin affects the Dropdown arrow placement.
* This is handled using additional CSS.
*
* @param array $attrs
* @param string $render_slug
*
* @since 4.3.4
*/
public function add_additional_css( $attrs, $render_slug ) {
if ( ! is_array( $attrs ) || empty( $attrs ) ) {
return;
}
$prop = 'dropdown_menus_custom_margin';
$values = et_pb_responsive_options()->get_property_values( $attrs, $prop );
$hover_value = et_pb_hover_options()->get_value( $prop, $attrs, '' );
$processed_values = array();
foreach ( $values as $device => $value ) {
if ( empty( $value ) ) {
continue;
}
$processed_values[ $device ] = $this->calculate_dropdown_arrow_margin( $value );
}
// Generate style for desktop, tablet, and phone.
et_pb_responsive_options()->declare_responsive_css(
$processed_values,
'%%order_class%% form.cart .variations td.value span:after',
$render_slug
);
}
/**
* Calculates Dropdown's arrow margin values.
*
* The Dropdown's arrow margin values depend on the actual
* Dropdown margin values.
*
* @since 4.3.4
*
* @param $value
*
* @return string
*/
public function calculate_dropdown_arrow_margin( $value ) {
$dropdown_margin = explode( '|', $value );
$dropdown_bottom_margin = empty( $dropdown_margin[2] ) ? '0px' : $dropdown_margin[2];
$dropdown_left_margin = empty( $dropdown_margin[3] ) ? '0px' : $dropdown_margin[3];
$declarations = array(
sprintf( 'margin-top: calc( 3px - %s )', $dropdown_bottom_margin ),
sprintf( 'right: calc( 10px - %s )', $dropdown_left_margin ),
);
// The last declaration wouldn't have the `;`. So appending manually.
return implode( ';', $declarations ) . ';';
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
$multi_view = et_pb_multi_view_options( $this );
$use_focus_border_color = $this->props['use_focus_border_color'];
// Module classnames.
if ( 'on' !== $multi_view->get_value( 'show_quantity' ) ) {
$this->add_classname( 'et_pb_hide_input_quantity' );
}
if ( 'on' !== $multi_view->get_value( 'show_stock' ) ) {
$this->add_classname( 'et_pb_hide_stock' );
}
if ( 'on' === $use_focus_border_color ) {
$this->add_classname( 'et_pb_with_focus_border' );
}
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
ET_Builder_Module_Helper_Woocommerce_Modules::process_custom_button_icons( $render_slug, $this );
$this->add_classname( $this->get_text_orientation_classname() );
$this->add_additional_css( $this->props, $render_slug );
add_filter( "et_builder_module_{$render_slug}_outer_wrapper_attrs", array( $this, 'add_multi_view_attrs' ) );
$output = self::get_add_to_cart( $this->props );
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Add_To_Cart();

View File

@ -0,0 +1,346 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Additional_Info class
*
* The ET_Builder_Module_Woocommerce_Additional_Info Class is responsible for rendering the
* Additional markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Additional Info component.
*/
class ET_Builder_Module_Woocommerce_Additional_Info extends ET_Builder_Module {
/**
* Initialize.
*
* @since 4.0.6 Implemented Attribute Row, Title and Body Custom CSS fields.
*/
public function init() {
$this->name = esc_html__( 'Woo Additional Info', 'et_builder' );
$this->plural = esc_html__( 'Woo Additional Info', 'et_builder' );
$this->slug = 'et_pb_wc_additional_info';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
'elements' => et_builder_i18n( 'Elements' ),
),
),
'advanced' => array(
'toggles' => array(
'text' => array(
'title' => et_builder_i18n( 'Text' ),
'priority' => 45,
'tabbed_subtoggles' => true,
'bb_icons_support' => true,
'sub_toggles' => array(
'p' => array(
'name' => 'P',
'icon' => 'text-left',
),
'a' => array(
'name' => 'A',
'icon' => 'text-link',
),
),
),
'header' => array(
'title' => esc_html__( 'Title Text', 'et_builder' ),
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'body' => array(
'label' => et_builder_i18n( 'Text' ),
'css' => array(
'main' => '%%order_class%% td',
'important' => array( 'line-height' ),
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.5em',
),
'toggle_slug' => 'text',
'sub_toggle' => 'p',
'font' => array(
'default' => '||on||||||',
),
'hide_text_align' => true,
),
'link' => array(
'label' => et_builder_i18n( 'Link' ),
'css' => array(
'main' => '%%order_class%% a',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.5em',
),
'toggle_slug' => 'text',
'sub_toggle' => 'a',
'hide_text_align' => true,
),
'header' => array(
'label' => et_builder_i18n( 'Title' ),
'css' => array(
'main' => '%%order_class%% h2',
),
'font_size' => array(
'default' => '26px',
),
'line_height' => array(
'default' => '1em',
),
'toggle_slug' => 'header',
),
'attribute' => array(
'label' => esc_html__( 'Attribute', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% th',
'important' => 'all',
'text_align' => '%%order_class%% th, %%order_class%% td',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.5em',
),
'font' => array(
'default' => '|700|||||||',
),
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
'text' => array(
'css' => array(
'text_orientation' => '%%order_class%%',
),
'use_background_layout' => true,
'sub_toggle' => 'p',
'options' => array(
'text_orientation' => array(
'default' => 'left',
),
'background_layout' => array(
'default' => 'light',
'hover' => 'tabs',
),
),
),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options.
'default' => false,
),
'button' => false,
);
$this->custom_css_fields = array(
'title_text' => array(
'label' => esc_html__( 'Title Text', 'et_builder' ),
'selector' => 'h2',
),
'content_area' => array(
'label' => esc_html__( 'Content Area', 'et_builder' ),
'selector' => '.shop_attributes',
),
'attribute_row' => array(
'label' => esc_html__( 'Attribute Row', 'et_builder' ),
'selector' => '.shop_attributes .woocommerce-product-attributes-item',
),
'attribute_title' => array(
'label' => esc_html__( 'Attribute Title', 'et_builder' ),
'selector' => '.shop_attributes .woocommerce-product-attributes-item__label',
),
'attribute_text' => array(
'label' => esc_html__( 'Attribute Body', 'et_builder' ),
'selector' => '.shop_attributes .woocommerce-product-attributes-item__value',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__additional_info',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__additional_info',
),
)
),
'show_title' => array(
'label' => esc_html__( 'Show Title', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose to display the title.', 'et_builder' ),
'computed_affects' => array(
'__additional_info',
),
'mobile_options' => true,
'hover' => 'tabs',
),
'__additional_info' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Additional_Info',
'get_additional_info',
),
'computed_depends_on' => array(
'product',
'product_filter',
'show_title',
),
'computed_minimum' => array(
'product',
'show_title',
),
),
);
return $fields;
}
/**
* Get additional information
*
* @param array $args Additional arguments.
*
* @return string
*/
public static function get_additional_info( $args = array() ) {
$defaults = array(
'show_title' => 'on',
);
$args = wp_parse_args( $args, $defaults );
$display_title = 'on' === $args['show_title'];
/*
* WooCommerce's default additional information template conditionally display heading
* markup based on filterable value which can be plugged and unplugged here.
*/
if ( ! $display_title ) {
add_filter( 'woocommerce_product_additional_information_heading', '__return_false' );
}
$additional_info = et_builder_wc_render_module_template(
'woocommerce_product_additional_information_tab',
$args
);
if ( ! $display_title ) {
remove_filter( 'woocommerce_product_additional_information_heading', '__return_false' );
}
return $additional_info;
}
/**
* Adds Multi view attributes to the Outer wrapper.
*
* Since we do not have control over the WooCommerce Additional Info markup, we inject Multi
* view attributes on to the Outer wrapper.
*
* @param array $outer_wrapper_attrs
* @param ET_Builder_Module_Woocommerce_Additional_Info $this_class
*
* @return array
*/
public function add_multi_view_attrs( $outer_wrapper_attrs, $this_class ) {
$multi_view = et_pb_multi_view_options( $this_class );
$multi_view_attrs = $multi_view->render_attrs(
array(
'classes' => array(
'et_pb_hide_title' => array(
'show_title' => 'off',
),
),
),
false,
null,
true
);
if ( $multi_view_attrs && is_array( $multi_view_attrs ) ) {
$outer_wrapper_attrs = array_merge( $outer_wrapper_attrs, $multi_view_attrs );
}
return $outer_wrapper_attrs;
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
$this->add_classname( $this->get_text_orientation_classname() );
add_filter( "et_builder_module_{$render_slug}_outer_wrapper_attrs", array( $this, 'add_multi_view_attrs' ), 10, 2 );
$output = self::get_additional_info( $this->props );
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Additional_Info();

View File

@ -0,0 +1,365 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Breadcrumb class
*
* The ET_Builder_Module_Woocommerce_Breadcrumb Class is responsible for rendering the
* Breadcrumb markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Breadcrumb component.
*/
class ET_Builder_Module_Woocommerce_Breadcrumb extends ET_Builder_Module {
/**
* Home URL.
*
* @var string
*/
public static $home_url;
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Breadcrumb', 'et_builder' );
$this->plural = esc_html__( 'Woo Breadcrumbs', 'et_builder' );
$this->slug = 'et_pb_wc_breadcrumb';
$this->vb_support = 'on';
$this->main_css_element = '%%order_class%% .woocommerce-breadcrumb';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => array(
'title' => et_builder_i18n( 'Content' ),
),
),
),
'advanced' => array(
'toggles' => array(
'text' => array(
'title' => et_builder_i18n( 'Text' ),
'priority' => 45,
'tabbed_subtoggles' => true,
'bb_icons_support' => true,
'sub_toggles' => array(
'p' => array(
'name' => 'P',
'icon' => 'text-left',
),
'a' => array(
'name' => 'A',
'icon' => 'text-link',
),
),
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'body' => array(
'label' => et_builder_i18n( 'Text' ),
'css' => array(
'main' => '%%order_class%%, %%order_class%% .et_pb_module_inner, %%order_class%% .woocommerce-breadcrumb, %%order_class%% .woocommerce-breadcrumb a',
'text_align' => '%%order_class%%',
),
'font_size' => array(
'default' => '13px',
),
'line_height' => array(
'default' => '1.7em',
),
'toggle_slug' => 'text',
'sub_toggle' => 'p',
'hide_text_align' => true,
),
'link' => array(
'label' => et_builder_i18n( 'Link' ),
'css' => array(
'main' => '%%order_class%%.et_pb_wc_breadcrumb a, %%order_class%%.et_pb_wc_breadcrumb .woocommerce-breadcrumb a',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.7em',
),
'toggle_slug' => 'text',
'sub_toggle' => 'a',
'hide_text_align' => true,
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
),
'margin_padding' => array(
'css' => array(
'margin' => '%%order_class%% .woocommerce-breadcrumb',
'important' => 'all',
),
),
'text' => array(
'use_background_layout' => false,
'sub_toggle' => 'p',
'options' => array(
'text_orientation' => array(
'default' => 'left',
),
'background_layout' => array(
'default' => 'light',
),
),
),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options.
'default' => false,
),
'button' => false,
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* Includes any Module specific fields.
*
* Fields from Parent module that may be not needed are also removed.
*
* @since 4.0 Removed Hover options from Breadcrumb URL.
*
* @return array Parent's fields w/ module specific fields.
*/
public function get_fields() {
// Content Toggle.
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__breadcrumb',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__breadcrumb',
),
)
),
'breadcrumb_home_text' => array(
'label' => esc_html__( 'Home Text', 'et_builder' ),
'type' => 'text',
'option_category' => 'basic_option',
'description' => esc_html__( 'Here you can create the breadcrumb text for the Home page.', 'et_builder' ),
'toggle_slug' => 'main_content',
'default' => __( 'Home', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
'dynamic_content' => 'text',
),
'breadcrumb_home_url' => array(
'label' => esc_html__( 'Home Link', 'et_builder' ),
'type' => 'text',
'option_category' => 'basic_option',
'description' => esc_html__( 'Here you can create the link for the Home page.', 'et_builder' ),
'toggle_slug' => 'main_content',
'default' => get_home_url(),
'mobile_options' => true,
'dynamic_content' => 'url',
),
'breadcrumb_separator' => array(
'label' => esc_html__( 'Separator', 'et_builder' ),
'type' => 'text',
'option_category' => 'basic_option',
'description' => esc_html__( 'Here you can set the Breadcrumb separator.', 'et_builder' ),
'toggle_slug' => 'main_content',
'default' => ' / ',
'dynamic_content' => 'text',
),
'__breadcrumb' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Breadcrumb',
'get_breadcrumb',
),
'computed_depends_on' => array(
'product',
'product_filter',
),
),
);
return $fields;
}
/**
* Get breadcrumb
*
* @since 3.29
*
* @param array $args Additional arguments.
*
* @return string
*/
public static function get_breadcrumb( $args = array() ) {
global $post, $product, $wp_query;
$defaults = array(
'product' => 'current',
'breadcrumb_home_text' => __( 'Home', 'et_builder' ),
'breadcrumb_home_url' => get_home_url(),
'breadcrumb_separator' => '/',
);
$args = wp_parse_args( $args, $defaults );
$args['breadcrumb_separator'] = esc_html( $args['breadcrumb_separator'] );
/*
* Replace update-able string in visual builder with text placeholder which can be
* easily replaced by builder for quick interaction on field change
*
* The `et_fb_is_resolve_post_content_callback_ajax()` check is added to enable
* Product Breadcrumb dynamic content field.
*
* Breadcrumb customization is not required when resolving dynamic content field.
* Hence we exclude customizations if the AJAX request is to resolve dynamic content fields.
*/
$main_query_post_id = ET_Post_Stack::get_main_post_id();
$layout_post_id = ET_Builder_Element::get_layout_id();
$is_fb = et_core_is_fb_enabled() && $main_query_post_id === $layout_post_id;
if ( ! et_fb_is_resolve_post_content_callback_ajax() && ( $is_fb || et_fb_is_builder_ajax() || et_fb_is_computed_callback_ajax() ) ) {
$args = wp_parse_args(
array(
'breadcrumb_home_text' => '%HOME_TEXT%',
'breadcrumb_home_url' => '%HOME_URL%',
'breadcrumb_separator' => '%SEPARATOR%',
),
$args
);
}
// Update home URL which is rendered inside breadcrumb function and pluggable via filter.
self::$home_url = $args['breadcrumb_home_url'];
add_filter(
'woocommerce_breadcrumb_home_url',
array( 'ET_Builder_Module_Woocommerce_Breadcrumb', 'modify_home_url' )
);
$breadcrumb = et_builder_wc_render_module_template(
'woocommerce_breadcrumb',
$args,
array(
'product',
'post',
'wp_query',
)
);
// Reset home URL.
self::$home_url = get_home_url();
remove_filter(
'woocommerce_breadcrumb_home_url',
array( 'ET_Builder_Module_Woocommerce_Breadcrumb', 'modify_home_url' )
);
return $breadcrumb;
}
/**
* Modify home url
*
* @since 3.29
*
* @return string
*/
public static function modify_home_url() {
return self::$home_url;
}
/**
* Adds Multi view attributes to the Inner wrapper.
*
* Since we do not have control over the WooCommerce Breadcrumb markup, we inject Multi view
* attributes on to the Inner wrapper.
*
* Inner wrapper is selected to inject the Multi view attributes because, there is already
* a lot going on w/ the Outer wrapper.
*
* @param array $inner_wrapper_attrs
*
* @return array
*/
public function add_multi_view_attrs( $inner_wrapper_attrs ) {
$multi_view = et_pb_multi_view_options( $this );
/*
* Breadcrumb separator cannot have Multi-view options as it is not enclosed in a HTML tag.
* Element being enclose in a tag is essential for the Multi-view options to work.
*/
$multi_view_attrs = $multi_view->render_attrs(
array(
'content' => '{{breadcrumb_home_text}}',
'attrs' => array(
'href' => '{{breadcrumb_home_url}}',
'data-breadcrumb-separator' => '{{breadcrumb_separator}}',
),
'target' => '%%order_class%% .woocommerce-breadcrumb a:first-child',
),
false,
null,
true
);
if ( $multi_view_attrs && is_array( $multi_view_attrs ) ) {
$inner_wrapper_attrs = array_merge( $inner_wrapper_attrs, $multi_view_attrs );
}
return $inner_wrapper_attrs;
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
$this->add_classname( $this->get_text_orientation_classname() );
$output = self::get_breadcrumb( $this->props );
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
add_filter( "et_builder_module_{$render_slug}_inner_wrapper_attrs", array( $this, 'add_multi_view_attrs' ) );
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Breadcrumb();

View File

@ -0,0 +1,319 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Cart_Notice class
*
* The ET_Builder_Module_Woocommerce_Cart_Notice Class is responsible for rendering the
* Cart Notice markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Cart Notice component.
*/
class ET_Builder_Module_Woocommerce_Cart_Notice extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Cart Notice', 'et_builder' );
$this->plural = esc_html__( 'Woo Cart Notices', 'et_builder' );
$this->slug = 'et_pb_wc_cart_notice';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
),
),
'advanced' => array(
'toggles' => array(
'text' => array(
'title' => et_builder_i18n( 'Text' ),
'priority' => 45,
),
),
),
);
$this->main_css_element = '%%order_class%% .woocommerce-message';
$this->advanced_fields = array(
'fonts' => array(
'body' => array(
'label' => et_builder_i18n( 'Text' ),
'css' => array(
'main' => '%%order_class%% .woocommerce-message',
// CPT style uses `!important` so outputting important is inevitable.
'important' => 'all',
),
'font_size' => array(
'default' => '18px',
),
'line_height' => array(
'default' => '1.7em',
),
'toggle_slug' => 'text',
'hide_text_align' => true,
),
),
'max_width' => array(
'css' => array(
'module_alignment' => '%%order_class%%.et_pb_module',
),
),
'margin_padding' => array(
'css' => array(
'padding' => '%%order_class%% .woocommerce-message',
'important' => 'all',
),
'custom_padding' => array(
'default' => '15px|15px|15px|15px|false|false',
),
'custom_margin' => array(
'default' => '0em|0em|2em|0em|false|false',
),
),
'button' => array(
'button' => array(
'label' => et_builder_i18n( 'Button' ),
'css' => array(
'main' => '%%order_class%% .wc-forward',
'important' => true,
),
'use_alignment' => false,
'border_width' => array(
'default' => '0px',
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% .wc-forward',
),
),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
),
),
'text' => array(
'use_background_layout' => true,
'css' => array(
'main' => '%%order_class%%',
'text_shadow' => '%%order_class%%',
),
'options' => array(
'text_orientation' => array(
'default' => 'left',
),
'background_layout' => array(
'default' => 'dark',
),
),
),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options.
'default' => false,
),
'background' => array(
'css' => array(
// Defined explicitly to solve
// @see https://github.com/elegantthemes/Divi/issues/17200#issuecomment-542140907
'main' => '%%order_class%% .woocommerce-message',
// Important is required to override
// Appearance ⟶ Customize ⟶ Color schemes styles.
'important' => 'all',
),
),
'border' => array(
'css' => array(
'important' => true,
),
),
);
$this->custom_css_fields = array(
'text' => array(
'label' => et_builder_i18n( 'Text' ),
'selector' => '.woocommerce-message',
),
'button' => array(
'label' => et_builder_i18n( 'Button' ),
'selector' => '.wc-forward',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
/*
* Disable default cart notice if needed. Priority need to be set at 100 to
* that the callback is being called after modules are being loaded.
*
* See: et_builder_load_framework()
*/
add_action(
'wp',
array(
'ET_Builder_Module_Woocommerce_Cart_Notice',
'disable_default_notice',
),
100
);
// Clear notices array which was modified during render.
add_action( 'wp_footer', array( 'ET_Builder_Module_Woocommerce_Cart_Notice', 'clear_notices' ) );
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__cart_notice',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__cart_notice',
),
)
),
'__cart_notice' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Cart_Notice',
'get_cart_notice',
),
'computed_depends_on' => array(
'product',
'product_filter',
),
'computed_minumum' => array(
'product',
),
),
);
return $fields;
}
/**
* Disable default WooCommerce notice if current page's main query post content contains
* Cart Notice module to prevent duplicate cart notices being rendered AND to make Cart Notice
* module can render the notices correctly (notices are cleared once they are rendered)
*
* @since 3.29
*/
public static function disable_default_notice() {
global $post;
$remove_default_notices = false;
$tb_layouts = et_theme_builder_get_template_layouts();
$tb_layout_types = et_theme_builder_get_layout_post_types();
// Check if a TB layout outputs the notices.
foreach ( $tb_layout_types as $post_type ) {
$id = et_()->array_get( $tb_layouts, array( $post_type, 'id' ), 0 );
$enabled = et_()->array_get( $tb_layouts, array( $post_type, 'enabled' ), 0 );
if ( ! $id || ! $enabled ) {
continue;
}
$content = get_post_field( 'post_content', $id );
if ( has_shortcode( $content, 'et_pb_wc_cart_notice' ) ) {
$remove_default_notices = true;
break;
}
}
// Check if the product itself outputs the notices.
if ( isset( $post->post_content ) && has_shortcode( $post->post_content, 'et_pb_wc_cart_notice' ) ) {
$remove_default_notices = true;
}
if ( $remove_default_notices ) {
remove_action( 'woocommerce_before_single_product', 'woocommerce_output_all_notices', 10 );
}
}
/**
* We update Woo Notices array during modules render and need to cleat it
* after Woo Product is fully rendered to avoid duplicated notifications on
* subsequent page loads.
*/
public static function clear_notices() {
if ( ! empty( WC()->session ) ) {
WC()->session->set( 'wc_notices', null );
}
}
/**
* Gets the Cart notice markup.
*
* @param array $args Additional arguments.
*
* @return string
*/
public static function get_cart_notice( $args = array() ) {
if ( et_fb_enabled() || et_fb_is_builder_ajax() || et_fb_is_computed_callback_ajax() ) {
return et_builder_wc_render_module_template( 'wc_print_notice', $args );
}
return et_builder_wc_render_module_template( 'wc_print_notices', $args );
}
function get_button_classname() {
return 'wc-forward';
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
/*
* In front end, do not print cart notice module if there is no notices exist.
*
* There is no custom style rendered below (to make sure that styles are correctly cached
* nevertheless), thus it is fine to exit early;
*/
if ( ! empty( WC()->session ) && empty( WC()->session->get( 'wc_notices', array() ) ) ) {
return '';
}
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
ET_Builder_Module_Helper_Woocommerce_Modules::process_custom_button_icons( $render_slug, $this );
$this->add_classname( $this->get_text_orientation_classname() );
$output = self::get_cart_notice( $this->props );
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Cart_Notice();

View File

@ -0,0 +1,540 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Description class
*
* The ET_Builder_Module_Woocommerce_Description Class is responsible for rendering the
* Description markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Description component.
*/
class ET_Builder_Module_Woocommerce_Description extends ET_Builder_Module {
/**
* Initialize.
*
* @since 4.0.6 Updated `toggle_slug` to avoid empty Tabs in Text OG.
*/
public function init() {
$this->name = esc_html__( 'Woo Description', 'et_builder' );
$this->plural = esc_html__( 'Woo Descriptions', 'et_builder' );
$this->slug = 'et_pb_wc_description';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
),
),
'advanced' => array(
'toggles' => array(
'body' => array(
'title' => et_builder_i18n( 'Text' ),
'priority' => 45,
'tabbed_subtoggles' => true,
'bb_icons_support' => true,
'sub_toggles' => array(
'p' => array(
'name' => 'P',
'icon' => 'text-left',
),
'a' => array(
'name' => 'A',
'icon' => 'text-link',
),
'ul' => array(
'name' => 'UL',
'icon' => 'list',
),
'ol' => array(
'name' => 'OL',
'icon' => 'numbered-list',
),
'quote' => array(
'name' => 'QUOTE',
'icon' => 'text-quote',
),
),
),
'header' => array(
'title' => esc_html__( 'Heading Text', 'et_builder' ),
'priority' => 49,
'tabbed_subtoggles' => true,
'sub_toggles' => array(
'h1' => array(
'name' => 'H1',
'icon' => 'text-h1',
),
'h2' => array(
'name' => 'H2',
'icon' => 'text-h2',
),
'h3' => array(
'name' => 'H3',
'icon' => 'text-h3',
),
'h4' => array(
'name' => 'H4',
'icon' => 'text-h4',
),
'h5' => array(
'name' => 'H5',
'icon' => 'text-h5',
),
'h6' => array(
'name' => 'H6',
'icon' => 'text-h6',
),
),
),
'width' => array(
'title' => et_builder_i18n( 'Sizing' ),
'priority' => 65,
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'body' => array(
'label' => et_builder_i18n( 'Text' ),
'css' => array(
'line_height' => '%%order_class%% p',
'color' => '%%order_class%%.et_pb_wc_description',
),
'line_height' => array(
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
),
'font_size' => array(
'default' => absint( et_get_option( 'body_font_size', '14' ) ) . 'px',
),
'toggle_slug' => 'body',
'sub_toggle' => 'p',
'hide_text_align' => true,
),
'link' => array(
'label' => et_builder_i18n( 'Link' ),
'css' => array(
'main' => '%%order_class%% a',
'color' => '%%order_class%%.et_pb_wc_description a',
),
'line_height' => array(
'default' => '1em',
),
'font_size' => array(
'default' => absint( et_get_option( 'body_font_size', '14' ) ) . 'px',
),
'toggle_slug' => 'body',
'sub_toggle' => 'a',
'hide_text_align' => true,
),
'ul' => array(
'label' => esc_html__( 'Unordered List', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% ul',
'color' => '%%order_class%%.et_pb_wc_description ul',
'line_height' => '%%order_class%% ul li',
),
'line_height' => array(
'default' => '1em',
),
'font_size' => array(
'default' => '14px',
),
'toggle_slug' => 'body',
'sub_toggle' => 'ul',
),
'ol' => array(
'label' => esc_html__( 'Ordered List', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% ol',
'color' => '%%order_class%%.et_pb_wc_description ol',
'line_height' => '%%order_class%% ol li',
),
'line_height' => array(
'default' => '1em',
),
'font_size' => array(
'default' => '14px',
),
'toggle_slug' => 'body',
'sub_toggle' => 'ol',
),
'quote' => array(
'label' => esc_html__( 'Blockquote', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% blockquote',
'color' => '%%order_class%%.et_pb_wc_description blockquote',
),
'line_height' => array(
'default' => '1em',
),
'font_size' => array(
'default' => '14px',
),
'toggle_slug' => 'body',
'sub_toggle' => 'quote',
),
'header' => array(
'label' => esc_html__( 'Heading', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% h1',
),
'font_size' => array(
'default' => absint( et_get_option( 'body_header_size', '30' ) ) . 'px',
),
'line_height' => array(
'default' => '1em',
),
'toggle_slug' => 'header',
'sub_toggle' => 'h1',
),
'header_2' => array(
'label' => esc_html__( 'Heading 2', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% h2',
),
'font_size' => array(
'default' => '26px',
),
'line_height' => array(
'default' => '1em',
),
'toggle_slug' => 'header',
'sub_toggle' => 'h2',
),
'header_3' => array(
'label' => esc_html__( 'Heading 3', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% h3',
),
'font_size' => array(
'default' => '22px',
),
'line_height' => array(
'default' => '1em',
),
'toggle_slug' => 'header',
'sub_toggle' => 'h3',
),
'header_4' => array(
'label' => esc_html__( 'Heading 4', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% h4',
),
'font_size' => array(
'default' => '18px',
),
'line_height' => array(
'default' => '1em',
),
'toggle_slug' => 'header',
'sub_toggle' => 'h4',
),
'header_5' => array(
'label' => esc_html__( 'Heading 5', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% h5',
),
'font_size' => array(
'default' => '16px',
),
'line_height' => array(
'default' => '1em',
),
'toggle_slug' => 'header',
'sub_toggle' => 'h5',
),
'header_6' => array(
'label' => esc_html__( 'Heading 6', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% h6',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1em',
),
'toggle_slug' => 'header',
'sub_toggle' => 'h6',
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
'text' => array(
'use_background_layout' => true,
'sub_toggle' => 'p',
'toggle_slug' => 'body',
'options' => array(
'text_orientation' => array(
'default' => 'left',
),
'background_layout' => array(
'default' => 'light',
'hover' => 'tabs',
),
),
),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options.
'default' => false,
),
'button' => false,
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__description',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__description',
),
)
),
'description_type' => array(
'label' => esc_html__( 'Description Type', 'et_builder' ),
'type' => 'select',
'option_category' => 'configuration',
'options' => array(
'description' => esc_html__( 'Description', 'et_builder' ),
'short_description' => esc_html__( 'Short Description', 'et_builder' ),
),
'toggle_slug' => 'main_content',
'description' => esc_html__( 'Here you can choose between Description and short description to display.', 'et_builder' ),
'default_on_front' => 'short_description',
'mobile_options' => true,
'hover' => 'tabs',
'computed_affects' => array(
'__description',
),
),
'__description' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Description',
'get_description',
),
'computed_depends_on' => array(
'product',
'product_filter',
'description_type',
),
'computed_minimum' => array(
'product',
),
),
);
return $fields;
}
/**
* Gets the Description
*
* @since 3.29
*
* @param array $args Additional arguments.
*
* @return string
*/
public static function get_description( $args = array(), $conditional_tags = array(), $current_page = array() ) {
$defaults = array(
'product' => 'current',
'description_type' => 'short_description',
);
$args = wp_parse_args( $args, $defaults );
// Theme builder's description placeholder; short-circuit is cleaner and more efficient than
// global object element being modified. NOTE: $conditional_tags element value is string
if ( et_builder_tb_enabled() || 'true' === et_()->array_get( $conditional_tags, 'is_tb', false ) ) {
$placeholders = et_theme_builder_wc_placeholders();
$description = 'short_description' === $args['description_type'] ?
$placeholders['short_description'] :
$placeholders['description'];
// Description comes from Post Content or Excerpt or Custom Field which is processed by WP and should be properly escaped during save.
return et_core_intentionally_unescaped( $description, 'html' );
}
$post_id = ET_Builder_Module_Helper_Woocommerce_Modules::get_product_id( $args['product'] );
$post = get_post( $post_id );
if ( ! ( $post instanceof WP_Post ) ) {
return '';
}
if ( 'description' === $args['description_type'] ) {
// If builder is not used on given post, display post content.
if ( ! et_pb_is_pagebuilder_used( $post_id ) ) {
/** This filter is documented in wp-includes/post-template.php */
$description = apply_filters( 'the_content', $post->post_content );
} else {
$description = get_post_meta( $post->ID, ET_BUILDER_WC_PRODUCT_LONG_DESC_META_KEY, true );
// Cannot use `the_content` filter since it adds content wrapper.
// Content wrapper added at
// `includes/builder/core.php`::et_builder_add_builder_content_wrapper()
// This filter is documented at
// includes/builder/feature/woocommerce-modules.php
$description = apply_filters( 'et_builder_wc_description', $description );
}
} else {
$description = apply_filters( 'woocommerce_short_description', $post->post_excerpt );
}
// Description comes from Post Content or Excerpt or Custom Field which is processed by WP and should be properly escaped during save.
return et_core_intentionally_unescaped( $description, 'html' );
}
/**
* Adds Multi view attributes to the Outer wrapper.
*
* Since we do not have control over the WooCommerce Breadcrumb markup, we inject Multi view
* attributes on to the Outer wrapper.
*
* @param array $outer_wrapper_attrs
* @param ET_Builder_Module_Woocommerce_Description $this_class
*
* @return array
*/
public function add_multi_view_attrs( $outer_wrapper_attrs, $this_class ) {
$multi_view = et_pb_multi_view_options( $this_class );
$contexts = array(
'content' => '{{description_type}}',
'target' => '%%order_class%% .et_pb_module_inner',
);
$multi_view_attrs = $multi_view->render_attrs( $contexts, false, null, true );
if ( $multi_view_attrs && is_array( $multi_view_attrs ) ) {
$outer_wrapper_attrs = array_merge( $outer_wrapper_attrs, $multi_view_attrs );
}
return $outer_wrapper_attrs;
}
/**
* Filter multi view value.
*
* @see ET_Builder_Module_Helper_MultiViewOptions::filter_value
*
* @param mixed $raw_value Props raw value.
* @param array $args {
* Context data.
*
* @type string $context Context param: content,
* attrs, visibility, classes.
* @type string $name Module options props name.
* @type string $mode Current data mode: desktop,
* hover, tablet, phone.
* @type string $attr_key Attribute key for attrs
* context data. Example: src, class, etc.
* @type string $attr_sub_key Attribute sub key that
* availabe when passing attrs value as array such as styes. Example: padding-top,
* margin-botton, etc.
* }
*
* @param ET_Builder_Module_Helper_MultiViewOptions $multi_view Multiview object instance.
*
* @return mixed
*/
public function multi_view_filter_value( $raw_value, $args, $multi_view ) {
if ( empty( $multi_view->get_module_props() ) ) {
return $raw_value;
}
$maybe_product = et_()->array_get( $multi_view->get_module_props(), 'product', '0' );
$product = ET_Builder_Module_Helper_Woocommerce_Modules::get_product( $maybe_product );
if ( ! $product ) {
return $raw_value;
}
$name = et_()->array_get( $args, 'name', '' );
$mode = et_()->array_get( $args, 'mode', '' );
$post = get_post( $product->get_id() );
// Validating $post validates $post_id. No separate $post_id validation is required.
if ( 'description_type' !== $name || ! $post ) {
return $raw_value;
}
if ( 'description' === $multi_view->get_inherit_value( $name, $mode ) ) {
if ( ! et_pb_is_pagebuilder_used( $product->get_id() ) ) {
$raw_value = $post->post_content;
} else {
$raw_value = get_post_meta( $post->ID, ET_BUILDER_WC_PRODUCT_LONG_DESC_META_KEY, true );
}
} else {
$raw_value = $post->post_excerpt;
}
return $raw_value;
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
$this->add_classname( $this->get_text_orientation_classname() );
add_filter( "et_builder_module_{$render_slug}_outer_wrapper_attrs", array( $this, 'add_multi_view_attrs' ), 10, 2 );
$output = self::get_description( $this->props );
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Description();

View File

@ -0,0 +1,293 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Description class
*
* The ET_Builder_Module_Woocommerce_Description Class is responsible for rendering the
* Description markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
if ( ! class_exists( 'ET_Builder_Module_Gallery' ) ) {
require_once ET_BUILDER_DIR_RESOLVED_PATH . '/module/Gallery.php';
}
/**
* Class representing WooCommerce Gallery component.
*/
class ET_Builder_Module_Woocommerce_Gallery extends ET_Builder_Module_Gallery {
/**
* Modify properties defined on base module's (gallery) init()
*
* @since 3.29
*/
public function init() {
parent::init();
$this->name = esc_html__( 'Woo Gallery', 'et_builder' );
$this->plural = esc_html__( 'Woo Galleries', 'et_builder' );
$this->slug = 'et_pb_wc_gallery';
$this->main_css_element = '%%order_class%%';
// Intentionally removing inherited options group.
unset( $this->settings_modal_toggles['general']['toggles']['main_content'] );
// Rename Elements Option group to Content.
$this->settings_modal_toggles['general']['toggles']['elements'] = et_builder_i18n( 'Content' );
// Intentionally removing inherited advanced options group.
$this->advanced_fields['link_options'] = false;
$this->advanced_fields['fonts']['title']['font_size'] = array(
'default' => '18px',
);
$this->advanced_fields['fonts']['title']['line_height'] = array(
'default' => '1em',
);
$this->advanced_fields['fonts']['pagination']['font_size'] = array(
'default' => '16px',
);
$this->advanced_fields['fonts']['pagination']['line_height'] = array(
'default' => '16px',
);
$this->advanced_fields['fonts']['caption']['font_size'] = array(
'default' => '14px',
);
$this->advanced_fields['fonts']['caption']['line_height'] = array(
'default' => '1em',
);
$this->advanced_fields['position_fields'] = array(
'default' => 'relative',
);
$this->custom_css_fields = array(
'gallery_item' => array(
'label' => esc_html__( 'Gallery Item', 'et_builder' ),
'selector' => '.et_pb_gallery_item',
),
'gallery_pagination' => array(
'label' => esc_html__( 'Gallery Pagination', 'et_builder' ),
'selector' => '.et-pb-controllers a',
),
'gallery_pagination_active' => array(
'label' => esc_html__( 'Pagination Active Page', 'et_builder' ),
'selector' => '.et-pb-controllers a.et-pb-active-control',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
// Insert classname to module wrapper.
add_filter(
'et_builder_wc_gallery_classes',
array(
$this,
'add_wc_gallery_classname',
),
10,
2
);
}
/**
* Insert Woo Galleries specific fields and modify fields inherited from base module (gallery)
*
* @return array
*/
public function get_fields() {
/*
* Woo Galleries fields that need to be prepended before fields inherited from gallery
* module.
*/
$product_default = ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default();
$wc_gallery_fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => $product_default,
'toggle_slug' => 'elements',
'computed_affects' => array(
'__gallery',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'toggle_slug' => 'elements',
'computed_affects' => array(
'__gallery',
),
)
),
);
// Base module (gallery) fields.
$fields = parent::get_fields();
// Set the default Layout as Slider.
if ( array_key_exists( 'fullwidth', $fields ) ) {
$fields['fullwidth']['default_on_front'] = 'on';
}
// Prepending WC images field to fields inherited from gallery module (base module).
$fields = array_merge( $wc_gallery_fields, $fields );
// Hide gallery upload image field because module images are set from "Product" field.
$fields['gallery_ids']['type'] = 'hidden';
/*
* Modify `__gallery`'s `computed_callback` attribute so Woo Gallery can insert additional
* arguments to computed callback result.
*/
$fields['__gallery'] = array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Gallery',
'get_wc_gallery',
),
'computed_depends_on' => array(
// Field is hidden because its control is take over by `product` field.
'gallery_ids',
/*
* Fields exist but not being rendered because their options group is hidden
* based on the spec.
*/
'gallery_orderby',
'gallery_captions',
// Exising and visible fields.
'fullwidth',
'orientation',
'show_pagination',
'product',
'product_filter',
),
);
return $fields;
}
/**
* Gets Placeholder ID as Gallery IDs when in TB mode.
*
* @see https://github.com/elegantthemes/Divi/issues/18768
*
* @since 4.10.8
*
* @param array $conditional_tags Conditional Tags.
*
* @return array Array containing placeholder Id when in TB mode. Empty array otherwise.
*/
public static function get_gallery_ids( $conditional_tags ) {
if ( ! is_array( $conditional_tags ) ) {
return array();
}
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
if ( ! $is_tb || ! function_exists( 'wc_placeholder_img_src' ) ) {
return array();
}
$placeholder_src = wc_placeholder_img_src( 'full' );
$placeholder_id = attachment_url_to_postid( $placeholder_src );
if ( 0 === absint( $placeholder_id ) ) {
return array();
}
return array( $placeholder_id );
}
/**
* Computed callback's callback method which adjusted arguments passed to original computed
* callback's callback so the result is suitable for Woo Gallery module
*
* @since 4.10.8 Load Placeholder Image when in TB mode.
* @since 3.29
*
* @param array $args Arguments from Computed Prop AJAX call.
* @param array $conditional_tags Conditional Tags.
* @param array $current_page Current page args.
*
* @return array
*/
public static function get_wc_gallery( $args = array(), $conditional_tags = array(), $current_page = array() ) {
if ( 'current' === $args['product'] && 'true' === et_()->array_get( $conditional_tags, 'is_tb', false ) ) {
et_theme_builder_wc_set_global_objects( $conditional_tags );
global $product;
} else {
// Generate valid `gallery_ids` value based `product` attribute.
$product = ET_Builder_Module_Helper_Woocommerce_Modules::get_product( $args['product'] );
}
$attachment_ids = array();
if ( $product ) {
$featured_image_id = intval( $product->get_image_id() );
$attachment_ids = $product->get_gallery_image_ids();
}
// Load placeholder Image when in TB.
if ( is_array( $attachment_ids ) && empty( $attachment_ids ) ) {
$attachment_ids = self::get_gallery_ids( $conditional_tags );
}
// Modify `gallery_ids` value.
$args['gallery_ids'] = $attachment_ids;
// Don't display Placeholder when no Gallery image is available.
// @see https://github.com/elegantthemes/submodule-builder/pull/6706#issuecomment-542275647
if ( 0 === count( $attachment_ids ) ) {
$args['attachment_id'] = -1;
}
return ET_Builder_Module_Gallery::get_gallery( $args, $conditional_tags, $current_page );
}
/**
* Modify module wrapper's classname
*
* @since 3.29
*
* @param array $classname List of class names.
* @param int $render_count Count of times the module is rendered.
*
* @return array
*/
public function add_wc_gallery_classname( $classname, $render_count ) {
// For gallery to be properly rendered, it needs `et_pb_gallery` classname.
$classname[] = 'et_pb_gallery';
return $classname;
}
/**
* Use ET_Builder_Module_Woocommerce_Gallery::get_wc_gallery() instead of base module's
* ET_Builder_Module_Gallery::get_gallery() method for defining attachment value in
* frontend's `render()` and visual builder's computed callback result
*
* @since 3.29
*
* @param array $args Additional arguments.
*
* @return array
*/
public function get_attachments( $args = array() ) {
$args['product'] = $this->props['product'];
return self::get_wc_gallery( $args );
}
}
new ET_Builder_Module_Woocommerce_Gallery();

View File

@ -0,0 +1,342 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Images class
*
* The ET_Builder_Module_Woocommerce_Images Class is responsible for rendering the
* Image markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Images component.
*/
class ET_Builder_Module_Woocommerce_Images extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Images', 'et_builder' );
$this->slug = 'et_pb_wc_images';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
'elements' => et_builder_i18n( 'Elements' ),
),
),
'advanced' => array(
'toggles' => array(
'image' => et_builder_i18n( 'Image' ),
),
),
);
$this->advanced_fields = array(
'borders' => array(
'default' => array(),
'image' => array(
'css' => array(
'main' => array(
'border_radii' => '%%order_class%% div.images ol.flex-control-thumbs.flex-control-nav li, %%order_class%% .flex-viewport, %%order_class%% .woocommerce-product-gallery--without-images .woocommerce-product-gallery__wrapper, %%order_class%% .woocommerce-product-gallery > div:not(.flex-viewport) .woocommerce-product-gallery__image, %%order_class%% .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper .woocommerce-product-gallery__image, %%order_class%% .woocommerce-product-gallery .woocommerce-product-gallery__wrapper .woocommerce-product-gallery__image',
'border_styles' => '%%order_class%% div.images ol.flex-control-thumbs.flex-control-nav li, %%order_class%% .flex-viewport, %%order_class%% .woocommerce-product-gallery--without-images .woocommerce-product-gallery__wrapper, %%order_class%% .woocommerce-product-gallery > div:not(.flex-viewport) .woocommerce-product-gallery__image, %%order_class%% .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper .woocommerce-product-gallery__image',
),
),
'label_prefix' => et_builder_i18n( 'Image' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
),
),
'box_shadow' => array(
'default' => array(),
'image' => array(
'label' => esc_html__( 'Image Box Shadow', 'et_builder' ),
'option_category' => 'layout',
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'css' => array(
'main' => '%%order_class%% div.images ol.flex-control-thumbs.flex-control-nav li, %%order_class%% .flex-viewport, %%order_class%% .woocommerce-product-gallery--without-images .woocommerce-product-gallery__wrapper, %%order_class%% .woocommerce-product-gallery > div:not(.flex-viewport) .woocommerce-product-gallery__image, %%order_class%% .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper .woocommerce-product-gallery__image',
'overlay' => 'inset',
'important' => true,
),
),
),
'background' => array(),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
'text_shadow' => array(),
'text' => false,
'fonts' => array(
'sale_badge' => array(
'label' => esc_html__( 'Sale Badge', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .et_pb_module_inner span.onsale',
'important' => 'all',
),
'hide_text_align' => true,
'line_height' => array(
'default' => '1.7em',
),
'font_size' => array(
'default' => '20px',
),
'letter_spacing' => array(
'default' => '0px',
),
),
),
'button' => false,
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__images',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__images',
),
)
),
'show_product_image' => array(
'label' => esc_html__( 'Show Featured Image', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether product image should be displayed or not.', 'et_builder' ),
'computed_affects' => array(
'__images',
),
),
'show_product_gallery' => array(
'label' => esc_html__( 'Show Gallery Images', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether product gallery should be displayed or not.', 'et_builder' ),
'computed_affects' => array(
'__images',
),
),
'show_sale_badge' => array(
'label' => esc_html__( 'Show Sale Badge', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether Sale Badge should be displayed or not.', 'et_builder' ),
'computed_affects' => array(
'__images',
),
),
'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' ),
'type' => 'color-alpha',
'custom_color' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'sale_badge',
'hover' => 'tabs',
'sticky' => true,
'mobile_options' => true,
),
'__images' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Images',
'get_images',
),
'computed_depends_on' => array(
'product',
'product_filter',
'show_product_image',
'show_product_gallery',
'show_sale_badge',
),
'computed_minimum' => array(
'product',
),
),
'force_fullwidth' => array(
'label' => esc_html__( 'Force Fullwidth', 'et_builder' ),
'description' => esc_html__( "When enabled, this will force your image to extend 100% of the width of the column it's in.", 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'layout',
'options' => array(
'off' => et_builder_i18n( 'No' ),
'on' => et_builder_i18n( 'Yes' ),
),
'default' => 'off',
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'affects' => array(
'max_width',
'width',
),
),
);
return $fields;
}
/**
* Get images output
*
* @since 4.12.0 Set $defaults['overwrite'] to array( 'product', 'post' )
* @since 3.29
*
* @param array $args Additional args.
*
* @return string
*/
public static function get_images( $args = array() ) {
/*
* YITH Badge Management plugin executes only when
* did_action( 'woocommerce_product_thumbnails' ) returns FALSE.
*
* The above wouldn't be the case when multiple Woo Images modules
* are placed on the same page.
* Hence the workaround is to reset the 'woocommerce_product_thumbnails' action.
*
* @link https://github.com/elegantthemes/Divi/issues/18530
*/
global $wp_actions;
$tag = 'woocommerce_product_thumbnails';
$reset = false;
$value = 0;
if ( isset( $wp_actions[ $tag ] ) ) {
$value = $wp_actions[ $tag ];
$reset = true;
unset( $wp_actions[ $tag ] );
}
$defaults = array(
'product' => 'current',
'show_product_image' => 'on',
'show_product_gallery' => 'on',
'show_sale_badge' => 'on',
);
$args = wp_parse_args( $args, $defaults );
$images = et_builder_wc_render_module_template(
'woocommerce_show_product_images',
$args,
array( 'product', 'post' )
);
/*
* Reset changes made for YITH Badge Management plugin.
*
* That way we won't bleed creating new issues.
*
* @link https://github.com/elegantthemes/Divi/issues/18530
*/
if ( $reset && ! isset( $wp_actions[ $tag ] ) ) {
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Fix compatibility.
$wp_actions[ $tag ] = $value;
}
return $images;
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
$sale_badge_color_hover = $this->get_hover_value( 'sale_badge_color' );
$sale_badge_color_values = et_pb_responsive_options()->get_property_values( $this->props, 'sale_badge_color' );
$force_fullwidth = et_()->array_get( $this->props, 'force_fullwidth', 'off' );
$show_product_image = et_()->array_get( $this->props, 'show_product_image', 'off' );
// Sale Badge Color.
$this->generate_styles(
array(
'base_attr_name' => 'sale_badge_color',
'selector' => '%%order_class%% span.onsale',
'css_property' => 'background-color',
'important' => true,
'render_slug' => $render_slug,
'type' => 'color',
)
);
// Image force fullwidth.
if ( 'on' === $force_fullwidth ) {
ET_Builder_Element::set_style(
$render_slug,
array(
'selector' => '%%order_class%% .woocommerce-product-gallery__image img',
'declaration' => 'width: 100%;',
)
);
}
// Toggle featured image.
if ( 'off' === $show_product_image ) {
ET_Builder_Element::set_style(
$render_slug,
array(
'selector' => '%%order_class%% .woocommerce-product-gallery__image--placeholder img[src*="woocommerce-placeholder"]',
'declaration' => 'visibility: hidden;',
)
);
}
$output = self::get_images( $this->props );
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Images();

View File

@ -0,0 +1,399 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Meta class
*
* The ET_Builder_Module_Woocommerce_Meta Class is responsible for rendering the
* Meta markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Meta component.
*/
class ET_Builder_Module_Woocommerce_Meta extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Meta', 'et_builder' );
$this->plural = esc_html__( 'Woo Metas', 'et_builder' );
$this->slug = 'et_pb_wc_meta';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
'elements' => et_builder_i18n( 'Elements' ),
),
),
'advanced' => array(
'toggles' => array(
'layout' => et_builder_i18n( 'Layout' ),
'body' => array(
'title' => et_builder_i18n( 'Text' ),
'priority' => 45,
'tabbed_subtoggles' => true,
'bb_icons_support' => true,
'sub_toggles' => array(
'p' => array(
'name' => 'P',
'icon' => 'text-left',
),
'a' => array(
'name' => 'A',
'icon' => 'text-link',
),
),
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'body' => array(
'label' => esc_html__( 'Meta', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .product_meta, %%order_class%% .product_meta a',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.7em',
),
'sub_toggle' => 'p',
'toggle_slug' => 'body',
),
'link' => array(
'label' => et_builder_i18n( 'Link' ),
'css' => array(
'main' => '%%order_class%% div.product_meta a',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.7em',
),
'toggle_slug' => 'body',
'sub_toggle' => 'a',
'hide_text_align' => true,
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
'css' => array(
'main' => '%%order_class%% .product_meta',
),
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% .product_meta',
'important' => 'all',
),
),
'text' => array(
'use_text_orientation' => false,
),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options.
'default' => false,
),
'box_shadow' => array(
'default' => array(
'css' => array(
'main' => '%%order_class%% .product_meta',
),
),
),
'button' => false,
'borders' => array(
'default' => array(
'css' => array(
'main' => array(
'border_radii' => '%%order_class%% .product_meta',
'border_styles' => '%%order_class%% .product_meta',
),
),
'defaults' => array(
'border_radii' => 'on||||',
'border_styles' => array(
'width' => '0px',
'color' => '#dadada',
'style' => 'solid',
),
'composite' => array(
'border_top' => array(
'border_width_top' => '1px',
'border_color_top' => '#dadada',
),
),
),
),
),
'height' => array(
'css' => array(
'main' => '%%order_class%% .product_meta',
),
),
);
$this->custom_css_fields = array(
'meta_text' => array(
'label' => esc_html__( 'Meta Text', 'et_builder' ),
'selector' => '.product_meta, .product_meta a',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__meta',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__meta',
),
)
),
'separator' => array(
'label' => esc_html__( 'Separator', 'et_builder' ),
'type' => 'text',
'option_category' => 'basic_option',
'description' => esc_html__( 'Here you can set the separator.', 'et_builder' ),
'toggle_slug' => 'main_content',
'default' => '/',
'show_if' => array(
'meta_layout' => 'inline',
),
),
'show_sku' => array(
'label' => esc_html__( 'Show SKU', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether the SKU should be added.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'show_categories' => array(
'label' => esc_html__( 'Show Categories', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether the Categories should be added.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'show_tags' => array(
'label' => esc_html__( 'Show Tags', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether the Tags should be added.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'meta_layout' => array(
'label' => esc_html__( 'Meta Layout', 'et_builder' ),
'type' => 'select',
'option_category' => 'layout',
'options' => array(
'inline' => esc_html__( 'Inline', 'et_builder' ),
'stacked' => esc_html__( 'Stacked', 'et_builder' ),
),
'tab_slug' => 'advanced',
'toggle_slug' => 'layout',
'description' => esc_html__( 'Here you can choose how to position the product meta.', 'et_builder' ),
'default_on_front' => 'inline',
'affects' => array(
'separator',
),
),
'__meta' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Meta',
'get_meta',
),
'computed_depends_on' => array(
'product',
'product_filter',
),
'computed_minimum' => array(
'product',
),
),
);
return $fields;
}
/**
* Get meta output
*
* @since 3.29
*
* @param array $args Additional arguments.
*
* @return string
*/
public static function get_meta( $args = array() ) {
$defaults = array(
'product' => 'current',
);
$args = wp_parse_args( $args, $defaults );
$meta = et_builder_wc_render_module_template(
'woocommerce_template_single_meta',
$args
);
return $meta;
}
/**
* Adds Multi view attributes to the Outer wrapper.
*
* Since we do not have control over the WooCommerce Breadcrumb markup, we inject Multi view
* attributes on to the Outer wrapper.
*
* @param array $outer_wrapper_attrs
* @param ET_Builder_Module_Woocommerce_Meta $this_class
*
* @return array
*/
public function add_multi_view_attrs( $outer_wrapper_attrs, $this_class ) {
$multi_view = et_pb_multi_view_options( $this_class );
$multi_view_attrs = $multi_view->render_attrs(
array(
'classes' => array(
'et_pb_wc_no_sku' => array(
'show_sku' => 'off',
),
'et_pb_wc_no_categories' => array(
'show_categories' => 'off',
),
'et_pb_wc_no_tags' => array(
'show_tags' => 'off',
),
),
),
false,
null,
true
);
if ( $multi_view_attrs && is_array( $multi_view_attrs ) ) {
$outer_wrapper_attrs = array_merge( $outer_wrapper_attrs, $multi_view_attrs );
}
return $outer_wrapper_attrs;
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
$multi_view = et_pb_multi_view_options( $this );
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
$this->add_classname( $this->get_text_orientation_classname() );
// Module classnames.
if ( 'on' !== $multi_view->get_value( 'show_sku' ) ) {
$this->add_classname( 'et_pb_wc_no_sku' );
}
if ( 'on' !== $multi_view->get_value( 'show_categories' ) ) {
$this->add_classname( 'et_pb_wc_no_categories' );
}
if ( 'on' !== $multi_view->get_value( 'show_tags' ) ) {
$this->add_classname( 'et_pb_wc_no_tags' );
}
$this->add_classname( esc_attr( 'et_pb_wc_meta_layout_' . $this->props['meta_layout'] ) );
/*
* Append separator via css pseudo selector so meta module can reuse default WooCommerce
* template (default WooCommerce meta template has no separator option)
*/
ET_Builder_Element::set_style(
$render_slug,
array(
'selector' => array(
'%%order_class%%:not(.et_pb_wc_no_categories).et_pb_wc_meta_layout_inline .sku_wrapper:after',
'%%order_class%%:not(.et_pb_wc_no_tags).et_pb_wc_meta_layout_inline .sku_wrapper:after',
'%%order_class%%:not(.et_pb_wc_no_tags).et_pb_wc_meta_layout_inline .posted_in:after',
),
'declaration' => 'content: " ' . esc_html(
ET_Builder_Module_Helper_Woocommerce_Modules::escape_special_chars(
$this->props['separator']
)
) . ' "',
)
);
add_filter( "et_builder_module_{$render_slug}_outer_wrapper_attrs", array( $this, 'add_multi_view_attrs' ), 10, 2 );
$output = self::get_meta( $this->props );
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Meta();

View File

@ -0,0 +1,236 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Price class
*
* The ET_Builder_Module_Woocommerce_Price Class is responsible for rendering the
* Price markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Price component.
*/
class ET_Builder_Module_Woocommerce_Price extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Price', 'et_builder' );
$this->plural = esc_html__( 'Woo Prices', 'et_builder' );
// Use `et_pb_wc_{module}` for all WooCommerce modules.
$this->slug = 'et_pb_wc_price';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
),
),
'advanced' => array(
'toggles' => array(
/*
* Manually define `text` to avoid `Text Text` toggle defined by advanced
* field font which automatically append ` Text` by default.
*/
'text' => array(
'title' => esc_html__( 'Price Text', 'et_builder' ),
'priority' => 45,
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'body' => array(
'label' => esc_html__( 'Price', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .price',
'important' => array( 'size' ),
),
'line_height' => array(
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
),
'font_size' => array(
'default' => '26px',
),
'hide_text_align' => true,
),
'before_sale_price' => array(
'label' => esc_html__( 'Sale Old Price', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .price del',
),
'line_height' => array(
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
),
'font_size' => array(
'default' => '26px',
),
'hide_text_align' => true,
),
'sale_price' => array(
'label' => esc_html__( 'Sale New Price', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .price ins',
'important' => array( 'font' ),
),
'line_height' => array(
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
),
'font' => array(
'default' => '|700|||||||',
),
'font_size' => array(
'default' => '26px',
),
'hide_text_align' => true,
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
),
'margin_padding' => array(
'css' => array(
/*
* Module has default margin-bottom which adapts to column it currently in
* thus, stronger selector needed for module's custom styling to overwrite it.
*/
'margin' => '.et_pb_row .et_pb_column div%%order_class%%',
'important' => 'all',
),
),
'text' => array(
'css' => array(
'text_shadow' => '%%order_class%%',
),
'options' => array(
'background_layout' => array(
'default' => 'light',
'hover' => 'tabs',
),
),
// Assign to main font advanced field (body), keeping things simplified
'toggle_slug' => 'body',
),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options
'default' => false,
),
'button' => false,
);
$this->custom_css_fields = array(
'text' => array(
'label' => esc_html__( 'Price', 'et_builder' ),
'selector' => '.price',
),
'before_sale_price' => array(
'label' => esc_html__( 'Sale Old Price', 'et_builder' ),
'selector' => '.price del',
),
'sale_price' => array(
'label' => esc_html__( 'Sale New Price', 'et_builder' ),
'selector' => '.price ins',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__price',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__price',
),
)
),
'__price' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Price',
'get_price',
),
'computed_depends_on' => array(
'product',
'product_filter',
),
'computed_minumum' => array(
'product',
),
),
);
return $fields;
}
/**
* Get price data
*
* @since 3.29
*
* @param array $args Arguments from Computed Prop AJAX call.
* @param array $conditional_tags Conditional Tags.
* @param array $current_page Current page args.
*
* @return string
*/
public static function get_price( $args = array(), $conditional_tags = array(), $current_page = array() ) {
return et_builder_wc_render_module_template( 'woocommerce_template_single_price', $args );
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
$this->add_classname( $this->get_text_orientation_classname() );
$output = self::get_price( $this->props );
// Render empty string if no output or no price value are generated
// to avoid unwanted vertical space.
if ( '' === trim( $output ) || '<p class="price"></p>' === trim( $output ) ) {
return '';
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Price();

View File

@ -0,0 +1,346 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Rating class
*
* The ET_Builder_Module_Woocommerce_Rating Class is responsible for rendering the
* Rating markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Rating component.
*/
class ET_Builder_Module_Woocommerce_Rating extends ET_Builder_Module {
/**
* Initialize.
*
* @since 3.29.2 Added custom margin default.
*/
public function init() {
$this->name = esc_html__( 'Woo Rating', 'et_builder' );
$this->plural = esc_html__( 'Woo Ratings', 'et_builder' );
$this->slug = 'et_pb_wc_rating';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
'elements' => et_builder_i18n( 'Elements' ),
),
),
'advanced' => array(
'toggles' => array(
'layout' => et_builder_i18n( 'Layout' ),
// Avoid Text suffix by manually defining the `text` toggle slug.
'text' => array(
'title' => et_builder_i18n( 'Text' ),
'priority' => 45,
),
// Avoid Text suffix by manually defining the `star` toggle slug.
'star' => esc_html__( 'Star Rating', 'et_builder' ),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'rating' => array(
'label' => esc_html__( 'Star Rating', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .woocommerce-product-rating .star-rating',
'color' => '%%order_class%% .woocommerce-product-rating .star-rating > span:before',
'text_align' => '%%order_class%% .woocommerce-product-rating',
),
'font_size' => array(
'default' => '14px',
),
'hide_font' => true,
'hide_line_height' => true,
'hide_text_shadow' => true,
'text_align' => array(
'label' => esc_html__( 'Star Rating Alignment', 'et_builder' ),
),
'font_size' => array(
'label' => esc_html__( 'Star Rating Size', 'et_builder' ),
),
'text_color' => array(
'label' => esc_html__( 'Star Rating Color', 'et_builder' ),
),
'toggle_slug' => 'star',
),
'body' => array(
'label' => et_builder_i18n( 'Text' ),
'css' => array(
'main' => '%%order_class%% a.woocommerce-review-link',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.7em',
),
'hide_text_align' => true,
/*
* Manually assign `text` toggle to avoid `Text Text` toggle defined by advanced
* field font which automatically append ` Text` by default.
*/
'toggle_slug' => 'text',
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
'custom_margin' => array(
'default' => '0em|0em|1.618em|0em|false|false',
),
),
'text' => array(),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options.
'default' => false,
),
'button' => false,
);
$this->custom_css_fields = array(
'text' => array(
'label' => et_builder_i18n( 'Text' ),
'selector' => 'a.woocommerce-review-link',
),
'star_rating_text' => array(
'label' => esc_html__( 'Star Rating', 'et_builder' ),
'selector' => '.woocommerce-product-rating .star-rating',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__rating',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__rating',
),
)
),
'show_rating' => array(
'label' => esc_html__( 'Show Star Rating', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether the star rating should be added.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'show_reviews_link' => array(
'label' => esc_html__( 'Show Customer Reviews Count', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => et_builder_i18n( 'On' ),
'off' => et_builder_i18n( 'Off' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Here you can choose whether the custom reviews link should be added.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'layout' => array(
'label' => esc_html__( 'Rating Layout', 'et_builder' ),
'type' => 'select',
'option_category' => 'layout',
'options' => array(
'inline' => esc_html__( 'Inline', 'et_builder' ),
'stacked' => esc_html__( 'Stacked', 'et_builder' ),
),
'tab_slug' => 'advanced',
'toggle_slug' => 'layout',
'description' => esc_html__( 'Here you can choose where to place the reviews link.', 'et_builder' ),
'default_on_front' => 'inline',
),
'__rating' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Rating',
'get_rating',
),
'computed_depends_on' => array(
'product',
'product_filter',
),
'computed_minimum' => array(
'product',
),
),
);
return $fields;
}
/**
* {@inheritdoc}
*/
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',
);
return $fields;
}
/**
* Get rating output
*
* @param array $args Additional arguments.
*
* @return string
*/
public static function get_rating( $args = array() ) {
$defaults = array(
'product' => 'current',
);
$args = wp_parse_args( $args, $defaults );
if ( 'current' !== $args['product'] ) {
// Enable comments via filter to render the reviews link.
add_filter( 'comments_open', '__return_true' );
}
$rating = et_builder_wc_render_module_template(
'woocommerce_template_single_rating',
$args,
array( 'product', 'wp_query' )
);
if ( 'current' !== $args['product'] ) {
// Remove filter after module is rendered.
remove_filter( 'comments_open', '__return_true' );
}
return $rating;
}
/**
* Adds Multi view attributes to the Outer wrapper.
*
* Since we do not have control over the WooCommerce Rating markup, we inject Multi view
* attributes on to the Outer wrapper.
*
* @param array $outer_wrapper_attrs
*
* @return array
*/
public function add_multi_view_attrs( $outer_wrapper_attrs ) {
$multi_view = et_pb_multi_view_options( $this );
$multi_view_attrs = $multi_view->render_attrs(
array(
'classes' => array(
'et_pb_wc_rating_no_rating' => array(
'show_rating' => 'off',
),
'et_pb_wc_rating_no_reviews' => array(
'show_reviews_link' => 'off',
),
),
),
false,
null,
true
);
if ( $multi_view_attrs && is_array( $multi_view_attrs ) ) {
$outer_wrapper_attrs = array_merge( $outer_wrapper_attrs, $multi_view_attrs );
}
return $outer_wrapper_attrs;
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
ET_Builder_Module_Helper_Woocommerce_Modules::add_star_rating_style(
$render_slug,
$this->props,
'%%order_class%% .star-rating',
'%%order_class%%:hover .star-rating',
array( 'rating_letter_spacing' )
);
$this->add_classname( $this->get_text_orientation_classname() );
// Add classes to hide disabled elements.
if ( 'on' !== $this->props['show_rating'] ) {
$this->add_classname( 'et_pb_wc_rating_no_rating' );
}
if ( 'on' !== $this->props['show_reviews_link'] ) {
$this->add_classname( 'et_pb_wc_rating_no_reviews' );
}
if ( ! empty( $this->props['layout'] ) ) {
$this->add_classname( "et_pb_wc_rating_layout_{$this->props['layout']}" );
}
add_filter( "et_builder_module_{$render_slug}_outer_wrapper_attrs", array( $this, 'add_multi_view_attrs' ) );
$output = self::get_rating( $this->props );
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Rating();

View File

@ -0,0 +1,704 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Related_Products class
*
* The ET_Builder_Module_Woocommerce_Related_Products Class is responsible for rendering the
* Related Products markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Related Products component.
*
* @since 3.29
*/
class ET_Builder_Module_Woocommerce_Related_Products extends ET_Builder_Module {
/**
* Holds Prop values across static methods.
*
* @var array
*
* @used-by ET_Builder_Module_Woocommerce_Related_Products::get_related_products()
* @used-by ET_Builder_Module_Woocommerce_Related_Products::get_selected_related_product_args()
*/
public static $static_props;
/**
* Initialize.
*
* @since 4.0.7 Introduced Product title toggle slug to allow Copy/Paste
* @see {https://github.com/elegantthemes/Divi/issues/17436}
*/
public function init() {
$this->name = esc_html__( 'Woo Related Product', 'et_builder' );
$this->plural = esc_html__( 'Woo Related Products', 'et_builder' );
// Use `et_pb_wc_{module}` for all WooCommerce modules.
$this->slug = 'et_pb_wc_related_products';
$this->vb_support = 'on';
$this->main_css_element = '%%order_class%%';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
),
),
'advanced' => array(
'toggles' => array(
'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(
'fonts' => array(
'title' => array(
'label' => et_builder_i18n( 'Title' ),
'css' => array(
'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',
'important' => 'all',
),
'font_size' => array(
'default' => '26px',
),
'line_height' => array(
'default' => '1',
),
),
'rating' => array(
'label' => esc_html__( 'Star Rating', 'et_builder' ),
'css' => array(
'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',
),
'font_size' => array(
'default' => 14,
),
'hide_font' => true,
'hide_line_height' => true,
'hide_text_shadow' => true,
'use_original_label' => true,
'text_align' => array(
'label' => esc_html__( 'Star Rating Alignment', 'et_builder' ),
),
'font_size' => array(
'label' => esc_html__( 'Star Rating Size', 'et_builder' ),
),
'text_color' => array(
'label' => esc_html__( 'Star Rating Color', 'et_builder' ),
),
'toggle_slug' => 'star',
),
'product_title' => array(
'label' => esc_html__( 'Product Title', 'et_builder' ),
'css' => array(
'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",
'important' => 'all',
),
'font_size' => array(
'default' => '26px',
),
'line_height' => array(
'default' => '1',
),
),
'price' => array(
'label' => esc_html__( 'Price', 'et_builder' ),
'css' => array(
'main' => "{$this->main_css_element} ul.products li.product .price, {$this->main_css_element} ul.products li.product .price .amount",
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'range_settings' => array(
'min' => '1',
'max' => '100',
'step' => '1',
),
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
),
),
'sale_badge' => array(
'label' => esc_html__( 'Sale Badge', 'et_builder' ),
'css' => array(
'main' => "{$this->main_css_element} ul.products li.product .onsale",
'important' => array( 'line-height', 'font', 'text-shadow' ),
),
'hide_text_align' => true,
'line_height' => array(
'default' => '1.7em',
),
'font_size' => array(
'default' => '20px',
),
'letter_spacing' => array(
'default' => '0px',
),
),
'sale_price' => array(
'label' => esc_html__( 'Sale Price', 'et_builder' ),
'css' => array(
'main' => "{$this->main_css_element} ul.products li.product .price ins .amount",
),
'hide_text_align' => true,
'font' => array(
'default' => '|700|||||||',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'range_settings' => array(
'min' => '1',
'max' => '100',
'step' => '1',
),
'default' => '1.7em',
),
),
),
'borders' => array(
'default' => array(
'css' => array(
'main' => array(
'border_radii' => '%%order_class%%.et_pb_wc_related_products .product',
'border_styles' => '%%order_class%%.et_pb_wc_related_products .product',
),
),
),
'image' => array(
'css' => array(
'main' => array(
'border_radii' => '%%order_class%%.et_pb_module .et_shop_image',
'border_styles' => '%%order_class%%.et_pb_module .et_shop_image',
),
'important' => 'all',
),
'label_prefix' => et_builder_i18n( 'Image' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
),
),
'box_shadow' => array(
'default' => array(
'css' => array(
'main' => '%%order_class%% .product',
),
),
'image' => array(
'label' => esc_html__( 'Image Box Shadow', 'et_builder' ),
'option_category' => 'layout',
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'css' => array(
'main' => '%%order_class%% .et_shop_image',
'overlay' => 'inset',
),
'default_on_fronts' => array(
'color' => '',
'position' => '',
),
),
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%%',
// Needed to overwrite last module margin-bottom styling.
'important' => array( 'custom_margin' ),
),
),
'text' => array(
'css' => array(
'text_shadow' => implode(
', ',
array(
// Title.
"{$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",
// Price.
"{$this->main_css_element} ul.products .price",
"{$this->main_css_element} ul.products .price .amount",
)
),
),
),
'filters' => array(
'child_filters_target' => array(
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
),
),
'image' => array(
'css' => array(
'main' => '%%order_class%% .et_shop_image',
),
),
'button' => false,
);
$this->custom_css_fields = array(
'product' => array(
'label' => esc_html__( 'Product', 'et_builder' ),
'selector' => 'li.product',
),
'onsale' => array(
'label' => esc_html__( 'Onsale', 'et_builder' ),
'selector' => 'li.product .onsale',
),
'image' => array(
'label' => et_builder_i18n( 'Image' ),
'selector' => '.et_shop_image',
),
'overlay' => array(
'label' => et_builder_i18n( 'Overlay' ),
'selector' => '.et_overlay',
),
'title' => array(
'label' => et_builder_i18n( 'Title' ),
'selector' => ET_Builder_Module_Helper_Woocommerce_Modules::get_title_selector(),
),
'rating' => array(
'label' => esc_html__( 'Star Rating', 'et_builder' ),
'selector' => '.star-rating',
),
'price' => array(
'label' => esc_html__( 'Price', 'et_builder' ),
'selector' => 'li.product .price',
),
'price_old' => array(
'label' => esc_html__( 'Old Price', 'et_builder' ),
'selector' => 'li.product .price del span.amount',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__related_products',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__related_products',
),
)
),
'posts_number' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'posts_number',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_columns_posts_default(),
'computed_affects' => array(
'__related_products',
),
)
),
'columns_number' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'columns_number',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_columns_posts_default(),
'computed_affects' => array(
'__related_products',
),
)
),
'orderby' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'orderby',
array(
'options' => array(
'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(
'__related_products',
),
)
),
'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' ),
'type' => 'color-alpha',
'custom_color' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'sale_badge',
'hover' => 'tabs',
'mobile_options' => true,
'sticky' => 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' ),
'type' => 'color-alpha',
'custom_color' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'sticky' => 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' ),
'type' => 'color-alpha',
'custom_color' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'sticky' => true,
),
'hover_icon' => array(
'label' => esc_html__( 'Overlay Icon', 'et_builder' ),
'description' => esc_html__( 'Here you can define a custom icon for the overlay', 'et_builder' ),
'type' => 'select_icon',
'option_category' => 'configuration',
'class' => array( 'et-pb-font-icon' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'sticky' => true,
),
'__related_products' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Related_Products',
'get_related_products',
),
'computed_depends_on' => array(
'product',
'product_filter',
'posts_number',
'columns_number',
'orderby',
),
'computed_minimum' => array(
'product',
),
),
);
return $fields;
}
/**
* {@inheritdoc}
*/
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',
);
return $fields;
}
/**
* Gets the related Products.
*
* Used as a callback to the __related_products computed prop.
*
* @param array $args Arguments from Computed Prop AJAX call.
* @param array $conditional_tags Conditional Tags.
* @param array $current_page Current page args.
*
* @return string
*/
public static function get_related_products( $args = array(), $conditional_tags = array(), $current_page = array() ) {
/*
* User selected Posts per page, Columns and Order by values are propagated to WooCommerce
* using the `woocommerce_output_related_products_args` filter.
*
* Since we cannot directly pass the `$args` as argument to the filter,
* we pass them via a static variable.
*/
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 ) ) {
add_filter( 'woocommerce_product_class', 'et_theme_builder_wc_product_class' );
}
add_filter(
'woocommerce_output_related_products_args',
array(
'ET_Builder_Module_Woocommerce_Related_Products',
'set_related_products_args',
)
);
$output = et_builder_wc_render_module_template( 'woocommerce_output_related_products', $args );
remove_filter(
'woocommerce_output_related_products_args',
array(
'ET_Builder_Module_Woocommerce_Related_Products',
'set_related_products_args',
)
);
return $output;
}
/**
* Returns the User selected Posts per page, columns and Order by values to WooCommerce.
*
* @param array $args Documented at
* {@see woocommerce_output_related_products()}.
*
* @return array
*/
public static function set_related_products_args( $args ) {
$selected_args = self::get_selected_related_product_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_Related_Products::get_related_products()
*
* @return array
*/
public static function get_selected_related_product_args() {
$selected_args = array();
$selected_args['posts_per_page'] = et_()->array_get(
self::$static_props,
'posts_number',
''
);
$selected_args['columns'] = et_()->array_get(
self::$static_props,
'columns_number',
''
);
$selected_args['orderby'] = et_()->array_get(
self::$static_props,
'orderby',
''
);
// Set default values when parameters are empty.
$default = ET_Builder_Module_Helper_Woocommerce_Modules::get_columns_posts_default_value();
if ( empty( $selected_args['posts_per_page'] ) ) {
$selected_args['posts_per_page'] = $default;
}
if ( empty( $selected_args['columns'] ) ) {
$selected_args['columns'] = $default;
}
$selected_args = array_filter( $selected_args, 'strlen' );
if ( isset( $selected_args['orderby'] ) ) {
$orderby = $selected_args['orderby'];
if ( in_array( $orderby, array( 'price-desc', 'date-desc' ), true ) ) {
/*
* For the list of all allowed Orderby values, refer
*
* @see wc_products_array_orderby
*/
$selected_args['orderby'] = str_replace( '-desc', '', $orderby );
} else {
/*
* Implicitly specify when ascending is required since `desc` is the default value.
*
* @see woocommerce_related_products()
*/
$selected_args['order'] = 'asc';
}
}
return $selected_args;
}
/**
* Renders the module output.
*
* @since 4.1.0 Show only Products irrespective of Customizer Product Catalog setting on Shop page.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
ET_Builder_Module_Helper_Woocommerce_Modules::add_star_rating_style(
$render_slug,
$this->props,
'%%order_class%% ul.products li.product .star-rating',
'%%order_class%% ul.products li.product:hover .star-rating'
);
// Sale Badge Color.
$this->generate_styles(
array(
'base_attr_name' => 'sale_badge_color',
'selector' => '%%order_class%% span.onsale',
'css_property' => 'background-color',
'important' => true,
'render_slug' => $render_slug,
'type' => 'color',
)
);
// Icon Hover Color.
$this->generate_styles(
array(
'hover' => false,
'base_attr_name' => 'icon_hover_color',
'selector' => '%%order_class%% .et_overlay:before, %%order_class%% .et_pb_extra_overlay:before',
'css_property' => 'color',
'important' => true,
'render_slug' => $render_slug,
'type' => 'color',
)
);
// Hover Overlay Color.
$this->generate_styles(
array(
'hover' => false,
'base_attr_name' => 'hover_overlay_color',
'selector' => '%%order_class%% .et_overlay, %%order_class%% .et_pb_extra_overlay',
'css_property' => array( 'background-color', 'border-color' ),
'important' => true,
'render_slug' => $render_slug,
'type' => 'color',
)
);
// Overlay Icon Styles.
$this->generate_styles(
array(
'hover' => false,
'utility_arg' => 'icon_font_family',
'render_slug' => $render_slug,
'base_attr_name' => 'hover_icon',
'important' => true,
'selector' => '%%order_class%% .et_overlay:before',
'processor' => array(
'ET_Builder_Module_Helper_Style_Processor',
'process_extended_icon',
),
)
);
// Images: Add CSS Filters and Mix Blend Mode rules (if set).
if ( array_key_exists( 'image', $this->advanced_fields ) && array_key_exists( 'css', $this->advanced_fields['image'] ) ) {
$this->add_classname(
$this->generate_css_filters(
$render_slug,
'child_',
self::$data_utils->array_get( $this->advanced_fields['image']['css'], 'main', '%%order_class%%' )
)
);
}
$this->add_classname( $this->get_text_orientation_classname() );
$is_shop = function_exists( 'is_shop' ) && is_shop();
$is_wc_loop_prop_get_set_exists = function_exists( 'wc_get_loop_prop' ) && function_exists( 'wc_set_loop_prop' );
$is_product_category = function_exists( 'is_product_category' ) && is_product_category();
if ( $is_shop ) {
$display_type = ET_Builder_Module_Helper_Woocommerce_Modules::set_display_type_to_render_only_products( 'woocommerce_shop_page_display' );
} elseif ( $is_product_category ) {
$display_type = ET_Builder_Module_Helper_Woocommerce_Modules::set_display_type_to_render_only_products( 'woocommerce_category_archive_display' );
}
// Required to handle Customizer preview pane.
// Refer: https://github.com/elegantthemes/Divi/issues/17998#issuecomment-565955422
if ( $is_wc_loop_prop_get_set_exists && is_customize_preview() ) {
$is_filtered = wc_get_loop_prop( 'is_filtered' );
wc_set_loop_prop( 'is_filtered', true );
}
$output = self::get_related_products( $this->props );
// Required to handle Customizer preview pane.
// Refer: https://github.com/elegantthemes/Divi/issues/17998#issuecomment-565955422
if ( $is_wc_loop_prop_get_set_exists && is_customize_preview() && isset( $is_filtered ) ) {
wc_set_loop_prop( 'is_filtered', $is_filtered );
}
if ( $is_shop && isset( $display_type ) ) {
ET_Builder_Module_Helper_Woocommerce_Modules::reset_display_type( 'woocommerce_shop_page_display', $display_type );
} elseif ( $is_product_category && isset( $display_type ) ) {
ET_Builder_Module_Helper_Woocommerce_Modules::reset_display_type( 'woocommerce_category_archive_display', $display_type );
}
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
add_filter(
"et_builder_module_{$render_slug}_outer_wrapper_attrs",
array(
'ET_Builder_Module_Helper_Woocommerce_Modules',
'output_data_icon_attrs',
),
10,
2
);
$output = $this->_render_module_wrapper( $output, $render_slug );
remove_filter(
"et_builder_module_{$render_slug}_outer_wrapper_attrs",
array(
'ET_Builder_Module_Helper_Woocommerce_Modules',
'output_data_icon_attrs',
),
10
);
return $output;
}
}
new ET_Builder_Module_Woocommerce_Related_Products();

View File

@ -0,0 +1,490 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Reviews class
*
* The ET_Builder_Module_Woocommerce_Reviews Class is responsible for rendering the
* Reviews markup.
*
* @package Divi\Builder
*
* @since 3.29
*/
if ( ! class_exists( 'ET_Builder_Module_Gallery' ) ) {
require_once ET_BUILDER_DIR_RESOLVED_PATH . '/module/Comments.php';
}
/**
* Class representing WooCommerce Reviews component.
*/
class ET_Builder_Module_Woocommerce_Reviews extends ET_Builder_Module_Comments {
/**
* Modify properties defined on base module's (comment) init()
*
* @since 3.29
*/
public function init() {
parent::init();
// Define basic module information.
$this->name = esc_html__( 'Woo Reviews', 'et_builder' );
$this->plural = esc_html__( 'Woo Reviews', 'et_builder' );
$this->slug = 'et_pb_wc_reviews';
// Modify toggle settings.
$this->settings_modal_toggles['general']['toggles']['main_content'] = array(
'title' => et_builder_i18n( 'Content' ),
'priority' => 1,
);
$this->settings_modal_toggles['advanced']['toggles']['rating'] = array(
'title' => esc_html__( 'Star Rating', 'et_builder' ),
'priority' => 60,
);
$this->settings_modal_toggles['advanced']['toggles']['image'] = array(
'title' => et_builder_i18n( 'Image' ),
'priority' => 30,
);
// Modify advanced field settings.
$this->advanced_fields['fonts']['header']['label'] = esc_html__( 'Review Count', 'et_builder' );
$this->advanced_fields['fonts']['header']['header_level']['default'] = 'h2';
$this->advanced_fields['fonts']['header']['header_level']['computed_affects'] = array(
'__reviews',
);
$this->advanced_fields['fonts']['header']['font_size'] = array(
'default' => '26px',
);
$this->advanced_fields['fonts']['header']['line_height'] = array(
'default' => '1em',
);
$this->advanced_fields['fonts']['title']['font_size'] = array(
'default' => '14px',
);
$this->advanced_fields['fonts']['title']['line_height'] = array(
'default' => '1.7em',
);
$this->advanced_fields['fonts']['header']['css']['main'] = "{$this->main_css_element} h1.woocommerce-Reviews-title, {$this->main_css_element} h2.woocommerce-Reviews-title, {$this->main_css_element} h3.woocommerce-Reviews-title, {$this->main_css_element} h4.woocommerce-Reviews-title, {$this->main_css_element} h5.woocommerce-Reviews-title, {$this->main_css_element} h6.woocommerce-Reviews-title";
$this->advanced_fields['fonts']['meta']['css']['main'] = "{$this->main_css_element} #reviews #comments ol.commentlist li .comment-text p.meta, %%order_class%% .comment-form-rating label";
$this->advanced_fields['fonts']['meta']['hide_text_align'] = true;
$this->advanced_fields['fonts']['body']['css']['main'] = "{$this->main_css_element} .comment-text .description";
$this->advanced_fields['fonts']['rating'] = array(
'label' => esc_html__( 'Star Rating', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .star-rating, %%order_class%% .comment-form-rating p.stars a',
'letter_spacing' => '%%order_class%% .star-rating, %%order_class%% .comment-form-rating p.stars',
'letter_spacing_hover' => '%%order_class%% .star-rating:hover, %%order_class%% .comment-form-rating p.stars:hover',
'color' => '%%order_class%% .star-rating > span:before, %%order_class%% .comment-form-rating p.stars a',
'color_hover' => '%%order_class%% .star-rating:hover > span:before, %%order_class%% .comment-form-rating p.stars:hover a',
'main' => '%%order_class%% .star-rating, %%order_class%% .comment-form-rating p.stars a',
'text_align' => '%%order_class%% .comment-form-rating p.stars',
),
'font_size' => array(
'default' => 14,
),
'hide_font' => true,
'hide_line_height' => true,
'hide_text_shadow' => true,
);
$this->advanced_fields['borders']['image']['css']['main']['border_radii'] = '%%order_class%%.et_pb_wc_reviews #reviews #comments ol.commentlist li img.avatar';
$this->advanced_fields['borders']['image']['css']['main']['border_styles'] = '%%order_class%%.et_pb_wc_reviews #reviews #comments ol.commentlist li img.avatar';
$this->advanced_fields['box_shadow']['image']['css']['main'] = '%%order_class%%.et_pb_wc_reviews #reviews #comments ol.commentlist li img.avatar';
$this->advanced_fields['image']['css']['main'] = '%%order_class%%.et_pb_wc_reviews #reviews #comments ol.commentlist li img.avatar';
$this->advanced_fields['form_field']['form_field']['font_field']['css']['main'] = "{$this->main_css_element} #commentform textarea, {$this->main_css_element} #commentform input[type='text'], {$this->main_css_element} #commentform input[type='email'], {$this->main_css_element} #commentform input[type='url']";
$this->advanced_fields['form_field']['form_field']['font_field']['font_size'] = array(
'default' => '18px',
);
// Disable form title heading level because it uses span tag.
unset( $this->advanced_fields['fonts']['title']['header_level'] );
$this->custom_css_fields = array(
'main_header' => array(
'label' => esc_html__( 'Reviews Count', 'et_builder' ),
'selector' => '.woocommerce-Reviews-title',
),
'comment_body' => array(
'label' => esc_html__( 'Review Body', 'et_builder' ),
'selector' => '.comment_container',
),
'comment_meta' => array(
'label' => esc_html__( 'Review Meta', 'et_builder' ),
'selector' => '#reviews #comments ol.commentlist li .comment-text p.meta',
),
'comment_content' => array(
'label' => esc_html__( 'Review Rating', 'et_builder' ),
'selector' => '.comment-form-rating',
),
'comment_avatar' => array(
'label' => esc_html__( 'Review Avatar', 'et_builder' ),
'selector' => '#reviews #comments ol.commentlist li img.avatar',
),
'new_title' => array(
'label' => esc_html__( 'New Review Title', 'et_builder' ),
'selector' => '#reply-title',
),
'message_field' => array(
'label' => esc_html__( 'Message Field', 'et_builder' ),
'selector' => '.comment-form-comment textarea#comment',
),
'name_field' => array(
'label' => esc_html__( 'Name Field', 'et_builder' ),
'selector' => '.comment-form-author input#author',
),
'email_field' => array(
'label' => esc_html__( 'Email Field', 'et_builder' ),
'selector' => '.comment-form-email input#email',
),
'submit_button' => array(
'label' => esc_html__( 'Submit Button', 'et_builder' ),
'selector' => '#submit',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
// Insert classname to module wrapper.
add_filter(
'et_builder_wc_reviews_classes',
array(
$this,
'add_wc_reviews_classname',
),
10,
2
);
}
/**
* Insert Woo Reviews specific fields and modify fields inherited from base module (comments).
*
* @return array
*/
public function get_fields() {
$et_accent_color = et_builder_accent_color();
// Get base module (comment)'s fields.
$fields = parent::get_fields();
$fields['product'] = ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'computed_affects' => array(
'__reviews',
),
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
)
);
$fields['product_filter'] = ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__reviews',
),
)
);
$fields['__reviews'] = array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Reviews',
'get_reviews_html',
),
'computed_depends_on' => array(
'product',
'product_filter',
'header_level',
),
);
/*
* Modify base module (comment) fields; These fields can't be hidden because Woo Reviews
* uses base module's `render()` method which it expects
* `$this->props['show_reply']` to exist
*/
$fields['show_reply']['type'] = 'hidden';
return $fields;
}
/**
* {@inheritdoc}
*/
public function get_transition_fields_css_props() {
$fields = parent::get_transition_fields_css_props();
$fields['rating_letter_spacing'] = array(
'font-size' => '%%order_class%% .star-rating, %%order_class%% .comment-form-rating p.stars',
'width' => '%%order_class%% .star-rating',
'letter-spacing' => '%%order_class%% .star-rating, %%order_class%% .comment-form-rating p.stars',
);
$fields['rating_font_size'] = array(
'font-size' => '%%order_class%% .star-rating, %%order_class%% .comment-form-rating p.stars a',
);
return $fields;
}
/**
* Get reviews HTML.
*
* @param array $args Arguments from Computed Prop AJAX call.
* @param array $conditional_tags Conditional Tags.
* @param array $current_page Current page args.
*
* @return string
*/
public static function get_reviews_html( $args = array(), $conditional_tags = array(), $current_page = array() ) {
$maybe_product_id = 'current';
$defaults = array(
'header_level' => 'h2',
);
$args = wp_parse_args( $args, $defaults );
// Get correct product ID when current request is computed callback request.
if ( ET_Builder_Element::get_current_post_id() && ! et_builder_tb_enabled() ) {
$maybe_product_id = ET_Builder_Element::get_current_post_id();
}
if ( array_key_exists( 'id', $current_page ) ) {
$maybe_product_id = $current_page['id'];
}
if ( array_key_exists( 'product', $args ) && ! empty( $args['product'] ) ) {
$maybe_product_id = $args['product'];
}
$is_tb = et_builder_tb_enabled();
if ( $is_tb ) {
global $product;
et_theme_builder_wc_set_global_objects();
} else {
$product = ET_Builder_Module_Helper_Woocommerce_Modules::get_product( $maybe_product_id );
}
if ( ! ( $product instanceof WC_Product ) ) {
return '';
}
$reviews_markup = self::get_reviews_markup( $product, $args['header_level'], true );
if ( $is_tb ) {
et_theme_builder_wc_reset_global_objects();
}
return $reviews_markup;
}
/**
* Gets the Reviews markup.
*
* This includes the Reviews and the Review comment form.
*
* @since 3.29
*
* @param WC_Product $product WooCommerce Product.
* @param string $header_level Heading level.
* @param bool $is_ajax Should be set to TRUE when used in AJAX call for proper
* results.
*
* @return string
*/
public static function get_reviews_markup( $product, $header_level, $is_ajax = false ) {
if ( ! ( $product instanceof WC_Product ) ) {
return '';
}
if ( ! comments_open( $product->get_id() ) ) {
return '';
}
$reviews_title = ET_Builder_Module_Helper_Woocommerce_Modules::get_reviews_title( $product );
// Product could be changed using the Product filter in the Settings modal.
// Hence supplying the Product ID to fetch data based on the selected Product.
$reviews = get_comments(
array(
'post_id' => $product->get_id(),
'status' => 'approve',
)
);
$total_pages = get_comment_pages_count( $reviews );
$reviews_content = wp_list_comments(
array(
'callback' => 'woocommerce_comments',
'echo' => false,
),
$reviews
);
// Supply the `$total_pages` var. Otherwise $pagination would always be empty.
if ( $is_ajax ) {
$page = get_query_var( 'cpage' );
if ( ! $page ) {
$page = 1;
}
$args = array(
'base' => add_query_arg( 'cpage', '%#%' ),
'format' => '',
'total' => $total_pages,
'current' => $page,
'echo' => false,
'add_fragment' => '#comments',
'type' => 'list',
);
global $wp_rewrite;
if ( $wp_rewrite->using_permalinks() ) {
$args['base'] = user_trailingslashit( trailingslashit( get_permalink() ) . $wp_rewrite->comments_pagination_base . '-%#%', 'commentpaged' );
}
$pagination = paginate_links( $args );
} else {
$pagination = paginate_comments_links(
array(
'echo' => false,
'type' => 'list',
'total' => $total_pages,
)
);
}
// Pass $product, $reviews to unify the flow of data.
$reviews_comment_form = ET_Builder_Module_Helper_Woocommerce_Modules::get_reviews_comment_form( $product, $reviews );
return sprintf(
'
<div id="reviews" class="woocommerce-Reviews">
<div id="comments">
<%3$s class="woocommerce-Reviews-title">
%1$s
</%3$s>
<ol class="commentlist">
%2$s
</ol>
<nav class="woocommerce-pagination">
%4$s
</nav>
</div>
<div id="review_form_wrapper">
%5$s
</div>
<div class="clear"></div>
</div>
',
/* 1$s */
$reviews_title,
/* 2$s */
$reviews_content,
/* 3$s */
$header_level,
/* 4$s */
$pagination,
/* 5$s */
$reviews_comment_form
);
}
/**
* Add classname into module wrapper.
*
* @param array $classname List of class names.
* @param int $render_count Count of times the module is rendered.
*/
public function add_wc_reviews_classname( $classname, $render_count ) {
/*
* Woo Reviews can't add `et_pb_wc_reviews` via `$this->add_classname()` method because
* comments module specifically remove slug classname at the end of its rendering process
* {@link https://github.com/elegantthemes/submodule-builder/pull/2910/files#diff-832b621946ab4f4dee33ddbf442d0225R348}
*/
$classname[] = $this->slug;
return $classname;
}
/**
* Remove action and filter hook performed before comment contents rendering by extending
* the method because Woo Reviews doesn't need it
*
* @since 3.29
*/
public function before_comments_content() {
/* intentionally empty*/
}
/**
* Render review (comments) content
*
* @since 3.29
*/
public function get_comments_content() {
$header_level = $this->props['header_level'];
$product = $this->props['product'];
$verified_product = ET_Builder_Module_Helper_Woocommerce_Modules::get_product( $product );
return self::get_reviews_markup(
$verified_product,
et_pb_process_header_level( $header_level, 'h2' )
);
}
/**
* Remove action and filter hook performed before comment contents rendering by extending
* the method because Woo Reviews doesn't need it.
*
* @since 3.29
*/
public function after_comments_content() {
/* intentionally empty*/
}
/**
* {@inheritdoc}
*/
public function render( $attrs, $content, $render_slug ) {
// Image - CSS Filters.
if ( et_()->array_get( $this->advanced_fields, 'image.css', false ) ) {
$classes = $this->generate_css_filters( $this->slug, 'child_', et_()->array_get( $this->advanced_fields['image']['css'], 'main', '%%order_class%%' ) );
$this->add_classname( $classes );
}
ET_Builder_Module_Helper_Woocommerce_Modules::add_star_rating_style(
$render_slug,
$this->props,
'%%order_class%% .star-rating',
'%%order_class%% .star-rating:hover'
);
// Fixes right text alignment of review form star rating. By default, WC adds text-indent -999em to
// hide the original rating number. However, it causes an issue if the alignment is set to right
// position. We should push the rating value to the right side and hide the overflow.
$rating_alignments = array();
$rating_alignment_values = et_pb_responsive_options()->get_property_values( $this->props, 'rating_text_align' );
foreach ( $rating_alignment_values as $mode => $value ) {
// Should be added only when the alignment is right.
if ( 'right' !== $value ) {
continue;
}
$rating_alignments[ $mode ] = 'overflow: hidden; text-indent: 999em;';
}
// Generate style for desktop, tablet, and phone.
et_pb_responsive_options()->declare_responsive_css(
$rating_alignments,
'%%order_class%% p.stars a',
$render_slug
);
return parent::render( $attrs, $content, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Reviews();

View File

@ -0,0 +1,205 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Stock class
*
* The ET_Builder_Module_Woocommerce_Stock Class is responsible for rendering the
* Stock markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Stock component.
*/
class ET_Builder_Module_Woocommerce_Stock extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Stock', 'et_builder' );
$this->plural = esc_html__( 'Woo Stock', 'et_builder' );
$this->slug = 'et_pb_wc_stock';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'instock' => array(
'label' => esc_html__( 'In Stock', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .et_pb_module_inner .stock.in-stock',
'plugin_main' => '%%order_class%% .in-stock, %%order_class%% .in-stock a, %%order_class%% .in-stock span',
),
'font_size' => array(
'default' => '13px',
),
'line_height' => array(
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
),
),
'outofstock' => array(
'label' => esc_html__( 'Out Of Stock', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .et_pb_module_inner .stock.out-of-stock',
'plugin_main' => '%%order_class%% .out-of-stock, %%order_class%% .out-of-stock a, %%order_class%% .out-of-stock span',
),
'font_size' => array(
'default' => '13px',
),
'line_height' => array(
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
),
),
'onbackorder' => array(
'label' => esc_html__( 'On Backorder', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% .available-on-backorder',
'plugin_main' => '%%order_class%% .available-on-backorder, %%order_class%% .available-on-backorder a, %%order_class%% .available-on-backorder span',
),
'font_size' => array(
'default' => '13px',
),
'line_height' => array(
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
),
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
'text' => array(),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options.
'default' => false,
),
'button' => false,
);
$this->custom_css_fields = array(
'instock_text' => array(
'label' => esc_html__( 'In Stock Text', 'et_builder' ),
'selector' => '.in-stock',
),
'outofstock_text' => array(
'label' => esc_html__( 'Out of Stock Text', 'et_builder' ),
'selector' => '.out-of-stock',
),
'backorder_text' => array(
'label' => esc_html__( 'On Backorder Text', 'et_builder' ),
'selector' => '.available-on-backorder',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__stock',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__stock',
),
)
),
'__stock' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Stock',
'get_stock',
),
'computed_depends_on' => array(
'product',
'product_filter',
),
'computed_minimum' => array(
'product',
),
),
);
return $fields;
}
/**
* Get stock output
*
* @since 3.29
*
* @param array $args Additional arguments.
*
* @return string
*/
public static function get_stock( $args = array() ) {
$defaults = array(
'product' => 'current',
);
$args = wp_parse_args( $args, $defaults );
$rating = et_builder_wc_render_module_template(
'wc_get_stock_html',
$args
);
return $rating;
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
$this->add_classname( $this->get_text_orientation_classname() );
$output = self::get_stock( $this->props );
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Stock();

View File

@ -0,0 +1,453 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Tabs class
*
* The ET_Builder_Module_Woocommerce_Tabs Class is responsible for rendering the
* Tabs markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
if ( ! class_exists( 'ET_Builder_Module_Tabs' ) ) {
require_once ET_BUILDER_DIR_RESOLVED_PATH . '/module/Tabs.php';
}
/**
* Class representing WooCommerce Add to cart component.
*
* @since 3.29
*/
class ET_Builder_Module_Woocommerce_Tabs extends ET_Builder_Module_Tabs {
/**
* Define WooCommerce Tabs property.
*/
public function init() {
// Inherit tabs module property.
parent::init();
// Define WooCommerce Tabs module property; overwriting inherited property.
$this->name = esc_html__( 'Woo Tabs', 'et_builder' );
$this->plural = esc_html__( 'Woo Tabs', 'et_builder' );
$this->slug = 'et_pb_wc_tabs';
/*
* Set property for holding rendering data so the data rendering via
* ET_Builder_Module_Woocommerce_Tabs::get_tabs() is only need to be done once.
*/
$this->rendered_tabs_data = array();
// Remove module item.
$this->child_slug = null;
$this->child_item_text = null;
// Set WooCommerce Tabs specific toggle / options group.
$this->settings_modal_toggles['general']['toggles']['main_content'] = array(
'title' => et_builder_i18n( 'Content' ),
'priority' => 10,
);
$this->advanced_fields['fonts']['tab']['font_size'] = array(
'default' => '14px',
);
$this->advanced_fields['fonts']['tab']['line_height'] = array(
'default' => '1.7em',
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* Get product all possible tabs data
*
* @since 3.29
* @since 4.4.2 Fix to include Custom tabs.
*
* @global WP_Post $post WordPress Post.
* @global WC_Product $product WooCommerce Product.
*
* @return array
*/
public function get_product_tabs() {
static $tabs = null;
if ( ! is_null( $tabs ) ) {
return $tabs;
}
global $post, $product;
// Save existing $post and $product global.
$original_post = $post;
$original_product = $product;
$post_id = 'product' === $this->get_post_type()
? ET_Builder_Element::get_current_post_id()
: ET_Builder_Module_Helper_Woocommerce_Modules::get_product_id( 'latest' );
// Overwriting global $post is necessary as WooCommerce relies on it.
$post = get_post( $post_id );
$product = wc_get_product( $post_id );
/*
* Get relevant product tabs data. Product tabs hooks use global based conditional
* for adding / removing product tabs data via filter hoook callback, hence the
* need to overwrite the global for determining product tabs data
*/
$tabs = is_object( $product )
? apply_filters( 'woocommerce_product_tabs', array() )
: ET_Builder_Module_Helper_Woocommerce_Modules::get_default_product_tabs();
// Reset $post and $product global.
$post = $original_post;
$product = $original_product;
/*
* Always return all possible tabs
*/
return $tabs;
}
/**
* Get product tabs options; product data formatted for checkbox control's options
*
* @since 3.29
*
* @return array
*/
public function get_tab_options() {
$tabs = $this->get_product_tabs();
$options = array();
foreach ( $tabs as $name => $tab ) {
if ( ! isset( $tab['title'] ) ) {
continue;
}
$options[ $name ] = array(
'value' => $name,
'label' => 'reviews' === $name ? esc_html__( 'Reviews', 'et_builder' ) :
esc_html( $tab['title'] ),
);
}
return $options;
}
/**
* Get product tabs default based on product tabs options
*
* @since 3.29
*
* @return string
*/
public function get_tab_defaults() {
return implode( '|', array_keys( $this->get_product_tabs() ) );
}
/**
* Define Woo Tabs fields
*
* @since 3.29
*
* @return array
*/
public function get_fields() {
$fields = array_merge(
parent::get_fields(),
array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__tabs',
'include_tabs',
),
)
),
'include_tabs' => array(
'label' => esc_html__( 'Include Tabs', 'et_builder' ),
'type' => 'checkboxes_advanced_woocommerce',
'option_category' => 'configuration',
'default' =>
ET_Builder_Module_Helper_Woocommerce_Modules::get_woo_default_tabs(),
'description' => esc_html__( 'Here you can select the tabs that you would like to display.', 'et_builder' ),
'toggle_slug' => 'main_content',
'mobile_options' => true,
'hover' => 'tabs',
'computed_depends_on' => array(
'product',
),
),
'__tabs' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Tabs',
'get_tabs',
),
'computed_depends_on' => array(
'product',
),
'computed_minimum' => array(
'product',
),
),
)
);
return $fields;
}
/**
* Get tabs nav output
*
* @since 3.29
*
* @return string
*/
public function get_tabs_nav() {
$nav = '';
$index = 0;
// get_tabs_content() method is called earlier so get_tabs_nav() can reuse tabs data.
if ( ! empty( $this->rendered_tabs_data ) ) {
foreach ( $this->rendered_tabs_data as $name => $tab ) {
$index ++;
$nav .= sprintf(
'<li class="%3$s%1$s"><a href="#tab-%4$s">%2$s</a></li>',
( 1 === $index ? ' et_pb_tab_active' : '' ),
esc_html( $tab['title'] ),
sprintf( '%1$s_tab', esc_attr( $name ) ),
esc_attr( $name )
);
}
}
return $nav;
}
/**
* Get tabs content output
*
* @since 4.4.1 Fix [embed][/embed] shortcodes not working in tab content
* @since 3.29
*
* @return string
*/
public function get_tabs_content() {
// Get tabs data.
$this->rendered_tabs_data = self::get_tabs(
array(
'product' => $this->props['product'],
'include_tabs' => $this->props['include_tabs'],
)
);
// Add tabs module classname.
$this->add_classname( 'et_pb_tabs' );
// Render tabs content output.
$index = 0;
$content = '';
foreach ( $this->rendered_tabs_data as $name => $tab ) {
$index ++;
$content .= sprintf(
'<div class="et_pb_tab clearfix%2$s">
<div class="et_pb_tab_content">
%1$s
</div>
</div>',
$tab['content'],
1 === $index ? ' et_pb_active_content' : ''
);
}
return $content;
}
/**
* Load comments template.
*
* @param string $template template to load.
* @return string
*/
public static function comments_template_loader( $template ) {
if ( ! et_builder_tb_enabled() ) {
return $template;
}
$check_dirs = array(
trailingslashit( get_stylesheet_directory() ) . WC()->template_path(),
trailingslashit( get_template_directory() ) . WC()->template_path(),
trailingslashit( get_stylesheet_directory() ),
trailingslashit( get_template_directory() ),
trailingslashit( WC()->plugin_path() ) . 'templates/',
);
if ( WC_TEMPLATE_DEBUG_MODE ) {
$check_dirs = array( array_pop( $check_dirs ) );
}
foreach ( $check_dirs as $dir ) {
if ( file_exists( trailingslashit( $dir ) . 'single-product-reviews.php' ) ) {
return trailingslashit( $dir ) . 'single-product-reviews.php';
}
}
}
/**
* Get tabs data
*
* @since 4.0.9 Avoid fetching Tabs content using `the_content` when editing TB layout.
*
* @param array $args Additional args.
*
* @return array
*/
public static function get_tabs( $args = array() ) {
global $product, $post, $wp_query;
/*
* Visual builder fetches all tabs data and filter the included tab on the app to save
* app to server request for faster user experience. Frontend passes `includes_tab` to
* this method so it only process required tabs
*/
$defaults = array(
'product' => 'current',
);
$args = wp_parse_args( $args, $defaults );
// Get actual product id based on given `product` attribute.
$product_id = ET_Builder_Module_Helper_Woocommerce_Modules::get_product_id( $args['product'] );
// Determine whether current tabs data needs global variable overwrite or not.
$overwrite_global = et_builder_wc_need_overwrite_global( $args['product'] );
// Check if TB is used
$is_tb = et_builder_tb_enabled();
if ( $is_tb ) {
et_theme_builder_wc_set_global_objects();
} elseif ( $overwrite_global ) {
// Save current global variable for later reset.
$original_product = $product;
$original_post = $post;
$original_wp_query = $wp_query;
// Overwrite global variable.
$post = get_post( $product_id );
$product = wc_get_product( $product_id );
$wp_query = new WP_Query( array( 'p' => $product_id ) );
}
// Get product tabs.
$all_tabs = apply_filters( 'woocommerce_product_tabs', array() );
$active_tabs = isset( $args['include_tabs'] ) ? explode( '|', $args['include_tabs'] ) : false;
$tabs = array();
// Get product tabs data.
foreach ( $all_tabs as $name => $tab ) {
// Skip if current tab is not included, based on `include_tabs` attribute value.
if ( $active_tabs && ! in_array( $name, $active_tabs, true ) ) {
continue;
}
if ( 'description' === $name ) {
if ( ! et_builder_tb_enabled() && ! et_pb_is_pagebuilder_used( $product_id ) ) {
// If selected product doesn't use builder, retrieve post content.
if ( et_theme_builder_overrides_layout( ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE ) ) {
$tab_content = apply_filters( 'et_builder_wc_description', $post->post_content );
} else {
$tab_content = $post->post_content;
}
} else {
/*
* Description can't use built in callback data because it gets `the_content`
* which might cause infinite loop; get Divi's long description from
* post meta instead.
*/
if ( et_builder_tb_enabled() ) {
$placeholders = et_theme_builder_wc_placeholders();
$tab_content = $placeholders['description'];
} else {
$tab_content = get_post_meta( $product_id, ET_BUILDER_WC_PRODUCT_LONG_DESC_META_KEY, true );
// Cannot use `the_content` filter since it adds content wrapper.
// Content wrapper added at
// `includes/builder/core.php`::et_builder_add_builder_content_wrapper()
// This filter is documented at
// includes/builder/feature/woocommerce-modules.php
$tab_content = apply_filters( 'et_builder_wc_description', $tab_content );
}
}
} else {
// Skip if the 'callback' key does not exist.
if ( ! isset( $tab['callback'] ) ) {
continue;
}
// Get tab value based on defined product tab's callback attribute.
ob_start();
// @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
call_user_func( $tab['callback'], $name, $tab );
$tab_content = ob_get_clean();
}
// Populate product tab data.
$tabs[ $name ] = array(
'name' => $name,
'title' => $tab['title'],
'content' => $tab_content,
);
}
// Reset overwritten global variable.
if ( $is_tb ) {
et_theme_builder_wc_reset_global_objects();
} elseif ( $overwrite_global ) {
$product = $original_product;
$post = $original_post;
$wp_query = $original_wp_query;
}
return $tabs;
}
/**
* Gets Multi view attributes to the Outer wrapper.
*
* Since we do not have control over the WooCommerce Breadcrumb markup, we inject Multi view
* attributes on to the Outer wrapper.
*
* @used-by ET_Builder_Module_Tabs::render()
*
* @return string
*/
public function get_multi_view_attrs() {
$multi_view = et_pb_multi_view_options( $this );
$multi_view_attrs = $multi_view->render_attrs(
array(
'attrs' => array(
'data-include_tabs' => '{{include_tabs}}',
),
'target' => '%%order_class%%',
)
);
return $multi_view_attrs;
}
}
new ET_Builder_Module_Woocommerce_Tabs();

View File

@ -0,0 +1,214 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Title class
*
* The ET_Builder_Module_Woocommerce_Title Class is responsible for rendering the
* Title markup using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Title component.
*/
class ET_Builder_Module_Woocommerce_Title extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Title', 'et_builder' );
$this->plural = esc_html__( 'Woo Titles', 'et_builder' );
$this->slug = 'et_pb_wc_title';
$this->vb_support = 'on';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
),
),
'advanced' => array(
'toggles' => array(
'header' => array(
'title' => esc_html__( 'Title Text', 'et_builder' ),
'priority' => 49,
),
'width' => array(
'title' => et_builder_i18n( 'Sizing' ),
'priority' => 65,
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'header' => array(
'label' => et_builder_i18n( 'Title' ),
'css' => array(
'main' => '%%order_class%% h1, %%order_class%% h2, %%order_class%% h3, %%order_class%% h4, %%order_class%% h5, %%order_class%% h6',
),
'header_level' => array(
'default' => 'h1',
),
'tab_slug' => 'advanced',
'toggle_slug' => 'header',
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
'text' => array(
'use_background_layout' => true,
'use_text_orientation' => false,
'css' => array(
'text_shadow' => '%%order_class%% .et_pb_wc_title',
),
'options' => array(
'background_layout' => array(
'default_on_front' => 'light',
'hover' => 'tabs',
),
),
'toggle_slug' => 'header',
),
'text_shadow' => array(
// Don't add text-shadow fields since they already are via font-options.
'default' => false,
),
'button' => false,
);
$this->custom_css_fields = array(
'title_text' => array(
'label' => esc_html__( 'Title Text', 'et_builder' ),
'selector' => '%%order_class%% h1, %%order_class%% h2, %%order_class%% h3, %%order_class%% h4, %%order_class%% h5, %%order_class%% h6',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__title',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__title',
),
)
),
'__title' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Title',
'get_title',
),
'computed_depends_on' => array(
'product',
'product_filter',
),
'computed_minimum' => array(
'product',
),
),
);
return $fields;
}
/**
* Gets the Title.
*
* @param array $args Additional arguments.
*
* @return string
*/
public static function get_title( $args = array() ) {
if ( et_builder_tb_enabled() ) {
return esc_html( 'Product Name', 'et_builder' );
}
$defaults = array(
'product' => 'current',
);
$args = wp_parse_args( $args, $defaults );
$title = et_builder_wc_render_module_template(
'the_title',
$args,
array( 'post' )
);
return $title;
}
/**
* Gets the WooCommerce Product Title markup.
*
* @return string
*/
protected function get_title_markup() {
$header_level = $this->props['header_level'];
$product_title = self::get_title( $this->props );
return sprintf(
'
<%1$s>%2$s</%1$s>',
et_pb_process_header_level( $header_level, 'h1' ),
et_core_esc_previously( $product_title )
);
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
$this->add_classname( $this->get_text_orientation_classname() );
$output = self::get_title_markup();
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Title();

View File

@ -0,0 +1,686 @@
<?php
/**
* 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.
*
* @package Divi\Builder
*
* @since 3.29
*/
/**
* Class representing WooCommerce Upsells component.
*/
class ET_Builder_Module_Woocommerce_Upsells extends ET_Builder_Module {
/**
* Holds Prop values across static methods.
*
* @var array
*/
public static $static_props;
/**
* Initialize.
*/
public function init() {
$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(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
),
),
'advanced' => array(
'toggles' => array(
'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(
'fonts' => array(
'title' => array(
'label' => et_builder_i18n( 'Title' ),
'css' => array(
'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',
'important' => 'all',
),
'font_size' => array(
'default' => '26px',
),
'line_height' => array(
'default' => '1',
),
),
'rating' => array(
'label' => esc_html__( 'Star Rating', 'et_builder' ),
'css' => array(
'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',
),
'font_size' => array(
'default' => 14,
),
'hide_font' => true,
'hide_line_height' => true,
'hide_text_shadow' => true,
'text_align' => array(
'label' => esc_html__( 'Star Rating Alignment', 'et_builder' ),
),
'font_size' => array(
'label' => esc_html__( 'Star Rating Size', 'et_builder' ),
),
'text_color' => array(
'label' => esc_html__( 'Star Rating Color', 'et_builder' ),
),
'toggle_slug' => 'star',
),
'product_title' => array(
'label' => esc_html__( 'Product Title', 'et_builder' ),
'css' => array(
'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",
'important' => 'all',
),
'font_size' => array(
'default' => '1em',
),
'line_height' => array(
'default' => '1',
),
),
'price' => array(
'label' => esc_html__( 'Price', 'et_builder' ),
'css' => array(
'main' => "{$this->main_css_element} ul.products li.product .price, {$this->main_css_element} ul.products li.product .price .amount",
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'range_settings' => array(
'min' => '1',
'max' => '100',
'step' => '1',
),
'default' => floatval( et_get_option( 'body_font_height', '1.7' ) ) . 'em',
),
),
'sale_badge' => array(
'label' => esc_html__( 'Sale Badge', 'et_builder' ),
'css' => array(
'main' => "{$this->main_css_element} ul.products li.product .onsale",
'important' => array( 'line-height', 'font', 'text-shadow' ),
),
'hide_text_align' => true,
'line_height' => array(
'default' => '1.7em',
),
'font_size' => array(
'default' => '20px',
),
'letter_spacing' => array(
'default' => '0px',
),
),
'sale_price' => array(
'label' => esc_html__( 'Sale Price', 'et_builder' ),
'css' => array(
'main' => "{$this->main_css_element} ul.products li.product .price ins .amount",
),
'hide_text_align' => true,
'font' => array(
'default' => '|700|||||||',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'range_settings' => array(
'min' => '1',
'max' => '100',
'step' => '1',
),
'default' => '1.7em',
),
),
),
'borders' => array(
'default' => array(
'css' => array(
'main' => array(
'border_radii' => '%%order_class%%.et_pb_wc_upsells .product',
'border_styles' => '%%order_class%%.et_pb_wc_upsells .product',
),
),
),
'image' => array(
'css' => array(
'main' => array(
'border_radii' => '%%order_class%%.et_pb_module .et_shop_image',
'border_styles' => '%%order_class%%.et_pb_module .et_shop_image',
),
'important' => 'all',
),
'label_prefix' => et_builder_i18n( 'Image' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
),
),
'box_shadow' => array(
'default' => array(
'css' => array(
'main' => '%%order_class%% .product',
),
),
'image' => array(
'label' => esc_html__( 'Image Box Shadow', 'et_builder' ),
'option_category' => 'layout',
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
'css' => array(
'main' => '%%order_class%% .et_shop_image',
'overlay' => 'inset',
),
'default_on_fronts' => array(
'color' => '',
'position' => '',
),
),
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%%',
// Needed to overwrite last module margin-bottom styling.
'important' => array( 'custom_margin' ),
),
),
'text' => array(
'css' => array(
'text_shadow' => implode(
', ',
array(
// Title.
"{$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",
// Price.
"{$this->main_css_element} ul.products .price",
"{$this->main_css_element} ul.products .price .amount",
)
),
),
),
'filters' => array(
'child_filters_target' => array(
'tab_slug' => 'advanced',
'toggle_slug' => 'image',
),
),
'image' => array(
'css' => array(
'main' => '%%order_class%% .et_shop_image',
),
),
'button' => false,
);
$this->custom_css_fields = array(
'product' => array(
'label' => esc_html__( 'Product', 'et_builder' ),
'selector' => 'li.product',
),
'onsale' => array(
'label' => esc_html__( 'Onsale', 'et_builder' ),
'selector' => 'li.product .onsale',
),
'image' => array(
'label' => et_builder_i18n( 'Image' ),
'selector' => '.et_shop_image',
),
'overlay' => array(
'label' => et_builder_i18n( 'Overlay' ),
'selector' => '.et_overlay',
),
'title' => array(
'label' => et_builder_i18n( 'Title' ),
'selector' => ET_Builder_Module_Helper_Woocommerce_Modules::get_title_selector(),
),
'rating' => array(
'label' => esc_html__( 'Star Rating', 'et_builder' ),
'selector' => '.star-rating',
),
'price' => array(
'label' => esc_html__( 'Price', 'et_builder' ),
'selector' => 'li.product .price',
),
'price_old' => array(
'label' => esc_html__( 'Old Price', 'et_builder' ),
'selector' => 'li.product .price del span.amount',
),
);
$this->help_videos = array(
array(
'id' => '7X03vBPYJ1o',
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'product' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_product_default(),
'computed_affects' => array(
'__upsells',
),
)
),
'product_filter' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'product_filter',
array(
'computed_affects' => array(
'__upsells',
),
)
),
'posts_number' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'posts_number',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_columns_posts_default(),
'computed_affects' => array(
'__upsells',
),
)
),
'columns_number' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'columns_number',
array(
'default' => ET_Builder_Module_Helper_Woocommerce_Modules::get_columns_posts_default(),
'computed_affects' => array(
'__upsells',
),
)
),
'orderby' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'orderby',
array(
'options' => array(
'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(
'__upsells',
),
)
),
'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' ),
'type' => 'color-alpha',
'custom_color' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'sale_badge',
'hover' => 'tabs',
'mobile_options' => true,
'sticky' => 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' ),
'type' => 'color-alpha',
'custom_color' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'sticky' => 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' ),
'type' => 'color-alpha',
'custom_color' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'sticky' => true,
),
'hover_icon' => array(
'label' => esc_html__( 'Overlay Icon', 'et_builder' ),
'description' => esc_html__( 'Here you can define a custom icon for the overlay', 'et_builder' ),
'type' => 'select_icon',
'option_category' => 'configuration',
'class' => array( 'et-pb-font-icon' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'overlay',
'mobile_options' => true,
'sticky' => true,
),
'__upsells' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Upsells',
'get_upsells',
),
'computed_depends_on' => array(
'product',
'product_filter',
'posts_number',
'columns_number',
'orderby',
),
'computed_minimum' => array(
'product',
),
),
);
return $fields;
}
/**
* {@inheritdoc}
*/
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',
);
return $fields;
}
/**
* 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.
*
* @return string
*/
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
// default value
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' );
}
add_filter(
'woocommerce_upsell_display_args',
array(
'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
*/
$args['order'] = 'asc';
}
}
$output = et_builder_wc_render_module_template( 'woocommerce_upsell_display', $args );
remove_filter(
'woocommerce_upsell_display_args',
array(
'ET_Builder_Module_Woocommerce_Upsells',
'set_upsell_display_args',
)
);
return $output;
}
/**
* Returns the User selected Posts per page, columns and Order by values to WooCommerce.
*
* @param array $args Documented at
* {@see woocommerce_upsell_display()}.
*
* @return array
*/
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()
*
* @return array
*/
public static function get_selected_upsell_display_args() {
$selected_args = array();
$selected_args['posts_per_page'] = et_()->array_get(
self::$static_props,
'posts_number',
''
);
$selected_args['columns'] = et_()->array_get(
self::$static_props,
'columns_number',
''
);
$selected_args['orderby'] = et_()->array_get(
self::$static_props,
'orderby',
''
);
// Set default values when parameters are empty.
$default = ET_Builder_Module_Helper_Woocommerce_Modules::get_columns_posts_default_value();
if ( empty( $selected_args['posts_per_page'] ) ) {
$selected_args['posts_per_page'] = $default;
}
if ( empty( $selected_args['columns'] ) ) {
$selected_args['columns'] = $default;
}
$selected_args = array_filter( $selected_args, 'strlen' );
return $selected_args;
}
/**
* Renders the module output.
*
* @param array $attrs List of attributes.
* @param string $content Content being processed.
* @param string $render_slug Slug of module that is used for rendering output.
*
* @return string
*/
public function render( $attrs, $content, $render_slug ) {
ET_Builder_Module_Helper_Woocommerce_Modules::process_background_layout_data( $render_slug, $this );
ET_Builder_Module_Helper_Woocommerce_Modules::add_star_rating_style(
$render_slug,
$this->props,
'%%order_class%% ul.products li.product .star-rating',
'%%order_class%% ul.products li.product:hover .star-rating'
);
// Sale Badge Color.
$this->generate_styles(
array(
'base_attr_name' => 'sale_badge_color',
'selector' => '%%order_class%% span.onsale',
'css_property' => 'background-color',
'important' => true,
'render_slug' => $render_slug,
'type' => 'color',
)
);
// Icon Hover Color.
$this->generate_styles(
array(
'hover' => false,
'base_attr_name' => 'icon_hover_color',
'selector' => '%%order_class%% .et_overlay:before',
'css_property' => 'color',
'important' => true,
'render_slug' => $render_slug,
'type' => 'color',
)
);
// Hover Overlay Color.
$this->generate_styles(
array(
'hover' => false,
'base_attr_name' => 'hover_overlay_color',
'selector' => '%%order_class%% .et_overlay',
'css_property' => array( 'background-color', 'border-color' ),
'important' => true,
'render_slug' => $render_slug,
'type' => 'color',
)
);
// Extended Icon Styles.
$this->generate_styles(
array(
'utility_arg' => 'icon_font_family',
'render_slug' => $render_slug,
'base_attr_name' => 'hover_icon',
'important' => true,
'selector' => '%%order_class%% .et_overlay:before',
'processor' => array(
'ET_Builder_Module_Helper_Style_Processor',
'process_extended_icon',
),
)
);
// Images: Add CSS Filters and Mix Blend Mode rules (if set).
if ( array_key_exists( 'image', $this->advanced_fields ) && array_key_exists( 'css', $this->advanced_fields['image'] ) ) {
$this->add_classname(
$this->generate_css_filters(
$render_slug,
'child_',
self::$data_utils->array_get( $this->advanced_fields['image']['css'], 'main', '%%order_class%%' )
)
);
}
$this->add_classname( $this->get_text_orientation_classname() );
$is_shop = function_exists( 'is_shop' ) && is_shop();
$is_wc_loop_prop_get_set_exists = function_exists( 'wc_get_loop_prop' ) && function_exists( 'wc_set_loop_prop' );
$is_product_category = function_exists( 'is_product_category' ) && is_product_category();
if ( $is_shop ) {
$display_type = ET_Builder_Module_Helper_Woocommerce_Modules::set_display_type_to_render_only_products( 'woocommerce_shop_page_display' );
} elseif ( is_product_category() ) {
$display_type = ET_Builder_Module_Helper_Woocommerce_Modules::set_display_type_to_render_only_products( 'woocommerce_category_archive_display' );
}
// Required to handle Customizer preview pane.
// Refer: https://github.com/elegantthemes/Divi/issues/17998#issuecomment-565955422
if ( $is_wc_loop_prop_get_set_exists && is_customize_preview() ) {
$is_filtered = wc_get_loop_prop( 'is_filtered' );
wc_set_loop_prop( 'is_filtered', true );
}
$output = self::get_upsells( $this->props );
// Required to handle Customizer preview pane.
// Refer: https://github.com/elegantthemes/Divi/issues/17998#issuecomment-565955422
if ( $is_wc_loop_prop_get_set_exists && is_customize_preview() && isset( $is_filtered ) ) {
wc_set_loop_prop( 'is_filtered', $is_filtered );
}
if ( $is_shop && isset( $display_type ) ) {
ET_Builder_Module_Helper_Woocommerce_Modules::reset_display_type( 'woocommerce_shop_page_display', $display_type );
} elseif ( $is_product_category && isset( $display_type ) ) {
ET_Builder_Module_Helper_Woocommerce_Modules::reset_display_type( 'woocommerce_category_archive_display', $display_type );
}
// Render empty string if no output is generated to avoid unwanted vertical space.
if ( '' === $output ) {
return '';
}
add_filter(
"et_builder_module_{$render_slug}_outer_wrapper_attrs",
array(
'ET_Builder_Module_Helper_Woocommerce_Modules',
'output_data_icon_attrs',
),
10,
2
);
$output = $this->_render_module_wrapper( $output, $render_slug );
remove_filter(
"et_builder_module_{$render_slug}_outer_wrapper_attrs",
array(
'ET_Builder_Module_Helper_Woocommerce_Modules',
'output_data_icon_attrs',
),
10
);
return $output;
}
}
new ET_Builder_Module_Woocommerce_Upsells();