: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
function et_builder_is_post_type_custom( $post_type ) {
return $post_type && ( ! in_array( $post_type, et_builder_get_default_post_types() ) || et_theme_builder_is_layout_post_type( $post_type ) );
* Check whether the supplied post is of a custom post type as far as the builder is concerned.
* If no post id is supplied, checks whether the current page is the singular view of a custom post type.
* @param integer $post_id
function et_builder_post_is_of_custom_post_type( $post_id = 0 ) {
$post_types = et_builder_get_default_post_types();
return is_singular() && ! in_array( get_post_type( get_the_ID() ), $post_types );
return et_builder_is_post_type_custom( get_post_type( $post_id ) );
* Check whether the current request is for a custom post type archive.
function et_builder_is_custom_post_type_archive() {
// Use get_the_ID() explicitly so we decide based on the first post of an archive page.
return is_archive() && et_builder_post_is_of_custom_post_type( get_the_ID() );
* Get an array of post types the Divi Builder is enabled on.
function et_builder_get_enabled_builder_post_types() {
et_builder_get_default_post_types(),
et_builder_get_third_party_post_types()
* Filter the array of enabled post type options.
* Allows Divi/Extra/DBP to only supply their option value in order to reduce code duplication.
* 'post_type_name' => <'on' or 'off'>,
* @param string[] $options
$options = apply_filters( 'et_builder_enabled_builder_post_type_options', array() );
foreach ( $default as $post_type ) {
if ( ! isset( $options[ $post_type ] ) ) {
$options[ $post_type ] = 'on';
foreach ( $options as $post_type => $state ) {
if ( 'on' === $state && array_key_exists( $post_type, et_get_registered_post_type_options() ) && ! in_array( $post_type, et_builder_get_blocklisted_post_types() ) ) {
$filtered[] = $post_type;
function et_builder_get_builder_post_types() {
* Array of post types which have the builder enabled.
return apply_filters( 'et_builder_post_types', et_builder_get_enabled_builder_post_types() );
function et_builder_get_fb_post_types() {
* Array of post types which have the frontend builder enabled.
return apply_filters( 'et_fb_post_types', et_builder_get_enabled_builder_post_types() );
* Check whether the specified post can have the builder enabled.
* @param integer $post_id
function et_builder_enabled_for_post( $post_id ) {
if ( et_pb_is_pagebuilder_used( $post_id ) ) {
return et_builder_enabled_for_post_type( get_post_type( $post_id ) );
* Check whether the specified post type can have the builder enabled.
* @param string $post_type
function et_builder_enabled_for_post_type( $post_type ) {
return in_array( $post_type, et_builder_get_builder_post_types() );
* Check whether the specified post can have the FB enabled.
* @param string $post_type
function et_builder_fb_enabled_for_post( $post_id ) {
$post_type = get_post_type( $post_id );
$pto = get_post_type_object( $post_type );
$is_default_post_type = in_array( $post_type, et_builder_get_default_post_types() );
$is_public_post_type = et_builder_is_post_type_public( $post_type );
if ( $pto && ( $is_default_post_type || $is_public_post_type ) ) {
$enabled = et_builder_enabled_for_post( $post_id );
* Filter whether the FB is enabled for a given post.
* @param boolean $enabled
* @param integer $post_id
$enabled = apply_filters( 'et_builder_fb_enabled_for_post', $enabled, $post_id );
* Check whether the specified post type is public.
* @param string $post_type
function et_builder_is_post_type_public( $post_type ) {
$pto = get_post_type_object( $post_type );
// Note: the page post type is not publicly_queryable but we should treat it as such.
return ( $pto && ( $pto->publicly_queryable || $pto->name === 'page' ) );
function et_is_extra_library_layout( $post_id ) {
return 'layout' === get_post_type( $post_id );
* Check whether the specified capability allowed for the user
* @param array|string $capabilities
* @param string $role - The user role. If empty the role of the current user is used
function et_pb_is_allowed( $capabilities, $role = '' ) {
$saved_capabilities = et_pb_get_role_settings();
$test_current_user = '' === $role;
$role = $test_current_user ? et_pb_get_current_user_role() : $role;
// Disable certain capabilities for non-allowlisted roles by default.
$dangerous = array( 'theme_builder', 'read_dynamic_content_custom_fields' );
$roles_allowlist = array( 'administrator', 'et_support_elevated', 'et_support' );
foreach ( (array) $capabilities as $capability ) {
$is_dangerous = in_array( $capability, $dangerous, true );
$role_not_allowlisted = ! in_array( $role, $roles_allowlist, true );
if ( $test_current_user && $is_dangerous && is_multisite() && is_super_admin() ) {
// Super admins always have access to dangerous capabilities and that cannot be
// changed in the role editor.
if ( ! empty( $saved_capabilities[ $role ][ $capability ] ) ) {
return 'on' === $saved_capabilities[ $role ][ $capability ];
if ( $is_dangerous && $role_not_allowlisted ) {
// Allowlisted roles have access to dangerous capabilities by default,
// but that can be changed in the role editor.
* Performs a check against ET capabilities before passing on to {@see et_core_security_check()}.
* @param string $et_capability
* @param string $wp_capability
* @param string $nonce_action
* @param string $nonce_key
* @param string $nonce_location
function et_builder_security_check( $et_capability, $wp_capability = 'manage_options', $nonce_action = '', $nonce_key = '', $nonce_location = '_POST', $die = true ) {
if ( ! et_pb_is_allowed( $et_capability ) ) {
return et_core_security_check( $wp_capability, $nonce_action, $nonce_key, $nonce_location, $die );
* Gets the array of role settings
function et_pb_get_role_settings() {
global $et_pb_role_settings;
// if we don't have saved global variable, then get the value from WPDB
$et_pb_role_settings = isset( $et_pb_role_settings ) ? $et_pb_role_settings : get_option( 'et_pb_role_settings', array() );
return $et_pb_role_settings;
* Determines the current user role
function et_pb_get_current_user_role() {
$current_user = wp_get_current_user();
$user_roles = $current_user->roles;
// retrieve the role from array if exists or determine it using custom mechanism
// $user_roles array may start not from 0 index. Use reset() to retrieve the first value from array regardless its index
$role = ! empty( $user_roles ) ? reset( $user_roles ) : et_pb_determine_current_user_role();
* Generate the list of all roles ( with editing permissions ) registered in current WP
function et_pb_get_all_roles_list() {
// get all roles registered in current WP
if ( ! function_exists( 'get_editable_roles' ) ) {
require_once( ABSPATH . 'wp-admin/includes/user.php' );
$all_roles = get_editable_roles();
$builder_roles_array = array();
if ( ! empty( $all_roles ) ) {
foreach( $all_roles as $role => $role_data ) {
// add roles with edit_posts capability into $builder_roles_array (but not Support)
! empty( $role_data['capabilities']['edit_posts'] )
1 === (int) $role_data['capabilities']['edit_posts']
! in_array( $role_data['name'], array( "ET Support", "ET Support - Elevated" ) )
$builder_roles_array[ $role ] = $role_data['name'];
// fill the builder roles array with default roles if it's empty
if ( empty( $builder_roles_array ) ) {
$builder_roles_array = array(
'administrator' => esc_html__( 'Administrator', 'et_builder' ),
'editor' => esc_html__( 'Editor', 'et_builder' ),
'author' => esc_html__( 'Author', 'et_builder' ),
'contributor' => esc_html__( 'Contributor', 'et_builder' ),
return $builder_roles_array;
* Determine the current user role by checking every single registered role via current_user_can()
function et_pb_determine_current_user_role() {
$all_roles = et_pb_get_all_roles_list();
// go through all the registered roles and return the one current user have
foreach( $all_roles as $role => $role_data ) {
if ( current_user_can( $role ) ) {
function et_pb_show_all_layouts_built_for_post_type( $post_type ) {
$similar_post_types = array(
if ( in_array( $post_type, $similar_post_types ) ) {
return $similar_post_types;
add_filter( 'et_pb_show_all_layouts_built_for_post_type', 'et_pb_show_all_layouts_built_for_post_type' );
function et_pb_show_all_layouts() {
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'edit_posts' ) ) {
<label for="et_pb_load_layout_replace">
<input name="et_pb_load_layout_replace" type="checkbox" id="et_pb_load_layout_replace" %2$s/>
esc_html__( 'Replace the existing content with loaded layout', 'et_builder' ),
checked( get_theme_mod( 'et_pb_replace_content', 'on' ), 'on', false )
$post_type = ! empty( $_POST['et_layouts_built_for_post_type'] ) ? sanitize_text_field( $_POST['et_layouts_built_for_post_type'] ) : 'post';
$layouts_type = ! empty( $_POST['et_load_layouts_type'] ) ? sanitize_text_field( $_POST['et_load_layouts_type'] ) : 'predefined';
$predefined_operator = 'predefined' === $layouts_type ? 'EXISTS' : 'NOT EXISTS';
$post_type = apply_filters( 'et_pb_show_all_layouts_built_for_post_type', $post_type, $layouts_type );
'key' => '_et_pb_predefined_layout',
'compare' => $predefined_operator,
'key' => '_et_pb_built_for_post_type',
'key' => '_et_pb_layout_applicability',
'value' => 'product_tour',
'compare' => 'NOT EXISTS',
'taxonomy' => 'layout_type',
'terms' => array( 'section', 'row', 'module', 'fullwidth_section', 'specialty_section', 'fullwidth_module' ),
'post_type' => ET_BUILDER_LAYOUT_POST_TYPE,
'posts_per_page' => '-1',
'suppress_filters' => 'predefined' === $layouts_type,
$query = new WP_Query( $query_args );
if ( $query->have_posts() ) :
echo '<ul class="et-pb-all-modules et-pb-load-layouts">';
while ( $query->have_posts() ) : $query->the_post();
$button_html = 'predefined' !== $layouts_type ?
sprintf( '<a href="#" class="button et_pb_layout_button_delete">%1$s</a>',
esc_html__( 'Delete', 'et_builder' )
printf( '<li class="et_pb_text" data-layout_id="%2$s">%1$s<span class="et_pb_layout_buttons"><a href="#" class="button-primary et_pb_layout_button_load">%3$s</a>%4$s</span></li>',
esc_html( get_the_title() ),
esc_attr( get_the_ID() ),
esc_html__( 'Load', 'et_builder' ),
et_core_esc_previously( $button_html )
add_action( 'wp_ajax_et_pb_show_all_layouts', 'et_pb_show_all_layouts' );
function et_pb_get_saved_templates() {
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'edit_posts' ) ) {
$layout_type = ! empty( $_POST['et_layout_type'] ) ? sanitize_text_field( $_POST['et_layout_type'] ) : 'layout';
$module_width = ! empty( $_POST['et_module_width'] ) && 'module' === $layout_type ? sanitize_text_field( $_POST['et_module_width'] ) : '';
$is_global = ! empty( $_POST['et_is_global'] ) ? sanitize_text_field( $_POST['et_is_global'] ) : 'false';
$specialty_query = ! empty( $_POST['et_specialty_columns'] ) && 'row' === $layout_type ? sanitize_text_field( $_POST['et_specialty_columns'] ) : '0';
$post_type = ! empty( $_POST['et_post_type'] ) ? sanitize_text_field( $_POST['et_post_type'] ) : 'post';
$templates_data = et_pb_retrieve_templates( $layout_type, $module_width, $is_global, $specialty_query, $post_type );
if ( empty( $templates_data ) ) {
$templates_data = array( 'error' => esc_html__( 'You have not saved any items to your Divi Library yet. Once an item has been saved to your library, it will appear here for easy use.', 'et_builder' ) );
$json_templates = wp_json_encode( $templates_data );
die( et_core_esc_previously( $json_templates ) );
add_action( 'wp_ajax_et_pb_get_saved_templates', 'et_pb_get_saved_templates' );
* Retrieves saved builder layouts.
* @param string $layout_type Accepts 'section', 'row', 'module', 'fullwidth_section',
* 'specialty_section', 'fullwidth_module'.
* @param string $module_width Accepts 'regular', 'fullwidth'.
* @param string $is_global Filter layouts based on their scope. Accepts 'global' to include
* only global layouts, 'false' to include only non-global layouts,
* or 'all' to include both global and non-global layouts.
* @param string $specialty_query Limit results to layouts of type 'row' that can be put inside
* specialty sections. Accepts '3' to include only 3-column rows,
* '2' for 2-column rows, or '0' to disable the specialty query. Default '0'.
* @param string $post_type Limit results to layouts built for this post type.
* @param string $deprecated Deprecated.
* @param array $boundaries {
* Return a subset of the total results.
* @type int $offset Start from this point in the results. Default `0`.
* @type int $limit Maximum number of results to return. Default `-1`.