You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1530 lines
55 KiB
PHTML
1530 lines
55 KiB
PHTML
8 months ago
|
<?php
|
||
|
|
||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||
|
die( 'Direct access forbidden.' );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Responsive options helper methods.
|
||
|
*
|
||
|
* @since 3.23 Add more helper functions. Originally, this class is introduced on Options Harmony v2.
|
||
|
* @since 3.22
|
||
|
*
|
||
|
* Class ET_Builder_Module_Helper_ResponsiveOptions
|
||
|
*/
|
||
|
class ET_Builder_Module_Helper_ResponsiveOptions {
|
||
|
|
||
|
const DESKTOP = 'desktop';
|
||
|
const TABLET = 'tablet';
|
||
|
const PHONE = 'phone';
|
||
|
|
||
|
public static function instance() {
|
||
|
static $instance;
|
||
|
|
||
|
return $instance ? $instance : $instance = new self();
|
||
|
}
|
||
|
|
||
|
private function __construct() {
|
||
|
// Now call me if you can
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get value from an array based on key. However, we can force to return default value if key
|
||
|
* doesn't exist or value is empty.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $list Array of values.
|
||
|
* @param string $key Target key.
|
||
|
* @param mixed $default Default value, return if the target doesn't exist.
|
||
|
* @param mixed $default_on_empty Force to return default if value is empty.
|
||
|
* @return mixed Value.
|
||
|
*/
|
||
|
private function get( $list, $key, $default = null, $default_on_empty = false ) {
|
||
|
$value = isset( $list[ $key ] ) ? $list[ $key ] : $default;
|
||
|
|
||
|
// Return default if we need non empty value to be used.
|
||
|
if ( $default_on_empty && empty( $value ) ) {
|
||
|
$value = $default;
|
||
|
}
|
||
|
|
||
|
return $value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if responsive settings is enabled or not on the option.
|
||
|
*
|
||
|
* Mostly used by FE.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $attrs All module attributes.
|
||
|
* @param string $name Option name.
|
||
|
* @return boolean Responsive settings status.
|
||
|
*/
|
||
|
public function is_responsive_enabled( $attrs, $name ) {
|
||
|
$last_edited = $this->get( $attrs, "{$name}_last_edited", '' );
|
||
|
return $this->get_responsive_status( $last_edited );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if responsive settings are enabled on one of the options list.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $attrs All module attributes.
|
||
|
* @param array $list Options list.
|
||
|
* @return boolean Responsive styles status.
|
||
|
*/
|
||
|
public function is_any_responsive_enabled( $attrs, $list ) {
|
||
|
// Ensure list is not empty and valid array.
|
||
|
if ( empty( $list ) || ! is_array( $list ) ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Check the responsive status one by one.
|
||
|
$is_responsive_enabled = false;
|
||
|
foreach ( $list as $name ) {
|
||
|
if ( $this->is_responsive_enabled( $attrs, $name ) ) {
|
||
|
// Break early if current field enabled responsive is found.
|
||
|
$is_responsive_enabled = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $is_responsive_enabled;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get responsive status based one last edited value.
|
||
|
*
|
||
|
* Parsed *_last_edited value and determine wheter the passed string means it has responsive value
|
||
|
* or not. *_last_edited holds two values (responsive status and last opened tabs) in the following
|
||
|
* format: status|last_opened_tab.
|
||
|
*
|
||
|
* Copy of et_pb_get_responsive_status() with a little modified and to organize the code.
|
||
|
*
|
||
|
* @param string $last_edited Last edited field value.
|
||
|
* @return bool Responsive field status.
|
||
|
*/
|
||
|
public function get_responsive_status( $last_edited ) {
|
||
|
if ( empty( $last_edited ) || ! is_string( $last_edited ) ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$parsed_last_edited = explode( '|', $last_edited );
|
||
|
|
||
|
return isset( $parsed_last_edited[0] ) ? 'on' === $parsed_last_edited[0] : false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate video background markup.
|
||
|
*
|
||
|
* When background support responsive settings, the default callback will be replaced with
|
||
|
* get_video_background() function to retrieve all video values for desktop, hover, tablet,
|
||
|
* and phone.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $args Background values.
|
||
|
* @param array $conditional_tags Conditional tags.
|
||
|
* @param array $current_page Current page info.
|
||
|
* @return mixed Mixed background content generated as video markup.
|
||
|
*/
|
||
|
public static function get_video_background( $args = array(), $conditional_tags = array(), $current_page = array() ) {
|
||
|
$base_name = isset( $args['computed_variables'] ) && isset( $args['computed_variables']['base_name'] ) ? $args['computed_variables']['base_name'] : 'background';
|
||
|
$attr_prefix = "{$base_name}_";
|
||
|
|
||
|
// Build custom args.
|
||
|
$default_args = array(
|
||
|
"{$attr_prefix}video_mp4" => isset( $args[ "{$attr_prefix}video_mp4" ] ) ? $args[ "{$attr_prefix}video_mp4" ] : '',
|
||
|
"{$attr_prefix}video_webm" => isset( $args[ "{$attr_prefix}video_webm" ] ) ? $args[ "{$attr_prefix}video_webm" ] : '',
|
||
|
"{$attr_prefix}video_width" => isset( $args[ "{$attr_prefix}video_width" ] ) ? $args[ "{$attr_prefix}video_width" ] : '',
|
||
|
"{$attr_prefix}video_height" => isset( $args[ "{$attr_prefix}video_height" ] ) ? $args[ "{$attr_prefix}video_height" ] : '',
|
||
|
'computed_variables' => array(
|
||
|
'base_name' => $base_name,
|
||
|
),
|
||
|
);
|
||
|
|
||
|
$hover_args = array(
|
||
|
"{$attr_prefix}video_mp4__hover" => isset( $args[ "{$attr_prefix}video_mp4__hover" ] ) ? $args[ "{$attr_prefix}video_mp4__hover" ] : '',
|
||
|
"{$attr_prefix}video_webm__hover" => isset( $args[ "{$attr_prefix}video_webm__hover" ] ) ? $args[ "{$attr_prefix}video_webm__hover" ] : '',
|
||
|
"{$attr_prefix}video_width__hover" => isset( $args[ "{$attr_prefix}video_width__hover" ] ) ? $args[ "{$attr_prefix}video_width__hover" ] : '',
|
||
|
"{$attr_prefix}video_height__hover" => isset( $args[ "{$attr_prefix}video_height__hover" ] ) ? $args[ "{$attr_prefix}video_height__hover" ] : '',
|
||
|
'computed_variables' => array(
|
||
|
'base_name' => $base_name,
|
||
|
'device' => '_hover',
|
||
|
),
|
||
|
);
|
||
|
|
||
|
$tablet_args = array(
|
||
|
"{$attr_prefix}video_mp4_tablet" => isset( $args[ "{$attr_prefix}video_mp4_tablet" ] ) ? $args[ "{$attr_prefix}video_mp4_tablet" ] : '',
|
||
|
"{$attr_prefix}video_webm_tablet" => isset( $args[ "{$attr_prefix}video_webm_tablet" ] ) ? $args[ "{$attr_prefix}video_webm_tablet" ] : '',
|
||
|
"{$attr_prefix}video_width_tablet" => isset( $args[ "{$attr_prefix}video_width_tablet" ] ) ? $args[ "{$attr_prefix}video_width_tablet" ] : '',
|
||
|
"{$attr_prefix}video_height_tablet" => isset( $args[ "{$attr_prefix}video_height_tablet" ] ) ? $args[ "{$attr_prefix}video_height_tablet" ] : '',
|
||
|
'computed_variables' => array(
|
||
|
'base_name' => $base_name,
|
||
|
'device' => 'tablet',
|
||
|
),
|
||
|
);
|
||
|
|
||
|
$phone_args = array(
|
||
|
"{$attr_prefix}video_mp4_phone" => isset( $args[ "{$attr_prefix}video_mp4_phone" ] ) ? $args[ "{$attr_prefix}video_mp4_phone" ] : '',
|
||
|
"{$attr_prefix}video_webm_phone" => isset( $args[ "{$attr_prefix}video_webm_phone" ] ) ? $args[ "{$attr_prefix}video_webm_phone" ] : '',
|
||
|
"{$attr_prefix}video_width_phone" => isset( $args[ "{$attr_prefix}video_width_phone" ] ) ? $args[ "{$attr_prefix}video_width_phone" ] : '',
|
||
|
"{$attr_prefix}video_height_phone" => isset( $args[ "{$attr_prefix}video_height_phone" ] ) ? $args[ "{$attr_prefix}video_height_phone" ] : '',
|
||
|
'computed_variables' => array(
|
||
|
'base_name' => $base_name,
|
||
|
'device' => 'phone',
|
||
|
),
|
||
|
);
|
||
|
|
||
|
$video_backgrounds = array();
|
||
|
|
||
|
// Get video background markup.
|
||
|
$background_video = ET_Builder_Element::get_video_background( $default_args );
|
||
|
if ( $background_video ) {
|
||
|
$video_backgrounds['desktop'] = $background_video;
|
||
|
}
|
||
|
|
||
|
$background_video_hover = ET_Builder_Element::get_video_background( $hover_args );
|
||
|
if ( $background_video_hover ) {
|
||
|
$video_backgrounds['hover'] = $background_video_hover;
|
||
|
}
|
||
|
|
||
|
$background_video_tablet = ET_Builder_Element::get_video_background( $tablet_args );
|
||
|
if ( $background_video_tablet ) {
|
||
|
$video_backgrounds['tablet'] = $background_video_tablet;
|
||
|
}
|
||
|
|
||
|
$background_video_phone = ET_Builder_Element::get_video_background( $phone_args );
|
||
|
if ( $background_video_phone ) {
|
||
|
$video_backgrounds['phone'] = $background_video_phone;
|
||
|
}
|
||
|
|
||
|
return $video_backgrounds;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the field original name by removing the `_tablet` or `_phone` suffix if it exists.
|
||
|
*
|
||
|
* Only remove tablet/phone string of the last setting name. Doesn't work for other format.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param string $name Setting name.
|
||
|
* @return string Base setting name.
|
||
|
*/
|
||
|
public function get_field_base_name( $name ) {
|
||
|
// Do not use rtim as it removes by character not by string. So, cases like `key_tablets`
|
||
|
// will be reduced to `key`.
|
||
|
$regex = '/(.*)(_tablet|_phone)$/';
|
||
|
$replace = '${1}';
|
||
|
return preg_replace( $regex, $replace, $name );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the field responsive name by adding the `_tablet` or `_phone` suffix if it exists.
|
||
|
*
|
||
|
* @since 3.27.4
|
||
|
*
|
||
|
* @param string $name Setting name.
|
||
|
* @param string $device Device name.
|
||
|
* @return string Field setting name.
|
||
|
*/
|
||
|
public function get_field_name( $name, $device = 'desktop' ) {
|
||
|
// Field name should not be empty.
|
||
|
if ( empty( $name ) ) {
|
||
|
return $name;
|
||
|
}
|
||
|
|
||
|
// Ensure device is not empty.
|
||
|
$device = '' === $device ? 'desktop' : $device;
|
||
|
|
||
|
// Get device name.
|
||
|
return 'desktop' !== $device ? "{$name}_{$device}" : $name;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the device name by removing the `name` prefix. If the result is one of tablet or phone,
|
||
|
* return it. But, if it's empty, return desktop.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param string $name Setting name.
|
||
|
* @return string Device name.
|
||
|
*/
|
||
|
public function get_device_name( $name ) {
|
||
|
// Do not use rtim as it removes by character not by string. So, cases like `key_tablets`
|
||
|
// will be reduced to `key`.
|
||
|
$regex = '/(.*)(tablet|phone)$/';
|
||
|
$replace = '${2}';
|
||
|
$result = preg_replace( $regex, $replace, $name );
|
||
|
return in_array( $result, array( 'tablet', 'phone' ) ) ? $result : 'desktop';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get responsive value based on field base name and device.
|
||
|
*
|
||
|
* NOTE: Function get_single_value() is different with get_any_value(). It will return only
|
||
|
* current field value without checking the previous device value.
|
||
|
*
|
||
|
* For example: We have Title Text Font Size -> desktop 30px, tablet 10px, phone 10px. Fetch
|
||
|
* the value for phone, it will return pure 10px even the value is same with tablet.
|
||
|
* We have Subtitle Text Font Size -> desktop 20px, tablet 15px, phone ''. Fetch
|
||
|
* the value for phone, it will return pure '' or default even the value is empty.
|
||
|
*
|
||
|
* To get tablet or phone value:
|
||
|
* 1. You can pass only field base name and device name as the 4th argument. The parameters
|
||
|
* structure it's made like that to make it similar with other get* method we already have.
|
||
|
* For example: get_single_value( $this->props, 'title_text_font_size', '', 'tablet' ).
|
||
|
*
|
||
|
* 2. Or you can pass the actual field name with device. If the field name is already contains
|
||
|
* _tablet and _phone, don't pass device parameter because it will be added as suffix.
|
||
|
* For example: get_single_value( $this->props, 'title_text_font_size_tablet', '' ).
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $attrs All module attributes.
|
||
|
* @param string $name Option name.
|
||
|
* @param array $default_value Default value.
|
||
|
* @param string $device Current device name.
|
||
|
* @return mixed Current option value based on active device.
|
||
|
*/
|
||
|
public function get_single_value( $attrs, $name = '', $default_value = '', $device = 'desktop' ) {
|
||
|
// Ensure $device is not empty.
|
||
|
$device = '' === $device ? 'desktop' : $device;
|
||
|
|
||
|
// Ensure always use device as suffix if device is not desktop or empty.
|
||
|
if ( 'desktop' !== $device ) {
|
||
|
$base_name = $this->get_field_base_name( $name );
|
||
|
$name = "{$base_name}_{$device}";
|
||
|
}
|
||
|
|
||
|
return $this->get( $attrs, $name, $default_value, true );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get current active device value from attributes.
|
||
|
*
|
||
|
* NOTE: Function get_any_value() is different with get_value(). It also compare the value
|
||
|
* with the previous device value to avoid duplication. Or you can also force to return
|
||
|
* either current or previous default value if needed.
|
||
|
*
|
||
|
* For example: We have Title Text Font Size -> desktop 30px, tablet 30px, phone 10px. When
|
||
|
* we fetch the value for tablet, it will return pure empty string ('') because
|
||
|
* tablet value is equal with desktop value.
|
||
|
*
|
||
|
* We have Title Text Font Size -> desktop 30px, tablet '', phone ''. When
|
||
|
* we fetch the value for phone and force it to return any value, it will
|
||
|
* return 30px because phone and tablet value is empty and the function will
|
||
|
* look up to tablet or even desktop value.
|
||
|
*
|
||
|
* To get tablet or phone value:
|
||
|
* 1. You can pass only field base name and device name as the 4th argument. The parameters
|
||
|
* structure it's made like that to make it similar with other get* method we already have.
|
||
|
* For example: get_any_value( $this->props, 'title_text_font_size', '', 'tablet' ).
|
||
|
*
|
||
|
* 2. Or you can pass the actual field name with device. If the field name is already contains
|
||
|
* _tablet and _phone, don't pass device parameter because it will be added as suffix.
|
||
|
* For example: get_any_value( $this->props, 'title_text_font_size_tablet', '' ).
|
||
|
*
|
||
|
* 3. You can also force to return any value by passing true on the 5th argument. In some cases
|
||
|
* we need this to fill missing tablet/phone value with desktop value.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $attrs All module attributes.
|
||
|
* @param string $name Option name.
|
||
|
* @param array $default_value Default value.
|
||
|
* @param bool $force_return Force to return any value.
|
||
|
* @param string $device Current device name.
|
||
|
* @return mixed Current option value based on active device.
|
||
|
*/
|
||
|
public function get_any_value( $attrs, $name = '', $default_value = '', $force_return = false, $device = 'desktop' ) {
|
||
|
// Ensure $device is not empty.
|
||
|
$device = '' === $device ? 'desktop' : $device;
|
||
|
|
||
|
// Ensure always use device as suffix if device is not desktop/empty.
|
||
|
if ( 'desktop' !== $device ) {
|
||
|
$base_name = $this->get_field_base_name( $name );
|
||
|
$name = "{$base_name}_{$device}";
|
||
|
}
|
||
|
|
||
|
// Get current value.
|
||
|
$current_value = $this->get( $attrs, $name, '' );
|
||
|
|
||
|
// Get previous value to be compared.
|
||
|
$prev_value = $this->get_default_value( $attrs, $name, $default_value );
|
||
|
|
||
|
// Force to return any values given.
|
||
|
if ( $force_return ) {
|
||
|
return ! empty( $current_value ) ? $current_value : $prev_value;
|
||
|
}
|
||
|
|
||
|
// Ensure current value is different with the previous device or default.
|
||
|
if ( $current_value === $prev_value ) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
return $current_value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get property's values for requested device.
|
||
|
*
|
||
|
* This function is added to summarize how we fetch desktop/hover/tablet/phone value. This
|
||
|
* function still uses get_any_value to get current device values.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $attrs List of all attributes and values.
|
||
|
* @param string $name Property name.
|
||
|
* @param mixed $default_value Default value.
|
||
|
* @param string $device Device name.
|
||
|
* @param boolean $force_return Force to return any values found.
|
||
|
*
|
||
|
* @return array Pair of devices and the values.
|
||
|
*/
|
||
|
public function get_property_value( $attrs, $name, $default_value = '', $device = 'desktop', $force_return = false ) {
|
||
|
// Default values.
|
||
|
$default_value = esc_attr( $default_value );
|
||
|
|
||
|
// Ensure $device is not empty.
|
||
|
$device = '' === $device ? 'desktop' : $device;
|
||
|
|
||
|
// Ensure attrs (values list) and name (property name) are not empty.
|
||
|
if ( empty( $attrs ) || '' === $name ) {
|
||
|
return $default_value;
|
||
|
}
|
||
|
|
||
|
$is_enabled = 'desktop' !== $device ? $this->is_responsive_enabled( $attrs, $name ) : true;
|
||
|
$suffix = 'desktop' !== $device ? "_{$device}" : '';
|
||
|
$value = $is_enabled ? $this->get_any_value( $attrs, "{$name}{$suffix}", $default_value, $force_return ) : $default_value;
|
||
|
|
||
|
return esc_attr( $value );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get all properties values for all devices.
|
||
|
*
|
||
|
* This function is added to summarize how we fetch desktop/hover, tablet, and phone values. This
|
||
|
* function still use get_any_value to get current device values.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $attrs List of all attributes and values.
|
||
|
* @param string $name Property name.
|
||
|
* @param mixed $default_value Default value.
|
||
|
* @param boolean $force_return Force to return any values found.
|
||
|
*
|
||
|
* @return array Pair of devices and the values.
|
||
|
*/
|
||
|
public function get_property_values( $attrs, $name, $default_value = '', $force_return = false ) {
|
||
|
// Default values.
|
||
|
$default_value = esc_attr( $default_value );
|
||
|
$values = array(
|
||
|
'desktop' => $default_value,
|
||
|
'tablet' => $default_value,
|
||
|
'phone' => $default_value,
|
||
|
);
|
||
|
|
||
|
// Ensure attrs (values list) and name (property name) are not empty.
|
||
|
if ( empty( $attrs ) || '' === $name ) {
|
||
|
return $values;
|
||
|
}
|
||
|
|
||
|
$is_responsive = $this->is_responsive_enabled( $attrs, $name );
|
||
|
|
||
|
// Get values for each devices.
|
||
|
$values['desktop'] = esc_html( $this->get_any_value( $attrs, $name, $default_value, $force_return ) );
|
||
|
if ( $is_responsive ) {
|
||
|
$values['tablet'] = esc_html( $this->get_any_value( $attrs, "{$name}_tablet", $default_value, $force_return ) );
|
||
|
$values['phone'] = esc_html( $this->get_any_value( $attrs, "{$name}_phone", $default_value, $force_return ) );
|
||
|
}
|
||
|
|
||
|
return $values;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get property value after checking whether it uses responsive or not
|
||
|
*
|
||
|
* If responsive is used, automatically return array of all devices value.
|
||
|
* If responsive is not used, return string of desktop value
|
||
|
*
|
||
|
* @since 4.6.0
|
||
|
*
|
||
|
* @param array $attrs List of all attributes and values.
|
||
|
* @param string $name Property name.
|
||
|
* @param mixed $default_value Default value.
|
||
|
* @param boolean $force_return Force to return any values found.
|
||
|
*
|
||
|
* @return string|array String if not responsive, Pair of devices and the values if responsive.
|
||
|
*/
|
||
|
public function get_checked_property_value( $attrs, $name, $default_value = '', $force_return = false ) {
|
||
|
$is_responsive = $this->is_responsive_enabled( $attrs, $name );
|
||
|
|
||
|
return $is_responsive ?
|
||
|
$this->get_property_values( $attrs, $name, $default_value, $force_return ) :
|
||
|
$this->get_property_value( $attrs, $name, $default_value, 'desktop', $force_return );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get composite property's value for requested device.
|
||
|
*
|
||
|
* This function is added to summarize how we fetch desktop/hover/tablet/phone value. This
|
||
|
* function still uses get_any_value to get current device values.
|
||
|
*
|
||
|
* @since 3.27.4
|
||
|
*
|
||
|
* @param array $attrs List of all attributes and values.
|
||
|
* @param string $composite_name Composite property name.
|
||
|
* @param string $name Property name.
|
||
|
* @param mixed $default_value Default value.
|
||
|
* @param string $device Device name.
|
||
|
* @param boolean $force_return Force to return any values found.
|
||
|
*
|
||
|
* @return array Pair of devices and the values.
|
||
|
*/
|
||
|
public function get_composite_property_value( $attrs, $composite_name, $name, $default_value = '', $device = 'desktop', $force_return = false ) {
|
||
|
// Default values.
|
||
|
$default_value = esc_attr( $default_value );
|
||
|
|
||
|
// Ensure $device is not empty.
|
||
|
$device = '' === $device ? 'desktop' : $device;
|
||
|
|
||
|
// Ensure attrs, composite name (parent property name), name (property name) are not empty.
|
||
|
if ( empty( $attrs ) || '' === $composite_name || '' === $name ) {
|
||
|
return $default_value;
|
||
|
}
|
||
|
|
||
|
$is_enabled = 'desktop' !== $device ? $this->is_responsive_enabled( $attrs, $composite_name ) : true;
|
||
|
$suffix = 'desktop' !== $device ? "_{$device}" : '';
|
||
|
$value = $is_enabled ? $this->get_any_value( $attrs, "{$name}{$suffix}", $default_value, $force_return ) : $default_value;
|
||
|
|
||
|
return esc_attr( $value );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get all composite properties values for all devices.
|
||
|
*
|
||
|
* This function is added to summarize how we fetch desktop/hover, tablet, and phone values. This
|
||
|
* function still use get_any_value to get current device values.
|
||
|
*
|
||
|
* @since 3.27.4
|
||
|
*
|
||
|
* @param array $attrs List of all attributes and values.
|
||
|
* @param string $composite_name Composite property name.
|
||
|
* @param string $name Property name.
|
||
|
* @param mixed $default_value Default value.
|
||
|
* @param boolean $force_return Force to return any values found.
|
||
|
*
|
||
|
* @return array Pair of devices and the values.
|
||
|
*/
|
||
|
public function get_composite_property_values( $attrs, $composite_name, $name, $default_value = '', $force_return = false ) {
|
||
|
// Default values.
|
||
|
$default_value = esc_attr( $default_value );
|
||
|
$values = array(
|
||
|
'desktop' => $default_value,
|
||
|
'tablet' => $default_value,
|
||
|
'phone' => $default_value,
|
||
|
);
|
||
|
|
||
|
// Ensure attrs, composite name (parent property name), name (property name) are not empty.
|
||
|
if ( empty( $attrs ) || '' === $composite_name || '' === $name ) {
|
||
|
return $values;
|
||
|
}
|
||
|
|
||
|
$is_responsive = $this->is_responsive_enabled( $attrs, $composite_name );
|
||
|
|
||
|
// Get values for each devices.
|
||
|
$values['desktop'] = esc_attr( $this->get_any_value( $attrs, $name, $default_value, $force_return ) );
|
||
|
if ( $is_responsive ) {
|
||
|
$values['tablet'] = esc_attr( $this->get_any_value( $attrs, "{$name}_tablet", $default_value, $force_return ) );
|
||
|
$values['phone'] = esc_attr( $this->get_any_value( $attrs, "{$name}_phone", $default_value, $force_return ) );
|
||
|
}
|
||
|
|
||
|
return $values;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get multiple attributes value from current active device.
|
||
|
*
|
||
|
* Basically, this function is combination of:
|
||
|
* - Get any value of attribute
|
||
|
* - Check attribute responsive status for tablet/phone
|
||
|
* - Only send non empty attributes, except you force to return any given value
|
||
|
* - Doing all of the process above for more than one fields
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $attrs All module attributes.
|
||
|
* @param string $list List of options name. Name should be field base name.
|
||
|
* @param bool $force_return Force to return any value.
|
||
|
* @param string $device Current device name.
|
||
|
* @return array All option values.
|
||
|
*/
|
||
|
public function get_any_responsive_values( $attrs, $list, $force_return = false, $device = 'desktop' ) {
|
||
|
// Ensure list is not empty and valid array.
|
||
|
if ( empty( $list ) || ! is_array( $list ) ) {
|
||
|
return array();
|
||
|
}
|
||
|
|
||
|
// Ensure device is not empty.
|
||
|
$device = '' === $device ? 'desktop' : $device;
|
||
|
|
||
|
// Fetch each attribute and store it in $values.
|
||
|
$values = array();
|
||
|
foreach ( $list as $field_key => $field_value ) {
|
||
|
// Check responsive status if current device is tablet or phone.
|
||
|
if ( 'desktop' !== $device && ! $this->is_responsive_enabled( $attrs, $field_key ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Get value.
|
||
|
$value = $this->get_any_value( $attrs, $field_key, $field_value, $force_return, $device );
|
||
|
|
||
|
// No need to save the value if it's empty and we don't force to return any value.
|
||
|
if ( ! $force_return && empty( $value ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$values[ $field_key ] = $value;
|
||
|
}
|
||
|
|
||
|
return $values;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get default value of active device. Mechanism:
|
||
|
*
|
||
|
* - Desktop => Return default value.
|
||
|
* - Tablet => Return desktop value or default value.
|
||
|
* - Phone => Return tablet value or desktop value or default value.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $attrs All module attributes.
|
||
|
* @param string $name Option name.
|
||
|
* @param array $default_value All module advanced defaults.
|
||
|
* @return mixed Previous option value based on active device.
|
||
|
*/
|
||
|
public function get_default_value( $attrs, $name = '', $default_value = '' ) {
|
||
|
// Get option base name.
|
||
|
$base_name = $this->get_field_base_name( $name );
|
||
|
$device = $this->get_device_name( $name );
|
||
|
|
||
|
// Get default value and return it for Desktop.
|
||
|
if ( 'desktop' === $device ) {
|
||
|
return $default_value;
|
||
|
}
|
||
|
|
||
|
// Get tablet value and return it for Tablet.
|
||
|
$desktop_value = $this->get( $attrs, "{$base_name}", $default_value, true );
|
||
|
if ( 'tablet' === $device ) {
|
||
|
return $desktop_value;
|
||
|
}
|
||
|
|
||
|
// Get phone value and return it for Phone.
|
||
|
$tablet_value = $this->get( $attrs, "{$base_name}_tablet", $desktop_value, true );
|
||
|
if ( 'phone' === $device ) {
|
||
|
return $tablet_value;
|
||
|
}
|
||
|
|
||
|
return $default_value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns responsive modes list from largest to narrow
|
||
|
*
|
||
|
* @return string[]
|
||
|
*/
|
||
|
public function get_modes() {
|
||
|
return array( self::DESKTOP, self::TABLET, self::PHONE );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns next wider mode then provided
|
||
|
*
|
||
|
* @param $mode
|
||
|
*
|
||
|
* @return null|string
|
||
|
*/
|
||
|
public function get_wider_mode( $mode ) {
|
||
|
$modes = $this->get_modes();
|
||
|
$key = array_search( $this->validate_mode( $mode ), $modes );
|
||
|
|
||
|
return false != $key ? et_()->array_get( $modes, '[' . ( -- $key ) . ']', null ) : null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns next narrower mode then provided
|
||
|
*
|
||
|
* @param $mode
|
||
|
*
|
||
|
* @return null|string
|
||
|
*/
|
||
|
public function get_narrower_mode( $mode ) {
|
||
|
$modes = $this->get_modes();
|
||
|
$key = array_search( $this->validate_mode( $mode ), $modes );
|
||
|
|
||
|
return false !== $key && isset( $modes[ $key + 1 ] ) ? $modes[ $key + 1 ] : null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return default responsive mode
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function get_default_mode() {
|
||
|
return self::DESKTOP;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns setting field name by responsive mode
|
||
|
*
|
||
|
* @param $setting
|
||
|
* @param $mode
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function get_field( $setting, $mode ) {
|
||
|
return $setting . $this->mode_field( (string) $this->validate_mode( $mode ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns setting field name of the last edited mode
|
||
|
*
|
||
|
* @param string $setting
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function get_last_edited_field( $setting ) {
|
||
|
return "{$setting}_last_edited";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if setting responsive mode is enabled
|
||
|
*
|
||
|
* @param $setting
|
||
|
* @param $props
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function is_enabled( $setting, $props ) {
|
||
|
$value = et_builder_module_prop( $this->get_last_edited_field( $this->get_field_base_name( $setting ) ), $props, '' );
|
||
|
|
||
|
return et_pb_get_responsive_status( $value );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the props value by mode
|
||
|
* If no mode provided, the default mode is used
|
||
|
*
|
||
|
* @param $setting
|
||
|
* @param $props
|
||
|
* @param null $mode
|
||
|
* @param string $default
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function get_value( $setting, $props, $mode = null, $default = '' ) {
|
||
|
$mode = $this->get_mode_or_default( $mode );
|
||
|
|
||
|
if ( $this->get_default_mode() != $mode && ! $this->is_enabled( $setting, $props ) ) {
|
||
|
return $default;
|
||
|
}
|
||
|
|
||
|
return et_builder_module_prop( $this->get_field( $setting, $mode ), $props, $default );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Is the implementation of get_value specifically for desktop mode
|
||
|
*
|
||
|
* Note: since the desktop mode is the default mode,
|
||
|
* this method would similar to get_value without providing mode,
|
||
|
* but can be used for a more explicit representation
|
||
|
*
|
||
|
* @param string $setting
|
||
|
* @param array $props
|
||
|
* @param mixed $default
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function get_desktop_value( $setting, $props, $default = null ) {
|
||
|
return $this->get_value( $setting, $props, self::DESKTOP, $default );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Is the implementation of get_value specifically for tablet mode
|
||
|
*
|
||
|
* @param string $setting
|
||
|
* @param array $props
|
||
|
* @param mixed $default
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function get_tablet_value( $setting, $props, $default = null ) {
|
||
|
return $this->get_value( $setting, $props, self::TABLET, $default );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Is the implementation of get_value specifically for phone mode
|
||
|
*
|
||
|
* @param string $setting
|
||
|
* @param array $props
|
||
|
* @param mixed $default
|
||
|
*
|
||
|
* @return mixed
|
||
|
*/
|
||
|
public function get_phone_value( $setting, $props, $default = null ) {
|
||
|
return $this->get_value( $setting, $props, self::PHONE, $default );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the last edited responsive mode of the provided setting
|
||
|
* If not valid value is provided, default mode is returned
|
||
|
*
|
||
|
* @param $setting
|
||
|
* @param $props
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function get_last_edited( $setting, $props ) {
|
||
|
$value = et_builder_module_prop( $this->get_last_edited_field( $setting ), $props, '' );
|
||
|
$mode = et_()->array_get( explode( '|', $value ), '[1]' );
|
||
|
|
||
|
return $this->validate_mode( $mode ) ? $mode : $this->get_default_mode();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get breakpoint minimum widths
|
||
|
*
|
||
|
* @since 4.3.2
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function get_breakpoint_min_widths() {
|
||
|
return array(
|
||
|
'desktop' => 980,
|
||
|
'tablet' => 768,
|
||
|
'phone' => 0,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get breakpoint based on device name.
|
||
|
*
|
||
|
* @since 4.0
|
||
|
*
|
||
|
* @param string $device
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function get_breakpoint_by_device( $device = 'desktop' ) {
|
||
|
switch ( $device ) {
|
||
|
case 'desktop_only':
|
||
|
return 'min_width_981';
|
||
|
case 'tablet':
|
||
|
return 'max_width_980';
|
||
|
case 'tablet_only':
|
||
|
return '768_980';
|
||
|
case 'desktop_tablet_only':
|
||
|
return 'min_width_768';
|
||
|
case 'phone':
|
||
|
return 'max_width_767';
|
||
|
default:
|
||
|
return 'general';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param $mode
|
||
|
*
|
||
|
* @return bool|string
|
||
|
*/
|
||
|
protected function validate_mode( $mode ) {
|
||
|
return in_array( strtolower( $mode ), $this->get_modes() ) ? strtolower( $mode ) : false;
|
||
|
}
|
||
|
|
||
|
protected function get_mode_or_default( $mode ) {
|
||
|
return $this->validate_mode( $mode ) ? strtolower( $mode ) : $this->get_default_mode();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns mode suffix
|
||
|
* The default mode suffix is empty
|
||
|
*
|
||
|
* @param $mode
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function mode_field( $mode ) {
|
||
|
switch ( $mode ) {
|
||
|
case $this->get_default_mode():
|
||
|
return '';
|
||
|
default:
|
||
|
return "_$mode";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generates the css code for responsive options.
|
||
|
*
|
||
|
* Uses array of values for each device as input parameter and css_selector with property to
|
||
|
* apply the css.
|
||
|
*
|
||
|
* Copy of et_pb_generate_responsive_css() with some modifications to improve.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $values_array All device values.
|
||
|
* @param mixed $css_selector CSS selector.
|
||
|
* @param string $css_property CSS property.
|
||
|
* @param string $function_name Module slug.
|
||
|
* @param string $additional_css Additional CSS.
|
||
|
* @param string $type Value type to determine need filter or not. Previously, it only
|
||
|
* accept value from range control and run a function to process
|
||
|
* range value.
|
||
|
* @param string $priority CSS style declaration priority.
|
||
|
*/
|
||
|
public function generate_responsive_css( $values_array, $css_selector, $css_property, $function_name, $additional_css = '', $type = 'range', $priority = '' ) {
|
||
|
if ( empty( $values_array ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
foreach ( $values_array as $device => $current_value ) {
|
||
|
if ( empty( $current_value ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// 1. Selector.
|
||
|
// There are some cases where selector is an object contains specific selector for
|
||
|
// each devices.
|
||
|
$selector = $css_selector;
|
||
|
if ( is_array( $css_selector ) ) {
|
||
|
$selector = ! empty( $css_selector[ $device ] ) ? $css_selector[ $device ] : '';
|
||
|
}
|
||
|
|
||
|
if ( empty( $selector ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// 2. Declare CSS style.
|
||
|
// There are some cases before we can declare the CSS style:
|
||
|
// 1. The value is an array contains pair of properties and values.
|
||
|
// 2. The value is single string but we have multiple properties exist.
|
||
|
// 3. The value is single string with only one property.
|
||
|
$declaration = '';
|
||
|
|
||
|
// Value can be provided as a string or array in following format:
|
||
|
// array(
|
||
|
// 'property_1' => 'value_1', 'property_2' => 'value_2', ... ,
|
||
|
// 'property_n' => 'value_n'
|
||
|
// )
|
||
|
if ( is_array( $current_value ) ) {
|
||
|
foreach ( $current_value as $this_property => $this_value ) {
|
||
|
if ( empty( $this_property ) || '' === $this_value ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Get valid value. Previously, it only works for range control value and run
|
||
|
// et_builder_process_range_value function directly. Keep it as it is now for
|
||
|
// backward compatibility.
|
||
|
$valid_value = $this_value;
|
||
|
if ( 'range' === $type ) {
|
||
|
$valid_value = et_builder_process_range_value( $this_value, $this_property );
|
||
|
}
|
||
|
|
||
|
$declaration .= sprintf(
|
||
|
'%1$s: %2$s%3$s',
|
||
|
$this_property,
|
||
|
esc_html( $valid_value ),
|
||
|
'' !== $additional_css ? $additional_css : ';'
|
||
|
);
|
||
|
}
|
||
|
} elseif ( is_array( $css_property ) ) {
|
||
|
// Get valid value. Previously, it only works for range control value and run
|
||
|
// et_builder_process_range_value function directly.
|
||
|
$valid_value = $current_value;
|
||
|
|
||
|
foreach ( $css_property as $this_property ) {
|
||
|
if ( empty( $this_property ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( 'range' === $type ) {
|
||
|
$valid_value = et_builder_process_range_value( $current_value, $this_property );
|
||
|
}
|
||
|
|
||
|
$declaration .= sprintf(
|
||
|
'%1$s: %2$s%3$s',
|
||
|
$this_property,
|
||
|
esc_html( $valid_value ),
|
||
|
'' !== $additional_css ? $additional_css : ';'
|
||
|
);
|
||
|
}
|
||
|
} elseif ( ! empty( $css_property ) ) {
|
||
|
// Get valid value. Previously, it only works for range control value and run
|
||
|
// et_builder_process_range_value function directly.
|
||
|
$valid_value = $current_value;
|
||
|
if ( 'range' === $type ) {
|
||
|
$valid_value = et_builder_process_range_value( $current_value, $css_property );
|
||
|
}
|
||
|
|
||
|
$declaration = sprintf(
|
||
|
'%1$s: %2$s%3$s',
|
||
|
$css_property,
|
||
|
esc_html( $valid_value ),
|
||
|
'' !== $additional_css ? $additional_css : ';'
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ( '' === $declaration ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$style = array(
|
||
|
'selector' => $selector,
|
||
|
'declaration' => $declaration,
|
||
|
);
|
||
|
|
||
|
if ( 'desktop_only' === $device ) {
|
||
|
$style['media_query'] = ET_Builder_Element::get_media_query( 'min_width_981' );
|
||
|
} elseif ( 'desktop' !== $device ) {
|
||
|
$current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767';
|
||
|
$style['media_query'] = ET_Builder_Element::get_media_query( $current_media_query );
|
||
|
}
|
||
|
|
||
|
// Priority.
|
||
|
if ( '' !== $priority ) {
|
||
|
$style['priority'] = $priority;
|
||
|
}
|
||
|
|
||
|
ET_Builder_Element::set_style( $function_name, $style );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generates the CSS code for responsive options based on existing declaration.
|
||
|
*
|
||
|
* Similar with generate_responsive_css(), but it's only used to declare the CSS and selector
|
||
|
* without set styles on ET_Builder_Element.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param array $values_array All device values.
|
||
|
* @param mixed $css_selector CSS selector.
|
||
|
* @param string $function_name Module slug.
|
||
|
* @param string $priority CSS style declaration priority.
|
||
|
*/
|
||
|
public function declare_responsive_css( $values_array, $css_selector, $function_name, $priority = '' ) {
|
||
|
if ( empty( $values_array ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
foreach ( $values_array as $device => $declaration ) {
|
||
|
if ( empty( $declaration ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
$style = array(
|
||
|
'selector' => $css_selector,
|
||
|
'declaration' => $declaration,
|
||
|
);
|
||
|
|
||
|
// Media query.
|
||
|
if ( 'desktop_only' === $device ) {
|
||
|
$style['media_query'] = ET_Builder_Element::get_media_query( 'min_width_981' );
|
||
|
} elseif ( 'desktop' !== $device ) {
|
||
|
$current_media_query = 'tablet' === $device ? 'max_width_980' : 'max_width_767';
|
||
|
$style['media_query'] = ET_Builder_Element::get_media_query( $current_media_query );
|
||
|
}
|
||
|
|
||
|
// Priority.
|
||
|
if ( '' !== $priority ) {
|
||
|
$style['priority'] = $priority;
|
||
|
}
|
||
|
|
||
|
ET_Builder_Element::set_style( $function_name, $style );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generate additional responsive fields such as _tablet, _phone, and _last_edited.
|
||
|
*
|
||
|
* @since 3.23
|
||
|
*
|
||
|
* @param string $field_name Base field name.
|
||
|
* @param string $toggle_slug Toggle slug name.
|
||
|
* @param string $tab_slug Tab slug name.
|
||
|
* @param array $field Field data in array.
|
||
|
* @return array Responsive fields set.
|
||
|
*/
|
||
|
public function generate_responsive_fields( $field_name, $toggle_slug, $tab_slug, $field = array() ) {
|
||
|
$responsive_options = array();
|
||
|
|
||
|
// Add fields with responsive suffix for each devices.
|
||
|
$responsive_options[ "{$field_name}_tablet" ] = array(
|
||
|
'type' => 'skip',
|
||
|
'tab_slug' => $tab_slug,
|
||
|
'toggle_slug' => $toggle_slug,
|
||
|
);
|
||
|
$responsive_options[ "{$field_name}_phone" ] = array(
|
||
|
'type' => 'skip',
|
||
|
'tab_slug' => $tab_slug,
|
||
|
'toggle_slug' => $toggle_slug,
|
||
|
);
|
||
|
$responsive_options[ "{$field_name}_last_edited" ] = array(
|
||
|
'type' => 'skip',
|
||
|
'tab_slug' => $tab_slug,
|
||
|
'toggle_slug' => $toggle_slug,
|
||
|
);
|
||
|
|
||
|
// Add computed effect field on mobile and hover fields.
|
||
|
if ( ! empty( $field['computed_affects'] ) && isset( $field['affects_mobile'] ) && true === $field['affects_mobile'] ) {
|
||
|
$responsive_options[ "{$field_name}_tablet" ]['computed_affects'] = $field['computed_affects'];
|
||
|
$responsive_options[ "{$field_name}_phone" ]['computed_affects'] = $field['computed_affects'];
|
||
|
|
||
|
$responsive_options[ "{$field_name}__hover" ] = array(
|
||
|
'type' => 'skip',
|
||
|
'tab_slug' => $tab_slug,
|
||
|
'toggle_slug' => $toggle_slug,
|
||
|
'computed_affects' => $field['computed_affects'],
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Set default on tablet and phone if needed.
|
||
|
if ( ! empty( $field['default_on_mobile'] ) ) {
|
||
|
$default = ! empty( $field['default'] ) ? $field['default'] : '';
|
||
|
$default_mobile = ! empty( $field['default_on_mobile'] ) ? $field['default_on_mobile'] : $default;
|
||
|
$default_tablet = ! empty( $field['default_on_tablet'] ) ? $field['default_on_tablet'] : $default_mobile;
|
||
|
$default_phone = ! empty( $field['default_on_phone'] ) ? $field['default_on_phone'] : $default_mobile;
|
||
|
|
||
|
$responsive_options[ "{$field_name}_tablet" ]['default'] = $default_tablet;
|
||
|
$responsive_options[ "{$field_name}_phone" ]['default'] = $default_phone;
|
||
|
}
|
||
|
|
||
|
// Set default on hover if needed.
|
||
|
if ( ! empty( $field['default_on_hover'] ) ) {
|
||
|
$default = ! empty( $field['default'] ) ? $field['default'] : '';
|
||
|
$default_hover = ! empty( $field['default_on_hover'] ) ? $field['default_on_hover'] : $default_mobile;
|
||
|
|
||
|
$responsive_options[ "{$field_name}__hover" ]['default'] = $default_hover;
|
||
|
}
|
||
|
|
||
|
return $responsive_options;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get main background value based on enabled status of current field. It's used to selectively
|
||
|
* get the correct color, gradient status, image, and video. It's introduced along with new
|
||
|
* enable fields to decide should we remove or inherit the value from larger device.
|
||
|
*
|
||
|
* @since 3.24.1
|
||
|
*
|
||
|
* @param array $attrs All module attributes.
|
||
|
* @param string $base_setting Setting need to be checked.
|
||
|
* @param string $preview_mode Current preview mode.
|
||
|
* @param string $background_base Background base name (background, button_bg, etc.)
|
||
|
* @param array $fields All module fields definition.
|
||
|
* @param string $value Active value.
|
||
|
* @param string $default_value Active default value.
|
||
|
*
|
||
|
* @return string New value.
|
||
|
*/
|
||
|
public function get_inheritance_background_value( $attrs, $base_setting, $preview_mode, $background_base = 'background', $fields = array(), $value = '', $default_value = '' ) {
|
||
|
// Default new value is same with the generated or active one.
|
||
|
$new_value = $value;
|
||
|
|
||
|
$enable_fields = array(
|
||
|
"{$background_base}_color" => "{$background_base}_enable_color",
|
||
|
'use_background_color_gradient' => 'use_background_color_gradient',
|
||
|
"{$background_base}_use_color_gradient" => "{$background_base}_use_color_gradient",
|
||
|
"{$background_base}_image" => "{$background_base}_enable_image",
|
||
|
"video_{$background_base}_values" => "video_{$background_base}_values",
|
||
|
"{$background_base}_pattern_style" => "{$background_base}_enable_pattern_style",
|
||
|
"{$background_base}_mask_style" => "{$background_base}_enable_mask_style",
|
||
|
);
|
||
|
|
||
|
// Empty string is slug for desktop.
|
||
|
$map_slugs = array(
|
||
|
'desktop' => array( '' ),
|
||
|
'hover' => array( '__hover', '' ),
|
||
|
'sticky' => array( '__sticky', '' ),
|
||
|
'tablet' => array( '_tablet', '' ),
|
||
|
'phone' => array( '_phone', '_tablet', '' ),
|
||
|
);
|
||
|
|
||
|
// Start checking if current field is enabled or disabled.
|
||
|
$base_enable_field_name = ! empty( $enable_fields[ $base_setting ] ) ? $enable_fields[ $base_setting ] : '';
|
||
|
|
||
|
// Bail early if setting name is different.
|
||
|
if ( '' === $base_enable_field_name || ! isset( $map_slugs[ $preview_mode ] ) ) {
|
||
|
return $new_value;
|
||
|
}
|
||
|
|
||
|
$new_value = '';
|
||
|
|
||
|
$origin_mp4_enabled = '';
|
||
|
$origin_mp4_data = array();
|
||
|
$origin_webm_enabled = '';
|
||
|
$origin_webm_data = array();
|
||
|
|
||
|
foreach ( $map_slugs[ $preview_mode ] as $slug ) {
|
||
|
|
||
|
// BG Color, BG Image, BG Pattern, BG Mask.
|
||
|
if (
|
||
|
in_array(
|
||
|
$base_setting,
|
||
|
array(
|
||
|
"{$background_base}_color",
|
||
|
"{$background_base}_image",
|
||
|
"{$background_base}_pattern_style",
|
||
|
"{$background_base}_mask_style",
|
||
|
),
|
||
|
true
|
||
|
)
|
||
|
) {
|
||
|
$base_type = str_replace( "{$background_base}_", '', $base_setting );
|
||
|
$enable_default = ! empty( $fields[ "{$background_base}_enable_{$base_type}{$slug}" ] ) && ! empty( $fields[ "{$background_base}_enable_{$base_type}{$slug}" ]['default'] ) ? $fields[ "{$background_base}_enable_{$base_type}{$slug}" ]['default'] : '';
|
||
|
$enable_value = ! empty( $attrs[ "{$background_base}_enable_{$base_type}{$slug}" ] ) ? $attrs[ "{$background_base}_enable_{$base_type}{$slug}" ] : $enable_default;
|
||
|
$setting_value = ! empty( $attrs[ "{$background_base}_{$base_type}{$slug}" ] ) ? $attrs[ "{$background_base}_{$base_type}{$slug}" ] : '';
|
||
|
$is_tab_enabled = 'off' !== $enable_value;
|
||
|
|
||
|
if ( '' !== $setting_value && $is_tab_enabled ) {
|
||
|
$new_value = $setting_value;
|
||
|
break;
|
||
|
} elseif ( ! $is_tab_enabled ) {
|
||
|
$new_value = '';
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// BG Gradient.
|
||
|
} elseif ( in_array( $base_setting, array( 'use_background_color_gradient', "{$background_base}_use_color_gradient" ), true ) ) {
|
||
|
|
||
|
$new_value = 'off';
|
||
|
|
||
|
$field_map = array(
|
||
|
'use_background_color_gradient' => array(
|
||
|
'value' => "use_background_color_gradient{$slug}",
|
||
|
'start' => "{$background_base}_color_gradient_start{$slug}",
|
||
|
'end' => "{$background_base}_color_gradient_end{$slug}",
|
||
|
'stops' => "{$background_base}_color_gradient_stops{$slug}",
|
||
|
'unit' => "{$background_base}_color_gradient_unit{$slug}",
|
||
|
),
|
||
|
"{$background_base}_use_color_gradient" => array(
|
||
|
'value' => "{$background_base}_use_color_gradient{$slug}",
|
||
|
'start' => "{$background_base}_color_gradient_start{$slug}",
|
||
|
'end' => "{$background_base}_color_gradient_end{$slug}",
|
||
|
'stops' => "{$background_base}_color_gradient_stops{$slug}",
|
||
|
'unit' => "{$background_base}_color_gradient_unit{$slug}",
|
||
|
),
|
||
|
);
|
||
|
|
||
|
$field_value = '';
|
||
|
$field_start = '';
|
||
|
$field_end = '';
|
||
|
$field_stops = '';
|
||
|
|
||
|
if ( ! empty( $field_map[ $base_setting ] ) ) {
|
||
|
$field_value = ! empty( $field_map[ $base_setting ]['value'] ) ? $field_map[ $base_setting ]['value'] : '';
|
||
|
$field_start = ! empty( $field_map[ $base_setting ]['start'] ) ? $field_map[ $base_setting ]['start'] : '';
|
||
|
$field_end = ! empty( $field_map[ $base_setting ]['end'] ) ? $field_map[ $base_setting ]['end'] : '';
|
||
|
$field_stops = ! empty( $field_map[ $base_setting ]['stops'] ) ? $field_map[ $base_setting ]['stops'] : '';
|
||
|
}
|
||
|
|
||
|
// Set value from attrs, otherwise, assign default value, for desktop/tablet/phone.
|
||
|
$use_gradient_value = $this->get_any_value( $attrs, $field_value, 'off', true );
|
||
|
$gradient_start_value = $this->get_any_value( $attrs, $field_start, '', true );
|
||
|
$gradient_end_value = $this->get_any_value( $attrs, $field_end, '', true );
|
||
|
$gradient_stops_value = $this->get_any_value( $attrs, $field_stops, '', true );
|
||
|
|
||
|
// Set value from attrs, otherwise, assign value from desktop.
|
||
|
if ( in_array( $slug, array( '__hover', '__sticky' ), true ) ) {
|
||
|
$use_gradient_value = ! empty( $attrs[ $field_value ] ) ? $attrs[ $field_value ] : $use_gradient_value;
|
||
|
$gradient_start_value = ! empty( $attrs[ $field_start ] ) ? $attrs[ $field_start ] : $gradient_start_value;
|
||
|
$gradient_end_value = ! empty( $attrs[ $field_end ] ) ? $attrs[ $field_end ] : $gradient_end_value;
|
||
|
$gradient_stops_value = ! empty( $attrs[ $field_stops ] ) ? $attrs[ $field_stops ] : $gradient_stops_value;
|
||
|
}
|
||
|
|
||
|
$is_gradient_enabled = 'off' !== $use_gradient_value;
|
||
|
|
||
|
if ( ( '' !== $gradient_stops_value || ( '' !== $gradient_start_value || '' !== $gradient_end_value ) ) && $is_gradient_enabled ) {
|
||
|
$new_value = 'on';
|
||
|
break;
|
||
|
} elseif ( ! $is_gradient_enabled ) {
|
||
|
$new_value = 'off';
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// BG Video.
|
||
|
} elseif ( "video_{$background_base}_values" === $base_setting ) {
|
||
|
$base_slug = preg_replace( '/[_]+/', '', $slug );
|
||
|
$current_mode = '' !== $base_slug ? $base_slug : 'desktop';
|
||
|
|
||
|
// Video markup.
|
||
|
$video_background = et_()->array_get( $attrs, "{$base_setting}.{$current_mode}", '' );
|
||
|
|
||
|
// MP4.
|
||
|
$enable_mp4_default = et_()->array_get( $fields, "{$background_base}_enable_video_mp4{$slug}", '' );
|
||
|
$enable_mp4_value = $this->get_any_value( $attrs, "{$background_base}_enable_video_mp4{$slug}", $enable_mp4_default, true );
|
||
|
$is_mp4_enabled = 'off' !== $enable_mp4_value;
|
||
|
|
||
|
$video_mp4_value = et_pb_responsive_options()->get_any_value( $attrs, "{$background_base}_video_mp4" );
|
||
|
if ( 'hover' === $current_mode ) {
|
||
|
$video_mp4_hover_value = et_()->array_get( $attrs, "{$background_base}_video_mp4__hover", '' );
|
||
|
$video_mp4_value = '' !== $video_mp4_hover_value ? $video_mp4_hover_value : $video_mp4_value;
|
||
|
} else {
|
||
|
$video_mp4_value = et_pb_responsive_options()->get_any_value( $attrs, "{$background_base}_video_mp4{$slug}", '', true );
|
||
|
}
|
||
|
|
||
|
// Check MP4 enabled and data status.
|
||
|
if ( '' === $origin_mp4_enabled ) {
|
||
|
if ( '' !== $video_mp4_value && $is_mp4_enabled ) {
|
||
|
$origin_mp4_enabled = 'enabled';
|
||
|
$origin_mp4_data = array(
|
||
|
'mode' => $current_mode,
|
||
|
'video_value' => $video_mp4_value,
|
||
|
'video_background' => $video_background,
|
||
|
'display' => ! empty( $video_background ) ? 'self' : 'inherit',
|
||
|
);
|
||
|
} elseif ( false === $is_mp4_enabled ) {
|
||
|
$origin_mp4_enabled = 'disabled';
|
||
|
$origin_mp4_data = array();
|
||
|
}
|
||
|
} elseif ( 'enabled' === $origin_mp4_enabled ) {
|
||
|
if ( isset( $origin_mp4_data['video_background'] ) && empty( $origin_mp4_data['video_background'] ) ) {
|
||
|
$origin_mp4_data['video_background'] = $video_background;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Webm.
|
||
|
$enable_webm_default = et_()->array_get( $fields, "{$background_base}_enable_video_webm{$slug}", '' );
|
||
|
$enable_webm_value = $this->get_any_value( $attrs, "{$background_base}_enable_video_webm{$slug}", $enable_webm_default, true );
|
||
|
$is_webm_enabled = 'off' !== $enable_webm_value;
|
||
|
|
||
|
$video_webm_value = et_pb_responsive_options()->get_any_value( $attrs, "{$background_base}_video_webm" );
|
||
|
if ( 'hover' === $current_mode ) {
|
||
|
$video_webm_hover_value = et_()->array_get( $attrs, "{$background_base}_video_webm__hover", '' );
|
||
|
$video_webm_value = '' !== $video_webm_hover_value ? $video_webm_hover_value : $enable_webm_value;
|
||
|
} else {
|
||
|
$video_webm_value = et_pb_responsive_options()->get_any_value( $attrs, "{$background_base}_video_webm{$slug}", '', true );
|
||
|
}
|
||
|
|
||
|
// Check Webm enabled and data status.
|
||
|
if ( '' === $origin_webm_enabled ) {
|
||
|
if ( '' !== $video_webm_value && $is_webm_enabled ) {
|
||
|
$origin_webm_enabled = 'enabled';
|
||
|
$origin_webm_data = array(
|
||
|
'mode' => $current_mode,
|
||
|
'video_value' => $video_webm_value,
|
||
|
'video_background' => $video_background,
|
||
|
'display' => ! empty( $video_background ) ? 'self' : 'inherit',
|
||
|
);
|
||
|
} elseif ( ! $is_webm_enabled ) {
|
||
|
$origin_webm_enabled = 'disabled';
|
||
|
$origin_webm_data = array();
|
||
|
}
|
||
|
} elseif ( 'enabled' === $origin_webm_enabled ) {
|
||
|
if ( isset( $origin_webm_data['video_background'] ) && empty( $origin_webm_data['video_background'] ) ) {
|
||
|
$origin_webm_data['video_background'] = $video_background;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Continue if current mode is not desktop.
|
||
|
if ( '' !== $slug ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Decide to display the video or not.
|
||
|
if ( 'disabled' === $origin_mp4_enabled && 'disabled' === $origin_webm_enabled ) {
|
||
|
$new_value = array(
|
||
|
'display' => 'hide',
|
||
|
'video' => '',
|
||
|
);
|
||
|
} else {
|
||
|
// MP4 display and video status.
|
||
|
$mp4_enabled_display = et_()->array_get( $origin_mp4_data, 'display', '' );
|
||
|
$mp4_enabled_mode = et_()->array_get( $origin_mp4_data, 'mode', '' );
|
||
|
$mp4_video_background = '';
|
||
|
if ( $preview_mode === $mp4_enabled_mode ) {
|
||
|
$mp4_video_background = et_()->array_get( $origin_mp4_data, 'video_background', '' );
|
||
|
}
|
||
|
|
||
|
// Webm display and video status.
|
||
|
$webm_enabled_display = et_()->array_get( $origin_webm_data, 'display', '' );
|
||
|
$webm_enabled_mode = et_()->array_get( $origin_webm_data, 'mode', '' );
|
||
|
$webm_video_background = '';
|
||
|
if ( $preview_mode === $webm_enabled_mode ) {
|
||
|
$webm_video_background = et_()->array_get( $origin_webm_data, 'video_background', '' );
|
||
|
}
|
||
|
|
||
|
// Set display current video or not.
|
||
|
$new_video_display = 'hide';
|
||
|
if ( '' !== $mp4_enabled_display ) {
|
||
|
$new_video_display = $mp4_enabled_display;
|
||
|
} elseif ( '' !== $webm_enabled_display ) {
|
||
|
$new_video_display = $webm_enabled_display;
|
||
|
}
|
||
|
|
||
|
// Set video markup.
|
||
|
$new_video_background = '';
|
||
|
if ( '' !== $mp4_video_background ) {
|
||
|
$new_video_background = $mp4_video_background;
|
||
|
} elseif ( '' !== $webm_video_background ) {
|
||
|
$new_video_background = $webm_video_background;
|
||
|
}
|
||
|
|
||
|
$new_value = array(
|
||
|
'display' => $new_video_display,
|
||
|
'video' => $new_video_background,
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $new_value;
|
||
|
}
|
||
|
|
||
|
public function create( $additional_options ) {
|
||
|
// Add hover field indication
|
||
|
$additional_options['hover_enabled'] = array(
|
||
|
'type' => 'skip',
|
||
|
'default' => 0,
|
||
|
);
|
||
|
|
||
|
// Generate responsive fields for additional options (Design).
|
||
|
// There are 4 types where the mobile_options exist on the options.
|
||
|
// 1. Exist on the option definition.
|
||
|
// 2. Exist on the computed field type, just like point 1 but we threat it differently
|
||
|
// because there are some properties need to be updated and added.
|
||
|
// 3. Exist on the background-field.
|
||
|
// 4. Exist on the composite field.
|
||
|
foreach ( $additional_options as $field_name => $field ) {
|
||
|
$is_mobile_options = isset( $field['mobile_options'] ) && $field['mobile_options'];
|
||
|
$is_hover = isset( $field['hover'] ) && 'tabs' === $field['hover'];
|
||
|
$field_type = isset( $field['type'] ) ? $field['type'] : '';
|
||
|
$field_context = isset( $field['context'] ) ? $field['context'] : '';
|
||
|
$field_last_edited = isset( $field['last_edited'] ) ? $field['last_edited'] : '';
|
||
|
|
||
|
// Mobile options property maybe exist on the field.
|
||
|
if ( $is_mobile_options ) {
|
||
|
// Get tab and toggle slugs value.
|
||
|
$tab_slug = isset( $field['tab_slug'] ) ? $field['tab_slug'] : '';
|
||
|
$toggle_slug = isset( $field['toggle_slug'] ) ? $field['toggle_slug'] : '';
|
||
|
|
||
|
// 2. Mobile options property for computed fields.
|
||
|
if ( 'computed' === $field_type ) {
|
||
|
// Computed depends on. Add suffix after depends on info.
|
||
|
if ( ! empty( $field['computed_depends_on'] ) ) {
|
||
|
$computed_depends_on = $field['computed_depends_on'];
|
||
|
foreach ( $computed_depends_on as $depends_value ) {
|
||
|
if ( $is_hover ) {
|
||
|
array_push( $field['computed_depends_on'], "{$depends_value}_tablet", "{$depends_value}_phone", "{$depends_value}__hover" );
|
||
|
} else {
|
||
|
array_push( $field['computed_depends_on'], "{$depends_value}_tablet", "{$depends_value}_phone" );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Computed minimum. Add suffix after minimum info.
|
||
|
if ( ! empty( $field['computed_minimum'] ) ) {
|
||
|
$computed_minimum = $field['computed_minimum'];
|
||
|
foreach ( $computed_minimum as $minimum_value ) {
|
||
|
if ( $is_hover ) {
|
||
|
array_push( $field['computed_minimum'], "{$minimum_value}_tablet", "{$minimum_value}_phone", "{$minimum_value}__hover" );
|
||
|
} else {
|
||
|
array_push( $field['computed_minimum'], "{$minimum_value}_tablet", "{$minimum_value}_phone" );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$additional_options[ "{$field_name}" ] = $field;
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// 3. Mobile options property maybe exist under background field.
|
||
|
if ( 'background-field' === $field_type ) {
|
||
|
// Just in case current field is background-field and the mobile_options
|
||
|
// attributes are located in the fields. Ensure background fields is exist.
|
||
|
if ( ! empty( $field['background_fields'] ) ) {
|
||
|
// Fetch the fields and check for mobile_options.
|
||
|
foreach ( $field['background_fields'] as $background_name => $background_field ) {
|
||
|
if ( isset( $background_field['mobile_options'] ) && $background_field['mobile_options'] ) {
|
||
|
// Get tab and toggle slugs value.
|
||
|
$tab_slug = isset( $background_field['tab_slug'] ) ? $background_field['tab_slug'] : '';
|
||
|
$toggle_slug = isset( $background_field['toggle_slug'] ) ? $background_field['toggle_slug'] : '';
|
||
|
|
||
|
// Add fields with responsive suffix for each devices.
|
||
|
$additional_options = array_merge(
|
||
|
$additional_options,
|
||
|
et_pb_responsive_options()->generate_responsive_fields( $background_name, $toggle_slug, $tab_slug )
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// 1. Mobile options property added directly on options definition. Add fields
|
||
|
// with responsive suffix for each devices.
|
||
|
$additional_options = array_merge(
|
||
|
$additional_options,
|
||
|
et_pb_responsive_options()->generate_responsive_fields( $field_name, $toggle_slug, $tab_slug, $field )
|
||
|
);
|
||
|
|
||
|
// Additional last edited field just in case we need more last edited field.
|
||
|
if ( ! empty( $field_last_edited ) ) {
|
||
|
$additional_options[ "{$field_last_edited}_last_edited" ] = array(
|
||
|
'type' => 'skip',
|
||
|
'tab_slug' => $tab_slug,
|
||
|
'toggle_slug' => $toggle_slug,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// 4. Mobile options property maybe exist under composite field.
|
||
|
if ( 'composite' === $field_type ) {
|
||
|
// Just in case current field is composite and the mobile_options attributes
|
||
|
// are located in the controls. Ensure composite structure is exist.
|
||
|
$composite_structure = isset( $field['composite_structure'] ) ? $field['composite_structure'] : array();
|
||
|
if ( empty( $composite_structure ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
foreach ( $composite_structure as $composite_field ) {
|
||
|
// Ensure composite field controls is exist and not empty.
|
||
|
$composite_field_controls = isset( $composite_field['controls'] ) ? $composite_field['controls'] : array();
|
||
|
if ( empty( $composite_field_controls ) ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Fetch the controls and check for mobile_options.
|
||
|
foreach ( $composite_field_controls as $control_name => $control ) {
|
||
|
if ( isset( $control['mobile_options'] ) && $control['mobile_options'] ) {
|
||
|
// Get tab and toggle slugs value.
|
||
|
$tab_slug = isset( $control['tab_slug'] ) ? $control['tab_slug'] : '';
|
||
|
$toggle_slug = isset( $control['toggle_slug'] ) ? $control['toggle_slug'] : '';
|
||
|
|
||
|
// Add fields with responsive suffix for each devices.
|
||
|
$additional_options = array_merge(
|
||
|
$additional_options,
|
||
|
et_pb_responsive_options()->generate_responsive_fields( $control_name, $toggle_slug, $tab_slug )
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return $additional_options;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|