Commit realizado el 12:13:52 08-04-2024

This commit is contained in:
Pagina Web Monito
2024-04-08 12:13:55 -04:00
commit 0c33094de9
7815 changed files with 1365694 additions and 0 deletions

View File

@@ -0,0 +1,660 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* 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 Product Add To Cart', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Add To Cart', 'et_builder' );
$this->slug = 'et_pb_wc_add_to_cart';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
'elements' => et_builder_i18n( 'Elements' ),
),
),
'advanced' => array(
'toggles' => array(
'field_label' => array(
'title' => esc_html__( 'Field Labels', 'et_builder' ),
),
'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(
'field_label' => array(
'label' => esc_html__( 'Field Labels', 'et_builder' ),
'css' => array(
'main' => implode(
',',
array(
'%%order_class%% label',
)
),
),
'font' => array(
'default' => '|700|||||||',
),
'font_size' => array(
'default' => '14px',
),
'toggle_slug' => 'field_label',
),
),
'background' => array(
'settings' => array(
'color' => 'alpha',
),
),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
'text' => array(
'use_background_layout' => false,
'css' => array(
'main' => '%%order_class%% td.label',
'text_shadow' => '%%order_class%% td.label',
),
'options' => array(
'text_orientation' => array(
'default' => 'left',
),
),
),
'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',
),
'field_label_position' => array(
'label' => esc_html__( 'Fields Label Position', 'et_builder' ),
'description' => esc_html__( 'Set the position of the field labels.', 'et_builder' ),
'type' => 'select',
'option_category' => 'configuration',
'options' => array(
'inline' => __( 'Inline', 'et_builder' ),
'stacked' => __( 'Stacked', 'et_builder' ),
),
'default' => 'default',
'tab_slug' => 'advanced',
'toggle_slug' => 'field_label',
'mobile_options' => true,
'priority' => 15,
),
'__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;
}
/**
* Replaces the Add to Cart form's action.
*
* @since 4.14.0
*
* @param string $permalink Permalink.
*
* @return string
*/
public static function replace_add_to_cart_form_action( $permalink ) {
$the_id = et_core_page_resource_get_the_ID();
if ( 0 === absint( et_core_page_resource_get_the_ID() ) ) {
return $permalink;
}
$link = get_permalink( $the_id );
// Validate if Post exists.
return $link ? $link : $permalink;
}
/**
* Get add to cart markup as string
*
* @since 4.14.0 Update Add to Cart Form action {@see https://github.com/elegantthemes/Divi/issues/16682}
*
* @since 4.4.0 Fixed compatibility w/ WooCommerce Product Add-ons
* @see https://github.com/elegantthemes/Divi/issues/19116
*
* @param array $args Arguments from Computed Prop AJAX call.
* @param array $conditional_tags Conditional Tags.
*
* @return string
*/
public static function get_add_to_cart( $args = array(), $conditional_tags = array() ) {
$is_tb = 'true' === et_()->array_get( $conditional_tags, 'is_tb', 'false' );
$is_bfb = 'true' === et_()->array_get( $conditional_tags, 'is_bfb', 'false' );
$is_bfb_activated = 'true' === et_()->array_get( $conditional_tags, 'is_bfb_activated', 'false' );
$is_builder = $is_tb || $is_bfb || $is_bfb_activated || is_et_pb_preview();
if ( ! $is_builder ) {
add_filter(
'woocommerce_add_to_cart_form_action',
array(
'ET_Builder_Module_Woocommerce_Add_To_Cart',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- This is a function call.
'replace_add_to_cart_form_action'
)
);
}
$output = et_builder_wc_render_module_template(
'woocommerce_template_single_add_to_cart',
$args,
array( 'product', 'post' )
);
if ( ! $is_builder ) {
remove_filter(
'woocommerce_add_to_cart_form_action',
array(
'ET_Builder_Module_Woocommerce_Add_To_Cart',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- This is a function call.
'replace_add_to_cart_form_action'
)
);
}
return $output;
}
/**
* 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',
),
'et_pb_fields_label_position_inline' => array(
'field_label_position' => 'inline',
),
'et_pb_fields_label_position_stacked' => array(
'field_label_position' => 'stacked',
),
),
),
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' );
}
$fields_label_position = et_()->array_get( $this->props, 'field_label_position', 'inline' );
$this->add_classname( "et_pb_fields_label_position_{$fields_label_position}" );
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,584 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* 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 Product Information', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Information', 'et_builder' );
$this->slug = 'et_pb_wc_additional_info';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$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' ),
),
'table' => array(
'title' => esc_html__( 'Table', 'et_builder' ),
'priority' => 70,
),
'table_row' => array(
'title' => esc_html__( 'Table Row', 'et_builder' ),
'priority' => 75,
),
'table_cell' => array(
'title' => esc_html__( 'Table Cell', 'et_builder' ),
'priority' => 80,
),
),
),
);
$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,
'form_field' => array(
'table' => array(
'label' => esc_html__( 'Table', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% table.shop_attributes',
),
'font_field' => false,
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% table.shop_attributes',
),
'use_padding' => false,
),
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'border_styles' => array(
'table' => array(
'label_prefix' => 'Table',
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% table.shop_attributes',
'border_radii' => '%%order_class%% table.shop_attributes',
),
),
'use_focus_borders' => false,
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'dotted',
),
'composite' => array(
'border_top' => array(
'border_width_top' => '1px',
),
),
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% table.shop_attributes',
),
),
),
'table_row' => array(
'label' => esc_html__( 'Table Row', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% table.shop_attributes tr',
),
'font_field' => false,
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% table.shop_attributes tr th, %%order_class%% table.shop_attributes tr td',
),
'use_margin' => false,
),
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'border_styles' => array(
'table_row' => array(
'label_prefix' => 'Table Row',
'css' => array(
'main' => array(
// Accepts only string and not array. Hence using `implode`.
'border_radii' => implode(
', ',
array(
'%%order_class%% table.shop_attributes th',
'%%order_class%% table.shop_attributes td',
)
),
'border_styles' => implode(
', ',
array(
'%%order_class%% table.shop_attributes th',
'%%order_class%% table.shop_attributes td',
)
),
),
'important' => true,
),
'use_focus_borders' => false,
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '1px',
'style' => 'dotted',
),
),
),
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% table.shop_attributes tr',
),
),
),
'table_row' => array(
'label' => esc_html__( 'Table Row', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% table.shop_attributes tr',
),
'font_field' => false,
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% table.shop_attributes tr th, %%order_class%% table.shop_attributes tr td',
),
'use_margin' => false,
),
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'border_styles' => array(
'table_row' => array(
'label_prefix' => 'Table Row',
'css' => array(
'main' => array(
// Accepts only string and not array. Hence using `implode`.
'border_radii' => implode(
', ',
array(
'%%order_class%% table.shop_attributes th',
'%%order_class%% table.shop_attributes td',
)
),
'border_styles' => implode(
', ',
array(
'%%order_class%% table.shop_attributes th',
'%%order_class%% table.shop_attributes td',
)
),
),
),
'use_focus_borders' => false,
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '1px',
'style' => 'dotted',
),
),
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% table.shop_attributes tr',
),
),
),
'table_cell' => array(
'label' => esc_html__( 'Table Cell', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% table.shop_attributes tr th, %%order_class%% table.shop_attributes tr td',
),
'font_field' => false,
'margin_padding' => array(
'css' => array(
'main' => implode(
', ',
array(
'%%order_class%% table.shop_attributes tr th',
'%%order_class%% table.shop_attributes tr td',
)
),
),
'use_margin' => false,
),
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'border_styles' => array(
'table_cell' => array(
'label_prefix' => 'Table Cell',
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% table.shop_attributes tr th,%%order_class%% table.shop_attributes tr td',
'border_radii' => '%%order_class%% table.shop_attributes tr th, %%order_class%% table.shop_attributes tr td',
),
),
'use_focus_borders' => false,
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '1px',
'style' => 'dotted',
),
'composite' => array(
'border_top' => array(
'border_width_top' => '1px',
),
),
),
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% table.shop_attributes tr th, %%order_class%% table.shop_attributes td',
),
),
),
),
);
$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 );
$table_row_bg_color = et_()->array_get( $this->props, 'table_row_background_color', '' );
if ( ! empty( $table_row_bg_color ) ) {
ET_Builder_Element::set_style(
$render_slug,
array(
'selector' => implode(
',',
array(
'%%order_class%% table.shop_attributes tr:nth-child(even) th',
'%%order_class%% table.shop_attributes tr:nth-child(even) td',
)
),
'declaration' => 'background: inherit',
)
);
}
$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,372 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* 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 Breadcrumbs', 'et_builder' );
$this->plural = esc_html__( 'Woo Breadcrumbs', 'et_builder' );
$this->slug = 'et_pb_wc_breadcrumb';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$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(
'css' => array(
// Backgrounds need to be applied to module wrapper.
'main' => '%%order_class%%.et_pb_wc_breadcrumb',
),
'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() || is_et_pb_preview() ) ) {
$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();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,587 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Checkout_Additional_Info class
*
* The ET_Builder_Module_Woocommerce_Checkout_Additional_Info Class is responsible for rendering the
* Checkout Additional Info section using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 4.14.0
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Checkout Additional Info component.
*/
final class ET_Builder_Module_Woocommerce_Checkout_Additional_Info extends ET_Builder_Module {
/**
* Initialize.
*
* @since 4.14.0 Fixed PHP Warnings {@link https://github.com/elegantthemes/Divi/issues/22104}
*/
public function init() {
$this->name = esc_html__( 'Woo Checkout Information', 'et_builder' );
$this->plural = esc_html__( 'Woo Checkout Information', 'et_builder' );
$this->slug = 'et_pb_wc_checkout_additional_info';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'elements' => esc_html__( 'Elements', 'et_builder' ),
),
),
'advanced' => array(
'toggles' => array(
'title' => array(
'title' => esc_html__( 'Title Text', 'et_builder' ),
'priority' => 49,
),
'field_label' => array(
'title' => esc_html__( 'Field Labels', 'et_builder' ),
'priority' => 60,
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'title' => array(
'label' => esc_html__( 'Title', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% h3',
),
'font_size' => array(
'default' => '22px',
),
'line_height' => array(
'default' => '1em',
),
'tab_slug' => 'advanced',
'toggle_slug' => 'title',
),
'field_label' => array(
'label' => esc_html__( 'Field Label', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% form .form-row label',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '2em',
),
'toggle_slug' => 'field_label',
),
),
'text' => array(
'use_background_layout' => false,
'use_text_orientation' => true,
),
'button' => false,
'link_options' => false,
'form_field' => array(
'form_field' => array(
'label' => esc_html__( 'Fields', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% form .form-row .input-text',
'focus_text_color' => implode(
',',
[
'.woocommerce %%order_class%% form .form-row .input-text:focus',
'.woocommerce-page %%order_class%% form .form-row .input-text:focus',
]
),
),
'box_shadow' => false,
'border_styles' => array(
'form_field' => array(
'label_prefix' => esc_html__( 'Fields', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% .et_pb_module_inner form .form-row textarea',
'border_radii' => '%%order_class%% .et_pb_module_inner form .form-row textarea',
),
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
),
),
),
),
'form_field_focus' => array(
'label_prefix' => esc_html__( 'Fields Focus', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% form .form-row textarea.input-text:focus',
'border_radii' => '%%order_class%% form .form-row textarea.input-text:focus',
),
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
),
),
),
),
),
'font_field' => array(
'css' => array(
'main' => implode(
', ',
array(
'%%order_class%% form .form-row .input-text',
'%%order_class%% form .form-row .input-text::placeholder',
'%%order_class%% form .form-row .input-text::-webkit-input-placeholder',
'%%order_class%% form .form-row .input-text::-moz-placeholder',
'%%order_class%% form .form-row .input-text:-ms-input-placeholder',
)
),
'hover' => implode(
', ',
array(
'%%order_class%% form .input-text',
'%%order_class%% form .input-text:hover::placeholder',
'%%order_class%% form .input-text:hover::-webkit-input-placeholder',
'%%order_class%% form .input-text:hover::-moz-placeholder',
'%%order_class%% form .input-text:hover:-ms-input-placeholder',
)
),
// Required to override default WooCommerce styles.
'important' => array( 'line-height', 'font', 'size' ),
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.7em',
),
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% form .form-row textarea',
'padding' => '%%order_class%% form .form-row textarea.input-text',
),
'custom_padding' => array(
'default' => '15px|15px|15px|15px|false|false',
),
),
'width' => array(),
'toggle_priority' => 65,
),
),
);
$this->custom_css_fields = array(
'title_text' => array(
'label' => esc_html__( 'Title Text', 'et_builder' ),
'selector' => '%%order_class%% h3',
),
'field_label' => array(
'label' => esc_html__( 'Field Label', 'et_builder' ),
'selector' => '%%order_class%% form .form-row label',
),
'fields' => array(
'label' => esc_html__( 'Fields', 'et_builder' ),
'selector' => '%%order_class%% form .input-text',
),
'fields_placeholder' => array(
'label' => esc_html__( 'Fields Placeholder', 'et_builder' ),
'selector' => implode(
', ',
array(
'%%order_class%% form .form-row .input-text::placeholder',
'%%order_class%% form .form-row .input-text::-webkit-input-placeholder',
'%%order_class%% form .form-row .input-text::-moz-placeholder',
'%%order_class%% form .form-row .input-text:-ms-input-placeholder',
)
),
),
);
$this->help_videos = array(
array(
'id' => esc_html( '7X03vBPYJ1o' ),
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'show_title' => array(
'label' => esc_html__( 'Show Title', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Turn title on or off.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'placeholder_color' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'placeholder_color'
),
'__checkout_additional_info' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Checkout_Additional_Info',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
'get_additional_info'
),
'computed_depends_on' => array(
/*
* `depends_on` arg is required. Otherwise AJAX will return null.
* @see et_pb_process_computed_property().
* `product` will not be processed since there is no definition in
* @see ET_Builder_Module_Woocommerce_Checkout_Order::get_fields()
*/
'product',
),
),
);
return $fields;
}
/**
* Reset hooks.
*/
public static function maybe_reset_hooks( $conditional_tags ) {
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_order_review();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_payment();
if ( ! et_fb_is_computed_callback_ajax() && ! $is_tb ) {
remove_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Additional_Info',
'swap_template',
],
10,
5
);
}
}
/**
* Handle hooks.
*/
public static function maybe_handle_hooks( $conditional_tags ) {
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_order_review();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_payment();
if ( ! et_fb_is_computed_callback_ajax() && ! $is_tb ) {
add_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Additional_Info',
'swap_template',
],
10,
5
);
}
}
/**
* Invoke WooCommerce hooks.
*
* When Dynamic framework is enabled, some of WooCommerce's actions/filters
* won't be invoked because of lazy loading.
*
* Since WooCommerce's hooks are required before render() they are
* invoked using the `et_builder_module_lazy_shortcodes_registered` hook.
*
* @see et_builder_wc_init()
* @see ET_Builder_Module_Shortcode_Manager::register_all_shortcodes()
*/
public static function maybe_invoke_woocommerce_hooks() {
/*
* The respective remove_filter is used at
*
* @see ET_Builder_Module_Woocommerce_Checkout_Additional_Info::get_additional_info()
*/
add_filter(
'woocommerce_checkout_fields',
array(
'ET_Builder_Module_Woocommerce_Checkout_Additional_Info',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
'modify_order_comments_rows'
)
);
}
/**
* Increases the Checkout Information Textarea `rows` attribute.
*
* @param array $fields Array of checkout fields.
*
* @return array
*/
public static function modify_order_comments_rows( $fields ) {
if ( ! is_array( $fields ) ) {
return $fields;
}
if ( ! isset( $fields['order'] ) || ! isset( $fields['order']['order_comments'] ) ) {
return $fields;
}
$fields['order']['order_comments']['custom_attributes']['rows'] = 4;
return $fields;
}
/**
* {@inheritdoc}
*/
public function get_transition_fields_css_props() {
$fields = parent::get_transition_fields_css_props();
$fields['placeholder_color'] = array(
'color' => array(
'%%order_class%% form .form-row textarea.input-text::placeholder',
'%%order_class%% form .form-row textarea.input-text::-webkit-input-placeholder',
'%%order_class%% form .form-row textarea.input-text::-moz-placeholder',
'%%order_class%% form .form-row textarea.input-text:-ms-input-placeholder',
),
);
return $fields;
}
/**
* Swaps Checkout Order Details template.
*
* Coupon Remove Link must be shown in VB. Hence we swap the template.
*
* @param string $template Template.
* @param string $template_name Template name.
* @param array $args Arguments.
* @param string $template_path Template path.
* @param string $default_path Default path.
*
* @return string
*/
public static function swap_template( $template, $template_name, $args, $template_path, $default_path ) {
$is_template_override = in_array(
$template_name,
array(
'checkout/form-checkout.php',
),
true
);
if ( $is_template_override ) {
return trailingslashit( ET_BUILDER_DIR ) . 'feature/woocommerce/templates/' . $template_name;
}
return $template;
}
/**
* Gets the Checkout Additional Info markup.
*
* @param array $args Settings used to render the module's output.
* Refer ET_Builder_Element::props.
*
* @return string
*/
public static function get_additional_info( $args = array(), $conditional_tags = array() ) {
self::maybe_handle_hooks( $conditional_tags );
$is_cart_empty = function_exists( 'WC' ) && isset( WC()->cart ) && WC()->cart->is_empty();
// Is Page Builder mode?.
$is_pb_mode = et_fb_is_computed_callback_ajax() || is_et_pb_preview();
// Set dummy cart contents to output Additional Information when no product is in cart.
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
add_filter(
'woocommerce_get_cart_contents',
array(
'ET_Builder_Module_Helper_Woocommerce_Modules',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
'set_dummy_cart_contents'
)
);
}
// Show Checkout Additional Info module title.
add_filter( 'woocommerce_cart_needs_shipping', '__return_false' );
add_filter(
'woocommerce_checkout_fields',
array(
'ET_Builder_Module_Woocommerce_Checkout_Additional_Info',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
'modify_order_comments_rows'
)
);
ob_start();
WC_Shortcode_Checkout::output( array() );
$markup = ob_get_clean();
remove_filter(
'woocommerce_checkout_fields',
array(
'ET_Builder_Module_Woocommerce_Checkout_Additional_Info',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
'modify_order_comments_rows'
)
);
// Reset showing Checkout Additional Info module title.
remove_filter( 'woocommerce_cart_needs_shipping', '__return_false' );
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
remove_filter(
'woocommerce_get_cart_contents',
array(
'ET_Builder_Module_Helper_Woocommerce_Modules',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
'set_dummy_cart_contents'
)
);
}
self::maybe_reset_hooks( $conditional_tags );
// Fallback.
if ( ! is_string( $markup ) ) {
$markup = '';
}
return $markup;
}
/**
* 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.
*
* @since 4.14.0
*
* @param array $outer_wrapper_attrs Outer wrapper attributes.
*
* @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_no_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 ) {
if ( function_exists( 'is_order_received_page' )
&& is_order_received_page() ) {
return '';
}
// Add classes to hide disabled elements.
if ( 'off' === $this->prop( 'show_title', 'on' ) ) {
$this->add_classname( 'et_pb_wc_no_title' );
}
$this->add_classname( $this->get_text_orientation_classname() );
add_filter( "et_builder_module_{$render_slug}_outer_wrapper_attrs", array( $this, 'add_multi_view_attrs' ) );
// Placeholder Color.
$placeholder_selectors = array(
'%%order_class%% form .form-row textarea.input-text::placeholder',
'%%order_class%% form .form-row textarea.input-text::-webkit-input-placeholder',
'%%order_class%% form .form-row textarea.input-text::-moz-placeholder',
'%%order_class%% form .form-row textarea.input-text:-ms-input-placeholder',
);
$this->generate_styles(
array(
'base_attr_name' => 'placeholder_color',
'selector' => join( ', ', $placeholder_selectors ),
'hover_pseudo_selector_location' => 'suffix',
'sticky_pseudo_selector_location' => 'prefix',
'css_property' => 'color',
'important' => false,
'render_slug' => $render_slug,
'type' => 'color',
)
);
global $wp;
if ( ! empty( $wp->query_vars['order-pay'] ) ) {
$this->add_classname( 'et_pb_wc_order_pay' );
}
if ( isset( WC()->cart )
&& ! is_null( WC()->cart && method_exists( WC()->cart, 'check_cart_items' ) )
&& ! is_et_pb_preview() ) {
$return = WC()->cart->check_cart_items();
if ( wc_notice_count( 'error' ) > 0 ) {
$this->add_classname( 'et_pb_hide_module' );
}
}
$output = self::get_additional_info( $this->props );
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Checkout_Additional_Info();

View File

@@ -0,0 +1,674 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Checkout_Billing class
*
* The ET_Builder_Module_Woocommerce_Checkout_Billing Class is responsible for rendering the
* Checkout billing section using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 4.14.0
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Checkout billing component.
*/
class ET_Builder_Module_Woocommerce_Checkout_Billing extends ET_Builder_Module {
/**
* Initialize.
*
* @since 4.14.0 Fixed PHP Warnings {@link https://github.com/elegantthemes/Divi/issues/22104}
*/
public function init() {
$this->name = esc_html__( 'Woo Checkout Billing', 'et_builder' );
$this->plural = esc_html__( 'Woo Checkout Billing', 'et_builder' );
$this->slug = 'et_pb_wc_checkout_billing';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$this->settings_modal_toggles = array(
'advanced' => array(
'toggles' => array(
'layout' => array(
'title' => et_builder_i18n( 'Layout' ),
'priority' => 45,
),
'title' => array(
'title' => esc_html__( 'Title Text', 'et_builder' ),
'priority' => 55,
),
'field_label' => array(
'title' => esc_html__( 'Field Labels', 'et_builder' ),
'priority' => 60,
),
'form_field' => array(
'title' => esc_html__( 'Fields', 'et_builder' ),
'priority' => 65,
),
'form_notice' => array(
'title' => esc_html__( 'Form Notice', 'et_builder' ),
'priority' => 70,
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
// Use `title` in place of `header` since `header` needs a workaround in Copy/Paste.
'title' => array(
'label' => esc_html__( 'Title', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% h3',
),
'font_size' => array(
'default' => '22px',
),
'line_height' => array(
'default' => '1em',
),
'tab_slug' => 'advanced',
'toggle_slug' => 'title',
),
'field_label' => array(
'label' => esc_html__( 'Field Label', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% form .form-row label',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '2em',
),
'toggle_slug' => 'field_label',
),
),
'text' => array(
'use_background_layout' => false,
'use_text_orientation' => true,
),
'button' => false,
'link_options' => false,
'form_field' => array(
'form_field' => array(
'label' => esc_html__( 'Fields', 'et_builder' ),
'css' => array(
'main' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single',
'.woocommerce %%order_class%% form .form-row .input-text',
)
),
'background_color_hover' => implode(
',',
[
'%%order_class%% .select2-container--default .select2-selection--single:hover',
'.woocommerce %%order_class%% form .form-row .input-text:hover',
]
),
'focus_background_color' => implode(
',',
[
'.woocommerce %%order_class%% .select2-container--open .select2-selection',
'.woocommerce %%order_class%% form .input-text:focus',
]
),
'focus_background_color_hover' => implode(
',',
[
'.woocommerce %%order_class%% .select2-container--open:hover .select2-selection',
'.woocommerce %%order_class%% form .input-text:focus:hover',
]
),
'focus_text_color' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--open .select2-selection__rendered',
'.woocommerce %%order_class%% form .form-row input.input-text:focus',
)
),
'focus_text_color_hover' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--open:hover .select2-selection__rendered',
'.woocommerce %%order_class%% form .form-row input.input-text:focus:hover',
)
),
'form_text_color' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single .select2-selection__rendered',
'.woocommerce %%order_class%% form .form-row .input-text',
)
),
'form_text_color_hover' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container .select2-selection--single:hover .select2-selection__rendered',
'.woocommerce %%order_class%% form .form-row .input-text:hover',
)
),
),
'box_shadow' => array(
'css' => array(
'main' => implode(
',',
array(
'%%order_class%% .select2-container--default .select2-selection--single',
'%%order_class%% form .form-row input.input-text',
)
),
),
),
'border_styles' => array(
'form_field' => array(
'label_prefix' => esc_html__( 'Fields', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single',
'.woocommerce %%order_class%% form .form-row .input-text',
)
),
'border_radii' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single',
'.woocommerce %%order_class%% form .form-row input.input-text',
)
),
),
),
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
),
),
),
'form_field_focus' => array(
'label_prefix' => esc_html__( 'Fields Focus', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default.select2-container--open .select2-selection--single',
'.woocommerce %%order_class%% form .form-row .input-text:focus',
)
),
'border_radii' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default.select2-container--open .select2-selection--single',
'.woocommerce %%order_class%% form .form-row input.input-text:focus',
)
),
),
),
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
),
),
),
),
'font_field' => array(
'css' => array(
'main' => implode(
',',
[
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single',
'.woocommerce %%order_class%% form .form-row .input-text',
]
),
// Required to override default WooCommerce styles.
'important' => array( 'line-height', 'size', 'font' ),
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.7em',
),
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% form .form-row input.input-text, %%order_class%% .select2-container--default .select2-selection--single .select2-selection__rendered',
'padding' => '%%order_class%% form .form-row input.input-text, %%order_class%% .select2-container--default .select2-selection--single',
'margin' => '%%order_class%% form .form-row input.input-text, %%order_class%% .select2-container--default .select2-selection--single',
),
),
'width' => array(),
'toggle_priority' => 55,
),
'form_notice' => array(
'label' => esc_html__( 'Form Notice', 'et_builder' ),
'css' => array(
'form_text_color' => '%%order_class%% .woocommerce-error li',
'background_color' => '%%order_class%% .woocommerce-error',
'important' => array( 'background_color' ),
),
'background_color' => array(
'description' => esc_html__( 'Pick a color to fill the module\'s notice.', 'et_builder' ),
),
'text_color' => array(
'description' => esc_html__( 'Pick a color to be used for the text written inside notice.', 'et_builder' ),
),
'focus_background_color' => false,
'focus_text_color' => false,
'font_field' => array(
'css' => array(
'main' => '%%order_class%% .woocommerce-NoticeGroup .woocommerce-error',
'important' => array( 'text-shadow', 'size' ),
'text_shadow' => '%%order_class%% .woocommerce-NoticeGroup .woocommerce-error',
),
'font_size' => array(
'default' => '18px',
),
'line_height' => array(
'default' => '1.7em',
),
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% .woocommerce-error',
'important' => array( 'custom_padding' ),
),
'custom_padding' => array(
'default' => '15px|15px|15px|15px|false|false',
),
),
'border_styles' => array(
'form_notice' => array(
'label_prefix' => esc_html__( 'Form Notice', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% .woocommerce-error',
'border_radii' => '%%order_class%% .woocommerce-error',
),
'important' => true,
),
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
),
),
'use_focus_borders' => false,
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% .woocommerce-error',
'important' => true,
),
),
),
),
);
$this->custom_css_fields = array(
'title_text' => array(
'label' => esc_html__( 'Title Text', 'et_builder' ),
'selector' => '%%order_class%% h3',
),
'field_label' => array(
'label' => esc_html__( 'Field Label', 'et_builder' ),
'selector' => '%%order_class%% form .form-row label',
),
'form_field' => array(
'label' => esc_html__( 'Fields', 'et_builder' ),
'selector' => implode(
',',
array(
'%%order_class%% .select2-container--default .select2-selection--single',
'%%order_class%% form .form-row .input-text',
)
),
),
'form_notice' => array(
'label' => esc_html__( 'Form Notice', 'et_builder' ),
'selector' => '%%order_class%% .woocommerce-error',
),
);
$this->help_videos = array(
array(
'id' => esc_html( '7X03vBPYJ1o' ),
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'required_field_indicator_color' => array(
'label' => esc_html__(
'Required Field Indicator Color',
'et_builder'
),
'description' => esc_html__(
'Pick a color to be used for the required field indicator.',
'et_builder'
),
'type' => 'color-alpha',
'option_category' => 'button',
'custom_color' => true,
'default' => '',
'tab_slug' => 'advanced',
'toggle_slug' => 'field_label',
'hover' => 'tabs',
'mobile_options' => true,
'priority' => 5,
),
'fields_width' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'fields_width'
),
'__checkout_billing' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Checkout_Billing',
'get_checkout_billing',
),
'computed_depends_on' => array(
/*
* `depends_on` arg is required. Otherwise AJAX will return null.
* @see et_pb_process_computed_property().
* `product` will not be processed since there is no definition in
* @see ET_Builder_Module_Woocommerce_Checkout_Order::get_fields()
*/
'product',
),
),
'placeholder_color' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'placeholder_color'
),
);
return $fields;
}
/**
* {@inheritdoc}
*/
public function get_transition_fields_css_props() {
$fields = parent::get_transition_fields_css_props();
$fields['required_field_indicator_color'] = array(
'color' => '%%order_class%% form .form-row .required',
);
$fields['placeholder_color'] = array(
'color' => array(
'%%order_class%% form .input-text::placeholder',
'%%order_class%% form .input-text::-webkit-input-placeholder',
'%%order_class%% form .input-text::-moz-placeholder',
'%%order_class%% form .input-text:-ms-input-placeholder',
),
);
return $fields;
}
/**
* Swaps Checkout Order Details template.
*
* Coupon Remove Link must be shown in VB. Hence we swap the template.
*
* @param string $template Template.
* @param string $template_name Template name.
* @param array $args Arguments.
* @param string $template_path Template path.
* @param string $default_path Default path.
*
* @return string
*/
public static function swap_template( $template, $template_name, $args, $template_path, $default_path ) {
$is_template_override = in_array(
$template_name,
array(
'checkout/form-checkout.php',
),
true
);
if ( $is_template_override ) {
return trailingslashit( ET_BUILDER_DIR ) . 'feature/woocommerce/templates/' . $template_name;
}
return $template;
}
/**
* Reset hooks.
*
* @since 4.14.8 $conditional_tags param added.
*
* @param array $conditional_tags List of conditional tags.
*/
public static function maybe_reset_hooks( $conditional_tags ) {
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_order_review();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_payment();
if ( ! et_fb_is_computed_callback_ajax() && ! $is_tb ) {
remove_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Billing',
'swap_template',
],
10,
5
);
}
add_action(
'woocommerce_checkout_shipping',
[
WC_Checkout::instance(),
'checkout_form_shipping',
]
);
}
/**
* Handle hooks.
*
* @since 4.14.8 $conditional_tags param added.
*
* @param array $conditional_tags List of conditional tags.
*/
public static function maybe_handle_hooks( $conditional_tags = array() ) {
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_order_review();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_payment();
if ( ! et_fb_is_computed_callback_ajax() && ! $is_tb ) {
add_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Billing',
'swap_template',
],
10,
5
);
}
remove_action(
'woocommerce_checkout_shipping',
[
WC_Checkout::instance(),
'checkout_form_shipping',
]
);
}
/**
* Gets the Billing markup.
*
* @param array $args List of Shortcode attributes.
* @param array $conditional_tags List of conditional tags.
*
* @return string
*/
public static function get_checkout_billing( $args = array(), $conditional_tags = array() ) {
if ( ! class_exists( 'WC_Shortcode_Checkout' ) ||
! method_exists( 'WC_Shortcode_Checkout', 'output' ) ) {
return '';
}
self::maybe_handle_hooks( $conditional_tags );
$is_cart_empty = function_exists( 'WC' ) && isset( WC()->cart ) && WC()->cart->is_empty();
$is_pb_mode = et_fb_is_computed_callback_ajax() || is_et_pb_preview();
$class = 'ET_Builder_Module_Helper_Woocommerce_Modules';
// Set dummy cart contents to output Billing when no product is in cart.
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
add_filter(
'woocommerce_get_cart_contents',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
array( $class, 'set_dummy_cart_contents' )
);
}
ob_start();
WC_Shortcode_Checkout::output( array() );
$markup = ob_get_clean();
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
remove_filter(
'woocommerce_get_cart_contents',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
array( $class, 'set_dummy_cart_contents' )
);
}
self::maybe_reset_hooks( $conditional_tags );
// Fallback.
if ( ! is_string( $markup ) ) {
$markup = '';
}
return $markup;
}
/**
* 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 ) {
if ( function_exists( 'is_order_received_page' )
&& is_order_received_page() ) {
return '';
}
$output = self::get_checkout_billing();
$fields_width = et_()->array_get( $this->props, 'fields_width', false );
if ( false !== $fields_width ) {
$this->add_classname( "et_pb_fields_layout_{$fields_width}" );
}
// Handle Required Field Indicator Color responsive and hover fields.
$required_field_indicator_color_values = et_pb_responsive_options()->get_property_values( $this->props, 'required_field_indicator_color' );
$required_field_indicator_color_hover = $this->get_hover_value( 'required_field_indicator_color' );
$required_field_indicator_selector = '%%order_class%% form .form-row .required';
et_pb_responsive_options()->generate_responsive_css(
$required_field_indicator_color_values,
$required_field_indicator_selector,
'color',
$render_slug,
' !important;',
'color'
);
// Placeholder Color.
$placeholder_selectors = array(
'%%order_class%% form .form-row input.input-text::placeholder',
'%%order_class%% form .form-row input.input-text::-webkit-input-placeholder',
'%%order_class%% form .form-row input.input-text::-moz-placeholder',
'%%order_class%% form .form-row input.input-text:-ms-input-placeholder',
);
$this->generate_styles(
array(
'base_attr_name' => 'placeholder_color',
'selector' => join( ', ', $placeholder_selectors ),
'hover_pseudo_selector_location' => 'suffix',
'sticky_pseudo_selector_location' => 'prefix',
'css_property' => 'color',
'important' => false,
'render_slug' => $render_slug,
'type' => 'color',
)
);
if ( et_builder_is_hover_enabled( 'required_field_indicator_color', $this->props ) ) {
ET_Builder_Element::set_style(
$render_slug,
array(
'selector' => '%%order_class%% form .form-row:hover .required',
'declaration' => sprintf(
'color: %1$s;',
esc_html( $required_field_indicator_color_hover )
),
)
);
}
$this->add_classname( $this->get_text_orientation_classname() );
global $wp;
if ( ! empty( $wp->query_vars['order-pay'] ) ) {
$this->add_classname( 'et_pb_wc_order_pay' );
}
if ( isset( WC()->cart )
&& ! is_null( WC()->cart && method_exists( WC()->cart, 'check_cart_items' ) )
&& ! is_et_pb_preview() ) {
$return = WC()->cart->check_cart_items();
if ( wc_notice_count( 'error' ) > 0 ) {
$this->add_classname( 'et_pb_hide_module' );
}
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Checkout_Billing();

View File

@@ -0,0 +1,678 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Checkout_Order_Details class
*
* The ET_Builder_Module_Woocommerce_Checkout_Order_Details Class is responsible for rendering the
* Checkout order details section using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 4.14.0
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing Woo Checkout Details component.
*/
class ET_Builder_Module_Woocommerce_Checkout_Order_Details extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Checkout Details', 'et_builder' );
$this->plural = esc_html__( 'Woo Checkout Details', 'et_builder' );
$this->slug = 'et_pb_wc_checkout_order_details';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$this->settings_modal_toggles = array(
'advanced' => array(
'toggles' => array(
'title' => array(
'title' => esc_html__( 'Title Text', 'et_builder' ),
'priority' => 55,
),
'column_label' => array(
'title' => esc_html__( 'Column Label', 'et_builder' ),
'priority' => 60,
),
'body' => array(
'title' => esc_html__( 'Body Text', 'et_builder' ),
'tabbed_subtoggles' => true,
'sub_toggles' => array(
'p' => array(
'name' => 'P',
'icon' => 'text-left',
),
'a' => array(
'name' => 'A',
'icon' => 'text-link',
),
),
'priority' => 65,
),
'table' => array(
'title' => esc_html__( 'Table', 'et_builder' ),
'priority' => 70,
),
'table_row' => array(
'title' => esc_html__( 'Table Row', 'et_builder' ),
'priority' => 75,
),
'table_cell' => array(
'title' => esc_html__( 'Table Cell', 'et_builder' ),
'priority' => 80,
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'title' => array(
'label' => esc_html__( 'Title', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% #order_review_heading',
),
'font_size' => array(
'default' => '22px',
),
'line_height' => array(
'default' => '1em',
),
),
'column_label' => array(
'label' => esc_html__( 'Column Label', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% table.shop_table thead th',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.5em',
),
),
'body' => array(
'label' => esc_html__( 'Body', 'et_builder' ),
'css' => array(
// Accepts only string and not array. Hence using `implode`.
'main' => implode(
', ',
array(
'%%order_class%% td',
'%%order_class%% tfoot th',
)
),
// Accepts only string and not array. Hence using `implode`.
'line_height' => implode(
', ',
array(
'%%order_class%% table.shop_table th',
'%%order_class%% table.shop_table td',
)
),
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.5em',
),
'toggle_slug' => 'body',
'sub_toggle' => 'p',
),
'link' => array(
'label' => esc_html__( 'Link', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% td a',
'line_height' => '%%order_class%% td a',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.5em',
),
'toggle_slug' => 'body',
'sub_toggle' => 'a',
),
),
'text' => array(
'css' => array(
'text_orientation' => '%%order_class%% h3, table.shop_table th, table.shop_table tr td',
// Refer ET_Builder_Module_Field_TextShadow::update_styles for selector
// definition.
'text_shadow' => '%%order_class%% h3, table.shop_table th, table.shop_table tr td',
),
),
'link_options' => false,
'form_field' => array(
'table' => array(
'label' => esc_html__( 'Table', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% table.shop_table',
),
'background_color' => array(
'description' => esc_html__( 'Pick a color to fill the module\'s table.', 'et_builder' ),
),
'font_field' => false,
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% table.shop_table',
'important' => array( 'custom_margin' ),
),
'depends_on' => array(
'collapse_table_gutters_borders',
),
'depends_show_if' => 'off',
),
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'border_styles' => array(
'table' => array(
'label_prefix' => esc_html__( 'Table', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% table.shop_table',
'border_radii' => '%%order_class%% table.shop_table',
),
),
'use_focus_borders' => false,
'defaults' => array(
'border_radii' => 'on|5px|5px|5px|5px',
'border_styles' => array(
'width' => '1px',
),
),
'depends_on' => array(
'collapse_table_gutters_borders',
),
'depends_show_if' => 'off',
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% table.shop_table',
),
),
),
'table_row' => array(
'label' => esc_html__( 'Table Row', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% table.shop_table tr',
),
'background_color' => array(
'description' => esc_html__( 'Pick a color to fill the module\'s table row.', 'et_builder' ),
),
'font_field' => false,
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% table.shop_table tr th, %%order_class%% table.shop_table tr td',
),
'use_margin' => false,
'use_padding' => false,
),
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'border_styles' => array(
'table_row' => array(
'label_prefix' => esc_html__( 'Table Row', 'et_builder' ),
'css' => array(
'main' => array(
// Accepts only string and not array. Hence using `implode`.
'border_radii' => implode(
', ',
array(
'%%order_class%% table.shop_table th',
'%%order_class%% table.shop_table td',
)
),
'border_styles' => implode(
', ',
array(
'%%order_class%% table.shop_table th',
'%%order_class%% table.shop_table td',
)
),
),
'important' => true,
),
'use_focus_borders' => false,
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '1px',
),
),
'depends_on' => array(
'collapse_table_gutters_borders',
),
'depends_show_if' => 'on',
'use_radius' => false,
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% table.shop_table tr',
),
),
),
'table_cell' => array(
'label' => esc_html__( 'Table Cell', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% table.shop_table tr th, %%order_class%% table.shop_table tr td',
),
'background_color' => array(
'description' => esc_html__( 'Pick a color to fill the module\'s table cell.', 'et_builder' ),
),
'font_field' => false,
'margin_padding' => array(
'css' => array(
'main' => implode(
', ',
array(
'%%order_class%% table.shop_table tr th',
'%%order_class%% table.shop_table tr td',
)
),
),
'use_margin' => false,
),
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'border_styles' => array(
'table_cell' => array(
'label_prefix' => esc_html__( 'Table Cell', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% table.shop_table tr th,%%order_class%% table.shop_table tr td',
'border_radii' => '%%order_class%% table.shop_table tr th, %%order_class%% table.shop_table tr td',
),
'important' => array( 'border-color' ),
),
'use_focus_borders' => false,
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
),
'composite' => array(
'border_top' => array(
'border_width_top' => '1px',
'border_style_top' => 'solid',
'border_color_top' => '#eeeeee',
),
),
),
'depends_on' => array(
'collapse_table_gutters_borders',
),
'depends_show_if' => 'off',
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% table.shop_table tr th, %%order_class%% table.shop_table td',
),
),
),
),
// Use !important in Spacing OG — Margin values.
'margin_padding' => array(
'css' => array(
'important' => array( 'custom_margin' ),
),
),
);
$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' => esc_html( '7X03vBPYJ1o' ),
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'__checkout_order_details' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Checkout_Order_Details',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- This is a function call.
'get_checkout_order_details'
),
'computed_depends_on' => array(
/*
* `depends_on` arg is required. Otherwise AJAX will return null.
* @see et_pb_process_computed_property().
* `product` will not be processed since there is no definition in
* @see ET_Builder_Module_Woocommerce_Checkout_Order::get_fields()
*/
'product',
),
),
'collapse_table_gutters_borders' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field( 'collapse_table_gutters_borders' ),
'vertical_gutter_width' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field( 'vertical_gutter_width' ),
'horizontal_gutter_width' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field( 'horizontal_gutter_width' ),
);
return $fields;
}
/**
* Swaps Checkout Order Details template.
*
* Coupon Remove Link must be shown in VB. Hence we swap the template.
*
* @param string $template Template.
* @param string $template_name Template name.
* @param array $args Arguments.
* @param string $template_path Template path.
* @param string $default_path Default path.
*
* @return string
*/
public static function swap_template_fe( $template, $template_name, $args, $template_path, $default_path ) {
$is_template_override = in_array(
$template_name,
array(
'checkout/form-checkout.php',
),
true
);
if ( $is_template_override ) {
return trailingslashit( ET_BUILDER_DIR ) . 'feature/woocommerce/templates/' . $template_name;
}
return $template;
}
/**
* Swaps Checkout Order Details template.
*
* Coupon Remove Link must be shown in VB. Hence we swap the template.
*
* @param string $template Template.
* @param string $template_name Template name.
* @param array $args Arguments.
* @param string $template_path Template path.
* @param string $default_path Default path.
*
* @return string
*/
public static function swap_template( $template, $template_name, $args, $template_path, $default_path ) {
$is_template_override = in_array(
$template_name,
array(
'checkout/review-order.php',
),
true
);
if ( $is_template_override ) {
return trailingslashit( ET_BUILDER_DIR ) . 'feature/woocommerce/templates/' . $template_name;
}
return $template;
}
/**
* Reset hooks.
*
* @param array $conditional_tags Array of conditional tags.
*/
public static function maybe_reset_hooks( $conditional_tags ) {
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_billing();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_shipping();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_payment();
if ( et_fb_is_computed_callback_ajax() || $is_tb ) {
remove_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Order_Details',
'swap_template',
],
10,
5
);
}
if ( ! et_fb_is_computed_callback_ajax() && ! $is_tb ) {
remove_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Order_Details',
'swap_template_fe',
],
10,
5
);
}
}
/**
* Handle hooks.
*
* @param array $conditional_tags Array of conditional tags.
*/
public static function maybe_handle_hooks( $conditional_tags ) {
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_billing();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_shipping();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_payment();
if ( et_fb_is_computed_callback_ajax() || $is_tb ) {
add_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Order_Details',
'swap_template',
],
10,
5
);
}
if ( ! et_fb_is_computed_callback_ajax() && ! $is_tb ) {
add_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Order_Details',
'swap_template_fe',
],
10,
5
);
}
}
/**
* Gets the Checkout Order Details markup.
*
* @param array $args Array of `depends_on` key/value pairs.
* @param array $conditional_tags Array of conditional tags.
*
* @return string
*/
public static function get_checkout_order_details( $args = array(), $conditional_tags = array() ) {
if ( ! class_exists( 'WC_Shortcode_Checkout' )
|| ! method_exists( 'WC_Shortcode_Checkout', 'output' ) ) {
return '';
}
self::maybe_handle_hooks( $conditional_tags );
$is_cart_empty = function_exists( 'WC' ) && isset( WC()->cart ) && WC()->cart->is_empty();
$is_pb_mode = et_fb_is_computed_callback_ajax() || is_et_pb_preview();
$class = 'ET_Builder_Module_Helper_Woocommerce_Modules';
// Set dummy cart contents to output Billing when no product is in cart.
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
add_filter(
'woocommerce_get_cart_contents',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- This is a function call.
array( $class, 'set_dummy_cart_contents' )
);
}
ob_start();
WC_Shortcode_Checkout::output( array() );
$markup = ob_get_clean();
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
remove_filter(
'woocommerce_get_cart_contents',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- This is a function call.
array( $class, 'set_dummy_cart_contents' )
);
}
self::maybe_reset_hooks( $conditional_tags );
// Fallback.
if ( ! is_string( $markup ) ) {
$markup = '';
}
return $markup;
}
/**
* 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 ) {
if ( function_exists( 'is_order_received_page' )
&& is_order_received_page() ) {
return '';
}
$this->add_classname( $this->get_text_orientation_classname() );
$output = self::get_checkout_order_details();
$collapse_table_gutters_borders_style_values = array();
$table_border_spacing_style_values = array();
foreach ( et_pb_responsive_options()->get_modes() as $device ) {
$collapse_table_gutters_borders = et_pb_responsive_options()->get_property_value(
$attrs,
'collapse_table_gutters_borders',
'off',
$device,
true
);
$horizontal_gutter_width_value = et_pb_responsive_options()->get_property_value(
$attrs,
'horizontal_gutter_width',
'0px',
$device,
true
);
$vertical_gutter_width_value = et_pb_responsive_options()->get_property_value(
$attrs,
'vertical_gutter_width',
'0px',
$device,
true
);
if ( 'on' === $collapse_table_gutters_borders ) {
$collapse_table_gutters_borders_style_values[ $device ] = array(
'border-collapse' => 'collapse',
);
$table_border_spacing_style_values[ $device ] = array(
'border-spacing' => '0 0',
);
} else {
$collapse_table_gutters_borders_style_values[ $device ] = array(
'border-collapse' => 'separate',
);
$table_border_spacing_style_values[ $device ] = array(
'border-spacing' => sprintf(
'%s %s',
$horizontal_gutter_width_value,
$vertical_gutter_width_value
),
);
}
}
et_pb_responsive_options()->generate_responsive_css(
$collapse_table_gutters_borders_style_values,
'%%order_class%% table.shop_table',
'border-collapse',
$render_slug,
'',
'border-collapse' /* Can be anything other than `range`. */
);
et_pb_responsive_options()->generate_responsive_css(
$table_border_spacing_style_values,
'%%order_class%% table.shop_table',
'border-spacing',
$render_slug,
'',
'border-spacing' /* Can be anything other than `range`. */
);
if ( isset( WC()->cart )
&& ! is_null( WC()->cart && method_exists( WC()->cart, 'check_cart_items' ) )
&& ! is_et_pb_preview() ) {
$return = WC()->cart->check_cart_items();
if ( wc_notice_count( 'error' ) > 0 ) {
$this->add_classname( 'et_pb_hide_module' );
}
}
global $wp;
if ( ! empty( $wp->query_vars['order-pay'] ) ) {
$this->add_classname( 'et_pb_wc_order_pay' );
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Checkout_Order_Details();

View File

@@ -0,0 +1,694 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Checkout_Payment_Info class
*
* The ET_Builder_Module_Woocommerce_Checkout_Payment_Info Class is responsible for rendering the
* Checkout payment info using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 4.14.0
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Checkout Payment component.
*/
class ET_Builder_Module_Woocommerce_Checkout_Payment_Info extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Checkout Payment', 'et_builder' );
$this->plural = esc_html__( 'Woo Checkout Payment', 'et_builder' );
$this->slug = 'et_pb_wc_checkout_payment_info';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$this->main_css_element = implode(
',',
array(
'%%order_class%% .woocommerce-checkout #payment',
'%%order_class%% .woocommerce-order',
)
);
$this->settings_modal_toggles = array(
'advanced' => array(
'toggles' => array(
'body' => array(
'title' => esc_html__( 'Body Text', 'et_builder' ),
'tabbed_subtoggles' => true,
'sub_toggles' => array(
'p' => array(
'name' => 'P',
'icon' => 'text-left',
),
'a' => array(
'name' => 'A',
'icon' => 'text-link',
),
),
'priority' => 52,
),
'radio_button' => array(
'title' => esc_html__( 'Radio Buttons', 'et_builder' ),
'priority' => 65,
),
'selected_radio_button' => array(
'title' => esc_html__( 'Selected Radio Button', 'et_builder' ),
'priority' => 70,
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
'body' => array(
'label' => et_builder_i18n( 'Body' ),
'css' => array(
'main' => implode(
',',
array(
'%%order_class%% .woocommerce-privacy-policy-text',
'%%order_class%% .woocommerce-privacy-policy-text a',
'%%order_class%% .wc_payment_method a',
// Order confirmation Page elements.
'%%order_class%% .woocommerce-order p',
'%%order_class%% .woocommerce-order .woocommerce-order-overview',
)
),
'important' => array( 'size', 'line-height' ),
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.7em',
),
'toggle_slug' => 'body',
'sub_toggle' => 'p',
),
'link' => array(
'label' => et_builder_i18n( 'Link' ),
'css' => array(
'main' => implode(
',',
array(
'%%order_class%% .woocommerce-privacy-policy-text a',
'%%order_class%% .wc_payment_method a',
)
),
// CPT style uses `!important` so outputting important is inevitable.
'important' => 'all',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.7em',
),
'toggle_slug' => 'body',
'sub_toggle' => 'a',
),
),
'link_options' => false,
'button' => array(
'button' => array(
'label' => esc_html__( 'Button', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% #payment #place_order',
),
'use_alignment' => false,
'border_width' => array(
'default' => '2px',
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% #payment #place_order',
),
),
'margin_padding' => array(
'css' => array(
'important' => 'all',
),
),
'toggle_priority' => 80,
),
),
'form_field' => array(
'radio_button' => array(
'label' => esc_html__( 'Radio Button', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% #payment .wc_payment_method',
'text_shadow' => '%%order_class%% #payment .wc_payment_method label',
),
'background_color' => array(
'description' => esc_html__( 'Pick a color to fill the module\'s radio buttons.', 'et_builder' ),
),
'text_color' => array(
'description' => esc_html__( 'Pick a color to be used for the text written next to radio button.', 'et_builder' ),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% #payment .wc_payment_method',
),
),
'border_styles' => array(
'radio_button' => array(
'label_prefix' => esc_html__( 'Radio Button', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% #payment .wc_payment_method',
'border_radii' => '%%order_class%% #payment .wc_payment_method',
),
),
'defaults' => array(
'border_radii' => 'off|0px|0px|0px|0px',
'border_style' => array(
'width' => '0px',
'style' => 'none',
),
),
),
),
'font_field' => array(
'css' => array(
'main' => '%%order_class%% #payment .wc_payment_method label',
'focus' => '%%order_class%% #payment .input-radio:focus',
'text_align' => '%%order_class%% #payment ul.payment_methods li',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.4em',
),
),
'focus_background_color' => false,
'focus_text_color' => false,
'margin_padding' => array(
'css' => array(
// Different from main css selector for added specificity.
'margin' => '%%order_class%% #payment ul.payment_methods li',
'padding' => '%%order_class%% #payment ul.payment_methods li',
),
),
'width' => array(),
),
'selected_radio_button' => array(
'label' => esc_html__( 'Selected Radio Button', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% #payment .wc_payment_method.et_pb_checked',
'text_shadow' => '%%order_class%% #payment .wc_payment_method.et_pb_checked label',
),
'background_color' => array(
'description' => esc_html__( 'Pick a color to fill the module\'s selected radio button.', 'et_builder' ),
),
'text_color' => array(
'description' => esc_html__( 'Pick a color to be used for the text written next to selected radio button.', 'et_builder' ),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% #payment .wc_payment_method.et_pb_checked',
),
),
'border_styles' => array(
'selected_radio_button' => array(
'label_prefix' => esc_html__( 'Selected Radio Button', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% #payment .wc_payment_method.et_pb_checked',
'border_radii' => '%%order_class%% #payment .wc_payment_method.et_pb_checked',
),
),
'defaults' => array(
'border_radii' => 'off|0px|0px|0px|0px',
'border_style' => array(
'width' => '0px',
'style' => 'none',
),
),
),
),
'font_field' => array(
'css' => array(
'main' => '%%order_class%% #payment .wc_payment_method.et_pb_checked label',
'focus' => '%%order_class%% #payment .wc_payment_method.et_pb_checked .input-radio:focus',
'text_align' => '%%order_class%% #payment ul.payment_methods li.et_pb_checked',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.4em',
),
),
'focus_background_color' => false,
'focus_text_color' => false,
'margin_padding' => array(
'css' => array(
// Different from main css selector for added specificity.
'margin' => '%%order_class%% #payment ul.payment_methods li.et_pb_checked',
'padding' => '%%order_class%% #payment ul.payment_methods li.et_pb_checked',
),
),
'width' => array(),
),
'tooltip' => array(
'label' => esc_html__( 'Tooltip', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% #payment div.payment_box',
),
'background_color' => array(
'description' => esc_html__( 'Pick a color to fill the module\'s tooltip.', 'et_builder' ),
),
'font_field' => array(
'css' => array(
'main' => '%%order_class%% .wc_payment_method p',
),
'font_size' => array(
'default' => '',
'allowed_values' => et_builder_get_acceptable_css_string_values( 'width' ),
'allow_empty' => true,
),
'line_height' => array(
'default' => '1.5em',
),
'hide_text_color' => false,
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% #payment div.payment_box',
),
),
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'border_styles' => array(
'tooltip' => array(
'label_prefix' => 'Tooltip',
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% #payment div.payment_box',
'border_radii' => '%%order_class%% #payment div.payment_box',
),
),
'defaults' => array(
'border_radii' => 'on|2px|2px|2px|2px',
),
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% #payment div.payment_box',
),
),
'toggle_priority' => 70,
),
'form_notice' => array(
'label' => esc_html__( 'Form Notice', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% #payment ul.payment_methods li.woocommerce-info',
),
'background_color' => array(
'description' => esc_html__( 'Pick a color to fill the module\'s notice.', 'et_builder' ),
),
'font_field' => array(
'css' => array(
'main' => '%%order_class%% #payment ul.payment_methods li.woocommerce-notice',
'important' => array( 'size', 'text-shadow' ),
),
'font_size' => array(
'default' => '18px',
),
'line_height' => array(
'default' => '1.7em',
),
'hide_text_color' => false,
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% #payment ul.payment_methods li.woocommerce-info',
'important' => array( 'custom_padding' ),
),
'custom_padding' => array(
'default' => '15px|15px|15px|15px|false|false',
),
),
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'border_styles' => array(
'form_notice' => array(
'label_prefix' => esc_html__( 'Notice', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => '%%order_class%% #payment ul.payment_methods li.woocommerce-info',
'border_radii' => '%%order_class%% #payment ul.payment_methods li.woocommerce-info',
),
'important' => true,
),
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
),
),
'use_focus_borders' => false,
),
),
'box_shadow' => array(
'css' => array(
'main' => '%%order_class%% #payment ul.payment_methods li.woocommerce-info',
'important' => true,
),
),
'toggle_priority' => 75,
),
),
'background' => array(
'css' => array(
// Backgrounds need to be applied to module wrapper.
'main' => '%%order_class%%.et_pb_wc_checkout_payment_info',
),
'options' => array(
'background_color' => array(
'default' => '#ebe9eb',
),
),
),
'borders' => array(
'default' => array(
'css' => array(
'main' => implode(
',',
array(
'%%order_class%% .woocommerce-checkout #payment',
'%%order_class%% .woocommerce-order',
)
),
),
'defaults' => array(
'border_radii' => 'on|5px|5px|5px|5px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
'color' => '#eee',
),
),
),
),
'margin_padding' => array(
'css' => array(
'main' => implode(
',',
array(
'%%order_class%% .woocommerce-checkout #payment',
'%%order_class%% .woocommerce-order',
)
),
),
'custom_padding' => array(
'default' => '1em|1em|1em|1em|false|false',
),
),
);
$this->custom_css_fields = array(
'fields' => array(
'label' => esc_html__( 'Fields', 'et_builder' ),
'selector' => '%%order_class%% #payment .input-radio',
),
'body' => array(
'label' => esc_html__( 'Body', 'et_builder' ),
'selector' => '%%order_class%% .woocommerce-privacy-policy-text',
),
'body_anchor' => array(
'label' => esc_html__( 'Body Link', 'et_builder' ),
'selector' => '%%order_class%% .woocommerce-privacy-policy-text a',
),
'button' => array(
'label' => esc_html__( 'Button', 'et_builder' ),
'selector' => '%%order_class%% #payment #place_order',
),
'tooltip' => array(
'label' => esc_html__( 'Tooltip', 'et_builder' ),
'selector' => '%%order_class%% #payment div.payment_box',
),
'form_notice' => array(
'label' => esc_html__( 'Form Notice', 'et_builder' ),
'selector' => '%%order_class%% #payment ul.payment_methods li.woocommerce-info',
),
);
$this->help_videos = array(
array(
'id' => esc_html( '7X03vBPYJ1o' ),
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'__checkout_payment_info' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Checkout_Payment_Info',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- This is a function call.
'get_checkout_payment_info'
),
'computed_depends_on' => array(
/*
* `depends_on` arg is required. Otherwise AJAX will return null.
* @see et_pb_process_computed_property().
* `product` will not be processed since there is no definition in
* @see ET_Builder_Module_Woocommerce_Checkout_Order::get_fields()
*/
'product',
),
),
);
return $fields;
}
/**
* Gets the Button classname.
*
* @used-by ET_Builder_Module_Helper_Woocommerce_Modules::add_custom_button_icons()
*
* @return string
*/
public function get_button_classname() {
return 'button';
}
/**
* Swaps login form template.
*
* By default WooCommerce displays these only when logged-out.
* However these templates must be shown in VB when logged-in. Hence we use these templates.
*
* @param string $template Template.
* @param string $template_name Template name.
* @param array $args Arguments.
* @param string $template_path Template path.
* @param string $default_path Default path.
*
* @return string
*/
public static function swap_template( $template, $template_name, $args, $template_path, $default_path ) {
$is_template_override = in_array(
$template_name,
array(
'checkout/payment.php',
'checkout/payment-method.php',
),
true
);
if ( $is_template_override ) {
return trailingslashit( ET_BUILDER_DIR ) . 'feature/woocommerce/templates/' . $template_name;
}
return $template;
}
/**
* Reset hooks.
*/
public static function maybe_reset_hooks() {
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_billing();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_shipping();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_order_review();
}
/**
* Handle hooks.
*/
public static function maybe_handle_hooks() {
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_billing();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_shipping();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_order_review();
}
/**
* Gets the Checkout Payment info markup.
*
* @param array $args Additional arguments.
* @param array $conditional_tags Array of conditional tags.
*
* @return string
*/
public static function get_checkout_payment_info( $args = array(), $conditional_tags = array() ) {
if ( ! class_exists( 'WC_Shortcode_Checkout' )
|| ! method_exists( 'WC_Shortcode_Checkout', 'output' ) ) {
return '';
}
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
self::maybe_handle_hooks();
$is_cart_empty = function_exists( 'WC' ) && isset( WC()->cart ) && WC()->cart->is_empty();
$is_pb_mode = et_fb_is_computed_callback_ajax() || is_et_pb_preview();
$class = 'ET_Builder_Module_Helper_Woocommerce_Modules';
// Set dummy cart contents to output Billing when no product is in cart.
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
add_filter(
'woocommerce_get_cart_contents',
array( $class, 'set_dummy_cart_contents' )
);
}
if ( et_fb_is_computed_callback_ajax() || $is_tb || is_et_pb_preview() ) {
/*
* Show Login form in VB.
*
* The swapped login form will display irrespective of the user logged-in status.
*
* Previously swapped template (FE) will only display the form when
* a user is not logged-in. Hence we use a different template in VB.
*/
add_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Payment_Info',
'swap_template',
],
10,
5
);
}
ob_start();
if ( is_et_pb_preview() ) {
printf(
'<div className="et_pb_wc_inactive__message">%s</div>',
esc_html__( 'Woo Checkout Payment module can be used on a page and cannot be previewd.', 'et_builder' )
);
} else {
WC_Shortcode_Checkout::output( array() );
}
$markup = ob_get_clean();
if ( et_fb_is_computed_callback_ajax() || $is_tb || is_et_pb_preview() ) {
remove_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Payment_Info',
'swap_template',
],
10,
5
);
}
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
remove_filter(
'woocommerce_get_cart_contents',
array( $class, 'set_dummy_cart_contents' )
);
}
self::maybe_reset_hooks();
// Fallback.
if ( ! is_string( $markup ) ) {
$markup = '';
}
return $markup;
}
/**
* 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_custom_button_icons( $render_slug, $this );
// Module classname.
$this->add_classname( $this->get_text_orientation_classname() );
if ( $this->_module_has_background() ) {
ET_Builder_Element::set_style(
$render_slug,
array(
'selector' => '%%order_class%% .woocommerce-checkout #payment, %%order_class%% .woocommerce-order',
'declaration' => 'background: transparent !important;',
)
);
}
$output = self::get_checkout_payment_info( $attrs );
return $this->_render_module_wrapper( $output, $render_slug );
}
/**
* Checks if module has background.
*
* @since 4.15.0
*
* @return bool
*/
protected function _module_has_background() {
$has_background_color = ! empty( $this->props['background_color'] );
$has_background_gradient = isset( $this->props['use_background_color_gradient'] ) && 'on' === $this->props['use_background_color_gradient'];
$has_background_image = ! empty( $this->props['background_image'] );
$has_background_video_mp4 = ! empty( $this->props['background_video_mp4'] );
$has_background_video_webm = ! empty( $this->props['background_video_webm'] );
$has_background_pattern = isset( $this->props['background_enable_pattern_style'] ) && 'on' === $this->props['background_enable_pattern_style'] && ! empty( $this->props['background_pattern_style'] );
$has_background_mask = isset( $this->props['background_enable_pattern_style'] ) && 'on' === $this->props['background_enable_mask_style'] && ! empty( $this->props['background_mask_style'] );
return $has_background_color
|| $has_background_gradient
|| $has_background_image
|| $has_background_video_mp4
|| $has_background_video_webm
|| $has_background_pattern
|| $has_background_mask;
}
}
new ET_Builder_Module_Woocommerce_Checkout_Payment_Info();

