: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @param string $selector
* @param string $css_prop
public function generate_responsive_hover_style( $option, $selector, $css_prop ) {
$responsive = et_pb_responsive_options();
$hover = et_pb_hover_options();
$values = $responsive->get_property_values( $this->props, $option );
$hover_value = $hover->get_value( $option, $this->props );
$responsive->generate_responsive_css( $values, $selector, $css_prop, $this->slug, '', 'color' );
self::set_style( $this->slug, array(
'selector' => $hover->add_hover_to_selectors( $selector ),
'declaration' => "{$css_prop}: $hover_value;"
protected static function _set_style( $function_name, $style ) {
$declaration = rtrim($style['declaration']);
if ( empty($declaration) ) {
// Do not add empty declarations
$builder_post_types = et_builder_get_builder_post_types();
$allowed_post_types = apply_filters( 'et_builder_set_style_allowed_post_types', $builder_post_types );
if ( $builder_post_types !== $allowed_post_types ) {
$matches = array_intersect( $allowed_post_types, array_keys( self::$_module_slugs_by_post_type ) );
foreach ( $matches as $post_type ) {
if ( ! isset( self::$_module_slugs_by_post_type[ $post_type ] ) ) {
if ( in_array( $function_name, self::$_module_slugs_by_post_type[ $post_type ] ) ) {
global $et_pb_rendering_column_content;
// do not process all the styles if FB enabled. Only those for modules without fb support and styles for the internal modules from Blog/Slider
$main_query_post = ET_Post_Stack::get_main_post();
$main_query_post_id = null !== $main_query_post ? $main_query_post->ID : 0;
$editing_current_post = et_fb_is_enabled() && self::get_layout_id() === $main_query_post_id;
if ( $editing_current_post && ! in_array( $function_name, self::get_fb_unsupported_modules() ) && ! $et_pb_rendering_column_content ) {
$order_class_name = self::get_module_order_class( $function_name );
$selector = str_replace( '%%order_class%%', ".{$order_class_name}", $style['selector'] );
$selector = str_replace( '%order_class%', ".{$order_class_name}", $selector );
// %%parent_class%% only works if child module's slug is `parent_slug` + _item suffix. If child module slug
// use different slug structure, %%parent_class%% should not be used
if ( false !== strpos( $selector, '%%parent_class%%' ) ) {
$parent_class = str_replace( '_item', '', $function_name );
$selector = str_replace( '%%parent_class%%', ".{$parent_class}", $selector );
$selector = strip_tags( apply_filters( 'et_pb_set_style_selector', $selector, $function_name ) );
$selector = et_builder_maybe_wrap_css_selectors( $selector, false );
// New lines are saved as || in CSS Custom settings, remove them
$declaration = preg_replace( '/(\|\|)/i', '', $declaration );
$media_query = isset( $style[ 'media_query' ] ) ? $style[ 'media_query' ] : 'general';
$internal = $et_pb_rendering_column_content && self::$prepare_internal_styles;
$style_key = self::get_style_key();
$styles = self::get_style_array( $internal );
// prepare styles for internal content. Used in Blog/Slider modules if they contain Divi modules
if ( isset( $styles[ $media_query ][ $selector ]['declaration'] ) ) {
$styles[ $media_query ][ $selector ]['declaration'] = sprintf(
$styles[ $media_query ][ $selector ]['declaration'],
$styles[ $media_query ][ $selector ]['declaration'] = $declaration;
if ( isset( $style['priority'] ) ) {
$styles[ $media_query ][ $selector ]['priority'] = (int) $style['priority'];
self::$internal_modules_styles[ $style_key ] = $styles;
self::$styles[ $style_key ] = $styles;
static function get_module_order_class( $function_name ) {
global $et_pb_rendering_column_content, $et_pb_predefined_module_index;
// determine whether we need to get the internal module class or regular
$get_inner_module_class = $et_pb_rendering_column_content;
if ( $get_inner_module_class ) {
if ( self::_get_index( array( self::INDEX_INNER_MODULE_ORDER, $function_name ) ) === -1 ) {
if ( self::_get_index( array( self::INDEX_MODULE_ORDER, $function_name ) ) === -1 ) {
if ( isset( $et_pb_predefined_module_index ) && $et_pb_predefined_module_index ) {
$shortcode_order_num = $et_pb_predefined_module_index;
$shortcode_order_num = $get_inner_module_class ? self::_get_index( array( self::INDEX_INNER_MODULE_ORDER, $function_name ) ) : self::_get_index( array( self::INDEX_MODULE_ORDER, $function_name ) );
$theme_builder_suffix = self::_get_theme_builder_order_class_suffix();
$order_class_name = sprintf( '%1$s_%2$s%3$s', $function_name, $shortcode_order_num, $theme_builder_suffix );
return $order_class_name;
static function set_order_class( $function_name ) {
global $et_pb_rendering_column_content;
// determine whether we need to update the internal module class or regular
$process_inner_module_class = $et_pb_rendering_column_content;
if ( $process_inner_module_class ) {
$current_inner_index = self::_get_index( array( self::INDEX_INNER_MODULE_ORDER, $function_name ) );
array( self::INDEX_INNER_MODULE_ORDER, $function_name ),
$current_inner_index > -1 ? $current_inner_index + 1 : self::$internal_modules_counter
array( self::INDEX_MODULE_ORDER, $function_name ),
self::_get_index( array( self::INDEX_MODULE_ORDER, $function_name ) ) + 1
static function add_module_order_class( $module_class, $function_name ) {
$order_class_name = self::get_module_order_class( $function_name );
return "{$module_class} {$order_class_name}";
* Generate video background markup.
* @since 3.23 Add support for responsive settings.
* @param array $args Background values.
* @param string $base_name Background base name.
* @return string Video background string value.
function video_background( $args = array(), $base_name = 'background' ) {
$attr_prefix = "{$base_name}_";
$custom_prefix = 'background' === $base_name ? '' : "{$base_name}_";
$module_attrs = $this->props;
// Default background class for each devices.
$background_video_class = '';
$background_video_class_tablet = 'et_pb_section_video_bg_tablet';
$background_video_class_phone = 'et_pb_section_video_bg_phone';
$background_video_class_hover = 'et_pb_section_video_bg_hover';
// Hover and Responsive Status.
$hover_enabled = self::$_->array_get( $this->props, "{$base_name}__hover_enabled", 'off' );
$is_background_hover = 'on' === $hover_enabled;
$is_background_mobile = et_pb_responsive_options()->is_responsive_enabled( $this->props, $base_name );
if ( ! empty( $args ) ) {
$background_video = self::get_video_background( $args );
$background_video_tablet = '';
$background_video_phone = '';
$background_video_hover = '';
$pause_outside_viewport = self::$_->array_get( $args, "{$attr_prefix}video_pause_outside_viewport", 'off' );
$allow_player_pause = self::$_->array_get( $args, "{$custom_prefix}allow_player_pause", 'off' );
$background_videos = array();
"{$attr_prefix}video_mp4" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_mp4" ),
"{$attr_prefix}video_webm" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_webm" ),
"{$attr_prefix}video_width" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_width", '', true ),
"{$attr_prefix}video_height" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_height", '', true ),
'computed_variables' => array(
'base_name' => $base_name,
// Collecting background videos.
$background_videos['desktop'] = self::get_video_background( $default_args );
$module_attrs["video_{$base_name}_values"] = $background_videos;
// Get video and display status.
$background_video_status = et_pb_responsive_options()->get_inheritance_background_value( $module_attrs, "video_{$base_name}_values", 'desktop', $base_name, $this->fields_unprocessed );
$background_video = self::$_->array_get( $background_video_status, 'video', '' );
$background_display = self::$_->array_get( $background_video_status, 'display', '' );
$background_video_hover = '';
$background_display_hover = '';
if ( $is_background_hover ) {
"{$attr_prefix}video_mp4__hover" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_mp4__hover" ),
"{$attr_prefix}video_webm__hover" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_webm__hover" ),
"{$attr_prefix}video_width__hover" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_width__hover", '', true ),
"{$attr_prefix}video_height__hover" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_height__hover", '', true ),
'computed_variables' => array(
'base_name' => $base_name,
// Collecting background videos.
$background_videos['hover'] = self::get_video_background( $hover_args );
$module_attrs["video_{$base_name}_values"] = $background_videos;
// Get video and display status.
$background_video_status_hover = et_pb_responsive_options()->get_inheritance_background_value( $module_attrs, "video_{$base_name}_values", 'hover', $base_name, $this->fields_unprocessed );
$background_video_hover = self::$_->array_get( $background_video_status_hover, 'video', '' );
$background_display_hover = self::$_->array_get( $background_video_status_hover, 'display', '' );
$background_video_tablet = '';
$background_display_tablet = '';
$background_video_phone = '';
$background_display_phone = '';
if ( $is_background_mobile ) {
"{$attr_prefix}video_mp4_tablet" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_mp4_tablet" ),
"{$attr_prefix}video_webm_tablet" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_webm_tablet" ),
"{$attr_prefix}video_width_tablet" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_width_tablet", '', true ),
"{$attr_prefix}video_height_tablet" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_height_tablet", '', true ),
'computed_variables' => array(
'base_name' => $base_name,
"{$attr_prefix}video_mp4_phone" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_mp4_phone" ),
"{$attr_prefix}video_webm_phone" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_webm_phone" ),
"{$attr_prefix}video_width_phone" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_width_phone", '', true ),
"{$attr_prefix}video_height_phone" => et_pb_responsive_options()->get_any_value( $this->props, "{$attr_prefix}video_height_phone", '', true ),
'computed_variables' => array(
'base_name' => $base_name,
// Collecting background videos.
$background_videos['tablet'] = self::get_video_background( $tablet_args );
$background_videos['phone'] = self::get_video_background( $phone_args );
$module_attrs["video_{$base_name}_values"] = $background_videos;
// Get video and display status.
$background_video_status_tablet = et_pb_responsive_options()->get_inheritance_background_value( $module_attrs, "video_{$base_name}_values", 'tablet', $base_name, $this->fields_unprocessed );
$background_video_tablet = self::$_->array_get( $background_video_status_tablet, 'video', '' );
$background_display_tablet = self::$_->array_get( $background_video_status_tablet, 'display', '' );
$background_video_status_phone = et_pb_responsive_options()->get_inheritance_background_value( $module_attrs, "video_{$base_name}_values", 'phone', $base_name, $this->fields_unprocessed );
$background_video_phone = self::$_->array_get( $background_video_status_phone, 'video', '' );
$background_display_phone = self::$_->array_get( $background_video_status_phone, 'display', '' );
// Set background video and class. Inherit is used to avoid rendering the same video.
if ( '' !== $background_display_phone ) {
if ( 'hide' === $background_display_phone ) {
$background_video_class = 'et_pb_section_video_bg_desktop_tablet';
$background_video_class_tablet = 'et_pb_section_video_bg_tablet_only';
} else if ( 'inherit' === $background_display_phone ) {
$background_video_phone = '';
if ( '' !== $background_display_tablet ) {
if ( 'hide' === $background_display_tablet ) {
$background_video_class = 'et_pb_section_video_bg_desktop_only';
} else if ( 'inherit' === $background_display_tablet ) {
$background_video_tablet = '';
if ( '' !== $background_display_hover ) {
if ( 'inherit' === $background_display_hover ) {
$background_video_class .= ' et_pb_section_video_bg_hover_inherit';
$background_video_hover = '';
if ( $background_video ) {
// Video on desktop properties.
$pause_outside_viewport = self::$_->array_get( $this->props, "{$attr_prefix}video_pause_outside_viewport", '' );
$allow_player_pause = self::$_->array_get( $this->props, "{$custom_prefix}allow_player_pause", 'off' );
$video_background .= sprintf(
'<span class="et_pb_section_video_bg %2$s %3$s%4$s">
( 'on' === $allow_player_pause ? ' et_pb_allow_player_pause' : '' ),
( 'off' === $pause_outside_viewport ? ' et_pb_video_play_outside_viewport' : '' )
if ( $is_background_hover ) {
if ( $background_video_hover ) {
// Video on hover properties.
$pause_outside_viewport_hover = self::$_->array_get( $this->props, "{$attr_prefix}video_pause_outside_viewport__hover", '' );
$allow_player_pause_hover = self::$_->array_get( $this->props, "{$custom_prefix}allow_player_pause__hover", 'off' );
$video_background .= sprintf(
'<span class="et_pb_section_video_bg %2$s %3$s%4$s">
$background_video_class_hover,
( 'on' === $allow_player_pause_hover ? ' et_pb_allow_player_pause' : '' ),
( 'off' === $pause_outside_viewport_hover ? ' et_pb_video_play_outside_viewport' : '' )
$this->add_classname( 'et_pb_section_video_on_hover' );
if ( $background_video_tablet && $is_background_mobile ) {
// Video on tablet properties.
$pause_outside_viewport_tablet = self::$_->array_get( $this->props, "{$attr_prefix}video_pause_outside_viewport_tablet", '' );
$allow_player_pause_tablet = self::$_->array_get( $this->props, "{$custom_prefix}allow_player_pause_tablet", 'off' );
$video_background .= sprintf(
'<span class="et_pb_section_video_bg %2$s %3$s%4$s">
$background_video_tablet,
$background_video_class_tablet,
( 'on' === $allow_player_pause_tablet ? ' et_pb_allow_player_pause' : '' ),
( 'off' === $pause_outside_viewport_tablet ? ' et_pb_video_play_outside_viewport' : '' )
if ( $background_video_phone && $is_background_mobile ) {
// Video on phone properties.
$pause_outside_viewport_phone = self::$_->array_get( $this->props, "{$attr_prefix}video_pause_outside_viewport_phone", '' );
$allow_player_pause_phone = self::$_->array_get( $this->props, "{$custom_prefix}allow_player_pause_phone", 'off' );
$video_background .= sprintf(
'<span class="et_pb_section_video_bg %2$s %3$s%4$s">
$background_video_class_phone,
( 'on' === $allow_player_pause_phone ? ' et_pb_allow_player_pause' : '' ),
( 'off' === $pause_outside_viewport_phone ? ' et_pb_video_play_outside_viewport' : '' )
// Added classname for module wrapper
if ( '' !== $video_background ) {
wp_enqueue_style( 'wp-mediaelement' );
wp_enqueue_script( 'wp-mediaelement' );
$this->add_classname( array( 'et_pb_section_video', 'et_pb_preload' ) );
return $video_background;
function get_parallax_image_background( $base_name = 'background' ) {
$attr_prefix = "{$base_name}_";
$custom_prefix = 'background' === $base_name ? '' : "{$base_name}_";
$parallax_processed = array();
$parallax_background = '';
$hover_suffix = et_pb_hover_options()->get_suffix();
$preview_modes = array( $hover_suffix, '_phone', '_tablet', '' );
// Featured Image as Background.
$featured_placement = '';
$featured_image_src = '';
if ( $this->featured_image_background ) {
$featured_image = self::$_->array_get( $this->props, 'featured_image', '' );
$featured_placement = self::$_->array_get( $this->props, 'featured_placement', '' );
$featured_image_src_obj = wp_get_attachment_image_src( get_post_thumbnail_id( self::_get_main_post_id() ), 'full' );
$featured_image_src = isset( $featured_image_src_obj[0] ) ? $featured_image_src_obj[0] : '';
foreach( $preview_modes as $suffix ) {
$is_hover = $hover_suffix === $suffix;
// A. Bail early if hover or responsive settings disabled on mobile/hover.
// Ensure responsive settings is enabled on mobile.
if ( ! $is_hover && ! et_pb_responsive_options()->is_responsive_enabled( $this->props, $base_name ) ) {
// Ensure hover settings is enabled.
if ( $is_hover && ! et_pb_hover_options()->is_enabled( $base_name, $this->props ) ) {
$mode = '' !== $suffix ? str_replace( '_', '', $suffix ) : 'desktop';
$mode = $is_hover ? 'hover' : $mode;
// B.1. Get inherited background value.
$background_image = et_pb_responsive_options()->get_inheritance_background_value( $this->props, "{$attr_prefix}image", $mode, $base_name, $this->fields_unprocessed );
$parallax = $is_hover ? et_pb_hover_options()->get_raw_value( "{$custom_prefix}parallax", $this->props ) : et_pb_responsive_options()->get_any_value( $this->props, "{$custom_prefix}parallax{$suffix}", '', true );
$parallax_method = $is_hover ? et_pb_hover_options()->get_raw_value( "{$custom_prefix}parallax_method", $this->props ) : et_pb_responsive_options()->get_any_value( $this->props, "{$custom_prefix}parallax_method{$suffix}", '', true );
// B.2. Set default value for parallax and parallax method on hover when they are empty.
$parallax = empty( $parallax ) ? et_pb_responsive_options()->get_any_value( $this->props, "{$custom_prefix}parallax", '', true ) : $parallax;
$parallax_method = empty( $parallax_method ) ? et_pb_responsive_options()->get_any_value( $this->props, "{$custom_prefix}parallax_method", '', true ) : $parallax_method;
// B.3. Override background image with featured image if needed.
if ( 'on' === $featured_image && 'background' === $featured_placement && '' !== $featured_image_src ) {
$background_image = $featured_image_src;
// C.1. Parallax BG Class to inform if other modes exist.
$parallax_classname = array();
if ( ( '_tablet' === $suffix || '' === $suffix ) && in_array( '_phone', $parallax_processed ) ) {
$parallax_classname[] = 'et_parallax_bg_phone_exist';
if ( '' === $suffix && in_array( '_tablet', $parallax_processed ) ) {
$parallax_classname[] = 'et_parallax_bg_tablet_exist';
if ( in_array( $hover_suffix, $parallax_processed ) ) {
$parallax_classname[] = 'et_parallax_bg_hover_exist';
// C.2. Set up parallax class and wrapper.
if ( '' !== $background_image && 'on' === $parallax ) {
$parallax_classname[] = 'et_parallax_bg';
if ( 'off' === $parallax_method ) {
$parallax_classname[] = 'et_pb_parallax_css';
// Parallax BG Class with suffix.
$parallax_classname[] = "et_parallax_bg{$suffix}";
$parallax_background .= sprintf(
'<span class="et_parallax_bg_wrap"><span
style="background-image: url(%2$s);"
esc_attr( implode( ' ', $parallax_classname ) ),
esc_url( $background_image )
// set `.et_parallax_bg_wrap` border-radius.
et_set_parallax_bg_wrap_border_radius( $this->props, $this->slug, $this->main_css_element );
// C.3. Hover parallax class.
if ( '' !== $background_image && $is_hover ) {
$this->add_classname( 'et_pb_section_parallax_hover' );
array_push( $parallax_processed, $suffix );
// Added classname for module wrapper