: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( ! is_wp_error( $value ) ) {
// Update the multi content data.
$data['desktop'] = $value;
* Populate attrs data context.
* @param array $attrs Data contexts.
protected function populate_data__attrs( $attrs ) {
if ( ! $attrs || ! is_array( $attrs ) ) {
foreach ( $attrs as $attr_key => $attr_value ) {
if ( preg_match_all( $this->pattern, $attr_value, $matches, PREG_SET_ORDER, 0 ) ) {
foreach ( $matches as $match ) {
if ( ! isset( $match[1] ) ) {
$values = $this->get_values( $match[1] );
foreach ( $values as $mode => $value ) {
// Manipulate the value if needed.
$value = $this->filter_value(
if ( ! is_wp_error( $value ) ) {
$value = et_core_esc_attr( $attr_key, $value );
if ( ! is_wp_error( $value ) ) {
if ( ! isset( $data[ $mode ][ $attr_key ] ) ) {
$data[ $mode ][ $attr_key ] = $attr_value;
$data[ $mode ][ $attr_key ] = str_replace( $match[0], $value, $data[ $mode ][ $attr_key ] );
// Manipulate the value if needed.
$attr_value = $this->filter_value(
if ( ! is_wp_error( $attr_value ) ) {
$attr_value = et_core_esc_attr( $attr_key, $attr_value );
if ( ! is_wp_error( $attr_value ) ) {
// Update the multi content data.
$data['desktop'][ $attr_key ] = $attr_value;
* Populate styles data context.
* @param array $styles Data contexts.
protected function populate_data__styles( $styles ) {
if ( ! $styles || ! is_array( $styles ) ) {
foreach ( $styles as $style_key => $style_value ) {
if ( preg_match_all( $this->pattern, $style_value, $matches, PREG_SET_ORDER, 0 ) ) {
foreach ( $matches as $match ) {
if ( ! isset( $match[1] ) ) {
$values = $this->get_values( $match[1] );
foreach ( $values as $mode => $value ) {
// Manipulate the value if needed.
$value = $this->filter_value(
'style_key' => $style_key,
if ( ! is_wp_error( $value ) ) {
if ( ! isset( $data[ $mode ][ $style_key ] ) ) {
$data[ $mode ][ $style_key ] = $style_value;
$full_style_value = str_replace( $match[0], $value, $data[ $mode ][ $style_key ] );
if ( ! is_wp_error( et_core_esc_attr( 'style', $style_key . ':' . $full_style_value ) ) ) {
$data[ $mode ][ $style_key ] = $full_style_value;
// Manipulate the value if needed.
$style_value = $this->filter_value(
'style_key' => $style_key,
if ( ! is_wp_error( $style_value ) && ! is_wp_error( et_core_esc_attr( 'style', $style_key . ':' . $style_value ) ) ) {
$data['desktop'][ $style_key ] = $style_value;
* Populate classes data context.
* @param array $classes Data contexts.
protected function populate_data__classes( $classes ) {
if ( ! $classes || ! is_array( $classes ) ) {
foreach ( self::get_modes() as $mode ) {
foreach ( $classes as $class_name => $conditionals ) {
$class_name = et_core_esc_attr( 'class', $class_name );
if ( is_wp_error( $class_name ) ) {
$conditionals_match = array();
foreach ( $conditionals as $name => $value_compare ) {
$value = $this->get_inherit_value( $name, $mode );
// Manipulate the value if needed.
$value = $this->filter_value(
if ( ! is_wp_error( $value ) ) {
$conditionals_match[ $name ] = self::compare_value( $value, $value_compare ) ? 1 : 0;
$action = count( $conditionals ) === array_sum( $conditionals_match ) ? 'add' : 'remove';
if ( ! isset( $data[ $mode ][ $action ] ) ) {
$data[ $mode ][ $action ] = array();
$data[ $mode ][ $action ][] = $class_name;
* Populate visibility data context.
* @param array $visibility Data contexts.
protected function populate_data__visibility( $visibility ) {
if ( ! $visibility || ! is_array( $visibility ) ) {
foreach ( self::get_modes() as $mode ) {
if ( ! isset( $data[ $mode ] ) ) {
$data[ $mode ] = array();
foreach ( $visibility as $name => $value_compare ) {
$value = $this->get_inherit_value( $name, $mode );
// Manipulate the value if needed.
$value = $this->filter_value(
'context' => 'visibility',
if ( ! is_wp_error( $value ) ) {
$data[ $mode ][ $name ] = self::compare_value( $value, $value_compare ) ? 1 : 0;
foreach ( $data as $mode => $value ) {
$data[ $mode ] = count( $value ) === array_sum( $value );
* @param mixed $raw_value Props raw value.
* @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 available when passing attrs value as array such as styes. Example: padding-top, margin-bottom, etc.
* @return mixed|WP_Error return WP_Error to skip the data.
protected function filter_value( $raw_value, $args = array() ) {
if ( $this->module instanceof ET_Builder_Element && method_exists( $this->module, 'multi_view_filter_value' ) && is_callable( array( $this->module, 'multi_view_filter_value' ) ) ) {
* Execute the filter value function defined for current module.
* @param mixed $raw_value Props raw value.
* @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 available when passing attrs value as array such as styes. Example: padding-top, margin-bottom, etc.
* @param ET_Builder_Module_Helper_MultiViewOptions $multi_view Current instance.
// @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
$raw_value = call_user_func( array( $this->module, 'multi_view_filter_value' ), $raw_value, $args, $this );
// Bail early if the $raw_value is WP_error object.
if ( is_wp_error( $raw_value ) ) {
$context = isset( $args['context'] ) ? $args['context'] : '';
$name = isset( $args['name'] ) ? $args['name'] : '';
$mode = isset( $args['mode'] ) ? $args['mode'] : 'desktop';
if ( $raw_value && 'content' === $context && 'desktop' !== $mode && in_array( $name, $content_fields, true ) ) {
$raw_value = str_replace( array( '%22', '%92', '%91', '%93' ), array( '"', '\\', '[', ']' ), $raw_value );
// Cleaning up invalid starting <\p> tag.
$cleaned_value = preg_replace( '/(^<\/p>)(.*)/ius', '$2', $raw_value );
// Cleaning up invalid ending <p> tag.
$cleaned_value = preg_replace( '/(.*)(<p>$)/ius', '$1', $cleaned_value );
// Override the raw value.
if ( $raw_value !== $cleaned_value ) {
$raw_value = trim( $cleaned_value, "\n" );
if ( 'raw_content' !== $name ) {
$raw_value = force_balance_tags( $raw_value );
// Try to process shortcode.
if ( false !== strpos( $raw_value, '[' ) && false !== strpos( $raw_value, ']' ) ) {
$raw_value = do_shortcode( et_pb_fix_shortcodes( str_replace( array( '[', ']' ), array( '[', ']' ), $raw_value ), true ) );
* Filter populated multi view data
* The use case of this method is to manipulate populated data such as injecting srcset attributes.
* @param array $data All populated raw data. The value value passed to this method has been processed by filter_value method.
protected function filter_data( $data ) {
static $defaults = array( false, false, false, false );
// Inject the image srcset and sizes attributes data.
if ( ! empty( $data['attrs'] ) && et_is_responsive_images_enabled() ) {
foreach ( $data['attrs'] as $mode => $attrs ) {
// Skip if src attr is empty.
if ( ! isset( $attrs['src'] ) ) {
$srcset_sizes = et_get_image_srcset_sizes( $attrs['src'] );
if ( isset( $srcset_sizes['srcset'], $srcset_sizes['sizes'] ) && $srcset_sizes['srcset'] && $srcset_sizes['sizes'] ) {
$data['attrs'][ $mode ]['srcset'] = $srcset_sizes['srcset'];
$data['attrs'][ $mode ]['sizes'] = $srcset_sizes['sizes'];
unset( $data['attrs'][ $mode ]['srcset'] );
unset( $data['attrs'][ $mode ]['sizes'] );
if ( $this->module instanceof ET_Builder_Element && method_exists( $this->module, 'multi_view_filter_data' ) && is_callable( array( $this->module, 'multi_view_filter_data' ) ) ) {
* Execute the filter data function defined for current module.
* @param mixed $data All populated raw data.
* @param ET_Builder_Module_Helper_MultiViewOptions $multi_view Current instance.
// @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
$data = call_user_func( array( $this->module, 'multi_view_filter_data' ), $data, $this );
* Normalize values to inject value for all modes
* @param array $values Raw values.
* @return array Normalized values for all modes.
protected function normalize_values( $values = array() ) {
if ( is_array( $values ) ) {
if ( ! isset( $values['desktop'] ) ) {
if ( ! isset( $values['tablet'] ) ) {
$values['tablet'] = isset( $values['desktop'] ) ? $values['desktop'] : '';
if ( ! isset( $values['phone'] ) ) {
$values['phone'] = isset( $values['tablet'] ) ? $values['tablet'] : ( isset( $values['desktop'] ) ? $values['desktop'] : '' );
if ( ! isset( $values['hover'] ) ) {
$values['hover'] = isset( $values['desktop'] ) ? $values['desktop'] : '';
foreach ( self::get_modes() as $mode ) {
if ( ! isset( $values[ $mode ] ) ) {
$normalized[ $mode ] = $values[ $mode ];
foreach ( self::get_modes() as $mode ) {
$normalized[ $mode ] = $values;
* @param array $values Raw values.
* @return array Filtered out for mode that has duplicate values.
public function distinct_values( $values ) {
foreach ( $values as $mode => $value ) {
// Stringify the value so can be easily compared.
$temp_values[ $mode ] = wp_json_encode( $value );
// Unset hover mode if same with desktop mode.
if ( isset( $temp_values['desktop'], $temp_values['hover'] ) && $temp_values['desktop'] === $temp_values['hover'] ) {
unset( $temp_values['hover'] );
// Unset tablet mode if same with desktop mode.
if ( isset( $temp_values['desktop'], $temp_values['tablet'] ) && $temp_values['desktop'] === $temp_values['tablet'] ) {
unset( $temp_values['tablet'] );
// Unset phone mode if same with tablet mode.
if ( isset( $temp_values['tablet'], $temp_values['phone'] ) && $temp_values['tablet'] === $temp_values['phone'] ) {
unset( $temp_values['phone'] );
// Unset phone mode if same with desktop mode but no tablet mode defined.
if ( isset( $temp_values['desktop'], $temp_values['phone'] ) && ! isset( $temp_values['tablet'] ) && $temp_values['desktop'] === $temp_values['phone'] ) {
unset( $temp_values['phone'] );
$filtered_values = array();
foreach ( self::get_modes() as $mode ) {
if ( ! isset( $temp_values[ $mode ] ) ) {
if ( ! isset( $values[ $mode ] ) ) {
$filtered_values[ $mode ] = $values[ $mode ];