includes( $field['taxonomy_name'], 'product' ) ) {
$renderer_method = 'et_builder_include_categories_shop_option';
} else {
$renderer_method = 'et_builder_include_categories_option';
}
break;
case 'select_sidebar':
$renderer_method = 'et_builder_get_widget_areas';
break;
case 'select_icon':
if ( isset( $field['renderer_options'] ) && isset( $field['renderer_options']['icons_list'] ) && 'icon_down' === $field['renderer_options']['icons_list'] ) {
$renderer_method = 'et_pb_get_font_down_icon_list';
} else {
$renderer_method = 'et_pb_get_font_icon_list';
}
$renderer_with_field = true;
break;
case 'upload_gallery':
$renderer_method = 'et_builder_get_gallery_settings';
break;
case 'center_map':
$renderer_method = 'et_builder_generate_center_map_setting';
break;
case 'border-radius':
$renderer_method = array(
'class' => 'ET_Builder_Module_Field_Template_Border_Radius',
);
break;
case 'composite':
if ( isset( $field['composite_type'] ) && 'default' === $field['composite_type'] ) {
$renderer_method = array(
'class' => 'ET_Builder_Module_Field_Template_Tabbed',
);
} elseif ( isset( $field['composite_type'] ) && 'tabbed' === $field['composite_type'] && 'border' === $field['option_category'] ) {
$renderer_method = array(
'class' => 'ET_Builder_Module_Field_Template_Border_Styles',
);
}
break;
}
}
if ( '' !== $renderer_method ) {
$renderer_data = array(
'renderer' => $renderer_method,
'renderer_options' => isset( $field['renderer_options'] ) ? $field['renderer_options'] : array(),
'renderer_with_field' => $renderer_with_field,
);
}
return apply_filters( 'et_bb_field_renderer_data', $renderer_data, $field );
}
/**
* Prepare module field (option) for use within BB microtemplates.
* The own field renderer can be used.
*
* @param array $field Module field.
*
* @param string $name Unused name param.
*
* @return mixed|string Html code of the field
*/
public function wrap_settings_option_field( $field, $name = '' ) {
$use_container_wrapper = isset( $field['use_container_wrapper'] ) && ! $field['use_container_wrapper'] ? false : true;
$field_renderer = $this->get_field_renderer( $field );
if ( ! empty( $field_renderer ) && is_array( $field_renderer['renderer'] ) && ! empty( $field_renderer['renderer']['class'] ) ) {
// cut off 'ET_Builder_Module_Field_Template_' part from renderer definition.
$class_name_without_prefix = strtolower( str_replace( 'ET_Builder_Module_Field_Template_', '', $field_renderer['renderer']['class'] ) );
// split class name string by underscore symbol.
$file_name_parts = explode( '_', $class_name_without_prefix );
if ( ! empty( $file_name_parts ) ) {
// the first symbol of class name must be uppercase.
$last_index = count( $file_name_parts ) - 1;
$file_name_parts[ $last_index ] = ucwords( $file_name_parts[ $last_index ] );
// load renderer class from 'module/field/template/' directory accordingly class name and class directory hierarchy.
require_once ET_BUILDER_DIR . 'module/field/template/' . implode( DIRECTORY_SEPARATOR, $file_name_parts ) . '.php';
$renderer = new $field_renderer['renderer']['class']();
// before calling the 'render' method make sure the instantiated class is child of 'ET_Builder_Module_Field_Template_Base'.
if ( is_subclass_of( $field_renderer['renderer']['class'], 'ET_Builder_Module_Field_Template_Base' ) ) {
// @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
$field_el = call_user_func( array( $renderer, 'render' ), $field, $this );
}
}
} elseif ( ! empty( $field_renderer ) ) {
$renderer_options = ! empty( $field_renderer['renderer_options'] ) ? $field_renderer['renderer_options'] : $field;
$default_value = isset( $field['default'] ) ? $field['default'] : '';
// @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
$field_el = is_callable( $field_renderer['renderer'] ) ? call_user_func( $field_renderer['renderer'], $renderer_options, $default_value ) : $field_renderer['renderer'];
if ( ! empty( $field_renderer['renderer_with_field'] ) && $field_renderer['renderer_with_field'] ) {
$field_el .= $this->render_field( $field, $name );
}
} else {
$field_el = $this->render_field( $field, $name );
}
$description = ! empty( $field['description'] ) ? sprintf( '%2$s
%1$s
', $field['description'], "\n\t\t\t\t\t" ) : '';
if ( '' === $description && ! $use_container_wrapper ) {
$output = $field_el;
} else {
$output = sprintf(
'%3$s
%1$s
%2$s
%4$s
',
$field_el,
$description,
"\n\n\t\t\t\t",
"\t",
( isset( $field['type'] ) && 'custom_css' === $field['type'] ? ' et-pb-custom-css-option' : '' ),
isset( $field['type'] ) ? esc_attr( $field['type'] ) : ''
);
}
$dynamic_content_notice = et_get_safe_localization(
sprintf(
__( 'This field contains a dynamic value which requires the Visual Builder.
Open Visual Builder', 'et_builder' ),
'et-pb-dynamic-content-fb-switch'
)
);
// Conditionally wrap fields depending on whether their values represent dynamic content or not.
$output = sprintf(
'<%% var isDynamic = typeof %1$s !== \'undefined\' && ET_PageBuilder.isDynamicContent(%1$s); %%>
<%% if (isDynamic) { %%>
%2$s
<%% } %%>
%3$s
<%% if (isDynamic) { %%>
<%% } %%>',
et_core_intentionally_unescaped( $this->get_field_variable_name( $field ), 'underscore_template' ),
et_core_intentionally_unescaped( $this->get_icon( 'lock' ) . $dynamic_content_notice, 'underscore_template' ),
et_core_intentionally_unescaped( $output, 'underscore_template' )
);
return $output;
}
/**
* Wrap setting option label.
*
* @param array $field Field settings.
*
* @return mixed|string
*/
public function wrap_settings_option_label( $field ) {
if ( ! empty( $field['label'] ) ) {
$label = $field['label'];
} else {
return '';
}
$field_name = $this->get_field_name( $field );
if ( isset( $field['type'] ) && 'font' === $field['type'] ) {
$field_name .= '_select';
}
$required = ! empty( $field['required'] ) ? '
*' : '';
$attributes = ! ( isset( $field['type'] ) && in_array( $field['type'], array( 'custom_margin', 'custom_padding' ), true ) )
? sprintf( ' for="%1$s"', esc_attr( $field_name ) )
: ' class="et_custom_margin_label"';
$label = sprintf(
'
',
et_core_esc_previously( $attributes ),
et_core_intentionally_unescaped( $label, 'html' ),
et_core_intentionally_unescaped( $required, 'fixed_string' ),
isset( $field['no_colon'] ) && true === $field['no_colon'] ? '' : ':'
);
return $label;
}
/**
* Get svg icon as string.
*
* @param string $icon_name icon name.
*
* @return string div-wrapped svg icon.
*/
public function get_icon( $icon_name ) {
$all_svg_icons = et_pb_get_svg_icons_list();
$icon = isset( $all_svg_icons[ $icon_name ] ) ? $all_svg_icons[ $icon_name ] : '';
if ( '' === $icon ) {
return '';
}
return '
';
}
/**
* Get structure of background UI tabs
*
* @param string $base_name Background base.
*
* @return array
*/
public function get_background_fields_structure( $base_name = 'background' ) {
$is_background_attr = 'background' === $base_name;
$use_background_color_gradient = $is_background_attr ? 'use_background_color_gradient' : "{$base_name}_use_color_gradient";
$prefix = $is_background_attr ? '' : "{$base_name}_";
$structure = array(
'color' => array(
"{$base_name}_color",
),
'gradient' => array(
$use_background_color_gradient,
"{$base_name}_color_gradient_repeat",
"{$base_name}_color_gradient_type",
"{$base_name}_color_gradient_direction",
"{$base_name}_color_gradient_direction_radial",
"{$base_name}_color_gradient_stops",
"{$base_name}_color_gradient_unit",
"{$base_name}_color_gradient_overlays_image",
// Deprecated.
"{$base_name}_color_gradient_start",
"{$base_name}_color_gradient_start_position",
"{$base_name}_color_gradient_end",
"{$base_name}_color_gradient_end_position",
),
'image' => array(
"{$base_name}_image",
"{$prefix}parallax",
"{$prefix}parallax_method",
"{$base_name}_size",
"{$base_name}_image_width",
"{$base_name}_image_height",
"{$base_name}_position",
"{$base_name}_horizontal_offset",
"{$base_name}_vertical_offset",
"{$base_name}_repeat",
"{$base_name}_blend",
),
'video' => array(
"{$base_name}_video_mp4",
"{$base_name}_video_webm",
"{$base_name}_video_width",
"{$base_name}_video_height",
"{$prefix}allow_player_pause",
"{$base_name}_video_pause_outside_viewport",
),
'pattern' => array(
"{$base_name}_pattern_style",
"{$base_name}_pattern_color",
"{$base_name}_pattern_transform",
"{$base_name}_pattern_size",
"{$base_name}_pattern_width",
"{$base_name}_pattern_height",
"{$base_name}_pattern_repeat_origin",
"{$base_name}_pattern_horizontal_offset",
"{$base_name}_pattern_vertical_offset",
"{$base_name}_pattern_repeat",
"{$base_name}_pattern_blend_mode",
),
'mask' => array(
"{$base_name}_mask_style",
"{$base_name}_mask_color",
"{$base_name}_mask_transform",
"{$base_name}_mask_aspect_ratio",
"{$base_name}_mask_size",
"{$base_name}_mask_width",
"{$base_name}_mask_height",
"{$base_name}_mask_position",
"{$base_name}_mask_horizontal_offset",
"{$base_name}_mask_vertical_offset",
"{$base_name}_mask_blend_mode",
),
);
if ( $is_background_attr ) {
$structure['color'][] = 'use_background_color';
$structure['image'][] = 'bg_img'; // Column.
}
return $structure;
}
/**
* Get list of background fields names in one dimensional array
*
* @return array
*/
public function get_background_fields_names() {
$background_structure = $this->get_background_fields_structure();
$fields_names = array();
foreach ( $background_structure as $tab_name ) {
foreach ( $tab_name as $field_name ) {
$fields_names[] = $field_name;
}
}
return $fields_names;
}
/**
* Get / extract background fields from all modules fields
*
* @param array $all_fields All modules fields.
*
* @param string $base_name Field base name.
*
* @return array background fields multidimensional array grouped based on its tab
*/
public function get_background_fields( $all_fields, $base_name = 'background' ) {
$background_fields_structure = $this->get_background_fields_structure( $base_name );
$background_tab_names = array_keys( $background_fields_structure );
$background_fields = array_fill_keys( $background_tab_names, array() );
foreach ( $all_fields as $field_name => $field ) {
// Multiple foreaches seem overkill. Use single foreach with little bit if conditions
// redundancy to get background fields grouped into multi-dimensional tab-based array.
if ( in_array( $field_name, $background_fields_structure['color'], true ) ) {
$background_fields['color'][ $field_name ] = $field;
}
if ( in_array( $field_name, $background_fields_structure['gradient'], true ) ) {
$background_fields['gradient'][ $field_name ] = $field;
}
if ( in_array( $field_name, $background_fields_structure['image'], true ) ) {
$background_fields['image'][ $field_name ] = $field;
}
if ( in_array( $field_name, $background_fields_structure['video'], true ) ) {
$background_fields['video'][ $field_name ] = $field;
}
// QF_BACKGROUND_MASKS.
if ( in_array( $field_name, $background_fields_structure['pattern'], true ) ) {
$background_fields['pattern'][ $field_name ] = $field;
}
if ( in_array( $field_name, $background_fields_structure['mask'], true ) ) {
$background_fields['mask'][ $field_name ] = $field;
}
}
return $background_fields;
}
/**
* Generate background fields based on base name
*
* @since 3.23 Add allowed CSS units for gradient start and end position. Override computed callback.
*
* @param string $base_name background base name.
* @param string $background_tab background tab name.
* @param string $tab_slug field's tab slug.
* @param string $toggle_slug field's toggle slug.
* @param string $context field's context.
* @param array $options_filters list of filters that should be used to skip some options.
*
* @return array of background fields
*/
public function generate_background_options( $base_name, $background_tab, $tab_slug, $toggle_slug, $context = null, $options_filters = array() ) {
$baseless_prefix = 'background' === $base_name ? '' : "{$base_name}_";
$options = array();
$i18n =& self::$i18n;
if ( ! isset( $i18n['background'] ) ) {
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
$i18n['background'] = array(
'color' => array(
'label' => esc_html__( 'Background Color', 'et_builder' ),
),
'gradient' => array(
'label' => esc_html__( 'Use Background Color Gradient', 'et_builder' ),
),
'gradient_repeat' => array(
'label' => esc_html__( 'Repeat Gradient', 'et_builder' ),
'description' => esc_html__( 'If enabled, defined gradient stops will be repeated until the outer boundary of the background is reached.', 'et_builder' ),
),
'gradient_type' => array(
'label' => esc_html__( 'Gradient Type', 'et_builder' ),
'description' => esc_html__( 'Linear gradients radiate in a single direction across one axis. Radial gradients radiate from the center of the background in the shape of a circle.', 'et_builder' ),
),
'gradient_direction' => array(
'label' => esc_html__( 'Gradient Direction', 'et_builder' ),
'description' => esc_html__( 'Change the direction of the gradient by choosing a starting position within a 360 degree range.', 'et_builder' ),
),
'gradient_direction_radial' => array(
'label' => esc_html__( 'Gradient Position', 'et_builder' ),
'description' => esc_html__( 'Change the direction of the gradient by choosing a starting position within a 360 degree range.', 'et_builder' ),
),
'gradient_stops' => array(
'label' => esc_html__( 'Gradient Stops', 'et_builder' ),
'description' => esc_html__( 'Add two or more color stops to your gradient background. Each stop can be dragged to any position on the gradient bar. From each color stop to the next the color is interpolated into a smooth gradient.', 'et_builder' ),
),
'gradient_unit' => array(
'label' => esc_html__( 'Gradient Unit', 'et_builder' ),
'description' => esc_html__( 'Define the units of your gradient stop positions.', 'et_builder' ),
),
'gradient_overlay' => array(
'label' => esc_html__( 'Place Gradient Above Background Image', 'et_builder' ),
'description' => esc_html__( 'If enabled, gradient will be positioned on top of background-image', 'et_builder' ),
),
// Deprecated.
'gradient_start' => array(
'label' => esc_html__( 'Gradient Start', 'et_builder' ),
),
// Deprecated.
'gradient_start_position' => array(
'label' => esc_html__( 'Start Position', 'et_builder' ),
'description' => esc_html__( 'By adjusting the starting position of the gradient, you can control how quickly or slowly each color transitions, and where the transition begins.', 'et_builder' ),
),
// Deprecated.
'gradient_end' => array(
'label' => esc_html__( 'Gradient End', 'et_builder' ),
),
// Deprecated.
'gradient_end_position' => array(
'label' => esc_html__( 'End Position', 'et_builder' ),
'description' => esc_html__( 'By adjusting the ending position of the gradient, you can control how quickly or slowly each color transitions, and where the transition begins.', 'et_builder' ),
),
'image' => array(
'label' => esc_html__( 'Background Image', 'et_builder' ),
'choose_text' => esc_attr__( 'Choose a Background Image', 'et_builder' ),
'update_text' => esc_attr__( 'Set As Background', 'et_builder' ),
),
'parallax' => array(
'label' => esc_html__( 'Use Parallax Effect', 'et_builder' ),
'description' => esc_html__( 'If enabled, your background image will stay fixed as your scroll, creating a fun parallax-like effect.', 'et_builder' ),
),
'parallax_method' => array(
'label' => esc_html__( 'Parallax Method', 'et_builder' ),
'description' => esc_html__( 'Define the method, used for the parallax effect.', 'et_builder' ),
'options' => array(
'on' => esc_html__( 'True Parallax', 'et_builder' ),
'off' => esc_html__( 'CSS', 'et_builder' ),
),
),
'size' => array(
'label' => esc_html__( 'Background Image Size', 'et_builder' ),
'description' => esc_html__( 'Choosing "Cover" will force the image to fill the entire background area, clipping the image when necessary. Choosing "Fit" will ensure that the entire image is always visible, but can result in blank spaces around the image. When set to "Actual Size," the image will not be resized at all.', 'et_builder' ),
'options' => array(
'cover' => et_builder_i18n( 'Cover' ),
'contain' => et_builder_i18n( 'Fit' ),
'initial' => et_builder_i18n( 'Actual Size' ),
'stretch' => et_builder_i18n( 'Stretch to Fill' ),
'custom' => et_builder_i18n( 'Custom Size' ),
),
),
'image_width' => array(
'label' => esc_html__( 'Background Image Width', 'et_builder' ),
),
'image_height' => array(
'label' => esc_html__( 'Background Image Height', 'et_builder' ),
),
'position' => array(
'label' => esc_html__( 'Background Image Position', 'et_builder' ),
'description' => esc_html__( "Choose where you would like the background image to be positioned within this element. You may want to position the background based on the the image's focus point.", 'et_builder' ),
),
'horizontal_offset' => array(
'label' => esc_html__( 'Background Image Horizontal Offset', 'et_builder' ),
),
'vertical_offset' => array(
'label' => esc_html__( 'Background Image Vertical Offset', 'et_builder' ),
),
'repeat' => array(
'label' => esc_html__( 'Background Image Repeat', 'et_builder' ),
'description' => esc_html__( 'If the background image is smaller than the size of the element, you may want the image to repeat. This result will result in a background image pattern.', 'et_builder' ),
),
'blend' => array(
'label' => esc_html__( 'Background Image Blend', 'et_builder' ),
'description' => esc_html__( 'Background images can be blended with the background color, merging the two and creating unique effects.', 'et_builder' ),
),
'mp4' => array(
'label' => esc_html__( 'Background Video MP4', 'et_builder' ),
'description' => esc_html__( 'All videos should be uploaded in both .MP4 .WEBM formats to ensure maximum compatibility in all browsers. Upload the .MP4 version here.', 'et_builder' ),
'upload_button_text' => esc_attr__( 'Upload a video', 'et_builder' ),
'choose_text' => esc_attr__( 'Choose a Background Video MP4 File', 'et_builder' ),
'update_text' => esc_attr__( 'Set As Background Video', 'et_builder' ),
),
'webm' => array(
'label' => esc_html__( 'Background Video Webm', 'et_builder' ),
'description' => esc_html__( 'All videos should be uploaded in both .MP4 .WEBM formats to ensure maximum compatibility in all browsers. Upload the .WEBM version here.', 'et_builder' ),
'upload_button_text' => esc_attr__( 'Upload a video', 'et_builder' ),
'choose_text' => esc_attr__( 'Choose a Background Video WEBM File', 'et_builder' ),
'update_text' => esc_attr__( 'Set As Background Video', 'et_builder' ),
),
'video_width' => array(
'label' => esc_html__( 'Background Video Width', 'et_builder' ),
'description' => esc_html__( 'In order for videos to be sized correctly, you must input the exact width (in pixels) of your video here.', 'et_builder' ),
),
'video_height' => array(
'label' => esc_html__( 'Background Video Height', 'et_builder' ),
'description' => esc_html__( 'In order for videos to be sized correctly, you must input the exact height (in pixels) of your video here.', 'et_builder' ),
),
'pause' => array(
'label' => esc_html__( 'Pause Video When Another Video Plays', 'et_builder' ),
'description' => esc_html__( 'Allow video to be paused by other players when they begin playing', 'et_builder' ),
),
'viewport' => array(
'label' => esc_html__( 'Pause Video While Not In View', 'et_builder' ),
'description' => esc_html__( 'Allow video to be paused while it is not in the visible area.', 'et_builder' ),
),
);
// phpcs:enable
}
// Not included on skip background tab because background-field is expected to be registered under "background_color" field.
if ( in_array( $background_tab, array( 'all', 'button', 'color' ), true ) ) {
$options[ "{$base_name}_color" ] = self::background_field_template(
'color',
array(
'label' => $i18n['background']['color']['label'],
'type' => 'color-alpha',
'option_category' => 'configuration',
'custom_color' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color',
'hover' => 'tabs',
'last_edited' => 'background',
'mobile_options' => true,
'sticky' => true,
)
);
// This option is used to enable or disable background color on VB or FE. This option has
// different function with use_background_color. Option background_enable_color won't hide
// background color option like what use_background_color does. It's used to ensure if
// current background should be rendered or not by inheriting or applying custom color.
$options[ "{$base_name}_enable_color" ] = self::background_field_template(
'enable_color',
array(
'type' => 'skip',
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'default' => 'on',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
}
if ( in_array( $background_tab, array( 'all', 'button', 'skip', 'gradient' ), true ) ) {
$use_background_color_gradient_name = 'background' === $base_name ? 'use_background_color_gradient' : "{$base_name}_use_color_gradient";
$options[ $use_background_color_gradient_name ] = self::background_field_template(
'use_color_gradient',
array(
'label' => $i18n['background']['gradient']['label'],
'description' => '',
'type' => 'skip' === $background_tab ? 'skip' : 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'off' => et_builder_i18n( 'No' ),
'on' => et_builder_i18n( 'Yes' ),
),
'default' => 'off',
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'use_color_gradient',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
$options[ "{$base_name}_color_gradient_repeat" ] = self::background_field_template(
'color_gradient_repeat',
array(
'label' => $i18n['background']['gradient_repeat']['label'],
'description' => $i18n['background']['gradient_repeat']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'off' => et_builder_i18n( 'No' ),
'on' => et_builder_i18n( 'Yes' ),
),
'default' => ET_Global_Settings::get_value( 'all_background_gradient_repeat' ),
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_repeat',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"$use_background_color_gradient_name" => 'on',
),
)
);
$options[ "{$base_name}_color_gradient_type" ] = self::background_field_template(
'color_gradient_type',
array(
'label' => $i18n['background']['gradient_type']['label'],
'description' => $i18n['background']['gradient_type']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'select',
'option_category' => 'configuration',
'options' => array(
'linear' => et_builder_i18n( 'Linear' ),
'circular' => et_builder_i18n( 'Circular' ),
'elliptical' => et_builder_i18n( 'Elliptical' ),
'conic' => et_builder_i18n( 'Conical' ),
),
'default' => ET_Global_Settings::get_value( 'all_background_gradient_type' ),
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_type',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"$use_background_color_gradient_name" => 'on',
),
)
);
$options[ "{$base_name}_color_gradient_direction" ] = self::background_field_template(
'color_gradient_direction',
array(
'label' => $i18n['background']['gradient_direction']['label'],
'description' => $i18n['background']['gradient_direction']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'range',
'option_category' => 'configuration',
'range_settings' => array(
'min' => 1,
'max' => 360,
'step' => 1,
),
'default' => ET_Global_Settings::get_value( 'all_background_gradient_direction' ),
'default_on_child' => true,
'validate_unit' => true,
'fixed_unit' => 'deg',
'fixed_range' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_direction',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"{$base_name}_color_gradient_type" => array(
'linear',
'conic',
),
),
)
);
$options[ "{$base_name}_color_gradient_direction_radial" ] = self::background_field_template(
'color_gradient_direction_radial',
array(
'label' => $i18n['background']['gradient_direction_radial']['label'],
'description' => $i18n['background']['gradient_direction_radial']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'select',
'option_category' => 'configuration',
'options' => array(
'center' => et_builder_i18n( 'Center' ),
'top left' => et_builder_i18n( 'Top Left' ),
'top' => et_builder_i18n( 'Top' ),
'top right' => et_builder_i18n( 'Top Right' ),
'right' => et_builder_i18n( 'Right' ),
'bottom right' => et_builder_i18n( 'Bottom Right' ),
'bottom' => et_builder_i18n( 'Bottom' ),
'bottom left' => et_builder_i18n( 'Bottom Left' ),
'left' => et_builder_i18n( 'Left' ),
),
'default' => ET_Global_Settings::get_value( 'all_background_gradient_direction_radial' ),
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_direction_radial',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"{$base_name}_color_gradient_type" => array(
'radial',
'circular',
'elliptical',
'conic',
),
),
)
);
$options[ "{$base_name}_color_gradient_stops" ] = self::background_field_template(
'color_gradient_stops',
array(
'label' => $i18n['background']['gradient_stops']['label'],
'description' => $i18n['background']['gradient_stops']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'gradient-stops',
'option_category' => 'configuration',
'default' => ET_Global_Settings::get_value( 'all_background_gradient_stops' ),
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_stops',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"$use_background_color_gradient_name" => 'on',
),
)
);
$options[ "{$base_name}_color_gradient_unit" ] = self::background_field_template(
'color_gradient_unit',
array(
'label' => $i18n['background']['gradient_unit']['label'],
'description' => $i18n['background']['gradient_unit']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'select',
'option_category' => 'configuration',
'options' => array(
'%' => et_builder_i18n( 'Percent' ),
'px' => et_builder_i18n( 'Pixels' ),
'em' => et_builder_i18n( 'Font Size (em)' ),
'rem' => et_builder_i18n( 'Root-level Font Size (rem)' ),
'ex' => et_builder_i18n( 'X-Height (ex)' ),
'ch' => et_builder_i18n( 'Zero-width (ch)' ),
'pc' => et_builder_i18n( 'Picas (pc)' ),
'pt' => et_builder_i18n( 'Points (pt)' ),
'cm' => et_builder_i18n( 'Centimeters (cm)' ),
'mm' => et_builder_i18n( 'Millimeters (mm)' ),
'in' => et_builder_i18n( 'Inches (in)' ),
'vh' => et_builder_i18n( 'Viewport Height (vh)' ),
'vw' => et_builder_i18n( 'Viewport Width (vw)' ),
'vmin' => et_builder_i18n( 'Viewport Minimum (vmin)' ),
'vmax' => et_builder_i18n( 'Viewport Maximum (vmax)' ),
),
'default' => ET_Global_Settings::get_value( 'all_background_gradient_unit' ),
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_unit',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
// Do not render this control for conic gradients.
"{$base_name}_color_gradient_type" => array(
'linear',
'radial',
'circular',
'elliptical',
),
),
)
);
$options[ "{$base_name}_color_gradient_overlays_image" ] = self::background_field_template(
'color_gradient_overlays_image',
array(
'label' => $i18n['background']['gradient_overlay']['label'],
'description' => $i18n['background']['gradient_overlay']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'off' => et_builder_i18n( 'No' ),
'on' => et_builder_i18n( 'Yes' ),
),
'default' => ET_Global_Settings::get_value( 'all_background_gradient_overlays_image' ),
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_overlays_image',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"$use_background_color_gradient_name" => 'on',
),
)
);
// Deprecated.
$options[ "{$base_name}_color_gradient_start" ] = self::background_field_template(
'color_gradient_start',
array(
'label' => $i18n['background']['gradient_start']['label'],
'description' => '',
'type' => 'skip',
'option_category' => 'configuration',
'default' => ET_Global_Settings::get_value( 'all_background_gradient_start' ),
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_start',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"$use_background_color_gradient_name" => 'deprecated',
),
)
);
// Deprecated.
$options[ "{$base_name}_color_gradient_start_position" ] = self::background_field_template(
'color_gradient_start_position',
array(
'label' => $i18n['background']['gradient_start_position']['label'],
'description' => $i18n['background']['gradient_start_position']['description'],
'type' => 'skip',
'option_category' => 'configuration',
'range_settings' => array(
'min' => 0,
'max' => 100,
'step' => 1,
),
'default' => ET_Global_Settings::get_value( 'all_background_gradient_start_position' ),
'default_on_child' => true,
'validate_unit' => true,
'allowed_units' => array( '%', 'em', 'rem', 'px', 'cm', 'mm', 'in', 'pc', 'ex', 'vh', 'vw' ),
'default_unit' => '%',
'fixed_range' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_start_position',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"$use_background_color_gradient_name" => 'deprecated',
),
)
);
// Deprecated.
$options[ "{$base_name}_color_gradient_end" ] = self::background_field_template(
'color_gradient_end',
array(
'label' => $i18n['background']['gradient_end']['label'],
'description' => '',
'type' => 'skip',
'option_category' => 'configuration',
'default' => ET_Global_Settings::get_value( 'all_background_gradient_end' ),
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_end',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"$use_background_color_gradient_name" => 'deprecated',
),
)
);
// Deprecated.
$options[ "{$base_name}_color_gradient_end_position" ] = self::background_field_template(
'color_gradient_end_position',
array(
'label' => $i18n['background']['gradient_end_position']['label'],
'description' => $i18n['background']['gradient_end_position']['description'],
'type' => 'skip',
'option_category' => 'configuration',
'range_settings' => array(
'min' => 0,
'max' => 100,
'step' => 1,
),
'default' => ET_Global_Settings::get_value( 'all_background_gradient_end_position' ),
'default_on_child' => true,
'validate_unit' => true,
'allowed_units' => array( '%', 'em', 'rem', 'px', 'cm', 'mm', 'in', 'pc', 'ex', 'vh', 'vw' ),
'default_unit' => '%',
'fixed_range' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'color_gradient_end_position',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"$use_background_color_gradient_name" => 'deprecated',
),
)
);
}
if ( in_array( $background_tab, array( 'all', 'button', 'skip', 'image' ), true ) ) {
$options[ "{$base_name}_image" ] = self::background_field_template(
'image',
array(
'label' => $i18n['background']['image']['label'],
'choose_text' => $i18n['background']['image']['choose_text'],
'update_text' => $i18n['background']['image']['update_text'],
'upload_button_text' => et_builder_i18n( 'Upload an image' ),
'type' => 'skip' === $background_tab ? 'skip' : 'upload',
'option_category' => 'configuration',
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'image',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
// This option is used to enable or disable background image on VB or FE. It's used to
// ensure if current background should be rendered or not by inheriting or applying
// custom image.
$options[ "{$base_name}_enable_image" ] = self::background_field_template(
'enable_image',
array(
'type' => 'skip',
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'default' => 'on',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
if ( 'button' !== $background_tab && ! in_array( 'parallax', $options_filters, true ) ) {
$options[ "{$baseless_prefix}parallax" ] = self::background_field_template(
'parallax',
array(
'label' => $i18n['background']['parallax']['label'],
'description' => $i18n['background']['parallax']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'off' => et_builder_i18n( 'No' ),
'on' => et_builder_i18n( 'Yes' ),
),
'default' => 'off',
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'parallax',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
$options[ "{$baseless_prefix}parallax_method" ] = self::background_field_template(
'parallax_method',
array(
'label' => $i18n['background']['parallax_method']['label'],
'description' => $i18n['background']['parallax_method']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'select',
'option_category' => 'configuration',
'options' => array(
'on' => $i18n['background']['parallax_method']['options']['on'],
'off' => $i18n['background']['parallax_method']['options']['off'],
),
'default' => self::$_->array_get( $this->advanced_fields, "background.options.{$baseless_prefix}parallax_method.default", 'on' ),
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'parallax_method',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"{$baseless_prefix}parallax" => 'on',
),
)
);
}
$options[ "{$base_name}_size" ] = self::background_field_template(
'size',
array(
'label' => $i18n['background']['size']['label'],
'description' => $i18n['background']['size']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'select',
'option_category' => 'layout',
'options' => array(
'cover' => $i18n['background']['size']['options']['cover'],
'contain' => $i18n['background']['size']['options']['contain'],
'initial' => $i18n['background']['size']['options']['initial'],
'stretch' => $i18n['background']['size']['options']['stretch'],
'custom' => $i18n['background']['size']['options']['custom'],
),
'default' => 'cover',
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'size',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'show_if' => array(
"{$baseless_prefix}parallax" => 'off',
),
)
);
$options[ "{$base_name}_image_width" ] = self::background_field_template(
'image_width',
array(
'allow_empty' => true,
'allowed_units' => et_pb_get_background_field_allowed_units(),
'allowed_values' => et_builder_get_acceptable_css_string_values( 'background-size' ),
'default' => 'auto',
'default_unit' => '%',
'default_on_child' => true,
'fixed_range' => true,
'hover' => 'tabs',
'label' => $i18n['background']['image_width']['label'],
'mobile_options' => true,
'option_category' => 'layout',
'range_settings' => array(
'min' => 0,
'min_limit' => 0,
'max' => 100,
'step' => 1,
),
'show_if' => array(
"{$base_name}_size" => 'custom',
),
'show_if_not' => array(
"{$baseless_prefix}parallax" => 'on',
),
'sticky' => true,
'type' => 'range',
'validate_unit' => true,
)
);
$options[ "{$base_name}_image_height" ] = self::background_field_template(
'image_height',
array(
'allow_empty' => true,
'allowed_units' => et_pb_get_background_field_allowed_units(),
'allowed_values' => et_builder_get_acceptable_css_string_values( 'background-size' ),
'default' => 'auto',
'default_unit' => '%',
'default_on_child' => true,
'fixed_range' => true,
'hover' => 'tabs',
'label' => $i18n['background']['image_height']['label'],
'mobile_options' => true,
'option_category' => 'layout',
'range_settings' => array(
'min' => 0,
'min_limit' => 0,
'max' => 100,
'step' => 1,
),
'show_if' => array(
"{$base_name}_size" => 'custom',
),
'show_if_not' => array(
"{$baseless_prefix}parallax" => 'on',
),
'sticky' => true,
'type' => 'range',
'validate_unit' => true,
)
);
$options[ "{$base_name}_position" ] = self::background_field_template(
'position',
array(
'label' => $i18n['background']['position']['label'],
'description' => $i18n['background']['position']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'select',
'option_category' => 'layout',
'options' => et_pb_get_background_position_options(),
'default' => 'center',
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'position',
'mobile_options' => true,
'sticky' => true,
'show_if_not' => array(
"{$baseless_prefix}parallax" => 'on',
),
'hover' => 'tabs',
)
);
$options[ "{$base_name}_horizontal_offset" ] = self::background_field_template(
'horizontal_offset',
array(
'allowed_units' => et_pb_get_background_field_allowed_units(),
'default' => '0',
'default_unit' => '%',
'default_on_child' => true,
'fixed_range' => true,
'hover' => 'tabs',
'label' => $i18n['background']['horizontal_offset']['label'],
'mobile_options' => true,
'option_category' => 'layout',
'range_settings' => array(
'min' => - 100,
'max' => 100,
'step' => 1,
),
'show_if' => array(
"{$base_name}_position" => array(
'top_left',
'top_right',
'center_left',
'center_right',
'bottom_left',
'bottom_right',
),
),
'show_if_not' => array(
"{$baseless_prefix}parallax" => 'on',
),
'sticky' => true,
'type' => 'range',
'validate_unit' => true,
)
);
$options[ "{$base_name}_vertical_offset" ] = self::background_field_template(
'vertical_offset',
array(
'allowed_units' => et_pb_get_background_field_allowed_units(),
'default' => '0',
'default_unit' => '%',
'default_on_child' => true,
'fixed_range' => true,
'hover' => 'tabs',
'label' => $i18n['background']['vertical_offset']['label'],
'mobile_options' => true,
'option_category' => 'layout',
'range_settings' => array(
'min' => - 100,
'max' => 100,
'step' => 1,
),
'show_if' => array(
"{$base_name}_position" => array(
'top_left',
'top_center',
'top_right',
'bottom_left',
'bottom_center',
'bottom_right',
),
),
'show_if_not' => array(
"{$baseless_prefix}parallax" => 'on',
),
'sticky' => true,
'type' => 'range',
'validate_unit' => true,
)
);
$options[ "{$base_name}_repeat" ] = self::background_field_template(
'repeat',
array(
'label' => $i18n['background']['repeat']['label'],
'description' => $i18n['background']['repeat']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'select',
'option_category' => 'layout',
'options' => et_pb_get_background_repeat_options(),
'default' => 'no-repeat',
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'repeat',
'mobile_options' => true,
'show_if' => array(
"{$base_name}_size" => array(
'cover',
'contain',
'initial',
'custom',
),
),
'show_if_not' => array(
"{$baseless_prefix}parallax" => 'on',
),
'sticky' => true,
'hover' => 'tabs',
)
);
$options[ "{$base_name}_blend" ] = self::background_field_template(
'blend',
array(
'label' => $i18n['background']['blend']['label'],
'description' => $i18n['background']['blend']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'select',
'option_category' => 'layout',
'options' => et_pb_get_background_blend_mode_options(),
'default' => 'normal',
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'blend',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
}
if ( in_array( $background_tab, array( 'all', 'skip', 'video' ), true ) ) {
$options[ "{$base_name}_video_mp4" ] = self::background_field_template(
'video_mp4',
array(
'label' => $i18n['background']['mp4']['label'],
'description' => $i18n['background']['mp4']['description'],
'upload_button_text' => $i18n['background']['mp4']['upload_button_text'],
'choose_text' => $i18n['background']['mp4']['choose_text'],
'update_text' => $i18n['background']['mp4']['update_text'],
'type' => 'skip' === $background_tab ? 'skip' : 'upload',
'option_category' => 'configuration',
'data_type' => 'video',
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'computed_affects' => array(
"__video_{$base_name}",
),
'field_template' => 'video_mp4',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'affects_mobile' => true,
)
);
// This option is used to enable or disable background MP4 video on VB or FE. It's used
// to ensure if current background should be rendered or not by inheriting or applying
// custom MP4 video.
$options[ "{$base_name}_enable_video_mp4" ] = self::background_field_template(
'enable_video_mp4',
array(
'type' => 'skip',
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'default' => 'on',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
$options[ "{$base_name}_video_webm" ] = self::background_field_template(
'video_webm',
array(
'label' => $i18n['background']['webm']['label'],
'description' => $i18n['background']['webm']['description'],
'upload_button_text' => $i18n['background']['webm']['upload_button_text'],
'choose_text' => $i18n['background']['webm']['choose_text'],
'update_text' => $i18n['background']['webm']['update_text'],
'type' => 'skip' === $background_tab ? 'skip' : 'upload',
'option_category' => 'configuration',
'data_type' => 'video',
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'computed_affects' => array(
"__video_{$base_name}",
),
'field_template' => 'video_webm',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'affects_mobile' => true,
)
);
// This option is used to enable or disable background Webm video on VB or FE. It's used
// to ensure if current background should be rendered or not by inheriting or applying
// custom Webm video.
$options[ "{$base_name}_enable_video_webm" ] = self::background_field_template(
'enable_video_webm',
array(
'type' => 'skip',
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'default' => 'on',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
$options[ "{$base_name}_video_width" ] = self::background_field_template(
'video_width',
array(
'label' => $i18n['background']['video_width']['label'],
'description' => $i18n['background']['video_width']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'text',
'option_category' => 'configuration',
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'computed_affects' => array(
"__video_{$base_name}",
),
'field_template' => 'video_width',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'affects_mobile' => true,
)
);
$options[ "{$base_name}_video_height" ] = self::background_field_template(
'video_height',
array(
'label' => $i18n['background']['video_height']['label'],
'description' => $i18n['background']['video_height']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'text',
'option_category' => 'configuration',
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'computed_affects' => array(
"__video_{$base_name}",
),
'field_template' => 'video_height',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
'affects_mobile' => true,
)
);
$options[ "{$baseless_prefix}allow_player_pause" ] = self::background_field_template(
'allow_player_pause',
array(
'label' => $i18n['background']['pause']['label'],
'description' => $i18n['background']['pause']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'off' => et_builder_i18n( 'No' ),
'on' => et_builder_i18n( 'Yes' ),
),
'default' => 'off',
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'allow_player_pause',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
$options[ "{$base_name}_video_pause_outside_viewport" ] = self::background_field_template(
'video_pause_outside_viewport',
array(
'label' => $i18n['background']['viewport']['label'],
'description' => $i18n['background']['viewport']['description'],
'type' => 'skip' === $background_tab ? 'skip' : 'yes_no_button',
'option_category' => 'configuration',
'options' => array(
'off' => et_builder_i18n( 'No' ),
'on' => et_builder_i18n( 'Yes' ),
),
'default' => 'on',
'default_on_child' => true,
'tab_slug' => $tab_slug,
'toggle_slug' => $toggle_slug,
'field_template' => 'video_pause_outside_viewport',
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
$options[ "__video_{$base_name}" ] = self::background_field_template(
'video_computed',
array(
'type' => 'computed',
'computed_callback' => array( 'ET_Builder_Module_Helper_ResponsiveOptions', 'get_video_background' ),
'computed_depends_on' => array(
"{$base_name}_video_mp4",
"{$base_name}_video_webm",
"{$base_name}_video_width",
"{$base_name}_video_height",
),
'computed_minimum' => array(
"{$base_name}_video_mp4",
"{$base_name}_video_webm",
),
'computed_variables' => array(
'base_name' => $base_name,
),
'mobile_options' => true,
'sticky' => true,
'hover' => 'tabs',
)
);
}
// QF_BACKGROUND_MASKS :: Mask Options.
// Not included on skip background tab because pattern should only load for background, not
// for background-fields (i.e button).
if ( in_array( $background_tab, array( 'all', 'pattern' ), true ) ) {
$pattern_fields = et_pb_get_pattern_fields( $base_name );
$options = array_merge( $options, $pattern_fields );
unset( $pattern_fields );
}
// Not included on skip background tab because mask should only load for background, not for
// background-fields (i.e button).
if ( in_array( $background_tab, array( 'all', 'mask' ), true ) ) {
$mask_fields = et_pb_get_mask_fields( $base_name );
$options = array_merge( $options, $mask_fields );
unset( $mask_fields );
}
foreach ( $options as $option_name => &$option ) {
$option['context'] = null === $context ? $base_name : $context;
}
return $options;
}
/**
* Get string of background fields UI. Used in place of background_color fields UI.
*
* @param array $all_fields list of all module fields.
*
* @param string $base_name background base name.
*
* @return string background fields UI
*/
public function wrap_settings_background_fields( $all_fields, $base_name = 'background' ) {
$tab_structure = $this->get_background_fields_structure( $base_name );
$tab_names = array_keys( $tab_structure );
$background_fields = $this->get_background_fields( $all_fields, $base_name );
// Concatenate background fields UI.
$background = '';
// Label.
$background .= sprintf(
'
',
esc_html__( 'Background:', 'et_builder' )
);
// Field wrapper.
$background .= sprintf(
'
',
esc_attr( $base_name )
);
$tab_names_processed = array();
foreach ( $tab_names as $tab_nav_name ) {
if ( ! empty( $background_fields[ $tab_nav_name ] ) ) {
$tab_names_processed[] = sanitize_text_field( $tab_nav_name );
}
}
// Apply background UI if the module has more than one backgroundFields to avoid 3rd party module's field which uses `background_color` field and incorrectly rendered as background UI.
if ( count( $tab_names_processed ) < 2 ) {
return '';
}
// Tab Nav.
$background .= sprintf( '<%%= window.et_builder.options_template_output("background_tabs_nav",%1$s) %%>', wp_json_encode( $tab_names_processed ) );
// Tabs.
foreach ( $tab_names as $tab_name ) {
$background .= sprintf(
'
',
esc_attr( $tab_name )
);
// Get tab's fields.
$tab_fields = $background_fields[ $tab_name ];
// Render gradient tab's preview.
if ( 'gradient' === $tab_name ) {
$background .= '<%= window.et_builder.options_template_output("background_gradient_buttons") %>';
}
// Tab's fields.
foreach ( $tab_fields as $tab_field_name => $tab_field ) {
if ( 'skip' === $tab_field['type'] ) {
continue;
}
$preview_class = '';
// Append field name.
$tab_field['name'] = $tab_field_name;
// Append preview class name.
if ( in_array( $tab_field['name'], array( "{$base_name}_color", "{$base_name}_image", "{$base_name}_url", "{$base_name}_video_mp4", "{$base_name}_video_webm" ), true ) ) {
$tab_field['has_preview'] = true;
$preview_class = ' et-pb-option--has-preview';
}
// Prepare field list attribute.
$depends = false;
$depends_attr = '';
if ( isset( $tab_field['depends_show_if'] ) || isset( $tab_field['depends_show_if_not'] ) ) {
$depends = true;
if ( isset( $tab_field['depends_show_if_not'] ) ) {
$depends_show_if_not = is_array( $tab_field['depends_show_if_not'] ) ? implode( ',', $tab_field['depends_show_if_not'] ) : $tab_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( $tab_field['depends_show_if'] ) );
}
}
// Append fields UI.
$background .= sprintf(
'
',
esc_attr( $tab_field_name ),
esc_attr( $preview_class ),
$depends_attr,
esc_attr( $tab_field['name'] ),
"{$base_name}_color" === $tab_field['name'] && 'background' !== $base_name ? 'et-pb-option-main' : 'et-pb-option',
isset( $tab_field['field_template'] ) ? esc_attr( $tab_field['field_template'] ) : ''
);
// This adds a CSS class based on whether it is `true` or `false`.
$this->is_background = true;
$background .= $this->wrap_settings_option_label( $tab_field );
$background .= $this->wrap_settings_option_field( $tab_field );
$this->is_background = false;
$background .= '
';
}
$background .= '
';
}
// End of field wrapper.
$background .= '
';
return $background;
}
/**
* Get field name with prefix.
*
* @param array $field Field.
*
* @return mixed|string
*/
public function get_field_name( $field ) {
$prefix = 'et_pb_';
// Option template convert array field into string id; return early to prevent error.
if ( is_string( $field ) ) {
return $prefix . 'option_template_' . $field;
}
// Don't add 'et_pb_' prefix to the "Admin Label" field.
if ( 'admin_label' === $field['name'] ) {
return $field['name'];
}
// Make sure the prefix is not doubled.
if ( strpos( $field['name'], $prefix ) === 0 ) {
return $field['name'];
}
return $prefix . $field['name'];
}
/**
* Get field name for use in underscore templates.
*
* @since 3.17.2
*
* @param array $field Field.
*
* @return string
*/
public function get_field_variable_name( $field ) {
$name = $this->get_field_name( $field );
if ( isset( $this->type ) && 'child' === $this->type ) {
$name = "data.{$name}";
}
$name = str_replace( '-', '_', $name );
return $name;
}
/**
* Process field attributes into markup.
*
* @param array $field Field.
* @param array $attributes Field attributes.
*/
public function process_html_attributes( $field, &$attributes ) {
if ( is_array( $field['attributes'] ) ) {
foreach ( $field['attributes'] as $attribute_key => $attribute_value ) {
$attributes .= ' ' . esc_attr( $attribute_key ) . '="' . esc_attr( $attribute_value ) . '"';
}
} else {
$attributes = ' ' . $field['attributes'];
}
}
/**
* Returns an underscore template for the options settings.
*
* @since 3.23 Disable mobile options (responsive settings) on unsupported field types. It's
* added to adapt Options Harmony v2. Fix unexpected token because composite fields
* with range type load empty last edited value.
*
* @param array $field {
* Associative array.
*
* @type 'id' => (int),
* @type string 'label' => (string),
* @type string 'description' => (string),
* @type string 'class' => (string),
* @type string 'type' => (string),
* @type string 'validate_input' => (bool),
* @type string 'name' => (string),
* @type string 'default' => (string),
* @type string 'defaults' => (array),
* @type string 'options' => (array),
* @type string 'option_category' => (string),
* @type string 'attributes' => (string),
* @type string 'affects' => (string),
* @type string 'before' => (string),
* @type string 'after' => (string),
* @type string 'display_if' => (string),
* @type string 'depends_on' => (string),
* @type string 'depends_show_if' => (string),
* @type string 'depends_show_if_not' => (string),
* @type string 'show_if' => (string),
* @type string 'show_if_not' => (string),
* @type string 'tab_slug' => (string),
* @type string 'toggle_slug' => (string),
* @type string 'composite_type' => (string),
* @type string 'composite_structure' => (array),
* }
* @param string $name Field name.
*
* @return string HTML underscore template.
*/
public function render_field( $field, $name = '' ) {
$classes = array();
$hidden_field = '';
$field_el = '';
$is_custom_color = isset( $field['custom_color'] ) && $field['custom_color'];
$reset_button_html = '
';
$need_mobile_options = isset( $field['mobile_options'] ) && $field['mobile_options'] ? true : false;
$only_options = isset( $field['only_options'] ) ? $field['only_options'] : false;
$is_child = isset( $this->type ) && 'child' === $this->type;
// Option template convert array field into string id; return early to prevent error.
if ( is_string( $field ) ) {
return '';
}
// Make sure 'type' is always set to prevent PHP notices.
if ( empty( $field['type'] ) ) {
$field['type'] = 'no-type';
}
// Disable mobile options for unsupported types. Before Options Harmony v2, only custom
// margin/padding, text/number, and range support responsive settings. Later on, we added
// responsive settings to all settings. However BB is no longer supported, so we need to
// disable mobile options on those selected field types.
$unsupported_mobile_options = array( 'upload-gallery', 'background-field', 'warning', 'tiny_mce', 'codemirror', 'textarea', 'custom_css', 'options_list', 'sortable_list', 'conditional_logic', 'text_align', 'align', 'select', 'divider', 'yes_no_button', 'multiple_buttons', 'font', 'select_with_option_groups', 'select_animation', 'presets_shadow', 'select_box_shadow', 'presets', 'color', 'color-alpha', 'upload', 'checkbox', 'multiple_checkboxes', 'hidden' );
if ( $need_mobile_options && in_array( $field['type'], $unsupported_mobile_options, true ) ) {
$need_mobile_options = false;
}
if ( $need_mobile_options ) {
$mobile_settings_tabs = et_pb_generate_mobile_settings_tabs();
}
if ( 0 !== strpos( $field['type'], 'select' ) ) {
$classes = array( 'regular-text' );
}
foreach ( $this->get_validation_class_rules() as $rule ) {
if ( ! empty( $field[ $rule ] ) ) {
$this->validation_in_use = true;
$classes[] = $rule;
}
}
if ( isset( $field['validate_unit'] ) && $field['validate_unit'] ) {
$classes[] = 'et-pb-validate-unit';
}
if ( ! empty( $field['class'] ) ) {
if ( is_string( $field['class'] ) ) {
$field['class'] = array( $field['class'] );
}
$classes = array_merge( $classes, $field['class'] );
}
$field['class'] = implode( ' ', $classes );
$field_name = $this->get_field_name( $field );
$field['id'] = ! empty( $field['id'] ) ? $field['id'] : $field_name;
$field['name'] = $field_name;
if ( $is_child ) {
$field_name = "data.{$field_name}";
}
$field_var_name = $this->get_field_variable_name( $field );
$default_on_front = self::$_->array_get( $field, 'default_on_front', '' );
$default_arr = self::$_->array_get( $field, 'default', $default_on_front );
// Inform that default value is array and last edited value maybe empty string. Decided to
// create new variable, just in case $default_arr will be modified later.
$default_last_edited_is_arr = false;
if ( is_array( $default_arr ) && isset( $default_arr[1] ) && is_array( $default_arr[1] ) ) {
list($default_parent_id, $defaults_list) = $default_arr;
$default_parent_id = sprintf( '%1$set_pb_%2$s', $is_child ? 'data.' : '', $default_parent_id );
$default = esc_attr( wp_json_encode( $default_arr ) );
$default_value = sprintf(
'(typeof(%1$s) !== \'undefined\' ? ( typeof(%1$s) === \'object\' ? (%2$s)[jQuery(%1$s).val()] : (%2$s)[%1$s] ) : \'\')',
$default_parent_id,
wp_json_encode( $defaults_list )
);
$default_is_arr = true;
$default_last_edited_is_arr = true;
} else {
$default_value = $default_arr;
$default = $default_value;
$default_is_arr = false;
}
if ( 'font' === $field['type'] ) {
$default = '' === $default ? '||||||||' : $default;
$default_value = '' === $default_value ? '||||||||' : $default_value;
}
$font_icon_options = array( 'et_pb_font_icon', 'et_pb_button_icon', 'et_pb_button_one_icon', 'et_pb_button_two_icon', 'et_pb_hover_icon' );
if ( in_array( $field_name, $font_icon_options, true ) ) {
$field_value = esc_attr( $field_var_name );
} else {
$field_value = esc_attr( $field_var_name ) . '.replace(/%91/g, "[").replace(/%93/g, "]").replace(/%22/g, "\"")';
}
$value_html = $default_is_arr
? ' value="<%%- typeof( %1$s ) !== \'undefined\' ? %2$s : %3$s %%>" '
: ' value="<%%- typeof( %1$s ) !== \'undefined\' ? %2$s : \'%3$s\' %%>" ';
$value = sprintf(
$value_html,
esc_attr( $field_var_name ),
$field_value,
$default_value
);
$attributes = '';
if ( ! empty( $field['attributes'] ) ) {
$this->process_html_attributes( $field, $attributes );
}
if ( ! empty( $field['affects'] ) ) {
$field['class'] .= ' et-pb-affects';
$attributes .= sprintf( ' data-affects="%s"', esc_attr( implode( ', ', $field['affects'] ) ) );
}
if ( ! empty( $field['responsive_affects'] ) ) {
$field['class'] .= ' et-pb-responsive-affects';
$attributes .= sprintf(
' data-responsive-affects="%1$s" data-responsive-desktop-name="%2$s"',
esc_attr( implode( ', ', $field['responsive_affects'] ) ),
esc_attr( $field['name'] )
);
}
if ( 'font' === $field['type'] ) {
$field['class'] .= ' et-pb-font-select';
}
if ( in_array( $field['type'], array( 'font', 'hidden', 'multiple_checkboxes', 'select_with_option_groups', 'select_animation', 'presets', 'presets_shadow', 'select_box_shadow' ), true ) && ! $only_options ) {
$hidden_field = sprintf(
'
',
esc_attr( $field['name'] ),
esc_attr( $field['id'] ),
esc_attr( $field['class'] ),
esc_attr( $default ),
$value,
$attributes
);
if ( 'select_with_option_groups' === $field['type'] ) {
// Since we are using a hidden field to manage the value, we need to clear the data-affects attribute so that
// it doesn't appear on both the `$field` AND the hidden field. This should probably be done for all of these
// field types but don't want to risk breaking anything :-/.
$attributes = preg_replace( '/data-affects="[\w\s,-]*"/', 'data-affects=""', $attributes );
}
}
foreach ( $this->get_validation_attr_rules() as $rule ) {
if ( ! empty( $field[ $rule ] ) ) {
$this->validation_in_use = true;
$attributes .= ' data-rule-' . esc_attr( $rule ) . '="' . esc_attr( $field[ $rule ] ) . '"';
}
}
if ( isset( $field['before'] ) && ! $only_options ) {
$field_el .= $this->render_field_before_after_element( $field['before'] );
}
switch ( $field['type'] ) {
case 'upload-gallery':
$field_el .= sprintf(
'
' .
'
',
esc_attr__( 'Update Gallery', 'et_builder' ),
$value,
esc_attr( $field['name'] ),
esc_attr( $field['id'] )
);
break;
case 'background-field':
$field_el .= $this->wrap_settings_background_fields( $field['background_fields'], $field['base_name'] );
break;
case 'warning':
$field_el .= sprintf(
'
%1$s
',
html_entity_decode( esc_html( $field['message'] ) ),
esc_attr( $field['name'] ),
esc_attr( $field['display_if'] )
);
break;
case 'tiny_mce':
if ( ! empty( $field['tiny_mce_html_mode'] ) ) {
$field['class'] .= ' html_mode';
}
$main_content_field_name = 'et_pb_content';
$main_content_property_name = $main_content_field_name;
if ( isset( $this->type ) && 'child' === $this->type ) {
$main_content_property_name = "data.{$main_content_property_name}";
}
if ( 'et_pb_signup' === $this->slug ) {
$main_content_field_name = $field['name'];
$main_content_property_name = $main_content_field_name;
}
$field_el .= sprintf(
'
<%%= typeof( %2$s ) !== \'undefined\' ? %2$s : \'\' %%>
',
esc_attr( $main_content_field_name ),
esc_html( $main_content_property_name )
);
break;
case 'codemirror':
case 'textarea':
case 'custom_css':
case 'options_list':
case 'sortable_list':
$field_custom_value = esc_html( $field_var_name );
if ( in_array( $field['type'], array( 'custom_css', 'options_list', 'sortable_list' ), true ) ) {
$field_custom_value .= '.replace( /\|\|/g, "\n" ).replace( /%22/g, """ ).replace( /%92/g, "\\\" )';
$field_custom_value .= '.replace( /%91/g, "[" ).replace( /%93/g, "]" )';
}
if ( in_array( $field_name, array( 'et_pb_custom_message' ), true ) ) {
// escape html to make sure it's not rendered inside the Textarea field in Settings Modal.
$field_custom_value = sprintf( '_.escape( %1$s )', $field_custom_value );
}
$field_el .= sprintf(
'