: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
// Format AB Testing data, since BB has UI and actual input IDs. FB uses BB's UI ID
$builder_settings['et_pb_enable_ab_testing'] = $builder_settings['et_pb_use_ab_testing'];
// Unset BB's actual input data
unset( $builder_settings['et_pb_use_ab_testing'] );
// Pseudo save AB Testing subjects for VB draft/builder-sync interface
if ( isset( $builder_settings['et_pb_ab_subjects'] ) ) {
// Save autosave/draft subjects
'_et_pb_ab_subjects_draft',
sanitize_text_field( et_prevent_duplicate_item( $builder_settings['et_pb_ab_subjects'], ',' ) )
// Format subjects data into array
$builder_settings['et_pb_ab_subjects'] = array_unique( explode( ',', $builder_settings['et_pb_ab_subjects'] ) );
$et_builder_settings_autosave_data = get_post_meta( $post_id, "_et_builder_settings_autosave_{$current_user_id}", true );
// Merge incoming post meta changes with saved ones to avoid missing post meta changes that
// has been synced but hasn't been delivered to VB. Let VB drops autosave once it has been
// used / inserted into the layout
if ( is_array( $et_builder_settings_autosave_data ) && is_array( $builder_settings ) ) {
$et_builder_settings_autosave_data = wp_parse_args(
$et_builder_settings_autosave_data
$et_builder_settings_autosave_data = $builder_settings;
"_et_builder_settings_autosave_{$current_user_id}",
$et_builder_settings_autosave_data
* Autosave with heartbeat
* @copyright 2016 by the WordPress contributors.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* This program incorporates work covered by the following copyright and
* b2 is (c) 2001, 2002 Michel Valdrighi - m@tidakada.com - http://tidakada.com
* b2 is released under the GPL
* WordPress - Web publishing software
* Copyright 2003-2010 by the contributors
* WordPress is released under the GPL
* @param array $response The Heartbeat response.
* @param array $data The $_POST data sent.
* @return array The Heartbeat response.
function et_fb_heartbeat_autosave( $response, $data ) {
et_core_nonce_verified_previously();
if ( ! current_user_can( 'edit_posts' ) ) {
if ( ! empty( $data['et_fb_autosave'] ) ) {
$post_id = ! empty( $data['et_fb_autosave']['post_id'] ) ? absint( $data['et_fb_autosave']['post_id'] ) : '';
if ( empty( $post_id ) || ! current_user_can( 'edit_post', $post_id ) ) {
$has_focus = !empty( $_POST['has_focus'] ) && 'true' === $_POST['has_focus'];
$force_autosave = !empty( $data['et'] ) && !empty( $data['et']['force_autosave'] ) && 'true' === $data['et']['force_autosave'];
$editor_1 = 'fb' === $data['et']['built_by'] ? 'fb' : 'bb';
$editor_2 = 'fb' === $editor_1 ? 'bb' : 'fb';
$editor_1_editing_cookie = isset( $_COOKIE[ 'et-editing-post-' . $post_id . '-' . $editor_1 ] ) ? $_COOKIE[ 'et-editing-post-' . $post_id . '-' . $editor_1 ] : false;
$editor_2_editor_available_cookie = isset( $_COOKIE[ 'et-editor-available-post-' . $post_id . '-' . $editor_2 ] ) ? $_COOKIE[ 'et-editor-available-post-' . $post_id . '-' . $editor_2 ] : false;
$editor_1_autosavable = !empty( $editor_1_editing_cookie ) && empty( $editor_2_editor_available_cookie );
if ( !$has_focus && !$force_autosave && !$editor_1_autosavable ) {
$response['et_fb_autosave'] = array( 'success' => false, 'message' => __( 'Not saved, editor out of focus', 'et_builder' ) );
$saved = et_fb_autosave( $data['et_fb_autosave'] );
if ( ! is_wp_error( $saved ) && ! empty( $data['et_fb_autosave']['builder_settings'] ) ) {
$builder_settings_autosaved = et_pb_autosave_builder_settings( $post_id, $data['et_fb_autosave']['builder_settings'] );
$response['et_pb_autosave_builder_settings'] = array( 'success' => $builder_settings_autosaved, 'message' => __( 'Builder settings synced', 'et_builder' ) );
if ( is_wp_error( $saved ) ) {
$response['et_fb_autosave'] = array( 'success' => false, 'message' => $saved->get_error_message() );
} elseif ( empty( $saved ) ) {
$response['et_fb_autosave'] = array( 'success' => false, 'message' => __( 'Error while saving.', 'et_builder' ) );
/* translators: draft saved date format, see https://secure.php.net/date */
$draft_saved_date_format = __( 'g:i:s a', 'et_builder' );
/* translators: %s: date and time */
$response['et_fb_autosave'] = array( 'success' => true, 'message' => sprintf( __( 'Draft saved at %s.', 'et_builder' ), date_i18n( $draft_saved_date_format ) ) );
add_filter( 'heartbeat_received', 'et_fb_heartbeat_autosave', 499, 2 );
function et_bb_heartbeat_autosave( $response, $data ) {
et_core_nonce_verified_previously();
if ( ! current_user_can( 'edit_posts' ) ) {
if ( ! empty( $data['wp_autosave'] ) ) {
$has_focus = !empty( $_POST['has_focus'] ) && 'true' === $_POST['has_focus'];
$force_autosave = !empty( $data['et'] ) && !empty( $data['et']['force_autosave'] ) && 'true' === $data['et']['force_autosave'];
if ( !$has_focus && !$force_autosave ) {
$response['wp_autosave'] = array( 'success' => true, 'message' => __( 'Not saved, editor out of focus', 'et_builder' ) );
remove_filter( 'heartbeat_received', 'heartbeat_autosave', 500, 2 );
remove_filter( 'heartbeat_received', 'et_bb_heartbeat_builder_settings_autosave', 500, 2 );
} else if ( $force_autosave ) {
$response['wp_autosave_check'] = array( 'success' => true, 'message' => 'saved, because force_autosave ' );
add_filter( 'heartbeat_received', 'et_bb_heartbeat_autosave', 498, 2 );
function et_bb_heartbeat_builder_settings_autosave( $response, $data ) {
if ( ! current_user_can( 'edit_posts' ) ) {
if ( ! empty( $data['wp_autosave'] ) ) {
$post_id = ! empty( $data['wp_autosave']['post_id'] ) ? absint( $data['wp_autosave']['post_id'] ) : '';
if ( empty( $post_id ) || ! current_user_can( 'edit_post', $post_id ) ) {
if ( ! empty( $data['wp_autosave']['builder_settings'] ) ) {
$builder_settings_autosaved = et_pb_autosave_builder_settings( $post_id, $data['wp_autosave']['builder_settings'] );
$response['et_pb_autosave_builder_settings'] = array( 'success' => $builder_settings_autosaved, 'message' => __( 'Builder settings synced', 'et_builder' ) );
add_filter( 'heartbeat_received', 'et_bb_heartbeat_builder_settings_autosave', 500, 2 );
function et_fb_wp_refresh_nonces( $response, $data, $screen_id ) {
if ( ! current_user_can( 'edit_posts' ) ) {
if ( ! isset( $data['et']['built_by'] ) || 'fb' !== $data['et']['built_by'] ) {
'exportUrl' => et_fb_get_portability_export_url(),
'nonces' => et_fb_get_nonces(),
'heartbeat_nonce' => wp_create_nonce( 'heartbeat-nonce' ),
add_filter( 'wp_refresh_nonces', 'et_fb_wp_refresh_nonces', 10, 3 );
function et_fb_get_portability_export_url() {
$admin_url = is_ssl() ? admin_url() : admin_url( '', 'http' );
'et_core_portability' => true,
'context' => 'et_builder',
'nonce' => wp_create_nonce( 'et_core_portability_nonce' ),
return add_query_arg( $args, $admin_url );
function et_fb_get_nonces() {
$nonces = apply_filters( 'et_fb_nonces', array() );
'moduleContactFormSubmit' => wp_create_nonce( 'et-pb-contact-form-submit' ),
'et_admin_load' => wp_create_nonce( 'et_admin_load_nonce' ),
'computedProperty' => wp_create_nonce( 'et_pb_process_computed_property_nonce' ),
'renderShortcode' => wp_create_nonce( 'et_pb_render_shortcode_nonce' ),
'updateAssets' => wp_create_nonce( 'et_fb_update_helper_assets_nonce' ),
'loadAssets' => wp_create_nonce( 'et_fb_load_helper_assets_nonce' ),
'renderSave' => wp_create_nonce( 'et_fb_save_nonce' ),
'convertToShortcode' => wp_create_nonce( 'et_fb_convert_to_shortcode_nonce' ),
'dropAutosave' => wp_create_nonce( 'et_fb_drop_autosave_nonce' ),
'prepareShortcode' => wp_create_nonce( 'et_fb_prepare_shortcode_nonce' ),
'processImportedData' => wp_create_nonce( 'et_fb_process_imported_data_nonce' ),
'retrieveLibraryModules' => wp_create_nonce( 'et_fb_retrieve_library_modules_nonce' ),
'saveLibraryModules' => wp_create_nonce( 'et_fb_save_library_modules_nonce' ),
'preview' => wp_create_nonce( 'et_pb_preview_nonce' ),
'autosave' => wp_create_nonce( 'et_fb_autosave_nonce' ),
'moduleEmailOptinFetchLists' => wp_create_nonce( 'et_builder_email_fetch_lists_nonce' ),
'moduleEmailOptinAddAccount' => wp_create_nonce( 'et_builder_email_add_account_nonce' ),
'moduleEmailOptinRemoveAccount' => wp_create_nonce( 'et_builder_email_remove_account_nonce' ),
'uploadFontNonce' => wp_create_nonce( 'et_fb_upload_font_nonce' ),
'abTestingReport' => wp_create_nonce( 'ab_testing_builder_nonce' ),
'libraryLayoutsData' => wp_create_nonce( 'et_builder_library_get_layouts_data' ),
'libraryGetLayout' => wp_create_nonce( 'et_builder_library_get_layout' ),
'libraryUpdateAccount' => wp_create_nonce( 'et_builder_library_update_account' ),
'fetchAttachments' => wp_create_nonce( 'et_fb_fetch_attachments' ),
'droploaderProcess' => wp_create_nonce( 'et_builder_droploader_process_nonce' ),
'resolvePostContent' => wp_create_nonce( 'et_fb_resolve_post_content' ),
'searchProducts' => wp_create_nonce( 'et_builder_search_products' ),
'searchPosts' => wp_create_nonce( 'et_builder_search_posts' ),
'getPostsList' => wp_create_nonce( 'et_fb_get_posts_list' ),
'sendErrorReport' => wp_create_nonce( 'et_fb_send_error_report' ),
'saveGlobalPresetsHistory' => wp_create_nonce( 'et_builder_save_global_presets_history' ),
'retrieveGlobalPresetsHistory' => wp_create_nonce( 'et_builder_retrieve_global_presets_history' ),
'migrateModuleCustomizerPhaseTwo' => wp_create_nonce( 'et_builder_migrate_module_customizer_phase_two' ),
'getWoocommerceTabs' => wp_create_nonce( 'et_builder_get_woocommerce_tabs' ),
return array_merge( $nonces, $fb_nonces );
if ( ! function_exists( 'et_builder_is_product_tour_enabled' ) ):
function et_builder_is_product_tour_enabled() {
static $product_tour_enabled = null;
if ( null !== $product_tour_enabled ) {
return $product_tour_enabled;
if ( ! ( function_exists( 'et_fb_is_enabled' ) && et_fb_is_enabled() ) ) {
// Do not update `$product_tour_enabled` at this point since we can run et_builder_is_product_tour_enabled() check later
// when et_fb_is_enabled() will be available.
* Filters the on/off status of the product tour for the current user.
* @param string $product_tour_status_override Accepts 'on', 'off'.
$product_tour_status_override = apply_filters( 'et_builder_product_tour_status_override', false );
if ( false !== $product_tour_status_override ) {
$product_tour_enabled = 'on' === $product_tour_status_override;
$user_id = (int) get_current_user_id();
$product_tour_settings = et_get_option( 'product_tour_status', array() );
$product_tour_status_global = 'on' === et_get_option( 'et_pb_product_tour_global', 'on' );
$product_tour_enabled = $product_tour_status_global && ( ! isset( $product_tour_settings[ $user_id ] ) || 'on' === $product_tour_settings[ $user_id ] );
return $product_tour_enabled;
function et_pb_get_backbone_template() {
if ( ! wp_verify_nonce( $_POST['et_admin_load_nonce'], 'et_admin_load_nonce' ) ) {
if ( ! current_user_can( 'edit_posts' ) ) {
$module_slugs = json_decode( str_replace( '\\', '', sanitize_text_field( $_POST['et_modules_slugs'] ) ) );
$post_type = sanitize_text_field( $_POST['et_post_type'] );
// Enable zlib compression
et_builder_enable_zlib_compression();
// get the portion of templates for specified slugs
$result = wp_json_encode( ET_Builder_Element::get_modules_templates( $post_type, $module_slugs->missing_modules_array ) );
die( et_core_esc_previously( $result ) );
add_action( 'wp_ajax_et_pb_get_backbone_template', 'et_pb_get_backbone_template' );
if ( ! function_exists( 'et_builder_email_add_account' ) ):
* Ajax handler for the Email Opt-in Module's "Add Account" action.
function et_builder_email_add_account() {
et_core_security_check( 'manage_options', 'et_builder_email_add_account_nonce' );
$provider_slug = isset( $_POST['et_provider'] ) ? sanitize_text_field( $_POST['et_provider'] ) : '';
$name_key = "et_{$provider_slug}_account_name";
$account_name = isset( $_POST[ $name_key ] ) ? sanitize_text_field( $_POST[ $name_key ] ) : '';
if ( isset( $_POST['module_class'] ) && in_array( $_POST['module_class'], array( 'Signup', 'Contact_Form' ) ) ) {
$module_class = sanitize_text_field( $_POST['module_class'] );
$module_class = 'Signup';
$is_BB = isset( $_POST['et_bb'] );
$is_spam_account = isset( $_POST['is_spam_account'] );
if ( empty( $provider_slug ) || empty( $account_name ) ) {
unset( $_POST[ $name_key ] );
$fields = et_builder_email_get_fields_from_post_data( $provider_slug, $is_spam_account );
if ( false === $fields ) {
if ( $is_spam_account ) {
$result = et_core_api_spam_add_account( $provider_slug, $account_name, $fields );
$result = et_core_api_email_fetch_lists( $provider_slug, $account_name, $fields );
$_ = ET_Core_Data_Utils::instance();
// Get data in builder format
$list_data = et_builder_email_get_lists_field_data( $provider_slug, $is_BB, $module_class );
if ( 'success' === $result ) {
'accounts_list' => $_->array_get( $list_data, 'accounts_list', $list_data ),
'custom_fields' => $_->array_get( $list_data, 'custom_fields', array() ),
'predefined_custom_fields' => ET_Core_API_Email_Providers::instance()->custom_fields_data(),
'message' => esc_html__( 'Error: ', 'et_builder' ) . esc_html( $result ),
'accounts_list' => $_->array_get( $list_data, 'accounts_list', $list_data ),
'custom_fields' => $_->array_get( $list_data, 'custom_fields', array() ),
'predefined_custom_fields' => ET_Core_API_Email_Providers::instance()->custom_fields_data(),
die( wp_json_encode( $result ) );
add_action( 'wp_ajax_et_builder_email_add_account', 'et_builder_email_add_account' );
if ( ! function_exists( 'et_builder_email_get_fields_from_post_data' ) ):
function et_builder_email_get_fields_from_post_data( $provider_slug, $is_spam_account = false ) {
et_core_security_check( 'manage_options', 'et_builder_email_add_account_nonce' );
if ( $is_spam_account ) {
$fields = ET_Core_API_Spam_Providers::instance()->account_fields( $provider_slug );
$fields = ET_Core_API_Email_Providers::instance()->account_fields( $provider_slug );
$protocol = is_ssl() ? 'https' : 'http';
// If there are no fields to check then the check passes.
foreach ( $fields as $field_name => $field_info ) {
$key = "et_{$provider_slug}_{$field_name}";
if ( empty( $_POST[$key] ) ) {
if ( isset( $field_info['required'] ) ) {
// Field can be required only when https or http
$required = $field_info['required'] === $protocol;
if ( $required && ! isset( $field_info['not_required'] ) ) {
$result[ $field_name ] = sanitize_text_field( $_POST[ $key ] );
if ( ! function_exists( 'et_builder_email_get_lists_field_data' ) ):
* Get email list data in a builder's options field format.
* @param string $provider_slug
* @return array|string The data in the BB's format if `$is_BB` is `true`, the FB's format otherwise.
function et_builder_email_get_lists_field_data( $provider_slug, $is_BB = false, $module_class = 'Signup' ) {
$module = 'ET_Builder_Module_' . $module_class;
$fields = $module->get_fields();
$field_name = $provider_slug . '_list';
$field = $fields[ $field_name ];
$field['only_options'] = true;
$field['name'] = $field_name;
$field_data = $module->render_field( $field );
'accounts_list' => $field['options'],
if ( 'Signup' === $module_class ) {
$signup_field = new ET_Builder_Module_Signup_Item;
$fields_data['custom_fields'] = $signup_field->get_fields();
et_pb_force_regenerate_templates();
et_fb_delete_builder_assets();
if ( ! function_exists( 'et_builder_email_get_lists' ) ):
* Ajax handler for the Email Opt-in Module's "Fetch Lists" action.
function et_builder_email_get_lists() {
et_core_security_check( 'manage_options', 'et_builder_email_fetch_lists_nonce' );
$provider_slug = isset( $_POST['et_provider'] ) ? sanitize_text_field( $_POST['et_provider'] ) : '';
$account_name = isset( $_POST['et_account'] ) ? sanitize_text_field( $_POST['et_account'] ) : '';
$is_BB = isset( $_POST['et_bb'] );
if ( empty( $provider_slug ) || empty( $account_name ) ) {
// Make sure email component group is loaded;
new ET_Core_API_Email_Providers();
$_ = ET_Core_Data_Utils::instance();
// Fetch lists from provider
$message = et_core_api_email_fetch_lists( $provider_slug, $account_name );
// Get data in builder format
$list_data = et_builder_email_get_lists_field_data( $provider_slug, $is_BB );
'accounts_list' => $_->array_get( $list_data, 'accounts_list', $list_data ),
'custom_fields' => $_->array_get( $list_data, 'custom_fields', array() ),
'predefined_custom_fields' => ET_Core_API_Email_Providers::instance()->custom_fields_data(),
if ( 'success' !== $message ) {
$result['message'] = esc_html__( 'Error: ', 'et_core' ) . esc_html( $message );
die( wp_json_encode( $result ) );
add_action( 'wp_ajax_et_builder_email_get_lists', 'et_builder_email_get_lists' );