: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
'midEnd' => $motion->getEndMiddle( $value ),
'end' => $motion->getEndLimit( $value ),
'startValue' => (float) $motion->getStartValue( $value ),
'midValue' => (float) $motion->getMiddleValue( $value ),
'endValue' => (float) $motion->getEndValue( $value ),
'resolver' => $option['resolver'],
'module_type' => esc_html( $function_name ),
'trigger_start' => $trigger_start,
'trigger_end' => $trigger_end,
$transform_class = ET_Builder_Module_Fields_Factory::get( 'Transform' );
$transform_class->set_props( $this->props + array( 'transforms_important' => true ) );
$elements = $transform_class->get_elements( $device );
// Process transforms if defined
if ( !empty( $elements ) && !empty( $elements['transform'] ) ) {
$item['transforms'] = $elements['transform'];
if ( 'on' === $grid_motion ) {
$item['grid_motion'] = $grid_motion;
$item['children_count'] = in_array( $function_name, $grid_modules ) ? $this->prop( 'posts_number', 10 ) : 0;
$item['module_index'] = self::_get_index( array( self::INDEX_MODULE_ORDER, $function_name ) );
if ( $this->child_slug && 'on' === $grid_motion ) {
self::$parent_motion_effects[ $id ] = $item;
unset(self::$parent_motion_effects[ $id ]['id'], self::$parent_motion_effects[ $id ]['grid_motion'], self::$parent_motion_effects[ $id ]['children_count'], self::$parent_motion_effects[ $id ]['module_index']);
$item['child_slug'] = $this->child_slug;
if ( $is_child_element ) {
if ( !empty( self::$parent_motion_effects[ $id ] ) ) {
$additional_item = self::$parent_motion_effects[ $id ];
$additional_item['id'] = $item['id'];
self::$_scroll_effects_fields[ $device ][] = $additional_item;
} else if ( 'on' !== $grid_motion ) {
self::$parent_motion_effects = array();
self::$_scroll_effects_fields[ $device ][] = $item;
public function process_height_options( $function_name ) {
if ( ! is_array( self::$_->array_get( $this->advanced_fields, 'height' ) ) ) {
$hover = et_pb_hover_options();
$responsive = et_pb_responsive_options();
$settings = self::$_->array_get( $this->advanced_fields, "height", array() );
$fields = array_merge( array( '' => $settings ), self::$_->array_get( $settings, 'extra', array() ) );
foreach ( $fields as $prefix => $settings ) {
$prefix = et_builder_add_prefix( $prefix, '' );
$default_selector = self::$_->array_get( $settings, "css.main", $this->main_css_element );
'height' => et_pb_height_options( $prefix ),
'min_height' => et_pb_min_height_options( $prefix ),
'max_height' => et_pb_max_height_options( $prefix ),
foreach ( $helpers as $key => $helper ) {
if ( ! self::$_->array_get( $settings, "use_{$key}", true ) ) {
$slug = $helper->get_field( $prefix );
$field = self::$_->array_get( $this->fields_unprocessed, $slug, array() );
$css_props = $this->field_to_css_prop( $key );
$selector = self::$_->array_get( $settings, "css.{$key}", $default_selector );
if ( $responsive->is_enabled( $slug, $this->props ) ) {
foreach ( $responsive->get_modes() as $mode ) {
$default_field = $mode == ET_Builder_Module_Helper_ResponsiveOptions::DESKTOP ? 'default' : "default_$mode";
$default = self::$_->array_get( $field, $default_field );
$values[ $mode ] = $responsive->get_value( $slug, $this->props, $mode, $default );
et_pb_generate_responsive_css( $values, $selector, $css_props, $function_name );
$default = self::$_->array_get( $field, 'default' );
$value = $helper->get_value( $this->props, $default );
if ( $value !== '' && $value !== $default ) {
self::set_style( $function_name,
'declaration' => sprintf( '%1$s: %2$s;', $css_props, esc_attr( $value ) ),
if ( $hover->is_enabled( $slug, $this->props ) ) {
$default = self::$_->array_get( $field, 'default' );
$value = $helper->get_value( $this->props, $default );
$hover_value = $hover->get_value( $slug, $this->props, $value );
$selector = $hover->add_hover_to_selectors( $selector );
if ( $hover_value !== '' && $hover_value !== $value ) {
self::set_style( $function_name,
'declaration' => sprintf( '%1$s: %2$s;', $css_props, esc_attr( $hover_value ) ),
public function process_overflow_options( $function_name ) {
if ( ! is_array( self::$_->array_get( $this->advanced_fields, 'overflow', array() ) ) ) {
$overflow = et_pb_overflow();
$hover = et_pb_hover_options();
$responsive = et_pb_responsive_options();
$selector = self::$_->array_get(
'overflow-x' => $overflow->get_field_x(),
'overflow-y' => $overflow->get_field_y(),
$controls = ET_Builder_Module_Fields_Factory::get( 'Overflow' )->get_fields( array(), true );
// Rebuilt template if template id is returned by get_fields()
if ( self::$option_template->is_enabled() && is_string( $controls ) ) {
$controls = self::$option_template->rebuild_field_template( $controls );
foreach ( $fields as $prop => $field ) {
$default_value = self::$_->array_get( $controls[ $field ], 'default', '' );
$overflow_values = et_pb_responsive_options()->get_property_values( $this->props, $field, $default_value );
et_pb_responsive_options()->generate_responsive_css( $overflow_values, $selector, $field, $function_name, '', 'overflow' );
if ( $hover->is_enabled( $field, $this->props ) ) {
$value = $hover->get_value( $field, $this->props, '' );
self::set_style( $function_name,
'selector' => $hover->add_hover_to_selectors( $selector ),
'declaration' => sprintf( '%1$s: %2$s;', $field, esc_attr( $value ) ),
function process_advanced_custom_margin_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 ( ! self::$_->array_get( $this->advanced_fields, 'margin_padding', false ) ) {
$hover = et_pb_hover_options();
$style_mobile_padding = array();
$style_mobile_margin = array();
$important_options = array();
$is_important_set = isset( $this->advanced_fields['margin_padding']['css']['important'] );
$use_global_important = $is_important_set && 'all' === $this->advanced_fields['margin_padding']['css']['important'];
$css = isset( $this->advanced_fields['margin_padding']['css'] ) ? $this->advanced_fields['margin_padding']['css'] : array();
if ( $is_important_set && is_array( $this->advanced_fields['margin_padding']['css']['important'] ) ) {
$important_options = $this->advanced_fields['margin_padding']['css']['important'];
$custom_margin = $this->advanced_fields['margin_padding']['use_margin'] ? $this->props['custom_margin'] : '';
$custom_padding = $this->advanced_fields['margin_padding']['use_padding'] ? $this->props['custom_padding'] : '';
$custom_margin_responsive_active = isset( $this->props['custom_margin_last_edited'] ) ? et_pb_get_responsive_status( $this->props['custom_margin_last_edited'] ) : false;
$custom_margin_mobile = $custom_margin_responsive_active && $this->advanced_fields['margin_padding']['use_margin'] && ( isset( $this->props['custom_margin_tablet'] ) || isset( $this->props['custom_margin_phone'] ) )
'tablet' => isset( $this->props['custom_margin_tablet'] ) ? $this->props['custom_margin_tablet'] : '',
'phone' => isset( $this->props['custom_margin_phone'] ) ? $this->props['custom_margin_phone'] : '',
$custom_padding_responsive_active = isset( $this->props['custom_padding_last_edited'] ) ? et_pb_get_responsive_status( $this->props['custom_padding_last_edited'] ) : false;
$custom_padding_mobile = $custom_padding_responsive_active && $this->advanced_fields['margin_padding']['use_padding'] && ( isset( $this->props['custom_padding_tablet'] ) || isset( $this->props['custom_padding_phone'] ) )
'tablet' => isset( $this->props['custom_padding_tablet'] ) ? $this->props['custom_padding_tablet'] : '',
'phone' => isset( $this->props['custom_padding_phone'] ) ? $this->props['custom_padding_phone'] : '',
if ( '' !== $custom_padding || ! empty( $custom_padding_mobile ) ) {
$important = in_array( 'custom_padding', $important_options ) || $use_global_important ? true : false;
$has_padding_selector = isset( $this->advanced_fields['margin_padding']['css'] ) && isset( $this->advanced_fields['margin_padding']['css']['padding'] );
$padding_styling = '' !== $custom_padding ? et_builder_get_element_style_css( $custom_padding, 'padding', $important ) : '';
if ( $has_padding_selector ) {
$style_padding .= $padding_styling;
$style .= $padding_styling;
if ( ! empty( $custom_padding_mobile ) ) {
foreach ( $custom_padding_mobile as $device => $settings ) {
$padding_mobile_styling = '' !== $settings ? et_builder_get_element_style_css( $settings, 'padding', $important ) : '';
if ( $has_padding_selector ) {
$style_mobile_padding[ $device ][] = $padding_mobile_styling;
$style_mobile[ $device ][] = $padding_mobile_styling;
$selective_paddings = array_filter( array(
'top' => isset( $css['padding-top'] ) ? $css['padding-top'] : false,
'right' => isset( $css['padding-right'] ) ? $css['padding-right'] : false,
'bottom' => isset( $css['padding-bottom'] ) ? $css['padding-bottom'] : false,
'left' => isset( $css['padding-left'] ) ? $css['padding-left'] : false,
// Only run the following if selective-padding selector is defined
if ( ! empty( $selective_paddings ) ) {
// Loop each padding sides. Selective padding works by creating filtered custom_margin value on the fly, then pass it to existin declaration builder
// Ie custom_padding = 10px|10px|10px|10px. Selective padding for padding-top works by creating 10px||| value on the fly then pass it to declaration builder
foreach ( $selective_paddings as $corner => $selective_padding_selectors ) {
// Default selective padding value: empty on all sides
$selective_padding = array( '', '', '', '' );
// Get padding order key. Expected order: top|right|bottom|left
$selective_padding_key = $item_mappings[ $corner ];
// Explode custom padding value into array
$selective_padding_array = explode( '|', $custom_padding );
// Pick current padding side's value
$selective_padding_value = isset( $selective_padding_array[ $selective_padding_key ] ) ? $selective_padding_array[ $selective_padding_key ] : '';
// Set selective padding value to $selective_padding
$selective_padding[ $selective_padding_key ] = $selective_padding_value;
// If selective padding for current side is found, set style for it
$selective_padding_filtered = array_filter( $selective_padding );
if ( ! empty( $selective_padding_filtered ) ) {
self::set_style( $function_name, array(
'selector' => $selective_padding_selectors,
'declaration' => rtrim( et_builder_get_element_style_css( implode( '|', $selective_padding ), 'padding' ) ),
'priority' => $this->_style_priority,
// Check wheter responsive padding is activated and padding has mobile value
if ( $custom_padding_responsive_active && is_array( $custom_padding_mobile ) ) {
// Assume no mobile padding value first
$has_selective_padding_mobile = false;
// Set default selective padding mobile
$selective_padding_mobile = array(
'tablet' => array( '', '', '', '' ),
'phone' => array( '', '', '', '' ),
// Loop padding mobile. This results per-breakpoint padding value
foreach ( $custom_padding_mobile as $breakpoint => $custom_padding_device ) {
// Explode per-breakpoint padding value into array
$custom_padding_device_array = explode( '|', $custom_padding_device );
// Get current padding side value on current breakpoint
$selective_padding_mobile_value = isset( $custom_padding_device_array[ $selective_padding_key ] ) ? $custom_padding_device_array[ $selective_padding_key ] : '';
// Set picked value into current padding side on current breakpoint
$selective_padding_mobile[ $breakpoint ][ $selective_padding_key ] = $selective_padding_mobile_value;
// If the side of padding on current breakpoint has value, build CSS declaration for it mark selective padding mobile as exist
$selective_padding_mobile[ $breakpoint ] = array_filter( $selective_padding_mobile[ $breakpoint ] );
if ( ! empty( $selective_padding_mobile[ $breakpoint ] ) ) {
$selective_padding_mobile[ $breakpoint ] = array( et_builder_get_element_style_css( implode( '|', $selective_padding_mobile[ $breakpoint ] ), 'padding' ) );
$has_selective_padding_mobile = true;
// Set style for selective padding on mobile
if ( $has_selective_padding_mobile ) {
$this->process_advanced_mobile_margin_options(
$selective_padding_mobile,
$selective_padding_selectors
if ( '' !== $custom_margin || ! empty( $custom_margin_mobile ) ) {
$important = in_array( 'custom_margin', $important_options ) || $use_global_important ? true : false;
$has_margin_selector = isset( $this->advanced_fields['margin_padding']['css'] ) && isset( $this->advanced_fields['margin_padding']['css']['margin'] );
$margin_styling = '' !== $custom_margin ? et_builder_get_element_style_css( $custom_margin, 'margin', $important ) : '';
if ( $has_margin_selector ) {
$style_margin .= $margin_styling;
$style .= $margin_styling;
if ( ! empty( $custom_margin_mobile ) ) {
foreach ( $custom_margin_mobile as $device => $settings ) {
$margin_mobile_styling = '' !== $settings ? et_builder_get_element_style_css( $settings, 'margin', $important ) : '';
if ( $has_margin_selector ) {
$style_mobile_margin[ $device ][] = $margin_mobile_styling;
$style_mobile[ $device ][] = $margin_mobile_styling;
if ( '' !== $style_padding ) {
$css_element_padding = $this->advanced_fields['margin_padding']['css']['padding'];
self::set_style( $function_name, array(
'selector' => $css_element_padding,
'declaration' => rtrim( $style_padding ),
'priority' => $this->_style_priority,
if ( '' !== $style_margin ) {
$css_element_margin = $this->advanced_fields['margin_padding']['css']['margin'];
self::set_style( $function_name, array(
'selector' => $css_element_margin,
'declaration' => rtrim( $style_margin ),
'priority' => $this->_style_priority,
$css_element = ! empty( $this->advanced_fields['margin_padding']['css']['main'] ) ? $this->advanced_fields['margin_padding']['css']['main'] : $this->main_css_element;
self::set_style( $function_name, array(
'selector' => $css_element,
'declaration' => rtrim( $style ),
'priority' => $this->_style_priority,
if ( ! empty( $style_mobile_padding ) ) {
$this->process_advanced_mobile_margin_options(
$this->advanced_fields['margin_padding']['css']['padding']
if ( ! empty( $style_mobile_margin ) ) {
$this->process_advanced_mobile_margin_options(
$this->advanced_fields['margin_padding']['css']['margin']
if ( ! empty( $style_mobile ) ) {
$css_element = ! empty( $this->advanced_fields['margin_padding']['css']['main'] ) ? $this->advanced_fields['margin_padding']['css']['main'] : $this->main_css_element;
$this->process_advanced_mobile_margin_options(
$custom_margin_hover = $hover->get_value( 'custom_margin', $this->props );
if ( '' !== $custom_margin_hover && et_builder_is_hover_enabled( 'custom_margin', $this->props ) ) {
$css_element_margin = self::$_->array_get( $this->advanced_fields, 'margin_padding.css.margin', $this->main_css_element );
self::set_style( $function_name, array(
'selector' => $this->add_hover_to_order_class( $css_element_margin ),
'declaration' => rtrim( et_builder_get_element_style_css( $custom_margin_hover, 'margin', true ) ),
$custom_padding_hover = $hover->get_value( 'custom_padding', $this->props, '' );
if ( '' !== $custom_padding_hover && et_builder_is_hover_enabled( 'custom_padding', $this->props ) ) {
$css_element_padding = self::$_->array_get( $this->advanced_fields, 'margin_padding.css.padding', $this->main_css_element );
self::set_style( $function_name, array(
'selector' => $this->add_hover_to_order_class( $css_element_padding ),
'declaration' => rtrim( et_builder_get_element_style_css( $custom_padding_hover, 'padding', true ) ),
function process_advanced_mobile_margin_options( $function_name, $style_mobile, $css_element ) {
foreach( $style_mobile as $device => $style ) {
if ( ! empty( $style ) ) {
$current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767';
foreach( $style as $css_code ) {
$current_media_css .= $css_code;
if ( '' === $current_media_css ) {
self::set_style( $function_name, array(
'selector' => $css_element,
'declaration' => rtrim( $current_media_css ),
'priority' => $this->_style_priority,
'media_query' => ET_Builder_Element::get_media_query( $current_media_query ),
protected function get_hover_value( $option ) {
$enabled_option = $option === 'background_color' ? 'background' : $option;
$original_value = self::$_->array_get( $this->props, $option );
$hover_enabled = et_pb_hover_options()->is_enabled( $enabled_option, $this->props );
$value = et_pb_hover_options()->get_value( $option, $this->props );
return ( ! $hover_enabled || $original_value === $value ) ? null : $value;
* Process advanced button options.
* @since 3.23 Add support to generate responsive styles of padding and button alignment.
* @param string $function_name Module slug.
function process_advanced_button_options( $function_name ) {
// Disable if module doesn't set advanced_fields property and has no VB support
if ( ! $this->has_advanced_fields ) {
if ( ! self::$_->array_get( $this->advanced_fields, 'button', false ) ) {
$hover = et_pb_hover_options();
foreach ( $this->advanced_fields['button'] as $option_name => $option_settings ) {
$button_custom = $this->props["custom_{$option_name}"];
$button_use_icon = isset( $this->props["{$option_name}_use_icon"] ) ? $this->props["{$option_name}_use_icon"] : 'on';
$button_icon_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_icon" );
$button_icon = isset( $button_icon_values['desktop'] ) ? $button_icon_values['desktop'] : '';
$button_icon_tablet = isset( $button_icon_values['tablet'] ) ? $button_icon_values['tablet'] : '';
$button_icon_phone = isset( $button_icon_values['phone'] ) ? $button_icon_values['phone'] : '';
$important = et_()->array_get( $option_settings, 'css.important', false ) ?
// Button Icon Placement.
$button_icon_placement_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_icon_placement" );
$button_icon_placement = isset( $button_icon_placement_values['desktop'] ) ? $button_icon_placement_values['desktop'] : 'right';
$button_icon_placement_tablet = isset( $button_icon_placement_values['tablet'] ) ? $button_icon_placement_values['tablet'] : '';
$button_icon_placement_phone = isset( $button_icon_placement_values['phone'] ) ? $button_icon_placement_values['phone'] : '';
$button_on_hover_values = et_pb_responsive_options()->get_property_values( $this->props, "{$option_name}_on_hover" );
$button_on_hover = isset( $button_on_hover_values['desktop'] ) ? $button_on_hover_values['desktop'] : '';
$button_on_hover_tablet = isset( $button_on_hover_values['tablet'] ) ? $button_on_hover_values['tablet'] : '';
$button_on_hover_phone = isset( $button_on_hover_values['phone'] ) ? $button_on_hover_values['phone'] : '';