: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Render a builder layout to string.
function et_builder_render_layout( $content ) {
* Filters layout content when it's being rendered.
return apply_filters( 'et_builder_render_layout', $content );
// Add all core filters that are applied to the_content() without do_blocks().
add_filter( 'et_builder_render_layout', 'capital_P_dangit', 11 );
add_filter( 'et_builder_render_layout', 'wptexturize' );
add_filter( 'et_builder_render_layout', 'convert_smilies', 20 );
add_filter( 'et_builder_render_layout', 'wpautop' );
add_filter( 'et_builder_render_layout', 'shortcode_unautop' );
add_filter( 'et_builder_render_layout', 'prepend_attachment' );
add_filter( 'et_builder_render_layout', 'et_builder_filter_content_image_tags' );
add_filter( 'et_builder_render_layout', 'do_shortcode', 11 ); // AFTER wpautop()
if ( ! function_exists( 'et_builder_filter_content_image_tags' ) ) {
* Whether filter image tags on post content with different functions.
* @param string $content The HTML content to be filtered.
* @return string Converted content with images modified.
function et_builder_filter_content_image_tags( $content ) {
if ( function_exists( 'wp_filter_content_tags' ) ) {
// Function wp_filter_content_tags() is introduced on WP 5.5 forward.
$content = wp_filter_content_tags( $content );
// Function wp_make_content_images_responsive() is used by WP 5.4 below.
$content = wp_make_content_images_responsive( $content );
if ( ! function_exists( 'et_builder_add_filters' ) ):
* Add common filters depending on what builder is being used.
* These hooks are not used in DBP as it has its own implementations for them.
function et_builder_add_filters() {
if ( et_is_builder_plugin_active() ) {
add_filter( 'et_builder_bfb_enabled', 'et_builder_filter_bfb_enabled' );
add_filter( 'et_builder_is_fresh_install', 'et_builder_filter_is_fresh_install' );
add_action( 'et_builder_toggle_bfb', 'et_builder_action_toggle_bfb' );
add_action( 'init', 'et_builder_add_filters' );
if ( ! function_exists( 'et_builder_should_load_framework' ) ):
function et_builder_should_load_framework() {
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
static $should_load = null;
if ( null !== $should_load ) {
if ( defined( 'WP_CLI' ) && WP_CLI ) {
return $should_load = true;
if ( ET_Core_Portability::doing_import() ) {
return $should_load = true;
$required_admin_pages = array( 'edit.php', 'post.php', 'post-new.php', 'admin.php', 'customize.php', 'edit-tags.php', 'admin-ajax.php', 'export.php', 'options-permalink.php', 'themes.php', 'revision.php' ); // list of admin pages where we need to load builder files
$specific_filter_pages = array( 'edit.php', 'post.php', 'post-new.php', 'admin.php', 'edit-tags.php' ); // list of admin pages where we need more specific filtering
$post_id = (int) et_()->array_get( $_GET, 'post', 0 );
$bfb_settings = get_option( 'et_bfb_settings' );
$is_bfb = et_pb_is_allowed( 'use_visual_builder' ) && isset( $bfb_settings['enable_bfb'] ) && 'on' === $bfb_settings['enable_bfb'];
$is_bfb_used = 'on' === get_post_meta( $post_id, '_et_pb_use_builder', true ) && $is_bfb;
$is_edit_library_page = in_array( $pagenow, array( 'edit.php', 'post.php', 'post-new.php' ) ) && ( ( isset( $_GET['post_type'] ) && 'et_pb_layout' === $_GET['post_type'] ) || ( $post_id && 'et_pb_layout' === get_post_type( $post_id ) ) );
$is_extra_builder = $post_id && 'layout' === get_post_type( $post_id );
$is_edit_page_not_bfb = in_array( $pagenow, array( 'post-new.php', 'post.php' ) ) && !$is_bfb_used;
$is_role_editor_page = 'admin.php' === $pagenow && isset( $_GET['page'] ) && apply_filters( 'et_divi_role_editor_page', 'et_divi_role_editor' ) === $_GET['page'];
$is_import_page = 'admin.php' === $pagenow && isset( $_GET['import'] ) && 'wordpress' === $_GET['import']; // Page Builder files should be loaded on import page as well to register the et_pb_layout post type properly
$is_wpml_page = 'admin.php' === $pagenow && isset( $_GET['page'] ) && 'sitepress-multilingual-cms/menu/languages.php' === $_GET['page']; // Page Builder files should be loaded on WPML clone page as well to register the custom taxonomies properly
$is_edit_layout_category_page = 'edit-tags.php' === $pagenow && isset( $_GET['taxonomy'] ) && ( 'layout_category' === $_GET['taxonomy'] || 'layout_pack' === $_GET['taxonomy'] );
if ( ! $is_admin || ( $is_admin && in_array( $pagenow, $required_admin_pages ) && ( ! in_array( $pagenow, $specific_filter_pages ) || $is_edit_library_page || $is_role_editor_page || $is_edit_layout_category_page || $is_import_page || $is_wpml_page || $is_edit_page_not_bfb || $is_extra_builder ) ) ) {
* Filters whether or not the Divi Builder codebase should be loaded for the current request.
* @param bool $should_load
$should_load = apply_filters( 'et_builder_should_load_framework', $should_load );
if ( et_builder_should_load_framework() ) {
// Initialize the Divi Library
require_once ET_BUILDER_DIR . 'feature/Library.php';
if ( ! function_exists( 'et_builder_maybe_enable_inline_styles' ) ):
function et_builder_maybe_enable_inline_styles() {
et_update_option( 'static_css_custom_css_safety_check_done', true );
if ( ! wp_get_custom_css() ) {
// This site has Custom CSS that existed prior to v3.0.54 which could contain syntax
// errors that the user is unaware of. Such errors would cause problems in a unified
// static CSS file so let's enable inline styles for the builder's design styles.
et_update_option( 'et_pb_css_in_footer', 'on' );
if ( defined( 'ET_CORE_UPDATED' ) && ! et_get_option( 'static_css_custom_css_safety_check_done', false ) ) {
et_builder_maybe_enable_inline_styles();
function et_pb_video_get_oembed_thumbnail() {
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'edit_posts' ) ) {
$video_url = esc_url( $_POST['et_video_url'] );
if ( false !== wp_oembed_get( $video_url ) ) {
add_filter( 'oembed_dataparse', 'et_pb_video_oembed_data_parse', 10, 3 );
$image_src = wp_oembed_get( $video_url );
remove_filter( 'oembed_dataparse', 'et_pb_video_oembed_data_parse', 10, 3 );
if ( '' === $image_src ) {
echo esc_url( $image_src );
add_action( 'wp_ajax_et_pb_video_get_oembed_thumbnail', 'et_pb_video_get_oembed_thumbnail' );
if ( ! function_exists( 'et_pb_video_oembed_data_parse' ) ) :
function et_pb_video_oembed_data_parse( $return, $data, $url ) {
if ( isset( $data->thumbnail_url ) ) {
return esc_url( str_replace( array('https://', 'http://'), '//', $data->thumbnail_url ), array('http') );
function et_pb_add_widget_area(){
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'manage_options' ) ) {
$et_pb_widgets = get_theme_mod( 'et_pb_widgets' );
$number = $et_pb_widgets ? intval( $et_pb_widgets['number'] ) + 1 : 1;
$et_widget_area_name = sanitize_text_field( $_POST['et_widget_area_name'] );
$et_pb_widgets['areas']['et_pb_widget_area_' . $number] = $et_widget_area_name;
$et_pb_widgets['number'] = $number;
set_theme_mod( 'et_pb_widgets', $et_pb_widgets );
et_pb_force_regenerate_templates();
printf( et_get_safe_localization( __( '<strong>%1$s</strong> widget area has been created. You can create more areas, once you finish update the page to see all the areas.', 'et_builder' ) ),
esc_html( $et_widget_area_name )
add_action( 'wp_ajax_et_pb_add_widget_area', 'et_pb_add_widget_area' );
function et_pb_remove_widget_area(){
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'manage_options' ) ) {
$et_pb_widgets = get_theme_mod( 'et_pb_widgets' );
$et_widget_area_name = sanitize_text_field( $_POST['et_widget_area_name'] );
unset( $et_pb_widgets['areas'][ $et_widget_area_name ] );
set_theme_mod( 'et_pb_widgets', $et_pb_widgets );
et_pb_force_regenerate_templates();
die( esc_html( $et_widget_area_name ) );
add_action( 'wp_ajax_et_pb_remove_widget_area', 'et_pb_remove_widget_area' );
function et_pb_current_user_can_lock() {
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'edit_posts' ) ) {
$permission = et_pb_is_allowed( 'lock_module' );
$permission = wp_json_encode( (bool) $permission );
die( et_core_esc_previously( $permission ) );
add_action( 'wp_ajax_et_pb_current_user_can_lock', 'et_pb_current_user_can_lock' );
* Get the supported post types by default.
function et_builder_get_default_post_types() {
* Filter default post types that are powered by the builder.
return apply_filters( 'et_builder_default_post_types', array(
* Get the supported third party post types.
function et_builder_get_third_party_post_types() {
$third_party_post_types = array();
// WooCommerce (https://wordpress.org/plugins/woocommerce/):
if ( class_exists( 'WooCommerce' ) ) {
$third_party_post_types[] = 'product';
// The Events Calendar (https://wordpress.org/plugins/the-events-calendar/):
if ( class_exists( 'Tribe__Events__Main' ) ) {
$third_party_post_types[] = 'tribe_events';
// Popup Maker (https://wordpress.org/plugins/popup-maker/):
if ( class_exists( 'Popup_Maker' ) ) {
$third_party_post_types[] = 'popup';
// All-in-One Event Calendar (https://wordpress.org/plugins/all-in-one-event-calendar/):
if ( function_exists( 'ai1ec_initiate_constants' ) ) {
$third_party_post_types[] = 'ai1ec_event';
// Events Manager (https://wordpress.org/plugins/events-manager/):
if ( function_exists( 'em_plugins_loaded' ) ) {
$third_party_post_types[] = 'event';
$third_party_post_types[] = 'location';
// Portfolio Post Type (https://wordpress.org/plugins/portfolio-post-type/):
if ( function_exists( 'portfolio_post_type_init' ) ) {
$third_party_post_types[] = 'portfolio';
// LifterLMS (https://wordpress.org/plugins/lifterlms/):
if ( class_exists( 'LifterLMS' ) ) {
$third_party_post_types[] = 'course';
// LearnDash (https://www.learndash.com/wordpress-course-plugin-features/):
if ( class_exists( 'Semper_Fi_Module' ) ) {
$third_party_post_types[] = 'sfwd-courses';
$third_party_post_types[] = 'sfwd-lessons';
* Array of third-party registered post types that should have support enabled by default.
return apply_filters( 'et_builder_third_party_post_types', $third_party_post_types );
* Look for builder's registered third party post type that isn't publicly queryable
function et_builder_get_third_party_unqueryable_post_types() {
// Save the value in static variable so if post type's publicly_queryable is modified due to current
// request is BFB request, this function still return correct value
static $unqueryable_post_types = array();
if ( empty( $unqueryable_post_types ) ) {
// Get third party's unqueryable post types only as default post types have been handled properly
$valid_third_party_post_types = array_diff(
et_builder_get_builder_post_types(),
et_builder_get_default_post_types()
$unqueryable_post_types = array_intersect(
$valid_third_party_post_types,
get_post_types( array('publicly_queryable' => false ) )
return apply_filters( 'et_builder_get_third_party_unqueryable_post_types', $unqueryable_post_types );
* Get the list of registered Post Types options.
* @since 4.0.7 Added the $require_editor parameter.
* @param boolean|callable $usort
* @param boolean $require_editor
function et_get_registered_post_type_options( $usort = false, $require_editor = true ) {
$require_editor_key = $require_editor ? '1' : '0';
$key = "et_get_registered_post_type_options:{$require_editor_key}";
if ( ET_Core_Cache::has( $key ) ) {
return ET_Core_Cache::get( $key );
$blocklist = et_builder_get_blocklisted_post_types();
$allowlist = et_builder_get_third_party_post_types();
// Extra and Library layouts shouldn't appear in Theme Options as configurable post types.
* Get array of post types to prevent from appearing as options for builder usage.
* @param string[] $blocklist Post types to blocklist.
$blocklist = apply_filters( 'et_builder_post_type_options_blocklist', array_merge( $blocklist, array(
$raw_post_types = get_post_types( array(
foreach ( $raw_post_types as $post_type ) {
$is_allowlisted = in_array( $post_type->name, $allowlist );
$is_blocklisted = in_array( $post_type->name, $blocklist );
$supports_editor = $require_editor ? post_type_supports( $post_type->name, 'editor' ) : true;
$is_public = et_builder_is_post_type_public( $post_type->name );
if ( ! $is_allowlisted && ( $is_blocklisted || ! $supports_editor || ! $is_public ) ) {
$post_types[] = $post_type;
if ( $usort && is_callable( $usort ) ) {
usort( $post_types, $usort );
$post_type_options = array_combine(
wp_list_pluck( $post_types, 'name' ),
wp_list_pluck( $post_types, 'label' )
// did_action() actually checks if the action has started, not ended so we
// need to check that we are not currently doing the action as well.
if ( did_action( 'init' ) && ! doing_action( 'init' ) ) {
// Only cache the value after init is done when we are sure all
// plugins have registered their post types.
ET_Core_Cache::add( $key, $post_type_options );
return $post_type_options;
* Clear post type options cache whenever a custom post type is registered.
function et_clear_registered_post_type_options_cache() {
ET_Core_Cache::delete( 'et_get_registered_post_type_options' );
add_action( 'registered_post_type', 'et_clear_registered_post_type_options_cache');
* Get the list of unsupported Post Types.
function et_builder_get_blocklisted_post_types() {
return apply_filters( 'et_builder_post_type_blocklist', array(
* Get the list of unsupported Post Types.
* @deprecated ?? No longer used by internal code; use `et_builder_get_blocklisted_post_types` instead.
* @since 4.5.1 Aliased to `et_builder_get_blocklisted_post_types`.
function et_builder_get_blacklisted_post_types() {
return et_builder_get_blocklisted_post_types();
* Check whether the supplied post type is a custom post type as far as the builder is concerned.
* @param string $post_type