(.*?)<\/script>/mis',
array( $this, 'fix_wptexturized_script' ),
$content
);
}
/**
* Callback :: Sort fields within tabs by priority.
*
* @param string $a Comparision field member.
* @param string $b Comparision field string.
*
* @return int|lt
*/
public static function compare_by_priority( $a, $b ) {
$a_priority = ! empty( $a['priority'] ) ? (int) $a['priority'] : self::DEFAULT_PRIORITY;
$b_priority = ! empty( $b['priority'] ) ? (int) $b['priority'] : self::DEFAULT_PRIORITY;
if ( isset( $a['_order_number'], $b['_order_number'] ) && ( $a_priority === $b_priority ) ) {
return $a['_order_number'] - $b['_order_number'];
}
return $a_priority - $b_priority;
}
/**
* Reorder toggles based on the priority with respect to manually ordered items with no priority
*
* @param array $toggles_array Toggles to reorder.
*
* @return array
*/
public static function et_pb_order_toggles_by_priority( $toggles_array ) {
if ( empty( $toggles_array ) ) {
return array();
}
$high_priority_toggles = array();
$low_priority_toggles = array();
$manually_ordered_toggles = array();
// fill 3 arrays based on priority.
foreach ( $toggles_array as $toggle_id => $toggle_data ) {
if ( isset( $toggle_data['priority'] ) ) {
if ( $toggle_data['priority'] < 10 ) {
$high_priority_toggles[ $toggle_id ] = $toggle_data;
} else {
$low_priority_toggles[ $toggle_id ] = $toggle_data;
}
} else {
// keep the original order of options without priority defined.
$manually_ordered_toggles[ $toggle_id ] = $toggle_data;
}
}
// order high and low priority toggles.
uasort( $high_priority_toggles, array( 'self', 'compare_by_priority' ) );
uasort( $low_priority_toggles, array( 'self', 'compare_by_priority' ) );
// merge 3 arrays to get the correct order of toggles.
return array_merge( $high_priority_toggles, $manually_ordered_toggles, $low_priority_toggles );
}
/**
* Callback :: Sort modules alphabetically by name.
*
* @param string $a Comparision member string.
* @param string $b Comparision member string.
*
* @return int|lt
*/
public static function compare_by_name( $a, $b ) {
return strcasecmp( $a->name, $b->name );
}
/**
* Get total modules count.
*
* @param string $post_type Post type.
*
* @return int
*/
public static function get_modules_count( $post_type ) {
$parent_modules = self::get_parent_modules( $post_type );
$child_modules = self::get_child_modules( $post_type );
$overall_count = count( $parent_modules ) + count( $child_modules );
return $overall_count;
}
/**
* Get modules js array to use in backbone template.
*
* @param string $post_type Current post type.
*
* @return string
*/
public static function get_modules_js_array( $post_type ) {
$modules = array();
$parent_modules = self::get_parent_modules( $post_type );
if ( ! empty( $parent_modules ) ) {
/**
* Sort modules alphabetically by name.
*/
$sorted_modules = $parent_modules;
uasort( $sorted_modules, array( 'self', 'compare_by_name' ) );
foreach ( $sorted_modules as $module ) {
/**
* Replace single and double quotes with %% and || respectively
* to avoid js conflicts
*/
$module_name = str_replace( array( '"', '"', '"', '"' ), '%%', $module->name );
$module_name = str_replace( array( "'", ''', ''' ), '||', $module_name );
$modules[] = sprintf(
'{ "title" : "%1$s", "label" : "%2$s"%3$s}',
esc_js( $module_name ),
esc_js( $module->slug ),
( isset( $module->fullwidth ) && $module->fullwidth ? ', "fullwidth_only" : "on"' : '' )
);
}
}
return '[' . implode( ',', $modules ) . ']';
}
/**
* Get all modules array.
*
* @param string $post_type Post type.
* @param bool $include_child Whether to include childs.
*
* @return array
*/
public static function get_modules_array( $post_type = '', $include_child = false ) {
$modules = array();
$module_icons = self::get_module_icons();
if ( ! empty( $post_type ) ) {
$parent_modules = self::get_parent_modules( $post_type );
if ( $include_child ) {
$parent_modules = array_merge( $parent_modules, self::get_child_modules( $post_type ) );
}
if ( ! empty( $parent_modules ) ) {
$sorted_modules = $parent_modules;
}
} else {
$parent_modules = self::get_parent_modules();
if ( $include_child ) {
$parent_modules = array_merge( $parent_modules, self::get_child_modules() );
}
if ( ! empty( $parent_modules ) ) {
$all_modules = array();
foreach ( $parent_modules as $post_type => $post_type_modules ) {
foreach ( $post_type_modules as $module_slug => $module ) {
$all_modules[ $module_slug ] = $module;
}
}
$sorted_modules = $all_modules;
}
}
if ( ! empty( $sorted_modules ) ) {
/**
* Sort modules alphabetically by name.
*/
uasort( $sorted_modules, array( 'self', 'compare_by_name' ) );
foreach ( $sorted_modules as $module ) {
/**
* Replace single and double quotes with %% and || respectively
* to avoid js conflicts
*/
$module_name = str_replace( '"', '%%', $module->name );
$module_name = str_replace( "'", '||', $module_name );
$module_name_plural = str_replace( '"', '%%', empty( $module->plural ) ? $module->name : $module->plural );
$module_name_plural = str_replace( "'", '||', $module_name_plural );
$_module = array(
'title' => esc_attr( $module_name ),
'plural' => esc_attr( $module_name_plural ),
'label' => esc_attr( $module->slug ),
'is_parent' => 'child' === $module->type ? 'off' : 'on',
'is_official_module' => $module->_is_official_module,
'use_unique_id' => $module->_use_unique_id,
'vb_support' => isset( $module->vb_support ) ? $module->vb_support : 'off',
'folder_name' => isset( $module->folder_name ) ? $module->folder_name : '',
);
if ( isset( $module->fullwidth ) && $module->fullwidth ) {
$_module['fullwidth_only'] = 'on';
}
// Get module icon character (font-icon).
$icon = self::$_->array_get( $module_icons, "{$module->slug}.icon" );
if ( $icon ) {
$_module['icon'] = $icon;
}
// Get module icon svg from fetched svg content.
$icon_svg = self::$_->array_get( $module_icons, "{$module->slug}.icon_svg" );
if ( $icon_svg ) {
$_module['icon_svg'] = $icon_svg;
}
$modules[] = $_module;
}
}
return $modules;
}
/**
* Get modules that does not support VB.
*
* @return array
*/
public static function get_fb_unsupported_modules() {
$parent_modules = self::get_parent_modules();
$unsupported_modules_array = array();
foreach ( $parent_modules as $post_type => $post_type_modules ) {
foreach ( $post_type_modules as $module_slug => $module ) {
if ( ! isset( $module->vb_support ) || 'off' === $module->vb_support ) {
$unsupported_modules_array[] = $module_slug;
}
}
}
return array_unique( $unsupported_modules_array );
}
/**
* Get list of modules that has rich content option
*
* @since 3.18
*
* @return array
*/
public static function get_has_content_modules() {
return self::$has_content_modules;
}
/**
* Returns a regex pattern that includes all parent module slugs.
*
* @since 3.1 Renamed from `get_parent_shortcodes()` to `get_parent_slugs_regex()`
* @since 1.0
*
* @param string $post_type Post type.
*
* @return string
*/
public static function get_parent_slugs_regex( $post_type = 'page' ) {
$slugs = array();
$parent_modules = self::get_parent_modules( $post_type );
if ( ! empty( $parent_modules ) ) {
foreach ( $parent_modules as $module ) {
$slugs[] = $module->slug;
}
}
return implode( '|', $slugs );
}
/**
* Returns a regex pattern that includes all child module slugs.
*
* @since 3.1 Renamed from `get_child_shortcodes()` to `get_child_slugs_regex()`
* @since 1.0
*
* @param string $post_type Post type.
*
* @return string
*/
public static function get_child_slugs_regex( $post_type = 'page' ) {
$slugs = array();
$child_modules = self::get_child_modules( $post_type );
if ( ! empty( $child_modules ) ) {
foreach ( $child_modules as $slug => $module ) {
if ( ! empty( $slug ) ) {
$slugs[] = $slug;
}
}
}
return implode( '|', $slugs );
}
/**
* Get child module slugs.
*
* @param string $post_type Post type.
*
* @return array
*/
public static function get_child_slugs( $post_type ) {
$child_slugs = array();
$child_modules = self::get_parent_modules( $post_type );
if ( ! empty( $child_modules ) ) {
foreach ( $child_modules as $module ) {
if ( ! empty( $module->child_slug ) ) {
$child_slugs[ $module->slug ] = $module->child_slug;
}
}
}
return $child_slugs;
}
/**
* Get row content module slugs. e.x et_pb_code
*
* @param string $post_type Post type.
*
* @return string
*/
public static function get_raw_content_slugs( $post_type ) {
$shortcodes = array();
$parent_modules = self::get_parent_modules( $post_type );
if ( ! empty( $parent_modules ) ) {
foreach ( $parent_modules as $module ) {
if ( isset( $module->use_raw_content ) && $module->use_raw_content ) {
$shortcodes[] = $module->slug;
}
}
}
$child_modules = self::get_child_modules( $post_type );
if ( ! empty( $child_modules ) ) {
foreach ( $child_modules as $module ) {
if ( isset( $module->use_raw_content ) && $module->use_raw_content ) {
$shortcodes[] = $module->slug;
}
}
}
return implode( '|', $shortcodes );
}
/**
* Get the portion of templates for specified slugs.
*
* @param string $post_type Post type.
* @param array $slugs_array Module slugs.
*
* @return array|string|void
*/
public static function get_modules_templates( $post_type, $slugs_array ) {
$all_modules = self::get_parent_and_child_modules( $post_type );
$templates_array = array();
if ( empty( $slugs_array ) ) {
return;
}
foreach ( $slugs_array as $slug ) {
if ( ! isset( $all_modules[ $slug ] ) ) {
return '';
}
$module = $all_modules[ $slug ];
$templates_array[] = array(
'slug' => $slug,
'template' => $module->build_microtemplate(),
);
}
if ( ET_BUILDER_OPTIMIZE_TEMPLATES ) {
$templates_array = array(
'templates' => $templates_array,
'unique' => self::$_unique_bb_keys_values,
);
}
return $templates_array;
}
/**
* Output modules backbone templates.
*
* @param string $post_type Post type.
* @param int $start_from Unused arg.
* @param int $amount Unused arg.
*
* @return array
*/
public static function output_templates( $post_type = '', $start_from = 0, $amount = 999 ) {
$all_modules = self::get_parent_and_child_modules( $post_type );
$modules_names = array_keys( $all_modules );
$output = array();
$output['templates'] = array();
if ( ! empty( $all_modules ) ) {
for ( $i = 0; $i < ET_BUILDER_AJAX_TEMPLATES_AMOUNT; $i++ ) {
if ( isset( $modules_names[ $i ] ) ) {
$module = $all_modules[ $modules_names[ $i ] ];
$output['templates'][ $module->slug ] = self::optimize_bb_chunk( $module->build_microtemplate() );
} else {
break;
}
}
}
if ( ET_BUILDER_OPTIMIZE_TEMPLATES ) {
$output['unique'] = self::$_unique_bb_keys_values;
}
return $output;
}
/**
* Get structure module slugs.
*
* @return array
*/
public static function get_structure_module_slugs() {
if ( ! empty( self::$structure_module_slugs ) ) {
return self::$structure_module_slugs;
}
$structure_modules = self::get_structure_modules();
self::$structure_module_slugs = array();
foreach ( $structure_modules as $structural_module ) {
self::$structure_module_slugs[] = $structural_module->slug;
}
/**
* Filters structural module slugs.
*
* @since 4.10.0
*
* @param array $structure_module_slugs.
*/
return apply_filters( 'et_builder_get_structural_module_slugs', self::$structure_module_slugs );
}
/**
* Get structure modules.
*
* @return array
*/
public static function get_structure_modules() {
if ( ! empty( self::$structure_modules ) ) {
return self::$structure_modules;
}
$parent_modules = self::get_parent_modules( 'et_pb_layout' );
self::$structure_modules = array();
foreach ( $parent_modules as $parent_module ) {
if ( isset( $parent_module->is_structure_element ) && $parent_module->is_structure_element ) {
$parent_module->plural = empty( $parent_module->plural ) ? $parent_module->name : $parent_module->plural;
self::$structure_modules[] = $parent_module;
}
}
return self::$structure_modules;
}
/**
* Get a filtered list of modules.
*
* @since 3.10
*
* @param string $post_type Leave empty for any.
* @param string $type 'parent' or 'child'. Leave empty for any.
*
* @return ET_Builder_Element[]
*/
public static function get_modules( $post_type = '', $type = '' ) {
$modules = array();
foreach ( self::$modules as $slug => $module ) {
if ( '' !== $post_type && ! in_array( $post_type, $module->post_types, true ) ) {
continue;
}
if ( '' !== $type && ! $module->type !== $type ) {
continue;
}
$modules[ $slug ] = $module;
}
return $modules;
}
/**
* Get modules by fallback post type for disabled post type.
*
* @param string $type Module type.
*
* @return ET_Builder_Element[]|mixed
*/
public static function get_custom_post_type_fallback_modules( $type = 'parent' ) {
$modules = 'child' === $type ? self::$child_modules : self::$parent_modules;
// Most of the time, page module is expected to be used as disabled post type fallback.
if ( isset( $modules['page'] ) ) {
return $modules['page'];
}
// Post module is also expected to be used.
if ( isset( $modules['post'] ) ) {
return $modules['post'];
}
// If Divi Builder is disabled for all post types use layout modules as fallback.
if ( isset( $modules['et_pb_layout'] ) ) {
return $modules['et_pb_layout'];
}
// If all else fail, use all modules.
return self::get_modules();
}
/**
* Get all parent modules.
*
* @param string $post_type Current post type.
*
* @return mixed|void
*/
public static function get_parent_modules( $post_type = '' ) {
if ( ! empty( $post_type ) ) {
// We get all modules when post type is not enabled so that posts that have
// had their post type support disabled still load all necessary modules.
$parent_modules = ! empty( self::$parent_modules[ $post_type ] )
? self::$parent_modules[ $post_type ]
: self::get_custom_post_type_fallback_modules( 'parent' );
} else {
$parent_modules = self::$parent_modules;
}
return apply_filters( 'et_builder_get_parent_modules', $parent_modules, $post_type );
}
/**
* Get all child modules.
*
* @param string $post_type Current post type.
*
* @return mixed|void
*/
public static function get_child_modules( $post_type = '' ) {
if ( ! empty( $post_type ) ) {
// We get all modules when post type is not enabled so that posts that have
// had their post type support disabled still load all necessary modules.
$child_modules = ! empty( self::$child_modules[ $post_type ] )
? self::$child_modules[ $post_type ]
: self::get_custom_post_type_fallback_modules( 'child' );
} else {
$child_modules = self::$child_modules;
}
return apply_filters( 'et_builder_get_child_modules', $child_modules, $post_type );
}
/**
* Get woocommerce modules.
*
* @return mixed|void
*/
public static function get_woocommerce_modules() {
return apply_filters( 'et_builder_get_woocommerce_modules', self::$woocommerce_modules );
}
/**
* Get registered module icons
*
* @since 3.1
*
* @return array
*/
public static function get_module_icons() {
/**
* Filters Module Icons displayed in Add Module modals.
*
* @param array $module_icons Array of all registered module icons.
*/
$module_icons = apply_filters( 'et_builder_module_icons', self::$module_icons );
// Loop module icons.
foreach ( $module_icons as $key => $icons ) {
if ( isset( $icons['icon_path'] ) ) {
// Get svg content based on given svg's path.
$icon_svg = et_()->WPFS()->exists( $icons['icon_path'] ) ? et_()->WPFS()->get_contents( $icons['icon_path'] ) : false;
if ( $icon_svg ) {
$module_icons[ $key ]['icon_svg'] = $icon_svg;
// Remove icon path attribute since it's no longer used.
unset( $module_icons[ $key ]['icon_path'] );
}
}
}
return $module_icons;
}
/**
* Get combined array of child and parent modules for provided post_type
*
* @param string $post_type Post type.
*
* @since 3.1
*
* @return array
*/
public static function get_parent_and_child_modules( $post_type = '' ) {
$parent_modules = self::get_parent_modules( $post_type );
$child_modules = self::get_child_modules( $post_type );
return array_merge( $parent_modules, $child_modules );
}
/**
* Get a module instance for provided post type by its slug.
*
* @since 3.10
*
* @param string $slug Module slug.
* @param string $post_type Current post type.
*
* @return ET_Builder_Element|null
*/
public static function get_module( $slug, $post_type = 'post' ) {
$modules = self::get_parent_and_child_modules( $post_type );
return self::$_->array_get( $modules, $slug );
}
/**
* Outputs list of all module help videos array
*
* @since 3.1
*
* @return array
*/
public static function get_help_videos() {
return self::$module_help_videos;
}
/**
* Get list of modules with support of featured image as background.
*
* @param string $post_type Current post type.
*
* @return mixed|void
*/
public static function get_featured_image_background_modules( $post_type = '' ) {
$parent_modules = self::get_parent_modules( $post_type );
$featured_image_background_modules = array();
foreach ( $parent_modules as $slug => $parent_module ) {
if ( ! empty( $parent_module->featured_image_background ) ) {
$featured_image_background_modules[] = $slug;
}
}
/**
* Filters list of modules with support of featured image as background.
*
* @since 3.1
*
* @param array[] $featured_image_background_modules List of modules with support of featured image as background.
*/
return apply_filters( 'et_pb_featured_image_background_modules', $featured_image_background_modules );
}
/**
* Get field group toggles.
*
* @param string $post_type Post type.
*
* @return array
*/
public static function get_toggles( $post_type ) {
static $toggles_array = array();
if ( $toggles_array ) {
return $toggles_array;
}
$modules = self::get_parent_and_child_modules( $post_type );
$custom_modules = array();
foreach ( $modules as $module_slug => $module ) {
if ( ! $module->_is_official_module ) {
$custom_modules[ $module_slug ] = $module;
}
foreach ( $module->settings_modal_toggles as $tab_slug => &$tab_data ) {
if ( ! isset( $tab_data['toggles'] ) ) {
continue;
}
$tab_data['toggles'] = self::et_pb_order_toggles_by_priority( $tab_data['toggles'] );
}
$toggles_array[ $module_slug ] = $module->settings_modal_toggles;
}
if ( $custom_modules ) {
// Add missing toggle definitions for any existing toggles used in custom modules.
foreach ( $custom_modules as $module_slug => $module ) {
foreach ( $module->get_complete_fields() as $field_name => $field_info ) {
$tab_slug = self::$_->array_get( $field_info, 'tab_slug' );
$tab_slug = empty( $tab_slug ) ? 'general' : $tab_slug;
$toggle_slug = self::$_->array_get( $field_info, 'toggle_slug' );
if ( ! $toggle_slug || isset( $toggles_array[ $module_slug ][ $tab_slug ]['toggles'][ $toggle_slug ] ) ) {
continue;
}
// Find existing definition.
foreach ( $toggles_array as $_module_slug => $tabs ) {
foreach ( $tabs as $tab => $toggles ) {
if ( isset( $toggles['toggles'][ $toggle_slug ] ) ) {
self::$_->array_set(
$toggles_array,
"{$module_slug}.{$tab_slug}.toggles.{$toggle_slug}",
$toggles['toggles'][ $toggle_slug ]
);
$toggles_array[ $module_slug ][ $tab_slug ]['toggles'] = self::et_pb_order_toggles_by_priority( $toggles_array[ $module_slug ][ $tab_slug ]['toggles'] );
break 2;
}
}
}
// Add missing unregistered toggles to the list.
if ( ! isset( $toggles_array[ $module_slug ][ $tab_slug ]['toggles'][ $toggle_slug ] ) ) {
if ( ! isset( $toggles_array[ $module_slug ][ $tab_slug ] ) ) {
$toggles_array[ $module_slug ][ $tab_slug ] = array( 'toggles' => array( $toggle_slug ) );
} else {
$toggles_array[ $module_slug ][ $tab_slug ]['toggles'][] = $toggle_slug;
}
}
}
}
}
return $toggles_array;
}
/**
* Get setting modal tabs.
*
* @param string $post_type Current post type.
*
* @return array
*/
public static function get_tabs( $post_type = '' ) {
$official_tabs = array(
'general' => '',
'advanced' => '',
'custom_css' => '',
);
$tabs_array = array();
$modules = self::get_parent_and_child_modules( $post_type );
foreach ( $modules as $module_slug => $module ) {
if ( '' === $post_type ) {
foreach ( $module as $_module_slug => $_module ) {
// Backward compatibility with custom tabs registered via `et_builder_main_tabs` filter.
$bb_custom_tabs = array_diff_key( $_module->get_main_tabs(), $official_tabs );
$bb_custom_tabs_formatted = array();
// Prepare properly formatted array of tabs data.
foreach ( $bb_custom_tabs as $tab_id => $tab_name ) {
$bb_custom_tabs_formatted[ $tab_id ] = array( 'name' => $tab_name );
}
// Add BB custom tabs to all modules.
$tabs_array[ $_module_slug ] = $bb_custom_tabs_formatted;
if ( ! isset( $_module->settings_modal_tabs ) ) {
continue;
}
$tabs_array[ $_module_slug ] = array_merge( $tabs_array[ $_module_slug ], $_module->settings_modal_tabs );
}
} else {
// Backward compatibility with custom tabs registered via `et_builder_main_tabs` filter.
$bb_custom_tabs = array_diff_key( $module->get_main_tabs(), $official_tabs );
$bb_custom_tabs_formatted = array();
// Prepare properly formatted array of tabs data.
foreach ( $bb_custom_tabs as $tab_id => $tab_name ) {
$bb_custom_tabs_formatted[ $tab_id ] = array( 'name' => $tab_name );
}
// Add BB custom tabs to all modules.
$tabs_array[ $module_slug ] = $bb_custom_tabs_formatted;
if ( ! isset( $module->settings_modal_tabs ) ) {
continue;
}
$tabs_array[ $module_slug ] = array_merge( $tabs_array[ $module_slug ], $module->settings_modal_tabs );
}
}
return $tabs_array;
}
/**
* Get permission options categories.
*
* @return array
*/
public static function get_options_categories() {
$options_categories = array(
'edit_colors' => array(
'name' => esc_html__( 'Edit Colors', 'et_builder' ),
),
'edit_content' => array(
'name' => esc_html__( 'Edit Content', 'et_builder' ),
),
'edit_fonts' => array(
'name' => esc_html__( 'Edit Fonts', 'et_builder' ),
),
'edit_buttons' => array(
'name' => esc_html__( 'Edit Buttons', 'et_builder' ),
),
'edit_layout' => array(
'name' => esc_html__( 'Edit Layout', 'et_builder' ),
),
'edit_borders' => array(
'name' => esc_html__( 'Edit Borders', 'et_builder' ),
),
'edit_configuration' => array(
'name' => esc_html__( 'Edit Configuration', 'et_builder' ),
),
);
$options_categories = array_merge( $options_categories, self::get_custom_options_categories() );
return $options_categories;
}
/**
* Get custom permission option categories.
*
* @param string $post_type Post type.
*
* @return array
*/
public static function get_custom_options_categories( $post_type = '' ) {
$parent_modules = self::get_parent_modules( $post_type );
$child_modules = self::get_child_modules( $post_type );
$custom_options_categories = array();
$_modules = array_merge_recursive( $parent_modules, $child_modules );
foreach ( $_modules as $_module_slug => $_module ) {
if ( '' === $post_type ) {
foreach ( $_module as $__module_slug => $__module ) {
if ( ! isset( $__module->options_categories ) ) {
continue;
}
$custom_options_categories = array_merge( $custom_options_categories, $__module->options_categories );
}
} else {
if ( ! isset( $_module->options_categories ) ) {
continue;
}
$custom_options_categories = array_merge( $custom_options_categories, $_module->options_categories );
}
}
return $custom_options_categories;
}
/**
* Get all fields.
*
* @param string $post_type Post type.
*
* @return array
*/
public static function get_all_fields( $post_type = '' ) {
$_modules = self::get_parent_and_child_modules( $post_type );
$module_fields = array();
foreach ( $_modules as $_module_slug => $_module ) {
// skip modules without fb support.
if ( ! isset( $_module->vb_support ) || 'off' === $_module->vb_support ) {
continue;
}
$_module->set_fields();
$_module->_add_additional_fields();
$_module->_add_custom_css_fields();
$_module->_maybe_add_defaults();
$_module->_finalize_all_fields();
foreach ( $_module->fields_unprocessed as $field_key => $field ) {
// do not add the fields with 'skip' type. These fields used for rendering shortcode on Front End only.
if ( isset( $field['type'] ) && 'skip' === $field['type'] ) {
continue;
}
$field['name'] = $field_key;
$module_fields[ $_module_slug ][ $field_key ] = $field;
}
}
return $module_fields;
}
/**
* Get general fields of modules.
*
* @param string $post_type Post type.
* @param string $mode Modules Mode - Parent, Child and All.
* @param string $module_type Module Slug.
*
* @return array|mixed
*/
public static function get_general_fields( $post_type = '', $mode = 'all', $module_type = 'all' ) {
$parent_modules = self::get_parent_modules( $post_type );
$child_modules = self::get_child_modules( $post_type );
switch ( $mode ) {
case 'parent':
$_modules = $parent_modules;
break;
case 'child':
$_modules = $child_modules;
break;
default:
$_modules = array_merge( $parent_modules, $child_modules );
break;
}
$module_fields = array();
foreach ( $_modules as $_module_slug => $_module ) {
// filter modules by slug if needed.
if ( 'all' !== $module_type && $module_type !== $_module_slug ) {
continue;
}
foreach ( $_module->fields_unprocessed as $field_key => $field ) {
$is_option_template = self::$option_template->is_option_template_field( $field_key );
// Do not process field template.
if ( ! $is_option_template && ( isset( $field['tab_slug'] ) && 'general' !== $field['tab_slug'] ) ) {
continue;
}
// Skip if current option template isn't eligible for `advanced` tab.
if ( $is_option_template && ! self::$option_template->is_template_inside_tab( 'general', $field ) ) {
continue;
}
$module_fields[ $_module_slug ][ $field_key ] = $field;
}
// Some module types must be separated for the Global Presets.
// For example we keep all section types as `et_pb_section` however they need different Global Presets.
$additional_slugs = self::$global_presets_manager->get_module_additional_slugs( $_module_slug );
foreach ( $additional_slugs as $alias ) {
$module_fields[ $alias ] = $module_fields[ $_module_slug ];
}
}
if ( 'all' !== $module_type ) {
return $module_fields[ $module_type ];
}
return $module_fields;
}
/**
* Get setting fields from custom tabs.
*
* @param string $post_type Post type.
* @param string $mode Modules Mode - Parent, Child and All.
* @param string $module_type Module Slug.
*
* @return array|mixed
*/
public static function get_settings_modal_tabs_fields( $post_type = '', $mode = 'all', $module_type = 'all' ) {
$parent_modules = self::get_parent_modules( $post_type );
$child_modules = self::get_child_modules( $post_type );
switch ( $mode ) {
case 'parent':
$_modules = $parent_modules;
break;
case 'child':
$_modules = $child_modules;
break;
default:
$_modules = array_merge( $parent_modules, $child_modules );
break;
}
$module_fields = array();
foreach ( $_modules as $_module_slug => $_module ) {
// filter modules by slug if needed.
if ( 'all' !== $module_type && $module_type !== $_module_slug ) {
continue;
}
foreach ( $_module->fields_unprocessed as $field_key => $field ) {
$this_tab_slug = isset( $field['tab_slug'] ) ? $field['tab_slug'] : false;
if ( ! $this_tab_slug || in_array( $this_tab_slug, array( 'general', 'advanced', 'custom_css' ), true ) ) {
continue;
}
$field['name'] = $field_key;
$module_fields[ $_module_slug ][ $this_tab_slug ][ $field_key ] = $field;
}
}
if ( 'all' !== $module_type ) {
return $module_fields[ $module_type ];
}
return $module_fields;
}
/**
* Get child module titles.
*
* @param string $post_type Post type.
*
* @return array
*/
public static function get_child_module_titles( $post_type ) {
$child_modules = self::get_child_modules( $post_type );
$child_modules_titles = array();
$child_modules_titles_fields = array( 'advanced_setting_title_text', 'child_title_fallback_var', 'child_title_var' );
foreach ( $child_modules as $_module_slug => $_module ) {
foreach ( $child_modules_titles_fields as $single_field ) {
if ( isset( $_module->$single_field ) ) {
$child_modules_titles[ $_module_slug ][ $single_field ] = $_module->$single_field;
}
}
}
return $child_modules_titles;
}
/**
* Get advanced fields.
*
* @param string $post_type Post type.
* @param string $mode Whether modules are parent, child or all.
* @param string $module_type Module slug.
*
* @return array|mixed
*/
public static function get_advanced_fields( $post_type = '', $mode = 'all', $module_type = 'all' ) {
$parent_modules = self::get_parent_modules( $post_type );
$child_modules = self::get_child_modules( $post_type );
switch ( $mode ) {
case 'parent':
$_modules = $parent_modules;
break;
case 'child':
$_modules = $child_modules;
break;
default:
$_modules = array_merge( $parent_modules, $child_modules );
break;
}
$module_fields = array();
foreach ( $_modules as $_module_slug => $_module ) {
// filter modules by slug if needed.
if ( 'all' !== $module_type && $module_type !== $_module_slug ) {
continue;
}
foreach ( $_module->fields_unprocessed as $field_key => $field ) {
$is_option_template = self::$option_template->is_option_template_field( $field_key );
// Do not process field template.
if ( ! $is_option_template && ( ! isset( $field['tab_slug'] ) || 'advanced' !== $field['tab_slug'] ) ) {
continue;
}
// Skip if current option template isn't eligible for `advanced` tab.
if ( $is_option_template && ! self::$option_template->is_template_inside_tab( 'advanced', $field ) ) {
continue;
}
if ( isset( $field['default'] ) ) {
$module_fields[ $_module_slug ]['advanced_defaults'][ $field_key ] = $field['default'];
}
$module_fields[ $_module_slug ][ $field_key ] = $field;
}
if ( ! empty( $_module->advanced_fields ) ) {
$module_fields[ $_module_slug ]['advanced_common'] = $_module->advanced_fields;
if ( isset( $_module->advanced_fields['border']['border_styles'] ) ) {
$module_fields[ $_module_slug ]['border_styles'] = array_merge( $module_fields[ $_module_slug ]['border_styles'], $_module->advanced_fields['border']['border_styles'] );
}
if ( isset( $_module->advanced_fields['border']['border_radii'] ) ) {
$module_fileds[ $_module_slug ]['border_radii'] = array_merge( $module_fields[ $_module_slug ]['border_radii'], $_module->advanced_fields['border']['border_radii'] );
}
}
// Some module types must be separated for the Global Presets.
// For example we keep all section types as `et_pb_section` however they need different Global Presets.
$additional_slugs = self::$global_presets_manager->get_module_additional_slugs( $_module_slug );
foreach ( $additional_slugs as $alias ) {
$module_fields[ $alias ] = $module_fields[ $_module_slug ];
}
}
if ( 'all' !== $module_type ) {
return $module_fields[ $module_type ];
}
return $module_fields;
}
/**
* Get custom css fields.
*
* @param string $post_type Post type.
* @param string $mode Whether modules are parent, child or all.
* @param string $module_type Module slug.
*
* @return array|mixed
*/
public static function get_custom_css_fields( $post_type = '', $mode = 'all', $module_type = 'all' ) {
$parent_modules = self::get_parent_modules( $post_type );
$child_modules = self::get_child_modules( $post_type );
switch ( $mode ) {
case 'parent':
$_modules = $parent_modules;
break;
case 'child':
$_modules = $child_modules;
break;
default:
$_modules = array_merge( $parent_modules, $child_modules );
break;
}
$module_fields = array();
$custom_css_unwanted_types = array( 'custom_css', 'column_settings_css', 'column_settings_css_fields', 'column_settings_custom_css' );
foreach ( $_modules as $_module_slug => $_module ) {
// filter modules by slug if needed.
if ( 'all' !== $module_type && $module_type !== $_module_slug ) {
continue;
}
$module_fields[ $_module_slug ] = $_module->custom_css_fields;
foreach ( $module_fields[ $_module_slug ] as &$item ) {
$item['hover'] = self::$_->array_get( $item, 'hover', 'tabs' );
$item['mobile_options'] = self::$_->array_get( $item, 'mobile_options', true );
$item['sticky'] = self::$_->array_get( $item, 'sticky', true );
}
// Automatically added module ID and module class fields to setting modal's CSS tab.
if ( ! empty( $_module->fields_unprocessed ) ) {
foreach ( $_module->fields_unprocessed as $field_unprocessed_key => $field_unprocessed ) {
$has_tab_slug = isset( $field_unprocessed['tab_slug'] );
$is_css_field = $has_tab_slug && 'custom_css' === $field_unprocessed['tab_slug'];
$has_type = isset( $field_unprocessed['type'] );
$is_unwanted_css_field = $has_type && in_array( $field_unprocessed['type'], $custom_css_unwanted_types, true );
$is_template_inside_css_tab = is_string( $field_unprocessed ) && self::$option_template->is_template_inside_tab( 'custom_css', $field_unprocessed );
// Option template's template that might be rendered in custom_css tab.
if ( ( $is_css_field && ! $is_unwanted_css_field ) || $is_template_inside_css_tab ) {
$module_fields[ $_module_slug ][ $field_unprocessed_key ] = $field_unprocessed;
}
}
}
// Some module types must be separated for the Global Presets.
// For example we keep all section types as `et_pb_section` however they need different Global Presets.
$additional_slugs = self::$global_presets_manager->get_module_additional_slugs( $_module_slug );
foreach ( $additional_slugs as $alias ) {
$module_fields[ $alias ] = $module_fields[ $_module_slug ];
}
}
if ( 'all' !== $module_type ) {
return $module_fields[ $module_type ];
}
return $module_fields;
}
/**
* Get modules i10n.
*
* @param string $post_type Post type.
* @param string $mode Whether it is parent, child or all module.
* @param string $module_type Module slug.
*
* @return array|mixed
*/
public static function get_modules_i10n( $post_type = '', $mode = 'all', $module_type = 'all' ) {
$parent_modules = self::get_parent_modules( $post_type );
$child_modules = self::get_child_modules( $post_type );
switch ( $mode ) {
case 'parent':
$_modules = $parent_modules;
break;
case 'child':
$_modules = $child_modules;
break;
default:
$_modules = array_merge( $parent_modules, $child_modules );
break;
}
$fields = array();
foreach ( $_modules as $_module_slug => $_module ) {
// filter modules by slug if needed.
if ( 'all' !== $module_type && $module_type !== $_module_slug ) {
continue;
}
$fields[ $_module_slug ] = array(
'addNew' => $_module->add_new_child_text(),
);
}
if ( 'all' !== $module_type ) {
return $fields[ $module_type ];
}
return $fields;
}
/**
* Get CSS fields transition for module.
*
* @param string $post_type Post type.
* @param string $mode Whether it is parent, child or all module.
* @param string $module_type Module slug.
*
* @return array
*/
public static function get_modules_transitions( $post_type = '', $mode = 'all', $module_type = 'all' ) {
/**
* List of `ET_Builder_Element` instances.
*
* @var ET_Builder_Element[] $_modules
*/
$parent_modules = self::get_parent_modules( $post_type );
$child_modules = self::get_child_modules( $post_type );
$fields = array();
switch ( $mode ) {
case 'parent':
$_modules = $parent_modules;
break;
case 'child':
$_modules = $child_modules;
break;
default:
$_modules = array_merge( $parent_modules, $child_modules );
break;
}
foreach ( $_modules as $_module_slug => $_module ) {
// filter modules by slug if needed.
if ( 'all' !== $module_type && $module_type !== $_module_slug ) {
continue;
}
$fields[ $_module_slug ] = $_module->get_transition_fields_css_props();
}
return $fields;
}
/**
* Get module items configs.
*
* @param string $post_type Current post type.
*
* @return array
*/
public static function get_module_items_configs( $post_type ) {
$modules = self::get_parent_and_child_modules( $post_type );
$configs = array();
foreach ( $modules as $slug => $module ) {
if ( isset( $module->module_items_config ) ) {
$configs[ $slug ] = $module->module_items_config;
}
}
return $configs;
}
/**
* Get combined array of parent and child modules fields.
*
* @param string $post_type Post type.
* @param string $module Parent module slug.
*
* @return array|bool
*/
public static function get_module_fields( $post_type, $module ) {
$_modules = self::get_parent_and_child_modules( $post_type );
if ( ! empty( $_modules[ $module ] ) ) {
return $_modules[ $module ]->fields_unprocessed;
}
return false;
}
/**
* Get all fields of parent module.
*
* @param string $post_type Post type.
* @param string $module Module slug.
*
* @return bool
*/
public static function get_parent_module_fields( $post_type, $module ) {
if ( ! empty( self::$parent_modules[ $post_type ][ $module ] ) ) {
return self::$parent_modules[ $post_type ][ $module ]->get_complete_fields();
}
return false;
}
/**
* Get all child module fields.
*
* @param string $post_type Post type.
* @param string $module Module slug.
*
* @return bool
*/
public static function get_child_module_fields( $post_type, $module ) {
if ( ! empty( self::$child_modules[ $post_type ][ $module ] ) ) {
return self::$child_modules[ $post_type ][ $module ]->get_complete_fields();
}
return false;
}
/**
* Get parent module field.
*
* @param string $post_type Post type.
* @param string $module Module slug.
* @param string $field Field slug.
*
* @return bool|mixed
*/
public static function get_parent_module_field( $post_type, $module, $field ) {
$fields = self::get_parent_module_fields( $post_type, $module );
if ( ! empty( $fields[ $field ] ) ) {
return $fields[ $field ];
}
return false;
}
/**
* Return font icon fields of all modules.
*
* @param string $post_type Current post type.
*
* @return array
*/
public static function get_font_icon_fields( $post_type = '' ) {
$_modules = self::get_parent_and_child_modules( $post_type );
$module_fields = array();
foreach ( $_modules as $module_name => $module ) {
foreach ( $module->fields_unprocessed as $module_field_name => $module_field ) {
if ( isset( $module_field['type'] ) && 'select_icon' === $module_field['type'] ) {
$module_fields[ $module_name ][ $module_field_name ] = true;
}
}
}
return $module_fields;
}
/**
* Retrieves credits of custom modules for VB
*
* @param string $post_type Current post type.
*
* @return array of credits info by module slug
*/
public static function get_custom_modules_credits( $post_type = '' ) {
$result = array();
$modules = self::get_parent_and_child_modules( $post_type );
/**
* Loop over the all modules to gather module credits.
*
* @var $module_slug string
* @var $module ET_Builder_Module
*/
foreach ( $modules as $module_slug => $module ) {
// Include custom module credits for displaying them within VB.
if ( $module->_is_official_module ) {
continue;
} else {
if ( isset( $module->module_credits ) && is_array( $module->module_credits ) ) {
$result[ $module_slug ] = $module->module_credits;
}
}
}
return $result;
}
/**
* Return media query key value pairs.
*
* @param bool $for_js Whether media queries is for js ETBuilderBackend.et_builder_css_media_queries variable.
*
* @return array|mixed|void
*/
public static function get_media_quries( $for_js = false ) {
$media_queries = array(
'min_width_1405' => '@media only screen and ( min-width: 1405px )',
'1100_1405' => '@media only screen and ( min-width: 1100px ) and ( max-width: 1405px)',
'981_1405' => '@media only screen and ( min-width: 981px ) and ( max-width: 1405px)',
'981_1100' => '@media only screen and ( min-width: 981px ) and ( max-width: 1100px )',
'min_width_981' => '@media only screen and ( min-width: 981px )',
'max_width_980' => '@media only screen and ( max-width: 980px )',
'768_980' => '@media only screen and ( min-width: 768px ) and ( max-width: 980px )',
'min_width_768' => '@media only screen and ( min-width: 768px )',
'max_width_767' => '@media only screen and ( max-width: 767px )',
'max_width_479' => '@media only screen and ( max-width: 479px )',
);
$media_queries['mobile'] = $media_queries['max_width_767'];
$media_queries = apply_filters( 'et_builder_media_queries', $media_queries );
if ( 'for_js' === $for_js ) {
$processed_queries = array();
foreach ( $media_queries as $key => $value ) {
$processed_queries[] = array( $key, $value );
}
} else {
$processed_queries = $media_queries;
}
return $processed_queries;
}
/**
* Set media queries key value pairs.
*/
public static function set_media_queries() {
self::$media_queries = self::get_media_quries();
}
/**
* Return media query from the media query name.
* E.g For max_width_767 media query name, this function return "@media only screen and ( max-width: 767px )".
*
* @param string $name Media query name e.g max_width_767, max_width_980.
*
* @return bool|mixed
*/
public static function get_media_query( $name ) {
if ( ! isset( self::$media_queries[ $name ] ) ) {
return false;
}
return self::$media_queries[ $name ];
}
/**
* Get style key.
*
* @return int|string
*/
public static function get_style_key() {
if ( self::is_theme_builder_layout() || self::is_wp_editor_template() ) {
return self::get_layout_id();
}
// Use a generic key in all other cases.
// For example, injector plugins that repeat a layout in a loop
// need to group that CSS under the same key.
return 'post';
}
/**
* Return style array from {@see self::$internal_modules_styles} or {@see self::$styles}.
*
* @param bool $internal Whether to return style from internal modules styles.
* @param int $key Style key.
*
* @return array|mixed
*/
public static function get_style_array( $internal = false, $key = 0 ) {
$styles = $internal ? self::$internal_modules_styles : self::$styles;
if ( 0 === $key ) {
$key = self::get_style_key();
}
return isset( $styles[ $key ] ) ? $styles[ $key ] : array();
}
/**
* Intended to be used for unit testing
*
* @intendedForTesting
*/
public static function reset_styles() {
self::$internal_modules_styles = array();
self::$styles = array();
self::$media_queries = array();
}
/**
* Get styles of the current page.
*
* @see set_advanced_styles()
*
* @param bool $internal Whether or not module's internal style.
* @param int $key Style key.
*
* @return string
*/
public static function get_style( $internal = false, $key = 0, $critical = false ) {
// use appropriate array depending on which styles we need.
$styles_array = self::get_style_array( $internal, $key );
if ( empty( $styles_array ) ) {
return '';
}
global $et_user_fonts_queue;
$output = '';
if ( ! empty( $et_user_fonts_queue ) ) {
$output .= et_builder_enqueue_user_fonts( $et_user_fonts_queue );
}
$styles_by_media_queries = $styles_array;
$styles_count = (int) count( $styles_by_media_queries );
$media_queries_order = array_merge( array( 'general' ), array_values( self::$media_queries ) );
// make sure styles in the array ordered by media query correctly from bigger to smaller screensize.
$styles_by_media_queries_sorted = array_merge( array_flip( $media_queries_order ), $styles_by_media_queries );
foreach ( $styles_by_media_queries_sorted as $media_query => $styles ) {
// skip wrong values which were added during the array sorting.
if ( ! is_array( $styles ) ) {
continue;
}
$media_query_output = '';
$wrap_into_media_query = 'general' !== $media_query;
// sort styles by priority.
et_()->uasort( $styles, array( 'ET_Builder_Element', 'compare_by_priority' ) );
// merge styles with identical declarations.
$merged_declarations = [];
foreach ( $styles as $selector => $settings ) {
if ( false === $critical && isset( $settings['critical'] ) ) {
continue;
} elseif ( true === $critical && empty( $settings['critical'] ) ) {
continue;
}
$this_declaration = md5( $settings['declaration'] );
// we want to skip combining anything with psuedo selectors or keyframes.
if ( false !== strpos( $selector, ':-' ) || false !== strpos( $selector, '@keyframes' ) ) {
// set unique key so that it cant be matched.
$unique_key = $this_declaration . '-' . uniqid();
$merged_declarations[ $unique_key ] = [
'declaration' => $settings['declaration'],
'selector' => $selector,
];
if ( ! empty( $settings['priority'] ) ) {
$merged_declarations[ $unique_key ]['priority'] = $settings['priority'];
}
continue;
}
if ( empty( $merged_declarations[ $this_declaration ] ) ) {
$merged_declarations[ $this_declaration ] = [
'selector' => '',
'priority' => '',
];
}
$new_selector = ! empty( $merged_declarations[ $this_declaration ]['selector'] )
? $merged_declarations[ $this_declaration ]['selector'] . ', ' . $selector
: $selector;
$merged_declarations[ $this_declaration ] = [
'declaration' => $settings['declaration'],
'selector' => $new_selector,
];
if ( ! empty( $settings['priority'] ) ) {
$merged_declarations[ $this_declaration ]['priority'] = $settings['priority'];
}
}
// get each rule in a media query.
foreach ( $merged_declarations as $settings ) {
$media_query_output .= sprintf(
'%3$s%4$s%1$s { %2$s }',
$settings['selector'],
$settings['declaration'],
"\n",
( $wrap_into_media_query ? "\t" : '' )
);
}
// All css rules that don't use media queries are assigned to the "general" key.
// Wrap all non-general settings into media query.
if ( $wrap_into_media_query && '' !== $media_query_output ) {
$media_query_output = sprintf(
'%3$s%3$s%1$s {%2$s%3$s}',
$media_query,
$media_query_output,
"\n"
);
}
$output .= $media_query_output;
}
return $output;
}
/**
* Generate video background markup for columns.
*
* @param array $args Background values.
* @param array $conditional_tags Conditional tags.
* @param array $current_page Current page info.
*
* @return bool|mixed
*/
public static function get_column_video_background( $args = array(), $conditional_tags = array(), $current_page = array() ) {
if ( empty( $args ) ) {
return false;
}
$formatted_args = array();
foreach ( $args as $key => $value ) {
$key_length = strlen( $key );
$formatted_args[ substr( $key, 0, ( $key_length - 2 ) ) ] = $value;
}
return self::get_video_background( $formatted_args, $conditional_tags, $current_page );
}
/**
* Generate video background markup.
*
* @since 3.23 Add support for responsive settings.
*
* @param array $args Background values.
* @param array $conditional_tags Conditional tags.
* @param array $current_page Current page info.
* @return mixed Mixed background content generated as video markup.
*/
public static function get_video_background( $args = array(), $conditional_tags = array(), $current_page = array() ) {
$base_name = isset( $args['computed_variables'] ) && isset( $args['computed_variables']['base_name'] ) ? $args['computed_variables']['base_name'] : 'background';
$device = isset( $args['computed_variables'] ) && isset( $args['computed_variables']['device'] ) ? $args['computed_variables']['device'] : 'desktop';
$suffix = ! empty( $device ) && 'desktop' !== $device ? "_{$device}" : '';
$defaults = array(
"{$base_name}_video_mp4{$suffix}" => '',
"{$base_name}_video_webm{$suffix}" => '',
"{$base_name}_video_width{$suffix}" => '',
"{$base_name}_video_height{$suffix}" => '',
);
$args = wp_parse_args( $args, $defaults );
if ( '' === $args[ "{$base_name}_video_mp4{$suffix}" ] && '' === $args[ "{$base_name}_video_webm{$suffix}" ] ) {
return false;
}
return do_shortcode(
sprintf(
'
',
( '' !== $args[ "{$base_name}_video_mp4{$suffix}" ] ? sprintf( '
"}}
// This is a rough solution implemented due to time constraints.
$json = preg_replace(
'~
("(?:before|after)":") # $1 = Anchor to the before/after settings.
(?: # Match cases where the value starts with the offending tag.
<\/?p> # The root of all evil.
[\r\n]+ # Whitespace follows the tag.
)*
(?: # Match cases where the value ends with the offending tag.
([^"]*) # $2 = The preceeding value.
[\r\n]+ # Whitespace preceedes the tag.
<\/?p> # The root of all evil.
)*
~xi',
'$1$2',
$json
);
// Remove line-breaks which break the json strings.
$json = preg_replace( '/\r|\n/', '', $json );
$json_value = et_builder_parse_dynamic_content_json( $json );
if ( null === $json_value ) {
return $value;
}
return $json_value->serialize();
}
/**
* Escape an attribute's value.
*
* @since 3.17.2
*
* @param string $attribute Attribute name.
* @param string $html 'limited', 'full', 'none'.
* @param string $predefined_value Predifined value need to escape.
*
* @return string
*/
protected function _esc_attr( $attribute, $html = 'none', $predefined_value = null ) {
$html = in_array( $html, array( 'limited', 'full' ), true ) ? $html : 'none';
$raw = isset( $this->attrs_unprocessed[ $attribute ] ) ? $this->attrs_unprocessed[ $attribute ] : '';
$formatted = isset( $this->props[ $attribute ] ) ? $this->props[ $attribute ] : '';
$dynamic_attributes = $this->_get_enabled_dynamic_attributes( $this->props );
// More often than not content is not an attribute so we need to handle that special case.
if ( 'content' === $attribute && ! isset( $this->attrs_unprocessed[ $attribute ] ) ) {
$raw = $this->content_unprocessed;
$formatted = $this->content;
}
if ( ! is_null( $predefined_value ) ) {
$formatted = $predefined_value;
}
if ( ! $this->_is_dynamic_value( $attribute, $raw, $dynamic_attributes ) ) {
if ( 'full' === $html ) {
return $formatted;
}
return esc_html( $formatted );
}
if ( 'limited' === $html ) {
return wp_kses(
$formatted,
array(
'strong' => array(
'id' => array(),
'class' => array(),
'style' => array(),
),
'em' => array(
'id' => array(),
'class' => array(),
'style' => array(),
),
'i' => array(
'id' => array(),
'class' => array(),
'style' => array(),
),
)
);
}
// Dynamic content values are escaped when they are resolved so we do not want to
// double-escape them when using them in the frontend, for example.
return et_core_esc_previously( $formatted );
}
/**
* Get the current TB layout ID if we are rendering one or the current post ID instead.
*
* @since 4.0
* @since 4.14.8 Get WP Template ID if we are rendering Divi Builder block in template.
*
* @return integer
*/
public static function get_layout_id() {
// TB Layout ID.
$layout_id = self::get_theme_builder_layout_id();
if ( $layout_id ) {
return $layout_id;
}
// WP Template ID.
$template_id = self::get_wp_editor_template_id();
if ( $template_id ) {
return $template_id;
}
// Post ID by default.
return self::get_current_post_id_reverse();
}
/**
* Get the current theme builder layout.
* Returns 'default' if no layout has been started.
*
* @since 4.0
*
* @return string
*/
public static function get_theme_builder_layout_type() {
$count = count( self::$theme_builder_layout );
if ( $count > 0 ) {
return self::$theme_builder_layout[ $count - 1 ]['type'];
}
return 'default';
}
/**
* Check if a module is rendered as normal post content or theme builder layout.
*
* @since 4.0
*
* @return bool
*/
public static function is_theme_builder_layout() {
return 'default' !== self::get_theme_builder_layout_type();
}
/**
* Get the current theme builder layout id.
* Returns 0 if no layout has been started.
*
* @since 4.0
*
* @return integer
*/
public static function get_theme_builder_layout_id() {
$count = count( self::$theme_builder_layout );
if ( $count > 0 ) {
return self::$theme_builder_layout[ $count - 1 ]['id'];
}
return 0;
}
/**
* Begin a theme builder layout.
*
* @since 4.0
*
* @param integer $layout_id Layout post id.
*
* @return void
*/
public static function begin_theme_builder_layout( $layout_id ) {
$type = get_post_type( $layout_id );
if ( ! et_theme_builder_is_layout_post_type( $type ) ) {
$type = 'default';
}
self::$theme_builder_layout[] = array(
'id' => (int) $layout_id,
'type' => $type,
);
}
/**
* End the current theme builder layout.
*
* @since 4.0
*
* @return void
*/
public static function end_theme_builder_layout() {
array_pop( self::$theme_builder_layout );
}
/**
* Get the order class suffix for the current theme builder layout, if any.
*
* @since 4.0
*
* @return string
*/
protected static function _get_theme_builder_order_class_suffix() {
$layout_type = self::get_theme_builder_layout_type();
$type_map = array(
ET_THEME_BUILDER_HEADER_LAYOUT_POST_TYPE => '_tb_header',
ET_THEME_BUILDER_BODY_LAYOUT_POST_TYPE => '_tb_body',
ET_THEME_BUILDER_FOOTER_LAYOUT_POST_TYPE => '_tb_footer',
);
if ( empty( $layout_type ) || ! isset( $type_map[ $layout_type ] ) ) {
return '';
}
return $type_map[ $layout_type ];
}
/**
* Begin Divi Builder block output on WP Editor template.
*
* As identifier od Divi Builder block render template location and the template ID.
* Introduced to handle Divi Layout block render on WP Template outside Post Content.
* WP Editor templates:
* - wp_template
* - wp_template_part
*
* @since 4.14.8
*
* @param array $template_id Template post ID.
*
* @return void
*/
public static function begin_wp_editor_template( $template_id ) {
$type = get_post_type( $template_id );
if ( ! et_builder_is_wp_editor_template_post_type( $type ) ) {
$type = 'default';
}
self::$wp_editor_template[] = array(
'id' => (int) $template_id,
'type' => $type,
);
}
/**
* End Divi Builder block output on WP Editor template.
*
* @since 4.14.8
*
* @return void
*/
public static function end_wp_editor_template() {
array_pop( self::$wp_editor_template );
}
/**
* Whether a module is rendered in WP Editor template or not.
*
* @since 4.14.8
*
* @return bool WP Editor template status.
*/
public static function is_wp_editor_template() {
return 'default' !== self::get_wp_editor_template_type();
}
/**
* Get the current WP Editor template id.
*
* Returns 0 if no template has been started.
*
* @since 4.14.8
*
* @return integer Template post ID (wp_id).
*/
public static function get_wp_editor_template_id() {
$count = count( self::$wp_editor_template );
$id = 0;
if ( $count > 0 ) {
$id = et_()->array_get( self::$wp_editor_template, array( $count - 1, 'id' ), 0 );
}
// Just want to be safe to not return any unexpected result.
return is_int( $id ) ? $id : 0;
}
/**
* Get the current WP Editor template type.
*
* Returns 'default' if no template has been started.
*
* @since 4.14.8
*
* @param boolean $is_id_needed Whether template ID is needed or not.
*
* @return string Template type.
*/
public static function get_wp_editor_template_type( $is_id_needed = false ) {
$count = count( self::$wp_editor_template );
$type = '';
if ( $count > 0 ) {
$type = et_()->array_get( self::$wp_editor_template, array( $count - 1, 'type' ) );
// Page may have more than one template parts. So, the wp_id is needed in certain
// situation as unique identifier.
if ( $is_id_needed && ET_WP_EDITOR_TEMPLATE_PART_POST_TYPE === $type ) {
$id = self::get_wp_editor_template_id();
$type .= "-{$id}";
}
}
// Just want to be safe to not return any unexpected result.
return ! empty( $type ) && is_string( $type ) ? $type : 'default';
}
/**
* Get the order class suffix for the current WP Editor template, if any.
*
* @since 4.14.8
*
* @return string Order class suffix.
*/
protected static function _get_wp_editor_order_class_suffix() {
$template_type = self::get_wp_editor_template_type();
$type_map = array(
ET_WP_EDITOR_TEMPLATE_POST_TYPE => '_wp_template',
ET_WP_EDITOR_TEMPLATE_PART_POST_TYPE => '_wp_template_part',
);
if ( ! isset( $type_map[ $template_type ] ) ) {
return '';
}
$suffix = $type_map[ $template_type ];
// Page may have more than one template parts. So, the wp_id is needed identifier.
if ( ET_WP_EDITOR_TEMPLATE_PART_POST_TYPE === $template_type ) {
$id = self::get_wp_editor_template_id();
$suffix .= "-{$id}";
}
return $suffix;
}
/**
* Convert field name into css property name.
*
* @param string $field Field name.
*
* @return string|string[]
*/
protected function field_to_css_prop( $field ) {
return str_replace( '_', '-', $field );
}
/**
* Initialize Modules Cache.
*
* @since 3.24
*/
public static function init_cache() {
$cache = self::get_cache_filename();
if ( $cache && et_()->WPFS()->is_readable( $cache ) ) {
// Load cache.
$result = @unserialize( et_()->WPFS()->get_contents( $cache ) );
if ( false !== $result ) {
if ( count( $result ) < 3 ) {
// Old cache format detected, delete everything.
et_fb_delete_builder_assets();
if ( ! file_exists( $cache ) ) {
// If cache has been successfully deleted, then init again.
self::init_cache();
}
return;
}
list ( self::$_cache, self::$_fields_unprocessed ) = $result;
// Define option template variable instead of using list to avoid error that might
// happen when option template file exists (theme is updated) and frontend is
// accessed while static module field data hasn't been updated.
$cached_option_template_data = et_()->array_get( $result, '2', array() );
$cached_option_template = et_()->array_get( $result, '3', array() );
$cached_option_template_tab_slug_maps = et_()->array_get( $result, '4', array() );
// init_cache() is called really early. $template property might not be available yet.
if ( null === self::$option_template ) {
self::$option_template = et_pb_option_template();
}
// Set option template data from static cache if exist.
if ( is_array( $cached_option_template_data ) && ! empty( $cached_option_template_data ) ) {
self::$option_template->set_data( $cached_option_template_data );
}
// Set option template from static cache if exist.
if ( is_array( $cached_option_template ) && ! empty( $cached_option_template ) ) {
self::$option_template->set_templates( $cached_option_template );
}
// Set option template tab slug maps from static cache if exist.
if ( is_array( $cached_option_template_tab_slug_maps ) && ! empty( $cached_option_template_tab_slug_maps ) ) {
self::$option_template->set_tab_slug_map( $cached_option_template_tab_slug_maps );
}
// Box Shadow sets WP hooks internally so we gotta load it anyway -> #blame_george.
ET_Builder_Module_Fields_Factory::get( 'BoxShadow' );
} else {
// Cache couldn't be unserialized, delete the file so it will be regenerated.
@unlink( $cache );
}
} elseif ( $cache ) {
// Only save cache when a builder page is being rendered, needed because some data
// (e.g. mail provider defaults) is only generated in this case, hence saving while rendering
// a FE page or during AJAX call would result in cache missing data.
self::$_cache = array();
add_filter( 'et_builder_modules_is_saving_cache', '__return_true' );
add_filter( 'et_builder_should_load_all_module_data', '__return_true' );
add_action( 'et_builder_ready', array( 'ET_Builder_Element', 'save_cache' ) );
}
}
/**
* Get Modules cache file name.
*
* @param mixed $post_type When set to `false`, autodetect.
*
* @since 3.24
*
* @return bool|mixed|string
*/
public static function get_cache_filename( $post_type = false ) {
global $post, $et_builder_post_type;
$ajax_use_cache = apply_filters( 'et_builder_ajax_use_cache', false );
if ( false === $post_type ) {
if ( is_a( $post, 'WP_POST' ) ) {
$post_type = $post->post_type;
} elseif ( $ajax_use_cache ) {
// phpcs:ignore WordPress.Security.NonceVerification -- Nonce verified in the ajax request.
$post_type = et_()->array_get( $_POST, 'et_post_type', 'page' );
} elseif ( is_admin() && ! wp_doing_ajax() ) {
$post_type = 'page';
$et_builder_post_type = $post_type;
}
if ( false === $post_type ) {
return false;
}
}
$post_type = apply_filters( 'et_builder_cache_post_type', $post_type, 'modules' );
$post_type = trim( sanitize_file_name( $post_type ), '.' );
// Per language Cache due to fields data being localized.
// Use user custom locale only if admin or VB/BFB.
$lang = is_admin() || et_fb_is_enabled() ? get_user_locale() : get_locale();
$lang = trim( sanitize_file_name( $lang ), '.' );
$prefix = 'modules';
$cache = sprintf( '%s/%s', ET_Core_PageResource::get_cache_directory(), $lang );
$files = glob( sprintf( '%s/%s-%s-*.data', $cache, $prefix, $post_type ) );
$exists = is_array( $files ) && $files;
if ( $exists ) {
return $files[0];
} elseif ( $ajax_use_cache ) {
// Allowlisted AJAX requests aren't allowed to generate cache, only to use it.
return false;
}
wp_mkdir_p( $cache );
// Create uniq filename.
$uniq = str_replace( '.', '', (string) microtime( true ) );
$file = sprintf( '%s/%s-%s-%s.data', $cache, $prefix, $post_type, $uniq );
return wp_is_writable( dirname( $file ) ) ? $file : false;
}
/**
* Get Module cache file name's id.
*
* @since 3.28
*
* @param mixed $post_type When set to `false`, autodetect.
*
* @return bool|string
*/
public static function get_cache_filename_id( $post_type = false ) {
$filename = self::get_cache_filename( $post_type );
if ( ! is_string( $filename ) ) {
return false;
}
preg_match( '/(?<=-)[0-9]*(?=.data)/', $filename, $matches );
return isset( $matches[0] ) ? $matches[0] : false;
}
/**
* Save the builder module caache.
*/
public static function save_cache() {
remove_filter( 'et_builder_modules_is_saving_cache', '__return_true' );
$cache = self::get_cache_filename();
if ( $cache ) {
et_()->WPFS()->put_contents(
$cache,
serialize(
array(
self::$_cache,
self::$_fields_unprocessed,
self::$option_template->all(),
self::$option_template->templates(),
self::$option_template->get_tab_slug_map(),
'3.0',
)
)
);
}
}
/**
* Render image element HTML
*
* @since 3.27.1
*
* @param string $image_props Image data props key or actual image URL.
* @param array $image_attrs_raw List of extra image attributes.
* @param bool $echo Whether to print the image output or return it.
* @param bool $disable_responsive Whether to enable the responsive image or not.
*
* @return string The images's HTML output. Empty string on failure.
*/
protected function render_image( $image_props, $image_attrs_raw = array(), $echo = true, $disable_responsive = false ) {
// Bail early when the $image_props arg passed is empty.
if ( ! $image_props ) {
return '';
}
$img_src = $image_props && is_string( $image_props ) ? self::$_->array_get( $this->props, $image_props, $image_props ) : $image_props;
if ( ! $img_src ) {
return '';
}
if ( ! count( $image_attrs_raw ) ) {
$html = sprintf(
'',
esc_url( $img_src )
);
return et_image_add_srcset_and_sizes( $html, $echo );
}
$image_attrs = array();
$is_disable_responsive = $disable_responsive || ! et_is_responsive_images_enabled();
foreach ( $image_attrs_raw as $name => $value ) {
// Skip src attributes key.
if ( 'src' === $name ) {
continue;
}
// Skip srcset & sizes attributes when setting is off.
if ( $is_disable_responsive && in_array( $name, array( 'srcset', 'sizes' ), true ) ) {
continue;
}
// Skip if attributes value is empty.
if ( ! strlen( $value ) ) {
continue;
}
// Format as JSON if the value is array or object.
if ( is_array( $value ) || is_object( $value ) ) {
$value = wp_json_encode( $value );
}
// Trim extra space from attributes value.
$value = trim( $value );
// Standalone attributes that act as Booleans (Numerical indexed array keys such as required, disabled, multiple).
if ( is_numeric( $name ) ) {
$value = et_core_esc_attr( $value, $value );
if ( ! is_wp_error( $value ) ) {
$image_attrs[ $value ] = et_core_esc_previously( $value );
}
} else {
$value = et_core_esc_attr( $name, $value );
if ( ! is_wp_error( $value ) ) {
$image_attrs[ $name ] = esc_attr( $name ) . '="' . et_core_esc_previously( $value ) . '"';
}
}
}
$html = sprintf(
'
',
esc_url( $img_src ),
et_core_esc_previously( implode( ' ', $image_attrs ) )
);
if ( ! $is_disable_responsive && ! isset( $image_attrs['srcset'] ) && ! isset( $image_attrs['sizes'] ) ) {
$html = et_image_add_srcset_and_sizes( $html, false );
}
if ( ! $echo ) {
return $html;
}
echo et_core_intentionally_unescaped( $html, 'html' );
}
/**
* Get advanced field settings exposed for layout block preview
*
* @since 4.3.2
*
* @return array
*/
public static function get_layout_block_assistive_settings() {
return self::$layout_block_assistive_settings;
}
/**
* Get whether the provided element content contains at least one of the
* specified modules based on their slugs.
*
* @since 4.3.3
*
* @param string $content Element content.
* @param string[] $module_slugs Module slug to search.
*
* @return bool
*/
protected static function contains( $content, $module_slugs ) {
foreach ( $module_slugs as $slug ) {
if ( false !== strpos( $content, '[' . $slug ) ) {
return true;
}
}
return false;
}
/**
* Public access provider for self::contains().
*
* @since 4.17.4
*
* @param string $content Element content.
* @param string[] $module_slugs Module slug to search.
*
* @return bool
*/
public static function module_contains( $content, $module_slugs ) {
return self::contains( $content, $module_slugs );
}
/**
* Generate background field setting properties by template
*
* NOTE: Unless the `priority` property is used, the order that settings are listed is the order
* that they'll appear in the settings modal.
*
* @param string $field_template Field template slug.
* @param array $overrides Field properties to override.
* @param array $unsets Field properties to unset.
*
* @return array
*
* @since 4.8.0
*
*/
public static function background_field_template( $field_template, $overrides = array(), $unsets = array() ) {
static $cache = null;
if ( is_null( $cache ) ) {
$cache = array();
$tabs = array(
// Tab: color, priority start with 100.
'color' => array(
'priority' => 100,
'data' => array(
'enable_color' => array(
'type' => 'skip',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'color' => array(
'type' => 'color-alpha',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
'tab_filler' => true,
),
'use_color' => array(
'type' => 'yes_no_button',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
),
),
// Tab: gradient, priority start with 200.
'gradient' => array(
'priority' => 200,
'data' => array(
'use_color_gradient' => array(
'priority' => 201,
'type' => 'yes_no_button',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
'tab_filler' => true,
),
'color_gradient_repeat' => array(
'priority' => 205,
'type' => 'yes_no_button',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'color_gradient_type' => array(
'priority' => 203,
'type' => 'select',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'color_gradient_direction' => array(
'priority' => 204,
'type' => 'range',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
'show_if' => array(
'color_gradient_type' => array(
'conic',
'linear',
),
),
),
'color_gradient_direction_radial' => array(
'priority' => 204,
'type' => 'select',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
'show_if' => array(
'color_gradient_type' => array(
'radial',
'circular',
'elliptical',
),
),
),
'color_gradient_stops' => array(
'priority' => 202,
'type' => 'gradient-stops',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'color_gradient_unit' => array(
'priority' => 206,
'type' => 'select',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'color_gradient_overlays_image' => array(
'priority' => 299,
'type' => 'yes_no_button',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
// Deprecated.
'color_gradient_start' => array(
'type' => 'skip',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
// Deprecated.
'color_gradient_start_position' => array(
'type' => 'skip',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
'option_category' => 'configuration',
),
// Deprecated.
'color_gradient_end' => array(
'type' => 'skip',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
// Deprecated.
'color_gradient_end_position' => array(
'type' => 'skip',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
),
),
// Tab: image, priority start with 300.
'image' => array(
'priority' => 300,
'data' => array(
'enable_image' => array(
'type' => 'skip',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'image' => array(
'type' => 'upload',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
'tab_filler' => true,
),
'parallax' => array(
'type' => 'yes_no_button',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'parallax_method' => array(
'type' => 'select',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'size' => array(
'type' => 'select',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'image_width' => array(
'type' => 'range',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'image_height' => array(
'type' => 'range',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'position' => array(
'type' => 'select',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'horizontal_offset' => array(
'type' => 'range',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'vertical_offset' => array(
'type' => 'range',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'repeat' => array(
'type' => 'select',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'blend' => array(
'type' => 'select',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
),
),
// Tab: video, priority start with 400.
'video' => array(
'priority' => 400,
'data' => array(
'enable_video_mp4' => array(
'type' => 'skip',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'video_mp4' => array(
'type' => 'upload',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
'tab_filler' => true,
),
'enable_video_webm' => array(
'type' => 'skip',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'video_webm' => array(
'type' => 'upload',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
'tab_filler' => true,
),
'video_width' => array(
'type' => 'text',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'video_height' => array(
'type' => 'text',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'allow_player_pause' => array(
'type' => 'yes_no_button',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'video_pause_outside_viewport' => array(
'type' => 'yes_no_button',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
'video_computed' => array(
'type' => 'computed',
'mobile_options' => false,
'hover' => false,
'sticky' => false,
),
),
),
// Tab: pattern, priority start with 500.
'pattern' => array(
'priority' => 500,
'data' => et_ph_pattern_field_templates(),
),
// Tab: mask, priority start with 500.
'mask' => array(
'priority' => 600,
'data' => et_ph_mask_field_templates(),
),
);
foreach ( $tabs as $background_tab_slug => $tab ) {
$priority = $tab['priority'];
foreach ( $tab['data'] as $template_slug => $template_data ) {
$template_priority = isset( $template_data['priority'] ) && is_numeric( $template_data['priority'] ) ? $template_data['priority'] : $priority;
if ( $template_priority < $tab['priority'] ) {
$template_priority += $tab['priority'];
}
$cache[ $template_slug ] = array_merge(
$template_data,
array(
'field_template' => $template_slug,
'background_tab' => $background_tab_slug,
'priority' => $template_priority,
'tab_slug' => 'general',
'toggle_slug' => 'background',
)
);
$priority += 10;
}
}
}
$template = isset( $cache[ $field_template ] ) ? $cache[ $field_template ] : array();
if ( $overrides && is_array( $overrides ) ) {
$template = array_merge( $template, $overrides );
}
if ( $unsets && is_array( $unsets ) ) {
foreach ( $unsets as $unset ) {
unset( $template[ $unset ] );
}
}
return array_merge(
$template,
array(
'field_template' => $field_template,
)
);
}
/**
* Generate markup for background pattern.
*
* @since 4.15.0
*
* @param array $args Props.
* @param string $base_name Background base name.
*
* @return string Background pattern markup.
*/
public function background_pattern( $args = array(), $base_name = 'background' ) {
$props = ! empty( $args ) ? (array) $args : $this->props;
$modes = array( 'desktop', 'hover', 'sticky', 'tablet', 'phone' );
$is_active = false;
foreach ( $modes as $mode ) {
// Checks whether pattern style is enabled and has value.
$style_name = et_pb_responsive_options()->get_inheritance_background_value(
$props,
"{$base_name}_pattern_style",
$mode,
'background',
$this->fields_unprocessed
);
if ( ! empty( $style_name ) ) {
// We need to render pattern element.
$is_active = true;
break;
}
}
$output = '';
if ( $is_active ) {
$class_name = array(
'et_pb_background_pattern',
);
$output = sprintf(
'',
implode( ' ', array_map( 'esc_attr', $class_name ) )
);
}
return $output;
}
/**
* Generate markup for background mask.
*
* @since 4.15.0
*
* @param array $args Props.
* @param string $base_name Background base name.
*
* @return string Background mask markup.
*/
public function background_mask( $args = array(), $base_name = 'background' ) {
$props = ! empty( $args ) ? (array) $args : $this->props;
$modes = array( 'desktop', 'hover', 'sticky', 'tablet', 'phone' );
$is_active = false;
foreach ( $modes as $mode ) {
// Checks whether mask style is enabled and has value.
$style_name = et_pb_responsive_options()->get_inheritance_background_value(
$props,
"{$base_name}_mask_style",
$mode,
'background',
$this->fields_unprocessed
);
if ( ! empty( $style_name ) ) {
// We need to render mask element.
$is_active = true;
break;
}
}
$output = '';
if ( $is_active ) {
$class_name = array(
'et_pb_background_mask',
);
$output = sprintf(
'',
implode( ' ', array_map( 'esc_attr', $class_name ) )
);
}
return $output;
}
/**
* Get components before & after module.
*
* This method is introduced to handle additional components added on WooCommerce
* product summary that should be moved to any suitable modules on builder preview.
*
* @since 4.14.5
*
* @param string $module_slug Module slug.
* @param array $module_data Module data passed.
*
* @return array Components before & after module.
*/
public static function get_component_before_after_module( $module_slug, $module_data ) {
// Default processed components for the return request. Need to use `__` to be set
// as the attribute name.
$processed_components = array(
'has_components' => false,
'__before_component' => '',
'__after_component' => '',
);
/**
* Filters module's before & after components for current builder page.
*
* @since 4.14.5
*
* @param array $processed_components Default of module's before & after components.
* @param string $module_slug Module slug.
* @param array $module_data Module data passed from the request.
*/
$components = apply_filters( "{$module_slug}_fb_before_after_components", $processed_components, $module_slug, $module_data );
// Skip if there is no before & after components.
$has_components = et_()->array_get( $components, 'has_components' );
if ( true !== $has_components ) {
return $processed_components;
}
$processed_components = array(
'has_components' => true,
'__before_component' => et_()->array_get( $components, '__before_component' ),
'__after_component' => et_()->array_get( $components, '__after_component' ),
);
return $processed_components;
}
/**
* ================================================================================================================
* -------------------------->>> Class-level (static) deprecations begin here! <<<---------------------------------
* ================================================================================================================
*/
// phpcs:disable -- Deprecated functions.
/**
* @deprecated See {@see self::get_parent_slugs_regex()}
*/
public static function get_parent_shortcodes( $post_type ) {
$method = __METHOD__;
$replacement = __CLASS__ . '::get_parent_slugs_regex()';
et_error( "You're Doing It Wrong! {$method} is deprecated. Use {$replacement} instead." );
return self::get_parent_slugs_regex( $post_type );
}
/**
* @deprecated See {@see self::get_child_slugs_regex()}
*/
public static function get_child_shortcodes( $post_type ) {
$method = __METHOD__;
$replacement = __CLASS__ . '::get_child_slugs_regex()';
et_error( "You're Doing It Wrong! {$method} is deprecated. Use {$replacement} instead." );
return self::get_child_slugs_regex( $post_type );
}
/**
* Deprecated.
*
* @deprecated
*
* @param string $post_type
* @param string $mode
*
* @return array
*/
public static function get_defaults( $post_type = '', $mode = 'all' ) {
et_error( "You're Doing It Wrong! " . __METHOD__ . ' is deprecated and should not be used.' );
return array();
}
/**
* Deprecated.
*
* @deprecated
*
* @param string $post_type
* @param string $mode
*
* @return array
*/
public static function get_fields_defaults( $post_type = '', $mode = 'all' ) {
et_error( "You're Doing It Wrong! " . __METHOD__ . ' is deprecated and should not be used.' );
return array();
}
/**
* @deprecated
*/
public static function get_slugs_with_children( $post_type ) {
$parent_modules = self::get_parent_modules( $post_type );
$slugs = array();
foreach ( $parent_modules as $module ) {
if ( ! empty( $module->child_slug ) ) {
$slugs[] = sprintf( '"%1$s":"%2$s"', esc_js( $module->slug ), esc_js( $module->child_slug ) );
}
}
return '{' . implode( ',', $slugs ) . '}';
}
// phpcs:enable
/**
* ================================================================================================================
* ------------------------------->>> Non-static deprecations begin here! <<<--------------------------------------
* ================================================================================================================
*/
/**
* Determine if current request is VB Data Request by checking $_POST['action'] value
*
* @deprecated {@see et_builder_is_loading_vb_data()}
*
* @since 4.0.7 Deprecated.
*
* @return bool
*/
protected function is_loading_vb_data() {
return et_builder_is_loading_data();
}
/**
* Determine if current request is BB Data Request by checking $_POST['action'] value
*
* @deprecated {@see et_builder_is_loading_bb_data()}
*
* @since 4.0.7 Deprecated.
*
* @return bool
*/
protected function is_loading_bb_data() {
return et_builder_is_loading_data( 'bb' );
}
/* NOTE: Adding a new method? New methods should be placed BEFORE deprecated methods. */
}
do_action( 'et_pagebuilder_module_init' );
/**
* Base class for module.
*
* Class ET_Builder_Module
*/
class ET_Builder_Module extends ET_Builder_Element {
/**
* Whether element is structure element.
*
* @var bool
*/
public $is_structure_element = false;
}
/**
* Base class for structure elements.
*
* Class ET_Builder_Structure_Element
*/
class ET_Builder_Structure_Element extends ET_Builder_Element {
/**
* Whether element is structure element.
*
* @var bool
*/
public $is_structure_element = true;
/**
* BB :: Wrap setting option in parent div.
*
* @param string $option_output Setting options markup.
* @param array $field Setting field.
* @param string $name Setting field name e.g background_color.
*
* @return string|string[]
*/
public function wrap_settings_option( $option_output, $field, $name = '' ) {
// Option template convert array field into string id; return early to prevent error.
if ( is_string( $field ) ) {
return '';
}
$field_type = ! empty( $field['type'] ) ? $field['type'] : '';
switch ( $field_type ) {
case 'column_settings_background':
$output = $this->generate_columns_settings_background();
$field['hover'] = 'tabs';
break;
case 'column_settings_padding':
$output = $this->generate_columns_settings_padding();
break;
case 'column_settings_css_fields':
$output = $this->generate_columns_settings_css_fields();
break;
case 'column_settings_css':
$output = $this->generate_columns_settings_css();
break;
case 'column-structure':
// column structure option is not supported in BB.
return '';
break;
default:
$depends = false;
$new_depends = isset( $field['show_if'] ) || isset( $field['show_if_not'] );
if ( ! $new_depends && ( isset( $field['depends_show_if'] ) || isset( $field['depends_show_if_not'] ) ) ) {
$depends = true;
if ( isset( $field['depends_show_if_not'] ) ) {
$depends_show_if_not = is_array( $field['depends_show_if_not'] ) ? implode( ',', $field['depends_show_if_not'] ) : $field['depends_show_if_not'];
$depends_attr = sprintf( ' data-depends_show_if_not="%s"', esc_attr( $depends_show_if_not ) );
} else {
$depends_attr = sprintf( ' data-depends_show_if="%s"', esc_attr( $field['depends_show_if'] ) );
}
}
// Overriding background color's attribute, turning it into appropriate background attributes.
if ( isset( $field['type'] ) && isset( $field['name'] ) && in_array( $field['name'], array( 'background_color' ), true ) ) {
$field['type'] = 'background';
// Appending background class.
if ( isset( $field['option_class'] ) ) {
$field['option_class'] .= ' et-pb-option--background';
} else {
$field['option_class'] = 'et-pb-option--background';
}
// Removing depends default variable which hides background color for unified background field UI.
$depends = false;
if ( isset( $field['depends_show_if'] ) ) {
unset( $field['depends_show_if'] );
}
}
$output = sprintf(
'%6$s