: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
et_fb_get_builder_shortcode_object( $post_type, $post_id, $layout_type )
// Enable zlib compression
et_builder_enable_zlib_compression();
die( json_encode( $fields_data ) );
add_action( 'wp_ajax_et_fb_retrieve_builder_data', 'et_fb_retrieve_builder_data' );
// Replaces site_url in a json string with its protocol-less version
function et_fb_remove_site_url_protocol( $json ) {
$no_proto = str_replace( '/', '\/', preg_replace( '#^\w+:#', '', get_site_url() ) );
"https:$no_proto" => $no_proto,
"http:$no_proto" => $no_proto,
// Used to update the content of the cached definitions js file.
function et_fb_get_asset_definitions( $content, $post_type ) {
$definitions = et_fb_get_builder_definitions( $post_type );
'window.ETBuilderBackend=jQuery.extend(true,%s,window.ETBuilderBackend)',
et_fb_remove_site_url_protocol( wp_json_encode( $definitions, ET_BUILDER_JSON_ENCODE_OPTIONS ) )
add_filter( 'et_fb_get_asset_definitions', 'et_fb_get_asset_definitions', 10, 2 );
function et_pb_get_options_page_link() {
// Builder plugin has different path to options page
if ( et_is_builder_plugin_active() ) {
return admin_url( 'admin.php?page=et_divi_options#tab_et_dashboard_tab_content_api_main' );
return apply_filters( 'et_pb_theme_options_link', admin_url( 'admin.php?page=et_divi_options' ) );
function et_fb_get_product_tour_text( $post_id ) {
$post_status = get_post_status( $post_id );
$productTourText = array(
'title' => esc_html__( 'Welcome To The Divi Builder', 'et_builder' ),
'description' => sprintf(
__( '%10$sBuilding beautiful pages is a breeze using the Visual Builder. To get started, add a new %1$s to your page by pressing the %2$s button. Next, add a %3$s of columns inside your section by pressing the %4$s button. Finally, start adding some content %5$s inside your columns by pressing the %6$s button. You can customize the design and content of any element on the page by pressing the %7$s button. If you ever need help, visit our %9$s page for a full list of tutorials.', 'et_builder' ),
sprintf( '<span class="et_fb_tour_text et_fb_tour_text_blue">%1$s</span>', esc_html__( 'Section' ) ),
'<span class="et_fb_tour_icon et_fb_tour_icon_blue"><svg viewBox="0 0 28 28" preserveAspectRatio="xMidYMid meet" shapeRendering="geometricPrecision"><g><path d="M18 13h-3v-3a1 1 0 0 0-2 0v3h-3a1 1 0 0 0 0 2h3v3a1 1 0 0 0 2 0v-3h3a1 1 0 0 0 0-2z" fillRule="evenodd" /></g></svg></span>',
sprintf( '<span class="et_fb_tour_text et_fb_tour_text_green">%1$s</span>', esc_html__( 'Row' ) ),
'<span class="et_fb_tour_icon et_fb_tour_icon_green"><svg viewBox="0 0 28 28" preserveAspectRatio="xMidYMid meet" shapeRendering="geometricPrecision"><g><path d="M18 13h-3v-3a1 1 0 0 0-2 0v3h-3a1 1 0 0 0 0 2h3v3a1 1 0 0 0 2 0v-3h3a1 1 0 0 0 0-2z" fillRule="evenodd" /></g></svg></span>',
sprintf( '<span class="et_fb_tour_text et_fb_tour_text_black">%1$s</span>', esc_html__( 'Modules' ) ),
'<span class="et_fb_tour_icon"><svg viewBox="0 0 28 28" preserveAspectRatio="xMidYMid meet" shapeRendering="geometricPrecision"><g><path d="M18 13h-3v-3a1 1 0 0 0-2 0v3h-3a1 1 0 0 0 0 2h3v3a1 1 0 0 0 2 0v-3h3a1 1 0 0 0 0-2z" fillRule="evenodd" /></g></svg></span>',
'<span class="et_fb_tour_icon"><svg viewBox="0 0 28 28" preserveAspectRatio="xMidYMid meet" shapeRendering="geometricPrecision"><g><path d="M20.426 13.088l-1.383-.362a.874.874 0 0 1-.589-.514l-.043-.107a.871.871 0 0 1 .053-.779l.721-1.234a.766.766 0 0 0-.116-.917 6.682 6.682 0 0 0-.252-.253.768.768 0 0 0-.917-.116l-1.234.722a.877.877 0 0 1-.779.053l-.107-.044a.87.87 0 0 1-.513-.587l-.362-1.383a.767.767 0 0 0-.73-.567h-.358a.768.768 0 0 0-.73.567l-.362 1.383a.878.878 0 0 1-.513.589l-.107.044a.875.875 0 0 1-.778-.054l-1.234-.722a.769.769 0 0 0-.918.117c-.086.082-.17.166-.253.253a.766.766 0 0 0-.115.916l.721 1.234a.87.87 0 0 1 .053.779l-.043.106a.874.874 0 0 1-.589.514l-1.382.362a.766.766 0 0 0-.567.731v.357a.766.766 0 0 0 .567.731l1.383.362c.266.07.483.26.588.513l.043.107a.87.87 0 0 1-.053.779l-.721 1.233a.767.767 0 0 0 .115.917c.083.087.167.171.253.253a.77.77 0 0 0 .918.116l1.234-.721a.87.87 0 0 1 .779-.054l.107.044a.878.878 0 0 1 .513.589l.362 1.383a.77.77 0 0 0 .731.567h.356a.766.766 0 0 0 .73-.567l.362-1.383a.878.878 0 0 1 .515-.589l.107-.044a.875.875 0 0 1 .778.054l1.234.721c.297.17.672.123.917-.117.087-.082.171-.166.253-.253a.766.766 0 0 0 .116-.917l-.721-1.234a.874.874 0 0 1-.054-.779l.044-.107a.88.88 0 0 1 .589-.513l1.383-.362a.77.77 0 0 0 .567-.731v-.357a.772.772 0 0 0-.569-.724v-.005zm-6.43 3.9a2.986 2.986 0 1 1 2.985-2.986 3 3 0 0 1-2.985 2.987v-.001z" fillRule="evenodd" /></g></svg></span>',
'<span class="et_fb_tour_text et_fb_tour_text_black">?</span>',
sprintf( '<a target="_blank" href="https://www.elegantthemes.com/documentation/divi/" class="et_fb_tour_text et_fb_tour_text_black">%1$s</a>', esc_html__( 'Documentation' ) ),
sprintf( '<div class="et-fb-tour-video-overlay" data-video="https://www.youtube.com/embed/JXZIGZqr9OE?rel=0&autoplay=1">
<div class="et-fb-play-overlay"></div>
esc_url( ET_BUILDER_URI . '/frontend-builder/assets/img/product-tour-intro.jpg' )
'endButtonText' => esc_html__( 'Start Building', 'et_builder' ),
'skipButtonText' => esc_html__( 'Take the Tour', 'et_builder' ),
'title' => esc_html__( 'Load A New Layout', 'et_builder' ),
'description' => esc_html__( 'Loading pre-made layouts is a great way to jump-start your new page. The Divi Builder comes with dozens of layouts to choose from, and you can find lots of great free layouts online too. You can save your favorite layouts to the Divi Library and load them on new pages or share them with the community. Click the highlighted button to open the layouts menu and select a pre-made layout.', 'et_builder' ),
'selectLayoutPack' => array(
'title' => esc_html__( 'Choose A Layout Pack', 'et_builder' ),
'description' => esc_html__( 'Here you can see a list of pre-made layout packs that ship with the Divi Builder. You can also access layouts that you have saved to your Divi Library. Choose the “Divi Builder Demo” layout pack to see the layouts it includes.', 'et_builder' ),
'loadLayoutItem' => array(
'title' => esc_html__( 'Choose A Layout To Start With', 'et_builder' ),
'description' => esc_html__( 'Now you can see more details about the layout pack as well as a list of the layouts it includes. Click “Use Layout” to apply the layout to your page.', 'et_builder' ),
'title' => esc_html__( 'Add A New Section', 'et_builder' ),
'description' => sprintf(
__( 'Now that your pre-made layout has been loaded, we can start adding new content to the page. The Divi Builder organizes content using %1$s, %2$s and Modules. Sections are the largest organizational element. Click the highlighted button to add a new section to the page.', 'et_builder' ),
sprintf( '<span class="et_fb_tour_text_blue">%1$s</span>', esc_html__( 'Sections' ) ),
sprintf( '<span class="et_fb_tour_text_green">%1$s</span>', esc_html__( 'Rows' ) )
'selectSectionType' => array(
'title' => esc_html__( 'Choose A Section Type', 'et_builder' ),
'description' => sprintf(
__( 'The Divi Builder has three different section types. %1$s sections conform to the standard width of your page layout. %2$s Sections can be used to create advanced sidebar layouts. %3$s sections extend the full width of your page and can be used with fullwidth modules. Click the “Regular” section button to add a new section to your page.', 'et_builder' ),
sprintf( '<span class="et_fb_tour_text_blue">%1$s</span>', esc_html__( 'Regular' ) ),
sprintf( '<span class="et_fb_tour_text_red">%1$s</span>', esc_html__( 'Specialty' ) ),
sprintf( '<span class="et_fb_tour_text_purple">%1$s</span>', esc_html__( 'Fullwidth' ) )
'title' => esc_html__( 'Add A New Row Of Columns', 'et_builder' ),
'description' => sprintf(
__( 'Every section contains one or more %1$s of columns. You can choose between various column layouts for each row you add to your page. Click the highlighted three-column layout to add a new row to your section.', 'et_builder' ),
sprintf( '<span class="et_fb_tour_text_green">%1$s</span>', esc_html__( 'Rows' ) )
'title' => esc_html__( 'Add A Module To The Column', 'et_builder' ),
'description' => esc_html__( 'Within each column you can add one or more Modules. A module is basic content element. The Divi Builder comes with over 40 different content elements to choose from, such as Images, Videos, Text, and Buttons. Click the highlighted Blurb button to add a new Blurb module to the first column in your row.', 'et_builder' ),
'configureModule' => array(
'title' => esc_html__( 'Adjust Your Module Settings', 'et_builder' ),
'description' => esc_html__( 'Each Module comes with various settings. These settings are separated into three tabs: Content, Design and Advanced. Inside the content tab you can modify the module content elements, such as text and images. If you need more control over the appearance of your module, head over to the Design tab. For more advanced modifications, such as custom CSS and HTML attributes, explore the Advanced tab. Try adjusting the Title of your blurb by clicking into the highlighted field.', 'et_builder' ),
'title' => esc_html__( 'Accept Or Discard Your Changes', 'et_builder' ),
'description' => esc_html__( 'Whenever you make changes in the Divi Builder, these changes can be Undone, Redone, Discarded or Accepted. Now that you have adjusted your module’s title, you can click the red discard button to cancel these changes, or your can click the green button to accept them.', 'et_builder' ),
'duplicateModule' => array(
'title' => esc_html__( 'Hover To Access Action Buttons', 'et_builder' ),
'description' => esc_html__( 'Whenever you hover over a Section, Row or Module in the Divi Builder, action buttons will appear. These buttons can be used to move, modify, duplicate or delete your content. Click the highlighted “duplicate” icon to duplicate the blurb module that you just added to the page.', 'et_builder' ),
'title' => __( 'Drag & Drop Content', 'et_builder' ),
'description' => esc_html__( 'Every item on the page can be dragged and dropped to new locations. Using your mouse, click the highlighted move icon and hold down the mouse button. While holding down the mouse button, move your cursor over to the empty column and then release your mouse button to drop the module into the new column.', 'et_builder' ),
'rightClickCopy' => array(
'title' => esc_html__( 'Access Right Click Options', 'et_builder' ),
'description' => esc_html__( 'In addition to hover actions, additional options can be accessed by Right Clicking or Cmd + Clicking on any module, row or section. Using the right click menu shown, click the highlighted “Copy Module” button to copy the blurb module that you just moved.', 'et_builder' ),
'rightClickPaste' => array(
'title' => esc_html__( 'Paste Your Copied Module', 'et_builder' ),
'description' => esc_html__( 'Now that you have copied a module using the Right Click menu, you can Right Click in a new location to paste that module. Using the right click options shown, click the “Paste Module” button to paste the module you just copied into the empty column.', 'et_builder' ),
'title' => esc_html__( 'Access Your Row Options', 'et_builder' ),
'description' => esc_html__( 'Every Row and Section has its own set of options that can be used to adjust the item’s appearance. You can adjust its width, padding, background and more. To access a row’s settings, hover over the row and click the highlighted options button.', 'et_builder' ),
'title' => esc_html__( 'Adjust Your Row Setting', 'et_builder' ),
'description' => esc_html__( 'Just like Modules, Rows come with a lot of settings that are separated into the Content, Design and Advanced tabs. Click the highlighted button to add a new background color to your row.', 'et_builder' ),
'title' => esc_html__( 'Accept Your Changes', 'et_builder' ),
'description' => esc_html__( 'Click the highlighted green check mark button to accept your changes. ', 'et_builder' ),
'title' => esc_html__( 'Open Your Page Settings', 'et_builder' ),
'description' => esc_html__( 'While using the Divi Builder, you can access your page settings by toggling the page settings bar at the bottom of your screen. Click the highlighted button to reveal your page settings.', 'et_builder' ),
'tabletPreview' => array(
'title' => esc_html__( 'Preview Your Page On Mobile', 'et_builder' ),
'description' => esc_html__( 'While editing your page, it’s easy to see what your design will look like on mobile devices. You can also make adjustments to your module, row and section settings for each mobile breakpoint. Click the highlighted “Tablet” icon to enter Tablet preview mode. ', 'et_builder' ),
'desktopPreview' => array(
'title' => esc_html__( 'Switch Back To Desktop Mode', 'et_builder' ),
'description' => esc_html__( 'You can switch back and forth between each preview mode freely while editing your page. Now that we have previewed our page on Tablet, let’s switch back to Desktop preview mode by clicking the highlighted button.', 'et_builder' ),
'title' => esc_html__( 'Access Your Editing History', 'et_builder' ),
'description' => esc_html__( 'Every change you make while editing your page is saved in your editing history. You can navigate backwards and forwards through time to any point during your current editing session, as well as undo and redo recent changes. Click the highlighted History button to access your editing history. ', 'et_builder' ),
'title' => esc_html__( 'Undo, Redo And Restore', 'et_builder' ),
'description' => esc_html__( 'Here you can undo, redo or restore a saved history state. If you change your mind about recent changes, simply click back in time and start building again. You can also undo and redo recent changes. Click the undo and redo buttons and then accept your changes by clicking the green check mark.', 'et_builder' ),
'title' => esc_html__( 'Save Your Page', 'et_builder' ),
'description' => sprintf( esc_html__( 'When you are all done, you can save your changes by clicking the %1$s button inside of your page settings bar. You can also press Ctrl + S at any time to save your changes. Click the highlighted Save button to save your changes. Don’t worry, the page you were working on before starting this tour will not be lost!', 'et_builder' ),
in_array( $post_status, array( 'private', 'publish' ) ) ? esc_html__( 'Save', 'et_builder' ) : esc_html__( 'Publish', 'et_builder' )
'title' => esc_html__( 'You’re Ready To Go!', 'et_builder' ),
'description' => sprintf(
__( '%10$sBuilding beautiful pages is a breeze using the Visual Builder. To get started, add a new %1$s to your page by pressing the %2$s button. Next, add a %3$s of columns inside your section by pressing the %4$s button. Finally, start adding some content %5$s inside your columns by pressing the %6$s button. You can customize the design and content of any element on the page by pressing the %7$s button. If you ever need help, visit our %9$s page for a full list of tutorials.', 'et_builder' ),
sprintf( '<span class="et_fb_tour_text et_fb_tour_text_blue">%1$s</span>', esc_html__( 'Section' ) ),
'<span class="et_fb_tour_icon et_fb_tour_icon_blue"><svg viewBox="0 0 28 28" preserveAspectRatio="xMidYMid meet" shapeRendering="geometricPrecision"><g><path d="M18 13h-3v-3a1 1 0 0 0-2 0v3h-3a1 1 0 0 0 0 2h3v3a1 1 0 0 0 2 0v-3h3a1 1 0 0 0 0-2z" fillRule="evenodd" /></g></svg></span>',
sprintf( '<span class="et_fb_tour_text et_fb_tour_text_green">%1$s</span>', esc_html__( 'Row' ) ),
'<span class="et_fb_tour_icon et_fb_tour_icon_green"><svg viewBox="0 0 28 28" preserveAspectRatio="xMidYMid meet" shapeRendering="geometricPrecision"><g><path d="M18 13h-3v-3a1 1 0 0 0-2 0v3h-3a1 1 0 0 0 0 2h3v3a1 1 0 0 0 2 0v-3h3a1 1 0 0 0 0-2z" fillRule="evenodd" /></g></svg></span>',
sprintf( '<span class="et_fb_tour_text et_fb_tour_text_black">%1$s</span>', esc_html__( 'Modules' ) ),
'<span class="et_fb_tour_icon"><svg viewBox="0 0 28 28" preserveAspectRatio="xMidYMid meet" shapeRendering="geometricPrecision"><g><path d="M18 13h-3v-3a1 1 0 0 0-2 0v3h-3a1 1 0 0 0 0 2h3v3a1 1 0 0 0 2 0v-3h3a1 1 0 0 0 0-2z" fillRule="evenodd" /></g></svg></span>',
'<span class="et_fb_tour_icon"><svg viewBox="0 0 28 28" preserveAspectRatio="xMidYMid meet" shapeRendering="geometricPrecision"><g><path d="M20.426 13.088l-1.383-.362a.874.874 0 0 1-.589-.514l-.043-.107a.871.871 0 0 1 .053-.779l.721-1.234a.766.766 0 0 0-.116-.917 6.682 6.682 0 0 0-.252-.253.768.768 0 0 0-.917-.116l-1.234.722a.877.877 0 0 1-.779.053l-.107-.044a.87.87 0 0 1-.513-.587l-.362-1.383a.767.767 0 0 0-.73-.567h-.358a.768.768 0 0 0-.73.567l-.362 1.383a.878.878 0 0 1-.513.589l-.107.044a.875.875 0 0 1-.778-.054l-1.234-.722a.769.769 0 0 0-.918.117c-.086.082-.17.166-.253.253a.766.766 0 0 0-.115.916l.721 1.234a.87.87 0 0 1 .053.779l-.043.106a.874.874 0 0 1-.589.514l-1.382.362a.766.766 0 0 0-.567.731v.357a.766.766 0 0 0 .567.731l1.383.362c.266.07.483.26.588.513l.043.107a.87.87 0 0 1-.053.779l-.721 1.233a.767.767 0 0 0 .115.917c.083.087.167.171.253.253a.77.77 0 0 0 .918.116l1.234-.721a.87.87 0 0 1 .779-.054l.107.044a.878.878 0 0 1 .513.589l.362 1.383a.77.77 0 0 0 .731.567h.356a.766.766 0 0 0 .73-.567l.362-1.383a.878.878 0 0 1 .515-.589l.107-.044a.875.875 0 0 1 .778.054l1.234.721c.297.17.672.123.917-.117.087-.082.171-.166.253-.253a.766.766 0 0 0 .116-.917l-.721-1.234a.874.874 0 0 1-.054-.779l.044-.107a.88.88 0 0 1 .589-.513l1.383-.362a.77.77 0 0 0 .567-.731v-.357a.772.772 0 0 0-.569-.724v-.005zm-6.43 3.9a2.986 2.986 0 1 1 2.985-2.986 3 3 0 0 1-2.985 2.987v-.001z" fillRule="evenodd" /></g></svg></span>',
'<span class="et_fb_tour_text et_fb_tour_text_black">?</span>',
sprintf( '<a target="_blank" href="https://www.elegantthemes.com/documentation/divi/" class="et_fb_tour_text et_fb_tour_text_black">%1$s</a>', esc_html__( 'Documentation' ) ),
sprintf( '<div class="et-fb-tour-video-overlay" data-video="https://www.youtube.com/embed/JXZIGZqr9OE?rel=0&autoplay=1">
<div class="et-fb-play-overlay"></div>
esc_url( ET_BUILDER_URI . '/frontend-builder/assets/img/product-tour-intro.jpg' )
'endButtonText' => esc_html__( 'Start Building', 'et_builder' ),
'endButtonTextDefault' => esc_html__( 'End the Tour', 'et_builder' ),
'skipButtonTextDefault' => esc_html__( 'Skip This Step', 'et_builder' ),
* Process builder shortcode into object
* The standard do_shortcode filter should be removed, and
* this function hooked instead
* This function is very similar to `do_shortcode`,
* with the main differences being:
* - Its main design is to allow recursive array to be built out of wp shortcode
* - Allows shortcode callback to return an array rather than a string
* - It tracks the inner `index` / `_i` of each child shortcode to the passed content, which is used in the address creation as well
* - It uses and passes `$address` & `$parent_address`, which are used by FB app
function et_fb_process_shortcode( $content, $parent_address = '', $global_parent = '', $global_parent_type = '', $parent_type = '' ) {
global $shortcode_tags, $fb_processing_counter;
if ( false === strpos( $content, '[' ) ) {
// Count started processes
$fb_processing_counter = isset($fb_processing_counter) ? $fb_processing_counter + 1 : 1;
// Find all registered tag names in $content.
preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $content, $matches );
// Only need unique tag names
$unique_matches = array_unique( $matches[1] );
$tagnames = array_intersect( array_keys( $shortcode_tags ), $unique_matches );
$pattern = get_shortcode_regex( $unique_matches );
$content = preg_match_all( "/$pattern/", $content, $matches, PREG_SET_ORDER );
foreach ( $matches as $match ) {
// reset global parent data to calculate it correctly for next modules
if ( $global_parent_type === $tag && '' !== $global_parent ) {
$global_parent_type = '';
$attr = shortcode_parse_atts( $match[3] );
if ( ! is_array( $attr ) ) {
$address = isset( $parent_address ) && '' !== $parent_address ? (string) $parent_address . '.' . (string) $index : (string) $index;
// set global parent and global parent tag if current module is global and can be a parent
$possible_global_parents = array( 'et_pb_section', 'et_pb_row', 'et_pb_row_inner' );
if ( '' === $global_parent && in_array( $tag, $possible_global_parents ) ) {
$global_parent = isset( $attr['global_module'] ) ? $attr['global_module'] : '';
$global_parent_type = $tag;
// As responsive content attributes value might be has been encoded before saving to database,
// so we need to decode it before passing back to builder.
$decoded_content_fields = array(
foreach( $decoded_content_fields as $decoded_content_field ) {
if ( array_key_exists( $decoded_content_field, $attr ) ) {
$attr[ $decoded_content_field ] = str_replace( array( '%22', '%92', '%91', '%93' ), array( '"', '\\', '[', ']' ), $attr[ $decoded_content_field ] );
$attr['_address'] = $address;
// Builder shortcode which exist on page but not registered in WP i.e. 3rd party shortcode when 3rd party module disabled
// Add dummy object to render it in Divi Builder
if ( ! in_array( $tag, $tagnames ) ) {
'component_path' => 'et-fb-removed-component',
// Flag that the shortcode object is being built.
$GLOBALS['et_fb_processing_shortcode_object'] = true;
if ( isset( $match[5] ) ) {
// @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
$output = call_user_func( $shortcode_tags[$tag], $attr, $match[5], $tag, $parent_address, $global_parent, $global_parent_type, $parent_type );
// @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
$output = call_user_func( $shortcode_tags[$tag], $attr, null, $tag );
$_matches[] = et_fb_add_additional_attrs( $attr, $output );
// Count finished processes
$fb_processing_counter = $fb_processing_counter - 1;
// Make sure ALL the processes finished to avoid wrong disabling of `et_fb_processing_shortcode_object` when several concurrent instances of `et_fb_process_shortcode` running.
if ( 0 === $fb_processing_counter ) {
// Turn off the flag since the shortcode object is done being built.
et_fb_reset_shortcode_object_processing();
// Allowlist any additional attributes
function et_fb_add_additional_attrs( $processed_attrs, $output ) {
if ( empty( $output['attrs'] ) ) {
// A list of all the attributes that are already returned after the shortcode is processed
$safe_attrs = array_keys( $output['attrs'] );
$allowlisted_attrs = array();
foreach ( $processed_attrs as $attr => $value ) {
if ( ! preg_match( '~_hover(_enabled)?$~', $attr ) ) {
$allowlisted_attrs[$attr] = $value;
if ( $allowlisted_attrs ) {
$output['attrs'] = array_merge( $output['attrs'], $allowlisted_attrs );
* Parse builder shortcode into an array.
* @param string $content Builder built post content.
* @return array Array representation of the builder shortcode.
function et_pb_parse_shortcode_to_array( $content ) {
if ( false === strpos( $content, '[' ) ) {
// Find all registered tag names in $content.
preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $content, $matches );
$tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
$pattern = get_shortcode_regex( $matches[1] );
$content = preg_match_all("/$pattern/", $content, $matches, PREG_SET_ORDER);
$shortcode_data = array();
foreach ( $matches as $match ) {
$attr = shortcode_parse_atts( $match[3] );
if ( ! is_array( $attr ) ) {
$_shortcode_data = array(
if ( ! empty( $match[5] ) ) {
$_shortcode_data['content'] = et_pb_parse_shortcode_to_array( $match[5] );
$shortcode_data[] = $_shortcode_data;
* Parse post content that includes builder shortcode to an array,
* then run it back through "some sanity check" and "some sanitization"
* and then form into a shortcode again.
* @see et_fb_process_to_shortcode() for exact sanitizations performed.
* @param string $content Builder built post content.
* @param bool $force_valid_builder_slugs Whether to force the shortcode to allow valid builder shortcode slugs only.
* @return string Sanitized builder built post content.
function et_pb_sanitize_shortcode( $content, $force_valid_builder_slugs = false ) {
if ( false === strpos( $content, '[' ) ) {
$content_array = et_pb_parse_shortcode_to_array( $content );
'force_valid_slugs' => $force_valid_builder_slugs,
$new_content = et_fb_process_to_shortcode( $content_array, $options );
* Use shortcode tag which renders the content to correctly display its properties
function et_fb_prepare_tag( $tag ) {
$aliases = apply_filters( 'et_fb_prepare_tag_aliases', array(
'et_pb_accordion_item' => 'et_pb_toggle',
return isset( $aliases[ $tag ] ) ? $aliases[ $tag ] : $tag;
if ( ! function_exists( 'et_strip_shortcodes' ) ) :
function et_strip_shortcodes( $content, $truncate_post_based_shortcodes_only = false ) {
$content = trim( $content );
$strip_content_shortcodes = array(
// list of post-based shortcodes
if ( $truncate_post_based_shortcodes_only ) {
$strip_content_shortcodes = array(
'et_pb_fullwidth_post_slider',
foreach ( $strip_content_shortcodes as $shortcode_name ) {
'(\[%1$s[^\]]*\][^\[]*\[\/%1$s\]|\[%1$s[^\]]*\])',
esc_html( $shortcode_name )
$content = preg_replace( $regex, '', $content );
// do not proceed if we need to truncate post-based shortcodes only
if ( $truncate_post_based_shortcodes_only ) {
$shortcode_tag_names = array();
foreach ( $shortcode_tags as $shortcode_tag_name => $shortcode_tag_cb ) {
if ( 0 !== strpos( $shortcode_tag_name, 'et_pb_' ) ) {
$shortcode_tag_names[] = $shortcode_tag_name;
$et_shortcodes = implode( '|', $shortcode_tag_names );
$regex_opening_shortcodes = sprintf( '(\[(%1$s)[^\]]+\])', esc_html( $et_shortcodes ) );
$regex_closing_shortcodes = sprintf( '(\[\/(%1$s)\])', esc_html( $et_shortcodes ) );
$content = preg_replace( $regex_opening_shortcodes, '', $content );
$content = preg_replace( $regex_closing_shortcodes, '', $content );
function et_fb_reset_shortcode_object_processing() {
$GLOBALS['et_fb_processing_shortcode_object'] = false;
add_action( 'et_fb_enqueue_assets', 'et_fb_backend_helpers' );
if ( ! function_exists( 'et_builder_maybe_flush_rewrite_rules' ) ) :
function et_builder_maybe_flush_rewrite_rules( $setting_name, $value = 'done' ) {
$string_value = (string) $value;