: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Prints hidden inputs for passing global modules data to database
function et_pb_builder_global_library_inputs( $post_id ) {
if ( 'et_pb_layout' !== $typenow ) {
$template_scope = wp_get_object_terms( get_the_ID(), 'scope' );
$template_type = wp_get_object_terms( get_the_ID(), 'layout_type' );
$is_global_template = ! empty( $template_scope[0] ) ? $template_scope[0]->slug : 'regular';
$template_type_slug = ! empty( $template_type[0] ) ? $template_type[0]->slug : '';
if ( 'global' !== $is_global_template || 'module' !== $template_type_slug ) {
$excluded_global_options = get_post_meta( $post_id, '_et_pb_excluded_global_options' );
'<input type="hidden" id="et_pb_unsynced_global_attrs" name="et_pb_unsynced_global_attrs" value="%1$s" />',
isset( $excluded_global_options[0] ) ? esc_attr( $excluded_global_options[0] ) : json_encode( array() )
* Returns array of default builder settings configuration item
function et_pb_get_builder_settings_configuration_default() {
'depends_show_if' => false,
function et_builder_update_settings( $settings, $post_id = 'global' ) {
et_core_nonce_verified_previously();
$is_global = 'global' === $post_id;
$is_BB = null === $settings;
$settings = $is_BB ? $_POST : $settings;
$fields = $is_global ? ET_Builder_Settings::get_fields( 'builder' ) : ET_Builder_Settings::get_fields();
$utils = ET_Core_Data_Utils::instance();
foreach ( (array) $settings as $setting_key => $setting_value ) {
$raw_setting_value = $setting_value;
$setting_key = $is_BB ? substr( $setting_key, 1 ) : $setting_key;
if ( ! isset( $fields[ $setting_key ] ) || ! isset( $fields[ $setting_key ]['type'] ) ) {
// Auto-formatting subjects' value format
if ( 'et_pb_ab_subjects' === $setting_key && is_array( $setting_value ) ) {
$setting_value = implode(',', $setting_value );
// TODO Possibly move sanitization.php to builder dir
switch ( $fields[ $setting_key ]['type'] ) {
$palette_colors = explode('|', $setting_value);
$setting_value = implode('|', array_map('et_sanitize_alpha_color', $palette_colors ) );
// Avoid setting absolute value for range if option is z_index.
if ( 'et_pb_page_z_index' == $setting_key ) {
$setting_value = absint( $setting_value );
$range_min = isset( $fields[ $setting_key ]['range_settings'] ) && isset( $fields[ $setting_key ]['range_settings']['min'] ) ?
absint( $fields[ $setting_key ]['range_settings']['min'] ) : -1;
$range_max = isset( $fields[ $setting_key ]['range_settings'] ) && isset( $fields[ $setting_key ]['range_settings']['max'] ) ?
absint( $fields[ $setting_key ]['range_settings']['max'] ) : -1;
if ( $setting_value < $range_min || $range_max < $setting_value ) {
$setting_value = et_sanitize_alpha_color( $setting_value );
// Allow HTML content on Excerpt field.
if ( 'et_pb_post_settings_excerpt' === $setting_key ) {
$setting_value = wp_kses_post( $setting_value );
$setting_value = sanitize_textarea_field( $setting_value );
$setting_value = array_map( 'intval', explode( ',', $setting_value ) );
$setting_value = sanitize_text_field( $setting_value );
// check whether or not the defined value === default value
$is_default = isset( $fields[ $setting_key ]['default'] ) && $setting_value === $fields[ $setting_key ]['default'];
// Auto-formatting AB Testing status' meta key
if ( 'et_pb_enable_ab_testing' === $setting_key ) {
$setting_key = 'et_pb_use_ab_testing';
* Fires before updating a builder setting in the database.
* @param string $setting_key The option name/id.
* @param string $setting_value The new option value.
* @param string|int $post_id The post id or 'global' for global settings.
do_action( 'et_builder_settings_update_option', $setting_key, $setting_value, $post_id );
// If `post_field` is defined, we need to update the post.
$post_field = $utils->array_get( $fields, "{$setting_key}.post_field", false );
if ( false !== $post_field ) {
if ( ! ( $is_global || $is_BB ) ) {
// Save the post field so we can do a single update.
// Use the raw value and rely on wp_update_post to sanitize it in order to allow certain HTML tags.
$update[ $post_field ] = $raw_setting_value;
// If `taxonomy_name` is defined, we need to update the post terms.
$taxonomy_name = $utils->array_get( $fields, "{$setting_key}.taxonomy_name", false );
if ( false !== $taxonomy_name ) {
if ( ! ( $is_global || $is_BB ) ) {
$post_type = $utils->array_get( $fields, "{$setting_key}.post_type", false );
if ( $post_type === get_post_type( $post_id ) ) {
// Only update if the post type matches.
wp_set_object_terms( $post_id, $setting_value, $taxonomy_name );
// Save the setting in a post meta.
$meta_key = $utils->array_get( $fields, $setting_key . '.meta_key', false ) ? $fields[ $setting_key ]['meta_key'] : "_{$setting_key}";
$save_post = $utils->array_get( $fields, $setting_key . '.save_post', true );
if ( $is_BB && $save_post === false ) {
// This meta key must be ignored during classic-editor / BB save action or it will
// overwrite values in the WP edit page.
// remove if value is default
$is_global ? et_delete_option( $setting_key ) : delete_post_meta( $post_id, $meta_key );
$is_global ? et_update_option( $setting_key, $setting_value ) : update_post_meta( $post_id, $meta_key, $setting_value );
delete_post_meta( $post_id, "{$meta_key}_draft" );
// Removing builder settings autosave
$current_user_id = get_current_user_id();
delete_post_meta( $post_id, "_et_builder_settings_autosave_{$current_user_id}");
if ( count( $update ) > 0 ) {
// This MUST NOT be executed while saving data in the BB or it will generate
// an update loop that will end the universe as we know it.
if ( ! ( $is_BB || wp_is_post_revision( $post_id ) ) ) {
$update['ID'] = $post_id;
wp_update_post( $update );
* Returns array of default color pallete
* @return array default color palette
function et_pb_get_default_color_palette( $post_id = 0 ) {
$default_palette = array(
$saved_global_palette = et_get_option( 'divi_color_palette', false );
$palette = $saved_global_palette && '' !== str_replace( '|', '', $saved_global_palette ) ? explode( '|', $saved_global_palette ) : $default_palette;
return apply_filters( 'et_pb_get_default_color_palette', $palette, $post_id );
* Modify builder editor's TinyMCE configuration
function et_pb_content_mce_config( $mceInit, $editor_id ) {
if ( 'et_pb_content' === $editor_id && isset( $mceInit['toolbar1'] ) ) {
$toolbar1 = explode(',', $mceInit['toolbar1'] );
// Look for read more (wp_more)'s array' key
$wp_more_key = array_search( 'wp_more', $toolbar1 );
unset( $toolbar1[ $wp_more_key ] );
// Update toolbar1 configuration
$mceInit['toolbar1'] = implode(',', $toolbar1 );
add_filter( 'tiny_mce_before_init', 'et_pb_content_mce_config', 10, 2 );
* Get post format with filterable output
* @todo once WordPress provide filter for get_post_format() output, this function can be retired
* @return mixed string|bool string of post format or false for default
function et_pb_post_format() {
return apply_filters( 'et_pb_post_format', get_post_format(), get_the_ID() );
* Return post format into false when using pagebuilder
* @return mixed string|bool string of post format or false for default
function et_pb_post_format_in_pagebuilder( $post_format, $post_id ) {
if ( et_pb_is_pagebuilder_used( $post_id ) ) {
add_filter( 'et_pb_post_format', 'et_pb_post_format_in_pagebuilder', 10, 2 );
if ( ! function_exists( 'et_get_first_audio_block' ) ) :
function et_get_first_audio_block() {
$content = get_the_content();
// It is assumed that audio module figures will not contain other figures.
preg_match( '/<figure\s+[^>]*?class=([\'"])[^\'"]*?wp-block-audio[^\'"]*?\1[^>]*?>.*?<\/figure>/', $content, $matches );
if ( empty( $matches ) ) {
if ( ! function_exists( 'et_pb_get_audio_player' ) ) :
function et_pb_get_audio_player() {
global $_et_pbgap_audio_to_remove;
$regex = get_shortcode_regex( array( 'audio' ) );
preg_match_all( "/{$regex}/s", get_the_content(), $matches );
foreach ( $matches[2] as $key => $shortcode_match ) {
// Remove audio shortcode if its contains first attached audio file URL
// first attached audio file is automatically appended on post's format content
if ( 'audio' === $shortcode_match ) {
$_et_pbgap_audio_to_remove = $matches[0][0];
$shortcode_audio = do_shortcode( $_et_pbgap_audio_to_remove );
if ( '' === $shortcode_audio ) {
$_et_pbgap_audio_to_remove = et_get_first_audio_block();
$shortcode_audio = $_et_pbgap_audio_to_remove;
if ( '' === $shortcode_audio ) {
'<div class="et_audio_container">
</div> <!-- .et_audio_container -->',
add_filter( 'the_content', 'et_delete_post_audio' );
* Displays post audio, quote and link post formats content
if ( ! function_exists( 'et_divi_post_format_content' ) ) :
function et_divi_post_format_content() {
$post_format = et_pb_post_format();
$text_color_class = et_divi_get_post_text_color();
$inline_style = et_divi_get_post_bg_inline_style();
if ( post_password_required( $post ) ) {
switch ( $post_format ) {
'<div class="et_audio_content%4$s"%5$s>
<h2><a href="%3$s">%1$s</a></h2>
</div> <!-- .et_audio_content -->',
esc_html( get_the_title() ),
et_core_intentionally_unescaped( et_pb_get_audio_player(), 'html' ),
esc_url( get_permalink() ),
esc_attr( $text_color_class ),
et_core_esc_previously( $inline_style )
'<div class="et_quote_content%4$s"%5$s>
<a href="%2$s" class="et_quote_main_link">%3$s</a>
</div> <!-- .et_quote_content -->',
et_core_intentionally_unescaped( et_get_blockquote_in_content(), 'html' ),
esc_url( get_permalink() ),
esc_html__( 'Read more', 'et_builder' ),
esc_attr( $text_color_class ),
et_core_esc_previously( $inline_style )
'<div class="et_link_content%5$s"%6$s>
<h2><a href="%2$s">%1$s</a></h2>
<a href="%3$s" class="et_link_main_url">%4$s</a>
</div> <!-- .et_link_content -->',
esc_html( get_the_title() ),
esc_url( get_permalink() ),
esc_url( et_get_link_url() ),
esc_html( et_get_link_url() ),
esc_attr( $text_color_class ),
et_core_esc_previously( $inline_style )
* Extract and return the first blockquote from content.
if ( ! function_exists( 'et_get_blockquote_in_content' ) ) :
function et_get_blockquote_in_content() {
$more = 1; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
remove_filter( 'the_content', 'et_remove_blockquote_from_content' );
$content = apply_filters( 'the_content', get_the_content() );
add_filter( 'the_content', 'et_remove_blockquote_from_content' );
$more = $more_default; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
if ( preg_match( '/<blockquote(.+?)<\/blockquote>/is', $content, $matches ) ) {
if ( ! function_exists( 'et_get_link_url' ) ) :
function et_get_link_url() {
if ( '' !== ( $link_url = get_post_meta( get_the_ID(), '_format_link_url', true ) ) ) {
$content = get_the_content();
$has_url = get_url_in_content( $content );
return ( $has_url ) ? $has_url : apply_filters( 'the_permalink', get_permalink() );
if ( ! function_exists( 'et_get_first_video' ) ) :
function et_get_first_video() {
$video_width = (int) apply_filters( 'et_blog_video_width', 1080 );
$video_height = (int) apply_filters( 'et_blog_video_height', 630 );
$content = get_the_content();
preg_match_all( '|^\s*https?://[^\s"]+\s*$|im', $content, $urls );
foreach ( $urls[0] as $url ) {
$first_url = trim( $url );
$oembed = wp_oembed_get( esc_url( $url ) );
$first_video = preg_replace( '/<embed /', '<embed wmode="transparent" ', $first_video );
$first_video = preg_replace( '/<\/object>/','<param name="wmode" value="transparent" /></object>', $first_video );
// If the url comes from a GB embed block
if ( preg_match( '|wp-block-embed.+?'.preg_quote($url).'|s', $content ) ) {
// We need to remove some useless markup later
add_filter( 'the_content', 'et_delete_post_video' );
if ( '' === $first_video ) {
// Gutenberg compatibility.
if ( ! has_shortcode( $content, 'video' ) && empty( $first_url ) ) {
preg_match( '/<!-- wp:video[^\]]+?class="wp-block-video"><video[^\]]+?src="([^\]]+?)"[^\]]+?<!-- \/wp:video -->/', $content, $gb_video );
$first_url = isset($gb_video[1]) ? $gb_video[1] : false;
if ( ! has_shortcode( $content, 'video' ) && ! empty( $first_url ) ) {
$video_shortcode = sprintf( '[video src="%1$s" /]', esc_attr( $first_url ) );
if ( ! empty( $gb_video ) ) {
$content = str_replace( $gb_video[0], $video_shortcode, $content );
$content = str_replace( $first_url, $video_shortcode, $content );
if ( has_shortcode( $content, 'video' ) ) {
$regex = get_shortcode_regex();
preg_match( "/{$regex}/s", $content, $match );
$first_video = preg_replace( "/width=\"[0-9]*\"/", "width=\"{$video_width}\"", $match[0] );
$first_video = preg_replace( "/height=\"[0-9]*\"/", "height=\"{$video_height}\"", $first_video );
add_filter( 'the_content', 'et_delete_post_video' );
$first_video = do_shortcode( et_pb_fix_shortcodes( $first_video ) );
return ( '' !== $first_video ) ? $first_video : false;