tags automatically when necessary.
*
* @since 4.11.4
*
* @param bool $should_wpautop Whether to apply wpautop. Default true.
* @param string $type The shortcode or module type.
* @param string $content The content to be filtered.
* @param array $item The current shortcode being processed.
*/
$should_wpautop = apply_filters( 'et_fb_should_apply_wpautop', true, $type, $content, $item );
$content = $should_wpautop ? wpautop( $content ) : $content;
}
$output .= $content;
} else {
if ( isset( $item['content'] ) ) {
$_content = $item['content'];
if ( $escape_content_slashes ) {
$_content = str_replace( '\\', '\\\\', $_content );
}
if ( et_is_builder_plugin_active() && in_array( $type, ET_Builder_Element::get_has_content_modules(), true ) ) {
// Wrap content in autop to avoid tagless content on FE due to content is edited on html editor and only
// have one-line without newline wrap which prevent `the_content`'s wpautop filter to properly wrap it.
/**
* Filter whether to apply wpautop to content.
*
* This filter allows customization of whether the wpautop filter should be applied to
* the content of a shortcode. It helps in wrapping content in
tags automatically when necessary.
*
* @since 4.11.4
*
* @param bool $should_wpautop Whether to apply wpautop. Default true.
* @param string $type The shortcode or module type.
* @param string $content The content to be filtered.
* @param array $item The current shortcode being processed.
*/
$should_wpautop = apply_filters( 'et_fb_should_apply_wpautop', true, $type, $_content, $item );
$_content = $should_wpautop ? wpautop( $_content ) : $_content;
}
$output .= $_content;
} else {
$output .= '';
}
}
}
// add the closing tag.
$output .= '[/' . $type . ']';
}
}
return $output;
}
/**
* Ajax Callback :: Render shortcode output.
*/
function et_fb_ajax_render_shortcode() {
if ( ! isset( $_POST['et_pb_render_shortcode_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['et_pb_render_shortcode_nonce'] ), 'et_pb_render_shortcode_nonce' ) ) {
wp_send_json_error();
}
if ( ! current_user_can( 'edit_posts' ) ) {
wp_send_json_error();
}
$utils = ET_Core_Data_Utils::instance();
global $et_pb_predefined_module_index;
$et_pb_predefined_module_index = isset( $_POST['et_fb_module_index'] ) && 'default' !== $_POST['et_fb_module_index'] ? sanitize_text_field( $_POST['et_fb_module_index'] ) : false;
$options = isset( $_POST['options'] ) ? $utils->sanitize_text_fields( $_POST['options'] ) : array(); // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- sanitize_text_fields sanitize the options.
// enforce valid module slugs only
// shortcode slugs need to be allowlisted so as to prevent malicious shortcodes from being generated and run through do_shortcode().
$options['force_valid_slugs'] = true;
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['object'] will not be stored in db.
$object = isset( $_POST['object'] ) ? $_POST['object'] : array();
// convert shortcode array to shortcode string.
$shortcode = et_fb_process_to_shortcode( $object, $options );
// take shortcode string and ensure it's properly sanitized for the purposes of this function.
$shortcode = et_pb_enforce_builder_shortcode( $shortcode );
$output = do_shortcode( $shortcode );
$styles = ET_Builder_Element::get_style();
if ( ! empty( $styles ) ) {
$output .= sprintf(
'',
$styles
);
}
wp_send_json_success( $output );
}
add_action( 'wp_ajax_et_fb_ajax_render_shortcode', 'et_fb_ajax_render_shortcode' );
/**
* Determine current user can save the post.
*
* @param int $post_id Post id.
* @param string $status Post status.
*
* @return bool
*/
function et_fb_current_user_can_save( $post_id, $status = '' ) {
if ( 'page' === get_post_type( $post_id ) ) {
if ( ! current_user_can( 'edit_pages' ) ) {
return false;
}
if ( ! current_user_can( 'publish_pages' ) && 'publish' === $status ) {
return false;
}
if ( ! current_user_can( 'edit_published_pages' ) && 'publish' === get_post_status( $post_id ) ) {
return false;
}
if ( ! current_user_can( 'edit_others_pages' ) && ! current_user_can( 'edit_page', $post_id ) ) {
return false;
}
} else {
if ( ! current_user_can( 'edit_posts' ) ) {
return false;
}
if ( ! current_user_can( 'publish_posts' ) && 'publish' === $status ) {
return false;
}
if ( ! current_user_can( 'edit_published_posts' ) && 'publish' === get_post_status( $post_id ) ) {
return false;
}
if ( ! current_user_can( 'edit_others_posts' ) && ! current_user_can( 'edit_post', $post_id ) ) {
return false;
}
}
// If this is a theme builder layout post type, check divi roles for that capability.
if ( in_array( get_post_type( $post_id ), et_theme_builder_get_layout_post_types(), true ) && ! et_pb_is_allowed( 'theme_builder' ) ) {
return false;
}
return true;
}
/**
* Ajax Callback :: Drop backup/autosave depending on exit type.
*/
function et_fb_ajax_drop_autosave() {
if ( ! isset( $_POST['et_fb_drop_autosave_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['et_fb_drop_autosave_nonce'] ), 'et_fb_drop_autosave_nonce' ) ) {
wp_send_json_error();
}
$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
if ( ! et_fb_current_user_can_save( $post_id ) ) {
wp_send_json_error();
}
$post_author = get_current_user_id();
$autosave = wp_get_post_autosave( $post_id, $post_author );
$autosave_deleted = false;
// delete builder settings autosave.
delete_post_meta( $post_id, "_et_builder_settings_autosave_{$post_author}" );
if ( ! empty( $autosave ) ) {
wp_delete_post_revision( $autosave->ID );
$autosave = wp_get_post_autosave( $post_id, $post_author );
if ( empty( $autosave ) ) {
$autosave_deleted = true;
}
} else {
$autosave_deleted = true;
}
if ( $autosave_deleted ) {
wp_send_json_success();
} else {
wp_send_json_error();
}
}
add_action( 'wp_ajax_et_fb_ajax_drop_autosave', 'et_fb_ajax_drop_autosave' );
/**
* Ajax Callback :: Save layout.
*/
function et_fb_ajax_save() {
if ( ! isset( $_POST['et_fb_save_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['et_fb_save_nonce'] ), 'et_fb_save_nonce' ) ) {
wp_send_json_error();
}
$utils = ET_Core_Data_Utils::instance();
$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
$options = isset( $_POST['options'] ) ? $_POST['options'] : array(); // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['options'] is an array, it's value sanitization is done at the time of accessing value.
$layout_type = isset( $_POST['layout_type'] ) ? sanitize_text_field( $_POST['layout_type'] ) : '';
$is_theme_builder_layout = in_array( get_post_type( $post_id ), et_theme_builder_get_layout_post_types(), true );
// For post content check if user can save post.
if ( ! et_fb_current_user_can_save( $post_id, $utils->array_get_sanitized( $options, 'status' ) ) ) {
wp_send_json_error();
}
$update = false;
if ( ! isset( $_POST['skip_post_update'] ) ) {
$is_layout_block_preview = sanitize_text_field( $utils->array_get( $_POST, 'options.conditional_tags.is_layout_block', '' ) );
$block_id = sanitize_title( $utils->array_get( $_POST, 'options.current_page.blockId', '' ) );
$shortcode_data = isset( $_POST['modules'] ) ? json_decode( stripslashes( $_POST['modules'] ), true ) : array(); // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- modules string will be sanitized at the time of saving in the db.
// Cast as bool if falsey; blockId is retrieved from ajax request, and
// already return empty string (falsey) if no value found. Nevertheless let's be more safe.
if ( ! $block_id ) {
$block_id = false;
}
// Cast as bool if falsey; is_layout_block_preview is retrieved from ajax request, and
// already return empty string (falsey) if no value found. Nevertheless let's be more safe.
if ( ! $is_layout_block_preview ) {
$is_layout_block_preview = false;
}
$built_for_type = get_post_meta( $post_id, '_et_pb_built_for_post_type', true );
if ( ! $built_for_type && ! $is_layout_block_preview ) {
update_post_meta( $post_id, '_et_pb_built_for_post_type', 'page' );
}
// If Default Editor is used for Post Content, and Post Content is not edited,
// handleAjaxSave will pass return_to_default_editor,
// and in that case we need reactivate the default editor for the post.
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput.InputNotSanitized -- input is inside isset() function so its value is not used
if ( isset( $_POST['return_to_default_editor'] ) && rest_sanitize_boolean( $_POST['return_to_default_editor'] ) ) {
update_post_meta( $post_id, '_et_pb_use_builder', 'off' );
update_post_meta( $post_id, '_et_pb_show_page_creation', 'on' );
// Get old content and if we should return to the Default Editor.
$post_content = get_post_meta( $post_id, '_et_pb_old_content', true );
} else {
if ( ! $is_layout_block_preview ) {
update_post_meta( $post_id, '_et_pb_use_builder', 'on' );
}
$post_content = et_fb_process_to_shortcode( $shortcode_data, $options, $layout_type, true, true );
}
// Store a copy of the sanitized post content in case wpkses alters it since that
// would cause our check at the end of this function to fail.
$sanitized_content = sanitize_post_field( 'post_content', $post_content, $post_id, 'db' );
// Exit early for layout block update; builder should not actually save post content in this scenario
// Update post meta and let it is being used to update layoutContent on editor.
if ( $is_layout_block_preview && $block_id ) {
$layout_preview_meta_key = "_et_block_layout_preview_{$block_id}";
$saved_layout = get_post_meta( $post_id, $layout_preview_meta_key, true );
// If saved layout is identical to the the layout sent via AJAX, return send json success;
// this is needed because update_post_meta() returns false if the saved layout is identical
// to the the one given as param.
if ( ! empty( $saved_layout ) && $saved_layout === $post_content ) {
wp_send_json_success(
array(
'save_verification' => true,
)
);
wp_die();
}
$update = update_post_meta( $post_id, $layout_preview_meta_key, $post_content );
if ( $update ) {
wp_send_json_success(
array(
'save_verification' => true,
)
);
} else {
wp_send_json_error();
}
wp_die();
}
$update = wp_update_post(
array(
'ID' => $post_id,
'post_content' => $post_content,
'post_status' => $utils->array_get_sanitized( $options, 'status' ),
)
);
}
// update Global modules with selective sync.
if ( 'module' === $layout_type && isset( $_POST['unsyncedGlobalSettings'] ) && 'none' !== $_POST['unsyncedGlobalSettings'] ) {
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['unsyncedGlobalSettings'] will be sanitized before storing in db.
$unsynced_options = stripslashes( $_POST['unsyncedGlobalSettings'] );
update_post_meta( $post_id, '_et_pb_excluded_global_options', sanitize_text_field( $unsynced_options ) );
}
// check if there is an autosave that is newer.
$post_author = get_current_user_id();
// Store one autosave per author. If there is already an autosave, overwrite it.
$autosave = wp_get_post_autosave( $post_id, $post_author );
if ( ! empty( $autosave ) ) {
wp_delete_post_revision( $autosave->ID );
}
if ( isset( $_POST['settings'] ) && is_array( $_POST['settings'] ) ) {
et_builder_update_settings( $_POST['settings'], $post_id ); // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['settings'] is an array, it's value sanitization is done inside function at the time of accessing value.
}
if ( isset( $_POST['preferences'] ) && is_array( $_POST['preferences'] ) && ! $is_theme_builder_layout ) {
$app_preferences = et_fb_app_preferences_settings();
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['et_builder_mode'] value used in the comparision.
$limited_prefix = ! empty( $_POST['et_builder_mode'] ) && 'limited' === $_POST['et_builder_mode'] ? 'limited_' : '';
foreach ( $app_preferences as $preference_key => $preference_data ) {
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $preference_value will be sanitized before saving in db.
$preference_value = isset( $_POST['preferences'][ $preference_key ] ) && isset( $_POST['preferences'][ $preference_key ]['value'] ) ? $_POST['preferences'][ $preference_key ]['value'] : $preference_data['default'];
// sanitize based on type.
switch ( $preference_data['type'] ) {
case 'int':
$preference_value = absint( $preference_value );
break;
case 'bool':
$preference_value = 'true' === $preference_value ? 'true' : 'false';
break;
default:
$preference_value = sanitize_text_field( $preference_value );
break;
}
$preference_value_max_length = et_()->array_get( $preference_data, 'max_length', 0 );
if ( $preference_value && is_numeric( $preference_value_max_length ) && $preference_value_max_length > 0 ) {
$preference_value = substr( $preference_value, 0, $preference_value_max_length );
}
$option_name = 'et_fb_pref_' . $preference_key;
if ( in_array( $preference_key, et_fb_unsynced_preferences(), true ) ) {
$option_name = 'et_fb_pref_' . $limited_prefix . $preference_key;
}
et_update_option( $option_name, $preference_value );
}
}
// Clear AB Testing stats & transient data.
if ( isset( $_POST['ab_testing'] ) && isset( $_POST['ab_testing']['is_clear_stats'] ) && 'true' === $_POST['ab_testing']['is_clear_stats'] && et_pb_is_allowed( 'ab_testing' ) ) {
et_pb_ab_remove_stats( $post_id );
et_pb_ab_clear_cache_handler( $post_id );
}
do_action( 'et_save_post', $post_id );
if ( $update ) {
if ( ! empty( $_POST['et_builder_version'] ) ) {
update_post_meta( $post_id, '_et_builder_version', sanitize_text_field( $_POST['et_builder_version'] ) );
}
// Get saved post, verify its content against the one that is being sent.
$saved_post = get_post( $update );
$saved_post_content = $saved_post->post_content;
$builder_post_content = stripslashes( $sanitized_content );
// Get rendered post content only if it's needed.
$return_rendered_content = sanitize_text_field( $utils->array_get( $_POST, 'options.return_rendered_content', 'false' ) );
$rendered_post_content = 'true' === $return_rendered_content ? do_shortcode( $saved_post_content ) : '';
// If `post_content` column on wp_posts table doesn't use `utf8mb4` charset, the saved post
// content's emoji will be encoded which means the check of saved post_content vs
// builder's post_content will be false; Thus check the charset of `post_content` column
// first then encode the builder's post_content if needed
// @see https://make.wordpress.org/core/2015/04/02/omg-emoji-%f0%9f%98%8e/
// @see https://make.wordpress.org/core/2015/04/02/the-utf8mb4-upgrade/.
global $wpdb;
if ( 'utf8' === $wpdb->get_col_charset( $wpdb->posts, 'post_content' ) ) {
$builder_post_content = wp_encode_emoji( $builder_post_content );
}
$saved_verification = $saved_post_content === $builder_post_content;
if ( $saved_verification ) {
// Strip non-printable characters to ensure preg_match_all operation work properly.
$post_content_cleaned = preg_replace( '/[\x00-\x1F\x7F]/u', '', $saved_post->post_content );
preg_match_all( '/\[et_pb_section(.*?)?\]\[et_pb_row(.*?)?\]\[et_pb_column(.*?)?\](.+?)\[\/et_pb_column\]\[\/et_pb_row\]\[\/et_pb_section\]/m', $post_content_cleaned, $matches );
if ( isset( $matches[4] ) && ! empty( $matches[4] ) ) {
// Set page creation flow to off.
update_post_meta( $post_id, '_et_pb_show_page_creation', 'off' );
} else {
delete_post_meta( $post_id, '_et_pb_show_page_creation' );
}
}
/**
* Hook triggered when the Post is updated.
*
* @param int $post_id Post ID.
*
* @since 3.29
*/
do_action( 'et_update_post', $post_id );
wp_send_json_success(
array(
'status' => get_post_status( $update ),
'save_verification' => apply_filters( 'et_fb_ajax_save_verification_result', $saved_verification ),
'rendered_content' => $rendered_post_content,
)
);
} elseif ( isset( $_POST['skip_post_update'] ) ) {
wp_send_json_success();
} else {
wp_send_json_error();
}
}
add_action( 'wp_ajax_et_fb_ajax_save', 'et_fb_ajax_save' );
/**
* Ajax Callback :: Convert fb object into shortcode.
*/
function et_fb_get_shortcode_from_fb_object() {
if ( ! et_core_security_check( 'edit_posts', 'et_fb_convert_to_shortcode_nonce', 'et_fb_convert_to_shortcode_nonce', '_POST', false ) ) {
wp_send_json_error();
}
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['modules'] will not be stored in db.
$shortcode_data = isset( $_POST['modules'] ) ? json_decode( stripslashes( $_POST['modules'] ), true ) : array();
$layout_type = isset( $_POST['layout_type'] ) ? sanitize_text_field( $_POST['layout_type'] ) : '';
$post_content = et_fb_process_to_shortcode( $shortcode_data, array(), $layout_type );
// Get rendered post content only if it's needed.
$utils = ET_Core_Data_Utils::instance();
$return_rendered_content = sanitize_text_field( $utils->array_get( $_POST, 'options.return_rendered_content', 'false' ) );
$rendered_post_content = 'true' === $return_rendered_content ? do_shortcode( $post_content ) : '';
wp_send_json_success(
array(
'processed_content' => $post_content,
'rendered_content' => $rendered_post_content,
)
);
}
add_action( 'wp_ajax_et_fb_get_shortcode_from_fb_object', 'et_fb_get_shortcode_from_fb_object' );
/**
* Ajax Callback :: Convert shortcode into HTML.
*/
function et_fb_get_html_from_shortcode() {
if ( ! et_core_security_check( 'edit_posts', 'et_fb_shortcode_to_html_nonce', 'et_fb_shortcode_to_html_nonce', '_POST', false ) ) {
wp_send_json_error();
}
// phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- $_POST['modules'] will not be stored in db.
$post_content = isset( $_POST['content'] ) ? stripslashes( $_POST['content'] ) : '';
// Get rendered post content by shortcode.
$rendered_post_content = do_shortcode( $post_content );
wp_send_json_success(
array(
'rendered_content' => $rendered_post_content,
)
);
}
add_action( 'wp_ajax_et_fb_get_html_from_shortcode', 'et_fb_get_html_from_shortcode' );
/**
* Ajax Callback :: Save library modules.
*/
function et_fb_save_layout() {
if ( ! isset( $_POST['et_fb_save_library_modules_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['et_fb_save_library_modules_nonce'] ), 'et_fb_save_library_modules_nonce' ) ) {
die( -1 );
}
if ( ! current_user_can( 'edit_posts' ) ) {
die( -1 );
}
if ( empty( $_POST['et_layout_name'] ) ) {
die( -1 );
}
$post_type = sanitize_text_field( et_()->array_get( $_POST, 'et_post_type', 'page' ) );
if ( et_theme_builder_is_layout_post_type( $post_type ) ) {
// Treat TB layouts as normal posts when storing layouts from the library.
$post_type = 'page';
}
$args = array(
'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'] ) : '',
'layout_selected_tags' => isset( $_POST['et_layout_tags'] ) ? sanitize_text_field( $_POST['et_layout_tags'] ) : '',
'built_for_post_type' => $post_type,
'layout_new_cat' => isset( $_POST['et_layout_new_cat'] ) ? sanitize_text_field( $_POST['et_layout_new_cat'] ) : '',
'layout_new_tag' => isset( $_POST['et_layout_new_tag'] ) ? sanitize_text_field( $_POST['et_layout_new_tag'] ) : '',
'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'] ) ? et_fb_process_to_shortcode( json_decode( stripslashes( $_POST['et_layout_content'] ), true ) ) : '', // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- The `$_POST['et_layout_content']` will be sanitized before saving into db.
'layout_name' => isset( $_POST['et_layout_name'] ) ? sanitize_text_field( $_POST['et_layout_name'] ) : '',
);
$new_layout_meta = et_pb_submit_layout( $args );
$updated_terms = array();
foreach ( [ 'layout_category', 'layout_tag' ] as $taxonomy ) {
$raw_terms_array = apply_filters( 'et_pb_new_layout_cats_array', get_terms( $taxonomy, array( 'hide_empty' => false ) ) );
$clean_terms_array = array();
if ( is_array( $raw_terms_array ) && ! empty( $raw_terms_array ) ) {
foreach ( $raw_terms_array as $term ) {
$clean_terms_array[] = array(
'name' => html_entity_decode( $term->name ),
'id' => $term->term_id,
'slug' => $term->slug,
);
}
}
$updated_terms[ $taxonomy ] = $clean_terms_array;
}
$data = array(
'layout_data' => json_decode( $new_layout_meta, true ),
'updated_terms' => $updated_terms,
);
die( wp_json_encode( et_core_esc_previously( $data ) ) );
}
add_action( 'wp_ajax_et_fb_save_layout', 'et_fb_save_layout' );
/**
* Ajax Callback :: Process shortcode to exported layout object.
*/
function et_fb_get_cloud_item_content() {
if ( ! isset( $_POST['et_fb_save_cloud_item_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['et_fb_save_cloud_item_nonce'] ), 'et_fb_save_cloud_item_nonce' ) ) {
die( -1 );
}
if ( ! current_user_can( 'edit_posts' ) ) {
die( -1 );
}
$layout_type = isset( $_POST['et_layout_type'] ) ? sanitize_text_field( $_POST['et_layout_type'] ) : '';
$layout_content = isset( $_POST['et_layout_content'] ) ? et_fb_process_to_shortcode( json_decode( stripslashes( $_POST['et_layout_content'] ), true ), array(), $layout_type ) : ''; // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- The `$_POST['et_layout_content']` will be sanitized before saving into db.
$exported_shortcode = get_exported_content( $layout_content );
die( wp_json_encode( array( 'shortcode' => $exported_shortcode ) ) );
}
add_action( 'wp_ajax_et_fb_get_cloud_item_content', 'et_fb_get_cloud_item_content' );
/**
* Prepare shortcode for exporting.
*
* @since 4.17.0
*
* @param string $shortcode Shortcode to process.
*
* @return array
*/
function get_exported_content( $shortcode ) {
// Set faux $_POST value that is required by portability.
$_POST['post'] = '1';
$_POST['content'] = $shortcode;
// Remove page value if it is equal to `false`, avoiding paginated images not accidentally triggered.
if ( isset( $_POST['page'] ) && false === $_POST['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification -- This function does not change any state, and is therefore not susceptible to CSRF.
unset( $_POST['page'] ); // phpcs:ignore WordPress.Security.NonceVerification -- This function does not change any state, and is therefore not susceptible to CSRF.
}
$portability = et_core_portability_load( 'et_builder' );
// Export the content.
return $portability->export( true, true );
}
/**
* Ajax Callback :: Process shortcode.
*/
function et_fb_prepare_shortcode() {
if ( ! isset( $_POST['et_fb_prepare_shortcode_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( $_POST['et_fb_prepare_shortcode_nonce'] ), 'et_fb_prepare_shortcode_nonce' ) ) {
wp_send_json_error();
}
if ( ! current_user_can( 'edit_posts' ) ) {
die( -1 );
}
// phpcs:disable ET.Sniffs.ValidatedSanitizedInput -- The `$_POST['et_page_content']` and `$_POST['apply_global_presets']` will not be stored on db.
$content = isset( $_POST['et_page_content'] ) ? json_decode( stripslashes( $_POST['et_page_content'] ), true ) : '';
$apply_global_presets = isset( $_POST['apply_global_presets'] ) ? wp_validate_boolean( $_POST['apply_global_presets'] ) : false;
// phpcs:enable
$options = array(
'apply_global_presets' => $apply_global_presets,
);
$result = $content ? et_fb_process_to_shortcode( $content, $options, '', false ) : '';
die( wp_json_encode( array( 'shortcode' => $result ) ) );
}
add_action( 'wp_ajax_et_fb_prepare_shortcode', 'et_fb_prepare_shortcode' );
/**
* Ajax Callback :: Save library module.
*/
function et_fb_update_layout() {
if ( ! isset( $_POST['et_fb_save_library_modules_nonce'] ) || ! wp_verify_nonce( $_POST['et_fb_save_library_modules_nonce'], 'et_fb_save_library_modules_nonce' ) ) { // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput -- The nonce value is used only for comparision in the `wp_verify_nonce`.
die( -1 );
}
if ( ! current_user_can( 'edit_posts' ) ) {
die( -1 );
}
$post_id = isset( $_POST['et_template_post_id'] ) ? absint( $_POST['et_template_post_id'] ) : '';
if ( ! current_user_can( 'edit_post', $post_id ) ) {
die( -1 );
}
// phpcs:disable ET.Sniffs.ValidatedSanitizedInput -- Following $_POST values will be sanitized before storing in db.
$post_content = isset( $_POST['et_layout_content'] ) ? json_decode( stripslashes( $_POST['et_layout_content'] ), true ) : array();
$new_content = isset( $_POST['et_layout_content'] ) ? et_fb_process_to_shortcode( $post_content ) : '';
$excluded_global_options = isset( $_POST['et_excluded_global_options'] ) ? stripslashes( $_POST['et_excluded_global_options'] ) : array();
$is_saving_global_module = isset( $_POST['et_saving_global_module'] ) ? sanitize_text_field( $_POST['et_saving_global_module'] ) : '';
// phpcs:enable
if ( '' !== $post_id ) {
$update = array(
'ID' => $post_id,
'post_content' => $new_content,
);
$result = wp_update_post( $update );
if ( ! $result || is_wp_error( $result ) ) {
wp_send_json_error();
}
ET_Core_PageResource::remove_static_resources( 'all', 'all' );
// update list of unsynced options for global module.
if ( 'true' === $is_saving_global_module ) {
update_post_meta( $post_id, '_et_pb_excluded_global_options', sanitize_text_field( $excluded_global_options ) );
}
}
die();
}
add_action( 'wp_ajax_et_fb_update_layout', 'et_fb_update_layout' );
/**
* Ajax Callback :: Return requested attachments from media library.
*/
function et_fb_fetch_attachments() {
et_core_security_check( 'edit_posts', 'et_fb_fetch_attachments', 'et_fb_fetch_attachments' );
$ids = ET_Core_Data_Utils::instance()->array_get( $_POST, 'ids' );
if ( empty( $ids ) ) {
wp_send_json( null );
} else {
$attachments = get_posts(
array(
'posts_per_page' => - 1,
'include' => $ids,
'post_type' => 'attachment',
)
);
foreach ( $attachments as $index => $attachment ) {
$metadata = array();
foreach ( get_intermediate_image_sizes() as $size ) {
$metadata[ $size ] = wp_get_attachment_image_src( $attachment->ID, $size );
}
$attachments[ $index ] = array_merge(
get_object_vars( $attachment ),
array(
'metadata' => $metadata,
)
);
}
wp_send_json( $attachments );
}
die();
}
add_action( 'wp_ajax_et_fb_fetch_attachments', 'et_fb_fetch_attachments' );
if ( ! function_exists( 'et_fb_disable_product_tour' ) ) :
/**
* Saving User Specific Tour status.
*/
function et_fb_disable_product_tour() {
do_action( 'et_fb_disable_product_tour' );
if ( ! et_core_security_check_passed( 'edit_posts' ) ) {
ET_Core_Logger::debug( 'Unable to disable product tour. Security check failed!' );
return;
}
$user_id = (int) get_current_user_id();
$product_tour_status = et_get_option( 'product_tour_status', [] );
$all_product_settings = is_array( $product_tour_status ) ? $product_tour_status : [];
$all_product_settings[ $user_id ] = 'off';
et_update_option( 'product_tour_status', $all_product_settings );
}
endif;
if ( ! function_exists( 'et_builder_include_categories_option' ) ) :
/**
* Generate output string for `include_categories` option used in backbone template.
*
* @param array $args Arguments to get project categories.
* @param string $default_category @todo Add parameter doc.
* @return string
*/
function et_builder_include_categories_option( $args = array(), $default_category = '' ) {
$custom_items = array();
if ( ! empty( $args['custom_items'] ) ) {
$custom_items = $args['custom_items'];
unset( $args['custom_items'] );
}
$defaults = array(
'use_terms' => true,
'term_name' => 'project_category',
'field_name' => 'et_pb_include_categories',
);
$defaults = apply_filters( 'et_builder_include_categories_defaults', $defaults );
$args = wp_parse_args( $args, $defaults );
$args['field_name'] = esc_attr( $args['field_name'] );
$term_args = apply_filters( 'et_builder_include_categories_option_args', array( 'hide_empty' => false ) );
$output = "\t<% var {$args['field_name']}_temp = typeof data !== 'undefined' && typeof data.{$args['field_name']} !== 'undefined' ? data.{$args['field_name']}.split( ',' ) : ['" . esc_html( $default_category ) . "']; {$args['field_name']}_temp = typeof data === 'undefined' && typeof {$args['field_name']} !== 'undefined' ? {$args['field_name']}.split( ',' ) : {$args['field_name']}_temp; %>\n";
if ( $args['use_terms'] ) {
$cats_array = get_terms( $args['term_name'], $term_args );
} else {
$cats_array = get_categories( apply_filters( 'et_builder_get_categories_args', 'hide_empty=0' ) );
}
$cats_array = array_merge( $custom_items, $cats_array );
if ( empty( $cats_array ) ) {
$taxonomy_type = $args['use_terms'] ? $args['term_name'] : 'category';
$taxonomy = get_taxonomy( $taxonomy_type );
$labels = get_taxonomy_labels( $taxonomy );
$output = sprintf( '
" . $output . '
';
return apply_filters( 'et_builder_include_categories_option_html', $output );
}
endif;
if ( ! function_exists( 'et_builder_include_categories_shop_option' ) ) :
/**
* Generate output string for `include_shop_categories` option used in backbone template.
*
* @param array $args arguments to get shop categories.
* @return string
*/
function et_builder_include_categories_shop_option( $args = array() ) {
if ( ! class_exists( 'WooCommerce' ) ) {
return '';
}
$output = "\t<% var et_pb_include_categories_shop_temp = typeof data !== 'undefined' && typeof data.et_pb_include_categories !== 'undefined' ? data.et_pb_include_categories.split( ',' ) : []; et_pb_include_categories_shop_temp = typeof data === 'undefined' && typeof et_pb_include_categories !== 'undefined' ? et_pb_include_categories.split( ',' ) : et_pb_include_categories_shop_temp; %>\n";
$product_categories = et_builder_get_shop_categories( $args );
$output .= '';
if ( is_array( $product_categories ) && ! empty( $product_categories ) ) {
foreach ( $product_categories as $category ) {
if ( is_object( $category ) && is_a( $category, 'WP_Term' ) ) {
$contains = sprintf(
'<%%= _.contains( et_pb_include_categories_shop_temp, "%1$s" ) ? checked="checked" : "" %%>',
esc_html( $category->term_id )
);
$output .= sprintf(
'%4$s
',
esc_attr( $category->term_id ),
esc_html( $category->name ),
$contains,
"\n\t\t\t\t\t"
);
}
}
}
$output .= '
';
return apply_filters( 'et_builder_include_categories_option_html', $output );
}
endif;
if ( ! function_exists( 'et_divi_get_projects' ) ) :
/**
* Return projects.
*
* @param array $args WP_Query arguments.
*/
function et_divi_get_projects( $args = array() ) {
$default_args = array(
'post_type' => 'project',
);
$args = wp_parse_args( $args, $default_args );
return new WP_Query( $args );
}
endif;
if ( ! function_exists( 'et_pb_extract_items' ) ) :
/**
* Return pricing table items html.
*
* @param string $content Content.
*/
function et_pb_extract_items( $content ) {
$output = '';
$first_character = '';
$lines = array_filter( explode( "\n", str_replace( array( '',
( $is_builder_used ? ' et_pb_builder_is_used' : '' ),
et_core_esc_previously( $buttons ),
( $is_builder_used ? ' class="et_pb_post_body_hidden"' : '' ),
( et_builder_bfb_enabled() ? ' style="opacity: 0;"' : '' )
);
} else {
printf(
'
',
( $is_builder_used ? ' class="et_pb_post_body_hidden"' : '' ),
( $is_builder_used ? ' et_pb_builder_is_used' : '' ),
( et_builder_bfb_enabled() ? ' style="opacity: 0;"' : '' )
);
}
if ( ! et_builder_bfb_enabled() ) {
$module_fields_dependencies = wp_json_encode( ET_Builder_Element::get_field_dependencies( $post->post_type ) );
echo et_core_esc_previously(
"
"
);
}
?>
ID ); ?>
ID ); ?>
ID ) ) {
return;
}
echo '
';
}
/**
* Setup Divi Builder in BFB.
*/
function et_pb_setup_main_editor() {
if ( ! et_core_is_gutenberg_enabled() ) {
add_action( 'edit_form_after_title', 'et_pb_before_main_editor' );
add_action( 'edit_form_after_editor', 'et_pb_after_main_editor' );
}
}
add_action( 'add_meta_boxes', 'et_pb_setup_main_editor', 11 );
/**
* Load scripts and styles in admin.
*
* @param string $hook The current admin page.
*/
function et_pb_admin_scripts_styles( $hook ) {
global $typenow, $pagenow;
// load css file for the Divi menu.
wp_enqueue_style( 'library-menu-styles', ET_BUILDER_URI . '/styles/library_menu.css', array(), ET_BUILDER_VERSION );
if ( 'widgets.php' === $hook ) {
wp_enqueue_script( 'et_pb_widgets_js', ET_BUILDER_URI . '/scripts/ext/widgets.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
$et_pb_options_admin = array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'et_admin_load_nonce' => wp_create_nonce( 'et_admin_load_nonce' ),
'widget_info' => sprintf(
'
',
esc_html__( 'Here you can create new widget areas for use in the Sidebar module', 'et_builder' ),
esc_html__( 'Note: Naming your widget area "sidebar 1", "sidebar 2", "sidebar 3", "sidebar 4" or "sidebar 5" will cause conflicts with this theme', 'et_builder' ),
esc_html__( 'Widget Name', 'et_builder' ),
esc_html__( 'Create', 'et_builder' )
),
'delete_string' => esc_html__( 'Delete', 'et_builder' ),
);
wp_localize_script( 'et_pb_widgets_js', 'et_pb_options', apply_filters( 'et_pb_options_admin', $et_pb_options_admin ) );
wp_enqueue_style( 'et_pb_widgets_css', ET_BUILDER_URI . '/styles/widgets.css', array(), ET_BUILDER_VERSION );
return;
}
// Do not enqueue BB assets if GB is active on this page.
if ( et_core_is_gutenberg_enabled() ) {
return;
}
if ( ! in_array( $hook, array( 'post-new.php', 'post.php' ), true ) ) {
return;
}
/*
* Load the builder javascript and css files for custom post types
* custom post types can be added using et_builder_post_types filter
*/
$post_types = et_builder_get_builder_post_types();
$on_enabled_post_type = isset( $typenow ) && in_array( $typenow, $post_types, true );
$on_enabled_post = isset( $pagenow ) && 'post.php' === $pagenow && isset( $_GET['post'] ) && et_builder_enabled_for_post( intval( $_GET['post'] ) ); // phpcs:ignore WordPress.Security.NonceVerification -- This function does not change any state, and is therefore not susceptible to CSRF.
if ( $on_enabled_post_type || $on_enabled_post ) {
wp_enqueue_style( 'et_bb_bfb_common', ET_BUILDER_URI . '/styles/bb_bfb_common.css', array(), ET_BUILDER_VERSION );
// Boot one builders assets or the other.
if ( et_builder_bfb_enabled() ) {
et_bfb_enqueue_scripts();
// do not load BFB if builder is disabled on page.
if ( ! et_pb_is_pagebuilder_used( get_the_ID() ) ) {
return;
}
// BFB loads builder modal outside the iframe using react portal. external scripts
// that is used on modal needs to be enqueued.
et_builder_enqueue_assets_main();
et_builder_enqueue_open_sans();
$secondary_css_bundles = glob( ET_BUILDER_DIR . 'frontend-builder/build/bundle.*.css' );
if ( $secondary_css_bundles ) {
$bundles = array( 'et-frontend-builder' );
foreach ( $secondary_css_bundles as $css_bundle ) {
$slug = basename( $css_bundle, '.css' );
$parts = explode( '.', $slug, -1 );
// Drop "bundle" from array.
array_shift( $parts );
$slug = implode( '-', $parts );
et_fb_enqueue_bundle( "et-fb-{$slug}", basename( $css_bundle ), $bundles, null );
$bundles[] = $slug;
}
}
// Hooks for theme/plugin specific styling which complements visual builder.
do_action( 'et_bfb_boot' );
} else {
et_pb_add_builder_page_js_css();
}
}
}
add_action( 'admin_enqueue_scripts', 'et_pb_admin_scripts_styles', 10, 1 );
/**
* Disable emoji detection script on edit page which has Backend Builder on it.
* WordPress automatically replaces emoji with plain image for backward compatibility
* on older browsers. This causes issue when emoji is used on header or other input
* text field because (when the modal is saved, shortcode is generated, and emoji
* is being replaced with plain image) it creates incorrect attribute markup
* such as `title="I

WP"` and causes
* the whole input text value to be disappeared
*
* @return void
*/
function et_pb_remove_emoji_detection_script() {
// phpcs:disable WordPress.Security.NonceVerification -- This function does not change any state, and is therefore not susceptible to CSRF.
global $pagenow;
$disable_emoji_detection = false;
// Disable emoji detection script on editing page which has Backend Builder
// global $post isn't available at admin_init, so retrieve $post data manually.
if ( 'post.php' === $pagenow && isset( $_GET['post'] ) ) {
$post_id = (int) $_GET['post'];
$post = get_post( $post_id );
if ( is_a( $post, 'WP_POST' ) && et_builder_enabled_for_post( $post->ID ) ) {
$disable_emoji_detection = true;
}
}
// Disable emoji detection script on post new page which has Backend Builder.
$has_post_type_query = isset( $_GET['post_type'] );
if ( 'post-new.php' === $pagenow && ( ! $has_post_type_query || ( $has_post_type_query && in_array( $_GET['post_type'], et_builder_get_builder_post_types(), true ) ) ) ) {
$disable_emoji_detection = true;
}
if ( $disable_emoji_detection ) {
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
}
// phpcs:enable
}
add_action( 'admin_init', 'et_pb_remove_emoji_detection_script' );
/**
* Disable emoji detection script on visual builder
* WordPress automatically replaces emoji with plain image for backward compatibility
* on older browsers. This causes issue when emoji is used on header or other input
* text field because the staticize emoji creates HTML markup which appears to be
* invalid on input[type="text"] field such as `title="I

WP"` and causes the input text value to be escaped and
* disappeared
*
* @return void
*/
function et_fb_remove_emoji_detection_script() {
global $post;
// Disable emoji detection script on visual builder. React's auto escaping will
// remove all staticized emoji when being opened on modal's input field.
if ( isset( $post->ID ) && et_fb_is_enabled( $post->ID ) ) {
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
}
}
add_action( 'wp', 'et_fb_remove_emoji_detection_script' );
/**
* If the builder is used for the page, get rid of random p tags.
*
* @param string $content content.
*
* @return string|string[]|null
*/
function et_pb_fix_builder_shortcodes( $content ) {
if ( is_admin() ) {
// ET_Builder_Element is not loaded in the administration and some plugins call
// the_content there (e.g. WP File Manager).
return $content;
}
$is_theme_builder = ET_Builder_Element::is_theme_builder_layout();
$is_singular = is_singular() && 'on' === get_post_meta( get_the_ID(), '_et_pb_use_builder', true );
// if the builder is used for the page, get rid of random p tags.
if ( $is_theme_builder || $is_singular ) {
$content = et_pb_fix_shortcodes( $content );
}
return $content;
}
add_filter( 'the_content', 'et_pb_fix_builder_shortcodes' );
add_filter( 'et_builder_render_layout', 'et_pb_fix_builder_shortcodes' );
/**
* Prepare code module for wpautop.
*
* @param string $content content.
*
* @return string|string[]|null
*/
function et_pb_the_content_prep_code_module_for_wpautop( $content ) {
if ( 'on' === get_post_meta( get_the_ID(), '_et_pb_use_builder', true ) ) {
$content = et_pb_prep_code_module_for_wpautop( $content );
}
return $content;
}
add_filter( 'the_content', 'et_pb_the_content_prep_code_module_for_wpautop', 0 );
add_filter( 'et_builder_render_layout', 'et_pb_the_content_prep_code_module_for_wpautop', 0 );
if ( ! function_exists( 'et_pb_generate_new_layout_modal' ) ) {
/**
* Generate the html for "Add new template" Modal in Library.
*
* @return mixed|void
*/
function et_pb_generate_new_layout_modal() {
$template_type_option_output = '';
$layout_cat_option_output = '';
$layout_cats_list = '';
$layout_tags_list = '';
$template_type_options_list = '';
$new_layout_template_types = array(
'module' => esc_html__( 'Module', 'et_builder' ),
'fullwidth_module' => esc_html__( 'Fullwidth Module', 'et_builder' ),
'row' => esc_html__( 'Row', 'et_builder' ),
'section' => esc_html__( 'Section', 'et_builder' ),
'fullwidth_section' => esc_html__( 'Fullwidth Section', 'et_builder' ),
'specialty_section' => esc_html__( 'Specialty Section', 'et_builder' ),
'layout' => et_builder_i18n( 'Layout' ),
);
$template_type_options = apply_filters( 'et_pb_new_layout_template_types', $new_layout_template_types );
// construct output for the template type option.
if ( ! empty( $template_type_options ) ) {
foreach ( $template_type_options as $option_id => $option_name ) {
$template_type_options_list .= sprintf(
'
',
esc_attr( $option_id ),
esc_html( $option_name )
);
}
$template_type_option_output = sprintf(
'
',
esc_html__( 'Layout Type', 'et_builder' ),
$template_type_options_list
);
}
$template_global_option_output = apply_filters(
'et_pb_new_layout_global_option',
sprintf(
'
',
esc_html__( 'Save as Global', 'et_builder' )
)
);
$layout_categories = apply_filters( 'et_pb_new_layout_cats_array', get_terms( 'layout_category', array( 'hide_empty' => false ) ) );
if ( is_array( $layout_categories ) && ! empty( $layout_categories ) ) {
foreach ( $layout_categories as $category ) {
$layout_cats_list .= sprintf(
'
',
esc_html( $category->name ),
esc_attr( $category->term_id )
);
}
}
$layout_tags = apply_filters( 'et_pb_new_layout_tags_array', get_terms( 'layout_tag', array( 'hide_empty' => false ) ) );
if ( is_array( $layout_tags ) && ! empty( $layout_tags ) ) {
foreach ( $layout_tags as $tag ) {
$layout_tags_list .= sprintf(
'
',
esc_html( $tag->name ),
esc_attr( $tag->term_id )
);
}
}
// Construct output for the layout Tag option.
$layout_cat_option_output = sprintf(
'
%3$s
',
esc_html__( 'Add To Categories', 'et_builder' ),
esc_html__( 'Create new Category', 'et_builder' ),
$layout_cats_list
);
// Construct output for the layout Tag option.
$layout_tag_option_output = sprintf(
'
%3$s
',
esc_html__( 'Add To Tags', 'et_builder' ),
esc_html__( 'Create new Tag', 'et_builder' ),
$layout_tags_list
);
$output = sprintf(
'
',
esc_html__( 'Add New Layout', 'et_builder' ),
esc_html__( 'Layout Name', 'et_builder' ),
$template_type_option_output,
$template_global_option_output,
$layout_cat_option_output, // #5
apply_filters( 'et_pb_new_layout_before_options', '' ),
apply_filters( 'et_pb_new_layout_after_options', '' ),
$layout_tag_option_output
);
return apply_filters( 'et_pb_new_layout_modal_output', $output );
}
}
if ( ! function_exists( 'et_pb_get_layout_type' ) ) :
/**
* Get layout type of given post ID.
*
* @param int $post_id post id.
*
* @return string|bool
*/
function et_pb_get_layout_type( $post_id ) {
// Get taxonomies.
$layout_type_data = wp_get_post_terms( $post_id, 'layout_type' );
if ( empty( $layout_type_data ) ) {
return false;
}
// Pluck name out of taxonomies.
$layout_type_array = wp_list_pluck( $layout_type_data, 'name' );
// Logically, a layout only have one layout type.
$layout_type = implode( '|', $layout_type_array );
return $layout_type;
}
endif;
if ( ! function_exists( 'et_pb_is_wp_old_version' ) ) :
/**
* Determine current wp version is less than 4.5.
*/
function et_pb_is_wp_old_version() {
global $wp_version;
$wp_major_version = substr( $wp_version, 0, 3 );
if ( version_compare( $wp_major_version, '4.5', '<' ) ) {
return true;
}
return false;
}
endif;
if ( ! function_exists( 'et_builder_theme_or_plugin_updated_cb' ) ) :
/**
* Delete cached definitions/helpers after theme or plugin update.
*/
function et_builder_theme_or_plugin_updated_cb() {
// Delete cached definitions / helpers.
et_fb_delete_builder_assets();
et_update_option( 'et_pb_clear_templates_cache', true );
}
add_action( 'after_switch_theme', 'et_builder_theme_or_plugin_updated_cb' );
add_action( 'activated_plugin', 'et_builder_theme_or_plugin_updated_cb', 10, 0 );
add_action( 'deactivated_plugin', 'et_builder_theme_or_plugin_updated_cb', 10, 0 );
add_action( 'upgrader_process_complete', 'et_builder_theme_or_plugin_updated_cb', 10, 0 );
add_action( 'et_support_center_toggle_safe_mode', 'et_builder_theme_or_plugin_updated_cb', 10, 0 );
endif;
/**
* Enqueue scripts that are required by BFB and Layout Block. These scripts are abstracted into
* separated file so Layout Block can enqueue the same sets of scripts without re-register and
* re-enqueue them
*
* @since 4.1.0
*/
function et_bfb_enqueue_scripts_dependencies() {
global $wp_version, $post;
$wp_major_version = substr( $wp_version, 0, 3 );
if ( et_pb_is_pagebuilder_used( get_the_ID() ) ) {
wp_enqueue_editor();
}
if ( version_compare( $wp_major_version, '4.5', '<' ) ) {
$jquery_ui = 'et_pb_admin_date_js';
wp_register_script( $jquery_ui, ET_BUILDER_URI . '/scripts/ext/jquery-ui-1.10.4.custom.min.js', array( 'jquery' ), ET_BUILDER_PRODUCT_VERSION, true );
} else {
$jquery_ui = 'jquery-ui-datepicker';
}
// Load timepicker script on admin page in case of BFB to make it work with modals loaded on WP admin DOM.
wp_enqueue_script( 'et_bfb_admin_date_addon_js', ET_BUILDER_URI . '/scripts/ext/jquery-ui-timepicker-addon.js', array( $jquery_ui ), ET_BUILDER_PRODUCT_VERSION, true );
// Load google maps script on admin page in case of BFB to make it work with modals loaded on WP admin DOM.
if ( et_pb_enqueue_google_maps_script() ) {
$bfb_google_maps_api_url_args = array(
'key' => et_pb_get_google_api_key(),
'callback' => 'initMap',
);
$bfb_google_maps_api_url = add_query_arg( $bfb_google_maps_api_url_args, is_ssl() ? 'https://maps.googleapis.com/maps/api/js' : 'http://maps.googleapis.com/maps/api/js' );
wp_enqueue_script( 'et_bfb_google_maps_api', esc_url( $bfb_google_maps_api_url ), array(), '3', true );
}
wp_enqueue_script( 'et_pb_media_library', ET_BUILDER_URI . '/scripts/ext/media-library.js', array( 'media-editor' ), ET_BUILDER_PRODUCT_VERSION, true );
if ( ! wp_script_is( 'wp-hooks', 'registered' ) ) {
// Use bundled wp-hooks script when WP < 5.0.
wp_enqueue_script( 'wp-hooks', ET_BUILDER_URI . '/frontend-builder/assets/backports/hooks.js', array(), ET_BUILDER_PRODUCT_VERSION, false );
}
}
if ( ! function_exists( 'et_bfb_enqueue_scripts' ) ) :
/**
* Register BFB scripts.
*/
function et_bfb_enqueue_scripts() {
global $post;
// Enqueue scripts required by BFB.
et_bfb_enqueue_scripts_dependencies();
wp_enqueue_script( 'et_bfb_admin_js', ET_BUILDER_URI . '/scripts/bfb_admin_script.js', array( 'jquery', 'et_pb_media_library' ), ET_BUILDER_PRODUCT_VERSION, true );
$bfb_options = array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'et_enable_bfb_nonce' => wp_create_nonce( 'et_enable_bfb_nonce' ),
'default_initial_column_type' => apply_filters( 'et_builder_default_initial_column_type', '4_4' ),
'default_initial_text_module' => apply_filters( 'et_builder_default_initial_text_module', 'et_pb_text' ),
'skip_default_content_adding' => apply_filters( 'et_builder_skip_content_activation', false, $post ) ? 'skip' : '',
);
wp_localize_script( 'et_bfb_admin_js', 'et_bfb_options', apply_filters( 'et_bfb_options', $bfb_options ) );
// Add filter to register tinyMCE buttons that is missing from BFB.
add_filter( 'mce_external_plugins', 'et_bfb_filter_mce_plugin' );
}
endif;
/**
* BFB use built-in WordPress tinyMCE initialization while visual builder uses standalone tinyMCE
* initialization which leads to several buttons in VB not available in BFB. This function register
* them as plugins
*
* @since 4.0.9
*
* @param array $plugins tinyMCE plugin list.
*
* @return array
*/
function et_bfb_filter_mce_plugin( $plugins ) {
// NOTE: `ET_FB_ASSETS_URI` constant isn't available yet at this point, so use `ET_BUILDER_URI`.
$plugins['table'] = ET_BUILDER_URI . '/frontend-builder/assets/vendors/plugins/table/plugin.min.js';
return $plugins;
}
/**
* Tinymce to load in html mode for BB.
*
* @param array $settings Array of editor arguments.
* @param string $editor_id Unique editor identifier, e.g. 'content'. Accepts 'classic-block'
* when called from block editor's Classic block.
*
* @return mixed
*/
function et_pb_wp_editor_settings( $settings, $editor_id ) {
if ( 'content' === $editor_id ) {
$settings['default_editor'] = 'html';
}
return $settings;
}
if ( ! function_exists( 'et_pb_add_builder_page_js_css' ) ) :
/**
* Load builder js and css.
*/
function et_pb_add_builder_page_js_css() {
global $typenow, $post, $wp_version;
// Get WP major version.
$wp_major_version = substr( $wp_version, 0, 3 );
// Avoid serving any data from object cache.
if ( ! defined( 'DONOTCACHEPAGE' ) ) {
define( 'DONOTCACHEPAGE', true );
}
// fix tinymce to load in html mode for BB.
if ( et_pb_is_pagebuilder_used() ) {
add_filter( 'wp_editor_settings', 'et_pb_wp_editor_settings', 10, 2 );
}
// BEGIN Process shortcodes (for module settings migrations and Yoast SEO compatibility)
// Get list of shortcodes that causes issue if being triggered in admin.
$conflicting_shortcodes = et_pb_admin_excluded_shortcodes();
if ( ! empty( $conflicting_shortcodes ) ) {
foreach ( $conflicting_shortcodes as $shortcode ) {
remove_shortcode( $shortcode );
}
}
// save the original content of $post variable.
$post_original = $post;
// get the content for yoast.
$post_content_processed = do_shortcode( $post->post_content );
// set the $post to the original content to make sure it wasn't changed by do_shortcode().
$post = $post_original; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- were restoring it to what it was beforea few lines above.
// END Process shortcodes.
$is_global_template = '';
$post_id = '';
$post_type = $typenow;
$selective_sync_status = '';
$global_module_type = '';
$excluded_global_options = array();
$utils = ET_Core_Data_Utils::instance();
$updates_options = get_site_option( 'et_automatic_updates_options', array() );
$et_account = array(
'et_username' => $utils->array_get( $updates_options, 'username', '' ),
'et_api_key' => $utils->array_get( $updates_options, 'api_key', '' ),
'status' => get_site_option( 'et_account_status', 'not_active' ),
);
// we need some post data when editing saved templates.
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';
$global_module_type = ! empty( $template_type[0] ) ? $template_type[0]->slug : '';
$post_id = get_the_ID();
// Check whether it's a Global item's page and display wp error if Global items disabled for current user.
if ( ! et_pb_is_allowed( 'edit_global_library' ) && 'global' === $is_global_template ) {
wp_die( esc_html__( "you don't have sufficient permissions to access this page", 'et_builder' ) );
}
if ( 'global' === $is_global_template ) {
$excluded_global_options = get_post_meta( $post_id, '_et_pb_excluded_global_options' );
$selective_sync_status = empty( $excluded_global_options ) ? '' : 'updated';
}
$built_for_post_type = get_post_meta( get_the_ID(), '_et_pb_built_for_post_type', true );
$built_for_post_type = '' !== $built_for_post_type ? $built_for_post_type : 'page';
$post_type = apply_filters( 'et_pb_built_for_post_type', $built_for_post_type, get_the_ID() );
}
// we need this data to create the filter when adding saved modules.
$layout_categories = get_terms( 'layout_category' );
$layout_cat_data = array();
$layout_cat_data_json = '';
if ( is_array( $layout_categories ) && ! empty( $layout_categories ) ) {
foreach ( $layout_categories as $category ) {
$layout_cat_data[] = array(
'slug' => $category->slug,
'name' => $category->name,
);
}
}
if ( ! empty( $layout_cat_data ) ) {
$layout_cat_data_json = wp_json_encode( $layout_cat_data );
}
// Set fixed protocol for preview URL to prevent cross origin issue.
$preview_scheme = is_ssl() ? 'https' : 'http';
$preview_url = esc_url( home_url( '/' ) );
if ( 'https' === $preview_scheme && ! strpos( $preview_url, 'https://' ) ) {
$preview_url = str_replace( 'http://', 'https://', $preview_url );
}
// force update cache if et_pb_clear_templates_cache option is set to on.
$force_cache_value = et_get_option( 'et_pb_clear_templates_cache', '', '', true );
$force_cache_update = '' !== $force_cache_value ? $force_cache_value : ET_BUILDER_FORCE_CACHE_PURGE;
/**
* Whether or not the backend builder should clear its Backbone template cache.
*
* @param bool $force_cache_update
*/
$force_cache_update = apply_filters( 'et_pb_clear_template_cache', $force_cache_update );
// delete et_pb_clear_templates_cache option it's not needed anymore.
et_delete_option( 'et_pb_clear_templates_cache' );
wp_enqueue_script( 'jquery-ui-core' );
wp_enqueue_script( 'underscore' );
wp_enqueue_script( 'backbone' );
if ( et_pb_enqueue_google_maps_script() ) {
$google_maps_api_url_args = array(
'v' => 3,
'key' => et_pb_get_google_api_key(),
);
$google_maps_api_url = add_query_arg( $google_maps_api_url_args, is_ssl() ? 'https://maps.googleapis.com/maps/api/js' : 'http://maps.googleapis.com/maps/api/js' );
wp_enqueue_script( 'google-maps-api', esc_url_raw( $google_maps_api_url ), array(), '3', true );
}
wp_enqueue_script( 'wp-color-picker' );
wp_enqueue_style( 'wp-color-picker' );
if ( version_compare( $wp_major_version, '4.9', '>=' ) ) {
wp_enqueue_script( 'wp-color-picker-alpha', ET_BUILDER_URI . '/scripts/ext/wp-color-picker-alpha.min.js', array( 'jquery', 'wp-color-picker' ), ET_BUILDER_VERSION, true );
$color_picker_strings = array(
'legacy_pick' => esc_html__( 'Select', 'et_builder' ),
'legacy_current' => esc_html__( 'Current Color', 'et_builder' ),
);
wp_localize_script( 'wp-color-picker-alpha', 'et_pb_color_picker_strings', apply_filters( 'et_pb_color_picker_strings_builder', $color_picker_strings ) );
} else {
wp_enqueue_script( 'wp-color-picker-alpha', ET_BUILDER_URI . '/scripts/ext/wp-color-picker-alpha-48.min.js', array( 'jquery', 'wp-color-picker' ), ET_BUILDER_VERSION, true );
}
wp_register_script( 'chart', ET_BUILDER_URI . '/scripts/ext/chart.min.js', array(), ET_BUILDER_VERSION, true );
wp_register_script( 'jquery-tablesorter', ET_BUILDER_URI . '/scripts/ext/jquery.tablesorter.min.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
// load 1.10.4 versions of jQuery-ui scripts if WP version is less than 4.5, load 1.11.4 version otherwise.
if ( et_pb_is_wp_old_version() ) {
$jquery_ui = 'et_pb_admin_date_js';
wp_enqueue_script( $jquery_ui, ET_BUILDER_URI . '/scripts/ext/jquery-ui-1.10.4.custom.min.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
} else {
$jquery_ui = 'jquery-ui-datepicker';
}
wp_enqueue_script( 'et_pb_admin_date_addon_js', ET_BUILDER_URI . '/scripts/ext/jquery-ui-timepicker-addon.js', array( $jquery_ui ), ET_BUILDER_VERSION, true );
wp_enqueue_script( 'validation', ET_BUILDER_URI . '/scripts/ext/jquery.validate.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
wp_enqueue_script( 'minicolors', ET_BUILDER_URI . '/scripts/ext/jquery.minicolors.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
wp_enqueue_script( 'et_pb_cache_notice_js', ET_BUILDER_URI . '/scripts/cache_notice.js', array( 'jquery', 'et_pb_admin_js' ), ET_BUILDER_VERSION, true );
$pb_notice_options = array(
'product_version' => ET_BUILDER_PRODUCT_VERSION,
);
wp_localize_script( 'et_pb_cache_notice_js', 'et_pb_notice_options', apply_filters( 'et_pb_notice_options_builder', $pb_notice_options ) );
wp_enqueue_script( 'lz_string', ET_BUILDER_URI . '/scripts/ext/lz-string.min.js', array(), ET_BUILDER_VERSION, true );
// phpcs:disable WordPress.WP.EnqueuedResourceParameters -- The script version number are specified in the src. No need to set $ver explicitly.
wp_enqueue_script( 'es6-promise', '//cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.min.js', array(), null, true );
wp_enqueue_script( 'postmate', '//cdn.jsdelivr.net/npm/postmate@1.1.9/build/postmate.min.js', array( 'es6-promise' ), null, true );
// phpcs:enable
wp_enqueue_script( 'et_pb_media_library', ET_BUILDER_URI . '/scripts/ext/media-library.js', array( 'media-editor' ), ET_BUILDER_PRODUCT_VERSION, true );
wp_enqueue_script( 'et_pb_admin_js', ET_BUILDER_URI . '/scripts/builder.js', array( 'jquery', 'jquery-ui-core', 'underscore', 'backbone', 'chart', 'jquery-tablesorter', 'et_pb_media_library', 'lz_string', 'es6-promise' ), ET_BUILDER_VERSION, true );
$saved_gutter_width = get_post_meta( get_the_ID(), '_et_pb_gutter_width', true );
$pb_options = array(
'debug' => defined( 'ET_DEBUG' ) && ET_DEBUG,
'wp_default_editor' => wp_default_editor(),
'et_account' => $et_account,
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'home_url' => home_url(),
'cookie_path' => SITECOOKIEPATH,
'preview_url' => add_query_arg( 'et_pb_preview', 'true', $preview_url ),
'et_admin_load_nonce' => wp_create_nonce( 'et_admin_load_nonce' ),
'images_uri' => ET_BUILDER_URI . '/images',
'postId' => $post->ID,
'post_type' => $post_type,
'is_third_party_post_type' => et_builder_is_post_type_custom( $post_type ) ? 'yes' : 'no',
'et_builder_module_parent_shortcodes' => ET_Builder_Element::get_parent_slugs_regex( $post_type ),
'et_builder_module_child_shortcodes' => ET_Builder_Element::get_child_slugs_regex( $post_type ),
'et_builder_module_raw_content_shortcodes' => ET_Builder_Element::get_raw_content_slugs( $post_type ),
'et_builder_modules' => ET_Builder_Element::get_modules_js_array( $post_type ),
'et_builder_modules_count' => ET_Builder_Element::get_modules_count( $post_type ),
'et_builder_modules_with_children' => ET_Builder_Element::get_slugs_with_children( $post_type ),
'et_builder_modules_featured_image_background' => ET_Builder_Element::get_featured_image_background_modules( $post_type ),
'et_builder_templates_amount' => ET_BUILDER_AJAX_TEMPLATES_AMOUNT,
'et_builder_edit_global_library' => et_pb_is_allowed( 'edit_global_library' ),
'default_initial_column_type' => apply_filters( 'et_builder_default_initial_column_type', '4_4' ),
'default_initial_text_module' => apply_filters( 'et_builder_default_initial_text_module', 'et_pb_text' ),
'section_only_row_dragged_away' => esc_html__( 'The section should have at least one row.', 'et_builder' ),
'fullwidth_module_dragged_away' => esc_html__( 'Fullwidth module can\'t be used outside of the Fullwidth Section.', 'et_builder' ),
'stop_dropping_3_col_row' => esc_html__( "This number of columns can't be used on this row.", 'et_builder' ),
'preview_image' => esc_html__( 'Preview', 'et_builder' ),
'empty_admin_label' => esc_html__( 'Module', 'et_builder' ),
'video_module_image_error' => esc_html__( 'Still images cannot be generated from this video service and/or this video format', 'et_builder' ),
'geocode_error' => esc_html__( 'Geocode was not successful for the following reason', 'et_builder' ),
'geocode_error_2' => esc_html__( 'Geocoder failed due to', 'et_builder' ),
'no_results' => esc_html__( 'No results found', 'et_builder' ),
'all_tab_options_hidden' => esc_html__( 'No available options for this configuration.', 'et_builder' ),
'update_global_module' => esc_html__( 'You\'re about to update global module. This change will be applied to all pages where you use this module. Press OK if you want to update this module', 'et_builder' ),
'global_row_alert' => esc_html__( 'You cannot add global rows into global sections', 'et_builder' ),
'global_module_alert' => esc_html__( 'You cannot add global modules into global sections or rows', 'et_builder' ),
'all_cat_text' => esc_html__( 'All Categories', 'et_builder' ),
'font_name_error' => esc_html__( 'Name Cannot be Empty', 'et_builder' ),
'font_file_error' => esc_html__( 'Please Select Font File', 'et_builder' ),
'font_weight_error' => esc_html__( 'Please Select Font Weight', 'et_builder' ),
'is_global_template' => $is_global_template,
'selective_sync_status' => $selective_sync_status,
'global_module_type' => $global_module_type,
'excluded_global_options' => isset( $excluded_global_options[0] ) ? json_decode( $excluded_global_options[0] ) : array(),
'template_post_id' => $post_id,
'layout_categories' => $layout_cat_data_json,
'map_pin_address_error' => esc_html__( 'Map Pin Address cannot be empty', 'et_builder' ),
'map_pin_address_invalid' => esc_html__( 'Invalid Pin and address data. Please try again.', 'et_builder' ),
'locked_section_permission_alert' => esc_html__( 'You do not have permission to unlock this section.', 'et_builder' ),
'locked_row_permission_alert' => esc_html__( 'You do not have permission to unlock this row.', 'et_builder' ),
'locked_module_permission_alert' => esc_html__( 'You do not have permission to unlock this module.', 'et_builder' ),
'locked_item_permission_alert' => esc_html__( 'You do not have permission to perform this task.', 'et_builder' ),
'localstorage_unavailability_alert' => esc_html__( 'Unable to perform copy/paste process due to inavailability of localStorage feature in your browser. Please use latest modern browser (Chrome, Firefox, or Safari) to perform copy/paste process', 'et_builder' ),
'invalid_color' => esc_html__( 'Invalid Color', 'et_builder' ),
'et_pb_preview_nonce' => wp_create_nonce( 'et_pb_preview_nonce' ),
'is_divi_library' => 'et_pb_layout' === $typenow ? 1 : 0,
'layout_type' => 'et_pb_layout' === $typenow ? et_pb_get_layout_type( get_the_ID() ) : 0,
'is_plugin_used' => et_is_builder_plugin_active(),
'yoast_content' => et_is_yoast_seo_plugin_active() ? $post_content_processed : '',
'ab_db_status' => true === et_pb_db_status_up_to_date() ? 'exists' : 'not_exists',
'ab_testing_builder_nonce' => wp_create_nonce( 'ab_testing_builder_nonce' ),
'page_color_palette' => get_post_meta( get_the_ID(), '_et_pb_color_palette', true ),
'default_color_palette' => implode( '|', et_pb_get_default_color_palette() ),
'page_section_bg_color' => get_post_meta( get_the_ID(), '_et_pb_section_background_color', true ),
'page_gutter_width' => '' !== $saved_gutter_width ? $saved_gutter_width : et_get_option( 'gutter_width', '3' ),
'product_version' => ET_BUILDER_PRODUCT_VERSION,
'active_plugins' => et_builder_get_active_plugins(),
'force_cache_purge' => $force_cache_update ? 'true' : 'false',
'memory_limit_increased' => esc_html__( 'Your memory limit has been increased', 'et_builder' ),
'memory_limit_not_increased' => esc_html__( "Your memory limit can't be changed automatically", 'et_builder' ),
'google_api_key' => et_pb_get_google_api_key(),
'options_page_url' => et_pb_get_options_page_link(),
'et_pb_google_maps_script_notice' => et_pb_enqueue_google_maps_script(),
'select_text' => esc_html__( 'Select', 'et_builder' ),
'et_fb_autosave_nonce' => wp_create_nonce( 'et_fb_autosave_nonce' ),
'et_builder_email_fetch_lists_nonce' => wp_create_nonce( 'et_builder_email_fetch_lists_nonce' ),
'et_builder_email_add_account_nonce' => wp_create_nonce( 'et_builder_email_add_account_nonce' ),
'et_builder_email_remove_account_nonce' => wp_create_nonce( 'et_builder_email_remove_account_nonce' ),
'et_pb_module_settings_migrations' => ET_Builder_Module_Settings_Migration::$migrated,
'acceptable_css_string_values' => et_builder_get_acceptable_css_string_values( 'all' ),
'upload_font_nonce' => wp_create_nonce( 'et_fb_upload_font_nonce' ),
'user_fonts' => et_builder_get_custom_fonts(),
'google_fonts' => et_builder_get_google_fonts(),
'supported_font_weights' => et_builder_get_font_weight_list(),
'supported_font_formats' => et_pb_get_supported_font_formats(),
'all_svg_icons' => et_pb_get_svg_icons_list(),
'library_get_layouts_data_nonce' => wp_create_nonce( 'et_builder_library_get_layouts_data' ),
'library_get_layout_nonce' => wp_create_nonce( 'et_builder_library_get_layout' ),
'library_update_account_nonce' => wp_create_nonce( 'et_builder_library_update_account' ),
'library_custom_tabs' => ET_Builder_Library::builder_library_modal_custom_tabs( $post_type ),
);
$pb_options_builder = array_merge( $pb_options, et_pb_history_localization() );
wp_localize_script( 'et_pb_admin_js', 'et_pb_options', apply_filters( 'et_pb_options_builder', $pb_options_builder ) );
$ab_settings = et_builder_ab_labels();
$pb_ab_js_options = array(
'test_id' => $post->ID,
'has_report' => et_pb_ab_has_report( $post->ID ),
'has_permission' => et_pb_is_allowed( 'ab_testing' ),
'refresh_interval_duration' => et_pb_ab_get_refresh_interval_duration( $post->ID ),
'refresh_interval_durations' => et_pb_ab_refresh_interval_durations(),
'analysis_formula' => et_pb_ab_get_analysis_formulas(),
'have_conversions' => et_pb_ab_get_modules_have_conversions(),
'sales_title' => esc_html__( 'Sales', 'et_builder' ),
'force_cache_purge' => $force_cache_update,
'total_title' => esc_html__( 'Total', 'et_builder' ),
// Saved data.
'subjects_rank' => ( 'on' === get_post_meta( $post->ID, '_et_pb_use_builder', true ) ) ? et_pb_ab_get_saved_subjects_ranks( $post->ID ) : false,
// Rank color.
'subjects_rank_color' => et_pb_ab_get_subject_rank_colors(),
// Configuration.
'has_no_permission' => array(
'title' => esc_html__( 'Unauthorized Action', 'et_builder' ),
'desc' => esc_html__( 'You do not have permission to edit the module, row or section in this split test.', 'et_builder' ),
),
// AB Testing.
'select_ab_testing_subject' => $ab_settings['select_subject'],
'select_ab_testing_goal' => $ab_settings['select_goal'],
'configure_ab_testing_alternative' => $ab_settings['configure_alternative'],
'select_ab_testing_winner_first' => $ab_settings['select_winner_first'],
'select_ab_testing_subject_first' => $ab_settings['select_subject_first'],
'select_ab_testing_goal_first' => $ab_settings['select_goal_first'],
'cannot_select_subject_parent_as_goal' => $ab_settings['cannot_select_subject_parent_as_goal'],
'cannot_select_global_children_as_subject' => $ab_settings['cannot_select_global_children_as_subject'],
'cannot_select_global_children_as_goal' => $ab_settings['cannot_select_global_children_as_goal'],
// Save to Library.
'cannot_save_app_layout_has_ab_testing' => $ab_settings['cannot_save_app_layout_has_ab_testing'],
'cannot_save_section_layout_has_ab_testing' => $ab_settings['cannot_save_section_layout_has_ab_testing'],
'cannot_save_row_layout_has_ab_testing' => $ab_settings['cannot_save_row_layout_has_ab_testing'],
'cannot_save_row_inner_layout_has_ab_testing' => $ab_settings['cannot_save_row_inner_layout_has_ab_testing'],
'cannot_save_module_layout_has_ab_testing' => $ab_settings['cannot_save_module_layout_has_ab_testing'],
// Load / Clear Layout.
'cannot_load_layout_has_ab_testing' => $ab_settings['cannot_load_layout_has_ab_testing'],
'cannot_clear_layout_has_ab_testing' => $ab_settings['cannot_clear_layout_has_ab_testing'],
// Cannot Import / Export Layout (Portability).
'cannot_import_export_layout_has_ab_testing' => $ab_settings['cannot_import_export_layout_has_ab_testing'],
// Moving Goal / Subject.
'cannot_move_module_goal_out_from_subject' => $ab_settings['cannot_move_module_goal_out_from_subject'],
'cannot_move_row_goal_out_from_subject' => $ab_settings['cannot_move_row_goal_out_from_subject'],
'cannot_move_goal_into_subject' => $ab_settings['cannot_move_goal_into_subject'],
'cannot_move_subject_into_goal' => $ab_settings['cannot_move_subject_into_goal'],
// Cloning + Has Goal.
'cannot_clone_section_has_goal' => $ab_settings['cannot_clone_section_has_goal'],
'cannot_clone_row_has_goal' => $ab_settings['cannot_clone_row_has_goal'],
// Removing + Has Goal.
'cannot_remove_section_has_goal' => $ab_settings['cannot_remove_section_has_goal'],
'cannot_remove_row_has_goal' => $ab_settings['cannot_remove_row_has_goal'],
// Removing + Has Unremovable Subjects.
'cannot_remove_section_has_unremovable_subject' => $ab_settings['cannot_remove_section_has_unremovable_subject'],
'cannot_remove_row_has_unremovable_subject' => $ab_settings['cannot_remove_row_has_unremovable_subject'],
// View stats summary table heading.
'view_stats_thead_titles' => $ab_settings['view_stats_thead_titles'],
);
wp_localize_script( 'et_pb_admin_js', 'et_pb_ab_js_options', apply_filters( 'et_pb_ab_js_options', $pb_ab_js_options ) );
$pb_help_options = array(
'shortcuts' => et_builder_get_shortcuts( 'bb' ),
);
wp_localize_script( 'et_pb_admin_js', 'et_pb_help_options', apply_filters( 'et_pb_help_options', $pb_help_options ) );
et_core_load_main_fonts();
wp_enqueue_style( 'et_pb_admin_css', ET_BUILDER_URI . '/styles/style.css', array(), ET_BUILDER_VERSION );
wp_enqueue_style( 'et_pb_admin_date_css', ET_BUILDER_URI . '/styles/jquery-ui-1.12.1.custom.css', array(), ET_BUILDER_VERSION );
wp_add_inline_style( 'et_pb_admin_css', et_pb_ab_get_subject_rank_colors_style() );
ET_Cloud_App::load_js();
}
endif;
/**
* Set et-editor-available-post-* cookie
*/
function et_pb_set_editor_available_cookie() {
$post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification -- This function does not change any state, and is therefore not susceptible to CSRF.
$headers_sent = headers_sent();
if ( et_builder_should_load_framework() && is_admin() && ! $headers_sent && ! empty( $post_id ) ) {
setcookie( 'et-editor-available-post-' . $post_id . '-bb', 'bb', time() + ( MINUTE_IN_SECONDS * 30 ), SITECOOKIEPATH, false, is_ssl() );
}
}
add_action( 'admin_init', 'et_pb_set_editor_available_cookie' );
/**
* List of history meta.
*
* @return array History meta.
*/
function et_pb_history_localization() {
return array(
'verb' => array(
'did' => esc_html__( 'Did', 'et_builder' ),
'added' => esc_html__( 'Added', 'et_builder' ),
'edited' => esc_html__( 'Edited', 'et_builder' ),
'removed' => esc_html__( 'Removed', 'et_builder' ),
'moved' => esc_html__( 'Moved', 'et_builder' ),
'expanded' => esc_html__( 'Expanded', 'et_builder' ),
'collapsed' => esc_html__( 'Collapsed', 'et_builder' ),
'locked' => esc_html__( 'Locked', 'et_builder' ),
'unlocked' => esc_html__( 'Unlocked', 'et_builder' ),
'cloned' => esc_html__( 'Cloned', 'et_builder' ),
'cleared' => esc_html__( 'Cleared', 'et_builder' ),
'enabled' => esc_html__( 'Enabled', 'et_builder' ),
'disabled' => esc_html__( 'Disabled', 'et_builder' ),
'copied' => esc_html__( 'Copied', 'et_builder' ),
'reset' => esc_html__( 'Reset', 'et_builder' ),
'cut' => esc_html__( 'Cut', 'et_builder' ),
'pasted' => esc_html__( 'Pasted', 'et_builder' ),
'pasted_styles' => esc_html__( 'Pasted Styles', 'et_builder' ),
'renamed' => esc_html__( 'Renamed', 'et_builder' ),
'loaded' => esc_html__( 'Loaded', 'et_builder' ),
'turnon' => esc_html__( 'Turned On', 'et_builder' ),
'turnoff' => esc_html__( 'Turned Off', 'et_builder' ),
'globalon' => esc_html__( 'Made Global', 'et_builder' ),
'globaloff' => esc_html__( 'Disabled Global', 'et_builder' ),
'configured' => esc_html__( 'Configured', 'et_builder' ),
'find_replace' => esc_html__( 'Find & Replace', 'et_builder' ),
'extend_styles' => esc_html__( 'Extend Styles', 'et_builder' ),
'imported' => esc_html__( 'Imported From Layout', 'et_builder' ),
'presetCreated' => esc_html__( 'Preset Created For', 'et_builder' ),
'presetNameChanged' => esc_html__( 'Preset Name Changed For', 'et_builder' ),
'presetDeleted' => esc_html__( 'Preset Deleted For', 'et_builder' ),
'presetAssignedAsDefault' => esc_html__( 'Preset Assigned As Default For', 'et_builder' ),
),
'noun' => array(
'section' => esc_html__( 'Section', 'et_builder' ),
'saved_section' => esc_html__( 'Saved Section', 'et_builder' ),
'fullwidth_section' => esc_html__( 'Fullwidth Section', 'et_builder' ),
'specialty_section' => esc_html__( 'Specialty Section', 'et_builder' ),
'column' => esc_html__( 'Column', 'et_builder' ),
'row' => esc_html__( 'Row', 'et_builder' ),
'saved_row' => esc_html__( 'Saved Row', 'et_builder' ),
'module' => esc_html__( 'Module', 'et_builder' ),
'saved_module' => esc_html__( 'Saved Module', 'et_builder' ),
'page' => esc_html__( 'Page', 'et_builder' ),
'layout' => et_builder_i18n( 'Layout' ),
'abtesting' => esc_html__( 'Split Testing', 'et_builder' ),
'settings' => esc_html__( 'Settings', 'et_builder' ),
),
'addition' => array(
'phone' => esc_html__( 'on Phone', 'et_builder' ),
'tablet' => esc_html__( 'on Tablet', 'et_builder' ),
'desktop' => esc_html__( 'on Desktop', 'et_builder' ),
),
);
}
/**
* Page Settings Metabox code is included in builder.js which won't be loaded unless BB is.
* In such cases (eg BFB or GB are enabled) we provide the mbox js logic in a separate file.
*
* @return void
*/
function et_pb_metabox_scripts() {
// Only act if `builder.js` isn't enqueued.
if ( ! wp_script_is( 'et_pb_admin_js' ) ) {
global $typenow;
wp_enqueue_script( 'et_page_settings_metabox_js', ET_BUILDER_URI . '/scripts/page-settings-metabox.js', array( 'jquery' ), ET_BUILDER_PRODUCT_VERSION, true );
$pb_options = array(
'post_type' => $typenow,
'is_third_party_post_type' => et_builder_is_post_type_custom( $typenow ) ? 'yes' : 'no',
);
wp_localize_script( 'et_page_settings_metabox_js', 'et_pb_options', $pb_options );
}
}
/**
* Prevents the Builder mbox from being hidden.
*
* @param string[] $hidden all hidden metaboxes.
*
* @return mixed
*/
function et_pb_hidden_meta_boxes( $hidden ) {
$found = array_search( 'et_pb_layout', $hidden, true );
if ( false !== $found ) {
unset( $hidden[ $found ] );
}
return $hidden;
}
/**
* Add "The Divi Builder" BB metabox.
*
* @param string $post_type post type.
* @param WP_Post $post post object.
*/
function et_pb_add_custom_box( $post_type, $post ) {
add_action( 'admin_enqueue_scripts', 'et_pb_metabox_scripts', 99 );
// Do not add BB metabox if GB is active on this page.
if ( et_core_is_gutenberg_enabled() ) {
return;
}
// Do not add BB metabox if builder is not activate on this page.
if ( et_builder_bfb_enabled() && ! et_pb_is_pagebuilder_used( $post->ID ) ) {
return;
}
$post_types = et_builder_get_builder_post_types();
$add = in_array( $post_type, $post_types, true );
if ( ! $add && ! empty( $post ) && et_builder_enabled_for_post( $post->ID ) ) {
$add = true;
}
if ( $add ) {
add_meta_box( ET_BUILDER_LAYOUT_POST_TYPE, esc_html__( 'The Divi Builder', 'et_builder' ), 'et_pb_pagebuilder_meta_box', $post_type, 'normal', 'high' );
}
}
if ( ! function_exists( 'et_pb_get_the_author_posts_link' ) ) :
/**
* Return a post author link markup.
*/
function et_pb_get_the_author_posts_link() {
global $authordata, $post;
// Fallback for preview.
if ( empty( $authordata ) && isset( $post->post_author ) ) {
$authordata = get_userdata( $post->post_author ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- If $authordata is not set then set it.
}
// If $authordata is empty, don't continue.
if ( empty( $authordata ) ) {
return;
}
$link = sprintf(
'
%3$s',
esc_url( get_author_posts_url( $authordata->ID, $authordata->user_nicename ) ),
// translators: post author name.
esc_attr( sprintf( __( 'Posts by %s', 'et_builder' ), get_the_author() ) ),
get_the_author()
);
return apply_filters( 'the_author_posts_link', $link );
}
endif;
if ( ! function_exists( 'et_pb_get_comments_popup_link' ) ) :
/**
* Return comments link.
*
* @param bool|string $zero text to display when 0 comments.
* @param bool|string $one text to display when 1 comment.
* @param bool|string $more text to display for more than 1 comments.
*/
function et_pb_get_comments_popup_link( $zero = false, $one = false, $more = false ) {
$id = get_the_ID();
$number = get_comments_number( $id );
if ( 0 === $number && ! comments_open() && ! pings_open() ) {
return;
}
if ( $number > 1 ) {
// translators: more comments text.
$output = str_replace( '%', number_format_i18n( $number ), ( false === $more ) ? __( '% Comments', 'et_builder' ) : $more );
} elseif ( 0 === $number ) {
$output = ( false === $zero ) ? __( 'No Comments', 'et_builder' ) : $zero;
} else { // must be one.
$output = ( false === $one ) ? __( '1 Comment', 'et_builder' ) : $one;
}
do_action( 'et_builder_before_comments_number' );
$link = '';
do_action( 'et_builder_after_comments_number' );
return $link;
}
endif;
if ( ! function_exists( 'et_pb_postinfo_meta' ) ) :
/**
* Return post meta.
*
* @param string[] $postinfo post info e.g date, author, categories.
* @param string $date_format date format.
* @param string $comment_zero text to display for 0 comments.
* @param string $comment_one text to display for 1 comments.
* @param string $comment_more text to display for more comments.
*/
function et_pb_postinfo_meta( $postinfo, $date_format, $comment_zero, $comment_one, $comment_more ) {
$postinfo_meta = array();
if ( in_array( 'author', $postinfo, true ) ) {
$postinfo_meta[] = ' ' . esc_html__( 'by', 'et_builder' ) . '
' . et_pb_get_the_author_posts_link() . '';
}
if ( in_array( 'date', $postinfo, true ) ) {
$postinfo_meta[] = '
' . esc_html( get_the_time( $date_format ) ) . '';
}
if ( in_array( 'categories', $postinfo, true ) ) {
$categories_list = get_the_category_list( ', ' );
// do not output anything if no categories retrieved.
if ( '' !== $categories_list ) {
$postinfo_meta[] = $categories_list;
}
}
if ( in_array( 'comments', $postinfo, true ) ) {
$postinfo_meta[] = et_pb_get_comments_popup_link( $comment_zero, $comment_one, $comment_more );
}
return implode( ' | ', array_filter( $postinfo_meta ) );
}
endif;
if ( ! function_exists( 'et_pb_fix_shortcodes' ) ) {
/**
* Fix shortcodes? @todo Add function doc.
*
* @param string $content post content.
* @param bool $is_raw_content whether content is row.
*
* @return string|string[]|null
*/
function et_pb_fix_shortcodes( $content, $is_raw_content = false ) {
// Turn back the "data-et-target-link" attribute as "target" attribte
// that has been made before saving the content in "et_fb_process_to_shortcode" function.
if ( false !== strpos( $content, 'data-et-target-link=' ) ) {
$content = str_replace( ' data-et-target-link=', ' target=', $content );
}
if ( $is_raw_content ) {
$content = et_builder_replace_code_content_entities( $content );
$content = ET_Builder_Element::convert_smart_quotes_and_amp( $content );
}
$slugs = ET_Builder_Element::get_module_slugs_by_post_type();
// The current patterns take care to replace only the shortcodes that extends `ET_Builder_Element` class
// In order to avoid cases like this: `[3:45]
`
// The pattern looks like this `(\[\/?(et_pb_section|et_pb_column|et_pb_row)[^\]]*\])`.
$shortcode_pattern = sprintf( '(\[\/?(%s)[^\]]*\])', implode( '|', $slugs ) );
$opening_pattern = '(
|
|\n)+';
$closing_pattern = '(
|<\/p>|\n)+';
$space_pattern = '[\s*|\n]*';
// Replace `]
`, `]
` `]\n` with `]`
// Make sure to remove any closing `` tags or line breaks or new lines after shortcode tag.
$pattern_1 = sprintf( '/%1$s%2$s%3$s/', $shortcode_pattern, $space_pattern, $closing_pattern );
// Replace `
[`, `
[` `\n[` with `[`
// Make sure to remove any opening `
` tags or line breaks or new lines before shortcode tag.
$pattern_2 = sprintf( '/%1$s%2$s%3$s/', $opening_pattern, $space_pattern, $shortcode_pattern );
$content = preg_replace( $pattern_1, '$1', $content );
$content = preg_replace( $pattern_2, '$2', $content );
return $content;
}
}
if ( ! function_exists( 'et_pb_load_global_module' ) ) {
/**
* Return gloval module content.
*
* @param integer $global_id layout id.
* @param string $row_type row type.
* @param string $prev_bg Previous background color.
* @param string $next_bg next background color.
*
* @return string|string[]|null
*/
function et_pb_load_global_module( $global_id, $row_type = '', $prev_bg = '', $next_bg = '' ) {
$global_shortcode = '';
if ( '' !== $global_id ) {
$query = new WP_Query(
array(
'p' => (int) $global_id,
'post_type' => array(
ET_BUILDER_LAYOUT_POST_TYPE,
ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE,
ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE,
ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE,
),
)
);
if ( ! empty( $query->post ) ) {
// Call the_post() to properly configure post data. Make sure to call the_post() and
// wp_reset_postdata() only if the posts result exist to avoid unexpected issues.
$query->the_post();
wp_reset_postdata();
$global_shortcode = $query->post->post_content;
if ( '' !== $row_type && 'et_pb_row_inner' === $row_type ) {
$global_shortcode = str_replace( 'et_pb_row', 'et_pb_row_inner', $global_shortcode );
$global_shortcode = str_replace( 'et_pb_column', 'et_pb_column_inner', $global_shortcode );
}
}
}
// Set provided prev_background_color.
if ( ! empty( $prev_bg ) ) {
$global_shortcode = preg_replace( '/prev_background_color="(.*?)"/', 'prev_background_color="' . $prev_bg . '"', $global_shortcode, 1 );
}
// Set provided next_background_color.
if ( ! empty( $next_bg ) ) {
$global_shortcode = preg_replace( '/next_background_color="(.*?)"/', 'next_background_color="' . $next_bg . '"', $global_shortcode, 1 );
}
return $global_shortcode;
}
}
if ( ! function_exists( 'et_pb_extract_shortcode_content' ) ) {
/**
* Return the shortcode content.
*
* @param string $content content.
* @param string $shortcode_name shortcode name.
*
* @return bool|false|string
*/
function et_pb_extract_shortcode_content( $content, $shortcode_name ) {
$start = strpos( $content, ']' ) + 1;
$end = strrpos( $content, '[/' . $shortcode_name );
if ( false !== $end ) {
$content = substr( $content, $start, $end - $start );
} else {
$content = (bool) false;
}
return $content;
}
}
if ( ! function_exists( 'et_pb_remove_shortcode_content' ) ) {
/**
* Remove the content part of the shortcode.
*
* @param string $content content.
* @param string $shortcode_name shortcode name.
*
* @return string|string[]
*/
function et_pb_remove_shortcode_content( $content, $shortcode_name ) {
$shortcode_content = et_pb_extract_shortcode_content( $content, $shortcode_name );
if ( $shortcode_content ) {
// Anchor to the ][ brackets around the content so content that appears in
// attributes does not get removed as well.
return str_replace( ']' . $shortcode_content . '[', '][', $content );
}
return $content;
}
}
if ( ! function_exists( 'et_pb_get_global_module_content' ) ) {
/**
* Return global module content.
*
* @param string $content content.
* @param string $shortcode_name shortcode slug.
* @param bool $for_inner_row whether we getting module content for inner row.
*
* @return bool|false|string|string[]|null
*/
function et_pb_get_global_module_content( $content, $shortcode_name, $for_inner_row = false ) {
/**
* Filter list of modules where we don't need to apply autop to the global module content.
*
* @param array Module slugs list.
*/
$custom_autop_ignored_modules = apply_filters( 'et_builder_global_modules_ignore_autop', array() );
$custom_autop_ignored_modules = is_array( $custom_autop_ignored_modules ) ? $custom_autop_ignored_modules : array();
$default_autop_ignored_modules = array_merge( array( 'et_pb_code', 'et_pb_fullwidth_code' ), $custom_autop_ignored_modules );
// Do not apply autop to code modules.
if ( in_array( $shortcode_name, $default_autop_ignored_modules, true ) ) {
return et_pb_extract_shortcode_content( $content, $shortcode_name );
}
$original_code_modules = array();
$shortcode_content = et_pb_extract_shortcode_content( $content, $shortcode_name );
// Getting content for Global row when it's turned to inner row in specialty section
// Need to make sure it wrapped in et_pb_column_inner, not et_pb_column.
if ( $for_inner_row && false === strpos( $shortcode_content, '[et_pb_column_inner' ) ) {
$shortcode_content = str_replace( 'et_pb_column', 'et_pb_column_inner', $shortcode_content );
}
// Get all the code and fullwidth code modules from content.
preg_match_all( '/(\[et_pb(_fullwidth_code|_code).+?\[\/et_pb(_fullwidth_code|_code)\])/s', $shortcode_content, $original_code_modules );
$global_content = et_pb_fix_shortcodes( wpautop( $shortcode_content ) );
// Replace content modified by wpautop for code and fullwidth code modules with original content.
if ( ! empty( $original_code_modules ) ) {
global $et_pb_global_code_replacements;
$et_pb_global_code_replacements = $original_code_modules[0];
$global_content = preg_replace_callback( '/(\[et_pb(_fullwidth_code|_code).+?\[\/et_pb(_fullwidth_code|_code)\])/s', 'et_builder_get_global_code_replacement', $global_content );
}
return $global_content;
}
}
if ( ! function_exists( 'et_builder_get_global_code_replacement' ) ) {
/**
* Retrieve the global code original instance to replace the modified in global code shortcode.
*
* @param array $matches found matches.
*
* @return mixed
*/
function et_builder_get_global_code_replacement( $matches ) {
global $et_pb_global_code_replacements;
return array_shift( $et_pb_global_code_replacements );
}
}
if ( ! function_exists( 'et_builder_activate_bfb_auto_draft' ) ) {
/**
* Force activate post_id which has auto-draft status
*/
function et_builder_activate_bfb_auto_draft() {
et_core_security_check( 'edit_posts', 'et_enable_bfb_nonce' );
$post_id = ! empty( $_POST['et_post_id'] ) ? absint( $_POST['et_post_id'] ) : 0;
if ( 0 === $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
die();
}
// et_builder_activate_bfb_auto_draft() is executed when post title and content empty which means post_status is still lik. ely
// to be "auto-draft". "auto-draft" status returns 404 page; thus post status needs to be updated to "draft".
wp_update_post(
array(
'ID' => $post_id,
'post_status' => 'draft',
)
);
update_post_meta( $post_id, '_et_pb_use_builder', 'on' );
die();
}
}
add_action( 'wp_ajax_et_builder_activate_bfb_auto_draft', 'et_builder_activate_bfb_auto_draft' );
if ( ! function_exists( 'et_builder_ajax_toggle_bfb' ) ) {
/**
* Ajax Callback :: Switch To The New Divi Builder.
*/
function et_builder_ajax_toggle_bfb() {
et_core_security_check( 'manage_options', 'et_builder_toggle_bfb', 'nonce', '_GET' );
$enable = isset( $_GET['enable'] ) && '1' === $_GET['enable'];
$redirect = isset( $_GET['redirect'] ) ? esc_url_raw( $_GET['redirect'] ) : '';
if ( empty( $redirect ) && isset( $_SERVER['HTTP_REFERER'] ) ) {
$redirect = esc_url_raw( $_SERVER['HTTP_REFERER'] );
}
if ( empty( $redirect ) ) {
$redirect = esc_url_raw( admin_url( '/' ) );
}
et_builder_toggle_bfb( $enable );
set_transient( 'et_builder_show_bfb_welcome_modal', true, 0 );
wp_safe_redirect( $redirect );
exit;
}
}
add_action( 'wp_ajax_et_builder_toggle_bfb', 'et_builder_ajax_toggle_bfb' );
/**
* Return font weight select input element html.
*
* @return string
*/
function et_generate_font_weight_select_output() {
$all_weights = et_builder_get_font_weight_list();
$output = '';
foreach ( $all_weights as $number => $name ) {
$output .= sprintf(
'',
esc_attr( $number ),
esc_html( $name ),
esc_html( $number )
);
}
return $output;
}
/**
* Return regular and specialty layouts.
*
* @return mixed|void
*/
function et_builder_get_columns() {
$columns = array(
'specialty' => array(
'1_2,1_2' => array(
'position' => '1,0',
'columns' => '3',
),
'1_2,1_2' => array(
'position' => '0,1',
'columns' => '3',
),
'1_4,3_4' => array(
'position' => '0,1',
'columns' => '3',
),
'3_4,1_4' => array(
'position' => '1,0',
'columns' => '3',
),
'1_4,1_4,1_2' => array(
'position' => '0,0,1',
'columns' => '3',
),
'1_2,1_4,1_4' => array(
'position' => '1,0,0',
'columns' => '3',
),
'1_4,1_2,1_4' => array(
'position' => '0,1,0',
'columns' => '3',
),
'1_3,2_3' => array(
'position' => '0,1',
'columns' => '4',
),
'2_3,1_3' => array(
'position' => '1,0',
'columns' => '4',
),
),
'regular' => array(
'4_4',
'1_2,1_2',
'1_3,1_3,1_3',
'1_4,1_4,1_4,1_4',
'1_5,1_5,1_5,1_5,1_5',
'1_6,1_6,1_6,1_6,1_6,1_6',
'2_5,3_5',
'3_5,2_5',
'1_3,2_3',
'2_3,1_3',
'1_4,3_4',
'3_4,1_4',
'1_4,1_2,1_4',
'1_5,3_5,1_5',
'1_4,1_4,1_2',
'1_2,1_4,1_4',
'1_5,1_5,3_5',
'3_5,1_5,1_5',
'1_6,1_6,1_6,1_2',
'1_2,1_6,1_6,1_6',
),
);
return apply_filters( 'et_builder_get_columns', $columns );
}
/**
* Return columns layout.
*
* @return mixed|void
*/
function et_builder_get_columns_layout() {
$layout_columns =
'<% if ( typeof et_pb_specialty !== \'undefined\' && et_pb_specialty === \'on\' ) { %>
<% } else if ( typeof view !== \'undefined\' && typeof view.model.attributes.specialty_columns !== \'undefined\' ) { %>
<% if ( view.model.attributes.layout === "2_3" ) { %>
<% } else { %>
<% } %>
<% } else { %>
<%
}
%>';
return apply_filters( 'et_builder_layout_columns', $layout_columns );
}
/**
* Display meta box in admin screen.
*/
function et_pb_pagebuilder_meta_box() {
global $typenow, $post;
do_action( 'et_pb_before_page_builder' );
if ( et_builder_bfb_enabled() ) {
$new_page_url = false;
$is_new_page = false;
$edit_page_id = get_the_ID();
$no_rtl_class = is_rtl() && 'on' === et_get_option( 'divi_disable_translations', 'off' ) ? 'et-fb-no-rtl' : '';
// Polylang creates copy of page and BFB should be loaded on page which is not saved yet and cannot be loaded on FE
// Therefore load the homepage and replace the content for BFB to make it load with content from other post.
if ( 'add' === get_current_screen()->action || (int) get_option( 'page_for_posts' ) === $edit_page_id ) {
$new_page_url = get_home_url();
$is_new_page = true;
}
$bfb_url = et_core_intentionally_unescaped( et_fb_get_bfb_url( $new_page_url, $is_new_page, $edit_page_id ), 'fixed_string' );
// If Admin is SSL but FE is not, we need to fix VB url or it won't work
// because trying to load insecure resource.
$bfb_url = set_url_scheme( $bfb_url, is_ssl() ? 'https' : 'http' );
// phpcs:disable WordPress.Security.EscapeOutput -- XSS safe.
echo "
";
// phpcs:enable
return;
}
$new_builder_url_args = array(
'action' => 'et_builder_toggle_bfb',
'enable' => '1',
'nonce' => wp_create_nonce( 'et_builder_toggle_bfb' ),
);
$new_builder_url = add_query_arg( $new_builder_url_args, admin_url( 'admin-ajax.php' ) );
// Disable BFB notification on Extra category builder. BFB support for Extra category builder will be added post inital launch
// This option available for admins only.
if ( apply_filters( 'et_pb_display_bfb_notification_under_bb', true ) && current_user_can( 'manage_options' ) && et_pb_is_allowed( 'use_visual_builder' ) && et_pb_is_allowed( 'divi_builder_control' ) ) {
echo '
';
}
echo '
';
echo '
';
$content_editor_settings = array(
'media_buttons' => true,
'tinymce' => array(
'wp_autoresize_on' => true,
),
);
wp_editor( '', 'et_pb_content', $content_editor_settings );
echo '
';
echo '
';
$description_editor_settings = array(
'media_buttons' => true,
'tinymce' => array(
'wp_autoresize_on' => true,
),
);
wp_editor( '', 'et_pb_description', $description_editor_settings );
echo '
';
echo '';
echo '
';
printf(
'
',
esc_attr( $typenow ),
! et_pb_is_allowed( 'move_module' ) ? ' et-pb-disable-sort' : ''
);
$rename_module_menu = et_pb_is_allowed( 'edit_module' ) && ( et_pb_is_allowed( 'general_settings' ) || et_pb_is_allowed( 'advanced_settings' ) || et_pb_is_allowed( 'custom_css_settings' ) ) ? sprintf(
'<%% if ( this.hasOption( "rename" ) ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Rename', 'et_builder' )
) : '';
$copy_module_menu = et_pb_is_allowed( 'add_module' ) ? sprintf(
'<%% if ( this.hasOption( "copy" ) ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Copy', 'et_builder' )
) : '';
$paste_after_menu = et_pb_is_allowed( 'add_module' ) ? sprintf(
'<%% if ( this.hasOption( "paste-after" ) ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Paste After', 'et_builder' )
) : '';
$paste_menu_item = et_pb_is_allowed( 'add_module' ) ? sprintf(
'<%% if ( this.hasOption( "paste-column" ) ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Paste', 'et_builder' )
) : '';
$paste_app_menu_item = et_pb_is_allowed( 'add_module' ) ? sprintf(
'<%% if ( this.hasOption( "paste-app" ) ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Paste', 'et_builder' )
) : '';
$save_to_lib_menu = et_pb_is_allowed( 'divi_library' ) && et_pb_is_allowed( 'save_library' ) ? sprintf(
'<%% if ( this.hasOption( "save-to-library") ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Save to Library', 'et_builder' )
) : '';
$lock_unlock_menu = et_pb_is_allowed( 'lock_module' ) ? sprintf(
'<%% if ( this.hasOption( "lock" ) ) { %%>
%1$s%2$s
<%% } %%>',
esc_html__( 'Unlock', 'et_builder' ),
esc_html__( 'Lock', 'et_builder' )
) : '';
$enable_disable_menu = et_pb_is_allowed( 'disable_module' ) ? sprintf(
'<%% if ( this.hasOption( "disable" ) ) { %%>
%1$s%2$s
<%% } %%>',
esc_html__( 'Enable', 'et_builder' ),
esc_html__( 'Disable', 'et_builder' )
) : '';
// Hide AB Testing menu if current post is Divi Library.
$is_divi_library = 'et_pb_layout' === $post->post_type;
$start_ab_testing_menu = et_pb_is_allowed( 'ab_testing' ) && ! $is_divi_library ? sprintf(
'<%% if ( this.hasOption( "start-ab-testing") ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Split Test', 'et_builder' )
) : '';
$end_ab_testing_menu = et_pb_is_allowed( 'ab_testing' ) && ! $is_divi_library ? sprintf(
'<%% if ( this.hasOption( "end-ab-testing") ) { %%>
%1$s
<%% } %%>',
esc_html__( 'End Split Test', 'et_builder' )
) : '';
$disable_global_menu = et_pb_is_allowed( 'edit_module' ) && et_pb_is_allowed( 'edit_global_library' ) ? sprintf(
'<%% if ( this.hasOption( "disable-global") ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Disable Global', 'et_builder' )
) : '';
// Right click options Template.
printf(
'',
et_core_esc_previously( $rename_module_menu ),
et_core_esc_previously( $enable_disable_menu ),
et_core_esc_previously( $lock_unlock_menu ),
et_builder_i18n( 'Expand' ),
esc_html__( 'Collapse', 'et_builder' ), // #5
et_core_esc_previously( $copy_module_menu ),
et_core_esc_previously( $paste_after_menu ),
et_core_esc_previously( $save_to_lib_menu ),
esc_html__( 'Undo', 'et_builder' ),
esc_html__( 'Redo', 'et_builder' ), // #10
et_core_esc_previously( $paste_menu_item ),
et_core_esc_previously( $paste_app_menu_item ),
et_core_esc_previously( et_pb_allowed_modules_list() ),
esc_html__( 'Preview', 'et_builder' ),
et_core_esc_previously( $start_ab_testing_menu ), // #15
et_core_esc_previously( $end_ab_testing_menu ),
et_core_esc_previously( $disable_global_menu )
);
// "Rename Module Admin Label" Modal Window Template
printf(
'',
et_builder_i18n( 'Cancel' ),
esc_attr__( 'Save', 'et_builder' )
);
// "Rename Module Admin Label" Modal Content Template
printf(
'',
esc_html__( 'Rename', 'et_builder' ),
esc_html__( 'Enter a new name for this module', 'et_builder' )
);
// Builder's Main Buttons.
$save_to_lib_button = et_pb_is_allowed( 'divi_library' ) && et_pb_is_allowed( 'save_library' ) ? sprintf(
'
%2$s
',
esc_attr__( 'Save to Library', 'et_builder' ),
esc_html__( 'Save to Library', 'et_builder' )
) : '';
$load_from_lib_button = et_pb_is_allowed( 'divi_library' ) && et_pb_is_allowed( 'load_layout' ) && et_pb_is_allowed( 'add_library' ) && et_pb_is_allowed( 'add_module' ) ? sprintf(
'
%2$s
',
esc_attr__( 'Load From Library', 'et_builder' ),
esc_html__( 'Load Layout', 'et_builder' )
) : '';
$clear_layout_button = et_pb_is_allowed( 'add_module' ) ? sprintf(
'
%2$s
',
esc_attr__( 'Clear Layout', 'et_builder' ),
esc_html__( 'Clear Layout', 'et_builder' )
) : '';
// Builder's History Buttons.
$history_button = sprintf(
'
%2$s
',
esc_attr__( 'See History', 'et_builder' ),
esc_html__( 'See History', 'et_builder' )
);
$redo_button = sprintf(
'
%2$s
',
esc_attr__( 'Redo', 'et_builder' ),
esc_html__( 'Redo', 'et_builder' )
);
$undo_button = sprintf(
'
%2$s
',
esc_attr__( 'Undo', 'et_builder' ),
esc_html__( 'Undo', 'et_builder' )
);
// App View Stats Button.
$view_ab_stats_button = sprintf(
'
%2$s
',
esc_attr__( 'View Stats', 'et_builder' ),
esc_html__( 'View Stats', 'et_builder' )
);
// App Settings Button.
$settings_button = sprintf(
'
%2$s
',
esc_attr__( 'Settings', 'et_builder' ),
esc_html__( 'Settings', 'et_builder' )
);
// App Template.
printf(
'',
et_core_esc_previously( $save_to_lib_button ),
et_core_esc_previously( $load_from_lib_button ),
et_core_esc_previously( $clear_layout_button ),
et_core_esc_previously( $history_button ),
et_core_esc_previously( $redo_button ),
et_core_esc_previously( $undo_button ),
et_core_esc_previously( $view_ab_stats_button ),
et_core_esc_previously( $settings_button )
);
// App Settings Buttons Template.
$builder_button_ab_testing_conditional = '( typeof et_pb_ab_goal === "undefined" || et_pb_ab_goal === "off" || typeof et_pb_ab_subject !== "undefined" )';
$is_ab_active = isset( $post->ID ) && 'on' === get_post_meta( $post->ID, '_et_pb_use_ab_testing', true );
$view_stats_active_class = $is_ab_active ? 'active' : '';
$view_stats_button = et_pb_is_allowed( 'ab_testing' ) ? sprintf(
'
%2$s
',
esc_attr( $view_stats_active_class ),
esc_attr__( 'View Split Testing Stats', 'et_builder' ),
esc_url( ET_BUILDER_URI )
) : '';
$portability_class = 'et-pb-app-portability-button';
if ( $is_ab_active ) {
$portability_class .= ' et-core-disabled';
}
$page_settings_button = et_pb_is_allowed( 'page_options' ) ? sprintf(
'
%2$s
',
esc_attr__( 'Settings', 'et_builder' ),
esc_html__( 'Settings', 'et_builder' ),
esc_url( ET_BUILDER_URI )
) : '';
printf(
'',
et_core_esc_previously( $page_settings_button ),
et_core_esc_previously( et_builder_portability_link( 'et_builder', array( 'class' => $portability_class ) ) ),
et_core_esc_previously( $view_stats_button )
);
// do not display settings on global sections if not allowed for current user.
$global_settings_logic = ! et_pb_is_allowed( 'edit_global_library' ) ? ' && typeof et_pb_global_module === "undefined"' : '';
$section_settings_button = sprintf(
'<%% if ( ( typeof et_pb_template_type === \'undefined\' || \'section\' === et_pb_template_type || \'\' === et_pb_template_type )%3$s ) { %%>
%2$s
<%% } %%>',
esc_attr__( 'Settings', 'et_builder' ),
esc_html__( 'Settings', 'et_builder' ),
et_core_esc_previously( $global_settings_logic )
);
$section_clone_button = sprintf(
'%3$s
%2$s
%4$s',
esc_attr__( 'Clone Section', 'et_builder' ),
esc_html__( 'Clone Section', 'et_builder' ),
'<% if ( ' . et_core_esc_previously( $builder_button_ab_testing_conditional ) . ' ) { %>',
'<% } %>'
);
$section_remove_button = sprintf(
'%3$s
%2$s
%4$s',
esc_attr__( 'Delete Section', 'et_builder' ),
esc_html__( 'Delete Section', 'et_builder' ),
'<% if ( ' . et_core_esc_previously( $builder_button_ab_testing_conditional ) . ' ) { %>',
'<% } %>'
);
$section_unlock_button = sprintf(
'
%2$s',
esc_attr__( 'Unlock Section', 'et_builder' ),
esc_html__( 'Unlock Section', 'et_builder' )
);
// Section Template.
$settings_controls = sprintf(
'
%1$s
<%% if ( typeof et_pb_template_type === \'undefined\' || ( \'section\' !== et_pb_template_type && \'row\' !== et_pb_template_type && \'module\' !== et_pb_template_type ) ) { %%>
%2$s
%3$s
<%% } %%>
%5$s
%6$s
',
et_pb_is_allowed( 'edit_module' ) && ( et_pb_is_allowed( 'general_settings' ) || et_pb_is_allowed( 'advanced_settings' ) || et_pb_is_allowed( 'custom_css_settings' ) ) ? et_core_esc_previously( $section_settings_button ) : '',
et_pb_is_allowed( 'add_module' ) ? et_core_esc_previously( $section_clone_button ) : '',
et_pb_is_allowed( 'add_module' ) ? et_core_esc_previously( $section_remove_button ) : '',
esc_attr__( 'Expand Section', 'et_builder' ),
esc_html__( 'Expand Section', 'et_builder' ),
et_pb_is_allowed( 'lock_module' ) ? et_core_esc_previously( $section_unlock_button ) : ''
);
$settings_controls = apply_filters( 'et_builder_section_settings_controls', $settings_controls );
$add_from_lib_section = et_pb_is_allowed( 'divi_library' ) && et_pb_is_allowed( 'add_library' ) ? sprintf(
'
%1$s',
esc_html__( 'Add From Library', 'et_builder' )
) : '';
$add_standard_section_button = sprintf(
'
%1$s',
esc_html__( 'Standard Section', 'et_builder' )
);
$add_standard_section_button = apply_filters( 'et_builder_add_main_section_button', $add_standard_section_button );
$add_fullwidth_section_button = sprintf(
'
%1$s',
esc_html__( 'Fullwidth Section', 'et_builder' )
);
$add_fullwidth_section_button = apply_filters( 'et_builder_add_fullwidth_section_button', $add_fullwidth_section_button );
$add_specialty_section_button = sprintf(
'
%1$s',
esc_html__( 'Specialty Section', 'et_builder' )
);
$add_specialty_section_button = apply_filters( 'et_builder_add_specialty_section_button', $add_specialty_section_button );
$settings_add_controls = sprintf(
'<%% if ( typeof et_pb_template_type === \'undefined\' || ( \'section\' !== et_pb_template_type && \'row\' !== et_pb_template_type && \'module\' !== et_pb_template_type ) ) { %%>
%1$s
%2$s
%3$s
%4$s
<%% } %%>',
et_core_esc_previously( $add_standard_section_button ),
et_core_esc_previously( $add_fullwidth_section_button ),
et_core_esc_previously( $add_specialty_section_button ),
et_core_esc_previously( $add_from_lib_section )
);
$settings_add_controls = et_pb_is_allowed( 'add_module' ) ? apply_filters( 'et_builder_section_add_controls', $settings_add_controls ) : '';
$insert_first_row_button = et_pb_is_allowed( 'add_module' ) ? sprintf(
'
%1$s
',
esc_html__( 'Insert Row(s)', 'et_builder' )
) : '';
$disable_sort_logic = ! et_pb_is_allowed( 'move_module' ) ? ' et-pb-disable-sort' : '';
$disable_global_sort_logic = ! et_pb_is_allowed( 'edit_global_library' )
? '<%= typeof et_pb_global_module !== \'undefined\' ? \' et-pb-disable-sort\' : \'\' %>'
: '';
printf(
'',
et_core_esc_previously( $settings_controls ),
et_core_esc_previously( $settings_add_controls ),
et_core_intentionally_unescaped( $disable_sort_logic, 'fixed_string' ),
et_core_intentionally_unescaped( $disable_global_sort_logic, 'fixed_string' ),
et_core_esc_previously( $insert_first_row_button )
);
$row_settings_button = sprintf(
'<%% if ( ( typeof et_pb_template_type === \'undefined\' || et_pb_template_type !== \'module\' )%3$s ) { %%>
%2$s
<%% } %%>',
esc_attr__( 'Settings', 'et_builder' ),
esc_html__( 'Settings', 'et_builder' ),
! et_pb_is_allowed( 'edit_global_library' ) ? ' && ( typeof et_pb_global_module === "undefined" || "" === et_pb_global_module ) && ( typeof et_pb_global_parent === "undefined" || "" === et_pb_global_parent )' : '' // do not display settings button on global rows if not allowed for current user.
);
$row_clone_button = sprintf(
'%3$s
%2$s
%4$s',
esc_attr__( 'Clone Row', 'et_builder' ),
esc_html__( 'Clone Row', 'et_builder' ),
! et_pb_is_allowed( 'edit_global_library' ) ? '<% if ( ( typeof et_pb_global_parent === "undefined" || "" === et_pb_global_parent ) && ' . $builder_button_ab_testing_conditional . ' ) { %>' : '<% if ( ' . $builder_button_ab_testing_conditional . ' ) { %>', // do not display clone button on rows within global sections if not allowed for current user.
'<% } %>'
);
$row_remove_button = sprintf(
'%3$s
%2$s
%4$s',
esc_attr__( 'Delete Row', 'et_builder' ),
esc_html__( 'Delete Row', 'et_builder' ),
! et_pb_is_allowed( 'edit_global_library' ) ? '<% if ( ( typeof et_pb_global_parent === "undefined" || "" === et_pb_global_parent ) && ' . $builder_button_ab_testing_conditional . ') { %>' : '<% if ( ' . $builder_button_ab_testing_conditional . ' ) { %>', // do not display clone button on rows within global sections if not allowed for current user.
'<% } %>'
);
$row_change_structure_button = sprintf(
'%3$s
%2$s
%4$s',
esc_attr__( 'Change Structure', 'et_builder' ),
esc_html__( 'Change Structure', 'et_builder' ),
! et_pb_is_allowed( 'edit_global_library' ) ? '<% if ( ( typeof et_pb_global_module === "undefined" || "" === et_pb_global_module ) && ( typeof et_pb_global_parent === "undefined" || "" === et_pb_global_parent ) ) { %>' : '', // do not display change structure button on global rows if not allowed for current user.
! et_pb_is_allowed( 'edit_global_library' ) ? '<% } %>' : ''
);
$row_unlock_button = sprintf(
'
%2$s',
esc_attr__( 'Unlock Row', 'et_builder' ),
esc_html__( 'Unlock Row', 'et_builder' )
);
// Row Template.
$settings = sprintf(
'
%1$s
<%% if ( typeof et_pb_template_type === \'undefined\' || \'section\' === et_pb_template_type ) { %%>
%2$s
<%% }
if ( typeof et_pb_template_type === \'undefined\' || et_pb_template_type !== \'module\' ) { %%>
%4$s
<%% }
if ( typeof et_pb_template_type === \'undefined\' || \'section\' === et_pb_template_type ) { %%>
%3$s
<%% } %%>
%6$s
%7$s
',
et_pb_is_allowed( 'edit_module' ) && ( et_pb_is_allowed( 'general_settings' ) || et_pb_is_allowed( 'advanced_settings' ) || et_pb_is_allowed( 'custom_css_settings' ) ) ? $row_settings_button : '',
et_pb_is_allowed( 'add_module' ) ? $row_clone_button : '',
et_pb_is_allowed( 'add_module' ) ? $row_remove_button : '',
et_pb_is_allowed( 'edit_module' ) && ( et_pb_is_allowed( 'general_settings' ) || et_pb_is_allowed( 'advanced_settings' ) || et_pb_is_allowed( 'custom_css_settings' ) ) ? $row_change_structure_button : '',
esc_attr__( 'Expand Row', 'et_builder' ),
esc_html__( 'Expand Row', 'et_builder' ),
et_pb_is_allowed( 'lock_module' ) ? $row_unlock_button : ''
);
$settings = apply_filters( 'et_builder_row_settings_controls', $settings );
$row_class = sprintf(
'class="et-pb-row-content et-pb-data-cid%1$s%2$s <%%= typeof et_pb_template_type !== \'undefined\' && \'module\' === et_pb_template_type ? \' et_pb_hide_insert\' : \'\' %%>"',
! et_pb_is_allowed( 'move_module' ) ? ' et-pb-disable-sort' : '',
! et_pb_is_allowed( 'edit_global_library' )
? sprintf( '<%%= typeof et_pb_global_parent !== \'undefined\' || typeof et_pb_global_module !== \'undefined\' ? \' et-pb-disable-sort\' : \'\' %%>' )
: ''
);
$data_skip = 'data-skip="<%= typeof( et_pb_skip_module ) === \'undefined\' ? \'false\' : \'true\' %>"';
$add_row_button = et_pb_is_allowed( 'add_module' ) ? sprintf(
'<%% if ( ( typeof et_pb_template_type === \'undefined\' || \'section\' === et_pb_template_type )%2$s ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Add Row', 'et_builder' ),
! et_pb_is_allowed( 'edit_global_library' ) ? ' && typeof et_pb_global_parent === "undefined"' : '' // do not display add row buton on global sections if not allowed for current user.
) : '';
$insert_column_button = et_pb_is_allowed( 'add_module' ) ? sprintf(
'
%1$s
',
esc_html__( 'Insert Column(s)', 'et_builder' )
) : '';
printf(
'',
et_core_esc_previously( $settings ),
et_core_intentionally_unescaped( $row_class, 'fixed_string' ),
et_core_intentionally_unescaped( $data_skip, 'fixed_string' ),
et_core_esc_previously( $insert_column_button ),
et_core_esc_previously( $add_row_button )
);
// Module Block Template.
$clone_button = et_pb_is_allowed( 'add_module' ) ? sprintf(
'<%% if ( ( typeof et_pb_template_type === \'undefined\' || et_pb_template_type !== \'module\' )%3$s && _.contains(%4$s, module_type) && ' . $builder_button_ab_testing_conditional . ' ) { %%>
%2$s
<%% } %%>',
esc_attr__( 'Clone Module', 'et_builder' ),
esc_html__( 'Clone Module', 'et_builder' ),
! et_pb_is_allowed( 'edit_global_library' ) ? ' && ( typeof et_pb_global_parent === "undefined" || "" === et_pb_global_parent )' : '',
et_pb_allowed_modules_list()
) : '';
$remove_button = et_pb_is_allowed( 'add_module' ) ? sprintf(
'<%% if ( ( typeof et_pb_template_type === \'undefined\' || et_pb_template_type !== \'module\' )%3$s && (_.contains(%4$s, module_type) || "removed" === component_status) && ' . $builder_button_ab_testing_conditional . ' ) { %%>
%2$s
<%% } %%>',
esc_attr__( 'Remove Module', 'et_builder' ),
esc_html__( 'Remove Module', 'et_builder' ),
! et_pb_is_allowed( 'edit_global_library' ) ? ' && ( typeof et_pb_global_parent === "undefined" || "" === et_pb_global_parent )' : '',
et_pb_allowed_modules_list()
) : '';
$unlock_button = et_pb_is_allowed( 'lock_module' ) ? sprintf(
'<%% if ( typeof et_pb_template_type === \'undefined\' || et_pb_template_type !== \'module\' ) { %%>
%2$s
<%% } %%>',
esc_html__( 'Unlock Module', 'et_builder' ),
esc_attr__( 'Unlock Module', 'et_builder' )
) : '';
$settings_button = et_pb_is_allowed( 'edit_module' ) && ( et_pb_is_allowed( 'general_settings' ) || et_pb_is_allowed( 'advanced_settings' ) || et_pb_is_allowed( 'custom_css_settings' ) ) ? sprintf(
'<%% if (%3$s _.contains( %4$s, module_type ) ) { %%>
%2$s
<%% } %%>',
esc_attr__( 'Module Settings', 'et_builder' ),
esc_html__( 'Module Settings', 'et_builder' ),
! et_pb_is_allowed( 'edit_global_library' ) ? ' ( typeof et_pb_global_parent === "undefined" || "" === et_pb_global_parent ) && ( typeof et_pb_global_module === "undefined" || "" === et_pb_global_module ) &&' : '',
et_pb_allowed_modules_list()
) : '';
printf(
'',
et_core_esc_previously( $settings_button ),
et_core_esc_previously( $clone_button ),
et_core_esc_previously( $remove_button ),
et_core_esc_previously( $unlock_button )
);
// Modal Template.
$can_edit_or_has_modal_view_tab = et_pb_is_allowed( 'edit_module' ) && ( et_pb_is_allowed( 'general_settings' ) || et_pb_is_allowed( 'advanced_settings' ) || et_pb_is_allowed( 'custom_css_settings' ) );
$save_exit_button = $can_edit_or_has_modal_view_tab ? sprintf(
'
%1$s
',
esc_html__( 'Save & Exit', 'et_builder' )
) : '';
$save_template_button = et_pb_is_allowed( 'divi_library' ) && et_pb_is_allowed( 'save_library' ) ? sprintf(
'<%% if ( typeof et_pb_template_type === \'undefined\' || \'\' === et_pb_template_type ) { %%>
%1$s
<%% } %%>',
esc_html__( 'Save & Add To Library', 'et_builder' )
) : '';
$preview_template_button = sprintf(
'
%1$s
',
esc_html__( 'Preview', 'et_builder' )
);
$single_button_class = ! et_pb_is_allowed( 'divi_library' ) || ! et_pb_is_allowed( 'save_library' ) ? ' et_pb_single_button' : '';
$no_editing_class = $can_edit_or_has_modal_view_tab ? '' : ' et_pb_no_editing';
printf(
'',
et_builder_i18n( 'Cancel' ),
et_core_esc_previously( $save_template_button ),
et_core_esc_previously( $save_exit_button ),
et_core_intentionally_unescaped( $single_button_class, 'fixed_string' ),
et_core_esc_previously( $preview_template_button ),
et_core_intentionally_unescaped( $no_editing_class, 'fixed_string' )
);
// Column Settings Template.
$columns_number =
'<% if ( view.model.attributes.specialty_columns === 3 ) { %>
3
<% } else { %>
2
<% } %>';
$data_specialty_columns = sprintf(
'<%% if ( typeof view !== \'undefined\' && typeof view.model.attributes.specialty_columns !== \'undefined\' ) { %%>
data-specialty_columns="%1$s"
<%% } %%>',
$columns_number
);
$saved_row_tab = et_pb_is_allowed( 'divi_library' ) && et_pb_is_allowed( 'add_library' ) ? sprintf(
'
%1$s
',
esc_html__( 'Add From Library', 'et_builder' )
) : '';
$saved_row_container = et_pb_is_allowed( 'divi_library' ) && et_pb_is_allowed( 'add_library' )
? '<% if ( ( typeof change_structure === \'undefined\' || \'true\' !== change_structure ) && ( typeof et_pb_specialty === \'undefined\' || et_pb_specialty !== \'on\' ) ) { %>
<% } %>'
: '';
printf(
'',
esc_html__( 'Insert Columns', 'et_builder' ),
et_core_intentionally_unescaped( $data_specialty_columns, 'fixed_string' ),
esc_html__( 'New Row', 'et_builder' ),
et_core_esc_previously( $saved_row_tab ),
et_core_intentionally_unescaped( et_builder_get_columns_layout(), 'fixed_string' ),
et_core_intentionally_unescaped( $saved_row_container, 'fixed_string' )
);
// "Add Module" Template
$fullwidth_class =
'<% if ( typeof module.fullwidth_only !== \'undefined\' && module.fullwidth_only === \'on\' ) { %> et_pb_fullwidth_only_module<% } %>';
$saved_modules_tab = et_pb_is_allowed( 'divi_library' ) && et_pb_is_allowed( 'add_library' ) ? sprintf(
'
%1$s
',
esc_html__( 'Add From Library', 'et_builder' )
) : '';
$saved_modules_container = et_pb_is_allowed( 'divi_library' ) && et_pb_is_allowed( 'add_library' )
? '
'
: '';
printf(
'',
esc_html__( 'Insert Module', 'et_builder' ),
esc_html__( 'New Module', 'et_builder' ),
et_core_esc_previously( $saved_modules_tab ),
et_core_intentionally_unescaped( $fullwidth_class, 'fixed_string' ),
et_core_intentionally_unescaped( $saved_modules_container, 'fixed_string' ),
et_core_esc_previously( et_pb_allowed_modules_list() )
);
// Load Layout Template.
printf(
'',
esc_html__( 'Load Layout', 'et_builder' ),
esc_html__( 'Premade Layouts', 'et_builder' ),
esc_html__( 'Your Saved Layouts', 'et_builder' )
);
// Library Account Status Error.
$root_directory = defined( 'ET_BUILDER_PLUGIN_ACTIVE' ) ? ET_BUILDER_PLUGIN_DIR : get_template_directory();
$library_i18n = require $root_directory . '/cloud/i18n/library.php';
printf(
'
',
et_core_esc_previously( $library_i18n['Uh Oh!'] ),
et_core_esc_previously( $library_i18n['$expiredAccount'] ),
et_core_esc_previously( $library_i18n['Authentication Required'] ),
et_core_esc_previously( $library_i18n['$noAccount'] ),
et_core_esc_previously( $library_i18n['Username'] ),
et_core_esc_previously( $library_i18n['$usernameHelp'] ),
et_core_esc_previously( $library_i18n['API Key'] ),
et_core_esc_previously( $library_i18n['$apiKeyHelp'] ),
et_core_esc_previously( $library_i18n['Submit'] )
);
// Library Back Button.
echo '
';
$insert_module_button = et_pb_is_allowed( 'add_module' ) ? sprintf(
'%2$s
%1$s
%3$s',
esc_html__( 'Insert Module(s)', 'et_builder' ),
! et_pb_is_allowed( 'edit_global_library' ) ? '<% if ( typeof et_pb_global_parent === "undefined" ) { %>' : '',
! et_pb_is_allowed( 'edit_global_library' ) ? '<% } %>' : ''
) : '';
// Column Template.
printf(
'',
et_core_esc_previously( $insert_module_button )
);
// Insert Row(s).
$insert_row_button = et_pb_is_allowed( 'add_module' ) ? sprintf(
'
%1$s
',
esc_html__( 'Insert Row(s)', 'et_builder' )
) : '';
// Insert Row Template.
printf(
'',
et_core_esc_previously( $insert_row_button )
);
// Advanced Settings Buttons Module.
printf(
'',
esc_html__( 'Delete', 'et_builder' ),
esc_html__( 'Settings', 'et_builder' ),
esc_html__( 'Clone Module', 'et_builder' )
);
// Advanced Settings Modal Buttons Template.
printf(
'',
et_builder_i18n( 'Cancel' ),
esc_html__( 'Save', 'et_builder' )
);
// "Deactivate Builder" Modal Message Template
printf(
'',
esc_html__( 'Disable Builder', 'et_builder' ),
esc_html__( 'All content created in the Divi Builder will be lost. Previous content will be restored.', 'et_builder' ),
esc_html__( 'Do you wish to proceed?', 'et_builder' )
);
// "Clear Layout" Modal Window Template
printf(
'',
esc_html__( 'Clear Layout', 'et_builder' ),
esc_html__( 'All of your current page content will be lost.', 'et_builder' ),
esc_html__( 'Do you wish to proceed?', 'et_builder' )
);
// "Reset Advanced Settings" Modal Template
printf(
'',
esc_html__( 'All advanced module settings in will be lost.', 'et_builder' ),
esc_html__( 'Do you wish to proceed?', 'et_builder' )
);
// "Save Layout" Modal Window Template
printf(
'',
et_builder_i18n( 'Cancel' ),
esc_html__( 'Save', 'et_builder' )
);
// "Save Layout" Modal Content Template
printf(
'',
esc_html__( 'Save To Library', 'et_builder' ),
esc_html__( 'Save your current page to the Divi Library for later use.', 'et_builder' ),
esc_html__( 'Layout Name', 'et_builder' )
);
// "Delete Font" Modal Text
printf(
'',
esc_html__( 'Delete Font', 'et_builder' ),
sprintf( '%1$s %2$s?', esc_html__( 'Are you sure want to delete', 'et_builder' ), '<%= font_name %>' )
);
// "Upload Font" Modal Template
printf(
'',
et_builder_i18n( 'Cancel' ),
esc_html__( 'Upload', 'et_builder' )
);
// "Upload Font" Modal Text
printf(
'',
esc_html__( 'Upload Font', 'et_builder' ),
esc_html__( 'Font Name', 'et_builder' ),
esc_html__( 'Drag Files Here', 'et_builder' ),
esc_html__( 'Choose Font Files', 'et_builder' ),
esc_html__( 'Supported Font Weights', 'et_builder' ),
esc_html__( 'All', 'et_builder' ),
esc_html__( 'Supported File Formats', 'et_builder' ),
esc_html__( 'Selected Font Files', 'et_builder' ),
esc_html__( 'Choose the font weights supported by your font. Select "All" if you don\'t know this information or if your font includes all weights.', 'et_builder' ),
et_core_esc_previously( et_generate_font_weight_select_output() )
);
// "Save Template" Modal Window Layout
printf(
'',
esc_attr__( 'Save And Add To Library', 'et_builder' )
);
// "Save Template" Content Layout
$layout_categories = get_terms( 'layout_category', array( 'hide_empty' => false ) );
$categories_output = sprintf(
'
';
}
$categories_output .= sprintf(
'
',
esc_html__( 'Create New Category', 'et_builder' )
);
$general_checkbox = sprintf(
'
',
esc_html__( 'Include General settings', 'et_builder' )
);
$advanced_checkbox = sprintf(
'
',
esc_html__( 'Include Advanced Design settings', 'et_builder' )
);
$css_checkbox = sprintf(
'
',
esc_html__( 'Include Custom CSS', 'et_builder' )
);
printf(
'',
esc_html__( 'Here you can save the current item and add it to your Divi Library for later use as well.', 'et_builder' ),
esc_html__( 'Template Name', 'et_builder' ),
esc_html__( 'Save as Global:', 'et_builder' ),
esc_html__( 'Make this a global item', 'et_builder' ),
et_core_esc_previously( $categories_output )
);
// Prompt Modal Window Template.
printf(
'',
et_builder_i18n( 'No' ),
et_builder_i18n( 'Yes' )
);
// "Open Settings" Modal Window Template
printf(
'',
et_builder_i18n( 'Cancel' ),
esc_html__( 'Save', 'et_builder' )
);
$utils = ET_Core_Data_Utils::instance();
$fields = array();
// Filter out fields not supposed to show in BB.
foreach ( ET_Builder_Settings::get_fields() as $key => $field ) {
if ( true === $utils->array_get( $field, 'show_in_bb', true ) ) {
$fields[ $key ] = $field;
}
}
// "Open Settings" Modal Content Template
printf(
'',
esc_html__( 'Divi Builder Settings', 'et_builder' ),
et_core_esc_previously( et_pb_get_builder_settings_fields( $fields ) )
);
// AB Testing.
$ab_testing = et_builder_ab_labels();
// "Turn off AB Testing" Modal Window Template
printf(
'',
et_builder_i18n( 'Cancel' ),
et_builder_i18n( 'Yes' )
);
// "Turn off AB Testing" Modal Content Template
printf(
'',
esc_html__( 'End Split Test?', 'et_builder' ),
esc_html__( 'Upon ending your split test, you will be asked to select which subject variation you would like to keep. Remaining subjects will be removed.', 'et_builder' ),
esc_html__( 'Note: this process cannot be undone.', 'et_builder' )
);
// AB Testing Alert :: Modal Window Template.
printf(
'',
esc_html__( 'Ok', 'et_builder' )
);
// AB Testing Alert :: Modal Content Template.
printf(
'',
esc_html__( 'An Error Occurred', 'et_builder' ),
esc_html__( 'For some reason, you cannot perform this task.', 'et_builder' )
);
// AB Testing Alert Yes/No :: Modal Window Template.
printf(
'',
et_builder_i18n( 'Cancel' ),
esc_html__( 'Proceed', 'et_builder' )
);
// AB Testing Alert Yes/No :: Modal Content Template.
printf(
'',
esc_html__( 'An Error Occurred', 'et_builder' ),
esc_html__( 'For some reason, you cannot perform this task.', 'et_builder' )
);
/**
* Split Testing :: Set global item winner status
*/
printf(
'',
et_core_esc_previously( $ab_testing['set_global_winner_status']['cancel'] ),
et_core_esc_previously( $ab_testing['set_global_winner_status']['proceed'] )
);
// AB Testing :: Set global item winner status template.
printf(
'',
et_core_esc_previously( $ab_testing['set_global_winner_status']['title'] ),
et_core_esc_previously( $ab_testing['set_global_winner_status']['desc'] ),
et_core_esc_previously( $ab_testing['set_global_winner_status']['option_1'] ),
et_core_esc_previously( $ab_testing['set_global_winner_status']['option_2'] )
);
/**
* AB Testing :: View Stats Template
*/
printf(
'',
et_builder_i18n( 'Cancel' )
);
$view_stats_tabs = '';
foreach ( et_pb_ab_get_analysis_types() as $analysis ) {
$view_stats_tabs .= sprintf(
'
',
esc_attr( $analysis ),
esc_html__( 'Last 24 Hours', 'et_builder' ),
esc_html__( 'Last 7 Days', 'et_builder' ),
esc_html__( 'Last Month', 'et_builder' ),
esc_html__( 'All Time', 'et_builder' ),
esc_html__( 'Summary & Data', 'et_builder' ),
esc_url( ET_BUILDER_URI ),
esc_html__( 'Statistics are still being collected for this time frame', 'et_builder' ),
esc_html__( 'Stats will be displayed upon sufficient data collection', 'et_builder' )
);
}
// AB Testing :: View Stats content.
printf(
'',
esc_html__( 'Split Testing Statistics', 'et_builder' ),
esc_html__( 'Clicks', 'et_builder' ),
esc_html__( 'Reads', 'et_builder' ),
esc_html__( 'Bounces', 'et_builder' ),
esc_html__( 'Goal Engagement', 'et_builder' ), // 5
esc_html__( 'Conversions', 'et_builder' ),
et_core_esc_previously( $view_stats_tabs ),
esc_url( ET_BUILDER_URI ),
esc_html__( 'Statistics are being collected', 'et_builder' ),
esc_html__( 'Stats will be displayed upon sufficient data collection', 'et_builder' ), // 10
esc_attr__( 'Refresh Stats', 'et_builder' ),
esc_html__( 'Refresh Stats', 'et_builder' ),
esc_html__( 'Shortcode Conversions', 'et_builder' ),
esc_attr__( 'End Split Test & Pick Winner', 'et_builder' )
);
// "Add Specialty Section" Button Template
printf(
'',
esc_html__( 'Add Specialty Section', 'et_builder' )
);
// Saved Entry Template.
echo '';
// Font Family Select Template.
$font_marker = et_pb_is_allowed( 'custom_fonts_management' ) ? '
' : '';
$upload_button = et_pb_is_allowed( 'custom_fonts_management' ) ? sprintf( '
', esc_html__( 'Upload', 'et_builder' ) ) : '';
printf(
'',
esc_html__( 'Uploaded', 'et_builder' ),
et_core_intentionally_unescaped( $font_marker, 'fixed_string' ),
et_core_esc_previously( $upload_button ),
et_core_esc_previously( et_builder_get_google_font_items() )
);
// Font Icons Template.
printf(
'',
et_core_esc_previously( et_pb_get_font_icon_list_items() )
);
// Histories Visualizer Item Template.
printf(
''
);
// Font Down Icons Template.
printf(
'',
et_core_esc_previously( et_pb_get_font_down_icon_list_items() )
);
printf(
'',
esc_html__( 'Mobile', 'et_builder' ),
et_builder_i18n( 'Tablet' ),
et_builder_i18n( 'Desktop' )
);
printf(
''
);
printf(
'',
et_builder_i18n( 'Desktop' ),
et_builder_i18n( 'Tablet' ),
esc_html__( 'Smartphone', 'et_builder' )
);
printf(
'',
et_builder_i18n( 'Default' ),
esc_html__( 'Hover', 'et_builder' )
);
printf(
'',
et_builder_i18n( 'Desktop' ),
esc_html__( 'Hover', 'et_builder' ),
et_builder_i18n( 'Tablet' ),
esc_html__( 'Smartphone', 'et_builder' )
);
printf(
''
);
printf(
''
);
printf(
''
);
print(
''
);
print(
''
);
print(
''
);
print(
''
);
printf(
''
);
printf(
'',
esc_html__( 'Font Weight', 'et_builder' )
);
printf(
'',
esc_html__( 'Font Style', 'et_builder' )
);
printf(
'',
esc_html__( 'Line Color', 'et_builder' ),
esc_attr__( 'Hex Value', 'et_builder' ),
esc_attr__( 'Line Style', 'et_builder' ),
esc_attr__( 'Choose Custom Color', 'et_builder' ),
esc_attr__( 'Underline', 'et_builder' ),
esc_attr__( 'Strikethrough', 'et_builder' ),
esc_attr__( 'Color', 'et_builder' ),
esc_attr__( 'Style', 'et_builder' )
);
printf(
''
);
printf(
''
);
printf(
'',
et_core_esc_previously( et_builder_get_failure_notification_modal() )
);
printf(
'',
et_core_esc_previously( et_builder_get_cache_notification_modal() )
);
printf(
'',
et_core_esc_previously( et_builder_page_creation_modal() )
);
// Help Template.
printf(
'',
esc_html__( 'Divi Builder Helper', 'et_builder' ),
esc_html__( 'Shortcuts', 'et_builder' )
);
do_action( 'et_pb_after_page_builder' );
}
/**
* Returns builder settings markup
*
* @param array $options builder settings' configuration.
* @return string builder settings' markup
*/
function et_pb_get_builder_settings_fields( $options ) {
$outputs = '';
$defaults = et_pb_get_builder_settings_configuration_default();
foreach ( $options as $option ) {
$option = wp_parse_args( $option, $defaults );
$type = $option['type'];
$field_list_class = $type;
$affecting = ! empty( $option['affects'] ) ? implode( '|', $option['affects'] ) : '';
if ( $option['depends_show_if'] ) {
$field_list_class .= ' et-pb-display-conditionally';
}
if ( isset( $option['class'] ) ) {
$field_list_class .= ' ' . $option['class'];
}
$outputs .= sprintf(
'
',
esc_attr( $field_list_class ),
esc_attr( $option['id'] ),
esc_attr( $type ),
esc_attr( $option['autoload'] ),
esc_attr( $affecting ),
esc_attr( $option['depends_show_if'] )
);
switch ( $option['type'] ) {
case 'yes_no_button':
$outputs .= sprintf(
'
',
esc_attr( $option['id'] ),
esc_html( $option['label'] ),
isset( $option['values'] ) ? esc_html( $option['values']['yes'] ) : et_builder_i18n( 'Yes' ),
isset( $option['values'] ) ? esc_html( $option['values']['no'] ) : et_builder_i18n( 'No' ),
et_builder_i18n( 'Off' ),
et_builder_i18n( 'On' )
);
break;
case 'codemirror':
case 'textarea':
$outputs .= sprintf(
'
',
esc_attr( $option['id'] ),
esc_html( $option['label'] ),
isset( $option['readonly'] ) && 'readonly' === $option['readonly'] ? ' readonly' : ''
);
break;
case 'colorpalette':
$outputs .= sprintf( '
', esc_html( $option['label'] ) );
$outputs .= '
';
for ( $colorpalette_index = 1; $colorpalette_index < 9; $colorpalette_index++ ) {
$outputs .= sprintf( '', esc_attr( $colorpalette_index ) );
}
$outputs .= '
';
for ( $colorpicker_index = 1; $colorpicker_index < 9; $colorpicker_index++ ) {
$outputs .= sprintf(
'
',
esc_attr( $option['id'] ),
esc_attr( $colorpicker_index )
);
}
$outputs .= '
';
break;
case 'color-alpha':
$outputs .= sprintf(
'
',
esc_attr( $option['id'] ),
esc_html( $option['label'] ),
esc_attr( $option['default'] )
);
break;
case 'range':
$outputs .= sprintf(
'
',
esc_attr( $option['id'] ),
esc_html( $option['label'] ),
esc_attr( $option['range_settings']['step'] ),
esc_attr( $option['range_settings']['min'] ),
esc_attr( $option['range_settings']['max'] )
);
break;
case 'select':
$options = '';
foreach ( $option['options'] as $value => $text ) {
$options .= sprintf(
'
',
esc_attr( $value ),
esc_html( $text )
);
}
$outputs .= sprintf(
'
',
esc_attr( $option['id'] ),
esc_html( $option['label'] ),
et_core_esc_previously( $options )
);
break;
}
$outputs .= sprintf( '
', esc_attr( $option['type'] ) );
}
return $outputs;
}
/**
* Prints hidden inputs for passing settings data to database
*
* @param integer $post_id post id.
*
* @return void|bool
*/
function et_pb_builder_settings_hidden_inputs( $post_id ) {
if ( ! class_exists( 'ET_Builder_Settings' ) ) {
return false;
}
$settings = ET_Builder_Settings::get_fields();
$defaults = et_pb_get_builder_settings_configuration_default();
if ( empty( $settings ) ) {
return;
}
if ( empty( $settings ) ) {
return;
}
foreach ( $settings as $setting ) {
$setting = wp_parse_args( $setting, $defaults );
if ( ! $setting['autoload'] ) {
continue;
}
$id = '_' . $setting['id'];
$meta_key = isset( $setting['meta_key'] ) ? $setting['meta_key'] : $id;
$value = get_post_meta( $post_id, $meta_key, true );
if ( ( ! $value || '' === $value ) && $setting['default'] ) {
$value = $setting['default'];
}
printf(
'
',
esc_attr( $id ),
esc_attr( $value )
);
}
}
/**
* Prints hidden inputs for passing global modules data to database.
*
* @param integer $post_id post id.
*
* @return void
*/
function et_pb_builder_global_library_inputs( $post_id ) {
global $typenow;
if ( 'et_pb_layout' !== $typenow ) {
return;
}
$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 ) {
return;
}
$excluded_global_options = get_post_meta( $post_id, '_et_pb_excluded_global_options' );
printf(
'
',
isset( $excluded_global_options[0] ) ? esc_attr( $excluded_global_options[0] ) : wp_json_encode( array() )
);
}
/**
* Returns array of default builder settings configuration item
*
* @return array
*/
function et_pb_get_builder_settings_configuration_default() {
return array(
'id' => '',
'type' => '',
'label' => '',
'min' => '',
'max' => '',
'step' => '',
'autoload' => true,
'default' => false,
'affects' => array(),
'depends_show_if' => false,
);
}
/**
* Update a builder setting.
*
* @param array $settings The new option value.
* @param string $post_id The post id or 'global' for global settings.
*/
function et_builder_update_settings( $settings, $post_id = 'global' ) {
// Allow the use of uppercase in $is_bb variable as BB is common abbreviation.
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();
$update = array();
foreach ( (array) $settings as $setting_key => $setting_value ) {
$raw_setting_value = $setting_value;
$setting_key = $is_bb ? substr( $setting_key, 1 ) : $setting_key;
// Verify setting key.
if ( ! isset( $fields[ $setting_key ] ) || ! isset( $fields[ $setting_key ]['type'] ) ) {
continue;
}
// 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
// Sanitize value.
switch ( $fields[ $setting_key ]['type'] ) {
case 'colorpalette':
$palette_colors = explode( '|', $setting_value );
$setting_value = implode( '|', array_map( 'et_sanitize_alpha_color', $palette_colors ) );
break;
case 'range':
// Avoid setting absolute value for range if option is z_index.
if ( 'et_pb_page_z_index' === $setting_key ) {
break;
}
$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 ) {
continue 2;
}
break;
case 'color-alpha':
$setting_value = et_sanitize_alpha_color( $setting_value );
break;
case 'codemirror':
case 'textarea':
// Allow HTML content on Excerpt field.
if ( 'et_pb_post_settings_excerpt' === $setting_key ) {
$setting_value = wp_kses_post( $setting_value );
} else {
$setting_value = sanitize_textarea_field( $setting_value );
}
break;
case 'categories':
$setting_value = array_map( 'intval', explode( ',', $setting_value ) );
break;
default:
$setting_value = sanitize_text_field( $setting_value );
break;
}
// 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 ) {
// Only allowed in VB.
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;
}
continue;
}
// 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 ) {
// Only allowed in VB.
if ( ! ( $is_global || $is_bb ) ) {
$post_type = $utils->array_get( $fields, "{$setting_key}.post_type", false );
if ( get_post_type( $post_id ) === $post_type ) {
// Only update if the post type matches.
wp_set_object_terms( $post_id, $setting_value, $taxonomy_name );
}
}
continue;
}
// 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 && false === $save_post ) {
// This meta key must be ignored during classic-editor / BB save action or it will
// overwrite values in the WP edit page.
continue;
}
// remove if value is default.
if ( $is_default ) {
$is_global ? et_delete_option( $setting_key ) : delete_post_meta( $post_id, $meta_key );
} else {
// Update.
$is_global ? et_update_option( $setting_key, $setting_value ) : update_post_meta( $post_id, $meta_key, $setting_value );
}
// Removing autosave.
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.
*
* @param integer $post_id post id.
*
* @return array default color palette
*/
function et_pb_get_default_color_palette( $post_id = 0 ) {
$default_palette = array(
'#000000',
'#FFFFFF',
'#E02B20',
'#E09900',
'#EDF000',
'#7CDA24',
'#0C71C3',
'#8300E9',
);
$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
*
* @param array $mce_init An array with TinyMCE config.
* @param string $editor_id Unique editor identifier.
*
* @return array
*/
function et_pb_content_mce_config( $mce_init, $editor_id ) {
if ( 'et_pb_content' === $editor_id && isset( $mce_init['toolbar1'] ) ) {
// Get toolbar as array.
$toolbar1 = explode( ',', $mce_init['toolbar1'] );
// Look for read more (wp_more)'s array' key.
$wp_more_key = array_search( 'wp_more', $toolbar1, true );
if ( $wp_more_key ) {
unset( $toolbar1[ $wp_more_key ] );
}
// Update toolbar1 configuration.
$mce_init['toolbar1'] = implode( ',', $toolbar1 );
}
return $mce_init;
}
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
* @see get_post_format()
*
* @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.
*
* @param string $post_format post format.
* @param integer $post_id post id.
*
* @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 ) ) {
return false;
}
return $post_format;
}
add_filter( 'et_pb_post_format', 'et_pb_post_format_in_pagebuilder', 10, 2 );
if ( ! function_exists( 'et_get_first_audio_block' ) ) :
/**
* Return the first audio block from the post content.
*/
function et_get_first_audio_block() {
$content = get_the_content();
// It is assumed that audio module figures will not contain other figures.
preg_match( '/
]*?class=([\'"])[^\'"]*?wp-block-audio[^\'"]*?\1[^>]*?>.*?<\/figure>/', $content, $matches );
if ( empty( $matches ) ) {
return '';
}
return $matches[0];
}
endif;
if ( ! function_exists( 'et_pb_get_audio_player' ) ) :
/**
* Return audio player.
*/
function et_pb_get_audio_player() {
global $_et_pbgap_audio_to_remove;
$shortcode_audio = '';
$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 );
break;
}
}
if ( '' === $shortcode_audio ) {
$_et_pbgap_audio_to_remove = et_get_first_audio_block();
$shortcode_audio = $_et_pbgap_audio_to_remove;
}
if ( '' === $shortcode_audio ) {
return false;
}
$output = sprintf(
'
%1$s
',
$shortcode_audio
);
add_filter( 'the_content', 'et_delete_post_audio' );
return $output;
}
endif;
if ( ! function_exists( 'et_divi_post_format_content' ) ) :
/**
* Displays post audio, quote and link post formats 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();
global $post;
if ( post_password_required( $post ) ) {
return;
}
switch ( $post_format ) {
case 'audio':
printf(
'',
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 )
);
break;
case 'quote':
printf(
'',
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 )
);
break;
case 'link':
printf(
'',
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 )
);
break;
}
}
endif;
if ( ! function_exists( 'et_get_blockquote_in_content' ) ) :
/**
* Extract and return the first blockquote from content.
*/
function et_get_blockquote_in_content() {
global $more;
$more_default = $more;
$more = 1; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Disable `$more` flag to get the blockquote that may exist after tag.
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.Prohibited -- Restore default `$more` flag.
if ( preg_match( '//is', $content, $matches ) ) {
return $matches[0];
} else {
return false;
}
}
endif;
if ( ! function_exists( 'et_get_link_url' ) ) :
/**
* Return link from the post content.
*/
function et_get_link_url() {
$link_url = get_post_meta( get_the_ID(), '_format_link_url', true );
if ( '' !== $link_url ) {
return $link_url;
}
$content = get_the_content();
$has_url = get_url_in_content( $content );
return ( $has_url ) ? $has_url : apply_filters( 'the_permalink', get_permalink() );
}
endif;
if ( ! function_exists( 'et_get_first_video' ) ) :
/**
* Fix the issue with thumbnail video player, not working, when video url is added to content without shortcode
*/
function et_get_first_video() {
$first_url = '';
$first_video = '';
$video_width = (int) apply_filters( 'et_blog_video_width', 1080 );
$video_height = (int) apply_filters( 'et_blog_video_height', 630 );
$i = 0;
$content = get_the_content();
preg_match_all( '|^\s*https?://[^\s"]+\s*$|im', $content, $urls );
foreach ( $urls[0] as $url ) {
$i++;
if ( 1 === $i ) {
$first_url = trim( $url );
}
$oembed = wp_oembed_get( esc_url( $url ) );
if ( ! $oembed ) {
continue;
}
$first_video = $oembed;
$first_video = preg_replace( '/