: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( $is_border_default && method_exists( $this, '_add_additional_border_fields' ) ) {
$border = self::$_->array_get( $this->advanced_fields, 'border', array() );
// Do not add overflow:hidden for some modules.
$no_overflow_module = array(
'et_pb_social_media_follow',
'et_pb_social_media_follow_network',
$overflow = ! in_array( $function_name, $no_overflow_module );
$overflow_x = ! in_array( self::$_->array_get( $this->props, 'overflow-x' ), array( '', 'hidden' ) );
$overflow_y = ! in_array( self::$_->array_get( $this->props, 'overflow-y' ), array( '', 'hidden' ) );
// Remove "overflow: hidden" if both overflow-x and overflow-y are not empty or not set to "hidden"
// Add "overflow-y: hidden" if overflow-x is not empty or not set to "hidden" (or vice versa)
if ( $overflow_x && $overflow_y ) {
} else if ( $overflow_x ) {
$overflow = 'overflow-y';
} else if ( $overflow_y ) {
$overflow = 'overflow-x';
// Render border radii for all devices.
foreach( et_pb_responsive_options()->get_modes() as $device ) {
$border_radii_attrs = array(
'selector' => self::$_->array_get( $border, 'css.main.border_radii', $this->main_css_element ),
'declaration' => $border_field->get_radii_style( $this->props, $this->advanced_fields, $suffix, $overflow, false, $device ),
'priority' => $this->_style_priority,
// Set media query attribute for non-desktop.
if ( 'desktop' !== $device ) {
$media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767';
$border_radii_attrs['media_query'] = ET_Builder_Element::get_media_query( $media_query );
self::set_style( $function_name, $border_radii_attrs );
if ( et_builder_is_hover_enabled( "border_radii$suffix", $this->props ) ) {
$main = self::$_->array_get( $border, 'css.hover', $this->main_css_element );
$main = self::$data_utils->array_get( $border, 'css.main.border_radii', $main );
$main = 'default' !== $border_name ? et_pb_hover_options()->add_hover_to_selectors( $main ) : et_pb_hover_options()->add_hover_to_order_class( $main );
$selector = self::$data_utils->array_get( $border, 'css.main.border_radii_hover', $main );
self::set_style( $function_name, array(
'declaration' => $border_field->get_radii_style( $this->props, $this->advanced_fields, $suffix, $overflow, true ),
'priority' => $this->_style_priority,
// Render border styles for all devices.
foreach( et_pb_responsive_options()->get_modes() as $device ) {
$border_styles_attrs = array(
'selector' => self::$_->array_get( $border, 'css.main.border_styles', $this->main_css_element ),
'declaration' => $border_field->get_borders_style( $this->props, $this->advanced_fields, $suffix, false, $device ),
'priority' => $this->_style_priority,
// Set media query attribute for non-desktop.
if ( 'desktop' !== $device ) {
$media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767';
$border_styles_attrs['media_query'] = ET_Builder_Element::get_media_query( $media_query );
self::set_style( $function_name, $border_styles_attrs );
$main = self::$_->array_get( $border, 'css.hover', $this->main_css_element );
$main = self::$data_utils->array_get( $border, 'css.main.border_styles', $main );
$main = 'default' !== $border_name ? et_pb_hover_options()->add_hover_to_selectors( $main ) : et_pb_hover_options()->add_hover_to_order_class( $main );
$selector = self::$data_utils->array_get( $border, 'css.main.border_styles_hover', $main );
self::set_style( $function_name, array(
'declaration' => $border_field->get_borders_style( $this->props, $this->advanced_fields, $suffix, true ),
'priority' => $this->_style_priority,
if ( ! $et_fb_processing_shortcode_object && $border_field->needs_border_reset_class( $function_name, $this->props ) ) {
// Try to apply old method for plugins without vb support
if ( 'on' !== $this->vb_support ) {
add_filter( "{$function_name}_shortcode_output", array( $border_field, 'add_border_reset_class' ), 10, 2 );
$this->add_classname( 'et_pb_with_border' );
if ( method_exists( $this, 'process_advanced_border_options' ) ) {
// Backwards Compatibility
// Call it after processing default fields because it's additional processing and is not replacement.
$this->process_advanced_border_options( $function_name );
function get_position_locations() {
return $this->position_locations;
function set_position_locations( $locations ) {
$this->position_locations = $locations;
function process_transform( $function_name ) {
$transform = self::$_->array_get( $this->advanced_fields, 'transform', array() );
if ( false === $transform || ! is_array( $transform ) ) {
$selector = self::$_->array_get( $transform, 'css.main', '%%order_class%%' );
$important = self::$_->array_get( $transform, 'css.important', false );
$hover = et_pb_hover_options();
$isHoverEnabled = $hover->is_enabled( 'transform_styles', $this->props );
$isResponsiveEnabled = isset( $this->props['transform_styles_last_edited'] )
&& et_pb_get_responsive_status( $this->props['transform_styles_last_edited'] );
$responsiveDirection = isset( $this->props['animation_direction_last_edited'] )
&& et_pb_get_responsive_status( $this->props['animation_direction_last_edited'] );
$animationType = self::$_->array_get( $this->props, 'animation_style', 'none' );
/** @var $class ET_Builder_Module_Field_Transform */
$class = ET_Builder_Module_Fields_Factory::get( 'Transform' );
$class->set_props( $this->props + array( 'transforms_important' => $important ) );
$position_locations = $this->get_position_locations();
$views = array( 'desktop' );
if ( $isHoverEnabled || isset( $position_locations['hover'] ) ) {
array_push( $views, 'hover' );
if ( $isResponsiveEnabled || ( 'none' !== $animationType && $responsiveDirection )
|| ( isset( $position_locations['hover'] ) || isset( $position_locations['phone'] ) ) ) {
array_push( $views, 'tablet', 'phone' );
foreach ( $views as $view ) {
$viewSelector = $selector;
if ( ! $isResponsiveEnabled && in_array( $view, array( 'phone', 'tablet' ) ) || ( 'hover' === $view && ! $isHoverEnabled ) ) {
$elements = $class->get_elements( $device );
if ( 'hover' === $view ) {
$viewSelector = $selector . ':hover';
} elseif ( 'tablet' === $view ) {
'media_query' => self::get_media_query( 'max_width_980' ),
} elseif ( 'phone' === $view ) {
'media_query' => self::get_media_query( 'max_width_767' ),
if ( isset( $position_locations[ $view ] ) ) {
$default_strpos = strpos( $position_locations[ $view ], '_is_default' );
$location = $position_locations[ $view ];
if ( $default_strpos !== false ) {
$location = substr( $position_locations[ $view ], 0, $default_strpos );
if ( ! isset( $elements['transform']['translateX'] ) ) {
if ( in_array( $location, array( 'top_center', 'bottom_center', 'center_center' ) ) ) {
$elements['transform']['translateX'] = '-50%';
} elseif ( $view !== 'desktop' ) {
$elements['transform']['translateX'] = '0px';
if ( ! isset( $elements['transform']['translateY'] ) ) {
if ( in_array( $location, array( 'center_left', 'center_right', 'center_center' ) ) ) {
$elements['transform']['translateY'] = '-50%';
} elseif ( $view !== 'desktop' ) {
$elements['transform']['translateY'] = '0px';
if ( ! empty( $elements['transform'] ) || ! empty( $elements['origin'] ) ) {
if ( 'hover' !== $view && ! empty( $animationType ) && 'none' !== $animationType && 'fade' !== $animationType ) {
$transformedAnimation = $class->transformedAnimation( $animationType, $elements, $function_name, $device );
if ( ! empty( $transformedAnimation ) ) {
self::set_style( $function_name, $transformedAnimation['keyframe'] + $media_query );
self::set_style( $function_name, $transformedAnimation['animationRules'] + $media_query );
self::set_style( $function_name,
'selector' => $viewSelector,
'declaration' => $transformedAnimation['declaration'],
'priority' => $this->_style_priority,
if ( ! empty( $elements['transform'] ) ) {
$declaration .= $class->getTransformDeclaration( $elements['transform'], $view );
if ( ! empty( $elements['origin'] ) ) {
array_push( $elements['origin'], '!important' );
$declaration .= sprintf( "transform-origin:%s;", implode( ' ', $elements['origin'] ) );
self::set_style( $function_name,
'selector' => $viewSelector,
'declaration' => $declaration,
'priority' => $this->_style_priority,
function process_position( $function_name ) {
/** @var $position_class ET_Builder_Module_Field_Position */
$position_class = ET_Builder_Module_Fields_Factory::get( 'Position' );
$position_class->set_module( $this );
$position_class->process( $function_name );
// Expose position settings on layout block preview so necesary adjustment can be applied
if ( ET_GB_Block_Layout::is_layout_block_preview() ) {
$layout_block_settings = $position_class->get_layout_block_settings( $function_name );
if ( is_array( $layout_block_settings ) && ! empty( $layout_block_settings ) ) {
self::$layout_block_assistive_settings['position'][] = array(
'selector' => '.' . self::get_module_order_class( $function_name ),
'settings' => $layout_block_settings,
* Adds Filter styles to the page custom css code
* Wrapper for `generate_css_filters` used for module defaults
function process_advanced_filter_options( $function_name ) {
// Disable if module doesn't set advanced_fields property and has no VB support
if ( ! $this->has_vb_support() && ! $this->has_advanced_fields ) {
// Module has to explicitly set false to disable filters options
if ( false === self::$_->array_get( $this->advanced_fields, 'filters', false ) ) {
return $this->generate_css_filters( $function_name );
function process_max_width_options( $function_name ) {
// Disable if module doesn't set advanced_fields property and has no VB support
if ( ! $this->has_vb_support() && ! $this->has_advanced_fields ) {
if ( ! is_array( self::$_->array_get( $this->advanced_fields, 'max_width', false ) ) ) {
$max_width = self::$_->array_get( $this->advanced_fields, 'max_width', array() );
$fields = array_merge( array('' => $max_width), self::$_->array_get( $max_width, 'extra', array() ) );
foreach ( $fields as $prefix => $field ) {
$is_customized = ! self::$_->array_get( $field, 'use_max_width', true ) && ! self::$_->array_get( $field, 'use_width', true );
$hover = et_pb_hover_options();
if ( 'et_pb_section' === $this->slug && 'inner' === $prefix && 'on' !== $this->prop( 'specialty' ) ) {
// https://github.com/elegantthemes/Divi/issues/14445
// This is a hot fix due to the fact that in near future
// modules will be processed and rendered in VB
// The real solution requires handling modules fields dependencies in FE
// As section inner sizing depends on section `speciality`
foreach ( array( 'width', 'max_width' ) as $key ) {
if ( ! self::$_->array_get( $field, "use_$key", true ) ) {
$slug = et_builder_add_prefix( $prefix, $key );
$css_prop = $this->field_to_css_prop( $key );
$option = self::$_->array_get( $this->fields_unprocessed, $slug, array() );
$width_options_css = self::$_->array_get($field, 'css', array());
$default_selector = self::$_->array_get( $width_options_css, 'main', '%%order_class%%' );
$selector = self::$_->array_get( $width_options_css, $key, $default_selector );
$desktop_default = self::$_->array_get( $option, 'default' );
$default = $desktop_default;
$width = $this->prop( $slug, $default );
$default_tablet = self::$_->array_get( $option, 'default_tablet', $width );
$width_tablet = $this->prop( "{$slug}_tablet", $default_tablet );
$default_phone = self::$_->array_get( $option, 'default_phone', $width_tablet );
$width_phone = $this->prop( "{$slug}_phone", $default_phone );
$width_hover = $hover->get_value( $slug, $this->props, '' );
$width_last_edited = $this->prop( "{$slug}_last_edited", '' );
$width_responsive_active = et_pb_get_responsive_status( $width_last_edited );
$width = $width === $default ? '' : $width;
$width_tablet = $width_tablet === $default_tablet ? '' : $width_tablet;
$width_phone = $width_phone === $default_phone ? '' : $width_phone;
if ( '' !== $width_tablet || '' !== $width_phone || '' !== $width ) {
$additional_css = $this->get_max_width_additional_css();
$width_attrs = array( $slug );
if ( isset( $width_options_css['important'] ) ) {
$additional_css = ' !important;';
if ( $width_responsive_active ) {
'desktop_only' => $width,
'tablet' => $width_tablet,
$width_attrs = array_merge( $width_attrs, array( "{$slug}_tablet", "{$slug}_phone" ) );
// Update $is_max_width_customized if one of max_width* value is modified
foreach ( $width_attrs as $width_attr ) {
if ( ! in_array( self::$_->array_get($this->props, $width_attr ), array( '', $default ) ) ) {
et_pb_generate_responsive_css(
} else if ( '' !== $default && '100%' !== $default && ! in_array( $default, array( 'auto', 'none' ) ) ) {
if ( '' !== $width_hover ) {
// Apply 100% max-width if there is only hover max-width set so that transition works.
$selector = isset( $width_options_css['main'] ) ? $width_options_css['main'] : '%%order_class%%';
$hover_width = $desktop_default ? $desktop_default : '100%';
'declaration' => esc_html( "$css_prop: $hover_width;" ),
ET_Builder_Element::set_style( $function_name, $hover_base );
$selector_hover = et_pb_hover_options()->add_hover_to_order_class( $selector );
$additional_css = $this->get_max_width_additional_css();
'selector' => $selector_hover,
'declaration' => esc_html( "$css_prop: {$width_hover}{$additional_css};" )
ET_Builder_Element::set_style( $function_name, $hover_style );
if ( self::$_->array_get( $field, 'use_module_alignment', true ) ) {
$module_alignment_styles = array(
'left' => 'margin-left: 0px !important; margin-right: auto !important;',
'center' => 'margin-left: auto !important; margin-right: auto !important;',
'right' => 'margin-left: auto !important; margin-right: 0px !important;',
$slug = et_builder_add_prefix( $prefix, 'module_alignment' );
$module_alignment = $this->prop( $slug, '' );
if ( $is_customized && isset( $module_alignment_styles[ $module_alignment ] ) ) {
$default_selector = self::$_->array_get( $field, 'css.main', '%%order_class%%.et_pb_module' );
$selector = self::$_->array_get( $field, 'css.module_alignment', $default_selector );
self::set_style( $function_name, array(
'declaration' => $module_alignment_styles[ $module_alignment ],
$is_module_alignment_responsive = et_pb_responsive_options()->is_responsive_enabled( $this->props, $slug );
$module_alignment_tablet = $this->prop( "{$slug}_tablet", '' );
if ( $is_customized && isset( $module_alignment_styles[ $module_alignment_tablet ] ) && $is_module_alignment_responsive ) {
$default_selector = self::$_->array_get( $field, 'css.main', '%%order_class%%.et_pb_module' );
$selector = self::$_->array_get( $field, 'css.module_alignment', $default_selector );
self::set_style( $function_name, array(
'declaration' => $module_alignment_styles[ $module_alignment_tablet ],
'media_query' => ET_Builder_Element::get_media_query( 'max_width_980' ),
$module_alignment_phone = $this->prop( "{$slug}_phone", '' );
if ( $is_customized && isset( $module_alignment_styles[ $module_alignment_phone ] ) && $is_module_alignment_responsive ) {
$default_selector = self::$_->array_get( $field, 'css.main', '%%order_class%%.et_pb_module' );
$selector = self::$_->array_get( $field, 'css.module_alignment', $default_selector );
self::set_style( $function_name, array(
'declaration' => $module_alignment_styles[ $module_alignment_phone ],
'media_query' => ET_Builder_Element::get_media_query( 'max_width_767' ),
function process_scroll_effects( $function_name ) {
$advanced_fields = self::$_->array_get( $this->advanced_fields, 'scroll_effects', array( 'default' => array() ) );
if ( ! $advanced_fields ) {
// Accordion Module reuses the Toggle Module and its child are not marked as child on FE, so check this specific case.
$is_child_element = 'child' === $this->type || 'et_pb_accordion_item' === $function_name;
$options = $this->get_scroll_effects_options();
$motion = ET_Builder_Module_Helper_Motion::instance();
$responsive = et_pb_responsive_options();
// Reset saved parent effects to not apply them on subsequent modules.
if ( !$is_child_element ) {
self::$parent_motion_effects = array();
foreach ( $options as $id => $option ) {
$is_effect_enabled = 'on' === $this->prop( $id . '_enable' );
$is_inherit_parent = $is_child_element && !empty( self::$parent_motion_effects ) && isset( self::$parent_motion_effects[ $id ] );
if ( !$is_effect_enabled && !$is_inherit_parent ) {
$default = $option['default'];
foreach ( $devices as $device ) {
if ( ! $is_effect_enabled ) {
$item = self::$parent_motion_effects[ $id ];
$item['id'] = '.' . self::get_module_order_class( $function_name );
$item['module_type'] = esc_html( $function_name );
$field = $responsive->get_field( $id, $device );
$default_value = $responsive->get_default_value( $this->props, $field, $default );
$saved_value = $this->prop( $field, $default_value );
$value = $motion->getValue( $saved_value, $default_value );
$grid_motion = $this->prop( 'enable_grid_motion', 'off' );
$trigger_start = $this->prop( 'motion_trigger_start', 'middle' );
$trigger_end = $this->prop( 'motion_trigger_end', 'middle' );
$grid_modules = array('et_pb_gallery', 'et_pb_portfolio', 'et_pb_fullwidth_portfolio', 'et_pb_filterable_portfolio', 'et_pb_shop', 'et_pb_blog');
'id' => '.' . self::get_module_order_class( $function_name ),
'start' => $motion->getStartLimit( $value ),
'midStart' => $motion->getStartMiddle( $value ),