/home/techb158/public_html/wp-content/plugins/kirki/includes/Frontend/Preview
Edit: /home/techb158/public_html/wp-content/plugins/kirki/includes/Frontend/Preview/Preview.php (84092B)
global, migrated, symbols. etc.
*/
protected $style_blocks = array();
/**
* $only_used_style_blocks only used style blocks.
*/
private $only_used_style_blocks = array();
/**
* $only_used_popup_id_array only used popup post ids.
*/
public static $only_used_popup_id_array = array();
/**
* $printed_font_family_tracker for tracking already printed font family markup.
*/
private static $printed_font_family_tracker = array();
private static $printed_variable_tracker = array();
private static $section_id_tracker_for_href = array(); // ['section_id' => 'Section-2', 'section_id_1' => 'section-2-1' ]
/**
* $view_ports user all viewports data.
*/
private $view_ports = array();
/**
* Initialize some variables for element related data. Like: custom codes, lightbox, map, slider etc.
* START
*/
/**
* $sliders for collect slider elements data.
*/
private $sliders = array();
/**
* $navigation for collect navigation elements data.
*/
private $navigations = array();
/**
* $navigation item for collect navigation item elements data.
*/
private $navigation_item = array();
/**
* $inputs for collect inputs elements data.
*/
private $inputs = array();
/**
* $maps for collect map elements data.
*/
private $maps = array();
/**
* $lotties for collect lottie elements data.
*/
private $lotties = array();
/**
* $popups for collect popup elements data.
*/
private $popups = array();
/**
* $tabs for collect tab elements data.
*/
private $tabs = array();
/**
* $lightboxes for collect lightbox elements data.
*/
private $lightboxes = array();
/**
* $re_captchas for collect reCaptcha elements data.
*/
private $re_captchas = array();
/**
* $videos for collect video elements data.
*/
private $videos = array();
/**
* $interactions for collect interaction elements data.
*/
private $interactions = array();
/**
* $interaction library for collect interaction library elements data.
*/
private $interaction_library = array();
/**
* $collections for collect collection elements data.
*/
private $collections = array();
/**
* $forms for collect form elements data.
*/
private $forms = array();
/**
* $liquid_glass for liquid glass effect
*/
private $liquid_glass = array();
/**
* $custom_codes for collect customCode elements data.
*/
public $custom_codes = '';
/**
* $dropdown for collect dropdown elements data.
*/
private $dropdown = array();
/**
* Initialize some variables for element related data. Like: custom codes, lightbox, map, slider etc.
* END
*/
/**
* elements wise variable modes array.
*/
private $ele_variable_modes = array();
/**
* interaction ['scroll-into-ele'] & ['scroll-out-ele'] tracker
*/
private $interaction_preset_and_text_animation_tracker = array();
private $interaction_library_text_animation_tracker = array();
private $scroll_into_custom_interaction_tracker = '';
private $track_animation_for_elements_with_this_class = '';
private $track_animation_for_children_with_this_class = '';
private $track_animation_for_sibling_with_this_class = '';
private $track_animation_for_trigger_sibling_with_this_class = '';
private $track_animation_for_trigger_with_this_class = '';
/**
* END
*/
/**
* List of exceptional elements.
*/
private $exceptional_elements = array(
'custom-code',
'map',
'svg',
'svg-icon',
'textarea',
'select',
'video',
'radio-group',
'checkbox-element',
'radio-button',
'image',
'collection',
'loading', // collection loading element
'items',
'collection-wrapper',
'users',
'pagination',
'pagination-item',
'pagination-number',
'terms',
'menus',
'symbol',
'link-block',
'form',
'button',
'popup-body',
'navigation',
'navigation-item',
'navigation-items',
'section',
'common',
'slider',
'slider_mask',
'slider_nav',
'tabs',
'tab_menu',
'tab',
'tab_content',
'tab_pane'
);
/**
* List of dynamic content element.
*/
private $exceptional_elements_contains_dyn_content = array( 'collection' );
/**
* List of inline elements.
*/
private $inline_elements = array( 'button', 'link-block', 'link-text' );
/**
* List of anchor elements.
*/
private $prevent_anchor_elements = array( 'heading', 'image', 'paragraph' );
/**
* List anchor attrs.
*/
private $anchor_attrs = array( 'href', 'target', 'rel' );
/**
* Preview script initilizer
*
* @param array $data elments data array.
* @param array $style_blocks elments style_blocks array.
* @param string $root root element id.
* @param string $symbol_id if preview script is initiate for symbol element generation.
*
* @return void
*/
public function __construct( $data, $style_blocks, $root = null, $symbol_id = null, $prefix = false ) {
if ( $root ) {
$this->root = $root;
} else {
$this->root = 'root';
}
$this->data = $data;
$this->style_blocks = $style_blocks;
$this->view_ports = UserData::get_view_port_list();
if ( $symbol_id ) {
$this->symbol_id = $symbol_id;
}
$this->prefix = $prefix;
}
/**
* Get the html string
*
* @return string
*/
public function getHTML( $options = array() ) {
$this->include_component_field_metadata = ! empty( $options['include_component_field_metadata'] );
// TODO: need to fix this code
// if(!isset($options['user']) && get_current_user_id() > 0){
// $options['user'] = Users::get_user_by_id(get_current_user_id());
// }
return $this->recGenHTML( $this->root, $options );
}
/**
* Get the style blocks that are used in the html
* this method is called after getHtml() method call and from the same instance
*
* @return string
*/
public function get_only_used_style_blocks() {
return $this->only_used_style_blocks;
}
public function add_to_only_used_style_blocks( $style_block ) {
$this->only_used_style_blocks[ $style_block['id'] ] = $style_block;
if ( isset( $style_block['liquid-glass'] ) ) {
$this->liquid_glass[ $style_block['id'] ] = array(
'id' => $style_block['id'],
'name' => $style_block['name'],
'liquid-glass' => $style_block['liquid-glass'],
'type' => $style_block['type'],
'prefix' => $this->prefix,
);
}
}
private function updateTranslateCSSString( $end ) {
$transforms = array();
if ( ! empty( $end['x']['unit'] ) && $end['x']['unit'] !== 'auto' ) {
$transforms[] = 'translateX(' . $this->addUnit( $end['x'] ) . ')';
}
if ( ! empty( $end['y']['unit'] ) && $end['y']['unit'] !== 'auto' ) {
$transforms[] = 'translateY(' . $this->addUnit( $end['y'] ) . ')';
}
if ( ! empty( $end['z']['unit'] ) && $end['z']['unit'] !== 'auto' ) {
$transforms[] = 'translateZ(' . $this->addUnit( $end['z'] ) . ')';
}
return implode( ' ', $transforms ); // Return only the transform part
}
private function updateRotateCSSString( $end ) {
$rotateProperties = array();
if ( $end['x']['unit'] !== 'auto' ) {
$rotateProperties[] = 'rotateX(' . $this->addUnit( $end['x'] ) . ')';
}
if ( $end['y']['unit'] !== 'auto' ) {
$rotateProperties[] = 'rotateY(' . $this->addUnit( $end['y'] ) . ')';
}
if ( $end['z']['unit'] !== 'auto' ) {
$rotateProperties[] = 'rotateZ(' . $this->addUnit( $end['z'] ) . ')';
}
return implode( ' ', $rotateProperties );
}
private function updateSkewCSSString( $end ) {
$skewProperties = array();
if ( $end['x']['unit'] !== 'auto' ) {
$skewProperties[] = 'skewX(' . $this->addUnit( $end['x'] ) . ')';
}
if ( $end['y']['unit'] !== 'auto' ) {
$skewProperties[] = 'skewY(' . $this->addUnit( $end['y'] ) . ')';
}
return implode( ' ', $skewProperties );
}
private function updateScaleCSSString( $end ) {
$scaleProperties = array();
if ( $end['x']['unit'] !== 'none' ) {
$scaleProperties[] = 'scaleX(' . $end['x']['value'] . ')';
}
if ( $end['y']['unit'] !== 'none' ) {
$scaleProperties[] = 'scaleY(' . $end['y']['value'] . ')';
}
return implode( ' ', $scaleProperties );
}
private function addUnit( $valueObj ) {
$specialValues = array( 'auto', 'fit-content', 'min-content', 'max-content', 'none', 'scrollHeight', 'scrollWidth' );
// Check if the unit is in specialValues, if so, don't append it
$unit = in_array( $valueObj['unit'], $specialValues ) ? '' : $valueObj['unit'];
return $valueObj['value'] . $unit;
}
private function updateCssStringForAnimation( $property, $end ) {
$css = '';
$transformProperties = array(); // Store all transform values
switch ( $property ) {
case 'move':
$transformProperties[] = $this->updateTranslateCSSString( $end );
break;
case 'rotate':
$transformProperties[] = $this->updateRotateCSSString( $end );
break;
case 'scale':
$transformProperties[] = $this->updateScaleCSSString( $end );
break;
case 'size':
$css .= 'width: ' . ( $end['width']['value'] === 'scrollWidth' ? 'auto' : $this->addUnit( $end['width'] ) ) . ';';
$css .= 'height: ' . ( $end['height']['value'] === 'scrollHeight' ? 'auto' : $this->addUnit( $end['height'] ) ) . ';';
break;
case 'skew':
$transformProperties[] = $this->updateSkewCSSString( $end );
break;
case 'fade':
$css .= 'opacity: ' . $end['value'] . ';';
break;
case 'color':
$css .= 'color: ' . $end['value'] . '; fill: ' . $end['value'] . ';';
break;
case 'border-color':
$css .= 'border-color: ' . $end['value'] . ';';
break;
case 'border-radius':
$css .= 'border-top-left-radius: ' . $this->addUnit( $end['border-top-left-radius'] ) . ';';
$css .= 'border-top-right-radius: ' . $this->addUnit( $end['border-top-right-radius'] ) . ';';
$css .= 'border-bottom-right-radius: ' . $this->addUnit( $end['border-bottom-right-radius'] ) . ';';
$css .= 'border-bottom-left-radius: ' . $this->addUnit( $end['border-bottom-left-radius'] ) . ';';
break;
case 'background-color':
$css .= 'background: ' . $end['value'] . ';';
break;
case 'background-size-position':
$css .= 'background-size: ' . $this->addUnit( $end['sizeWidth'] ) . ' ' . $this->addUnit( $end['sizeHeight'] ) . ';';
$css .= 'background-position-x: ' . $this->addUnit( $end['positionX'] ) . ';';
$css .= 'background-position-y: ' . $this->addUnit( $end['positionY'] ) . ';';
break;
case 'background-size':
$css .= 'background-size: ' . $this->addUnit( $end['sizeWidth'] ) . ' ' . $this->addUnit( $end['sizeHeight'] ) . ';';
break;
case 'background-position':
$css .= 'background-position-x: ' . $this->addUnit( $end['positionX'] ) . ';';
$css .= 'background-position-y: ' . $this->addUnit( $end['positionY'] ) . ';';
break;
case 'filter':
$filters = array();
foreach ( $end as $key => $value ) {
$filters[] = "$key(" . $this->addUnit( $value ) . ')';
}
$css .= 'filter: ' . implode( ' ', $filters ) . ';';
break;
default:
break;
}
if ( ! empty( $transformProperties ) ) {
$css .= implode( ' ', array_unique( $transformProperties ) );
$transformProperties = array(); // Reset for the next element
}
return $css;
}
/**
* Get the style tag string
*
* @param array|bool $blocks all styleblocks.
* @return string
*/
public function getStyleTag( $blocks = false ) {
if ( ! $blocks ) {
$blocks = $this->style_blocks;
}
$s = '';
if ( count( $this->ele_variable_modes ) > 0 ) {
$s .= $this->getElementWiseVariableCssCodes();
}
if ( $blocks ) {
foreach ( $this->view_ports as $key => $vp ) {
$css = '';
foreach ( $blocks as $style_block ) {
$css .= $this->getRawCssDeviceWise( $style_block, $vp );
}
if ( $css ) {
$s .= "';
}
}
}
return $s;
}
public function get_interaction_set_as_initial_css() {
$s = '';
if ( count( $this->interaction_preset_and_text_animation_tracker ) > 0 || count( $this->interaction_library_text_animation_tracker ) > 0 ) {
$animation_css = '';
foreach ( $this->interaction_preset_and_text_animation_tracker as $ele_id => $bool ) {
$animation_css .= "[data-kirki='" . $ele_id . "'] { visibility: hidden; }";
}
foreach ( $this->interaction_library_text_animation_tracker as $ele_id => $devices ) {
$css_value = "[data-kirki='" . $ele_id . "'] { visibility: hidden; }";
$media_queries = ! empty( $devices ) ? $this->setMediaQuery( $css_value, $devices ) : '';
$animation_css .= ! empty( $media_queries ) ? $media_queries : $css_value;
}
if ( $animation_css ) {
$s .= "';
}
}
if ( $this->scroll_into_custom_interaction_tracker ) {
$s .= "';
}
if ( $this->track_animation_for_elements_with_this_class ) {
$s .= "';
}
if ( $this->track_animation_for_children_with_this_class ) {
$s .= "';
}
if ( $this->track_animation_for_sibling_with_this_class ) {
$s .= "';
}
if ( $this->track_animation_for_trigger_sibling_with_this_class ) {
$s .= "';
}
if ( $this->track_animation_for_trigger_with_this_class ) {
$s .= "';
}
return $s;
}
private function setInitialAnimation( $ele_id, $animations, $single_res_value ) {
$elementStyleValues = array();
$hasClassName = false;
$css = '';
$media_queries = '';
foreach ( $animations as $ani_key => $animation ) {
if ( ! empty( $animation['setAsInitial'] ) && $animation['setAsInitial'] ) {
foreach ( $this->processElementStyles( $ele_id, $animation ) as $key => $value ) {
if ( ! isset( $elementStyleValues[ $key ] ) ) {
$elementStyleValues[ $key ] = array(
'transform' => $value['transform'] ?? array(),
'other' => $value['other'] ?? array(),
);
} else {
$elementStyleValues[ $key ]['transform'] = array_merge(
$elementStyleValues[ $key ]['transform'] ?? array(),
$value['transform'] ?? array()
);
$elementStyleValues[ $key ]['other'] = array_merge(
$elementStyleValues[ $key ]['other'] ?? array(),
$value['other'] ?? array()
);
}
}
}
}
if ( ! empty( $elementStyleValues ) ) {
$css .= $this->setAnimationStyles( $elementStyleValues, $hasClassName );
$media_queries = $this->getMediaQuery( $css, $single_res_value );
$this->scroll_into_custom_interaction_tracker .= ! empty( $media_queries ) ? $media_queries : $css;
}
}
private function setAnimationStyles( $elementStyleValues, $hasClassName ) {
$s = '';
foreach ( $elementStyleValues as $ele_id => $styles ) {
if ( empty( $styles['transform'] ) && empty( $styles['other'] ) ) {
continue;
}
$css = $hasClassName ? '' : "[data-kirki='$ele_id'] { ";
$css .= ! empty( $styles['transform'] ) ? 'transform: ' . implode( ' ', $styles['transform'] ) . '; ' : '';
$css .= ! empty( $styles['other'] ) ? implode( ' ', $styles['other'] ) : '';
$css .= $hasClassName ? '' : ' }';
$s .= $css;
}
return $s;
}
private function processElementStyles( $ele_id, $animation ) {
$elementStyles = array(); // Ensure the array is initialized properly
if ( ! isset( $elementStyles[ $ele_id ] ) ) {
$elementStyles[ $ele_id ] = array(
'transform' => array(),
'other' => array(),
);
}
if ( ! isset( $animation['property'] ) || ! isset( $animation['end'] ) ) {
return array(); // Skip invalid animations
}
$cssValue = $this->updateCssStringForAnimation( $animation['property'], $animation['end'] );
if ( ! empty( $cssValue ) ) {
switch ( $animation['property'] ) {
case 'move':
case 'rotate':
case 'scale':
case 'skew':
$elementStyles[ $ele_id ]['transform'][] = $cssValue;
break;
default:
$elementStyles[ $ele_id ]['other'][] = $cssValue;
break;
}
}
return $elementStyles;
}
/**
* Get the html string
*
* @param array $block single style block.
* @param array $vp viewport.
*
* @return string
*/
private function getRawCssDeviceWise( $block, $vp ) {
$css_string = '';
$selector = $this->getSelectorFromBlock( $block );
$variants = $block['variant'];
$global_css = "";
$local_css = "";
foreach ( $variants as $key => $value ) {
$variant = explode( '_', $key );
if ( $variant[0] === $vp['id'] ) {
if( $block && isset($block['isGlobalStyle']) && $block['isGlobalStyle'] === true){
$global_css .= $this->createMediaQueryString( $selector, $key, $value, $vp );
}else{
$local_css .= $this->createMediaQueryString( $selector, $key, $value, $vp );
}
}
}
return $global_css . $local_css;
}
/**
* Create Media Query String
*
* @param string $selector calss/tag selector like => .class-name.
* @param string $device_name media query key like => md.
* @param string $css_text css text like => color:red.
* @param object $vp current viewport object.
*
* @return string
*/
private function createMediaQueryString( $selector, $device_name, $css_text, $vp ) {
if ( $css_text === '' ) {
return '';
}
$css_string = '';
$variant = explode( '_', $device_name );
$type = $vp['type'];
if ( count( $variant ) === 1 ) {
// default class or sub class for devices.
if ( $variant[0] === 'md' ) {
$css_string .= $selector . '{' . $css_text . '}';
} elseif ( isset( $this->view_ports[ $variant[0] ] ) ) {
$css_string .= '@media only screen and (' . $type . '-width: ' . $this->view_ports[ $variant[0] ][ $type . 'Width' ] . 'px) {' . $selector . '{' . $css_text . '}}';
}
} elseif ( count( $variant ) === 2 ) {
// active, hover, focus or pseudo class.
$psuedo_class = $this->checkIfHasPsuedoClassValue( $variant[1] );
if ( $variant[0] === 'md' ) {
$css_string .= $selector . $psuedo_class . '{' . $css_text . '}';
} elseif ( isset( $this->view_ports[ $variant[0] ] ) ) {
$css_string .= '@media only screen and (' . $type . '-width: ' . $this->view_ports[ $variant[0] ][ $type . 'Width' ] . 'px) {';
$css_string .= $selector . $psuedo_class . '{' . $css_text . '}';
$css_string .= '}';
}
} elseif ( count( $variant ) === 3 ) {
// active, hover, focus + pseudo class.
$psuedo_class1 = $this->checkIfHasPsuedoClassValue( $variant[1] );
$psuedo_class2 = $this->checkIfHasPsuedoClassValue( $variant[2] );
if ( $variant[0] === 'md' ) {
$css_string .= $selector . $psuedo_class1 . $psuedo_class2 . '{' . $css_text . '}';
} elseif ( isset( $this->view_ports[ $variant[0] ] ) ) {
$css_string .= '@media only screen and (' . $type . '-width: ' . $this->view_ports[ $variant[0] ][ $type . 'Width' ] . 'px) {';
$css_string .= $selector . $psuedo_class1 . $psuedo_class2 . '{' . $css_text . '}';
$css_string .= '}';
}
}
return $css_string;
}
/**
* Get the script tag string
*
* @return string
*/
public function getScriptTag( $should_take_app_script = true ) {
$s = '';
$empty_vars = $this->getVariableString( 'Sliders', $this->sliders );
$empty_vars .= $this->getVariableString( 'Maps', $this->maps );
$empty_vars .= $this->getVariableString( 'Lotties', $this->lotties );
$empty_vars .= $this->getVariableString( 'Popups', $this->popups );
$empty_vars .= $this->getVariableString( 'Lightboxes', $this->lightboxes );
$empty_vars .= $this->getVariableString( 'ReCaptchas', $this->re_captchas );
$empty_vars .= $this->getVariableString( 'Videos', $this->videos );
$empty_vars .= $this->getVariableString( 'Tabs', $this->tabs );
$empty_vars .= $this->getVariableString( 'Interactions', $this->interactions );
$empty_vars .= $this->getVariableString( 'InteractionLibrary', $this->interaction_library );
$empty_vars .= $this->getVariableString( 'Collections', $this->collections );
$empty_vars .= $this->getVariableString( 'Forms', $this->forms );
$empty_vars .= $this->getVariableString( 'Dropdown', $this->dropdown );
$empty_vars .= $this->getVariableString( 'Navigations', $this->navigations );
$empty_vars .= $this->getVariableString( 'NavigationItem', $this->navigation_item );
$empty_vars .= $this->getVariableString( 'Inputs', $this->inputs );
$empty_vars .= $this->getVariableString( 'LiquidGlass', $this->liquid_glass );
if ( $empty_vars ) {
$s .= "';
}
if ( $this->custom_codes ) {
$s .= "';
}
$updatedScriptTags = false;
if ( $should_take_app_script ) {
$updatedScriptTags = apply_filters('kirki_add_script_tags', $s );
}
if ( $updatedScriptTags ) {
$s = $updatedScriptTags;
}
return $s;
}
private function getVariableString( $name, $value ) {
if ( count( $value ) === 0 ) {
return '';
}
$prefix = 'kirki';
$value = wp_json_encode( $value );
// SECURITY (prototype-pollution guard): only merge a PRE-EXISTING value when it is
// an OWN property of window. `window.kirkiX === undefined` is false when
// `Object.prototype.kirkiX` has been polluted (crafted query params / third-party
// gadget), and `{...kirkiX, ...}` would then launder attacker-controlled keys into a
// real own property that downstream scripts trust. Starting from `{}` unless window
// truly owns the value keeps inherited (attacker) data out.
$s = "var $prefix$name = Object.assign({}, (Object.prototype.hasOwnProperty.call(window, '$prefix$name') && window.$prefix$name) || {}, $value);";
return $s;
}
/**
* Returns the JS code with `