View File

@@ -0,0 +1,595 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Checkout_Shipping class
*
* The ET_Builder_Module_Woocommerce_Checkout_Shipping Class is responsible for rendering the
* Checkout shipping section using the WooCommerce template.
*
* @package Divi\Builder
*
* @since 4.14.0
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Checkout shipping component.
*
* @since 4.14.0
*/
class ET_Builder_Module_Woocommerce_Checkout_Shipping extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Checkout Shipping', 'et_builder' );
$this->plural = esc_html__( 'Woo Checkout Shipping', 'et_builder' );
$this->slug = 'et_pb_wc_checkout_shipping';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$this->settings_modal_toggles = array(
'advanced' => array(
'toggles' => array(
'layout' => array(
'title' => et_builder_i18n( 'Layout' ),
'priority' => 45,
),
'title' => array(
'title' => esc_html__( 'Title Text', 'et_builder' ),
'priority' => 55,
),
'field_label' => array(
'title' => esc_html__( 'Field Labels', 'et_builder' ),
'priority' => 60,
),
'form_field' => array(
'title' => esc_html__( 'Fields', 'et_builder' ),
'priority' => 65,
),
),
),
);
$this->advanced_fields = array(
'fonts' => array(
// Use `title` in place of `header` since `header` needs a workaround in Copy/Paste.
'title' => array(
'label' => esc_html__( 'Title', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% h3',
),
'font_size' => array(
'default' => '22px',
),
'line_height' => array(
'default' => '1em',
),
'tab_slug' => 'advanced',
'toggle_slug' => 'title',
),
'field_label' => array(
'label' => esc_html__( 'Field Label', 'et_builder' ),
'css' => array(
'main' => '%%order_class%% form .form-row label',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '2em',
),
'toggle_slug' => 'field_label',
),
),
'text' => array(
'use_background_layout' => false,
'use_text_orientation' => true,
),
'button' => false,
'link_options' => false,
'form_field' => array(
'form_field' => array(
'label' => esc_html__( 'Fields', 'et_builder' ),
'css' => array(
'main' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single',
'.woocommerce %%order_class%% form .form-row .input-text',
)
),
'background_color_hover' => implode(
',',
[
'%%order_class%% .select2-container--default .select2-selection--single:hover',
'.woocommerce %%order_class%% form .form-row .input-text:hover',
]
),
'focus_background_color' => implode(
',',
[
'.woocommerce %%order_class%% .select2-container--open .select2-selection',
'.woocommerce %%order_class%% form .input-text:focus',
]
),
'focus_background_color_hover' => implode(
',',
[
'.woocommerce %%order_class%% .select2-container--open:hover .select2-selection',
'.woocommerce %%order_class%% form .input-text:focus:hover',
]
),
'focus_text_color' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--open .select2-selection__rendered',
'.woocommerce %%order_class%% form .form-row input.input-text:focus',
)
),
'focus_text_color_hover' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--open:hover .select2-selection__rendered',
'.woocommerce %%order_class%% form .form-row input.input-text:focus:hover',
)
),
'form_text_color' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single .select2-selection__rendered',
'.woocommerce %%order_class%% form .form-row .input-text',
)
),
'form_text_color_hover' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container .select2-selection--single:hover .select2-selection__rendered',
'.woocommerce %%order_class%% form .form-row .input-text:hover',
)
),
),
'box_shadow' => array(
'css' => array(
'main' => implode(
',',
array(
'%%order_class%% .select2-container--default .select2-selection--single',
'%%order_class%% form .form-row input.input-text',
)
),
),
),
'border_styles' => array(
'form_field' => array(
'label_prefix' => esc_html__( 'Fields', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single',
'.woocommerce %%order_class%% form .form-row .input-text',
)
),
'border_radii' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single',
'.woocommerce %%order_class%% form .form-row input.input-text',
)
),
),
),
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
),
),
),
'form_field_focus' => array(
'label_prefix' => esc_html__( 'Fields Focus', 'et_builder' ),
'css' => array(
'main' => array(
'border_styles' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default.select2-container--open .select2-selection--single',
'.woocommerce %%order_class%% form .form-row .input-text:focus',
)
),
'border_radii' => implode(
',',
array(
'.woocommerce %%order_class%% .select2-container--default.select2-container--open .select2-selection--single',
'.woocommerce %%order_class%% form .form-row input.input-text:focus',
)
),
),
),
'defaults' => array(
'border_radii' => 'on|0px|0px|0px|0px',
'border_styles' => array(
'width' => '0px',
'style' => 'solid',
),
),
),
),
'font_field' => array(
'css' => array(
'main' => implode(
',',
[
'.woocommerce %%order_class%% .select2-container--default .select2-selection--single',
'.woocommerce %%order_class%% form .form-row .input-text',
]
),
// Required to override default WooCommerce styles.
'important' => array( 'line-height', 'size', 'font' ),
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1.7em',
),
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% form .form-row input.input-text, %%order_class%% .select2-container--default .select2-selection--single .select2-selection__rendered',
'padding' => '%%order_class%% form .form-row input.input-text, %%order_class%% .select2-container--default .select2-selection--single',
'margin' => '%%order_class%% form .form-row input.input-text, %%order_class%% .select2-container--default .select2-selection--single',
),
),
'width' => array(),
'toggle_priority' => 65,
),
),
);
$this->custom_css_fields = array(
'title_text' => array(
'label' => esc_html__( 'Title Text', 'et_builder' ),
'selector' => '%%order_class%% h3',
),
'field_label' => array(
'label' => esc_html__( 'Field Label', 'et_builder' ),
'selector' => '%%order_class%% form .form-row label',
),
'form_field' => array(
'label' => esc_html__( 'Fields', 'et_builder' ),
'selector' => implode(
',',
array(
'%%order_class%% .select2-container--default .select2-selection--single',
'%%order_class%% form .form-row .input-text',
)
),
),
);
$this->help_videos = array(
array(
'id' => esc_html( '7X03vBPYJ1o' ),
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'required_field_indicator_color' => array(
'label' => esc_html__( 'Required Field Indicator Color', 'et_builder' ),
'description' => esc_html__( 'Pick a color to be used for the required field indicator.', 'et_builder' ),
'type' => 'color-alpha',
'option_category' => 'button',
'custom_color' => true,
'default' => '',
'tab_slug' => 'advanced',
'toggle_slug' => 'field_label',
'hover' => 'tabs',
'mobile_options' => true,
'priority' => 5,
),
'fields_width' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'fields_width'
),
'__checkout_shipping' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Checkout_Shipping',
'get_checkout_shipping',
),
'computed_depends_on' => array(
/*
* `depends_on` arg is required. Otherwise AJAX will return null.
* @see et_pb_process_computed_property().
* `product` will not be processed since there is no definition in
* @see ET_Builder_Module_Woocommerce_Checkout_Order::get_fields()
*/
'product',
),
),
'placeholder_color' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'placeholder_color'
),
);
return $fields;
}
/**
* {@inheritdoc}
*/
public function get_transition_fields_css_props() {
$fields = parent::get_transition_fields_css_props();
$fields['required_field_indicator_color'] = array(
'color' => '%%order_class%% form .form-row .required',
);
$fields['placeholder_color'] = array(
'color' => array(
'%%order_class%% form .input-text::placeholder',
'%%order_class%% form .input-text::-webkit-input-placeholder',
'%%order_class%% form .input-text::-moz-placeholder',
'%%order_class%% form .input-text:-ms-input-placeholder',
),
);
return $fields;
}
/**
* Swaps Checkout Order Details template.
*
* Coupon Remove Link must be shown in VB. Hence we swap the template.
*
* @param string $template Template.
* @param string $template_name Template name.
* @param array $args Arguments.
* @param string $template_path Template path.
* @param string $default_path Default path.
*
* @return string
*/
public static function swap_template( $template, $template_name, $args, $template_path, $default_path ) {
$is_template_override = in_array(
$template_name,
array(
'checkout/form-checkout.php',
),
true
);
if ( $is_template_override ) {
return trailingslashit( ET_BUILDER_DIR ) . 'feature/woocommerce/templates/' . $template_name;
}
return $template;
}
/**
* Handle hooks.
*/
public static function maybe_handle_hooks( $conditional_tags ) {
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_order_review();
ET_Builder_Module_Helper_Woocommerce_Modules::detach_wc_checkout_payment();
if ( ! et_fb_is_computed_callback_ajax() && ! $is_tb ) {
add_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Shipping',
'swap_template',
],
10,
5
);
}
remove_action(
'woocommerce_checkout_billing',
[
WC_Checkout::instance(),
'checkout_form_billing',
]
);
}
/**
* Reset hooks.
*/
public static function maybe_reset_hooks( $conditional_tags ) {
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_coupon_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_login_form();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_order_review();
ET_Builder_Module_Helper_Woocommerce_Modules::attach_wc_checkout_payment();
if ( ! et_fb_is_computed_callback_ajax() && ! $is_tb ) {
remove_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Checkout_Shipping',
'swap_template',
],
10,
5
);
}
add_action(
'woocommerce_checkout_billing',
[
WC_Checkout::instance(),
'checkout_form_billing',
]
);
}
/**
* Gets the Checkout Shipping markup.
*
* @return string
*/
public static function get_checkout_shipping( $args = array(), $conditional_tags = array() ) {
self::maybe_handle_hooks( $conditional_tags );
$is_cart_empty = function_exists( 'WC' ) && isset( WC()->cart ) && WC()->cart->is_empty();
$is_pb_mode = et_fb_is_computed_callback_ajax() || is_et_pb_preview();
$class = 'ET_Builder_Module_Helper_Woocommerce_Modules';
// Set dummy cart contents to output Billing when no product is in cart.
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
add_filter(
'woocommerce_get_cart_contents',
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
array( $class, 'set_dummy_cart_contents' )
);
}
if ( $is_pb_mode ) {
add_filter( 'woocommerce_cart_needs_shipping_address', '__return_true' );
}
ob_start();
WC_Shortcode_Checkout::output( array() );
$markup = ob_get_clean();
if ( $is_pb_mode ) {
remove_filter( 'woocommerce_cart_needs_shipping_address', '__return_true' );
}
if ( ( $is_cart_empty && $is_pb_mode ) || is_et_pb_preview() ) {
remove_filter(
'woocommerce_get_cart_contents',
array(
$class,
// phpcs:ignore WordPress.Arrays.CommaAfterArrayItem.NoComma -- Call to a function.
'set_dummy_cart_contents'
)
);
}
self::maybe_reset_hooks( $conditional_tags );
// Fallback.
if ( ! is_string( $markup ) ) {
$markup = '';
}
return $markup;
}
/**
* 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 ) {
if ( function_exists( 'is_order_received_page' )
&& is_order_received_page() ) {
return '';
}
// The module will styled to remain hidden when the class is added.
if ( function_exists( 'wc_ship_to_billing_address_only' ) && wc_ship_to_billing_address_only() ) {
$this->add_classname( 'et_pb_wc_ship_to_billing_address_only' );
}
$output = self::get_checkout_shipping();
$fields_width = et_()->array_get( $this->props, 'fields_width', false );
if ( false !== $fields_width ) {
$this->add_classname( "et_pb_fields_layout_{$fields_width}" );
}
// Handle Required Field Indicator Color responsive and hover fields.
$required_field_indicator_color_values = et_pb_responsive_options()->get_property_values( $this->props, 'required_field_indicator_color' );
$required_field_indicator_color_hover = $this->get_hover_value( 'required_field_indicator_color' );
$required_field_indicator_selector = '%%order_class%% form .form-row .required';
et_pb_responsive_options()->generate_responsive_css(
$required_field_indicator_color_values,
$required_field_indicator_selector,
'color',
$render_slug,
' !important;',
'color'
);
// Placeholder Color.
$placeholder_selectors = array(
'%%order_class%% form .form-row input.input-text::placeholder',
'%%order_class%% form .form-row input.input-text::-webkit-input-placeholder',
'%%order_class%% form .form-row input.input-text::-moz-placeholder',
'%%order_class%% form .form-row input.input-text:-ms-input-placeholder',
);
$this->generate_styles(
array(
'base_attr_name' => 'placeholder_color',
'selector' => join( ', ', $placeholder_selectors ),
'hover_pseudo_selector_location' => 'suffix',
'sticky_pseudo_selector_location' => 'prefix',
'css_property' => 'color',
'important' => false,
'render_slug' => $render_slug,
'type' => 'color',
)
);
if ( et_builder_is_hover_enabled( 'required_field_indicator_color', $this->props ) ) {
ET_Builder_Element::set_style(
$render_slug,
array(
'selector' => '%%order_class%% form .form-row:hover .required',
'declaration' => sprintf(
'color: %1$s;',
esc_html( $required_field_indicator_color_hover )
),
)
);
}
$this->add_classname( $this->get_text_orientation_classname() );
if ( isset( WC()->cart )
&& ! is_null( WC()->cart && method_exists( WC()->cart, 'check_cart_items' ) )
&& ! is_et_pb_preview() ) {
$return = WC()->cart->check_cart_items();
if ( wc_notice_count( 'error' ) > 0 ) {
$this->add_classname( 'et_pb_hide_module' );
}
}
global $wp;
if ( ! empty( $wp->query_vars['order-pay'] ) ) {
$this->add_classname( 'et_pb_wc_order_pay' );
}
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Checkout_Shipping();

View File

@@ -0,0 +1,282 @@
<?php
/**
* WooCommerce Modules: ET_Builder_Module_Woocommerce_Cross_Sells class
*
* The ET_Builder_Module_Woocommerce_Cross_Sells Class is responsible for rendering the
* Cross sells using the WooCommerce template.
*
* @since 4.14.0
* @package Divi\Builder
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Cart Upsells component.
*
* @since 4.14.0
*/
class ET_Builder_Module_Woocommerce_Cross_Sells extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Cross Sells', 'et_builder' );
$this->plural = esc_html__( 'Woo Cross Sells', 'et_builder' );
$this->slug = 'et_pb_wc_cross_sells';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$this->main_css_element = '%%order_class%%.et_pb_wc_cross_sells';
$this->advanced_fields = array(
'fonts' => array(
'title' => array(
'label' => et_builder_i18n( 'Title' ),
'css' => array(
'main' => implode(
',',
[
"{$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",
]
),
'hover' => implode(
',',
[
"{$this->main_css_element} .woocommerce ul.products li.product h3:hover",
"{$this->main_css_element} .woocommerce ul.products li.product h1:hover",
"{$this->main_css_element} .woocommerce ul.products li.product h2:hover",
"{$this->main_css_element} .woocommerce ul.products li.product h4:hover",
"{$this->main_css_element} .woocommerce ul.products li.product h5:hover",
"{$this->main_css_element} .woocommerce ul.products li.product h6:hover",
]
),
'important' => 'plugin_only',
),
'font_size' => array(
'default' => '14px',
),
'line_height' => array(
'default' => '1em',
),
),
'price' => array(
'label' => esc_html__( 'Price', 'et_builder' ),
'css' => array(
'main' => implode(
',',
[
"{$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' => '26px',
),
),
),
);
$this->help_videos = array(
array(
'id' => esc_html( '7X03vBPYJ1o' ),
'name' => esc_html__( 'Divi WooCommerce Modules', 'et_builder' ),
),
);
}
/**
* {@inheritdoc}
*/
public function get_fields() {
$fields = array(
'__cross_sells' => array(
'type' => 'computed',
'computed_callback' => array(
'ET_Builder_Module_Woocommerce_Cross_Sells',
'get_cross_sells',
),
'computed_depends_on' => array(
/*
* `depends_on` arg is required. Otherwise AJAX will return null.
* @see et_pb_process_computed_property().
* `product` will not be processed since there is no definition in
* @see ET_Builder_Module_Woocommerce_Checkout_Order::get_fields()
*/
'product',
),
),
);
return $fields;
}
/**
* Swaps Cross-sells template.
*
* @param string $template Template.
* @param string $template_name Template name.
* @param array $args Arguments.
* @param string $template_path Template path.
* @param string $default_path Default path.
*
* @return string
*/
public static function swap_template( $template, $template_name, $args, $template_path, $default_path ) {
$is_template_override = in_array(
$template_name,
array(
'cart/cross-sells.php',
),
true
);
if ( $is_template_override ) {
return trailingslashit( ET_BUILDER_DIR ) . 'feature/woocommerce/templates/' . $template_name;
}
return $template;
}
/**
* Gets Cross sells markup.
*
* @param array $args Props.
* @param array $conditional_tags Conditional tags set during computed property AJAX call.
*
* @return string
*/
public static function get_cross_sells( $args = array(), $conditional_tags = array() ) {
if ( is_checkout() ) {
return;
}
if ( ! function_exists( 'woocommerce_cross_sell_display' ) ) {
return;
}
$is_tb = et_()->array_get( $conditional_tags, 'is_tb', false );
$output = '';
if ( ( $is_tb || et_fb_is_computed_callback_ajax() || is_et_pb_preview() ) ) {
$cross_sell_items = array(
1001 => array(
'name' => esc_html__( 'Product 4', 'et_builder' ),
'price' => '12.00',
),
1002 => array(
'name' => esc_html__( 'Product 5', 'et_builder' ),
'price' => '75.00',
),
1003 => array(
'name' => esc_html__( 'Product 6', 'et_builder' ),
'price' => '38.00',
),
);
$cross_sell_products = [];
foreach ( $cross_sell_items as $id => $details ) {
$product = new ET_Builder_Woocommerce_Product_Simple_Placeholder();
$product->set_name( $details['name'] );
$product->set_id( $id );
$product->set_price( $details['price'] );
$cross_sell_products[] = $product;
}
wc_set_loop_prop( 'name', 'cross-sells' );
wc_set_loop_prop( 'columns', apply_filters( 'woocommerce_cross_sells_columns', 2 ) );
$orderby = apply_filters( 'woocommerce_cross_sells_orderby', 'rand' );
$order = apply_filters( 'woocommerce_cross_sells_order', 'desc' );
$cross_sells = wc_products_array_orderby( $cross_sell_products, $orderby, $order );
$limit = apply_filters( 'woocommerce_cross_sells_total', 0 );
$cross_sells = $limit > 0 ? array_slice( $cross_sells, 0, $limit ) : $cross_sells;
// Runs only on Builder mode.
add_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Cross_Sells',
'swap_template',
],
10,
5
);
ob_start();
wc_get_template(
'cart/cross-sells.php',
array(
'cross_sells' => $cross_sells,
// Not used now, but used in previous version of up-sells.php.
'posts_per_page' => $limit,
'orderby' => $orderby,
'columns' => 2,
)
);
$output = ob_get_clean();
remove_filter(
'wc_get_template',
[
'ET_Builder_Module_Woocommerce_Cross_Sells',
'swap_template',
],
10,
5
);
} else {
if ( ! is_null( WC()->cart ) ) {
ob_start();
woocommerce_cross_sell_display( 0 );
$output = ob_get_clean();
}
}
return $output;
}
/**
* 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 ) {
// Module classnames.
$this->add_classname(
array(
$this->get_text_orientation_classname(),
)
);
$output = self::get_cross_sells();
return $this->_render_module_wrapper( $output, $render_slug );
}
}
new ET_Builder_Module_Woocommerce_Cross_Sells();

View File

@@ -0,0 +1,543 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* 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 Product Description', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Description', 'et_builder' );
$this->slug = 'et_pb_wc_description';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$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 ) || is_et_pb_preview() ) {
$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,296 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
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 Product Gallery', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Gallery', 'et_builder' );
$this->slug = 'et_pb_wc_gallery';
$this->folder_name = 'et_pb_woo_modules';
$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 ) || is_et_pb_preview() ) {
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,398 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Images component.
*/
class ET_Builder_Module_Woocommerce_Images extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Product Images', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Images', 'et_builder' );
$this->slug = 'et_pb_wc_images';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$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' ),
'sale_badge' => esc_html__( 'Sale Badge Text', 'et_builder' ),
),
),
);
$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',
),
'sale_badge' => array(
'css' => array(
'main' => array(
'border_radii' => '%%order_class%% span.onsale',
'border_styles' => '%%order_class%% span.onsale',
),
'important' => true,
),
'defaults' => array(
'border_radii' => 'on|3px|3px|3px|3px',
),
'label_prefix' => esc_html__( 'Sale Badge', 'et_builder' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'sale_badge',
),
),
'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,
),
),
'sale_badge' => array(
'label' => esc_html__( 'Sale Badge Box Shadow', 'et_builder' ),
'option_category' => 'layout',
'tab_slug' => 'advanced',
'toggle_slug' => 'sale_badge',
'css' => array(
'main' => '%%order_class%% span.onsale',
'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,
'form_field' => array(
'sale_badge' => array(
'label' => esc_html__( 'Sale Badge', 'et_builder' ),
'background_color' => false,
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'font_field' => false,
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% ul.products li.product span.onsale',
'important' => array( 'custom_margin', 'custom_padding' ),
),
'custom_margin' => array(
'default' => '0px|0px|0px|0px|false|false',
),
'custom_padding' => array(
'default' => '6px|18px|6px|18px|false|false',
),
'toggle_slug' => 'sale_badge',
),
'border_styles' => false,
'box_shadow' => 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,402 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Meta component.
*/
class ET_Builder_Module_Woocommerce_Meta extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Product Meta', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Meta', 'et_builder' );
$this->slug = 'et_pb_wc_meta';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$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,239 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Price component.
*/
class ET_Builder_Module_Woocommerce_Price extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Product Price', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Price', 'et_builder' );
// Use `et_pb_wc_{module}` for all WooCommerce modules.
$this->slug = 'et_pb_wc_price';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$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,349 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* 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 Product Rating', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Rating', 'et_builder' );
$this->slug = 'et_pb_wc_rating';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$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();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,507 @@
<?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';
}
defined( 'ABSPATH' ) || exit;
/**
* 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 Product Reviews', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Reviews', 'et_builder' );
$this->slug = 'et_pb_wc_reviews';
$this->folder_name = 'et_pb_woo_modules';
// 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['show_rating'] = array(
'label' => esc_html__( 'Show Rating', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Turn rating on or off.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
);
$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 || is_et_pb_preview() ) {
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 || is_et_pb_preview() ) {
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();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,208 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Stock component.
*/
class ET_Builder_Module_Woocommerce_Stock extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Product Stock', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Stock', 'et_builder' );
$this->slug = 'et_pb_wc_stock';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$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,469 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
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 {
/**
* Holds WooCommerce Tabs data rendered by self::get_tabs().
*
* @var array
*/
public $rendered_tabs_data = [];
/**
* 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 Product Tabs', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Tabs', 'et_builder' );
$this->slug = 'et_pb_wc_tabs';
$this->folder_name = 'et_pb_woo_modules';
/*
* 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 );
$tabs = array();
// 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();
$is_use_placeholder = $is_tb || is_et_pb_preview();
if ( $is_use_placeholder ) {
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 ) );
}
if ( ! is_a( $post, 'WP_Post' ) ) {
return $tabs;
}
// Get product tabs.
$all_tabs = apply_filters( 'woocommerce_product_tabs', array() );
$active_tabs = isset( $args['include_tabs'] ) ? explode( '|', $args['include_tabs'] ) : false;
// 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 ( ! $is_use_placeholder && ! 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 ( $is_use_placeholder ) {
$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_use_placeholder ) {
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,217 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* Class representing WooCommerce Title component.
*/
class ET_Builder_Module_Woocommerce_Title extends ET_Builder_Module {
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Product Title', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Title', 'et_builder' );
$this->slug = 'et_pb_wc_title';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$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', 'product' )
);
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,915 @@
<?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
*/
defined( 'ABSPATH' ) || exit;
/**
* 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;
/**
* Number of products to be offset.
*
* @var int Default 0.
*/
public static $offset = 0;
/**
* Initialize.
*/
public function init() {
$this->name = esc_html__( 'Woo Product Upsell', 'et_builder' );
$this->plural = esc_html__( 'Woo Product Upsell', 'et_builder' );
// Use `et_pb_wc_{module}` for all WooCommerce modules.
$this->slug = 'et_pb_wc_upsells';
$this->vb_support = 'on';
$this->folder_name = 'et_pb_woo_modules';
$this->main_css_element = '%%order_class%%';
$this->settings_modal_toggles = array(
'general' => array(
'toggles' => array(
'main_content' => et_builder_i18n( 'Content' ),
'elements' => et_builder_i18n( 'Elements' ),
),
),
'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' ),
'sale_badge' => esc_html__( 'Sale Badge Text', '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' => '14px',
'label' => esc_html__( 'Star Rating Size', 'et_builder' ),
),
'hide_font' => true,
'hide_line_height' => true,
'hide_text_shadow' => true,
'text_align' => array(
'label' => esc_html__( 'Star Rating Alignment', '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',
),
'sale_badge' => array(
'css' => array(
'main' => array(
'border_radii' => '%%order_class%% span.onsale',
'border_styles' => '%%order_class%% span.onsale',
),
'important' => true,
),
'defaults' => array(
'border_radii' => 'on|3px|3px|3px|3px',
),
'label_prefix' => esc_html__( 'Sale Badge', 'et_builder' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'sale_badge',
),
),
'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' => '',
),
),
'sale_badge' => array(
'label' => esc_html__( 'Sale Badge Box Shadow', 'et_builder' ),
'option_category' => 'layout',
'tab_slug' => 'advanced',
'toggle_slug' => 'sale_badge',
'css' => array(
'main' => '%%order_class%% span.onsale',
'overlay' => 'inset',
'important' => true,
),
),
),
'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,
'form_field' => array(
'sale_badge' => array(
'label' => esc_html__( 'Sale Badge', 'et_builder' ),
'background_color' => false,
'text_color' => false,
'focus_background_color' => false,
'focus_text_color' => false,
'font_field' => false,
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%% ul.products li.product span.onsale',
'important' => array( 'custom_margin', 'custom_padding' ),
),
'custom_margin' => array(
'default' => '0px|0px|0px|0px|false|false',
),
'custom_padding' => array(
'default' => '6px|18px|6px|18px|false|false',
),
'toggle_slug' => 'sale_badge',
),
'border_styles' => false,
'box_shadow' => 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,
),
'show_name' => array(
'label' => esc_html__( 'Show Name', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Turn name on or off.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'show_image' => array(
'label' => esc_html__( 'Show Image', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Turn image on or off.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'show_price' => array(
'label' => esc_html__( 'Show Price', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Turn price on or off.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'show_rating' => array(
'label' => esc_html__( 'Show Rating', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Turn rating on or off.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'show_sale_badge' => array(
'label' => esc_html__( 'Show Sale Badge', 'et_builder' ),
'type' => 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'on' => esc_html__( 'Yes', 'et_builder' ),
'off' => esc_html__( 'No', 'et_builder' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'elements',
'description' => esc_html__( 'Turn sale badge on or off.', 'et_builder' ),
'mobile_options' => true,
'hover' => 'tabs',
),
'offset_number' => ET_Builder_Module_Helper_Woocommerce_Modules::get_field(
'offset_number',
array(
'computed_affects' => array(
'__upsells',
),
)
),
'__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',
'offset_number',
),
'computed_minimum' => array(
'product',
),
),
);
return $fields;
}
/**
* Appends offset to the WP_Query that retrieves Products.
*
* @since 4.14.0
*
* @param array $query_args Query args.
*
* @return array
*/
public static function append_offset( $query_args ) {
if ( ! is_array( $query_args ) ) {
return $query_args;
}
$query_args['offset'] = self::$offset;
return $query_args;
}
/**
* {@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;
$offset_number = et_()->array_get( $args, 'offset_number', 0 );
// 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 ) || is_et_pb_preview() ) {
// 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' );
}
$is_offset_valid = absint( $offset_number ) > 0;
if ( $is_offset_valid ) {
self::$offset = $offset_number;
add_filter(
'woocommerce_shortcode_products_query',
array( 'ET_Builder_Module_Woocommerce_Upsells', 'append_offset' )
);
}
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' )
);
if ( $is_offset_valid ) {
remove_filter(
'woocommerce_shortcode_products_query',
array( 'ET_Builder_Module_Woocommerce_Upsells', 'append_offset' )
);
self::$offset = 0;
}
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;
}
/**
* Adds Multi view attributes to the Outer wrapper.
*
* Since we do not have control over the WooCommerce Related Products markup, we inject Multi
* view attributes on to the Outer wrapper.
*
* @param array $outer_wrapper_attrs Outer wrapper attributes.
*
* @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_upsells_no_name' => array(
'show_name' => 'off',
),
'et_pb_wc_upsells_no_image' => array(
'show_image' => 'off',
),
'et_pb_wc_upsells_no_price' => array(
'show_price' => 'off',
),
'et_pb_wc_upsells_no_rating' => array(
'show_rating' => 'off',
),
'et_pb_wc_upsells_no_sale_badge' => array(
'show_sale_badge' => '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%% 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
);
add_filter(
"et_builder_module_{$render_slug}_outer_wrapper_attrs",
array(
$this,
'add_multi_view_attrs',
)
);
$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();