: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
foreach ( $values_array as $device => $declaration ) {
if ( empty( $declaration ) ) {
'selector' => $css_selector,
'declaration' => $declaration,
if ( 'desktop_only' === $device ) {
$style['media_query'] = ET_Builder_Element::get_media_query( 'min_width_981' );
} elseif ( 'desktop' !== $device ) {
$current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767';
$style['media_query'] = ET_Builder_Element::get_media_query( $current_media_query );
if ( '' !== $priority ) {
$style['priority'] = $priority;
ET_Builder_Element::set_style( $function_name, $style );
* Generate additional responsive fields such as _tablet, _phone, and _last_edited.
* @param string $field_name Base field name.
* @param string $toggle_slug Toggle slug name.
* @param string $tab_slug Tab slug name.
* @param array $field Field data in array.
* @return array Responsive fields set.
public function generate_responsive_fields( $field_name, $toggle_slug, $tab_slug, $field = array() ) {
$responsive_options = array();
// Add fields with responsive suffix for each devices.
$responsive_options["{$field_name}_tablet"] = array(
'toggle_slug' => $toggle_slug,
$responsive_options["{$field_name}_phone"] = array(
'toggle_slug' => $toggle_slug,
$responsive_options["{$field_name}_last_edited"] = array(
'toggle_slug' => $toggle_slug,
// Add computed effect field on mobile and hover fields.
if ( ! empty( $field['computed_affects'] ) && isset( $field['affects_mobile'] ) && true === $field['affects_mobile'] ) {
$responsive_options["{$field_name}_tablet"]['computed_affects'] = $field['computed_affects'];
$responsive_options["{$field_name}_phone"]['computed_affects'] = $field['computed_affects'];
$responsive_options["{$field_name}__hover"] = array(
'toggle_slug' => $toggle_slug,
'computed_affects' => $field['computed_affects'],
// Set default on tablet and phone if needed.
if ( ! empty( $field['default_on_mobile'] ) ) {
$default = ! empty( $field['default'] ) ? $field['default'] : '';
$default_mobile = ! empty( $field['default_on_mobile'] ) ? $field['default_on_mobile'] : $default;
$default_tablet = ! empty( $field['default_on_tablet'] ) ? $field['default_on_tablet'] : $default_mobile;
$default_phone = ! empty( $field['default_on_phone'] ) ? $field['default_on_phone'] : $default_mobile;
$responsive_options["{$field_name}_tablet"]['default'] = $default_tablet;
$responsive_options["{$field_name}_phone"]['default'] = $default_phone;
// Set default on hover if needed.
if ( ! empty( $field['default_on_hover'] ) ) {
$default = ! empty( $field['default'] ) ? $field['default'] : '';
$default_hover = ! empty( $field['default_on_hover'] ) ? $field['default_on_hover'] : $default_mobile;
$responsive_options["{$field_name}__hover"]['default'] = $default_hover;
return $responsive_options;
* Get main background value based on enabled status of current field. It's used to selectively
* get the correct color, gradient status, image, and video. It's introduced along with new
* enable fields to decide should we remove or inherit the value from larger device.
* @param array $attrs All module attributes.
* @param string $base_setting Setting need to be checked.
* @param string $preview_mode Current preview mode.
* @param string $background_base Background base name (background, button_bg, etc.)
* @param array $fields All module fields definition.
* @param string $value Active value.
* @param string $default_value Active default value.
* @return string New value.
public function get_inheritance_background_value( $attrs, $base_setting, $preview_mode, $background_base = 'background', $fields = array(), $value = '', $default_value = '') {
// Default new value is same with the generated or active one.
"{$background_base}_color" => "{$background_base}_enable_color",
"use_background_color_gradient" => "use_background_color_gradient",
"{$background_base}_use_color_gradient" => "{$background_base}_enable_use_color_gradient",
"{$background_base}_image" => "{$background_base}_enable_image",
"video_{$background_base}_values" => "video_{$background_base}_values",
// Empty string is slug for desktop.
'desktop' => array( '' ),
'hover' => array( '__hover', '' ),
'tablet' => array( '_tablet', '' ),
'phone' => array( '_phone', '_tablet', '' ),
// Start checking if current field is enabled or disabled.
$base_enable_field_name = et_()->array_get( $enable_fields, $base_setting, '' );
// Bail early if setting name is different.
if ( '' === $base_enable_field_name || ! isset( $map_slugs[ $preview_mode ] ) ) {
$origin_mp4_enabled = '';
$origin_mp4_data = array();
$origin_webm_enabled = '';
$origin_webm_data = array();
foreach( $map_slugs[ $preview_mode ] as $slug ) {
if ( in_array( $base_setting, array( "{$background_base}_color", "{$background_base}_image" ) ) ) {
$base_type = str_replace( "{$background_base}_", '', $base_setting );
$enable_default = et_()->array_get( $fields, "{$background_base}_enable_{$base_type}{$slug}.default", '' );
$enable_value = et_()->array_get( $attrs, "{$background_base}_enable_{$base_type}{$slug}", $enable_default );
$bg_value = et_()->array_get( $attrs, "{$background_base}_{$base_type}{$slug}", '' );
$is_bg_enabled = 'off' !== $enable_value;
if ( '' !== $bg_value && $is_bg_enabled ) {
} else if ( ! $is_bg_enabled ) {
} else if ( in_array( $base_setting, array( 'use_background_color_gradient', "{$background_base}_use_color_gradient" ) ) ) {
'use_background_color_gradient' => array(
'value' => "use_background_color_gradient{$slug}",
'start' => "{$background_base}_color_gradient_start{$slug}",
'end' => "{$background_base}_color_gradient_end{$slug}",
"{$background_base}_use_color_gradient" => array(
'value' => "{$background_base}_use_color_gradient{$slug}",
'start' => "{$background_base}_color_gradient_start{$slug}",
'end' => "{$background_base}_color_gradient_end{$slug}",
$field_value = et_()->array_get( $field_map, "{$base_setting}.value", '' );
$field_start = et_()->array_get( $field_map, "{$base_setting}.start", '' );
$field_end = et_()->array_get( $field_map, "{$base_setting}.end", '' );
$use_gradient_default = et_()->array_get( $fields, $field_value, '' );
$use_gradient_value = et_()->array_get( $attrs, $field_value, $use_gradient_default );
$gradient_start_value = et_()->array_get( $attrs, $field_start, '' );
$gradient_end_value = et_()->array_get( $attrs, $field_end, '' );
$is_gradient_enabled = 'off' !== $use_gradient_value;
if ( ( '' !== $gradient_start_value || '' !== $gradient_end_value ) && $is_gradient_enabled ) {
} else if ( ! $is_gradient_enabled ) {
} else if ( "video_{$background_base}_values" === $base_setting ) {
$base_slug = preg_replace('/[_]+/', '', $slug);
$current_mode = '' !== $base_slug ? $base_slug : 'desktop';
$video_background = et_()->array_get( $attrs, "{$base_setting}.{$current_mode}", '' );
$enable_mp4_default = et_()->array_get( $fields, "{$background_base}_enable_video_mp4{$slug}", '' );
$enable_mp4_value = $this->get_any_value( $attrs, "{$background_base}_enable_video_mp4{$slug}", $enable_mp4_default, true );
$is_mp4_enabled = 'off' !== $enable_mp4_value;
$video_mp4_value = et_pb_responsive_options()->get_any_value( $attrs, "{$background_base}_video_mp4" );
if ( 'hover' === $current_mode ) {
$video_mp4_hover_value = et_()->array_get( $attrs, "{$background_base}_video_mp4__hover", '' );
$video_mp4_value = '' !== $video_mp4_hover_value ? $video_mp4_hover_value : $video_mp4_value;
$video_mp4_value = et_pb_responsive_options()->get_any_value( $attrs, "{$background_base}_video_mp4{$slug}", '', true );
// Check MP4 enabled and data status.
if ( '' === $origin_mp4_enabled ) {
if ( '' !== $video_mp4_value && $is_mp4_enabled ) {
$origin_mp4_enabled = 'enabled';
$origin_mp4_data = array(
'video_value' => $video_mp4_value,
'video_background' => $video_background,
'display' => ! empty( $video_background ) ? 'self' : 'inherit',
} else if ( false === $is_mp4_enabled ) {
$origin_mp4_enabled = 'disabled';
$origin_mp4_data = array();
} else if ( 'enabled' === $origin_mp4_enabled ) {
if ( isset( $origin_mp4_data['video_background'] ) && empty( $origin_mp4_data['video_background'] ) ) {
$origin_mp4_data['video_background'] = $video_background;
$enable_webm_default = et_()->array_get( $fields, "{$background_base}_enable_video_webm{$slug}", '' );
$enable_webm_value = $this->get_any_value( $attrs, "{$background_base}_enable_video_webm{$slug}", $enable_webm_default, true );
$is_webm_enabled = 'off' !== $enable_webm_value;
$video_webm_value = et_pb_responsive_options()->get_any_value( $attrs, "{$background_base}_video_webm" );
if ( 'hover' === $current_mode ) {
$video_webm_hover_value = et_()->array_get( $attrs, "{$background_base}_video_webm__hover", '' );
$video_webm_value = '' !== $video_webm_hover_value ? $video_webm_hover_value : $enable_webm_value;
$video_webm_value = et_pb_responsive_options()->get_any_value( $attrs, "{$background_base}_video_webm{$slug}", '', true );
// Check Webm enabled and data status.
if ( '' === $origin_webm_enabled ) {
if ( '' !== $video_webm_value && $is_webm_enabled ) {
$origin_webm_enabled = 'enabled';
$origin_webm_data = array(
'video_value' => $video_webm_value,
'video_background' => $video_background,
'display' => ! empty( $video_background ) ? 'self' : 'inherit',
} else if ( ! $is_webm_enabled ) {
$origin_webm_enabled = 'disabled';
$origin_webm_data = array();
} else if ( 'enabled' === $origin_webm_enabled ) {
if ( isset( $origin_webm_data['video_background'] ) && empty( $origin_webm_data['video_background'] ) ) {
$origin_webm_data['video_background'] = $video_background;
// Continue if current mode is not desktop.
// Decide to display the video or not.
if ( 'disabled' === $origin_mp4_enabled && 'disabled' === $origin_webm_enabled ) {
// MP4 display and video status.
$mp4_enabled_display = et_()->array_get( $origin_mp4_data, 'display', '' );
$mp4_enabled_mode = et_()->array_get( $origin_mp4_data, 'mode', '' );
$mp4_video_background = '';
if ( $preview_mode === $mp4_enabled_mode ) {
$mp4_video_background = et_()->array_get( $origin_mp4_data, 'video_background', '' );
// Webm display and video status.
$webm_enabled_display = et_()->array_get( $origin_webm_data, 'display', '' );
$webm_enabled_mode = et_()->array_get( $origin_webm_data, 'mode', '' );
$webm_video_background = '';
if ( $preview_mode === $webm_enabled_mode ) {
$webm_video_background = et_()->array_get( $origin_webm_data, 'video_background', '' );
// Set display current video or not.
$new_video_display = 'hide';
if ( '' !== $mp4_enabled_display ) {
$new_video_display = $mp4_enabled_display;
} else if ( '' !== $webm_enabled_display ) {
$new_video_display = $webm_enabled_display;
$new_video_background = '';
if ( '' !== $mp4_video_background ) {
$new_video_background = $mp4_video_background;
} else if ( '' !== $webm_video_background ) {
$new_video_background = $webm_video_background;
'display' => $new_video_display,
'video' => $new_video_background,
public function create( $additional_options ) {
// Add hover field indication
$additional_options['hover_enabled'] = array(
// Generate responsive fields for additional options (Design).
// There are 4 types where the mobile_options exist on the options.
// 1. Exist on the option definition.
// 2. Exist on the computed field type, just like point 1 but we threat it differently
// because there are some properties need to be updated and added.
// 3. Exist on the background-field.
// 4. Exist on the composite field.
foreach ( $additional_options as $field_name => $field ) {
$is_mobile_options = isset( $field['mobile_options'] ) && $field['mobile_options'];
$is_hover = isset( $field['hover'] ) && 'tabs' === $field['hover'];
$field_type = isset( $field['type'] ) ? $field['type'] : '';
$field_context = isset( $field['context'] ) ? $field['context'] : '';
$field_last_edited = isset( $field['last_edited'] ) ? $field['last_edited'] : '';
// Mobile options property maybe exist on the field.
if ( $is_mobile_options ) {
// Get tab and toggle slugs value.
$tab_slug = isset( $field['tab_slug'] ) ? $field['tab_slug'] : '';
$toggle_slug = isset( $field['toggle_slug'] ) ? $field['toggle_slug'] : '';
// 2. Mobile options property for computed fields.
if ( 'computed' === $field_type ) {
// Computed depends on. Add suffix after depends on info.
if ( ! empty( $field['computed_depends_on'] ) ) {
$computed_depends_on = $field['computed_depends_on'];
foreach ( $computed_depends_on as $depends_value ) {
array_push( $field['computed_depends_on'], "{$depends_value}_tablet", "{$depends_value}_phone", "{$depends_value}__hover" );
array_push( $field['computed_depends_on'], "{$depends_value}_tablet", "{$depends_value}_phone" );
// Computed minimum. Add suffix after minimum info.
if ( ! empty( $field['computed_minimum'] ) ) {
$computed_minimum = $field['computed_minimum'];
foreach ( $computed_minimum as $minimum_value ) {
array_push( $field['computed_minimum'], "{$minimum_value}_tablet", "{$minimum_value}_phone", "{$minimum_value}__hover" );
array_push( $field['computed_minimum'], "{$minimum_value}_tablet", "{$minimum_value}_phone" );
$additional_options["{$field_name}"] = $field;
// 3. Mobile options property maybe exist under background field.
if ( 'background-field' === $field_type ) {
// Just in case current field is background-field and the mobile_options
// attributes are located in the fields. Ensure background fields is exist.
if ( ! empty( $field['background_fields'] ) ) {
// Fetch the fields and check for mobile_options.
foreach ( $field['background_fields'] as $background_name => $background_field ) {
if ( isset( $background_field['mobile_options'] ) && $background_field['mobile_options'] ) {
// Get tab and toggle slugs value.
$tab_slug = isset( $background_field['tab_slug'] ) ? $background_field['tab_slug'] : '';
$toggle_slug = isset( $background_field['toggle_slug'] ) ? $background_field['toggle_slug'] : '';
// Add fields with responsive suffix for each devices.
$additional_options = array_merge(
et_pb_responsive_options()->generate_responsive_fields( $background_name, $toggle_slug, $tab_slug )
// 1. Mobile options property added directly on options definition. Add fields
// with responsive suffix for each devices.
$additional_options = array_merge(
et_pb_responsive_options()->generate_responsive_fields( $field_name, $toggle_slug, $tab_slug, $field )
// Additional last edited field just in case we need more last edited field.
if ( ! empty( $field_last_edited ) ) {
$additional_options["{$field_last_edited}_last_edited"] = array(
'toggle_slug' => $toggle_slug,
// 4. Mobile options property maybe exist under composite field.
if ( 'composite' === $field_type ) {
// Just in case current field is composite and the mobile_options attributes
// are located in the controls. Ensure composite structure is exist.
$composite_structure = isset( $field['composite_structure'] ) ? $field['composite_structure'] : array();
if ( empty( $composite_structure ) ) {
foreach ( $composite_structure as $composite_field ) {
// Ensure composite field controls is exist and not empty.
$composite_field_controls = isset( $composite_field['controls'] ) ? $composite_field['controls'] : array();
if ( empty( $composite_field_controls ) ) {
// Fetch the controls and check for mobile_options.
foreach ( $composite_field_controls as $control_name => $control ) {
if ( isset( $control['mobile_options'] ) && $control['mobile_options'] ) {
// Get tab and toggle slugs value.
$tab_slug = isset( $control['tab_slug'] ) ? $control['tab_slug'] : '';
$toggle_slug = isset( $control['toggle_slug'] ) ? $control['toggle_slug'] : '';
// Add fields with responsive suffix for each devices.
$additional_options = array_merge(
et_pb_responsive_options()->generate_responsive_fields( $control_name, $toggle_slug, $tab_slug )
return $additional_options;