: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( ! empty( $meta_key ) ) {
$content = get_post_meta( $post_id, $meta_key, true );
$enable_html = $_->array_get( $settings, 'enable_html' );
if ( 'on' !== $enable_html ) {
$content = esc_html( $content );
// Handle in post type URL options.
$post_types = et_builder_get_public_post_types();
foreach ( $post_types as $public_post_type ) {
$key = 'post_link_url_' . $public_post_type->name;
$selected_post_id = $_->array_get( $settings, 'post_id', $def( $post_id, $name, 'post_id' ) );
$content = esc_url( get_permalink( $selected_post_id ) );
// Wrap non plain text woo data to add custom selector for styling inheritance.
// It works by checking is the content has HTML tag.
if ( $is_woo && $content && preg_match( '/<\s?[^\>]*\/?\s?>/i', $content ) ) {
$content = sprintf( '<div class="woocommerce et-dynamic-content-woo et-dynamic-content-woo--%2$s">%1$s</div>', $content, $name );
$content = et_builder_wrap_dynamic_content( $post_id, $name, $content, $settings );
add_filter( 'et_builder_resolve_dynamic_content', 'et_builder_filter_resolve_default_dynamic_content', 10, 6 );
* Resolve custom field dynamic content fields.
* @param integer $post_id
function et_builder_filter_resolve_custom_field_dynamic_content( $content, $name, $settings, $post_id, $context, $overrides ) {
$post = get_post( $post_id );
$fields = et_builder_get_dynamic_content_fields( $post_id, $context );
if ( empty( $fields[ $name ]['meta_key'] ) ) {
if ( 'edit' === $context && ! et_pb_is_allowed( 'read_dynamic_content_custom_fields' ) ) {
if ( 'text' === $fields[ $name ]['type'] ) {
return esc_html__( 'You don\'t have sufficient permissions to access this content.', 'et_builder' );
$_ = ET_Core_Data_Utils::instance();
$def = 'et_builder_get_dynamic_attribute_field_default';
$enable_html = $_->array_get( $settings, 'enable_html', $def( $post_id, $name, 'enable_html' ) );
$content = get_post_meta( $post_id, $fields[ $name ]['meta_key'], true );
* Provide a hook for third party compatibility purposes of formatting meta values.
* @param string $meta_value
* @param string $meta_key
* @param integer $post_id
$content = apply_filters( 'et_builder_dynamic_content_meta_value', $content, $fields[ $name ]['meta_key'], $post_id );
// Sanitize HTML contents.
$content = wp_kses_post( $content );
if ( 'on' !== $enable_html ) {
$content = esc_html( $content );
$content = et_builder_wrap_dynamic_content( $post_id, $name, $content, $settings );
add_filter( 'et_builder_resolve_dynamic_content', 'et_builder_filter_resolve_custom_field_dynamic_content', 10, 6 );
* Resolve a dynamic group post content field for use during editing.
* @param integer $post_id
* @param array $overrides
* @param boolean $is_content
function et_builder_filter_resolve_dynamic_post_content_field( $field, $settings, $post_id, $overrides = array(), $is_content = false ) {
return et_builder_resolve_dynamic_content( $field, $settings, $post_id, 'edit', $overrides, $is_content );
add_action( 'et_builder_resolve_dynamic_post_content_field', 'et_builder_filter_resolve_dynamic_post_content_field', 10, 5 );
* Clean potential dynamic content from filter artifacts.
function et_builder_clean_dynamic_content( $value ) {
// Strip wrapping <p></p> tag as it appears in shortcode content in certain cases (e.g. BB preview).
$value = preg_replace( '/^<p>(.*)<\/p>$/i', '$1', trim( $value ) );
* Parse a JSON-encoded string into an ET_Builder_Value instance or null on failure.
* @return ET_Builder_Value|null
function et_builder_parse_dynamic_content_json( $json ) {
$post_types = array_keys( et_builder_get_public_post_types() );
$dynamic_content = json_decode( $json, true );
$is_dynamic_content = is_array( $dynamic_content ) && isset( $dynamic_content['dynamic'] ) && (bool) $dynamic_content['dynamic'];
$has_content = is_array( $dynamic_content ) && isset( $dynamic_content['content'] ) && is_string( $dynamic_content['content'] );
$has_settings = is_array( $dynamic_content ) && isset( $dynamic_content['settings'] ) && is_array( $dynamic_content['settings'] );
$has_category_type = is_array( $dynamic_content ) && isset( $dynamic_content['settings'] ) && isset( $dynamic_content['settings']['category_type'] );
// When adding a section from library get_post_type() will not work, and post type has to be fetched from $_POST
$is_added_from_library = isset( $_POST['et_post_type'] );
if ( ! $is_dynamic_content || ! $has_content || ! $has_settings ) {
// Replaces layout_category with proper category_type depending on the post type on which the layout is added
if ( $has_category_type && 'post_categories' === $dynamic_content['content'] && ! 0 === substr_compare( $dynamic_content['settings']['category_type'], "_tag", - 4 ) ) {
if ( $is_added_from_library ) {
$correct_post_type = sanitize_text_field( $_POST['et_post_type'] );
$correct_post_type = in_array( $correct_post_type, $post_types ) ? $correct_post_type : 'post';
$correct_post_type = get_post_type();
$correct_post_type = in_array( $correct_post_type, $post_types ) ? $correct_post_type : 'post';
if ( 'post' === $correct_post_type ) {
$dynamic_content['settings']['category_type'] = 'category';
$dynamic_content['settings']['category_type'] = $correct_post_type . '_category';
return new ET_Builder_Value(
(bool) $dynamic_content['dynamic'],
sanitize_text_field( $dynamic_content['content'] ),
array_map( 'wp_kses_post', $dynamic_content['settings'] )
* Convert a value to an ET_Builder_Value representation.
* @return ET_Builder_Value
function et_builder_parse_dynamic_content( $content ) {
$json = et_builder_clean_dynamic_content( $content );
$json = preg_replace( '/^@ET-DC@(.*?)@$/', '$1', $json );
$dynamic_content = et_builder_parse_dynamic_content_json( $json );
if ( null === $dynamic_content ) {
$json = base64_decode( $json );
$dynamic_content = et_builder_parse_dynamic_content_json( $json );
if ( null === $dynamic_content ) {
return new ET_Builder_Value( false, wp_kses_post( $content ), array() );
* Serialize dynamic content.
* @param mixed[] $settings
function et_builder_serialize_dynamic_content( $dynamic, $content, $settings ) {
// JSON_UNESCAPED_SLASHES is only supported from 5.4.
$options = defined( 'JSON_UNESCAPED_SLASHES' ) ? JSON_UNESCAPED_SLASHES : 0;
$result = wp_json_encode( array(
// Force object type for keyed arrays as empty arrays will be encoded to
// javascript arrays instead of empty objects.
'settings' => (object) $settings,
// Use fallback if needed
$result = 0 === $options ? str_replace( '\/', '/', $result ) : $result;
return '@ET-DC@' . base64_encode( $result ) . '@';
function et_builder_strip_dynamic_content( $content ) {
return preg_replace( '/@ET-DC@(.*?)@/', '', $content );
* Reencode legacy dynamic content in post excerpts.
* @param string $post_excerpt
* @param integer $post_id
function et_builder_reencode_legacy_dynamic_content_in_excerpt( $post_excerpt, $post_id ) {
(?: # non-capturing group
[^{}] # anything that is not a { or }
(?R) # recurse the entire pattern
)* # previous group zero or more times
return preg_replace_callback( $json, 'et_builder_reencode_legacy_dynamic_content_in_excerpt_callback', $post_excerpt );
add_filter( 'et_truncate_post', 'et_builder_reencode_legacy_dynamic_content_in_excerpt', 10, 2 );
* Callback to reencode legacy dynamic content for preg_replace_callback.
function et_builder_reencode_legacy_dynamic_content_in_excerpt_callback( $matches ) {
$value = et_builder_parse_dynamic_content_json( $matches[0] );
return null === $value ? $matches[0] : $value->serialize();
* Resolve dynamic content in post excerpts instead of showing raw JSON.
* @param string $post_excerpt
* @param integer $post_id
function et_builder_resolve_dynamic_content_in_excerpt( $post_excerpt, $post_id ) {
// Use an obscure acronym named global variable instead of an anonymous function as we are
global $_et_brdcie_post_id;
$_et_brdcie_post_id = $post_id;
$post_excerpt = preg_replace_callback( '/@ET-DC@.*?@/', 'et_builder_resolve_dynamic_content_in_excerpt_callback', $post_excerpt );
add_filter( 'et_truncate_post', 'et_builder_resolve_dynamic_content_in_excerpt', 10, 2 );
* Callback to resolve dynamic content for preg_replace_callback.
function et_builder_resolve_dynamic_content_in_excerpt_callback( $matches ) {
global $_et_brdcie_post_id;
return et_builder_parse_dynamic_content( $matches[0] )->resolve( $_et_brdcie_post_id );