version 4.13.0
This commit is contained in:
14
includes/builder/module/helpers/Alignment.php
Normal file
14
includes/builder/module/helpers/Alignment.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Helper class that provides necessary functions for managing alignment option
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Alignment
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Alignment extends ET_Builder_Module_Helper_Sizing {
|
||||
|
||||
public function get_raw_field() {
|
||||
return 'module_alignment';
|
||||
}
|
||||
}
|
||||
|
751
includes/builder/module/helpers/Background.php
Normal file
751
includes/builder/module/helpers/Background.php
Normal file
@ -0,0 +1,751 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Background helper methods.
|
||||
* This is abstraction of `ET_Builder_Element->process_advanced_background_options()` method which is
|
||||
* intended for module that needs to extend module background mechanism with few modification
|
||||
* (eg. post slider which needs to apply module background on individual slide that has featured
|
||||
* image).
|
||||
*
|
||||
* @since 4.3.3
|
||||
* @since 4.6.0 Add sticky style support
|
||||
*
|
||||
* @todo Use `ET_Builder_Module_Helper_Background->get_background_style()` for `ET_Builder_Element->process_advanced_background_options()`
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Background
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Background {
|
||||
public static function instance() {
|
||||
static $instance;
|
||||
|
||||
return $instance ? $instance : $instance = new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prop name alias. Some background settings (eg. button's gradient background enable) might
|
||||
* use slightly different prop name to store background config;
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param array $aliases Aliases.
|
||||
* @param string $prop_name Prop name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_prop_name_alias( $aliases = array(), $prop_name = '' ) {
|
||||
// If no aliases given, simply return the prop name because it has no alias.
|
||||
if ( empty( $aliases ) ) {
|
||||
return $prop_name;
|
||||
}
|
||||
|
||||
return et_()->array_get( $aliases, $prop_name, $prop_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gradient properties based on given props
|
||||
*
|
||||
* @since 4.3.3
|
||||
*
|
||||
* @param array $props Module's props
|
||||
* @param string $base_prop_name Background base prop name
|
||||
* @param string $suffix Background base prop name's suffix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function get_gradient_properties( $props, $base_prop_name, $suffix ) {
|
||||
return array(
|
||||
'type' => et_pb_responsive_options()->get_any_value( $props, "{$base_prop_name}_color_gradient_type{$suffix}", '', true ),
|
||||
'direction' => et_pb_responsive_options()->get_any_value( $props, "{$base_prop_name}_color_gradient_direction{$suffix}", '', true ),
|
||||
'radial_direction' => et_pb_responsive_options()->get_any_value( $props, "{$base_prop_name}_color_gradient_direction_radial{$suffix}", '', true ),
|
||||
'color_start' => et_pb_responsive_options()->get_any_value( $props, "{$base_prop_name}_color_gradient_start{$suffix}", '', true ),
|
||||
'color_end' => et_pb_responsive_options()->get_any_value( $props, "{$base_prop_name}_color_gradient_end{$suffix}", '', true ),
|
||||
'start_position' => et_pb_responsive_options()->get_any_value( $props, "{$base_prop_name}_color_gradient_start_position{$suffix}", '', true ),
|
||||
'end_position' => et_pb_responsive_options()->get_any_value( $props, "{$base_prop_name}_color_gradient_end_position{$suffix}", '', true ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gradient properties for hover mode
|
||||
*
|
||||
* @since 4.3.3
|
||||
* @since 4.6.0 add capability to look for sticky style's gradient
|
||||
*
|
||||
* @param array $props Module's props
|
||||
* @param string $base_prop_name Background base prop name
|
||||
* @param array $gradient_properties_desktop {
|
||||
* @type string $mode
|
||||
* @type string $type
|
||||
* @type string $direction
|
||||
* @type string $radial_direction
|
||||
* @type string $color_start
|
||||
* @type string $color_end
|
||||
* @type string $start_position
|
||||
* @type string $end_position
|
||||
* }
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_gradient_mode_properties( $mode, $props, $base_prop_name, $gradient_properties_desktop = array() ) {
|
||||
$helper = et_builder_get_helper( $mode );
|
||||
|
||||
if ( ! $mode ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Desktop value as default.
|
||||
$gradient_type_desktop = et_()->array_get( $gradient_properties_desktop, 'type', '' );
|
||||
$gradient_direction_desktop = et_()->array_get( $gradient_properties_desktop, 'direction', '' );
|
||||
$gradient_radial_direction_desktop = et_()->array_get( $gradient_properties_desktop, 'radial_direction', '' );
|
||||
$gradient_color_start_desktop = et_()->array_get( $gradient_properties_desktop, 'color_start', '' );
|
||||
$gradient_color_end_desktop = et_()->array_get( $gradient_properties_desktop, 'color_end', '' );
|
||||
$gradient_start_position_desktop = et_()->array_get( $gradient_properties_desktop, 'start_position', '' );
|
||||
$gradient_end_position_desktop = et_()->array_get( $gradient_properties_desktop, 'end_position', '' );
|
||||
$gradient_overlays_image_desktop = et_pb_responsive_options()->get_any_value( $props, "{$base_prop_name}_color_gradient_overlays_image", '', true );
|
||||
|
||||
// Mode value.
|
||||
$gradient_type_mode = $helper->get_raw_value( "{$base_prop_name}_color_gradient_type", $props, $gradient_type_desktop );
|
||||
$gradient_direction_mode = $helper->get_raw_value( "{$base_prop_name}_color_gradient_direction", $props, $gradient_direction_desktop );
|
||||
$gradient_direction_radial_mode = $helper->get_raw_value( "{$base_prop_name}_color_gradient_direction_radial", $props, $gradient_radial_direction_desktop );
|
||||
$gradient_start_mode = $helper->get_raw_value( "{$base_prop_name}_color_gradient_start", $props, $gradient_color_start_desktop );
|
||||
$gradient_end_mode = $helper->get_raw_value( "{$base_prop_name}_color_gradient_end", $props, $gradient_color_end_desktop );
|
||||
$gradient_start_position_mode = $helper->get_raw_value( "{$base_prop_name}_color_gradient_start_position", $props, $gradient_start_position_desktop );
|
||||
$gradient_end_position_mode = $helper->get_raw_value( "{$base_prop_name}_color_gradient_end_position", $props, $gradient_end_position_desktop );
|
||||
$gradient_overlays_image_mode = $helper->get_raw_value( "{$base_prop_name}_color_gradient_overlays_image", $props, $gradient_overlays_image_desktop );
|
||||
|
||||
return array(
|
||||
'type' => '' !== $gradient_type_mode ? $gradient_type_mode : $gradient_type_desktop,
|
||||
'direction' => '' !== $gradient_direction_mode ? $gradient_direction_mode : $gradient_direction_desktop,
|
||||
'radial_direction' => '' !== $gradient_direction_radial_mode ? $gradient_direction_radial_mode : $gradient_radial_direction_desktop,
|
||||
'color_start' => '' !== $gradient_start_mode ? $gradient_start_mode : $gradient_color_start_desktop,
|
||||
'color_end' => '' !== $gradient_end_mode ? $gradient_end_mode : $gradient_color_end_desktop,
|
||||
'start_position' => '' !== $gradient_start_position_mode ? $gradient_start_position_mode : $gradient_start_position_desktop,
|
||||
'end_position' => '' !== $gradient_end_position_mode ? $gradient_end_position_mode : $gradient_end_position_desktop,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get background gradient style based on properties given
|
||||
*
|
||||
* @since 4.3.3
|
||||
*
|
||||
* @param array $args {
|
||||
* @type string $type
|
||||
* @type string $direction
|
||||
* @type string $radial_direction
|
||||
* @type string $color_start
|
||||
* @type string $color_end
|
||||
* @type string $start_position
|
||||
* @type string $end_position
|
||||
* }
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function get_gradient_style( $args ) {
|
||||
$default_gradient = array(
|
||||
'type' => ET_Global_Settings::get_value( 'all_background_gradient_type' ),
|
||||
'direction' => ET_Global_Settings::get_value( 'all_background_gradient_direction' ),
|
||||
'radial_direction' => ET_Global_Settings::get_value( 'all_background_gradient_direction_radial' ),
|
||||
'color_start' => ET_Global_Settings::get_value( 'all_background_gradient_start' ),
|
||||
'color_end' => ET_Global_Settings::get_value( 'all_background_gradient_end' ),
|
||||
'start_position' => ET_Global_Settings::get_value( 'all_background_gradient_start_position' ),
|
||||
'end_position' => ET_Global_Settings::get_value( 'all_background_gradient_end_position' ),
|
||||
);
|
||||
|
||||
$defaults = apply_filters( 'et_pb_default_gradient', $default_gradient );
|
||||
|
||||
$args = wp_parse_args( array_filter( $args ), $defaults );
|
||||
$direction = 'linear' === $args['type'] ? $args['direction'] : "circle at {$args['radial_direction']}";
|
||||
$start_position = et_sanitize_input_unit( $args['start_position'], false, '%' );
|
||||
$end_position = et_sanitize_input_unit( $args['end_position'], false, '%' );
|
||||
|
||||
return esc_html(
|
||||
"{$args['type']}-gradient(
|
||||
{$direction},
|
||||
{$args['color_start']} ${start_position},
|
||||
{$args['color_end']} ${end_position}
|
||||
)"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get individual background image style
|
||||
*
|
||||
* @since 4.3.3
|
||||
*
|
||||
* @param string $attr Background attribute name
|
||||
* @param string $base_prop_name Base background prop name
|
||||
* @param string $suffix Attribute name suffix
|
||||
* @param array $props Module props
|
||||
* @param array $fields_definition Module's fields definition
|
||||
* @param bool $is_prev_image_active Whether previous background image is active or not
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function get_image_style( $attr, $base_prop_name, $suffix = '', $props = array(), $fields_definition = array(), $is_prev_image_active = true ) {
|
||||
// Get default style
|
||||
$default = et_()->array_get( $fields_definition, "{$base_prop_name}_{$attr}.default", '' );
|
||||
|
||||
// Get style
|
||||
$style = et_pb_responsive_options()->get_any_value( $props, "{$base_prop_name}_{$attr}{$suffix}", $default, ! $is_prev_image_active );
|
||||
|
||||
return $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get background UI option's style based on given props and prop name
|
||||
*
|
||||
* @since 4.3.3
|
||||
* @since 4.6.0 Add sticky style support.
|
||||
*
|
||||
* @todo Further simplify this method; Break it down into more encapsulated methods
|
||||
*
|
||||
* @param array $args {
|
||||
* @type string $base_prop_name
|
||||
* @type array $props
|
||||
* @type string $important
|
||||
* @type array $fields_Definition
|
||||
* @type string $selector
|
||||
* @type string $selector_hover
|
||||
* @type string $selector_sticky
|
||||
* @type number $priority
|
||||
* @type string $function_name
|
||||
* @type bool $has_background_color_toggle
|
||||
* @type bool $use_background_color
|
||||
* @type bool $use_background_color_gradient
|
||||
* @type bool $use_background_image
|
||||
* @type bool $use_background_video
|
||||
* @type bool $use_background_color_reset
|
||||
* @type bool $use_background_image_parallax
|
||||
* }
|
||||
*/
|
||||
function get_background_style( $args = array() ) {
|
||||
// Default settings
|
||||
$defaults = array(
|
||||
'base_prop_name' => 'background',
|
||||
'props' => array(),
|
||||
'important' => '',
|
||||
'fields_definition' => array(),
|
||||
'selector' => '',
|
||||
'selector_hover' => '',
|
||||
'selector_sticky' => '',
|
||||
'priority' => '',
|
||||
'function_name' => '',
|
||||
'has_background_color_toggle' => false,
|
||||
'use_background_color' => true,
|
||||
'use_background_color_gradient' => true,
|
||||
'use_background_image' => true,
|
||||
'use_background_video' => true,
|
||||
'use_background_color_reset' => true,
|
||||
'use_background_image_parallax' => true,
|
||||
'prop_name_aliases' => array(),
|
||||
);
|
||||
|
||||
// Parse arguments
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
// Break argument into variables
|
||||
$base_prop_name = $args['base_prop_name'];
|
||||
$props = $args['props'];
|
||||
$important = $args['important'];
|
||||
$fields_definition = $args['fields_definition'];
|
||||
$selector = $args['selector'];
|
||||
$priority = $args['priority'];
|
||||
$function_name = $args['function_name'];
|
||||
|
||||
// Possible values for use_background_* variables are true, false, or 'fields_only'
|
||||
$has_color_toggle_options = $args['has_background_color_toggle'];
|
||||
$use_gradient_options = $args['use_background_color_gradient'];
|
||||
$use_image_options = $args['use_background_image'];
|
||||
$use_color_options = $args['use_background_color'];
|
||||
$use_color_reset_options = $args['use_background_color_reset'];
|
||||
|
||||
// Prop name aliases. Some background element uses different prop name (eg. button background).
|
||||
$prop_name_aliases = $args['prop_name_aliases'];
|
||||
|
||||
// Save processed background. These will be compared with the smaller device background
|
||||
// processed value to avoid rendering the same styles.
|
||||
$processed_color = '';
|
||||
$processed_image = '';
|
||||
$gradient_properties_desktop = array();
|
||||
$processed_image_blend = '';
|
||||
$gradient_overlays_image_desktop = 'off';
|
||||
|
||||
// Store background images status because the process is extensive.
|
||||
$image_status = array(
|
||||
'desktop' => false,
|
||||
'tablet' => false,
|
||||
'phone' => false,
|
||||
);
|
||||
|
||||
// Helper.
|
||||
$responsive = et_pb_responsive_options();
|
||||
|
||||
// Parsed prop name, in case it has aliases.
|
||||
$base_prop_name_parsed = $this->get_prop_name_alias( $prop_name_aliases, $base_prop_name );
|
||||
|
||||
// Background Desktop, Tablet, and Phone.
|
||||
foreach ( $responsive->get_modes() as $device ) {
|
||||
$is_desktop = 'desktop' === $device;
|
||||
$suffix = ! $is_desktop ? "_{$device}" : '';
|
||||
$style = '';
|
||||
|
||||
// Conditionals
|
||||
$has_gradient = false;
|
||||
$has_image = false;
|
||||
$has_gradient_and_image = false;
|
||||
$is_gradient_disabled = false;
|
||||
$is_image_disabled = false;
|
||||
|
||||
// Ensure responsive settings is enabled on mobile.
|
||||
if ( ! $is_desktop && ! $responsive->is_responsive_enabled( $props, $base_prop_name_parsed ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Styles output
|
||||
$image_style = '';
|
||||
$color_style = '';
|
||||
$images = array();
|
||||
$gradient_overlays_image = 'off';
|
||||
|
||||
// A. Background Gradient.
|
||||
if ( $use_gradient_options && 'fields_only' !== $use_gradient_options ) {
|
||||
$use_gradient = $responsive->get_inheritance_background_value(
|
||||
$props,
|
||||
$this->get_prop_name_alias( $prop_name_aliases, "use_{$base_prop_name}_color_gradient" ),
|
||||
$device,
|
||||
$base_prop_name,
|
||||
$fields_definition
|
||||
);
|
||||
|
||||
// 1. Ensure gradient color is active.
|
||||
if ( 'on' === $use_gradient ) {
|
||||
$gradient_overlays_image = $responsive->get_any_value( $props, "{$base_prop_name}_color_gradient_overlays_image{$suffix}", '', true );
|
||||
$gradient_properties = $this->get_gradient_properties( $props, $base_prop_name, $suffix );
|
||||
|
||||
// Will be used as default of Gradient hover.
|
||||
if ( $is_desktop ) {
|
||||
$gradient_properties_desktop = $gradient_properties;
|
||||
$gradient_overlays_image_desktop = $gradient_overlays_image;
|
||||
}
|
||||
|
||||
// Save background gradient into background images list.
|
||||
$background_gradient = $this->get_gradient_style( $gradient_properties );
|
||||
$images[] = $background_gradient;
|
||||
|
||||
// Flag to inform Background Color if current module has Gradient.
|
||||
$has_gradient = true;
|
||||
} elseif ( 'off' === $use_gradient ) {
|
||||
$is_gradient_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// B. Background Image.
|
||||
if ( $use_image_options && 'fields_only' !== $use_image_options ) {
|
||||
$image = $responsive->get_inheritance_background_value( $props, "{$base_prop_name}_image", $device, $base_prop_name, $fields_definition );
|
||||
$parallax = $responsive->get_any_value( $props, "parallax{$suffix}", 'off' );
|
||||
|
||||
// Background image and parallax status.
|
||||
$is_image_active = '' !== $image && 'on' !== $parallax;
|
||||
$image_status[ $device ] = $is_image_active;
|
||||
|
||||
// 1. Ensure image exists and parallax is off.
|
||||
if ( $is_image_active ) {
|
||||
// Flag to inform Background Color if current module has Image.
|
||||
$has_image = true;
|
||||
|
||||
// Check previous Background image status. Needed to get the correct value.
|
||||
$is_prev_image_active = true;
|
||||
|
||||
if ( ! $is_desktop ) {
|
||||
$is_prev_image_active = 'tablet' === $device ?
|
||||
$image_status['desktop'] :
|
||||
$image_status['tablet'];
|
||||
}
|
||||
|
||||
// Size.
|
||||
$image_size = $this->get_image_style( 'size', $base_prop_name, $suffix, $props, $fields_definition, $is_prev_image_active );
|
||||
|
||||
if ( '' !== $image_size ) {
|
||||
$style .= sprintf( 'background-size: %1$s; ', esc_html( $image_size ) );
|
||||
}
|
||||
|
||||
// Position.
|
||||
$image_position = $this->get_image_style( 'position', $base_prop_name, $suffix, $props, $fields_definition, $is_prev_image_active );
|
||||
|
||||
if ( '' !== $image_position ) {
|
||||
$style .= sprintf(
|
||||
'background-position: %1$s; ',
|
||||
esc_html( str_replace( '_', ' ', $image_position ) )
|
||||
);
|
||||
}
|
||||
|
||||
// Repeat.
|
||||
$image_repeat = $this->get_image_style( 'repeat', $base_prop_name, $suffix, $props, $fields_definition, $is_prev_image_active );
|
||||
|
||||
if ( '' !== $image_repeat ) {
|
||||
$style .= sprintf( 'background-repeat: %1$s; ', esc_html( $image_repeat ) );
|
||||
}
|
||||
|
||||
// Blend.
|
||||
$image_blend = $this->get_image_style( 'blend', $base_prop_name, $suffix, $props, $fields_definition, $is_prev_image_active );
|
||||
$image_blend_inherit = $responsive->get_any_value( $props, "{$base_prop_name}_blend{$suffix}", '', true );
|
||||
$image_blend_default = et_()->array_get( $fields_definition, "{$base_prop_name}_blend.default", '' );
|
||||
|
||||
if ( '' !== $image_blend_inherit ) {
|
||||
// Don't print the same image blend style.
|
||||
if ( '' !== $image_blend ) {
|
||||
$style .= sprintf( 'background-blend-mode: %1$s; ', esc_html( $image_blend ) );
|
||||
}
|
||||
|
||||
// Reset - If background has image and gradient, force background-color: initial.
|
||||
if ( $has_gradient && $has_image && $use_color_reset_options !== 'fields_only' && $image_blend_inherit !== $image_blend_default ) {
|
||||
$has_gradient_and_image = true;
|
||||
$color_style = 'initial';
|
||||
|
||||
$style .= sprintf( 'background-color: initial%1$s; ', esc_html( $important ) );
|
||||
}
|
||||
|
||||
$processed_image_blend = $image_blend;
|
||||
}
|
||||
|
||||
// Only append background image when the image is exist.
|
||||
$images[] = sprintf( 'url(%1$s)', esc_html( $image ) );
|
||||
} elseif ( '' === $image ) {
|
||||
// Reset - If background image is disabled, ensure we reset prev background blend mode.
|
||||
if ( '' !== $processed_image_blend ) {
|
||||
$style .= 'background-blend-mode: normal; ';
|
||||
$processed_image_blend = '';
|
||||
}
|
||||
|
||||
$is_image_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $images ) ) {
|
||||
// The browsers stack the images in the opposite order to what you'd expect.
|
||||
if ( 'on' !== $gradient_overlays_image ) {
|
||||
$images = array_reverse( $images );
|
||||
}
|
||||
|
||||
// Set background image styles only it's different compared to the larger device.
|
||||
$image_style = join( ', ', $images );
|
||||
if ( $processed_image !== $image_style ) {
|
||||
$style .= sprintf(
|
||||
'background-image: %1$s%2$s;',
|
||||
esc_html( $image_style ),
|
||||
$important
|
||||
);
|
||||
}
|
||||
} elseif ( ! $is_desktop && $is_gradient_disabled && $is_image_disabled ) {
|
||||
// Reset - If background image and gradient are disabled, reset current background image.
|
||||
$image_style = 'initial';
|
||||
|
||||
$style .= sprintf(
|
||||
'background-image: %1$s%2$s;',
|
||||
esc_html( $image_style ),
|
||||
$important
|
||||
);
|
||||
}
|
||||
|
||||
// Save processed background images.
|
||||
$processed_image = $image_style;
|
||||
|
||||
// C. Background Color.
|
||||
if ( $use_color_options && 'fields_only' !== $use_color_options ) {
|
||||
|
||||
$use_color_value = $responsive->get_any_value( $props, "use_{$base_prop_name}_color{$suffix}", 'on', true );
|
||||
|
||||
if ( ! $has_gradient_and_image && 'off' !== $use_color_value ) {
|
||||
$color = $responsive->get_inheritance_background_value( $props, "{$base_prop_name}_color", $device, $base_prop_name, $fields_definition );
|
||||
$color = ! $is_desktop && '' === $color ? 'initial' : $color;
|
||||
$color_style = $color;
|
||||
|
||||
if ( '' !== $color && $processed_color !== $color ) {
|
||||
$style .= sprintf(
|
||||
'background-color: %1$s%2$s; ',
|
||||
esc_html( $color ),
|
||||
esc_html( $important )
|
||||
);
|
||||
}
|
||||
} elseif ( $has_color_toggle_options && 'off' === $use_color_value && ! $is_desktop ) {
|
||||
// Reset - If current module has background color toggle, it's off, and current mode
|
||||
// it's not desktop, we should reset the background color.
|
||||
$style .= sprintf(
|
||||
'background-color: initial %1$s; ',
|
||||
esc_html( $important )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Save processed background color.
|
||||
$processed_color = $color_style;
|
||||
|
||||
// Render background styles.
|
||||
if ( '' !== $style ) {
|
||||
// Add media query parameter.
|
||||
$background_args = array();
|
||||
if ( ! $is_desktop ) {
|
||||
$current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767';
|
||||
$background_args['media_query'] = ET_Builder_Element::get_media_query( $current_media_query );
|
||||
}
|
||||
|
||||
$el_style = array(
|
||||
'selector' => $selector,
|
||||
'declaration' => rtrim( $style ),
|
||||
'priority' => $priority,
|
||||
);
|
||||
ET_Builder_Element::set_style( $function_name, wp_parse_args( $background_args, $el_style ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Background Modes (Hover & Sticky).
|
||||
$modes = array( 'hover', 'sticky' );
|
||||
|
||||
foreach ( $modes as $mode ) {
|
||||
// Get helper.
|
||||
$helper = et_builder_get_helper( $mode );
|
||||
|
||||
// Bail if no helper.
|
||||
if ( ! $helper ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get selector.
|
||||
$selector_mode = $args[ "selector_{$mode}" ];
|
||||
|
||||
// If no fixed selector defined, prepend / append default selector.
|
||||
if ( '' === $selector_mode ) {
|
||||
if ( 'hover' === $mode ) {
|
||||
$selector_mode = $helper->add_hover_to_selectors( $selector );
|
||||
} elseif ( 'sticky' === $mode ) {
|
||||
$is_sticky_module = $helper->is_sticky_module( $props );
|
||||
$selector_mode = $helper->add_sticky_to_order_class( $selector, $is_sticky_module );
|
||||
}
|
||||
}
|
||||
|
||||
// Check if mode is enabled.
|
||||
if ( $helper->is_enabled( $this->get_prop_name_alias( $prop_name_aliases, $base_prop_name ), $props ) ) {
|
||||
$images_mode = array();
|
||||
$style_mode = '';
|
||||
|
||||
$has_gradient_mode = false;
|
||||
$has_image_mode = false;
|
||||
$has_gradient_and_image_mode = false;
|
||||
$is_gradient_mode_disabled = false;
|
||||
$is_image_mode_disabled = false;
|
||||
|
||||
$gradient_overlays_image_mode = 'off';
|
||||
|
||||
// Background Gradient Mode (Hover / Sticky).
|
||||
// This part is little bit different compared to responsive implementation. In
|
||||
// this case, mode is enabled on the background field, not on the each of those
|
||||
// fields. So, built in function get_value() doesn't work in this case.
|
||||
// Temporarily, we need to fetch the the value from get_raw_value().
|
||||
if ( $use_gradient_options && 'fields_only' !== $use_gradient_options ) {
|
||||
$use_gradient_mode = $responsive->get_inheritance_background_value(
|
||||
$props,
|
||||
$this->get_prop_name_alias( $prop_name_aliases, "use_{$base_prop_name}_color_gradient" ),
|
||||
$mode,
|
||||
$base_prop_name,
|
||||
$fields_definition
|
||||
);
|
||||
|
||||
// 1. Ensure gradient color is active and values are not null.
|
||||
if ( 'on' === $use_gradient_mode ) {
|
||||
// Flag to inform BG Color if current module has Gradient.
|
||||
$has_gradient_mode = true;
|
||||
$gradient_values_mode = $this->get_gradient_mode_properties(
|
||||
$mode,
|
||||
$props,
|
||||
$base_prop_name,
|
||||
$gradient_properties_desktop
|
||||
);
|
||||
$gradient_mode = $this->get_gradient_style( $gradient_values_mode );
|
||||
$images_mode[] = $gradient_mode;
|
||||
|
||||
$gradient_overlays_image_desktop = $responsive->get_any_value(
|
||||
$props,
|
||||
"{$base_prop_name}_color_gradient_overlays_image",
|
||||
'',
|
||||
true
|
||||
);
|
||||
$gradient_overlays_image_mode = $helper->get_raw_value(
|
||||
"{$base_prop_name}_color_gradient_overlays_image",
|
||||
$props,
|
||||
$gradient_overlays_image_desktop
|
||||
);
|
||||
} elseif ( 'off' === $use_gradient_mode ) {
|
||||
$is_gradient_mode_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Background Image Mode (Hover / Sticky).
|
||||
// This part is little bit different compared to responsive implementation. In
|
||||
// this case, mode is enabled on the background field, not on the each of those
|
||||
// fields. So, built in function get_value() doesn't work in this case.
|
||||
// Temporarily, we need to fetch the the value from get_raw_value().
|
||||
if ( $use_image_options && 'fields_only' !== $use_image_options ) {
|
||||
$image_mode = $responsive->get_inheritance_background_value(
|
||||
$props,
|
||||
"{$base_prop_name}_image",
|
||||
$mode,
|
||||
$base_prop_name,
|
||||
$fields_definition
|
||||
);
|
||||
$parallax_mode = $helper->get_raw_value( 'parallax', $props );
|
||||
|
||||
if ( '' !== $image_mode && null !== $image_mode && 'on' !== $parallax_mode ) {
|
||||
// Flag to inform BG Color if current module has Image.
|
||||
$has_image_mode = true;
|
||||
|
||||
// Size.
|
||||
$image_size_mode = $helper->get_raw_value( "{$base_prop_name}_size", $props );
|
||||
$image_size_desktop = et_()->array_get( $props, "{$base_prop_name}_size", '' );
|
||||
$is_same_image_size = $image_size_mode === $image_size_desktop;
|
||||
|
||||
if ( empty( $image_size_mode ) && ! empty( $image_size_desktop ) ) {
|
||||
$image_size_mode = $image_size_desktop;
|
||||
}
|
||||
|
||||
if ( ! empty( $image_size_mode ) && ! $is_same_image_size ) {
|
||||
$style_mode .= sprintf(
|
||||
'background-size: %1$s; ',
|
||||
esc_html( $image_size_mode )
|
||||
);
|
||||
}
|
||||
|
||||
// Position.
|
||||
$image_position_mode = $helper->get_raw_value( "{$base_prop_name}_position", $props );
|
||||
$image_position_desktop = et_()->array_get( $props, "{$base_prop_name}_position", '' );
|
||||
$is_same_image_position = $image_position_mode === $image_position_desktop;
|
||||
|
||||
if ( empty( $image_position_mode ) && ! empty( $image_position_desktop ) ) {
|
||||
$image_position_mode = $image_position_desktop;
|
||||
}
|
||||
|
||||
if ( ! empty( $image_position_mode ) && ! $is_same_image_position ) {
|
||||
$style_mode .= sprintf(
|
||||
'background-position: %1$s; ',
|
||||
esc_html( str_replace( '_', ' ', $image_position_mode ) )
|
||||
);
|
||||
}
|
||||
|
||||
// Repeat.
|
||||
$image_repeat_mode = $helper->get_raw_value( "{$base_prop_name}_repeat", $props );
|
||||
$image_repeat_desktop = et_()->array_get( $props, "{$base_prop_name}_repeat", '' );
|
||||
$is_same_image_repeat = $image_repeat_mode === $image_repeat_desktop;
|
||||
|
||||
if ( empty( $image_repeat_mode ) && ! empty( $image_repeat_desktop ) ) {
|
||||
$image_repeat_mode = $image_repeat_desktop;
|
||||
}
|
||||
|
||||
if ( ! empty( $image_repeat_mode ) && ! $is_same_image_repeat ) {
|
||||
$style_mode .= sprintf(
|
||||
'background-repeat: %1$s; ',
|
||||
esc_html( $image_repeat_mode )
|
||||
);
|
||||
}
|
||||
|
||||
// Blend.
|
||||
$image_blend_mode = $helper->get_raw_value( "{$base_prop_name}_blend", $props );
|
||||
$image_blend_default = et_()->array_get( $fields_definition, "{$base_prop_name}_blend.default", '' );
|
||||
$image_blend_desktop = et_()->array_get( $props, "{$base_prop_name}_blend", '' );
|
||||
$is_same_image_blend = $image_blend_mode === $image_blend_desktop;
|
||||
|
||||
if ( empty( $image_blend_mode ) && ! empty( $image_blend_desktop ) ) {
|
||||
$image_blend_mode = $image_blend_desktop;
|
||||
}
|
||||
|
||||
if ( ! empty( $image_blend_mode ) ) {
|
||||
// Don't print the same background blend.
|
||||
if ( ! $is_same_image_blend ) {
|
||||
$style_mode .= sprintf(
|
||||
'background-blend-mode: %1$s; ',
|
||||
esc_html( $image_blend_mode )
|
||||
);
|
||||
}
|
||||
|
||||
// Force background-color: initial.
|
||||
if ( $has_gradient_mode && $has_image_mode && $image_blend_mode !== $image_blend_default ) {
|
||||
$has_gradient_and_image_mode = true;
|
||||
$style_mode .= sprintf( 'background-color: initial%1$s; ', esc_html( $important ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Only append background image when the image is exist.
|
||||
$images_mode[] = sprintf( 'url(%1$s)', esc_html( $image_mode ) );
|
||||
} elseif ( '' === $image_mode ) {
|
||||
$is_image_mode_disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $images_mode ) ) {
|
||||
// The browsers stack the images in the opposite order to what you'd expect.
|
||||
if ( 'on' !== $gradient_overlays_image_mode ) {
|
||||
$images_mode = array_reverse( $images_mode );
|
||||
}
|
||||
|
||||
$style_mode .= sprintf(
|
||||
'background-image: %1$s%2$s;',
|
||||
esc_html( join( ', ', $images_mode ) ),
|
||||
$important
|
||||
);
|
||||
} elseif ( $is_gradient_mode_disabled && $is_image_mode_disabled ) {
|
||||
$style_mode .= sprintf(
|
||||
'background-image: initial %1$s;',
|
||||
$important
|
||||
);
|
||||
}
|
||||
|
||||
// Background Color Mode (Hover / Sticky).
|
||||
if ( $use_color_options && 'fields_only' !== $use_color_options ) {
|
||||
$use_color_mode_value = $helper->get_raw_value( "use_{$base_prop_name}_color", $props );
|
||||
$use_color_mode_value = ! empty( $use_color_mode_value ) ?
|
||||
$use_color_mode_value :
|
||||
et_()->array_get( $props, "use_{$base_prop_name}_color", 'on' );
|
||||
|
||||
if ( ! $has_gradient_and_image_mode && 'off' !== $use_color_mode_value ) {
|
||||
$color_mode = $responsive->get_inheritance_background_value(
|
||||
$props,
|
||||
"{$base_prop_name}_color",
|
||||
$mode,
|
||||
$base_prop_name,
|
||||
$fields_definition
|
||||
);
|
||||
$color_mode = '' !== $color_mode ? $color_mode : 'transparent';
|
||||
|
||||
if ( '' !== $color_mode ) {
|
||||
$style_mode .= sprintf(
|
||||
'background-color: %1$s%2$s; ',
|
||||
esc_html( $color_mode ),
|
||||
esc_html( $important )
|
||||
);
|
||||
}
|
||||
} elseif ( $has_color_toggle_options && 'off' === $use_color_mode_value ) {
|
||||
// Reset - If current module has background color toggle, it's off, and current mode
|
||||
// it's not desktop, we should reset the background color.
|
||||
$style .= sprintf(
|
||||
'background-color: initial %1$s; ',
|
||||
esc_html( $important )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Render background mode styles.
|
||||
if ( '' !== $style_mode ) {
|
||||
$el_style = array(
|
||||
'selector' => $selector_mode,
|
||||
'declaration' => rtrim( $style_mode ),
|
||||
'priority' => $priority,
|
||||
);
|
||||
ET_Builder_Element::set_style( $function_name, $el_style );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
138
includes/builder/module/helpers/BackgroundLayout.php
Normal file
138
includes/builder/module/helpers/BackgroundLayout.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
// Include dependency for ResponsiveOptions.
|
||||
if ( ! function_exists( 'et_pb_responsive_options' ) ) {
|
||||
require_once 'ResponsiveOptions.php';
|
||||
}
|
||||
|
||||
// Include dependency for HoverOptions.
|
||||
if ( ! function_exists( 'et_pb_hover_options' ) ) {
|
||||
require_once 'HoverOptions.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Background layout helper methods.
|
||||
*
|
||||
* @since 4.0.7
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_BackgroundLayout
|
||||
*/
|
||||
class ET_Builder_Module_Helper_BackgroundLayout {
|
||||
|
||||
public static function instance() {
|
||||
static $instance;
|
||||
|
||||
return $instance ? $instance : $instance = new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get background layout class names.
|
||||
*
|
||||
* @since 4.0.7
|
||||
*
|
||||
* @param array $attrs
|
||||
* @param boolean $is_skip_desktop Not all modules need to print desktop background layout.
|
||||
* @param boolean $is_text_color Not all modules need text color layout class name.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_background_layout_class( $attrs, $is_skip_desktop = false, $is_text_color = false ) {
|
||||
// Background layout values.
|
||||
$background_layouts = et_pb_responsive_options()->get_property_values( $attrs, 'background_layout' );
|
||||
$background_layout = et_()->array_get( $background_layouts, 'desktop', '' );
|
||||
$background_layout_tablet = et_()->array_get( $background_layouts, 'tablet', '' );
|
||||
$background_layout_phone = et_()->array_get( $background_layouts, 'phone', '' );
|
||||
$background_layout_hover = et_pb_hover_options()->get_value( 'background_layout', $attrs, 'light' );
|
||||
|
||||
// Background layout class names.
|
||||
$background_layout_class_names = ! $is_skip_desktop ? array( "et_pb_bg_layout_{$background_layout}" ) : array();
|
||||
|
||||
if ( ! empty( $background_layout_tablet ) ) {
|
||||
$background_layout_class_names[] = "et_pb_bg_layout_{$background_layout_tablet}_tablet";
|
||||
}
|
||||
|
||||
if ( ! empty( $background_layout_phone ) ) {
|
||||
$background_layout_class_names[] = "et_pb_bg_layout_{$background_layout_phone}_phone";
|
||||
}
|
||||
|
||||
// Text color class names.
|
||||
if ( $is_text_color ) {
|
||||
if ( 'light' === $background_layout ) {
|
||||
$background_layout_class_names[] = 'et_pb_text_color_dark';
|
||||
}
|
||||
|
||||
if ( 'light' === $background_layout_tablet ) {
|
||||
$background_layout_class_names[] = 'et_pb_text_color_dark_tablet';
|
||||
}
|
||||
|
||||
if ( 'light' === $background_layout_phone ) {
|
||||
$background_layout_class_names[] = 'et_pb_text_color_dark_phone';
|
||||
}
|
||||
}
|
||||
|
||||
return $background_layout_class_names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get background layout data attributes.
|
||||
*
|
||||
* @since 4.0.7
|
||||
*
|
||||
* @param array $attrs
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_background_layout_attrs( $attrs ) {
|
||||
// Background layout data attributes is only needed by hover or sticky effect.
|
||||
if ( ! et_pb_hover_options()->is_enabled( 'background_layout', $attrs ) && ! et_pb_sticky_options()->is_enabled( 'background_layout', $attrs ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Background layout values.
|
||||
$background_layouts = et_pb_responsive_options()->get_property_values( $attrs, 'background_layout' );
|
||||
$background_layout = et_()->array_get( $background_layouts, 'desktop', '' );
|
||||
$background_layout_tablet = et_()->array_get( $background_layouts, 'tablet', '' );
|
||||
$background_layout_phone = et_()->array_get( $background_layouts, 'phone', '' );
|
||||
$background_layout_hover = et_pb_hover_options()->get_value( 'background_layout', $attrs, '' );
|
||||
$background_layout_sticky = et_pb_sticky_options()->get_value( 'background_layout', $attrs, '' );
|
||||
|
||||
$data_background_layout = sprintf(
|
||||
' data-background-layout="%1$s"',
|
||||
esc_attr( $background_layout )
|
||||
);
|
||||
|
||||
if ( ! empty( $background_layout_hover ) ) {
|
||||
$data_background_layout .= sprintf(
|
||||
' data-background-layout-hover="%1$s"',
|
||||
esc_attr( $background_layout_hover )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! empty( $background_layout_sticky ) ) {
|
||||
$data_background_layout .= sprintf(
|
||||
' data-background-layout-sticky="%1$s"',
|
||||
esc_attr( $background_layout_sticky )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! empty( $background_layout_tablet ) ) {
|
||||
$data_background_layout .= sprintf(
|
||||
' data-background-layout-tablet="%1$s"',
|
||||
esc_attr( $background_layout_tablet )
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! empty( $background_layout_phone ) ) {
|
||||
$data_background_layout .= sprintf(
|
||||
' data-background-layout-phone="%1$s"',
|
||||
esc_attr( $background_layout_phone )
|
||||
);
|
||||
}
|
||||
|
||||
return $data_background_layout;
|
||||
}
|
||||
}
|
158
includes/builder/module/helpers/Font.php
Normal file
158
includes/builder/module/helpers/Font.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
// Include dependency for ResponsiveOptions.
|
||||
if ( ! function_exists( 'et_pb_responsive_options' ) ) {
|
||||
require_once 'ResponsiveOptions.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Font helper methods.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Font
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Font {
|
||||
|
||||
public static function instance() {
|
||||
static $instance;
|
||||
|
||||
return $instance ? $instance : $instance = new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current font is Default or not.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @param array $attrs
|
||||
* @param string $name
|
||||
* @param string $device
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_font_default( $attrs, $name, $device = 'desktop' ) {
|
||||
return 'Default' === $this->get_font_value( $attrs, $name, $device );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current font is empty or not.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @param array $attrs
|
||||
* @param string $name
|
||||
* @param string $device
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_font_empty( $attrs, $name, $device = 'desktop' ) {
|
||||
return '' === $this->get_font_value( $attrs, $name, $device );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font value based on device.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @param array $attrs
|
||||
* @param string $name
|
||||
* @param string $device
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_font_value( $attrs, $name, $device = 'desktop' ) {
|
||||
$value = et_pb_responsive_options()->get_property_value( $attrs, $name, '', $device, true );
|
||||
$value_pieces = ! empty( $value ) && is_string( $value ) ? explode( '|', $value ) : array();
|
||||
return et_()->array_get( $value_pieces, 0, '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom breakpoint by font value.
|
||||
*
|
||||
* There is a case where tablet and phone use Default font. Default font means the element will
|
||||
* use the original or font defined on Theme Customizer. It's different with empty string which
|
||||
* means the font will be inherited from the larger device. So, when current device use non
|
||||
* default font, we should check smaller device uses default font or not. If the smaller device
|
||||
* use default font, we have to render current font inclusidely on current device, something
|
||||
* likes desktop_only, tablet_only, or desktop_tablet_only.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @param array $attrs
|
||||
* @param string $name
|
||||
* @param string $device
|
||||
* @param string $default_breakpoint
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_breakpoint_by_font_value( $attrs, $name, $device = 'desktop', $default_breakpoint = '' ) {
|
||||
// Bail early if current $device value is default or empty.
|
||||
if ( $this->is_font_default( $attrs, $name, $device ) || $this->is_font_empty( $attrs, $name, $device ) ) {
|
||||
return $default_breakpoint;
|
||||
}
|
||||
|
||||
// Phone - There is no smaller $device than phone, no need to check.
|
||||
if ( 'phone' === $device ) {
|
||||
return $default_breakpoint;
|
||||
}
|
||||
|
||||
$is_phone_default = $this->is_font_default( $attrs, $name, 'phone' );
|
||||
$is_tablet_default = $this->is_font_default( $attrs, $name, 'tablet' );
|
||||
|
||||
// Tablet.
|
||||
if ( 'tablet' === $device ) {
|
||||
// Return breakpoint for tablet only if phone uses default, otherwise return default.
|
||||
return $is_phone_default ? et_pb_responsive_options()->get_breakpoint_by_device( 'tablet_only' ) : $default_breakpoint;
|
||||
}
|
||||
|
||||
// Desktop.
|
||||
if ( $is_tablet_default ) {
|
||||
// Return breakpoint for desktop only if tablet uses default.
|
||||
return et_pb_responsive_options()->get_breakpoint_by_device( 'desktop_only' );
|
||||
} elseif ( $is_phone_default ) {
|
||||
// Return breakpoint for desktop & only if tablet uses default.
|
||||
return et_pb_responsive_options()->get_breakpoint_by_device( 'desktop_tablet_only' );
|
||||
}
|
||||
|
||||
return $default_breakpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get font selector based on settings.
|
||||
*
|
||||
* @since 4.0
|
||||
*
|
||||
* @param array $option_settings
|
||||
* @param string $main_css_element
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_font_selector( $option_settings, $main_css_element ) {
|
||||
// Get main CSS selector.
|
||||
$main_selector = et_()->array_get( $option_settings, 'css.main', $main_css_element );
|
||||
$limited_main_selector = et_()->array_get( $option_settings, 'css.limited_main', '' );
|
||||
$font_selector = et_()->array_get( $option_settings, 'css.font', '' );
|
||||
|
||||
// Use different selector for plugin if defined.
|
||||
if ( et_builder_has_limitation( 'use_limited_main' ) && ! empty( $limited_main_selector ) ) {
|
||||
$main_selector = $limited_main_selector;
|
||||
}
|
||||
|
||||
// Use font selector if it's specified
|
||||
if ( ! empty( $font_selector ) ) {
|
||||
$main_selector = $font_selector;
|
||||
}
|
||||
|
||||
// Join all the main selectors if it's an array.
|
||||
if ( is_array( $main_selector ) ) {
|
||||
$main_selector = implode( ', ', $main_selector );
|
||||
}
|
||||
|
||||
return $main_selector;
|
||||
}
|
||||
}
|
13
includes/builder/module/helpers/Height.php
Normal file
13
includes/builder/module/helpers/Height.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Helper class that provides necessary functions for managing height option
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Height
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Height extends ET_Builder_Module_Helper_Sizing {
|
||||
|
||||
public function get_raw_field() {
|
||||
return 'height';
|
||||
}
|
||||
}
|
217
includes/builder/module/helpers/HoverOptions.php
Normal file
217
includes/builder/module/helpers/HoverOptions.php
Normal file
@ -0,0 +1,217 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Hover Options helper methods
|
||||
*
|
||||
* Class ET_Builder_Module_Hover_Options
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Hover_Options {
|
||||
|
||||
private static $instance;
|
||||
|
||||
public static function get() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new ET_Builder_Module_Helper_Hover_Options();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
private function util_get( $key, $list, $default = null ) {
|
||||
return ET_Core_Data_Utils::instance()->array_get( $list, $key, $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `__hover`
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_suffix() {
|
||||
return '__hover';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `__hover_enabled`
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_enabled_suffix() {
|
||||
return '__hover_enabled';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field original name by removing the `__hover` or `__hover_enabled` suffix if it exists.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_field_base_name( $name ) {
|
||||
// Do not use rtim as it removes by character not by string
|
||||
// So cases like `key__hoveree` will be reduced to `key`
|
||||
$regex = "/(.*)({$this->get_suffix()}|{$this->get_enabled_suffix()})$/";
|
||||
$replace = '${1}';
|
||||
|
||||
return preg_replace( $regex, $replace, $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the setting has enabled hover options
|
||||
*
|
||||
* @param string $setting
|
||||
* @param array $attrs
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_enabled( $setting, $attrs ) {
|
||||
$name = in_array( $setting, [ 'background_color', 'background_image' ], true ) ? 'background' : $setting;
|
||||
|
||||
$field = $this->get_hover_enabled_field( $name );
|
||||
|
||||
$value = ! empty( $attrs[ $field ] ) ? $attrs[ $field ] : '';
|
||||
|
||||
$result = ! empty( $value ) && strpos( $value, 'on' ) === 0;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if hover settings are enabled on one of the options list.
|
||||
*
|
||||
* @since 4.5.1
|
||||
*
|
||||
* @param array $attrs All module attributes.
|
||||
* @param array $list Options list.
|
||||
* @return boolean Hover settings status.
|
||||
*/
|
||||
public function is_any_hover_enabled( $attrs, $list ) {
|
||||
// Ensure list is not empty and valid array.
|
||||
if ( empty( $list ) || ! is_array( $list ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the hover status one by one.
|
||||
$is_any_hover_enabled = false;
|
||||
foreach ( $list as $name ) {
|
||||
if ( $this->is_enabled( $name, $attrs ) ) {
|
||||
$is_any_hover_enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $is_any_hover_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hover setting field name
|
||||
* E.g.: get_hover_enabled_field('test') => 'test__hover'
|
||||
*
|
||||
* @param string $setting
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_hover_field( $setting ) {
|
||||
return "{$this->get_field_base_name($setting)}{$this->get_suffix()}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hover enabled setting field name
|
||||
* E.g.: get_hover_enabled_field('test') => 'test__hover_enabled'
|
||||
*
|
||||
* @param string $setting
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_hover_enabled_field( $setting ) {
|
||||
return "{$this->get_field_base_name($setting)}{$this->get_enabled_suffix()}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns setting hover value if hover is enabled;
|
||||
* If it does not exist, return $default specified value
|
||||
*
|
||||
* @param string $setting
|
||||
* @param array $attrs
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_value( $setting, $attrs, $default = null ) {
|
||||
return $this->is_enabled( $setting, $attrs )
|
||||
? $this->get_raw_value( $setting, $attrs, $default )
|
||||
: $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns setting hover value if hover is enabled for a compose option;
|
||||
* If it does not exist, return $default specified value
|
||||
*
|
||||
* @param string $setting
|
||||
* @param string $option
|
||||
* @param array $attrs
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_compose_value( $setting, $option, $attrs, $default = null ) {
|
||||
return $this->is_enabled( $option, $attrs )
|
||||
? $this->get_raw_value( $setting, $attrs, $default )
|
||||
: $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns setting hover value;
|
||||
* If it does not exist, return $default specified value
|
||||
*
|
||||
* @param string $setting
|
||||
* @param array $attrs
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_raw_value( $setting, $attrs, $default = null ) {
|
||||
return $this->util_get( $this->get_hover_field( $setting ), $attrs, $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds `:hover` in selector at the end of the selector
|
||||
* E.g: add_hover_to_selectors('%%order_class%%% .image') >>> '%%order_class%%% .image:hover'
|
||||
*
|
||||
* @since 4.6.0 moved the order of `-` in capturing group 4's character set so it captures
|
||||
* `::-` prefixed pseudo selector like `::-moz-placeholder` correctly
|
||||
*
|
||||
* @param string $selector
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function add_hover_to_selectors( $selector ) {
|
||||
$selectors = explode( ',', $selector );
|
||||
$selectors = array_map( 'trim', $selectors );
|
||||
// Add hover to the end of the selector, but prevent specific situations like this:
|
||||
// .my-class:after => .my-class:after:hover, should be .my-class:hover:after
|
||||
$selectors = preg_replace( '/(.+\s)*([^\::?]+)((::?[-|a-z|\(|\)|\[|\]]+)+)?$/i', '$1$2:hover$3', $selectors );
|
||||
|
||||
return implode( ', ', $selectors );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds `:hover` in selector after `%%order_class%%`
|
||||
* E.g: add_hover_to_order_class('%%order_class%%% .image') >>> '%%order_class%%%:hover .image'
|
||||
*
|
||||
* @param string $selector
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function add_hover_to_order_class( $selector ) {
|
||||
$selectors = explode( ',', $selector );
|
||||
$selectors = array_map( 'trim', $selectors );
|
||||
// Add hover to the end of the selector, but prevent specific situations like this:
|
||||
// .my-class:after => .my-class:after:hover, should be .my-class:hover:after
|
||||
$selectors = preg_replace( '/(.*%%order_class%%[^\s|^:]*)(.*)/i', '$1:hover$2', $selectors );
|
||||
|
||||
return implode( ', ', $selectors );
|
||||
}
|
||||
}
|
||||
|
14
includes/builder/module/helpers/MaxHeight.php
Normal file
14
includes/builder/module/helpers/MaxHeight.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Helper class that provides necessary functions for managing max height option
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Max_Height
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Max_Height extends ET_Builder_Module_Helper_Sizing {
|
||||
|
||||
public function get_raw_field() {
|
||||
return 'max_height';
|
||||
}
|
||||
}
|
||||
|
14
includes/builder/module/helpers/MaxWidth.php
Normal file
14
includes/builder/module/helpers/MaxWidth.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Helper class that provides necessary functions for managing max width option
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Max_Width
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Max_Width extends ET_Builder_Module_Helper_Sizing {
|
||||
|
||||
public function get_raw_field() {
|
||||
return 'max_width';
|
||||
}
|
||||
}
|
||||
|
65
includes/builder/module/helpers/Media.php
Normal file
65
includes/builder/module/helpers/Media.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* ET_Builder_Module_Helper_Media class file.
|
||||
*
|
||||
* @class ET_Builder_Module_Helper_Media
|
||||
* @package Divi\Builder
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class ET_Builder_Module_Helper_Media.
|
||||
*
|
||||
* Module helpers for media (image).
|
||||
*
|
||||
* @since 4.6.4
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Media {
|
||||
/**
|
||||
* Return instance of current class.
|
||||
*
|
||||
* @return ET_Builder_Module_Helper_Media
|
||||
*/
|
||||
public static function instance() {
|
||||
static $instance;
|
||||
|
||||
return $instance ? $instance : $instance = new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image attachment class.
|
||||
*
|
||||
* - wp-image-{$id}
|
||||
* Add `wp-image-{$id}` class to let `wp_filter_content_tags()` fill in missing
|
||||
* height and width attributes on the image. Those attributes are required to add
|
||||
* loading "lazy" attribute on the image. WP doesn't have specific method to only
|
||||
* generate this class. It's included in get_image_tag() to generate image tags.
|
||||
*
|
||||
* @since 4.6.4
|
||||
*
|
||||
* @param array $attrs All module attributes.
|
||||
* @param string $source_key Key of image source.
|
||||
* @param integer $attachment_id Attachment ID. Optional.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_image_attachment_class( $attrs, $source_key, $attachment_id = 0 ) {
|
||||
$attachment_class = '';
|
||||
|
||||
// 1.a. Find attachment ID by URL. Skip if the source key is empty.
|
||||
if ( ! empty( $source_key ) ) {
|
||||
$attachment_src = et_()->array_get( $attrs, $source_key, '' );
|
||||
$attachment_id = et_get_attachment_id_by_url( $attachment_src );
|
||||
}
|
||||
|
||||
// 1.b. Generate attachment ID class.
|
||||
if ( $attachment_id > 0 ) {
|
||||
$attachment_class = "wp-image-{$attachment_id}";
|
||||
}
|
||||
|
||||
return $attachment_class;
|
||||
}
|
||||
}
|
14
includes/builder/module/helpers/MinHeight.php
Normal file
14
includes/builder/module/helpers/MinHeight.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Helper class that provides necessary functions for managing max height option
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Min_Height
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Min_Height extends ET_Builder_Module_Helper_Sizing {
|
||||
|
||||
public function get_raw_field() {
|
||||
return 'min_height';
|
||||
}
|
||||
}
|
||||
|
124
includes/builder/module/helpers/MultiValue.php
Normal file
124
includes/builder/module/helpers/MultiValue.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
class ET_Builder_Module_Helper_Multi_Value {
|
||||
private static $instance;
|
||||
|
||||
public static function instance() {
|
||||
return self::$instance ? self::$instance : ( self::$instance = new self() );
|
||||
}
|
||||
|
||||
public function get_delimiter() {
|
||||
return '|';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an array and transforms it in an valid multi value array
|
||||
*
|
||||
* @param array $value
|
||||
* @param int $elements
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parse( array $value, $elements = null ) {
|
||||
$length = (int) $elements;
|
||||
|
||||
if ( ! $elements || count( $value ) === (int) $length ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$new = array();
|
||||
|
||||
for ( $i = 0; $i < (int) $length; $i ++ ) {
|
||||
$new[ $i ] = isset( $value[ $i ] ) && $value[ $i ] !== null ? $value[ $i ] : '';
|
||||
}
|
||||
|
||||
return array_map( 'strval', $new );
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the multi value string in to an array of primitive values
|
||||
* User can provide also the required number of elements that value must have
|
||||
* In case the array original length will be larger then the required elements number
|
||||
* the array will be cut from head to tail
|
||||
* In cas the array length will be shorter, the array tail will be filled with empty strings `''`,
|
||||
* till array length will match the requested elements number
|
||||
*
|
||||
* @param string $value
|
||||
* @param int $elements
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function split( $value, $elements = null ) {
|
||||
return $this->parse( explode( $this->get_delimiter(), $value ), $elements );
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an array and converts it to a valid multi value
|
||||
* Provide the `elements` parameter to get the result string of the necessary length
|
||||
*
|
||||
* @param array $value
|
||||
* @param int $elements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function to_value( array $value, $elements = null ) {
|
||||
return implode( $this->get_delimiter(), $this->parse( $value, $elements ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the multi value is not empty.
|
||||
* A multi value is empty when all sub values are empty strings
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_value( $value ) {
|
||||
return trim( implode( '', $this->split( $value ) ) ) !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two multi values in to one.
|
||||
* If value1 nth element is empty, value2 nth element will be used
|
||||
*
|
||||
* @param $value_1
|
||||
* @param $value_2
|
||||
* @param int $elements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function merge( $value_1, $value_2, $elements = null ) {
|
||||
$v1 = $this->split( $value_1, $elements );
|
||||
$v2 = $this->split( $value_2, $elements );
|
||||
$max = max( count( $v1 ), count( $v2 ) );
|
||||
$new = array();
|
||||
|
||||
for ( $i = 0; $i < $max; $i ++ ) {
|
||||
$new[ $i ] = ! isset( $v1[ $i ] ) ? $v2[ $i ] : et_builder_get_or( $v1[ $i ], $v2[ $i ] );
|
||||
}
|
||||
|
||||
return $this->to_value( $new, $elements );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value at specific position in provided multiValue.
|
||||
*
|
||||
* @param int $key
|
||||
* @param string $value
|
||||
* @param string $motion_value
|
||||
* @param int $elements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function set( $key, $value, $motion_value, $elements = null ) {
|
||||
$arr = $this->split( $motion_value, $elements );
|
||||
|
||||
if ( ! isset( $arr[ $key ] ) ) {
|
||||
return $motion_value;
|
||||
}
|
||||
|
||||
$arr[ $key ] = $value;
|
||||
|
||||
return implode( $this->get_delimiter(), $arr );
|
||||
}
|
||||
}
|
2192
includes/builder/module/helpers/MultiViewOptions.php
Normal file
2192
includes/builder/module/helpers/MultiViewOptions.php
Normal file
File diff suppressed because it is too large
Load Diff
731
includes/builder/module/helpers/OptionTemplate.php
Normal file
731
includes/builder/module/helpers/OptionTemplate.php
Normal file
@ -0,0 +1,731 @@
|
||||
<?php
|
||||
/**
|
||||
* Option Templates helper methods.
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_OptionTemplate
|
||||
*/
|
||||
class ET_Builder_Module_Helper_OptionTemplate {
|
||||
|
||||
private $map = array();
|
||||
private $templates = array();
|
||||
private $data = array();
|
||||
private $cache = array();
|
||||
private $tab_slug_map = array();
|
||||
|
||||
public $template_prefix = '%t';
|
||||
|
||||
protected static $_ = null;
|
||||
|
||||
public static function instance() {
|
||||
static $instance;
|
||||
|
||||
return $instance ? $instance : $instance = new self();
|
||||
}
|
||||
|
||||
private function __construct() {
|
||||
self::$_ = ET_Core_Data_Utils::instance();
|
||||
}
|
||||
|
||||
private function uniq( $prefix, $content ) {
|
||||
$key = md5( $prefix . serialize( $content ) );
|
||||
if ( isset( $this->map[ $key ] ) ) {
|
||||
return $this->map[ $key ];
|
||||
}
|
||||
|
||||
return ( $this->map[ $key ] = $this->template_prefix . $key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether option template is enabled on current request or not
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_enabled() {
|
||||
// Option template tends to be enabled on most request to speed up performance
|
||||
$status = true;
|
||||
|
||||
// Option template is disabled on:
|
||||
// 1. AJAX request for fetching classic builder (BB)'s module data. BB data is shipped as
|
||||
// optimized template markup which is rendered on server then sent as string. Hence
|
||||
// Option Template's sent-config-rebuild-on-js won't be usable for BB
|
||||
// 2. BB's editing page. BB edit page scans for field dependency and generates visibility
|
||||
// setting on `window.et_pb_module_field_dependencies` variable for field depency thus
|
||||
// actual field should be rendered here instead of templateId
|
||||
if ( et_builder_is_loading_bb_data() || et_builder_is_bb_page() ) {
|
||||
$status = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters option template status
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @param bool $status
|
||||
*/
|
||||
return apply_filters( 'et_builder_option_template_is_active', $status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether given field name is option template field based on its first two characters
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_option_template_field( $field_name = '' ) {
|
||||
return $this->template_prefix === substr( $field_name, 0, 2 );
|
||||
}
|
||||
|
||||
public function has( $key ) {
|
||||
return isset( $this->templates[ $key ] );
|
||||
}
|
||||
|
||||
public function add( $key, $template ) {
|
||||
$fields_template = array_merge( $template, et_pb_responsive_options()->create( $template ) );
|
||||
|
||||
// Populate tab_slug of given template because advance fields can be rendered on any tab
|
||||
foreach ( $fields_template as $field_name => $field ) {
|
||||
if ( isset( $field['tab_slug'] ) ) {
|
||||
$tab_slug = '' === $field['tab_slug'] ? 'advanced' : $field['tab_slug'];
|
||||
|
||||
if ( ! isset( $this->tab_slug_map[ $tab_slug ] ) ) {
|
||||
$this->tab_slug_map[ $tab_slug ] = array( $key );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! in_array( $key, $this->tab_slug_map[ $tab_slug ] ) ) {
|
||||
$this->tab_slug_map[ $tab_slug ][] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->templates[ $key ] = $fields_template;
|
||||
}
|
||||
|
||||
public function create( $key, $config, $return_template_id = false ) {
|
||||
$data = array( $key, $config );
|
||||
$id = $this->uniq( $key, $data );
|
||||
// Alternative, this will save the values directly in the Module $this->unprocessed_fields
|
||||
// instead of this Calls $this->data and hence require a simpler logic.
|
||||
// Theoretically it should require more memory but blackfire begs to differ.
|
||||
$this->data[ $id ] = $data;
|
||||
|
||||
// Return as template id instead of id => key if needed
|
||||
if ( $return_template_id ) {
|
||||
return $id;
|
||||
}
|
||||
|
||||
return array( $id => $key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create placeholders for template's params
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function placeholders( $config, $idx = 1, $path = array() ) {
|
||||
$placeholders = array();
|
||||
foreach ( $config as $key => $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
// Prepend current key as path so placeholder later can correctly fetch correct
|
||||
// value from template data using dot notation path (both lodash get() or utils's
|
||||
// array_get() support this).
|
||||
$path[] = $key;
|
||||
|
||||
$value = $this->placeholders( $value, $idx, $path );
|
||||
} else {
|
||||
// Prepend dot notation path as prefix if needed
|
||||
$prefix = empty( $path ) ? '' : implode( '.', $path ) . '.';
|
||||
|
||||
$value = "%%{$prefix}{$key}%%";
|
||||
}
|
||||
$placeholders[ $key ] = $value;
|
||||
$idx++;
|
||||
}
|
||||
return $placeholders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get module's data
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function all() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get templates
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function templates() {
|
||||
return $this->templates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set `$this->data` property from external source (ie: static field definition cache).
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @param array $cached_data
|
||||
*/
|
||||
public function set_data( $cached_data = array() ) {
|
||||
$this->data = wp_parse_args(
|
||||
$cached_data,
|
||||
$this->data
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set `$this->templates` property from external source (ie: static field definition cache).
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @param array $cached_template
|
||||
*/
|
||||
public function set_templates( $cached_templates = array() ) {
|
||||
$this->templates = wp_parse_args(
|
||||
$cached_templates,
|
||||
$this->templates
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set `$this->tab_slug_map` from external source (ie: static field definition cache).
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param array $cached_tab_slug_map
|
||||
*/
|
||||
public function set_tab_slug_map( $cached_tab_slug_map = array() ) {
|
||||
$this->tab_slug_map = wp_parse_args(
|
||||
$cached_tab_slug_map,
|
||||
$this->tab_slug_map
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get template data based on given template id
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @param string $template_id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_data( $template_id = '' ) {
|
||||
return isset( $this->data[ $template_id ] ) ? $this->data[ $template_id ] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get template based on given template type
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_template( $type = '' ) {
|
||||
return isset( $this->templates[ $type ] ) ? $this->templates[ $type ] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hashed cache key based on params given
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @param mixed $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_cache_key( $params ) {
|
||||
$params = is_string( $params ) ? $params : serialize( $params );
|
||||
|
||||
return md5( $params );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached value
|
||||
* Return null if no cached value found
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_cache( $name, $key ) {
|
||||
if (
|
||||
! empty( $this->cache )
|
||||
&& ! empty( $this->cache[ $name ] )
|
||||
&& ! empty( $this->cache[ $name ][ $key ] )
|
||||
) {
|
||||
return $this->cache[ $name ][ $key ];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value to be cached
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_cache( $name, $key, $value ) {
|
||||
self::$_->array_set( $this->cache, "{$name}.{$key}", $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get placeholder of given template
|
||||
*
|
||||
* @since 3.28
|
||||
*
|
||||
* @param string $template
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function get_template_placeholder( $template ) {
|
||||
// Check for cached result first for faster performance
|
||||
$cache_name = 'template_placeholder';
|
||||
$cache_key = $this->get_cache_key( $template );
|
||||
$cache = $this->get_cache( $cache_name, $cache_key );
|
||||
|
||||
if ( ! is_null( $cache ) ) {
|
||||
return $cache;
|
||||
}
|
||||
|
||||
preg_match( '/(?<=%%).*(?=%%)/', $template, $placeholder );
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $placeholder );
|
||||
|
||||
return $placeholder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tab slug maps
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_tab_slug_map() {
|
||||
return $this->tab_slug_map;
|
||||
}
|
||||
|
||||
public function is_template_inside_tab( $tab_name, $template_type ) {
|
||||
// Template which has `%%tab_slug%%` tab_slug can exist on any tab
|
||||
if ( in_array( $template_type, self::$_->array_get( $this->tab_slug_map, '%%tab_slug%%', array() ) ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( in_array( $template_type, self::$_->array_get( $this->tab_slug_map, $tab_name, array() ) ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function rebuild_string_placeholder( $template, $data = array(), $settings = array() ) {
|
||||
// Placeholder settings
|
||||
$default_settings = array(
|
||||
'suffix' => '',
|
||||
'remove_suffix_if_empty' => false,
|
||||
);
|
||||
|
||||
$placeholder_settings = wp_parse_args( $settings, $default_settings );
|
||||
|
||||
// Check for cached result first for faster performance
|
||||
$cache_name = 'string_placeholder';
|
||||
$cache_key = $this->get_cache_key( array( $template, $data, $placeholder_settings ) );
|
||||
$cache = $this->get_cache( $cache_name, $cache_key );
|
||||
|
||||
if ( ! is_null( $cache ) ) {
|
||||
return $cache;
|
||||
}
|
||||
|
||||
// Get placeholder
|
||||
$placeholder = is_string( $template ) ? $this->get_template_placeholder( $template ) : false;
|
||||
|
||||
// If found, replace placeholder with correct value from data
|
||||
if ( is_array( $placeholder ) && isset( $placeholder[0] ) ) {
|
||||
// Get placeholder replacement
|
||||
$replacement = ! empty( $data[1] ) && ! empty( $data[1][ $placeholder[0] ] ) ? $data[1][ $placeholder[0] ] : '';
|
||||
|
||||
// Pass null as empty string; null as attribute affect builder differently.
|
||||
// Attribute with empty string will be omitted later.
|
||||
if ( is_null( $replacement ) ) {
|
||||
$replacement = '';
|
||||
}
|
||||
|
||||
// If placeholder is identical to template, return replacement early. This also
|
||||
// handles the case where replacement as array type
|
||||
if ( "%%{$placeholder[0]}%%" === $template ) {
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $replacement );
|
||||
|
||||
return $replacement;
|
||||
}
|
||||
|
||||
// Get placeholder suffix
|
||||
$has_suffix = '' === $replacement && $placeholder_settings['remove_suffix_if_empty'];
|
||||
$suffix = $has_suffix ? $placeholder_settings['suffix'] : '';
|
||||
|
||||
// Make sure replacement is string before proceed;
|
||||
if ( is_string( $replacement ) ) {
|
||||
$rebuilt_string = str_replace( "%%{$placeholder[0]}%%{$suffix}", $replacement, $template );
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $rebuilt_string );
|
||||
|
||||
return $rebuilt_string;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $template );
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
public function rebuild_preset_placeholder( $template, $data = array(), $settings = array() ) {
|
||||
// Check for cached result first for faster performance
|
||||
$cache_name = 'preset_placeholder';
|
||||
$cache_key = $this->get_cache_key( array( $template, $data, $settings ) );
|
||||
$cache = $this->get_cache( $cache_name, $cache_key );
|
||||
|
||||
if ( ! is_null( $cache ) ) {
|
||||
return $cache;
|
||||
}
|
||||
|
||||
$rebuild_attr = array();
|
||||
|
||||
foreach ( $template as $preset_attr_key => $preset_attr_value ) {
|
||||
// Object inside preset array mostly contains fields attribute which its object key
|
||||
// contains placeholder while its object value contains actual value without placeholder.
|
||||
if ( is_array( $preset_attr_value ) ) {
|
||||
$rebuilt_preset_attr_object = array();
|
||||
|
||||
foreach ( $preset_attr_value as $name => $value ) {
|
||||
$object_item_name = $this->rebuild_string_placeholder( $name, $data, $settings );
|
||||
|
||||
$rebuilt_preset_attr_object[ $object_item_name ] = $value;
|
||||
}
|
||||
|
||||
$rebuild_attr[ $preset_attr_key ] = $rebuilt_preset_attr_object;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$rebuild_attr[ $preset_attr_key ] = $preset_attr_value;
|
||||
}
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $rebuild_attr );
|
||||
|
||||
return $rebuild_attr;
|
||||
}
|
||||
|
||||
public function rebuild_composite_structure_placeholder( $template_type, $template, $data = array() ) {
|
||||
// Check for cached result first for faster performance
|
||||
$cache_name = 'composite_structure_placeholder';
|
||||
$cache_key = $this->get_cache_key( array( $template_type, $template, $data ) );
|
||||
$cache = $this->get_cache( $cache_name, $cache_key );
|
||||
|
||||
if ( ! is_null( $cache ) ) {
|
||||
return $cache;
|
||||
}
|
||||
|
||||
$rebuilt_composite_structure_field = $template;
|
||||
|
||||
// Replaces placeholder with actual value on border's nested composite structure fields
|
||||
if ( 'border' === $template_type ) {
|
||||
// Reset `controls` attribute output
|
||||
$rebuilt_composite_structure_field['controls'] = array();
|
||||
|
||||
// Loop composite structure's original `controls` from template
|
||||
foreach ( $template['controls'] as $field_name => $field ) {
|
||||
$rebuilt_field_name = $this->rebuild_string_placeholder( $field_name, $data );
|
||||
$rebuilt_field = $field;
|
||||
|
||||
// Loop field on composite structure controls
|
||||
foreach ( $rebuilt_field as $attr_name => $attr_value ) {
|
||||
$settings = array(
|
||||
'suffix' => 'label' === $attr_name ? ' ' : '',
|
||||
'remove_suffix_if_empty' => 'label' === $attr_name,
|
||||
);
|
||||
$rebuilt_field[ $attr_name ] = $this->rebuild_string_placeholder( $attr_value, $data, $settings );
|
||||
}
|
||||
|
||||
$rebuilt_composite_structure_field['controls'][ $rebuilt_field_name ] = $rebuilt_field;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $rebuilt_composite_structure_field );
|
||||
|
||||
return $rebuilt_composite_structure_field;
|
||||
}
|
||||
|
||||
public function rebuild_field_attr_value( $attr_name, $attr_value, $template_data ) {
|
||||
// Check for cached result first for faster performance
|
||||
$cache_name = 'field_attr_value';
|
||||
$cache_key = $this->get_cache_key( array( $attr_name, $attr_value, $template_data ) );
|
||||
$cache = $this->get_cache( $cache_name, $cache_key );
|
||||
|
||||
if ( ! is_null( $cache ) ) {
|
||||
return $cache;
|
||||
}
|
||||
|
||||
$template_type = ! empty( $template_data[0] ) ? $template_data[0] : '';
|
||||
$prefix = ! empty( $template_data[1]['prefix'] ) && ! empty( $template_data[1]['prefix'] ) ? $template_data[1]['prefix'] : '';
|
||||
|
||||
// Certain advanced field (ie. Text Shadow) automatically adds underscore
|
||||
$auto_add_prefix_underscore = isset( $template_data[0] ) && 'text_shadow' === $template_data[0] && '' === $prefix;
|
||||
|
||||
// 1. Field attribute value's type is string
|
||||
if ( is_string( $attr_value ) ) {
|
||||
$placeholder_has_space_suffix = 'label' === $attr_name && in_array( $template_type, array( 'border', 'text_shadow' ) );
|
||||
|
||||
$settings = array(
|
||||
'suffix' => $placeholder_has_space_suffix ? ' ' : '',
|
||||
'remove_suffix_if_empty' => $placeholder_has_space_suffix ? true : false,
|
||||
);
|
||||
$rebuilt_placeholder = $this->rebuild_string_placeholder( $attr_value, $template_data, $settings );
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $rebuilt_placeholder );
|
||||
|
||||
return $rebuilt_placeholder;
|
||||
}
|
||||
|
||||
// 2. Field attribute value's type is array (sequential)
|
||||
if ( is_array( $attr_value ) && isset( $attr_value[0] ) ) {
|
||||
$rebuild_attr_value = array();
|
||||
|
||||
foreach ( $attr_value as $array_value ) {
|
||||
// Array consists of string is most likely used for defining field relationship
|
||||
// such as `show_if` attribute; Replace prefix and suffix placeholder with
|
||||
// placeholder replacement also consider that text_shadow advanced field
|
||||
// automatically adds underscore after prefix so it needs to be adjusted as well
|
||||
if ( is_string( $array_value ) ) {
|
||||
$settings = array(
|
||||
'suffix' => '_',
|
||||
'remove_suffix_if_empty' => $auto_add_prefix_underscore,
|
||||
);
|
||||
$rebuild_attr_value[] = $this->rebuild_string_placeholder( $array_value, $template_data, $settings );
|
||||
} elseif ( 'presets' === $attr_name ) {
|
||||
// Handle preset attribute specifically due to how it is structured
|
||||
$settings = array(
|
||||
'suffix' => '_',
|
||||
'remove_suffix_if_empty' => $auto_add_prefix_underscore,
|
||||
);
|
||||
$rebuild_attr_value[] = $this->rebuild_preset_placeholder( $array_value, $template_data, $settings );
|
||||
} else {
|
||||
// Non string and `presets` attribute less likely contains placeholder
|
||||
$rebuild_attr_value[] = $array_value;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $rebuild_attr_value );
|
||||
|
||||
return $rebuild_attr_value;
|
||||
}
|
||||
|
||||
// 3. Field attribute value's type is array (associative)
|
||||
if ( is_array( $attr_value ) && ! isset( $attr_value[0] ) ) {
|
||||
$attr_object = array();
|
||||
|
||||
// Loop existing attrValue and populate the rebuilt result on `attrObject`.
|
||||
foreach ( $attr_value as $item_key => $item_value ) {
|
||||
$attr_object_key = $this->rebuild_string_placeholder( $item_key, $template_data );
|
||||
|
||||
// Replaces placeholder with actual value on border's nested composite structure fields
|
||||
if ( 'composite_structure' === $attr_name ) {
|
||||
$item_value = $this->rebuild_composite_structure_placeholder( $template_type, $item_value, $template_data );
|
||||
}
|
||||
|
||||
$attr_object[ $attr_object_key ] = $item_value;
|
||||
}
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $attr_object );
|
||||
|
||||
return $attr_object;
|
||||
}
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $attr_value );
|
||||
|
||||
// 4. Unknown attribute value type; directly pass it
|
||||
return $attr_value;
|
||||
}
|
||||
|
||||
public function rebuild_field_template( $template_id, $parent_template_id = false ) {
|
||||
// Check for cached result first for faster performance
|
||||
$cache_name = 'field_template';
|
||||
$cache_key = $parent_template_id ? "{$template_id}-inherits-{$parent_template_id}" : $template_id;
|
||||
$cache = $this->get_cache( $cache_name, $cache_key );
|
||||
|
||||
if ( ! is_null( $cache ) ) {
|
||||
return $cache;
|
||||
}
|
||||
|
||||
$fields = array();
|
||||
$template_data = $this->get_data( $template_id );
|
||||
|
||||
// No fields will be found without template data. Return early;
|
||||
if ( empty( $template_data ) ) {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
$template_type = ! empty( $template_data[0] ) ? $template_data[0] : '';
|
||||
$template_settings = ! empty( $template_data[1] ) ? $template_data[1] : array();
|
||||
$prefix = ! empty( $template_settings['prefix'] ) ? $template_settings['prefix'] : '';
|
||||
|
||||
$parent_template_data = false;
|
||||
|
||||
// If rebuilt parent template is inside another templateId (ie. Text Shadow inside Font)
|
||||
// its placeholder is passed for data; The expected structure becomes
|
||||
// `[templateType, parentTemplateSettings]` instead of `[templateType, templateSettings]`;
|
||||
// Thus get parent template's settings and use it
|
||||
if ( $parent_template_id ) {
|
||||
$parent_template_data = $this->get_data( $parent_template_id );
|
||||
$parent_template_settings = ! empty( $parent_template_data[1] ) ? $parent_template_data[1] : true;
|
||||
|
||||
$template_settings_inherits_from_parant = array();
|
||||
|
||||
foreach ( $template_settings as $name => $value ) {
|
||||
$placeholder = $this->get_template_placeholder( $value );
|
||||
|
||||
if ( is_array( $placeholder ) && isset( $placeholder[0] ) ) {
|
||||
$template_settings_inherits_from_parant[ $name ] = self::$_->array_get(
|
||||
$parent_template_settings,
|
||||
$placeholder[0],
|
||||
$value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$parent_template_data = array(
|
||||
$template_type,
|
||||
$template_settings_inherits_from_parant,
|
||||
);
|
||||
}
|
||||
|
||||
// Get fields template for given template type
|
||||
$fields_template = $this->get_template( $template_type );
|
||||
|
||||
// Loop fields template and replace placeholder with actual value
|
||||
foreach ( $fields_template as $field_name_template => $field_template ) {
|
||||
// Certain advanced field (ie. Text Shadow) automatically adds underscore
|
||||
// Related template type needs to be adjusted
|
||||
$remove_suffix_if_empty = 'text_shadow' === $template_type && '' === $prefix;
|
||||
|
||||
// Replace field attribute name's placeholder
|
||||
$field_template_data = $parent_template_id ? $parent_template_data : $template_data;
|
||||
$field_name = $this->rebuild_string_placeholder(
|
||||
$field_name_template,
|
||||
$field_template_data,
|
||||
array(
|
||||
'remove_suffix_if_empty' => $remove_suffix_if_empty,
|
||||
// placeholder's suffix, not placeholder named %%suffix%%
|
||||
'suffix' => '_',
|
||||
)
|
||||
);
|
||||
|
||||
// Replace field attribute value's placeholder
|
||||
$field = array();
|
||||
if ( is_array( $field_template ) ) {
|
||||
foreach ( $field_template as $attr_name => $attr_value ) {
|
||||
$rebuilt_attr_value = $this->rebuild_field_attr_value(
|
||||
$attr_name,
|
||||
$attr_value,
|
||||
$field_template_data
|
||||
);
|
||||
|
||||
// Omit attribute with empty value: existance of attribute even with empty
|
||||
// string value is handled differently in many field (ie, `show_if`)
|
||||
if ( '' === $rebuilt_attr_value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field[ $attr_name ] = $rebuilt_attr_value;
|
||||
}
|
||||
} else {
|
||||
$fields = array_merge(
|
||||
$fields,
|
||||
$this->rebuild_field_template( $field_name_template, $template_id )
|
||||
);
|
||||
}
|
||||
|
||||
// `name` attribute is dynamically added based on field's array key
|
||||
$field['name'] = $field_name;
|
||||
|
||||
// Populate rebuilt field
|
||||
$fields[ $field_name ] = $field;
|
||||
}
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $fields );
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function rebuild_default_props( $template_id ) {
|
||||
// Check for cached result first for faster performance
|
||||
$cache_name = 'default_props';
|
||||
$cache_key = $template_id;
|
||||
$cache = $this->get_cache( $cache_name, $cache_key );
|
||||
|
||||
if ( ! is_null( $cache ) ) {
|
||||
return $cache;
|
||||
}
|
||||
|
||||
$default_props = array();
|
||||
$rebuilt_fields = $this->rebuild_field_template( $template_id );
|
||||
|
||||
foreach ( $rebuilt_fields as $field_name => $field ) {
|
||||
$value = '';
|
||||
|
||||
if ( isset( $field['composite_type'], $field['composite_structure'] ) ) {
|
||||
require_once ET_BUILDER_DIR . 'module/field/attribute/composite/Parser.php';
|
||||
$composite_atts = ET_Builder_Module_Field_Attribute_Composite_Parser::parse( $field['composite_type'], $field['composite_structure'] );
|
||||
$default_props = array_merge( $default_props, $composite_atts );
|
||||
} else {
|
||||
if ( isset( $field['default_on_front'] ) ) {
|
||||
$value = $field['default_on_front'];
|
||||
} elseif ( isset( $field['default'] ) ) {
|
||||
$value = $field['default'];
|
||||
}
|
||||
|
||||
$default_props[ $field_name ] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache result
|
||||
$this->set_cache( $cache_name, $cache_key, $default_props );
|
||||
|
||||
return $default_props;
|
||||
}
|
||||
}
|
||||
|
||||
|
90
includes/builder/module/helpers/Overflow.php
Normal file
90
includes/builder/module/helpers/Overflow.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Overflow helper methods
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Overflow
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Overflow {
|
||||
|
||||
const OVERFLOW_DEFAULT = '';
|
||||
const OVERFLOW_VISIBLE = 'visible';
|
||||
const OVERFLOW_HIDDEN = 'hidden';
|
||||
const OVERFLOW_SCROLL = 'scroll';
|
||||
const OVERFLOW_AUTO = 'auto';
|
||||
|
||||
private static $instance;
|
||||
|
||||
public static function get() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
return self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns overflow settings X axis field
|
||||
*
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_field_x( $prefix = '' ) {
|
||||
return $prefix . 'overflow-x';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns overflow settings Y axis field
|
||||
*
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_field_y( $prefix = '' ) {
|
||||
return $prefix . 'overflow-y';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return overflow X axis value
|
||||
*
|
||||
* @param array $props
|
||||
* @param mixed $default
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_x( $props, $default = null, $prefix = '' ) {
|
||||
return et_()->array_get( $props, $this->get_field_x( $prefix ), $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return overflow Y axis value
|
||||
*
|
||||
* @param array $props
|
||||
* @param mixed $default
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_y( $props, $default = null, $prefix = '' ) {
|
||||
return et_()->array_get( $props, $this->get_field_y( $prefix ), $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns overflow valid values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_overflow_values() {
|
||||
return array(
|
||||
self::OVERFLOW_DEFAULT,
|
||||
self::OVERFLOW_VISIBLE,
|
||||
self::OVERFLOW_HIDDEN,
|
||||
self::OVERFLOW_AUTO,
|
||||
self::OVERFLOW_SCROLL,
|
||||
);
|
||||
}
|
||||
}
|
101
includes/builder/module/helpers/Overlay.php
Normal file
101
includes/builder/module/helpers/Overlay.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay helper methods.
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Overlay
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Overlay {
|
||||
/**
|
||||
* Get an overlay html tag's attributes.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_attributes( $args ) {
|
||||
$attributes = array();
|
||||
|
||||
if ( ! empty( $args['icon'] ) ) {
|
||||
$attributes['data-icon'] = et_pb_extended_process_font_icon( $args['icon'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $args['icon_tablet'] ) ) {
|
||||
$attributes['data-icon-tablet'] = et_pb_extended_process_font_icon( $args['icon_tablet'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $args['icon_phone'] ) ) {
|
||||
$attributes['data-icon-phone'] = et_pb_extended_process_font_icon( $args['icon_phone'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $args['icon_sticky'] ) ) {
|
||||
$attributes['data-icon-sticky'] = et_pb_extended_process_font_icon( $args['icon_sticky'] );
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an overlay html tag's attributes.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function render_attributes( $args ) {
|
||||
$attributes = self::get_attributes( $args );
|
||||
$html = array();
|
||||
|
||||
foreach ( $attributes as $attribute => $value ) {
|
||||
$html[] = sprintf(
|
||||
'%1$s="%2$s"',
|
||||
et_core_intentionally_unescaped( $attribute, 'fixed_string' ),
|
||||
et_core_esc_previously( $value )
|
||||
);
|
||||
}
|
||||
|
||||
return implode( ' ', $html );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an overlay html tag.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function render( $args ) {
|
||||
$attributes = et_core_esc_previously( self::render_attributes( $args ) );
|
||||
$classes = array( 'et_overlay' );
|
||||
|
||||
if ( ! empty( $args['icon'] ) ) {
|
||||
$classes[] = 'et_pb_inline_icon';
|
||||
}
|
||||
|
||||
if ( ! empty( $args['icon_tablet'] ) ) {
|
||||
$classes[] = 'et_pb_inline_icon_tablet';
|
||||
}
|
||||
|
||||
if ( ! empty( $args['icon_phone'] ) ) {
|
||||
$classes[] = 'et_pb_inline_icon_phone';
|
||||
}
|
||||
|
||||
if ( ! empty( $args['icon_sticky'] ) ) {
|
||||
$classes[] = 'et_pb_inline_icon_sticky';
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'<span class="%1$s"%2$s></span>',
|
||||
et_core_intentionally_unescaped( implode( ' ', $classes ), 'fixed_string' ),
|
||||
( '' !== $attributes ? ' ' . $attributes : '' )
|
||||
);
|
||||
}
|
||||
}
|
1501
includes/builder/module/helpers/ResponsiveOptions.php
Normal file
1501
includes/builder/module/helpers/ResponsiveOptions.php
Normal file
File diff suppressed because it is too large
Load Diff
63
includes/builder/module/helpers/Sizing.php
Normal file
63
includes/builder/module/helpers/Sizing.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Helper class that provides necessary functions for managing Sizing option
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Sizing
|
||||
*/
|
||||
abstract class ET_Builder_Module_Helper_Sizing {
|
||||
/**
|
||||
* @var string The prefix string that may be added to field name
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* Return raw field name to create the field
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function get_raw_field();
|
||||
|
||||
public function __construct( $prefix = '' ) {
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sizing options fields prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_prefix() {
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns field name of the sizing option
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_field() {
|
||||
return $this->get_prefix() . $this->get_raw_field();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the sizing feature option is enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_enabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sizing value
|
||||
*
|
||||
* @param array $props
|
||||
* @param string $default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_value( array $props, $default = '' ) {
|
||||
return (string) et_()->array_get( $props, $this->get_field(), $default );
|
||||
}
|
||||
}
|
137
includes/builder/module/helpers/Slider.php
Normal file
137
includes/builder/module/helpers/Slider.php
Normal file
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class ET_Builder_Module_Helper_Slider
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Slider {
|
||||
|
||||
/**
|
||||
* Returns slider arrows CSS selector
|
||||
*
|
||||
* @since 3.25.3
|
||||
*
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_arrows_selector( $prefix = '%%order_class%%' ) {
|
||||
return implode(
|
||||
',',
|
||||
array(
|
||||
"$prefix .et-pb-slider-arrows .et-pb-arrow-prev",
|
||||
"$prefix .et-pb-slider-arrows .et-pb-arrow-next",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns slider dots CSS selector
|
||||
*
|
||||
* @since 3.25.3
|
||||
*
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_dots_selector( $prefix = '%%order_class%%' ) {
|
||||
return "$prefix .et-pb-controllers a, $prefix .et-pb-controllers .et-pb-active-control";
|
||||
}
|
||||
|
||||
/**
|
||||
* Reapply (fullwidth) post slider's module background on slide item which has featured image
|
||||
*
|
||||
* @since 4.3.3
|
||||
*
|
||||
* @param array $args {
|
||||
* @type int $slide_post_id
|
||||
* @type string|bool $post_featured_image
|
||||
* @type string $render_slug
|
||||
* @type array $props
|
||||
* }
|
||||
*/
|
||||
public static function reapply_module_background_on_slide( $args = array() ) {
|
||||
$defaults = array(
|
||||
'slide_post_id' => 0,
|
||||
'post_featured_image' => false,
|
||||
'render_slug' => '',
|
||||
'props' => array(),
|
||||
);
|
||||
|
||||
// Parse argument
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
// Create slide class
|
||||
$slide_id_class = "et_pb_post_slide-{$args['slide_post_id']}";
|
||||
|
||||
// Reapply background color (affecting blend mode), gradient (can be placed on top of image
|
||||
// creating overlay-effect), and images (gradient is actually image) if:
|
||||
// 1. Featured image exist on current slide
|
||||
// 2. Featured image is shown (responsive)
|
||||
// 3. Featured image placement is placed on background
|
||||
// 4. Parallax (responsive) is off
|
||||
|
||||
// 1. Exit if featured image doesn't exist on current slide
|
||||
if ( ! $args['post_featured_image'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$props = $args['props'];
|
||||
|
||||
// 2. Exit if featured image is not shown
|
||||
$is_show_image_responsive = et_pb_responsive_options()->is_responsive_enabled( $props, 'show_image' );
|
||||
$is_featured_image_shown = $is_show_image_responsive ?
|
||||
in_array( 'on', et_pb_responsive_options()->get_property_values( $props, 'show_image' ) ) :
|
||||
'on' === et_()->array_get( $props, 'show_image' );
|
||||
|
||||
if ( ! $is_featured_image_shown ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Exit if feature image is not placed in background
|
||||
if ( 'background' !== et_()->array_get( $props, 'image_placement' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. Exit if parallax is activated
|
||||
$is_parallax_responsive = et_pb_responsive_options()->is_responsive_enabled( $props, 'parallax' );
|
||||
$is_parallax_active = $is_parallax_responsive ?
|
||||
in_array( 'on', et_pb_responsive_options()->get_property_values( $props, 'parallax' ) ) :
|
||||
'on' === et_()->array_get( $props, 'parallax' );
|
||||
|
||||
if ( $is_parallax_active ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process background
|
||||
$props['background_image'] = $args['post_featured_image'];
|
||||
$props['background_enable_image'] = 'on';
|
||||
|
||||
// Background responsive is generally set via background_last_edited instead of each background
|
||||
// type's *_last_edited; when background's responsive active and no background image is set,
|
||||
// background-image property will be set to `initial` and featured image on current image got
|
||||
// removed on current breakpoint. Thus, Set background image responsive attribute on current
|
||||
// background_image attribute to keep it visible
|
||||
if ( et_pb_responsive_options()->is_responsive_enabled( $props, 'background' ) ) {
|
||||
$props['background_image_last_edited'] = '';
|
||||
$props['background_image_tablet'] = $args['post_featured_image'];
|
||||
$props['background_image_phone'] = $args['post_featured_image'];
|
||||
|
||||
}
|
||||
|
||||
if ( et_builder_is_hover_enabled( 'background', $props ) ) {
|
||||
$props['background_image__hover'] = $args['post_featured_image'];
|
||||
}
|
||||
|
||||
et_pb_background_options()->get_background_style(
|
||||
array(
|
||||
'props' => $props,
|
||||
'selector' => "%%order_class%% .{$slide_id_class}",
|
||||
'selector_hover' => "%%order_class%%:hover .{$slide_id_class}",
|
||||
'function_name' => $args['render_slug'],
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
353
includes/builder/module/helpers/StickyOptions.php
Normal file
353
includes/builder/module/helpers/StickyOptions.php
Normal file
@ -0,0 +1,353 @@
|
||||
<?php
|
||||
/**
|
||||
* Sticky Helper
|
||||
*
|
||||
* @package Divi
|
||||
* @sub-package Builder
|
||||
* @since 4.6.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sticky Options helper methods
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* Class ET_Builder_Module_Sticky_Options
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Sticky_Options {
|
||||
|
||||
/**
|
||||
* Class instance object
|
||||
*
|
||||
* @var object Class instance.
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Get instance of ET_Builder_Module_Sticky_Options.
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @return object|ET_Builder_Module_Sticky_Options
|
||||
*/
|
||||
public static function get() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new ET_Builder_Module_Helper_Sticky_Options();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Sticky field suffix
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_suffix() {
|
||||
return '__sticky';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Sticky field enabled suffix
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_enabled_suffix() {
|
||||
return '__sticky_enabled';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field original name by removing the `_sticky` or `__sticky_enabled` suffix if it exists.
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param string $name Field name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_field_base_name( $name ) {
|
||||
$regex = "/(.*)({$this->get_suffix()}|{$this->get_enabled_suffix()})$/";
|
||||
$replace = '${1}';
|
||||
|
||||
return preg_replace( $regex, $replace, $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get valid sticky_position which implies module is sticky element
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_valid_sticky_positions() {
|
||||
return array( 'top', 'bottom', 'top_bottom' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the setting has enabled sticky options
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param string $setting Field name.
|
||||
* @param array $attrs Module attributes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_enabled( $setting, $attrs ) {
|
||||
$name = 'background_color' === $setting ? 'background' : $setting;
|
||||
|
||||
$field = $this->get_sticky_enabled_field( $name );
|
||||
|
||||
$value = ! empty( $attrs[ $field ] ) ? $attrs[ $field ] : '';
|
||||
|
||||
return ! empty( $value ) && strpos( $value, 'on' ) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current module is inside sticky module
|
||||
*
|
||||
* @since 4.6.2
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_inside_sticky_module() {
|
||||
global $is_inside_sticky_module;
|
||||
|
||||
return $is_inside_sticky_module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if module with given attributes is a sticky module. Need to consider responsive value:
|
||||
* desktop might have non sticky element value but its smaller breakpoint has sticky element value
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param array $attrs Module attributes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_sticky_module( $attrs ) {
|
||||
// No nested sticky element.
|
||||
if ( $this->is_inside_sticky_module() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bail if there is fields which its selected value are incompatible to sticky mechanism.
|
||||
if ( $this->has_incompatible_attrs( $attrs ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sticky_position = et_pb_responsive_options()->get_checked_property_value( $attrs, 'sticky_position', 'none', true );
|
||||
|
||||
// Non responsive.
|
||||
if ( is_string( $sticky_position ) ) {
|
||||
return in_array( $sticky_position, $this->get_valid_sticky_positions(), true );
|
||||
}
|
||||
|
||||
if ( ! is_array( $sticky_position ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Responsive.
|
||||
$is_sticky = false;
|
||||
|
||||
foreach ( $sticky_position as $device => $position ) {
|
||||
if ( in_array( $position, $this->get_valid_sticky_positions(), true ) ) {
|
||||
$is_sticky = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $is_sticky;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field / setting name with sticky suffix
|
||||
* E.g.: get_sticky_enabled_field('test') => 'test__sticky'
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param string $setting Field name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_sticky_field( $setting ) {
|
||||
return "{$this->get_field_base_name($setting)}{$this->get_suffix()}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sticky enabled setting field name
|
||||
* E.g.: get_sticky_enabled_field('test') => 'test__sticky_enabled'
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param string $setting Field name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_sticky_enabled_field( $setting ) {
|
||||
return "{$this->get_field_base_name($setting)}{$this->get_enabled_suffix()}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns setting value for sticky if enabled, otherwise return the default value
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param string $setting Field name.
|
||||
* @param array $attrs Module attributes.
|
||||
* @param mixed $default Default value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_value( $setting, $attrs, $default = null ) {
|
||||
return $this->is_enabled( $setting, $attrs )
|
||||
? $this->get_raw_value( $setting, $attrs, $default )
|
||||
: $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns setting sticky value if sticky is enabled for a compose option;
|
||||
* If it does not exist, return $default specified value
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param string $setting Field name.
|
||||
* @param string $option Option.
|
||||
* @param array $attrs Module attributes.
|
||||
* @param mixed $default Default value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_compose_value( $setting, $option, $attrs, $default = null ) {
|
||||
return $this->is_enabled( $option, $attrs )
|
||||
? $this->get_raw_value( $setting, $attrs, $default )
|
||||
: $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns setting sticky raw value;
|
||||
* If it does not exist, return $default specified value
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param string $setting Field name.
|
||||
* @param array $attrs Module attributes.
|
||||
* @param mixed $default Default value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_raw_value( $setting, $attrs, $default = null ) {
|
||||
return et_()->array_get( $attrs, $this->get_sticky_field( $setting ), $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds sticky state selector prefix before given selectors
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param string|array $selector CSS Selector.
|
||||
* @param bool $is_sticky Whether current module is sticky or not, based on
|
||||
* `sticky_position` prop value.
|
||||
* @param bool $return_string Return modified selector as string or not.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function add_sticky_to_selectors( $selector, $is_sticky = true, $return_string = true ) {
|
||||
$selectors = is_array( $selector ) ? $selector : explode( ',', $selector );
|
||||
$space = $is_sticky ? '' : ' ';
|
||||
$prefix = ".et_pb_sticky{$space}";
|
||||
$prefixed_selector = array();
|
||||
|
||||
foreach ( $selectors as $selector ) {
|
||||
$prefixed_selector[] = $prefix . trim( $selector );
|
||||
}
|
||||
|
||||
return $return_string ? implode( ', ', $prefixed_selector ) : $prefixed_selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add sticky state selector prefix to given selector
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param string $selector CSS Selector.
|
||||
* @param bool $is_sticky whether current module is sticky or not, based on `sticky_position`
|
||||
* prop value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function add_sticky_to_order_class( $selector, $is_sticky = true ) {
|
||||
$selectors = explode( ',', $selector );
|
||||
$selectors = array_map( 'trim', $selectors );
|
||||
|
||||
// If current selector is sticky module, sticky selector is directly attached; if it isn't
|
||||
// it is safe to assume that the sticky selector is one of its parent DOM, hence the space.
|
||||
if ( $is_sticky ) {
|
||||
$selectors = preg_replace( '/(%%order_class%%)/i', '.et_pb_sticky$1', $selectors, 1 );
|
||||
} else {
|
||||
$selectors = preg_replace( '/(%%order_class%%)/i', '.et_pb_sticky $1', $selectors, 1 );
|
||||
}
|
||||
|
||||
return implode( ', ', $selectors );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given attrs has incompatible attribute value which makes sticky mechanism can't
|
||||
* be used on current module
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @param array $attrs Module attributes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_incompatible_attrs( $attrs = array() ) {
|
||||
$incompatible = false;
|
||||
$fields = $this->get_incompatible_fields();
|
||||
|
||||
foreach ( $fields as $name => $options ) {
|
||||
// Get attribute value of current incompatible field from attributes.
|
||||
$attr = ! empty( $attrs[ $name ] ) ? $attrs[ $name ] : false;
|
||||
|
||||
// If the value exist on current incompatible field's options, stop loop and return true.
|
||||
if ( in_array( $attr, $options, true ) ) {
|
||||
$incompatible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $incompatible;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of fields and its value which prevent sticky mechanism to work due to how it behaves
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_incompatible_fields() {
|
||||
return array(
|
||||
// Position Options.
|
||||
'positioning' => array( 'absolute', 'fixed' ),
|
||||
|
||||
// Motion Effects.
|
||||
'scroll_vertical_motion_enable' => array( 'on' ),
|
||||
'scroll_horizontal_motion_enable' => array( 'on' ),
|
||||
'scroll_fade_enable' => array( 'on' ),
|
||||
'scroll_scaling_enable' => array( 'on' ),
|
||||
'scroll_rotating_enable' => array( 'on' ),
|
||||
'scroll_blur_enable' => array( 'on' ),
|
||||
);
|
||||
}
|
||||
}
|
372
includes/builder/module/helpers/StyleProcessor.php
Normal file
372
includes/builder/module/helpers/StyleProcessor.php
Normal file
@ -0,0 +1,372 @@
|
||||
<?php
|
||||
/**
|
||||
* Style Processor
|
||||
*
|
||||
* @package Divi
|
||||
* @sub-package Builder
|
||||
* @since 4.6.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
// Include dependency for ResponsiveOptions.
|
||||
if ( ! function_exists( 'et_pb_responsive_options' ) ) {
|
||||
require_once 'ResponsiveOptions.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon Font helper methods.
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Style_Processor
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Style_Processor {
|
||||
/**
|
||||
* Custom `generate_styles()` processor for responsive, hover, and sticky styles of `icon_font_size`
|
||||
* attributes which sets right property value of font icon in accordion/toggle title.
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @used-by ET_Builder_Module_Accordion->render()
|
||||
* @used-by ET_Builder_Module_Toggle->render()
|
||||
*
|
||||
* @param string $selector CSS Selector.
|
||||
* @param string|array $option_value Option value.
|
||||
* @param array $args Arguments.
|
||||
* @param string $option_type Option type (responsive|sticky|hover).
|
||||
*/
|
||||
public static function process_toggle_title_icon_font_size( $selector, $option_value, $args, $option_type ) {
|
||||
$icon_font_size_default = '16px'; // Default toggle icon size.
|
||||
|
||||
if ( 'responsive' === $option_type ) {
|
||||
$icon_font_size_right_values = array();
|
||||
|
||||
foreach ( $option_value as $device => $value ) {
|
||||
$icon_font_size_active = isset( $option_value[ $device ] ) ? $option_value[ $device ] : 0;
|
||||
if ( ! empty( $icon_font_size_active ) && $icon_font_size_active !== $icon_font_size_default ) {
|
||||
$icon_font_size_active_int = (int) $icon_font_size_active;
|
||||
$icon_font_size_active_unit = str_replace( $icon_font_size_active_int, '', $icon_font_size_active );
|
||||
$icon_font_size_active_diff = (int) $icon_font_size_default - $icon_font_size_active_int;
|
||||
|
||||
if ( 0 !== $icon_font_size_active_diff ) {
|
||||
// 2 is representation of left & right sides.
|
||||
$icon_font_size_right_values[ $device ] = round( $icon_font_size_active_diff / 2 ) . $icon_font_size_active_unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Icon Font Size.
|
||||
et_pb_responsive_options()->generate_responsive_css(
|
||||
$option_value,
|
||||
$selector,
|
||||
$args['css_property'],
|
||||
$args['render_slug']
|
||||
);
|
||||
|
||||
// Right property.
|
||||
et_pb_responsive_options()->generate_responsive_css(
|
||||
$icon_font_size_right_values,
|
||||
$selector,
|
||||
'right',
|
||||
$args['render_slug']
|
||||
);
|
||||
} elseif ( in_array( $option_type, array( 'sticky', 'hover' ), true ) ) {
|
||||
$helper = 'sticky' === $option_type ? et_pb_sticky_options() : et_pb_hover_options();
|
||||
$is_enabled = $helper->is_enabled( $args['base_attr_name'], $args['attrs'] );
|
||||
|
||||
if ( $is_enabled && $option_value !== $icon_font_size_default && '' !== $option_value ) {
|
||||
$icon_font_size_mode_int = (int) $option_value;
|
||||
$icon_font_size_mode_unit = str_replace( $icon_font_size_mode_int, '', $option_value );
|
||||
$icon_font_size_mode_diff = (int) $icon_font_size_default - $icon_font_size_mode_int;
|
||||
|
||||
// Icon Font Size.
|
||||
ET_Builder_Element::set_style(
|
||||
$args['render_slug'],
|
||||
array(
|
||||
'selector' => $selector,
|
||||
'declaration' => sprintf(
|
||||
'font-size:%1$s;',
|
||||
esc_html( $option_value )
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
if ( 0 !== $icon_font_size_mode_diff ) {
|
||||
// 2 is representation of left & right sides.
|
||||
$icon_font_size_right_mode = round( $icon_font_size_mode_diff / 2 ) . $icon_font_size_mode_unit;
|
||||
|
||||
// Right property.
|
||||
ET_Builder_Element::set_style(
|
||||
$args['render_slug'],
|
||||
array(
|
||||
'selector' => $selector,
|
||||
'declaration' => sprintf(
|
||||
'right:%1$s;',
|
||||
esc_html( $icon_font_size_right_mode )
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare and set icon styles(CSS properties `font-family` and `content`)
|
||||
* for the specified $selector.
|
||||
*
|
||||
* @since ?
|
||||
*
|
||||
* @param string $icon_value Extended Icon data.
|
||||
* @param string $render_slug Module slug.
|
||||
* @param string $selector CSS selector for icon container.
|
||||
* @param string $render_type If that param equal `icon_font_family_and_content` then CSS propert `content` will be also set.
|
||||
* @param string $media_query Media query name e.g max_width_767, max_width_980.
|
||||
* @param bool $important Is CSS decalration should containt `!important`.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
private static function _set_icon_styles( $icon_value, $render_slug, $selector, $render_type, $media_query, $important ) {
|
||||
$css_decalration_and_values['font-family:%1$s;'] = et_pb_get_icon_font_family( $icon_value );
|
||||
$css_decalration_and_values['font-weight:%1$s;'] = et_pb_get_icon_font_weight( $icon_value );
|
||||
|
||||
if ( 'icon_font_family_and_content' === $render_type ) {
|
||||
$css_decalration_and_values['content:%1$s;'] = et_pb_get_extended_icon_value_for_css( $icon_value );
|
||||
};
|
||||
|
||||
foreach ( $css_decalration_and_values as $declaration => $value ) {
|
||||
ET_Builder_Element::set_style(
|
||||
$render_slug,
|
||||
array(
|
||||
'selector' => $selector,
|
||||
'declaration' => sprintf(
|
||||
$declaration,
|
||||
$value . ( $important ? ' !important' : '' )
|
||||
),
|
||||
'media_query' => $media_query,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom `generate_styles()` processor for extended icon's css style such as `font-family` or `content`.
|
||||
*
|
||||
* @since ?
|
||||
*
|
||||
* @param string $selector CSS Selector.
|
||||
* @param string|array $option_value Option value.
|
||||
* @param array $args Arguments.
|
||||
* @param string $option_type Option type (responsive|sticky|hover).
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
public static function process_extended_icon( $selector, $option_value, $args, $option_type ) {
|
||||
$is_important = ! empty( $args['important'] );
|
||||
if ( ! empty( $args['utility_arg'] ) && in_array( $args['utility_arg'], array( 'icon_font_family_and_content', 'icon_font_family' ), true ) ) {
|
||||
$type = $args['utility_arg'];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'responsive' === $option_type ) {
|
||||
foreach ( $option_value as $breakpoint => $icon_value ) {
|
||||
if ( empty( $icon_value ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$media_query = 'general';
|
||||
if ( 'tablet' === $breakpoint ) {
|
||||
$media_query = ET_Builder_Element::get_media_query( 'max_width_980' );
|
||||
} elseif ( 'phone' === $breakpoint ) {
|
||||
$media_query = ET_Builder_Element::get_media_query( 'max_width_767' );
|
||||
}
|
||||
|
||||
self::_set_icon_styles( $icon_value, $args['render_slug'], $selector, $type, $media_query, $is_important );
|
||||
|
||||
}
|
||||
} elseif ( in_array( $option_type, array( 'sticky', 'hover' ), true ) ) {
|
||||
$helper = 'sticky' === $option_type ? et_pb_sticky_options() : et_pb_hover_options();
|
||||
$is_enabled = $helper->is_enabled( $args['base_attr_name'], $args['attrs'] );
|
||||
|
||||
if ( $is_enabled && ! empty( $option_value ) ) {
|
||||
self::_set_icon_styles( $option_value, $args['render_slug'], $selector, $type, 'general', $is_important );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom `generate_styles()` processor for responsive, hover, and sticky styles of
|
||||
* `icon_font_size` attributes which sets css properties for social media follow's icon and
|
||||
* its dimension.
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @used-by ET_Builder_Module_Social_Media_Follow->render()
|
||||
* @used-by ET_Builder_Module_Social_Media_Follow_Item->render()
|
||||
*
|
||||
* @param string $selector CSS Selector.
|
||||
* @param string|array $option_value Option value.
|
||||
* @param array $args Arguments.
|
||||
* @param string $option_type Option type (responsive|sticky|hover).
|
||||
*/
|
||||
public static function process_social_media_icon_font_size( $selector, $option_value, $args, $option_type ) {
|
||||
if ( 'responsive' === $option_type ) {
|
||||
foreach ( $option_value as $font_size_key => $font_size_value ) {
|
||||
if ( '' === $font_size_value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$media_query = 'general';
|
||||
|
||||
if ( 'tablet' === $font_size_key ) {
|
||||
$media_query = ET_Builder_Element::get_media_query( 'max_width_980' );
|
||||
} elseif ( 'phone' === $font_size_key ) {
|
||||
$media_query = ET_Builder_Element::get_media_query( 'max_width_767' );
|
||||
}
|
||||
|
||||
$font_size_value_double = et_builder_multiply_value_has_unit( $font_size_value, 2, 0 );
|
||||
|
||||
// Icon.
|
||||
ET_Builder_Element::set_style(
|
||||
$args['render_slug'],
|
||||
array(
|
||||
'selector' => $selector,
|
||||
'declaration' => sprintf(
|
||||
'font-size:%1$s; line-height:%2$s; height:%2$s; width:%2$s;',
|
||||
esc_html( $font_size_value ),
|
||||
esc_html( $font_size_value_double )
|
||||
),
|
||||
'media_query' => $media_query,
|
||||
)
|
||||
);
|
||||
|
||||
// Icon Wrapper.
|
||||
ET_Builder_Element::set_style(
|
||||
$args['render_slug'],
|
||||
array(
|
||||
'selector' => $args['selector_wrapper'],
|
||||
'declaration' => sprintf(
|
||||
'height:%1$s; width:%1$s;',
|
||||
esc_html( $font_size_value_double )
|
||||
),
|
||||
'media_query' => $media_query,
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ( in_array( $option_type, array( 'sticky', 'hover' ), true ) ) {
|
||||
$helper = 'sticky' === $option_type ? et_pb_sticky_options() : et_pb_hover_options();
|
||||
$is_enabled = $helper->is_enabled( $args['base_attr_name'], $args['attrs'] );
|
||||
|
||||
if ( $is_enabled && '' !== $option_value ) {
|
||||
$option_value_double = et_builder_multiply_value_has_unit( $option_value, 2, 0 );
|
||||
|
||||
// Selector wrapper isn't default argument so it needs to be turned into sticky /
|
||||
// hover selector manually here.
|
||||
$selector_wrapper = 'hover' === $option_type ?
|
||||
$helper->add_hover_to_selectors( $args['selector_wrapper'] ) :
|
||||
$helper->add_sticky_to_selectors( $args['selector_wrapper'], $args['is_sticky_module'] );
|
||||
|
||||
// Icon.
|
||||
ET_Builder_Element::set_style(
|
||||
$args['render_slug'],
|
||||
array(
|
||||
'selector' => $selector,
|
||||
'declaration' => sprintf(
|
||||
'font-size:%1$s; line-height:%2$s; height:%2$s; width:%2$s;',
|
||||
esc_html( $option_value ),
|
||||
esc_html( $option_value_double )
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// Icon Wrapper.
|
||||
ET_Builder_Element::set_style(
|
||||
$args['render_slug'],
|
||||
array(
|
||||
'selector' => $selector_wrapper,
|
||||
'declaration' => sprintf(
|
||||
'height:%1$s; width:%1$s;',
|
||||
esc_html( $option_value_double )
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom `generate_styles()` processor for responsive, hover, and sticky styles of
|
||||
* `icon_font_size` attributes which sets the size of overlay icon.
|
||||
*
|
||||
* @since 4.6.0
|
||||
*
|
||||
* @used-by ET_Builder_Module_Testimonial->render()
|
||||
* @used-by ET_Builder_Module_Video->render()
|
||||
* @used-by ET_Builder_Module_Video_Slider->render()
|
||||
* @used-by ET_Builder_Module_Video_Slider_Item->render()
|
||||
*
|
||||
* @param string $selector CSS Selector.
|
||||
* @param string|array $value Option value.
|
||||
* @param array $args Arguments.
|
||||
* @param string $option_type Option type (responsive|sticky|hover).
|
||||
*/
|
||||
public static function process_overlay_icon_font_size( $selector, $value, $args, $option_type ) {
|
||||
$declaration_format = '' !== $args['processor_declaration_format'] ?
|
||||
$args['processor_declaration_format'] :
|
||||
'font-size:%1$s; line-height:%1$s; margin-top:-%2$s; margin-left:-%2$s;';
|
||||
|
||||
if ( 'responsive' === $option_type ) {
|
||||
foreach ( $value as $breakpoint => $font_size_value ) {
|
||||
if ( '' === $font_size_value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$media_query = 'general';
|
||||
if ( 'tablet' === $breakpoint ) {
|
||||
$media_query = ET_Builder_Element::get_media_query( 'max_width_980' );
|
||||
} elseif ( 'phone' === $breakpoint ) {
|
||||
$media_query = ET_Builder_Element::get_media_query( 'max_width_767' );
|
||||
}
|
||||
|
||||
$font_size_value_half = et_builder_multiply_value_has_unit( $font_size_value, 0.5, 0 );
|
||||
|
||||
ET_Builder_Element::set_style(
|
||||
$args['render_slug'],
|
||||
array(
|
||||
'selector' => $selector,
|
||||
'declaration' => sprintf(
|
||||
$declaration_format,
|
||||
esc_html( $font_size_value ),
|
||||
esc_html( $font_size_value_half )
|
||||
),
|
||||
'media_query' => $media_query,
|
||||
)
|
||||
);
|
||||
}
|
||||
} elseif ( in_array( $option_type, array( 'sticky', 'hover' ), true ) ) {
|
||||
$helper = 'sticky' === $option_type ? et_pb_sticky_options() : et_pb_hover_options();
|
||||
$is_enabled = $helper->is_enabled( $args['base_attr_name'], $args['attrs'] );
|
||||
|
||||
if ( $is_enabled && '' !== $value ) {
|
||||
$value_half = et_builder_multiply_value_has_unit( $value, 0.5, 0 );
|
||||
|
||||
ET_Builder_Element::set_style(
|
||||
$args['render_slug'],
|
||||
array(
|
||||
'selector' => $selector,
|
||||
'declaration' => sprintf(
|
||||
$declaration_format,
|
||||
esc_html( $value ),
|
||||
esc_html( $value_half )
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
110
includes/builder/module/helpers/TransitionOptions.php
Normal file
110
includes/builder/module/helpers/TransitionOptions.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transition Options helper methods
|
||||
*
|
||||
* Class ET_Builder_Module_Transition_Options
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Transition_Options {
|
||||
|
||||
private static $instance;
|
||||
|
||||
public static function get() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new ET_Builder_Module_Helper_Transition_Options();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return transition value.
|
||||
*
|
||||
* @since 3.23 Add $device param to support responsive settings.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $list
|
||||
* @param string $default
|
||||
* @param string $device
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function get_value( $key, $list, $default = null, $device = 'desktop' ) {
|
||||
$value = (string) ET_Core_Data_Utils::instance()->array_get( $list, $key );
|
||||
|
||||
if ( 'desktop' !== $device ) {
|
||||
$responsive = ET_Builder_Module_Helper_ResponsiveOptions::instance();
|
||||
$is_enabled = $responsive->is_responsive_enabled( $list, $key );
|
||||
$value = $is_enabled ? $responsive->get_any_value( $list, "{$key}_{$device}", $value, true ) : $value;
|
||||
}
|
||||
|
||||
return '' === $value ? $default : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the module transition duration,
|
||||
* In case the setting is empty, a default value is returned
|
||||
*
|
||||
* @since 3.23 Add $device param to support responsive settings.
|
||||
*
|
||||
* @param array $props
|
||||
* @param string $device
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_duration( $props, $device = 'desktop' ) {
|
||||
return $this->get_value( 'hover_transition_duration', $props, '300ms', $device );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the module transition speed curve,
|
||||
* In case the setting is empty, a default value is returned
|
||||
*
|
||||
* @since 3.23 Add $device param to support responsive settings.
|
||||
*
|
||||
* @param array $props
|
||||
* @param string $device
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_easing( $props, $device = 'desktop' ) {
|
||||
return $this->get_value( 'hover_transition_speed_curve', $props, 'ease', $device );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the module transition transition delay,
|
||||
* In case the setting is empty, a default value is returned
|
||||
*
|
||||
* @since 3.23 Add $device param to support responsive settings.
|
||||
*
|
||||
* @param array $props
|
||||
* @param string $device
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_delay( $props, $device = 'desktop' ) {
|
||||
return $this->get_value( 'hover_transition_delay', $props, '0ms', $device );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return transition styles.
|
||||
*
|
||||
* @since 3.23 Add $device param to support responsive settings.
|
||||
*
|
||||
* @param string $property
|
||||
* @param array $props
|
||||
* @param string $device
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_style( $property, $props, $device = 'desktop' ) {
|
||||
$duration = $this->get_duration( $props, $device = 'desktop' );
|
||||
$easing = $this->get_easing( $props, $device = 'desktop' );
|
||||
$delay = $this->get_delay( $props, $device = 'desktop' );
|
||||
|
||||
return "{$property} {$duration} {$easing} {$delay}";
|
||||
}
|
||||
}
|
||||
|
14
includes/builder/module/helpers/Width.php
Normal file
14
includes/builder/module/helpers/Width.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Helper class that provides necessary functions for managing width option
|
||||
*
|
||||
* Class ET_Builder_Module_Helper_Width
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Width extends ET_Builder_Module_Helper_Sizing {
|
||||
|
||||
public function get_raw_field() {
|
||||
return 'width';
|
||||
}
|
||||
}
|
||||
|
986
includes/builder/module/helpers/WoocommerceModules.php
Normal file
986
includes/builder/module/helpers/WoocommerceModules.php
Normal file
@ -0,0 +1,986 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Module Helper
|
||||
*
|
||||
* @package Divi
|
||||
* @sub-package Builder
|
||||
* @since 3.29
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( 'Direct access forbidden.' );
|
||||
}
|
||||
|
||||
if ( et_is_woocommerce_plugin_active() ) {
|
||||
|
||||
/**
|
||||
* Class ET_Builder_Module_Helper_Woocommerce_Modules
|
||||
*
|
||||
* Shared code between all Woo Modules.
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Woocommerce_Modules {
|
||||
/**
|
||||
* Returns TRUE if the Product attribute value is valid.
|
||||
*
|
||||
* Valid values are Product Ids, `current` and `latest`.
|
||||
*
|
||||
* @param string $maybe_product_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_product_attr_valid( $maybe_product_id ) {
|
||||
if ( empty( $maybe_product_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( absint( $maybe_product_id ) === 0
|
||||
&& ! in_array( $maybe_product_id, array( 'current', 'latest' ) ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Product Id by the given Product prop value.
|
||||
*
|
||||
* @param string $valid_product_attr
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_product_id_by_prop( $valid_product_attr ) {
|
||||
if ( ! self::is_product_attr_valid( $valid_product_attr ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( 'current' === $valid_product_attr ) {
|
||||
$current_post_id = ET_Builder_Element::get_current_post_id();
|
||||
|
||||
if ( et_theme_builder_is_layout_post_type( get_post_type( $current_post_id ) ) ) {
|
||||
// We want to use the latest product when we are editing a TB layout.
|
||||
$valid_product_attr = 'latest';
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! in_array(
|
||||
$valid_product_attr,
|
||||
array(
|
||||
'current',
|
||||
'latest',
|
||||
)
|
||||
) && false === get_post_status( $valid_product_attr ) ) {
|
||||
$valid_product_attr = 'latest';
|
||||
}
|
||||
|
||||
if ( 'current' === $valid_product_attr ) {
|
||||
$product_id = ET_Builder_Element::get_current_post_id();
|
||||
} elseif ( 'latest' === $valid_product_attr ) {
|
||||
$args = array(
|
||||
'limit' => 1,
|
||||
'post_status' => array( 'publish', 'private' ),
|
||||
'perm' => 'readable',
|
||||
);
|
||||
|
||||
$products = wc_get_products( $args );
|
||||
if ( ! empty( $products ) ) {
|
||||
$product_id = $products[0]->get_id();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} elseif ( is_numeric( $valid_product_attr ) && 'product' !== get_post_type( $valid_product_attr ) ) {
|
||||
// There is a condition that $valid_product_attr value passed here is not the product ID.
|
||||
// For example when you set product breadcrumb as Blurb Title when building layout in TB.
|
||||
// So we get the most recent product ID in date descending order.
|
||||
$query = new WC_Product_Query(
|
||||
array(
|
||||
'limit' => 1,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
'return' => 'ids',
|
||||
'status' => array( 'publish' ),
|
||||
)
|
||||
);
|
||||
|
||||
$products = $query->get_products();
|
||||
|
||||
if ( $products && ! empty( $products[0] ) ) {
|
||||
$product_id = absint( $products[0] );
|
||||
} else {
|
||||
$product_id = absint( $valid_product_attr );
|
||||
}
|
||||
} else {
|
||||
$product_id = absint( $valid_product_attr );
|
||||
}
|
||||
|
||||
return $product_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Product (WC_Product) by the value stored in the Product attribute.
|
||||
*
|
||||
* @see WC_Product
|
||||
*
|
||||
* @param string $maybe_product_id The Value stored in the Product attribute using VB.
|
||||
*
|
||||
* @return false|WC_Product
|
||||
*/
|
||||
public static function get_product( $maybe_product_id ) {
|
||||
$product_id = self::get_product_id_by_prop( $maybe_product_id );
|
||||
|
||||
/*
|
||||
* No need to check `wc_get_product()` exists since this Class is defined only when
|
||||
* WooCommerce is active.
|
||||
*/
|
||||
$product = wc_get_product( $product_id );
|
||||
if ( empty( $product ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Product ID.
|
||||
*
|
||||
* @see WC_Product
|
||||
*
|
||||
* @param string $maybe_product_id The Value stored in the Product attribute using VB.
|
||||
*
|
||||
* @return int WP_Product ID.
|
||||
*/
|
||||
public static function get_product_id( $maybe_product_id ) {
|
||||
$product = self::get_product( $maybe_product_id );
|
||||
if ( ! $product ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $product->get_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reusable WooCommerce field definition
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param string $name Field template name.
|
||||
* @param array $attrs Attribute that need to be inserted into field definition.
|
||||
* @param array $unset Attribute that need to be removed from field definition.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_field( $name, $attrs = array(), $unset = array() ) {
|
||||
switch ( $name ) {
|
||||
case 'product':
|
||||
$field = array(
|
||||
'label' => esc_html__( 'Product', 'et_builder' ),
|
||||
'type' => 'select_product',
|
||||
'option_category' => 'basic_option',
|
||||
'description' => esc_html__( 'Here you can select the Product.', 'et_builder' ),
|
||||
'toggle_slug' => 'main_content',
|
||||
'searchable' => true,
|
||||
'displayRecent' => false,
|
||||
'default' => 'current',
|
||||
'post_type' => 'product',
|
||||
'computed_affects' => array(
|
||||
'__product',
|
||||
),
|
||||
);
|
||||
break;
|
||||
case 'product_filter':
|
||||
$field = array(
|
||||
'label' => esc_html__( 'Filter By', 'et_builder' ),
|
||||
'type' => 'select',
|
||||
'option_category' => 'configuration',
|
||||
'options' => array(
|
||||
'newest' => esc_html__( 'Newest', 'et_builder' ),
|
||||
),
|
||||
'toggle_slug' => 'main_content',
|
||||
'description' => esc_html__( 'Here you can filter the Products.', 'et_builder' ),
|
||||
'default' => 'newest',
|
||||
'show_if' => array(
|
||||
'product' => '-1',
|
||||
),
|
||||
'computed_affects' => array(
|
||||
'__product',
|
||||
),
|
||||
);
|
||||
break;
|
||||
case 'posts_number':
|
||||
$field = array(
|
||||
'default' => '12',
|
||||
'label' => esc_html__( 'Product Count', 'et_builder' ),
|
||||
'type' => 'text',
|
||||
'option_category' => 'configuration',
|
||||
'description' => esc_html__( 'Define the number of products that should be displayed per page.', 'et_builder' ),
|
||||
'computed_affects' => array(
|
||||
'__product',
|
||||
),
|
||||
'toggle_slug' => 'main_content',
|
||||
);
|
||||
break;
|
||||
case 'columns_number':
|
||||
$field = array(
|
||||
'label' => esc_html__( 'Column Layout', 'et_builder' ),
|
||||
'type' => 'select',
|
||||
'option_category' => 'layout',
|
||||
'options' => array(
|
||||
'6' => sprintf( esc_html__( '%1$s Columns', 'et_builder' ), esc_html( '6' ) ),
|
||||
'5' => sprintf( esc_html__( '%1$s Columns', 'et_builder' ), esc_html( '5' ) ),
|
||||
'4' => sprintf( esc_html__( '%1$s Columns', 'et_builder' ), esc_html( '4' ) ),
|
||||
'3' => sprintf( esc_html__( '%1$s Columns', 'et_builder' ), esc_html( '3' ) ),
|
||||
'2' => sprintf( esc_html__( '%1$s Columns', 'et_builder' ), esc_html( '2' ) ),
|
||||
'1' => esc_html__( '1 Column', 'et_builder' ),
|
||||
),
|
||||
'default' => '0',
|
||||
'description' => esc_html__( 'Choose how many columns to display.', 'et_builder' ),
|
||||
'computed_affects' => array(
|
||||
'__product',
|
||||
),
|
||||
'toggle_slug' => 'main_content',
|
||||
);
|
||||
break;
|
||||
case 'orderby':
|
||||
$field = array(
|
||||
'label' => esc_html__( 'Order', 'et_builder' ),
|
||||
'type' => 'select',
|
||||
'option_category' => 'configuration',
|
||||
'options' => array(
|
||||
'default' => esc_html__( 'Default Sorting', 'et_builder' ),
|
||||
'menu_order' => esc_html__( 'Sort by Menu Order', 'et_builder' ),
|
||||
'popularity' => esc_html__( 'Sort By Popularity', 'et_builder' ),
|
||||
'date' => esc_html__( 'Sort By Date: Oldest To Newest', 'et_builder' ),
|
||||
'date-desc' => esc_html__( 'Sort By Date: Newest To Oldest', 'et_builder' ),
|
||||
'price' => esc_html__( 'Sort By Price: Low To High', 'et_builder' ),
|
||||
'price-desc' => esc_html__( 'Sort By Price: High To Low', 'et_builder' ),
|
||||
),
|
||||
'default_on_front' => 'default',
|
||||
'description' => esc_html__( 'Choose how your products should be ordered.', 'et_builder' ),
|
||||
'computed_affects' => array(
|
||||
'__shop',
|
||||
),
|
||||
'toggle_slug' => 'main_content',
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$field = array();
|
||||
break;
|
||||
}
|
||||
|
||||
// Added custom attribute(s).
|
||||
if ( ! empty( $attrs ) ) {
|
||||
$field = wp_parse_args( $attrs, $field );
|
||||
}
|
||||
|
||||
// Remove default attribute(s).
|
||||
if ( ! empty( $unset ) ) {
|
||||
foreach ( $unset as $unset_attr ) {
|
||||
unset( $field[ $unset_attr ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Reviews title.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param WC_Product $product The Product Post.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reviews_title( $product ) {
|
||||
$reviews_title = '';
|
||||
|
||||
if ( ! ( $product instanceof WC_Product ) ) {
|
||||
return $reviews_title;
|
||||
}
|
||||
|
||||
$count = $product->get_review_count();
|
||||
if ( $count ) {
|
||||
$reviews_title = sprintf(
|
||||
esc_html( _n( '%1$s review for %2$s', '%1$s reviews for %2$s', $count, 'et_builder' ) ),
|
||||
esc_html( $count ),
|
||||
'<span>' . $product->get_title() . '</span>'
|
||||
);
|
||||
} else {
|
||||
$reviews_title = esc_html__( 'Reviews', 'et_builder' );
|
||||
}
|
||||
|
||||
return $reviews_title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Reviews comment form.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param WC_Product $product The Product Post.
|
||||
* @param WP_Comment[] $comments Array of Comment objects.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reviews_comment_form( $product, $comments ) {
|
||||
$has_reviews = empty( $comments ) ? false : true;
|
||||
ob_start();
|
||||
?>
|
||||
<?php
|
||||
if ( get_option( 'woocommerce_review_rating_verification_required' ) === 'no' ||
|
||||
wc_customer_bought_product( '', get_current_user_id(), $product->get_id() ) ) :
|
||||
?>
|
||||
|
||||
<div id="review_form_wrapper">
|
||||
<div id="review_form">
|
||||
<?php
|
||||
$commenter = wp_get_current_commenter();
|
||||
|
||||
$comment_form = array(
|
||||
'title_reply' => $has_reviews ? esc_html__( 'Add a review', 'et_builder' ) : sprintf( esc_html__( 'Be the first to review “%s”', 'woocommerce' ), get_the_title( $product->get_id() ) ),
|
||||
'title_reply_to' => esc_html__( 'Leave a Reply to %s', 'et_builder' ),
|
||||
'title_reply_before' => '<span id="reply-title" class="comment-reply-title">',
|
||||
'title_reply_after' => '</span>',
|
||||
'comment_notes_after' => '',
|
||||
'fields' => array(
|
||||
'author' => '<p class="comment-form-author">' . '<label for="author">' . esc_html__( 'Name', 'woocommerce' ) . ' <span class="required">*</span></label> ' .
|
||||
'<input id="author" name="author" type="text" value="' . esc_attr( $commenter['comment_author'] ) . '" size="30" required /></p>',
|
||||
'email' => '<p class="comment-form-email"><label for="email">' . esc_html__( 'Email', 'woocommerce' ) . ' <span class="required">*</span></label> ' .
|
||||
'<input id="email" name="email" type="email" value="' . esc_attr( $commenter['comment_author_email'] ) . '" size="30" required /></p>',
|
||||
),
|
||||
'label_submit' => esc_html__( 'Submit', 'et_builder' ),
|
||||
'submit_button' => '<button name="%1$s" type="submit" id="%2$s" class="et_pb_button %3$s" />%4$s</button>',
|
||||
'logged_in_as' => '',
|
||||
'comment_field' => '',
|
||||
);
|
||||
|
||||
if ( $account_page_url = wc_get_page_permalink( 'myaccount' ) ) {
|
||||
/* translators: %s opening and closing link tags respectively */
|
||||
$comment_form['must_log_in'] = '<p class="must-log-in">' . sprintf( esc_html__( 'You must be %1$slogged in%2$s to post a review.', 'woocommerce' ), '<a href="' . esc_url( $account_page_url ) . '">', '</a>' ) . '</p>';
|
||||
}
|
||||
|
||||
if ( get_option( 'woocommerce_enable_review_rating' ) === 'yes' ) {
|
||||
$comment_form['comment_field'] = '<div class="comment-form-rating"><label for="rating">' . esc_html__( 'Your rating', 'et_builder' ) . '</label><select name="rating" id="rating" required>
|
||||
<option value="">' . esc_html__( 'Rate…', 'et_builder' ) . '</option>
|
||||
<option value="5">' . esc_html__( 'Perfect', 'et_builder' ) . '</option>
|
||||
<option value="4">' . esc_html__( 'Good', 'et_builder' ) . '</option>
|
||||
<option value="3">' . esc_html__( 'Average', 'et_builder' ) . '</option>
|
||||
<option value="2">' . esc_html__( 'Not that bad', 'et_builder' ) . '</option>
|
||||
<option value="1">' . esc_html__( 'Very poor', 'et_builder' ) . '</option>
|
||||
</select></div>';
|
||||
}
|
||||
|
||||
$comment_form['comment_field'] .= '<p class="comment-form-comment"><label for="comment">' . esc_html__( 'Your review', 'et_builder' ) . ' <span class="required">*</span></label><textarea id="comment" name="comment" cols="45" rows="8" required></textarea></p>';
|
||||
|
||||
comment_form(
|
||||
apply_filters( 'woocommerce_product_review_comment_form_args', $comment_form ),
|
||||
$product->get_id()
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php else : ?>
|
||||
|
||||
<p class="woocommerce-verification-required"><?php esc_html_e( 'Only logged in customers who have purchased this product may leave a review.', 'woocommerce' ); ?></p>
|
||||
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatted weight markup for the given Product Id.
|
||||
*
|
||||
* @param int $product_id Product Id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_weight_formatted( $product_id ) {
|
||||
$product = self::get_product( $product_id );
|
||||
$markup = '';
|
||||
|
||||
if ( ! $product ) {
|
||||
return $markup;
|
||||
}
|
||||
|
||||
return ( $product->has_weight() ) ? wc_format_weight( $product->get_weight() ) : $markup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatted dimension markup for the given Product Id.
|
||||
*
|
||||
* @param int $product_id Product Id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_dimensions_formatted( $product_id ) {
|
||||
$product = self::get_product( $product_id );
|
||||
$markup = '';
|
||||
|
||||
if ( ! $product ) {
|
||||
return $markup;
|
||||
}
|
||||
|
||||
return ( $product->has_dimensions() ) ? wc_format_dimensions( $product->get_dimensions( false ) ) : $markup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the $outer_wrapper_attrs.
|
||||
* Adds 'data-background-layout' and 'data-background-layout-hover' attributes if needed.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param array $outer_wrapper_attrs Key value pairs of outer wrapper attributes.
|
||||
* @param ET_Builder_Element $this_class Module's class.
|
||||
*
|
||||
* @return array filtered $outer_wrapper_attrs.
|
||||
*/
|
||||
public static function maybe_add_background_layout_data( $outer_wrapper_attrs, $this_class ) {
|
||||
$background_layout = et_()->array_get( $this_class->props, 'background_layout', '' );
|
||||
$background_layout_hover = et_pb_hover_options()->get_value( 'background_layout', $this_class->props, 'light' );
|
||||
$background_layout_hover_enabled = et_pb_hover_options()->is_enabled( 'background_layout', $this_class->props );
|
||||
|
||||
if ( $background_layout_hover_enabled ) {
|
||||
$outer_wrapper_attrs['data-background-layout'] = esc_attr( $background_layout );
|
||||
$outer_wrapper_attrs['data-background-layout-hover'] = esc_attr( $background_layout_hover );
|
||||
}
|
||||
|
||||
return $outer_wrapper_attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the Background Layout options for Woocommerce Modules.
|
||||
* Adds Background Layout related classes.
|
||||
* Adds Filter for $outer_wrapper_attrs, so required data attributes can be added for specific modules.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param string $render_slug Module's render slug.
|
||||
* @param ET_Builder_Element $this_class Module's class.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
public static function process_background_layout_data( $render_slug, $this_class ) {
|
||||
$background_layout = et_()->array_get( $this_class->props, 'background_layout', '' );
|
||||
$background_layout_values = et_pb_responsive_options()->get_property_values( $this_class->props, 'background_layout' );
|
||||
$background_layout_tablet = et_()->array_get( $background_layout_values, 'tablet', '' );
|
||||
$background_layout_phone = et_()->array_get( $background_layout_values, 'phone', '' );
|
||||
|
||||
$this_class->add_classname( "et_pb_bg_layout_{$background_layout}" );
|
||||
|
||||
if ( ! empty( $background_layout_tablet ) ) {
|
||||
$this_class->add_classname( "et_pb_bg_layout_{$background_layout_tablet}_tablet" );
|
||||
}
|
||||
|
||||
if ( ! empty( $background_layout_phone ) ) {
|
||||
$this_class->add_classname( "et_pb_bg_layout_{$background_layout_phone}_phone" );
|
||||
}
|
||||
|
||||
add_filter( "et_builder_module_{$render_slug}_outer_wrapper_attrs", array( 'ET_Builder_Module_Helper_Woocommerce_Modules', 'maybe_add_background_layout_data' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the Button Icon options for Woocommerce Modules.
|
||||
* Adds et_pb_woo_custom_button_icon class if needed.
|
||||
* Adds Filter for $outer_wrapper_attrs, so required button icon attributes can be added for specific modules.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param string $render_slug Module's render slug.
|
||||
* @param ET_Builder_Element $this_class Module's class.
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
public static function process_custom_button_icons( $render_slug, $this_class ) {
|
||||
$button_custom = $this_class->props['custom_button'];
|
||||
$custom_icon_values = et_()->array_get( $this_class->props, 'button_icon', '' );
|
||||
|
||||
// Exit if no custom styles or icons defined for button.
|
||||
if ( 'on' !== $button_custom || '' === $custom_icon_values ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this_class->add_classname( 'et_pb_woo_custom_button_icon' );
|
||||
add_filter( "et_builder_module_{$render_slug}_outer_wrapper_attrs", array( 'ET_Builder_Module_Helper_Woocommerce_Modules', 'add_custom_button_icons' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the $outer_wrapper_attrs.
|
||||
* Adds 'data-button-class', 'data-button-icon', 'data-button-icon-tablet' and 'data-button-icon-phone' attributes if needed.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param array $outer_wrapper_attrs Key value pairs of outer wrapper attributes.
|
||||
* @param ET_Builder_Element $this_class Module's class.
|
||||
*
|
||||
* @return array filtered $outer_wrapper_attrs.
|
||||
*/
|
||||
public static function add_custom_button_icons( $outer_wrapper_attrs, $this_class ) {
|
||||
$custom_icon_values = et_pb_responsive_options()->get_property_values( $this_class->props, 'button_icon' );
|
||||
$custom_icon = isset( $custom_icon_values['desktop'] ) ? $custom_icon_values['desktop'] : '';
|
||||
$custom_icon_tablet = isset( $custom_icon_values['tablet'] ) ? $custom_icon_values['tablet'] : '';
|
||||
$custom_icon_phone = isset( $custom_icon_values['phone'] ) ? $custom_icon_values['phone'] : '';
|
||||
|
||||
if ( '' !== $custom_icon || '' !== $custom_icon_tablet || '' !== $custom_icon_phone ) {
|
||||
$outer_wrapper_attrs['data-button-class'] = esc_attr( $this_class->get_button_classname() );
|
||||
$outer_wrapper_attrs['data-button-icon'] = esc_attr( et_pb_process_font_icon( $custom_icon ) );
|
||||
$outer_wrapper_attrs['data-button-icon-tablet'] = esc_attr( et_pb_process_font_icon( $custom_icon_tablet ) );
|
||||
$outer_wrapper_attrs['data-button-icon-phone'] = esc_attr( et_pb_process_font_icon( $custom_icon_phone ) );
|
||||
}
|
||||
|
||||
return $outer_wrapper_attrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the columns default.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_columns_posts_default() {
|
||||
return array(
|
||||
'filter',
|
||||
'et_builder_get_woo_default_columns',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the columns default value for the current Product.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_columns_posts_default_value() {
|
||||
$post_id = et_core_page_resource_get_the_ID();
|
||||
$post_id = $post_id ? $post_id : (int) et_()->array_get( $_POST, 'current_page.id' );
|
||||
|
||||
$page_layout = get_post_meta( $post_id, '_et_pb_page_layout', true );
|
||||
|
||||
if ( $page_layout && 'et_full_width_page' !== $page_layout && ! ET_Builder_Element::is_theme_builder_layout() ) {
|
||||
return '3'; // Set to 3 if page has sidebar.
|
||||
}
|
||||
|
||||
/*
|
||||
* Default number is based on the WooCommerce plugin default value.
|
||||
*
|
||||
* @see woocommerce_output_related_products()
|
||||
*/
|
||||
return '4';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Title header tag.
|
||||
*
|
||||
* WooCommerce version influences the returned header.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_title_header() {
|
||||
$header = 'h3';
|
||||
|
||||
if ( ! et_is_woocommerce_plugin_active() ) {
|
||||
return $header;
|
||||
}
|
||||
|
||||
global $woocommerce;
|
||||
if ( version_compare( $woocommerce->version, '3.0.0', '>=' ) ) {
|
||||
$header = 'h2';
|
||||
}
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Title selector.
|
||||
*
|
||||
* WooCommerce changed the title tag from h3 to h2 in v3.0.0
|
||||
*
|
||||
* @uses ET_Builder_Module_Helper_Woocommerce_Modules::get_title_header()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_title_selector() {
|
||||
return sprintf( 'li.product %s', self::get_title_header() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends Data Icon attribute to the Outer wrapper.
|
||||
*
|
||||
* @param array $outer_wrapper_attrs Key value pairs of outer wrapper attributes.
|
||||
* @param mixed $this_class Module's class.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function output_data_icon_attrs( $outer_wrapper_attrs, $this_class ) {
|
||||
$hover_icon = et_()->array_get( $this_class->props, 'hover_icon', '' );
|
||||
$hover_icon_values = et_pb_responsive_options()->get_property_values( $this_class->props, 'hover_icon' );
|
||||
$hover_icon_tablet = et_()->array_get( $hover_icon_values, 'tablet', '' );
|
||||
$hover_icon_phone = et_()->array_get( $hover_icon_values, 'phone', '' );
|
||||
$hover_icon_sticky = et_pb_sticky_options()->get_value( 'hover_icon', $this_class->props );
|
||||
$overlay_attributes = ET_Builder_Module_Helper_Overlay::get_attributes(
|
||||
array(
|
||||
'icon' => $hover_icon,
|
||||
'icon_tablet' => $hover_icon_tablet,
|
||||
'icon_phone' => $hover_icon_phone,
|
||||
'icon_sticky' => $hover_icon_sticky,
|
||||
)
|
||||
);
|
||||
|
||||
return array_merge( $outer_wrapper_attrs, $overlay_attributes );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all possible product tabs.
|
||||
* See woocommerce_default_product_tabs() in woocommerce/includes/wc-template-functions.php
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_default_product_tabs() {
|
||||
$tabs = array(
|
||||
'description' => array(
|
||||
'title' => esc_html__( 'Description', 'et_builder' ),
|
||||
'priority' => 10,
|
||||
'callback' => 'woocommerce_product_description_tab',
|
||||
),
|
||||
'additional_information' => array(
|
||||
'title' => esc_html__( 'Additional information', 'et_builder' ),
|
||||
'priority' => 20,
|
||||
'callback' => 'woocommerce_product_additional_information_tab',
|
||||
),
|
||||
'reviews' => array(
|
||||
'title' => esc_html__( 'Reviews', 'et_builder' ),
|
||||
'priority' => 30,
|
||||
'callback' => 'comments_template',
|
||||
),
|
||||
);
|
||||
|
||||
// Add custom tabs on default for theme builder.
|
||||
if ( et_builder_tb_enabled() ) {
|
||||
et_theme_builder_wc_set_global_objects();
|
||||
$tabs = apply_filters( 'woocommerce_product_tabs', $tabs );
|
||||
et_theme_builder_wc_reset_global_objects();
|
||||
}
|
||||
|
||||
return $tabs;
|
||||
}
|
||||
|
||||
public static function get_default_tab_options() {
|
||||
$tabs = self::get_default_product_tabs();
|
||||
$options = array();
|
||||
|
||||
foreach ( $tabs as $name => $tab ) {
|
||||
if ( ! isset( $tab['title'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$options[ $name ] = array(
|
||||
'value' => $name,
|
||||
'label' => 'reviews' === $name ? esc_html__( 'Reviews', 'et_builder' ) :
|
||||
esc_html( $tab['title'] ),
|
||||
);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get calculated star rating width based on letter spacing value.
|
||||
*
|
||||
* WooCommerce's .star-rating uses `em` based width on float layout;
|
||||
* any additional width caused by letter-spacing makes the calculation incorrect;
|
||||
* thus the `width: calc()` overwrite.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_rating_width_style( $value ) {
|
||||
$value = et_builder_process_range_value( $value );
|
||||
$property_value = 'calc(5.4em + (' . $value . ' * 4))';
|
||||
|
||||
return sprintf( 'width: %1$s;', esc_html( $property_value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get margin properties & values based on current alignment status.
|
||||
*
|
||||
* Default star alignment is not controlled by standard text align system. It uses float to control
|
||||
* how stars symbol will be displayed based on the percentage. It's not possible to convert it to
|
||||
* simple text align. We have to use margin left & right to set the alignment.
|
||||
*
|
||||
* @param string $align
|
||||
* @param string $mode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_rating_alignment_style( $align, $mode = 'desktop' ) {
|
||||
// Bail early if mode is desktop and alignment is left or justify.
|
||||
if ( 'desktop' === $mode && in_array( $align, array( 'left', 'justify' ) ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$margin_properties = array(
|
||||
'center' => array(
|
||||
'left' => 'auto',
|
||||
'right' => 'auto',
|
||||
),
|
||||
'right' => array(
|
||||
'left' => 'auto',
|
||||
'right' => '0',
|
||||
),
|
||||
);
|
||||
|
||||
// By default (left or justify), the margin will be left: inherit and right: auto.
|
||||
$margin_left = et_()->array_get( $margin_properties, "{$align}.left", '0' );
|
||||
$margin_right = et_()->array_get( $margin_properties, "{$align}.right", 'auto' );
|
||||
|
||||
return sprintf(
|
||||
'margin-left: %1$s !important; margin-right: %2$s !important;',
|
||||
esc_html( $margin_left ),
|
||||
esc_html( $margin_right )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get specific star rating style based on property type.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $value
|
||||
* @param string $mode
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_rating_style( $type, $value, $mode = 'desktop' ) {
|
||||
$style = array();
|
||||
|
||||
switch ( $type ) {
|
||||
case 'rating_letter_spacing':
|
||||
$style = self::get_rating_width_style( $value );
|
||||
break;
|
||||
case 'rating_text_align':
|
||||
$style = self::get_rating_alignment_style( $value, $mode );
|
||||
break;
|
||||
}
|
||||
|
||||
return $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set styles for Woo's .star-rating element.
|
||||
*
|
||||
* @since 3.29
|
||||
*
|
||||
* @param string $render_slug
|
||||
* @param array $attrs
|
||||
* @param string $selector
|
||||
* @param string $hover_selector
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function add_star_rating_style( $render_slug, $attrs, $selector = '%%order_class%% .star-rating', $hover_selector = '%%order_class%%:hover .star-rating', $props = array() ) {
|
||||
// Supported star rating properties will be handled here.
|
||||
if ( ! is_array( $props ) || empty( $props ) ) {
|
||||
$props = array( 'rating_letter_spacing', 'rating_text_align' );
|
||||
}
|
||||
|
||||
foreach ( $props as $prop ) {
|
||||
// Get raw value.
|
||||
$values = et_pb_responsive_options()->get_property_values( $attrs, $prop );
|
||||
$hover_value = et_pb_hover_options()->get_value( $prop, $attrs, '' );
|
||||
$processed_values = array();
|
||||
|
||||
// Get specific style value for desktop, tablet, and phone.
|
||||
foreach ( $values as $device => $value ) {
|
||||
if ( empty( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$processed_values[ $device ] = self::get_rating_style( $prop, $value, $device );
|
||||
}
|
||||
|
||||
// Generate style for desktop, tablet, and phone.
|
||||
et_pb_responsive_options()->declare_responsive_css(
|
||||
$processed_values,
|
||||
$selector,
|
||||
$render_slug
|
||||
);
|
||||
|
||||
// Generate style for hover.
|
||||
if ( et_builder_is_hover_enabled( $prop, $attrs ) && ! empty( $hover_value ) ) {
|
||||
ET_Builder_Element::set_style(
|
||||
$render_slug,
|
||||
array(
|
||||
'selector' => $hover_selector,
|
||||
'declaration' => self::get_rating_style( $prop, $hover_value, 'hover', true ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the product default.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_product_default() {
|
||||
return array(
|
||||
'filter',
|
||||
'et_builder_get_woo_default_product',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the product default value for the current post type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_product_default_value() {
|
||||
$post_id = et_core_page_resource_get_the_ID();
|
||||
$post_id = $post_id ? $post_id : (int) et_()->array_get( $_POST, 'current_page.id' );
|
||||
$post_type = get_post_type( $post_id );
|
||||
|
||||
if ( 'product' === $post_type || et_theme_builder_is_layout_post_type( $post_type ) ) {
|
||||
return 'current';
|
||||
}
|
||||
|
||||
return 'latest';
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the special chars in to their entities to be used in :before or :after
|
||||
* pseudo selector content.
|
||||
*
|
||||
* @param string $chars
|
||||
*
|
||||
* @since 4.0
|
||||
* @see https://github.com/elegantthemes/Divi/issues/16976
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function escape_special_chars( $chars ) {
|
||||
switch ( trim( $chars ) ) {
|
||||
case '&':
|
||||
return '\0026';
|
||||
case '>':
|
||||
case '”>”':
|
||||
return '\003e';
|
||||
default:
|
||||
return $chars;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the WooCommerce Tabs defaults.
|
||||
*
|
||||
* Implementation based on
|
||||
*
|
||||
* @see https://github.com/elegantthemes/submodule-builder/pull/6568
|
||||
*
|
||||
* @since 4.4.2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_woo_default_tabs() {
|
||||
return array(
|
||||
'filter',
|
||||
'et_builder_get_woo_default_tabs',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the WooCommerce Tabs options for the given Product.
|
||||
*
|
||||
* @since 4.4.2
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_woo_default_tabs_options() {
|
||||
$maybe_product_id = self::get_product_default_value();
|
||||
$product_id = self::get_product( $maybe_product_id );
|
||||
|
||||
$current_product = wc_get_product( $product_id );
|
||||
if ( ! $current_product ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
global $product, $post;
|
||||
$original_product = $product;
|
||||
$original_post = $post;
|
||||
$product = $current_product;
|
||||
$post = get_post( $product->get_id() );
|
||||
|
||||
$tabs = apply_filters( 'woocommerce_product_tabs', array() );
|
||||
// Reset global $product.
|
||||
$product = $original_product;
|
||||
$post = $original_post;
|
||||
|
||||
if ( ! empty( $tabs ) ) {
|
||||
return implode( '|', array_keys( $tabs ) );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Display type to render only Products.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*
|
||||
* @see https://github.com/elegantthemes/Divi/issues/17998
|
||||
*
|
||||
* @used-by ET_Builder_Module_Woocommerce_Related_Products::render()
|
||||
* @used-by ET_Builder_Module_Woocommerce_Upsells::render()
|
||||
*
|
||||
* @param string $option_name
|
||||
* @param string $display_type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function set_display_type_to_render_only_products( $option_name, $display_type = '' ) {
|
||||
$existing_display_type = get_option( $option_name );
|
||||
update_option( $option_name, $display_type );
|
||||
|
||||
return $existing_display_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the display type to the existing value.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*
|
||||
* @see https://github.com/elegantthemes/Divi/issues/17998
|
||||
*
|
||||
* @used-by ET_Builder_Module_Woocommerce_Related_Products::render()
|
||||
* @used-by ET_Builder_Module_Woocommerce_Upsells::render()
|
||||
*
|
||||
* @param $option_name
|
||||
* @param $display_type
|
||||
*/
|
||||
public static function reset_display_type( $option_name, $display_type ) {
|
||||
update_option( $option_name, $display_type );
|
||||
}
|
||||
}
|
||||
|
||||
add_filter(
|
||||
'et_builder_get_woo_default_columns',
|
||||
array(
|
||||
'ET_Builder_Module_Helper_Woocommerce_Modules',
|
||||
'get_columns_posts_default_value',
|
||||
)
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'et_builder_get_woo_default_product',
|
||||
array(
|
||||
'ET_Builder_Module_Helper_Woocommerce_Modules',
|
||||
'get_product_default_value',
|
||||
)
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'et_builder_get_woo_default_tabs',
|
||||
array(
|
||||
'ET_Builder_Module_Helper_Woocommerce_Modules',
|
||||
'get_woo_default_tabs_options',
|
||||
)
|
||||
);
|
||||
}
|
24
includes/builder/module/helpers/motion/Blur.php
Normal file
24
includes/builder/module/helpers/motion/Blur.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
class ET_Builder_Module_Helper_Motion_Blur extends ET_Builder_Module_Helper_Motion_Sanitizer {
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function sanitize( $value ) {
|
||||
$unit = et_pb_get_value_unit( $value );
|
||||
$unit = in_array( $unit, $this->get_units() ) ? $unit : $this->get_default_unit();
|
||||
|
||||
return (float) $value . $unit;
|
||||
}
|
||||
|
||||
protected function get_units() {
|
||||
return array( 'cm', 'em', 'mm', 'in', 'pc', 'pt', 'px', 'rem' );
|
||||
}
|
||||
|
||||
protected function get_default_unit() {
|
||||
return 'px';
|
||||
}
|
||||
}
|
369
includes/builder/module/helpers/motion/Motions.php
Normal file
369
includes/builder/module/helpers/motion/Motions.php
Normal file
@ -0,0 +1,369 @@
|
||||
<?php
|
||||
/**
|
||||
* Motion Helper class.
|
||||
*
|
||||
* @package Divi
|
||||
* @subpackage Builder
|
||||
*/
|
||||
|
||||
/**
|
||||
* Motion Helpers.
|
||||
*/
|
||||
class ET_Builder_Module_Helper_Motion_Motions {
|
||||
private $START_LIMIT = 0;
|
||||
private $START_MIDDLE = 1;
|
||||
private $END_MIDDLE = 2;
|
||||
private $END_LIMIT = 3;
|
||||
private $START_VALUE = 4;
|
||||
private $MIDDLE_VALUE = 5;
|
||||
private $END_VALUE = 6;
|
||||
private $LENGTH = 7;
|
||||
|
||||
private static $instance;
|
||||
|
||||
public static function instance() {
|
||||
return self::$instance ? self::$instance : ( self::$instance = new self() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Motion Effect value. Which is the merge of Saved and Default values.
|
||||
*
|
||||
* @param string $value, $default_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValue( $saved_value, $default_value ) {
|
||||
if ( $saved_value === $default_value ) {
|
||||
return $saved_value;
|
||||
}
|
||||
|
||||
$saved_array = explode( '|', $saved_value );
|
||||
$default_array = explode( '|', $default_value );
|
||||
|
||||
if ( sizeof( $saved_array ) !== sizeof( $default_array ) ) {
|
||||
return $saved_value;
|
||||
}
|
||||
|
||||
return implode( '|', array_map( array( 'ET_Builder_Module_Helper_Motion_Motions', 'getNonEmpty' ), $saved_array, $default_array ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the non-empty value or default.
|
||||
*
|
||||
* @param string $value, $default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getNonEmpty( $value, $default ) {
|
||||
if ( '' === $value ) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns start limit.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStartLimit( $value ) {
|
||||
return $this->get( $this->START_LIMIT, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set start limit.
|
||||
*
|
||||
* If limit:
|
||||
* - is not a numeric value, return original motionValue
|
||||
* - is lower then 0, set limit to 0
|
||||
* - is higher then start middle, set limit equal to start middle
|
||||
*
|
||||
* @param int $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setStartLimit( $value, $multi_value ) {
|
||||
$value = $this->to_int( $value, $this->getStartLimit( $multi_value ) );
|
||||
$ranged = $this->range( 0, $this->getStartMiddle( $multi_value ), $value );
|
||||
|
||||
return $this->set( $this->START_LIMIT, $ranged, $multi_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns start limit.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getEndLimit( $value ) {
|
||||
return $this->get( $this->END_LIMIT, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set end limit.
|
||||
*
|
||||
* If limit:
|
||||
* - is not a numeric value, return original motionValue
|
||||
* - is lower then end middle, set limit equal to end middle
|
||||
* - is higher then 100, set limit equal to 100
|
||||
*
|
||||
* @param int $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setEndLimit( $value, $multi_value ) {
|
||||
$value = $this->to_int( $value, $this->getEndLimit( $multi_value ) );
|
||||
$ranged = $this->range( $this->getEndMiddle( $multi_value ), 100, $value );
|
||||
|
||||
return $this->set( $this->END_LIMIT, $ranged, $multi_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get start middle.
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStartMiddle( $value ) {
|
||||
return $this->get( $this->START_MIDDLE, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set start middle limit.
|
||||
*
|
||||
* If limit:
|
||||
* - is not a numeric value, return original motionValue
|
||||
* - is lower then start limit, set limit equal to start limit
|
||||
* - is higher then end middle, set limit equal to end middle
|
||||
*
|
||||
* @param int $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setStartMiddle( $value, $multi_value ) {
|
||||
$value = $this->to_int( $value, $this->getStartMiddle( $multi_value ) );
|
||||
$ranged = $this->range( $this->getStartLimit( $value ), $this->getEndMiddle( $value ), $value );
|
||||
|
||||
return $this->set( $this->START_MIDDLE, $ranged, $multi_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get end middle.
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getEndMiddle( $value ) {
|
||||
return $this->get( $this->END_MIDDLE, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set end middle limit.
|
||||
*
|
||||
* If limit:
|
||||
* - is not a numeric value, return original motionValue
|
||||
* - is lower then start middle limit, set limit equal to start middle limit
|
||||
* - is higher then end limit, set limit equal to end limit
|
||||
*
|
||||
* @param int $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setEndMiddle( $value, $multi_value ) {
|
||||
$value = $this->to_int( $value, $this->getEndMiddle( $multi_value ) );
|
||||
$ranged = $this->range( $this->getStartMiddle( $value ), $this->getEndLimit( $value ), $value );
|
||||
|
||||
return $this->set( $this->END_MIDDLE, $ranged, $multi_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns option value for start.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getStartValue( $value ) {
|
||||
return $this->get( $this->START_VALUE, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets option value for start.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setStartValue( $value, $multi_value ) {
|
||||
return $this->set( $this->START_VALUE, $value, $multi_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns option value for middle.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMiddleValue( $value ) {
|
||||
return $this->get( $this->MIDDLE_VALUE, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets option value for middle.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setMiddleValue( $value, $multi_value ) {
|
||||
return $this->set( $this->MIDDLE_VALUE, $value, $multi_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns option value for end.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEndValue( $value ) {
|
||||
return $this->get( $this->END_VALUE, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets option value for end.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setEndValue( $value, $multi_value ) {
|
||||
return $this->set( $this->END_VALUE, $value, $multi_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as Multi.merge, but applies the elements parameter
|
||||
*
|
||||
* @param string $value_1
|
||||
* @param string $value_2
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function merge( $value_1, $value_2 ) {
|
||||
return $this->to_value( $this->split( $this->multi()->merge( $value_1, $value_2, $this->LENGTH ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses array value and converts it to a valid motion array
|
||||
* - array length should be 7
|
||||
* - first 4 values should be numeric values
|
||||
* - first 4 values should respect 0-100 boundaries
|
||||
* - first 4 values should be ordered in ascending order
|
||||
* - last 3 values should be string values
|
||||
*
|
||||
* @param array $value
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parse( array $value ) {
|
||||
$arr = $this->multi()->parse( $value, $this->LENGTH );
|
||||
$range = array();
|
||||
|
||||
$range[ $this->START_LIMIT ] = $this->to_int( array_shift( $arr ), 0 );
|
||||
$range[ $this->START_MIDDLE ] = $this->to_int( array_shift( $arr ), 50 );
|
||||
$range[ $this->END_MIDDLE ] = $this->to_int( array_shift( $arr ), 50 );
|
||||
$range[ $this->END_LIMIT ] = $this->to_int( array_shift( $arr ), 100 );
|
||||
|
||||
sort( $range, SORT_NUMERIC );
|
||||
|
||||
$range[ $this->START_LIMIT ] = max( $range[ $this->START_LIMIT ], 0 );
|
||||
$range[ $this->END_LIMIT ] = min( $range[ $this->END_LIMIT ], 100 );
|
||||
$range[ $this->START_MIDDLE ] = max( $range[ $this->START_MIDDLE ], $range[ $this->START_LIMIT ] );
|
||||
$range[ $this->END_MIDDLE ] = min( $range[ $this->END_LIMIT ], $range[ $this->END_MIDDLE ] );
|
||||
|
||||
return array_merge( $range, $arr );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to a valid motion array value.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function split( $value ) {
|
||||
return $this->parse( $this->multi()->split( $value, $this->LENGTH ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to a valid motion string value.
|
||||
*
|
||||
* @param array $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function to_value( array $value ) {
|
||||
return $this->multi()->to_value( $this->parse( $value ), $this->LENGTH );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ET_Builder_Module_Helper_Multi_Value
|
||||
*/
|
||||
protected function multi() {
|
||||
return ET_Builder_Module_Helper_Multi_Value::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns specific key value
|
||||
*
|
||||
* @param int $key
|
||||
* @param string $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function get( $key, $value ) {
|
||||
$arr = $this->parse( $this->multi()->split( $value, $this->LENGTH ) );
|
||||
|
||||
return $arr[ $key ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $key
|
||||
* @param $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function set( $key, $value, $multi_value ) {
|
||||
return $this->multi()->set( $key, $value, $multi_value, $this->LENGTH );
|
||||
}
|
||||
|
||||
private function to_int( $value, $default ) {
|
||||
return is_numeric( $value ) ? (int) $value : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $min
|
||||
* @param int $max
|
||||
* @param int $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function range( $min, $max, $value ) {
|
||||
return min( $max, max( $min, $value ) );
|
||||
}
|
||||
}
|
13
includes/builder/module/helpers/motion/Opacity.php
Normal file
13
includes/builder/module/helpers/motion/Opacity.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
class ET_Builder_Module_Helper_Motion_Opacity extends ET_Builder_Module_Helper_Motion_Sanitizer {
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function sanitize( $value ) {
|
||||
return min( 100, max( 0, (int) $value ) ) . '%';
|
||||
}
|
||||
}
|
13
includes/builder/module/helpers/motion/Rotate.php
Normal file
13
includes/builder/module/helpers/motion/Rotate.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
class ET_Builder_Module_Helper_Motion_Rotate extends ET_Builder_Module_Helper_Motion_Sanitizer {
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function sanitize( $value ) {
|
||||
return min( 0, (int) $value ) . 'deg';
|
||||
}
|
||||
}
|
62
includes/builder/module/helpers/motion/Sanitizer.php
Normal file
62
includes/builder/module/helpers/motion/Sanitizer.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
abstract class ET_Builder_Module_Helper_Motion_Sanitizer extends ET_Builder_Module_Helper_Motion {
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getStartValue( $value ) {
|
||||
return $this->sanitize( parent::getStartValue( $value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setStartValue( $value, $multi_value ) {
|
||||
return parent::setStartValue( $this->sanitize( $value ), $multi_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMiddleValue( $value ) {
|
||||
return $this->sanitize( parent::getMiddleValue( $value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setMiddleValue( $value, $multi_value ) {
|
||||
return parent::setMiddleValue( $this->sanitize( $value ), $multi_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEndValue( $value ) {
|
||||
return $this->sanitize( parent::getEndValue( $value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param string $multi_value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setEndValue( $value, $multi_value ) {
|
||||
return parent::setEndValue( $this->sanitize( $value ), $multi_value );
|
||||
}
|
||||
|
||||
abstract protected function sanitize( $value );
|
||||
}
|
13
includes/builder/module/helpers/motion/Scale.php
Normal file
13
includes/builder/module/helpers/motion/Scale.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
class ET_Builder_Module_Helper_Motion_Scale extends ET_Builder_Module_Helper_Motion_Sanitizer {
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function sanitize( $value ) {
|
||||
return min( 0, (int) $value );
|
||||
}
|
||||
}
|
13
includes/builder/module/helpers/motion/Translate.php
Normal file
13
includes/builder/module/helpers/motion/Translate.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
class ET_Builder_Module_Helper_Motion_Translate extends ET_Builder_Module_Helper_Motion_Sanitizer {
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function sanitize( $value ) {
|
||||
return (float) $value;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user