: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( ! function_exists( 'et_delete_post_video' ) ) :
* Removes the first video shortcode from content on single pages since it is displayed
* at the top of the page. This will also remove the video shortcode url from archive pages content
function et_delete_post_video( $content ) {
if ( has_post_format( 'video' ) ) :
if ( has_shortcode( $content, 'video' ) ) {
$regex = get_shortcode_regex();
preg_match_all( "/{$regex}/s", $content, $matches );
// $matches[2] holds an array of shortcodes names in the post
foreach ( $matches[2] as $key => $shortcode_match ) {
if ( 'video' === $shortcode_match ) {
$content = str_replace( $matches[0][$key], '', $content );
if ( is_single() && is_main_query() ) {
// Gutenberg compatibility
preg_match( '/<figure class="wp-block-video"[^\]]+?<video[^\]]+?src="([^\]]+?)"[^\]]+?<\/figure>/', $content, $gb_video );
if ( ! empty( $gb_video[0] ) ) {
$content = str_replace( $gb_video[0], '', $content );
// Remove GB embed caption for the first video
$content = preg_replace( '|<figure class="wp-block-embed.+?><div.+?>\s*?</div>.+?</figure>|', '', $content, 1 );
if ( ! function_exists( 'et_delete_post_audio' ) ) :
* Removes the audio shortcode of the first attached (NOT embedded) audio from content on single pages since
* it is displayed at the top of the page. This will also remove the audio shortcode url from archive pages content
* @see https://www.elegantthemes.com/gallery/divi/documentation/post-formats/
function et_delete_post_audio( $content ) {
global $_et_pbgap_audio_to_remove;
if ( has_post_format( 'audio' ) && $_et_pbgap_audio_to_remove ) {
$content = str_replace( $_et_pbgap_audio_to_remove, '', $content );
if ( ! function_exists( 'et_delete_post_first_video' ) ) :
function et_delete_post_first_video( $content ) {
if ( 'video' === et_pb_post_format() && false !== ( $first_video = et_get_first_video() ) ) {
preg_match_all( '|^\s*https?:\/\/[^\s"]+\s*|im', $content, $urls );
if ( ! empty( $urls[0] ) ) {
$content = str_replace( $urls[0], '', $content );
* Fix JetPack post excerpt shortcode issue.
function et_jetpack_post_excerpt( $results ) {
foreach ( $results as $key => $post ) {
if ( isset( $post['excerpt'] ) ) {
// Remove ET shortcodes from JetPack excerpt.
$results[$key]['excerpt'] = preg_replace( '#\[et_pb(.*)\]#', '', $post['excerpt'] );
add_filter( 'jetpack_relatedposts_returned_results', 'et_jetpack_post_excerpt' );
* Adds a Divi gallery type when the Jetpack plugin is enabled
function et_jetpack_gallery_type( $types ) {
add_filter( 'jetpack_gallery_types', 'et_jetpack_gallery_type' );
if ( ! function_exists( 'et_get_gallery_attachments' ) ) :
* Fetch the gallery attachments
function et_get_gallery_attachments( $attr ) {
// We're trusting author input, so let's at least make sure it looks like a valid orderby statement
if ( isset( $attr['orderby'] ) ) {
$attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
if ( ! $attr['orderby'] ) {
unset( $attr['orderby'] );
$html5 = current_theme_supports( 'html5', 'gallery' );
$atts = shortcode_atts( array(
'orderby' => 'menu_order ID',
'id' => get_the_ID() ? get_the_ID() : 0,
'itemtag' => $html5 ? 'figure' : 'dl',
'icontag' => $html5 ? 'div' : 'dt',
'captiontag' => $html5 ? 'figcaption' : 'dd',
$id = intval( $atts['id'] );
if ( 'RAND' === $atts['order'] ) {
$atts['orderby'] = 'none';
if ( ! empty( $atts['include'] ) ) {
$_attachments = get_posts( array(
'include' => $atts['include'],
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => $atts['order'],
'orderby' => $atts['orderby'],
foreach ( $_attachments as $key => $val ) {
$attachments[ $val->ID ] = $_attachments[ $key ];
} elseif ( ! empty( $atts['exclude'] ) ) {
$attachments = get_children( array(
'exclude' => $atts['exclude'],
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => $atts['order'],
'orderby' => $atts['orderby'],
$attachments = get_children( array(
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => $atts['order'],
'orderby' => $atts['orderby'],
* Generate the HTML for custom gallery layouts
function et_gallery_layout( $val, $attr ) {
// check to see if the gallery output is already rewritten
// Do not filter gallery items in plugin to not break custom styles which may be applied by 3rd party theme
if ( et_is_builder_plugin_active() ) {
if ( ! apply_filters( 'et_gallery_layout_enable', false ) ) {
if ( ! is_singular() && ! et_pb_is_pagebuilder_used( get_the_ID() ) && ! is_et_pb_preview() ) {
$attachments = et_get_gallery_attachments( $attr );
foreach ( $attachments as $attachment ) {
$attachment_image = wp_get_attachment_url( $attachment->ID, 'et-pb-post-main-image-fullwidth' );
$gallery_output .= sprintf(
'<div class="et_pb_slide" style="background: url(%1$s);"></div>',
esc_attr( $attachment_image )
'<div class="et_pb_slider et_pb_slider_fullwidth_off et_pb_gallery_post_type">
<div class="et_pb_slides">
if ( ! isset( $attr['type'] ) || ! in_array( $attr['type'], array( 'rectangular', 'square', 'circle', 'rectangle' ) ) ) {
$attachments = et_get_gallery_attachments( $attr );
foreach ( $attachments as $attachment ) {
$gallery_output .= sprintf(
'<li class="et_gallery_item et_pb_gallery_image">
<a href="%1$s" title="%3$s">
<span class="et_portfolio_image">
<span class="et_overlay"></span>
esc_url( wp_get_attachment_url( $attachment->ID, 'full' ) ),
wp_get_attachment_image( $attachment->ID, 'et-pb-portfolio-image' ),
esc_attr( $attachment->post_title ),
! empty( $attachment->post_excerpt )
? sprintf( '<p class="et_pb_gallery_caption">%1$s</p>', esc_html( $attachment->post_excerpt ) )
'<ul class="et_post_gallery clearfix">
add_filter( 'post_gallery', 'et_gallery_layout', 1000, 2 );
if ( ! function_exists( 'et_pb_gallery_images' ) ) :
function et_pb_gallery_images( $force_gallery_layout = '' ) {
if ( 'slider' === $force_gallery_layout ) {
$post = get_post( get_the_ID() );
// We want to include GB galleries in results so need to convert them to shortcodes
// because `get_post_gallery` won't find them otherwise.
$post->post_content = apply_filters( 'et_gb_galleries_to_shortcodes', $post->post_content );
$attachments = get_post_gallery( $post, false );
$images_array = ! empty( $attachments['ids'] ) ? explode( ',', $attachments['ids'] ) : array();
if ( empty ( $images_array ) ) {
foreach ( $images_array as $attachment ) {
$image_src = wp_get_attachment_url( $attachment, 'et-pb-post-main-image-fullwidth' );
$gallery_output .= sprintf(
'<div class="et_pb_slide" style="background: url(%1$s);"></div>',
'<div class="et_pb_slider et_pb_slider_fullwidth_off et_pb_gallery_post_type">
<div class="et_pb_slides">
et_core_esc_previously( $gallery_output )
add_filter( 'et_gallery_layout_enable', 'et_gallery_layout_turn_on' );
et_core_intentionally_unescaped( get_post_gallery(), 'html' )
remove_filter( 'et_gallery_layout_enable', 'et_gallery_layout_turn_on' );
* Used to always use divi gallery on et_pb_gallery_images
function et_gallery_layout_turn_on() {
* Remove Elegant Builder plugin filter, that activates visual mode on each page load in WP-Admin
function et_pb_remove_lb_plugin_force_editor_mode() {
remove_filter( 'wp_default_editor', 'et_force_tmce_editor' );
add_action( 'admin_init', 'et_pb_remove_lb_plugin_force_editor_mode' );
* Generates array of all Role options
function et_pb_all_role_options() {
// get all the modules and build array of capabilities for them
$all_modules_array = ET_Builder_Element::get_modules_array();
$custom_user_tabs = ET_Builder_Element::get_tabs();
$options_categories = ET_Builder_Element::get_options_categories();
$module_capabilies = array();
'general_settings' => array(
'name' => esc_html__( 'Content Settings', 'et_builder' ),
'advanced_settings' => array(
'name' => esc_html__( 'Design Settings', 'et_builder' ),
'custom_css_settings' => array(
'name' => esc_html__( 'Advanced Settings', 'et_builder' ),
// add all custom user tabs into list
if ( ! empty( $custom_user_tabs ) ) {
foreach( $custom_user_tabs as $module => $tabs_data ) {
if ( ! empty( $tabs_data ) ) {
foreach( $tabs_data as $tab_slug => $tab_data ) {
$tabs_array[$tab_slug] = array(
'name' => $tab_data['name'],
foreach ( $all_modules_array as $module => $module_details ) {
if ( ! in_array( $module_details['label'], array( 'et_pb_section', 'et_pb_row', 'et_pb_row_inner', 'et_pb_column' ) ) ) {
$module_capabilies[ $module_details['label'] ] = array(
'name' => sanitize_text_field( $module_details['title'] ),
// we need to display some options only when theme activated
$theme_only_options = ! et_is_builder_plugin_active()
'theme_customizer' => array(
'name' => esc_html__( 'Theme Customizer', 'et_builder' ),
'applicability' => array( 'administrator' ),
'name' => esc_html__( 'Page Options', 'et_builder' ),
$all_role_options = array(
'general_capabilities' => array(
'theme_options' => array(
'name' => et_is_builder_plugin_active() ? esc_html__( 'Plugin Options', 'et_builder' ) : esc_html__( 'Theme Options', 'et_builder' ),
'applicability' => array( 'administrator' ),
'name' => esc_html__( 'Divi Library', 'et_builder' ),
'theme_builder' => array(
'name' => esc_html__( 'Theme Builder', 'et_builder' ),
'applicability' => array( 'administrator', 'editor' ),
'name' => esc_html__( 'Split Testing', 'et_builder' ),
'builder_capabilities' => array(
'section_title' => esc_html__( 'Builder Interface', 'et_builder'),
'name' => esc_html__( 'Add/Delete Item', 'et_builder' ),
'name' => esc_html__( 'Edit Item', 'et_builder' ),
'name' => esc_html__( 'Move Item', 'et_builder' ),
'disable_module' => array(
'name' => esc_html__( 'Disable Item', 'et_builder' ),
'name' => esc_html__( 'Lock Item', 'et_builder' ),
'divi_builder_control' => array(
'name' => esc_html__( 'Toggle Divi Builder', 'et_builder' ),
'name' => esc_html__( 'Load Layout', 'et_builder' ),
'use_visual_builder' => array(
'name' => esc_html__( 'Use Visual Builder', 'et_builder' ),
'custom_fonts_management' => array(
'name' => esc_html__( 'Upload/Remove Fonts', 'et_builder' ),
'read_dynamic_content_custom_fields' => array(
'name' => esc_html__( 'Dynamic Content Custom Fields', 'et_builder' ),
'library_capabilities' => array(
'section_title' => esc_html__( 'Library Settings', 'et_builder' ),
'name' => esc_html__( 'Save To Library', 'et_builder' ),
'name' => esc_html__( 'Add From Library', 'et_builder' ),
'edit_global_library' => array(
'name' => esc_html__( 'Edit Global Items', 'et_builder' ),
'section_title' => esc_html__( 'Settings Tabs', 'et_builder' ),
'options' => $tabs_array,
'general_module_capabilities' => array(
'section_title' => esc_html__( 'Settings Types', 'et_builder' ),
'options' => $options_categories,
'module_capabilies' => array(
'section_title' => esc_html__( 'Module Use', 'et_builder' ),
'options' => $module_capabilies,
$all_role_options = apply_filters( 'add_et_builder_role_options', $all_role_options );
$all_role_options['general_capabilities']['options'] = array_merge( $all_role_options['general_capabilities']['options'], $theme_only_options );
// Set portability capabilities.
$registered_portabilities = et_core_cache_get_group( 'et_core_portability' );
if ( ! empty( $registered_portabilities ) ) {
$all_role_options['general_capabilities']['options']['portability'] = array(
'name' => esc_html__( 'Portability', 'et_builder' ),
$all_role_options['portability'] = array(
'section_title' => esc_html__( 'Portability', 'et_builder' ),
// Dynamically create an option foreach portability.
foreach ( $registered_portabilities as $portability_context => $portability_instance ) {
$all_role_options['portability']['options']["{$portability_context}_portability"] = array(
'name' => esc_html( $portability_instance->name ),
return $all_role_options;
* Prints the admin page for Role Editor
function et_pb_display_role_editor() {
$all_role_options = et_pb_all_role_options();
$builder_roles_array = et_pb_get_all_roles_list();
foreach( $builder_roles_array as $role => $role_title ) {
$option_tabs .= et_pb_generate_roles_tab( $all_role_options, $role );
'<a href="#" class="et-pb-layout-buttons%4$s" data-open_tab="et_pb_role-%3$s_options" title="%1$s">
'administrator' === $role ? ' et_pb_roles_active_menu' : ''
'<div class="et_pb_roles_main_container">
<a href="#" id="et_pb_save_roles" class="button button-primary button-large">%3$s</a>
<h3 class="et_pb_roles_title"><span>%2$s</span></h3>
<div id="et_pb_main_container" class="post-type-page">
<div id="et_pb_layout_controls">
<a href="#" class="et-pb-layout-buttons et-pb-layout-buttons-reset" title="Reset all settings">
<span class="icon"></span><span class="label">Reset</span>