: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @return array[] $layouts {
* @type int $ID The layout's post id.
* @type string $title The layout's title/name.
* @type string $shortcode The layout's shortcode content.
* @type string $is_global The layout's scope. Accepts 'global', 'non_global'.
* @type string $layout_type The layout's type. See {@see self::$layout_type} param for accepted values.
* @type string $applicability The layout's applicability.
* @type string $layouts_type Deprecated. Will always be 'library'.
* @type string $module_type For layouts of type 'module', the module type/slug (eg. et_pb_blog).
* @type string[] $categories This layout's assigned categories (slugs).
* @type string $row_layout For layout's of type 'row', the row layout type (eg. 4_4).
* @type mixed[] $unsynced_options For global layouts, the layout's unsynced settings.
function et_pb_retrieve_templates( $layout_type = 'layout', $module_width = '', $is_global = 'false', $specialty_query = '0', $post_type = 'post', $deprecated = '', $boundaries = array() ) {
$templates_data = array();
$suppress_filters = false;
$extra_layout_post_type = 'layout';
$module_icons = ET_Builder_Element::get_module_icons();
$utils = ET_Core_Data_Utils::instance();
$similar_post_types = array_keys(ET_Builder_Settings::get_registered_post_type_options());
// All default and 3rd party post types considered similar and share the same library items, so retrieve all items for any post type from the list
$post_type = in_array($post_type, $similar_post_types) ? $similar_post_types : $post_type;
// need specific query for the layouts
if ( 'layout' === $layout_type ) {
if ( 'all' === $post_type ) {
'key' => '_et_pb_built_for_post_type',
'value' => $extra_layout_post_type,
'key' => '_et_pb_built_for_post_type',
'taxonomy' => 'layout_type',
'terms' => array( 'section', 'row', 'module', 'fullwidth_section', 'specialty_section', 'fullwidth_module' ),
$suppress_filters = 'predefined' === $layout_type;
$additional_condition = '' !== $module_width ?
'taxonomy' => 'module_width',
'terms' => $module_width,
if ( '0' !== $specialty_query ) {
$columns_val = '3' === $specialty_query ? array( '4_4', '1_2,1_2', '1_3,1_3,1_3' ) : array( '4_4', '1_2,1_2' );
'key' => '_et_pb_row_layout',
$post_type = apply_filters( 'et_pb_show_all_layouts_built_for_post_type', $post_type, $layout_type );
'key' => '_et_pb_built_for_post_type',
'taxonomy' => 'layout_type',
if ( 'all' !== $is_global ) {
$global_operator = 'global' === $is_global ? 'IN' : 'NOT IN';
'terms' => array( 'global' ),
'operator' => $global_operator,
if ( ! empty( $boundaries ) ) {
$start_from = $boundaries[0];
$limit_to = $boundaries[1];
* Filter suppress_filters argument.
* @param boolean $suppress_filters
$suppress_filters = wp_validate_boolean( apply_filters( 'et_pb_show_all_layouts_suppress_filters', $suppress_filters ) );
$query = new WP_Query( array(
'tax_query' => $tax_query,
'post_type' => ET_BUILDER_LAYOUT_POST_TYPE,
'posts_per_page' => $limit_to,
'meta_query' => $meta_query,
'suppress_filters' => $suppress_filters,
if ( ! empty ( $query->posts ) ) {
foreach( $query->posts as $single_post ) {
if ( 'module' === $layout_type ) {
$module_type = get_post_meta( $single_post->ID, '_et_pb_module_type', true );
// add only modules allowed for current user
if ( '' === $module_type || et_pb_is_allowed( $module_type ) ) {
$categories = wp_get_post_terms( $single_post->ID, 'layout_category' );
$scope = wp_get_post_terms( $single_post->ID, 'scope' );
$global_scope = isset( $scope[0] ) ? $scope[0]->slug : 'non_global';
$categories_processed = array();
$this_layout_applicability = '';
if ( ! empty( $categories ) ) {
foreach( $categories as $category_data ) {
$categories_processed[] = esc_html( $category_data->slug );
if ( 'row' === $layout_type ) {
$row_layout = get_post_meta( $single_post->ID, '_et_pb_row_layout', true );
if ( 'layout' === $layout_type ) {
$this_layout_type = 'on' === get_post_meta( $single_post->ID, '_et_pb_predefined_layout', true ) ? 'predefined' : 'library';
$this_layout_applicability = get_post_meta( $single_post->ID, '_et_pb_layout_applicability', true );
// get unsynced global options for module
if ( 'module' === $layout_type && 'false' !== $is_global ) {
$unsynced_options = get_post_meta( $single_post->ID, '_et_pb_excluded_global_options' );
$templates_datum = array(
'ID' => (int) $single_post->ID,
'title' => esc_html( $single_post->post_title ),
'shortcode' => et_core_intentionally_unescaped( $single_post->post_content, 'html' ),
'is_global' => esc_html( $global_scope ),
'layout_type' => esc_html( $layout_type ),
'applicability' => esc_html( $this_layout_applicability ),
'layouts_type' => esc_html( $this_layout_type ),
'module_type' => esc_html( $module_type ),
'categories' => et_core_esc_previously( $categories_processed ),
'row_layout' => esc_html( $row_layout ),
'unsynced_options' => ! empty( $unsynced_options ) ? $utils->esc_array( json_decode( $unsynced_options[0], true ), 'sanitize_text_field' ) : array(),
// Append icon if there's any
if ( $module_type && $template_icon = $utils->array_get( $module_icons, "{$module_type}.icon", false ) ) {
$templates_datum['icon'] = $template_icon;
// Append svg icon if there's any
if ( $module_type && $template_icon_svg = $utils->array_get( $module_icons, "{$module_type}.icon_svg", false ) ) {
$templates_datum['icon_svg'] = $template_icon_svg;
$templates_data[] = $templates_datum;
function et_pb_add_template_meta() {
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
$post_id = ! empty( $_POST['et_post_id'] ) ? sanitize_text_field( $_POST['et_post_id'] ) : '';
if ( empty( $post_id ) || ! current_user_can( 'edit_post', $post_id ) ) {
$value = ! empty( $_POST['et_meta_value'] ) ? sanitize_text_field( $_POST['et_meta_value'] ) : '';
$custom_field = ! empty( $_POST['et_custom_field'] ) ? sanitize_text_field( $_POST['et_custom_field'] ) : '';
$allowlisted_meta_keys = array(
if ( in_array( $custom_field, $allowlisted_meta_keys ) ) {
update_post_meta( $post_id, $custom_field, $value );
add_action( 'wp_ajax_et_pb_add_template_meta', 'et_pb_add_template_meta' );
if ( ! function_exists( 'et_pb_add_new_layout' ) ) {
function et_pb_add_new_layout() {
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'edit_posts' ) ) {
$fields_data = isset( $_POST['et_layout_options'] ) ? trim( $_POST['et_layout_options'] ) : '';
if ( empty( $fields_data ) ) {
$fields_data_json = str_replace( '\\', '', $fields_data );
$fields_data_array = json_decode( $fields_data_json, true );
$processed_data_array = array();
// prepare array with fields data in convenient format
if ( ! empty( $fields_data_array ) ) {
foreach ( $fields_data_array as $index => $field_data ) {
$processed_data_array[ $field_data['field_id'] ] = $field_data['field_val'];
$processed_data_array = apply_filters( 'et_pb_new_layout_data_from_form', $processed_data_array, $fields_data_array );
if ( empty( $processed_data_array ) ) {
$layout_type = et_()->array_get_sanitized( $processed_data_array, 'new_template_type', 'layout' );
$layout_is_global = 'global' === et_()->array_get( $processed_data_array, 'et_pb_template_global', 'not_global' );
if ( 'layout' === $layout_type ) {
// Layouts of type 'layout' are not allowed to be global.
$layout_is_global = false;
'layout_type' => $layout_type,
'layout_selected_cats' => ! empty( $processed_data_array['selected_cats'] ) ? sanitize_text_field( $processed_data_array['selected_cats'] ) : '',
'built_for_post_type' => ! empty( $processed_data_array['et_builder_layout_built_for_post_type'] ) ? sanitize_text_field( $processed_data_array['et_builder_layout_built_for_post_type'] ) : 'page',
'layout_new_cat' => ! empty( $processed_data_array['et_pb_new_cat_name'] ) ? sanitize_text_field( $processed_data_array['et_pb_new_cat_name'] ) : '',
'columns_layout' => ! empty( $processed_data_array['et_columns_layout'] ) ? sanitize_text_field( $processed_data_array['et_columns_layout'] ) : '0',
'module_type' => ! empty( $processed_data_array['et_module_type'] ) ? sanitize_text_field( $processed_data_array['et_module_type'] ) : 'et_pb_unknown',
'layout_scope' => $layout_is_global ? 'global' : 'not_global',
'module_width' => 'regular',
'layout_content' => ! empty( $processed_data_array['template_shortcode'] ) ? $processed_data_array['template_shortcode'] : '',
'layout_name' => ! empty( $processed_data_array['et_pb_new_template_name'] ) ? sanitize_text_field( $processed_data_array['et_pb_new_template_name'] ) : '',
// construct the initial shortcode for new layout
switch ( $args['layout_type'] ) {
$args['layout_content'] = '[et_pb_row template_type="row"][/et_pb_row]';
$args['layout_content'] = '[et_pb_section template_type="section"][et_pb_row][/et_pb_row][/et_pb_section]';
$args['layout_content'] = '[et_pb_module_placeholder selected_tabs="all"]';
case 'fullwidth_module' :
$args['layout_content'] = '[et_pb_fullwidth_module_placeholder selected_tabs="all"]';
$args['module_width'] = 'fullwidth';
$args['layout_type'] = 'module';
case 'fullwidth_section' :
$args['layout_content'] = '[et_pb_section template_type="section" fullwidth="on"][/et_pb_section]';
$args['layout_type'] = 'section';
case 'specialty_section' :
$args['layout_content'] = '[et_pb_section template_type="section" specialty="on" skip_module="true" specialty_placeholder="true"][/et_pb_section]';
$args['layout_type'] = 'section';
$new_layout_meta = et_pb_submit_layout( apply_filters( 'et_pb_new_layout_args', $args ) );
die( et_core_esc_previously( $new_layout_meta ) );
add_action( 'wp_ajax_et_pb_add_new_layout', 'et_pb_add_new_layout' );
if ( ! function_exists( 'et_pb_submit_layout' ) ):
* Handles saving layouts to the database for the builder. Essentially just a wrapper for
* {@see et_pb_create_layout()} that processes the data from the builder before passing it on.
* @param string[] $args {
* @type string $layout_type Accepts 'layout', 'section', 'row', 'module'.
* @type string $layout_selected_cats Categories to which the layout should be added. This should
* be one or more IDs separated by pipe symbols. Example: '1|2|3'.
* @type string $built_for_post_type The post type for which the layout was built.
* @type string $layout_new_cat Name of a new category to which the layout should be added.
* @type string $columns_layout When 'layout_type' is 'row', the row's columns structure. Example: '1_4'.
* @type string $module_type When 'layout_type' is 'module', the module type. Example: 'et_pb_blurb'.
* @type string $layout_scope Optional. The layout's scope. Accepts: 'global', 'not_global'.
* @type string $module_width When 'layout_type' is 'module', the module's width. Accepts: 'regular', 'fullwidth'.
* @type string $layout_content The layout's content (unprocessed shortcodes).
* @type string $layout_name The layout's name.
* @return string $layout_data The 'post_id' and 'edit_link' for the saved layout (JSON encoded).
function et_pb_submit_layout( $args ) {
* Filters the layout data passed to {@see et_pb_submit_layout()}.
* @param string[] $args See {@see et_pb_submit_layout()} for array structure definition.
$args = apply_filters( 'et_pb_submit_layout_args', $args );
$layout_cats_processed = array();
if ( '' !== $args['layout_selected_cats'] ) {
$layout_cats_array = explode( ',', $args['layout_selected_cats'] );
$layout_cats_processed = array_map( 'intval', $layout_cats_array );
if ( 'row' === $args['layout_type'] && '0' !== $args['columns_layout'] ) {
$meta = array_merge( $meta, array( '_et_pb_row_layout' => $args['columns_layout'] ) );
if ( 'module' === $args['layout_type'] ) {
$meta = array_merge( $meta, array( '_et_pb_module_type' => $args['module_type'] ) );
// save unsynced options for global modules. Always empty for new modules.
if ( 'global' === $args['layout_scope'] ) {
$meta = array_merge( $meta, array( '_et_pb_excluded_global_options' => wp_json_encode( array() ) ) );
//et_layouts_built_for_post_type
$meta = array_merge( $meta, array( '_et_pb_built_for_post_type' => $args['built_for_post_type'] ) );
'scope' => $args['layout_scope'],
'layout_type' => $args['layout_type'],
'module_width' => $args['module_width'],
'layout_category' => $layout_cats_processed,
$new_layout_id = et_pb_create_layout( $args['layout_name'], $args['layout_content'], $meta, $tax_input, $args['layout_new_cat'] );
$new_post_data['post_id'] = (int) $new_layout_id;
$new_post_data['edit_link'] = htmlspecialchars_decode( get_edit_post_link( $new_layout_id ) );
$json_post_data = wp_json_encode( $new_post_data );
if ( ! function_exists( 'et_pb_create_layout' ) ) :
function et_pb_create_layout( $name, $content, $meta = array(), $tax_input = array(), $new_category = '' ) {
'post_title' => sanitize_text_field( $name ),
'post_content' => $content,
'post_status' => 'publish',
'post_type' => ET_BUILDER_LAYOUT_POST_TYPE,
$layout_id = wp_insert_post( $layout );
foreach ( $meta as $meta_key => $meta_value ) {
add_post_meta( $layout_id, $meta_key, sanitize_text_field( $meta_value ) );
if ( '' !== $new_category ) {
$new_term_id = wp_insert_term( $new_category, 'layout_category' );
$tax_input['layout_category'][] = (int) $new_term_id['term_id'];
if ( ! empty( $tax_input ) ) {
foreach( $tax_input as $taxonomy => $terms ) {
wp_set_post_terms( $layout_id, $terms, $taxonomy );
function et_pb_save_layout() {
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'edit_posts' ) ) {
if ( empty( $_POST['et_layout_name'] ) ) {
'layout_type' => isset( $_POST['et_layout_type'] ) ? sanitize_text_field( $_POST['et_layout_type'] ) : 'layout',
'layout_selected_cats' => isset( $_POST['et_layout_cats'] ) ? sanitize_text_field( $_POST['et_layout_cats'] ) : '',
'built_for_post_type' => isset( $_POST['et_post_type'] ) ? sanitize_text_field( $_POST['et_post_type'] ) : 'page',
'layout_new_cat' => isset( $_POST['et_layout_new_cat'] ) ? sanitize_text_field( $_POST['et_layout_new_cat'] ) : '',
'columns_layout' => isset( $_POST['et_columns_layout'] ) ? sanitize_text_field( $_POST['et_columns_layout'] ) : '0',
'module_type' => isset( $_POST['et_module_type'] ) ? sanitize_text_field( $_POST['et_module_type'] ) : 'et_pb_unknown',
'layout_scope' => isset( $_POST['et_layout_scope'] ) ? sanitize_text_field( $_POST['et_layout_scope'] ) : 'not_global',
'module_width' => isset( $_POST['et_module_width'] ) ? sanitize_text_field( $_POST['et_module_width'] ) : 'regular',
'layout_content' => isset( $_POST['et_layout_content'] ) ? $_POST['et_layout_content'] : '',
'layout_name' => isset( $_POST['et_layout_name'] ) ? sanitize_text_field( $_POST['et_layout_name'] ) : '',
$new_layout_meta = et_pb_submit_layout( $args );
die( et_core_esc_previously( $new_layout_meta ) );
add_action( 'wp_ajax_et_pb_save_layout', 'et_pb_save_layout' );
function et_pb_get_global_module() {
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'edit_posts' ) ) {
$global_shortcode = array();
$utils = ET_Core_Data_Utils::instance();
$post_id = isset( $_POST['et_global_id'] ) ? (int) $_POST['et_global_id'] : '';
if ( empty( $post_id ) || ! current_user_can( 'edit_post', $post_id ) ) {
$global_autop = isset( $_POST['et_global_autop'] ) ? sanitize_text_field( $_POST['et_global_autop'] ) : 'apply';
if ( ! empty( $post_id ) ) {
$query = new WP_Query( array(
'post_type' => ET_BUILDER_LAYOUT_POST_TYPE,
if ( !empty( $query->post ) ) {
if ( 'skip' === $global_autop ) {
$post_content = $query->post->post_content;
$post_content = $query->post->post_content;
$post_content = et_pb_prep_code_module_for_wpautop( $post_content );