if ( ! defined( 'ET_BUILDER_DIVI_LIBRARY_URL' ) ) {
define( 'ET_BUILDER_DIVI_LIBRARY_URL', 'https://www.elegantthemes.com/layouts' );
if ( ! defined( 'ET_BUILDER_CSS_WRAPPER_PREFIX' ) ) {
define( 'ET_BUILDER_CSS_WRAPPER_PREFIX', '.et-db' );
if ( ! defined( 'ET_BUILDER_CSS_CONTAINER_PREFIX' ) ) {
define( 'ET_BUILDER_CSS_CONTAINER_PREFIX', '#et-boc' );
if ( ! defined( 'ET_BUILDER_CSS_LAYOUT_PREFIX' ) ) {
define( 'ET_BUILDER_CSS_LAYOUT_PREFIX', ET_BUILDER_CSS_CONTAINER_PREFIX . ' .et-l' );
if ( ! defined( 'ET_BUILDER_CSS_PREFIX' ) ) {
define( 'ET_BUILDER_CSS_PREFIX', ET_BUILDER_CSS_WRAPPER_PREFIX . ' ' . ET_BUILDER_CSS_LAYOUT_PREFIX );
if ( ! defined( 'ET_BUILDER_PLACEHOLDER_LANDSCAPE_IMAGE_DATA' ) ) {
define( 'ET_BUILDER_PLACEHOLDER_LANDSCAPE_IMAGE_DATA', 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4MCIgaGVpZ2h0PSI1NDAiIHZpZXdCb3g9IjAgMCAxMDgwIDU0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPHBhdGggZmlsbD0iI0VCRUJFQiIgZD0iTTAgMGgxMDgwdjU0MEgweiIvPgogICAgICAgIDxwYXRoIGQ9Ik00NDUuNjQ5IDU0MGgtOTguOTk1TDE0NC42NDkgMzM3Ljk5NSAwIDQ4Mi42NDR2LTk4Ljk5NWwxMTYuMzY1LTExNi4zNjVjMTUuNjItMTUuNjIgNDAuOTQ3LTE1LjYyIDU2LjU2OCAwTDQ0NS42NSA1NDB6IiBmaWxsLW9wYWNpdHk9Ii4xIiBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9Im5vbnplcm8iLz4KICAgICAgICA8Y2lyY2xlIGZpbGwtb3BhY2l0eT0iLjA1IiBmaWxsPSIjMDAwIiBjeD0iMzMxIiBjeT0iMTQ4IiByPSI3MCIvPgogICAgICAgIDxwYXRoIGQ9Ik0xMDgwIDM3OXYxMTMuMTM3TDcyOC4xNjIgMTQwLjMgMzI4LjQ2MiA1NDBIMjE1LjMyNEw2OTkuODc4IDU1LjQ0NmMxNS42Mi0xNS42MiA0MC45NDgtMTUuNjIgNTYuNTY4IDBMMTA4MCAzNzl6IiBmaWxsLW9wYWNpdHk9Ii4yIiBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9Im5vbnplcm8iLz4KICAgIDwvZz4KPC9zdmc+Cg==' );
if ( ! defined( 'ET_BUILDER_PLACEHOLDER_PORTRAIT_IMAGE_DATA' ) ) {
define( 'ET_BUILDER_PLACEHOLDER_PORTRAIT_IMAGE_DATA', 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAwIiBoZWlnaHQ9IjUwMCIgdmlld0JveD0iMCAwIDUwMCA1MDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxwYXRoIGZpbGw9IiNFQkVCRUIiIGQ9Ik0wIDBoNTAwdjUwMEgweiIvPgogICAgICAgIDxyZWN0IGZpbGwtb3BhY2l0eT0iLjEiIGZpbGw9IiMwMDAiIHg9IjY4IiB5PSIzMDUiIHdpZHRoPSIzNjQiIGhlaWdodD0iNTY4IiByeD0iMTgyIi8+CiAgICAgICAgPGNpcmNsZSBmaWxsLW9wYWNpdHk9Ii4xIiBmaWxsPSIjMDAwIiBjeD0iMjQ5IiBjeT0iMTcyIiByPSIxMDAiLz4KICAgIDwvZz4KPC9zdmc+Cg==' );
// Detect Codeception and load additional code required by tests.
if ( class_exists( 'Codeception\TestCase\WPTestCase' ) ) {
foreach ( glob( ET_BUILDER_DIR . 'tests/codeception/wpunit/*.php' ) as $test_file ) {
require_once ET_BUILDER_DIR . 'autoload.php';
* Retrieve a commonly used translation.
* @param string $key Translation key.
* @param boolean $reset Reset cache.
function et_builder_i18n( $key, $reset = false ) {
if ( ! isset( $cache[ $key ] ) ) {
$cache[ $key ] = ET_Builder_I18n::get( $key );
* Resets commonly used translations cache.
function et_builder_i18n_reset_cache() {
et_builder_i18n( '', true );
* Escape translation with optional value and caches the result.
function et_esc_html_once( $text, $value = '' ) {
if ( isset( $cache[ $text ][ $value ] ) ) {
return $cache[ $text ][ $value ];
$escaped = esc_html( '' === $value ? $text : sprintf( $text, $value ) );
$cache[ $text ][ $value ] = $escaped;
require_once ET_BUILDER_DIR . 'compat/early.php';
require_once ET_BUILDER_DIR . 'feature/gutenberg/blocks/Layout.php';
require_once ET_BUILDER_DIR . 'feature/gutenberg/utils/Conversion.php';
require_once ET_BUILDER_DIR . 'feature/gutenberg/EditorTypography.php';
require_once ET_BUILDER_DIR . 'core.php';
require_once ET_BUILDER_DIR . 'conditions.php';
require_once ET_BUILDER_DIR . 'post/PostStack.php';
require_once ET_BUILDER_DIR . 'feature/ClassicEditor.php';
require_once ET_BUILDER_DIR . 'feature/AjaxCache.php';
require_once ET_BUILDER_DIR . 'feature/post-content.php';
require_once ET_BUILDER_DIR . 'feature/dynamic-content.php';
require_once ET_BUILDER_DIR . 'feature/search-posts.php';
require_once ET_BUILDER_DIR . 'feature/ErrorReport.php';
require_once ET_BUILDER_DIR . 'api/DiviExtensions.php';
require_once ET_BUILDER_DIR . 'api/rest/BlockLayout.php';
require_once ET_BUILDER_DIR . 'frontend-builder/theme-builder/theme-builder.php';
require_once ET_BUILDER_DIR . 'feature/global-presets/Settings.php';
require_once ET_BUILDER_DIR . 'feature/global-presets/History.php';
require_once ET_BUILDER_DIR . 'feature/window.php';
if ( et_is_woocommerce_plugin_active() ) {
require_once ET_BUILDER_DIR . 'feature/woocommerce-modules.php';
if ( wp_doing_ajax() && ! is_customize_preview() ) {
define( 'WPE_HEARTBEAT_INTERVAL', et_builder_heartbeat_interval() );
// Default ajax request exceptions
$builder_load_requests = array(
'et_pb_get_backbone_template',
'et_pb_get_backbone_templates',
'et_pb_process_computed_property',
'et_fb_ajax_render_shortcode',
'et_fb_get_shortcode_from_fb_object',
'et_fb_ajax_drop_autosave',
'et_fb_get_saved_layouts',
'et_pb_execute_content_shortcodes',
'et_pb_create_ab_tables',
'et_pb_update_stats_table',
'et_fb_prepare_shortcode',
'et_fb_process_imported_content',
'et_fb_get_saved_templates',
'et_fb_retrieve_builder_data',
'et_fb_update_builder_assets',
'et_pb_process_custom_font',
'et_builder_email_add_account', // email opt-in module
'et_builder_email_remove_account', // email opt-in module
'et_builder_email_get_lists', // email opt-in module
'et_builder_save_settings', // builder plugin dashboard (global builder settings)
'save_epanel', // ePanel (global builder settings)
'et_builder_library_get_layout',
'et_builder_library_get_layouts_data',
'et_fb_fetch_attachments',
'et_pb_get_saved_templates',
'et_builder_resolve_post_content',
'et_builder_activate_bfb_auto_draft',
'et_core_portability_import',
'et_core_version_rollback',
'et_core_portability_export',
'et_core_portability_import',
'et_builder_migrate_module_customizer_phase_two',
'et_builder_save_global_presets_history',
'et_builder_retrieve_global_presets_history',
'et_theme_builder_api_import_theme_builder_step',
'et_pb_submit_subscribe_form',
'et_builder_get_woocommerce_tabs',
// AJAX requests that use PHP modules cache for performance reasons.
$builder_use_cache_actions = array(
'et_builder_retrieve_global_presets_history',
'et_fb_get_saved_templates',
'et_fb_ajax_drop_autosave',
// Added built-in third party plugins support
// Easy Digital Downloads
if ( class_exists( 'Easy_Digital_Downloads' ) ) {
$builder_load_requests['action'][] = 'edd_load_gateway';
// WooCommerce - it uses its own ajax endpoint instead of admin-ajax.php
if ( class_exists( 'WooCommerce' ) ) {
$builder_load_requests['wc-ajax'] = array(
if ( class_exists( 'SitePress' ) ) {
$builder_load_requests['action'][] = 'et_builder_wpml_translate_layout';
// Merging third party exceptions; built-in exceptions should not be removable
$builder_custom_load_requests = apply_filters( 'et_builder_load_requests', array() );
if ( ! empty( $builder_custom_load_requests ) ) {
foreach ( $builder_custom_load_requests as $builder_custom_query_string => $builder_custom_possible_values ) {
if ( ! isset( $builder_load_requests[ $builder_custom_query_string ] ) ) {
$builder_load_requests[ $builder_custom_query_string ] = $builder_custom_possible_values;
$builder_load_requests[ $builder_custom_query_string ] = array_merge( $builder_custom_possible_values, $builder_load_requests[ $builder_custom_query_string ] );
// Legacy compatibility for action only request exception filter
$builder_load_actions = apply_filters( 'et_builder_load_actions', array() );
if ( ! empty( $builder_load_actions ) ) {
$builder_load_requests['action'] = array_merge( $builder_load_actions, $builder_load_requests['action'] );
// Determine whether current AJAX request should load builder or not
$load_builder_on_ajax = false;
// If current request's query string exists on list of possible values, load builder
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
foreach ( $builder_load_requests as $query_string => $possible_values ) {
if ( isset( $_REQUEST[ $query_string ] ) && in_array( $_REQUEST[ $query_string ], $possible_values ) ) {
$load_builder_on_ajax = true;
define( 'ET_BUILDER_LOAD_ON_AJAX', $load_builder_on_ajax );
$action = et_()->array_get( $_POST, 'action', false );
$force_builder_load = isset( $_POST['et_load_builder_modules'] ) && '1' === $_POST['et_load_builder_modules'];
$force_memory_limit = 'et_fb_retrieve_builder_data' === $action;
if ( 'heartbeat' === $action ) {
// if this is the heartbeat, and if its not packing our heartbeat data, then return
if ( ! isset( $_REQUEST['data'] ) || ! isset( $_REQUEST['data']['et'] ) ) {
} elseif ( ! $force_builder_load && ! $load_builder_on_ajax ) {
if ( $force_memory_limit || et_should_memory_limit_increase() ) {
et_increase_memory_limit();
if ( $action && in_array( $action, $builder_use_cache_actions ) ) {
add_filter( 'et_builder_ajax_use_cache', '__return_true' );
function et_builder_load_global_functions_script() {
wp_enqueue_script( 'et-builder-modules-global-functions-script', ET_BUILDER_URI . '/frontend-builder/build/frontend-builder-global-functions.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
// These are variable that is used on frontend's script utils module. The utils is used by
// `et-builder-modules-global-functions-script` handle which is loaded earlier than other script
// when minify js option is disabled hence being defined here. If minify JS option is enabled,
// `et_builder_dequeue_minified_scripts()` will assign this to the minified bundle's handle.
'et-builder-modules-global-functions-script',
'et_builder_utils_params',
'diviTheme' => function_exists( 'et_divi_fonts_url' ),
'extraTheme' => function_exists( 'et_extra_fonts_url' ),
'scrollLocations' => et_builder_get_window_scroll_locations(),
'builderScrollLocations' => et_builder_get_onload_scroll_locations(),
'onloadScrollLocation' => et_builder_get_onload_scroll_location(),
'builderType' => et_builder_get_current_builder_type(),
add_action( 'wp_enqueue_scripts', 'et_builder_load_global_functions_script', 7 );
function et_builder_load_modules_styles() {
$current_page_id = apply_filters( 'et_is_ab_testing_active_post_id', get_the_ID() );
$is_fb_enabled = et_core_is_fb_enabled();
$ab_tests = function_exists( 'et_builder_ab_get_current_tests' ) ? et_builder_ab_get_current_tests() : array();
$is_ab_testing = ! empty( $ab_tests );
$google_maps_api_url_args = array(
'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_register_script( 'google-maps-api', esc_url_raw( $google_maps_api_url ), array(), ET_BUILDER_VERSION, true );
wp_register_script( 'hashchange', ET_BUILDER_URI . '/scripts/ext/jquery.hashchange.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
wp_register_script( 'salvattore', ET_BUILDER_URI . '/scripts/ext/salvattore.min.js', array(), ET_BUILDER_VERSION, true );
wp_register_script( 'easypiechart', ET_BUILDER_URI . '/scripts/ext/jquery.easypiechart.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
wp_enqueue_script( 'divi-fitvids', ET_BUILDER_URI . '/scripts/ext/jquery.fitvids.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
wp_enqueue_script( 'waypoints', ET_BUILDER_URI . '/scripts/ext/waypoints.min.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
wp_enqueue_script( 'magnific-popup', ET_BUILDER_URI . '/scripts/ext/jquery.magnific-popup.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
wp_enqueue_script( 'et-jquery-touch-mobile', ET_BUILDER_URI . '/scripts/ext/jquery.mobile.custom.min.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
wp_enqueue_script( 'et-builder-modules-script', ET_BUILDER_URI . '/frontend-builder/build/frontend-builder-scripts.js', apply_filters( 'et_pb_frontend_builder_scripts_dependencies', array( 'jquery', 'et-jquery-touch-mobile' ) ), ET_BUILDER_VERSION, true );
wp_enqueue_style( 'magnific-popup', ET_BUILDER_URI . '/styles/magnific_popup.css', array(), ET_BUILDER_VERSION );
$frontend_scripts_data = array(
'builderCssContainerPrefix' => ET_BUILDER_CSS_CONTAINER_PREFIX,
'builderCssLayoutPrefix' => ET_BUILDER_CSS_LAYOUT_PREFIX,
wp_localize_script( 'et-builder-modules-script', 'et_frontend_scripts', $frontend_scripts_data );
// Load modules wrapper on CPT.
// Use get_the_ID() explicitly so we decide based on the first post of an archive page.
if ( et_builder_post_is_of_custom_post_type( get_the_ID() ) ) {
wp_enqueue_script( 'et-builder-cpt-modules-wrapper', ET_BUILDER_URI . '/scripts/cpt-modules-wrapper.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
$modules_wrapper_data = array(
'builderCssContainerPrefix' => ET_BUILDER_CSS_CONTAINER_PREFIX,
'builderCssLayoutPrefix' => ET_BUILDER_CSS_LAYOUT_PREFIX,
wp_localize_script( 'et-builder-cpt-modules-wrapper', 'et_modules_wrapper', $modules_wrapper_data );
if ( et_builder_has_limitation( 'register_fittext_script' ) ) {
wp_register_script( 'fittext', ET_BUILDER_URI . '/scripts/ext/jquery.fittext.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
* Builder script handle name
$builder_modules_script_handle = apply_filters( 'et_builder_modules_script_handle', 'et-builder-modules-script' );
// Load main styles CSS file only if the Builder plugin is active
if ( et_is_builder_plugin_active() ) {
$style_suffix = et_load_unminified_styles() ? '' : '.unified';
wp_enqueue_style( 'et-builder-modules-style', ET_BUILDER_URI . '/styles/frontend-builder-plugin-style' . $style_suffix . '.css', array(), ET_BUILDER_VERSION );
// Load visible.min.js only if AB testing active on current page OR VB (because post settings is synced between VB and BB)
if ( $is_ab_testing || $is_fb_enabled ) {
wp_enqueue_script( 'et-jquery-visible-viewport', ET_BUILDER_URI . '/scripts/ext/jquery.visible.min.js', array( 'jquery', $builder_modules_script_handle ), ET_BUILDER_VERSION, true );
'ajaxurl' => is_ssl() ? admin_url( 'admin-ajax.php' ) : admin_url( 'admin-ajax.php', 'http' ),
'images_uri' => get_template_directory_uri() . '/images',
'builder_images_uri' => ET_BUILDER_URI . '/images',
'et_frontend_nonce' => wp_create_nonce( 'et_frontend_nonce' ),
'subscription_failed' => esc_html__( 'Please, check the fields below to make sure you entered the correct information.', 'et_builder' ),
'et_ab_log_nonce' => wp_create_nonce( 'et_ab_testing_log_nonce' ),
'fill_message' => esc_html__( 'Please, fill in the following fields:', 'et_builder' ),
'contact_error_message' => esc_html__( 'Please, fix the following errors:', 'et_builder' ),
'invalid' => esc_html__( 'Invalid email', 'et_builder' ),
'captcha' => esc_html__( 'Captcha', 'et_builder' ),
'prev' => esc_html__( 'Prev', 'et_builder' ),
'previous' => esc_html__( 'Previous', 'et_builder' ),
'next' => esc_html__( 'Next', 'et_builder' ),
'wrong_captcha' => esc_html__( 'You entered the wrong number in captcha.', 'et_builder' ),
'wrong_checkbox' => esc_html__( 'Checkbox', 'et_builder' ),
'ignore_waypoints' => et_is_ignore_waypoints() ? 'yes' : 'no',
'is_divi_theme_used' => function_exists( 'et_divi_fonts_url' ),
'widget_search_selector' => apply_filters( 'et_pb_widget_search_selector', '.widget_search' ),
'is_ab_testing_active' => $is_ab_testing,
'page_id' => $current_page_id,
'unique_test_id' => get_post_meta( $current_page_id, '_et_pb_ab_testing_id', true ),
'ab_bounce_rate' => '' !== get_post_meta( $current_page_id, '_et_pb_ab_bounce_rate_limit', true ) ? get_post_meta( $current_page_id, '_et_pb_ab_bounce_rate_limit', true ) : 5,
'is_cache_plugin_active' => false === et_pb_detect_cache_plugins() ? 'no' : 'yes',
'is_shortcode_tracking' => get_post_meta( $current_page_id, '_et_pb_enable_shortcode_tracking', true ),
'tinymce_uri' => defined( 'ET_FB_ASSETS_URI' ) ? ET_FB_ASSETS_URI . '/vendors' : '',
wp_localize_script( $builder_modules_script_handle, 'et_pb_custom', $pb_custom_data );
* Only load this during builder preview screen session
if ( is_et_pb_preview() ) {
// Set fixed protocol for preview URL to prevent cross origin issue
$preview_scheme = is_ssl() ? 'https' : 'http';
// Get home url, then parse it
$preview_origin_component = parse_url( home_url( '', $preview_scheme ) );
// Rebuild origin URL, strip sub-directory address if there's any (postMessage e.origin doesn't pass sub-directory address)
// Perform check, prevent unnecessary error
if ( isset( $preview_origin_component['scheme'] ) && isset( $preview_origin_component['host'] ) ) {
$preview_origin = "{$preview_origin_component['scheme']}://{$preview_origin_component['host']}";
// Append port number if different port number is being used
if ( isset( $preview_origin_component['port'] ) ) {
$preview_origin = "{$preview_origin}:{$preview_origin_component['port']}";
// Enqueue theme's style.css if it hasn't been enqueued (possibly being hardcoded by theme)
if ( ! et_builder_has_theme_style_enqueued() && et_builder_has_limitation( 'force_enqueue_theme_style' ) ) {
wp_enqueue_style( 'et-builder-theme-style-css', get_stylesheet_uri(), array() );
wp_enqueue_style( 'et-builder-preview-style', ET_BUILDER_URI . '/styles/preview.css', array(), ET_BUILDER_VERSION );
wp_enqueue_script( 'et-builder-preview-script', ET_BUILDER_URI . '/frontend-builder/build/frontend-builder-preview.js', array( 'jquery' ), ET_BUILDER_VERSION, true );
$preview_params_data = array(
'preview_origin' => esc_url( $preview_origin ),
'alert_origin_not_matched' => sprintf(
esc_html__( 'Unauthorized access. Preview cannot be accessed outside %1$s.', 'et_builder' ),
esc_url( home_url( '', $preview_scheme ) )
wp_localize_script( 'et-builder-preview-script', 'et_preview_params', $preview_params_data );
add_action( 'wp_enqueue_scripts', 'et_builder_load_modules_styles', 11 );
function et_builder_get_modules_js_data() {
// Data shouldn't be loaded in Builder, so always pass an empty array there.
$animation_data = et_core_is_fb_enabled() ? array() : et_builder_handle_animation_data();
$animation_data_json = json_encode( $animation_data );
$link_options_data = et_core_is_fb_enabled() ? array() : et_builder_handle_link_options_data();
$link_options_data_json = json_encode( $link_options_data );
if ( empty( $animation_data ) && empty( $link_options_data ) ) {
<script type="text/javascript">
<?php if ( $animation_data ) : ?>
var et_animation_data = <?php echo et_core_esc_previously( $animation_data_json ); ?>;
if ( $link_options_data ) :
var et_link_options_data = <?php echo et_core_esc_previously( $link_options_data_json ); ?>;
add_action( 'wp_footer', 'et_builder_get_modules_js_data' );
// Force Backbone templates cache to be cleared on language change to make sure the settings modal is translated
// defaults for arguments are provided because their number is different for both the actions
function et_pb_force_clear_template_cache( $meta_id = false, $object_id = false, $meta_key = false, $_meta_value = false ) {
$current_action = current_action();
if ( ( 'updated_user_meta' === $current_action && 'locale' === $meta_key ) || 'update_option_WPLANG' === $current_action ) {
et_update_option( 'et_pb_clear_templates_cache', true );
add_action( 'update_option_WPLANG', 'et_pb_force_clear_template_cache' );
add_action( 'updated_user_meta', 'et_pb_force_clear_template_cache', 10, 4 );
function et_builder_handle_animation_data( $element_data = false ) {
static $data_classes = array();
// This should not be possible but let's be safe
if ( empty( $element_data['class'] ) ) {
// Prevent duplication animation data entries created by global modules
if ( in_array( $element_data['class'], $data_classes ) ) {
$data[] = et_core_esc_previously( $element_data );
$data_classes[] = et_core_esc_previously( $element_data['class'] );
function et_builder_handle_link_options_data( $element_data = false ) {
static $data_classes = array();