/home/lnzliplg/public_html/header-footer-elementor.zip
PK ���\}{^=� � inc/js/counter.jsnu �[��� /**
* Counter Widget JavaScript
*
* Handles the counter animation functionality
*/
(function($) {
'use strict';
var HfeCounter = {
/**
* Initialize the counter
*/
init: function() {
elementorFrontend.hooks.addAction('frontend/element_ready/hfe-counter.default', this.initCounter);
},
/**
* Initialize counter for specific element
*/
initCounter: function($scope) {
var $counter = $scope.find('.hfe-counter-number');
if ($counter.length) {
HfeCounter.setupCounterAnimation($counter);
}
},
/**
* Setup counter animation
*/
setupCounterAnimation: function($counter) {
var startNumber = parseInt($counter.data('start')) || 0;
var endNumber = parseInt($counter.data('end'));
endNumber = isNaN(endNumber) ? 100 : endNumber;
var speed = parseInt($counter.data('speed')) || 3000;
var separator = $counter.data('separator') || '';
// Use Intersection Observer for better performance
if ('IntersectionObserver' in window) {
var observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting && !$counter.hasClass('hfe-counter-animated')) {
$counter.addClass('hfe-counter-animated');
HfeCounter.animateCounter($counter[0], startNumber, endNumber, speed, separator);
observer.unobserve(entry.target);
}
});
}, {
threshold: 0.5
});
observer.observe($counter[0]);
} else {
// Fallback for older browsers
$(window).on('scroll', function() {
if (HfeCounter.isElementInViewport($counter[0]) && !$counter.hasClass('hfe-counter-animated')) {
$counter.addClass('hfe-counter-animated');
HfeCounter.animateCounter($counter[0], startNumber, endNumber, speed, separator);
}
});
}
},
/**
* Animate the counter
*/
animateCounter: function(element, start, end, duration, separator) {
var startTime = null;
var $element = $(element);
function animate(currentTime) {
if (startTime === null) startTime = currentTime;
var progress = Math.min((currentTime - startTime) / duration, 1);
// Use easing function for smooth animation
var easedProgress = HfeCounter.easeOutQuart(progress);
var currentNumber = Math.floor(start + (end - start) * easedProgress);
$element.text(HfeCounter.formatNumber(currentNumber, separator));
if (progress < 1) {
requestAnimationFrame(animate);
} else {
$element.text(HfeCounter.formatNumber(end, separator));
}
}
requestAnimationFrame(animate);
},
/**
* Format number with separator
*/
formatNumber: function(number, separator) {
if (!separator) {
return number.toString();
}
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, separator);
},
/**
* Easing function for smooth animation
*/
easeOutQuart: function(t) {
return 1 - (--t) * t * t * t;
},
/**
* Check if element is in viewport (fallback)
*/
isElementInViewport: function(element) {
var rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
};
// Initialize when Elementor frontend is ready
$(window).on('elementor/frontend/init', function() {
HfeCounter.init();
});
// Fallback for when Elementor frontend is not available
$(document).ready(function() {
if (typeof elementorFrontend === 'undefined') {
// Create a mock elementorFrontend for standalone use
window.elementorFrontend = {
hooks: {
addAction: function(event, callback) {
$(document).ready(callback);
}
}
};
}
HfeCounter.init();
});
})(jQuery);PK ���\�L�s s inc/js/woo-products.jsnu �[��� /**
* HFE Woo Products Widget JavaScript
*/
(function($) {
'use strict';
var HFEWooProducts = {
init: function() {
this.bindEvents();
},
bindEvents: function() {
// Add any interactive functionality here
$(document).on('click', '.hfe-product-add-to-cart .button', this.handleAddToCart);
},
handleAddToCart: function(e) {
var $button = $(this);
// Add loading state
$button.addClass('loading');
// Remove loading state after WooCommerce handles the request
setTimeout(function() {
$button.removeClass('loading');
}, 2000);
}
};
// Initialize when document is ready
$(document).ready(function() {
HFEWooProducts.init();
});
// Initialize for Elementor editor
$(window).on('elementor/frontend/init', function() {
elementorFrontend.hooks.addAction('frontend/element_ready/hfe-woo-product-grid.default', function($scope) {
HFEWooProducts.init();
});
});
})(jQuery);
PK ���\]�3�C{ C{ inc/js/frontend.jsnu �[��� ( function( $ ) {
/**
* Search widget JS
*/
var WidgethfeSearchButton = function( $scope, $ ){
if ( 'undefined' == typeof $scope )
return;
var $input = $scope.find( "input.hfe-search-form__input" );
var $clear = $scope.find( "button#clear" );
var $clear_with_button = $scope.find( "button#clear-with-button" );
var $search_button = $scope.find( ".hfe-search-submit" );
var $toggle_search = $scope.find( ".hfe-search-icon-toggle input" );
$scope.find( '.hfe-search-icon-toggle' ).on( 'click', function( ){
$scope.find( ".hfe-search-form__input" ).trigger( 'focus' );
});
$scope.find( ".hfe-search-form__input" ).on( 'focus', function(){
$scope.find( ".hfe-search-button-wrapper" ).addClass( "hfe-input-focus" );
});
$scope.find( ".hfe-search-form__input" ).blur( function() {
$scope.find( ".hfe-search-button-wrapper" ).removeClass( "hfe-input-focus" );
});
$search_button.on( 'touchstart click', function(){
$input.submit();
});
$toggle_search.css( 'padding-right', $toggle_search.next().outerWidth() + 'px' );
$input.on( 'keyup', function(){
$clear.style = (this.value.length) ? $clear.css('visibility','visible'): $clear.css('visibility','hidden');
$clear_with_button.style = (this.value.length) ? $clear_with_button.css('visibility','visible'): $clear_with_button.css('visibility','hidden');
$clear_with_button.css( 'right', $search_button.outerWidth() + 'px' );
});
$clear.on("click",function(){
this.style = $clear.css('visibility','hidden');
$input.value = "";
});
$clear_with_button.on("click",function(){
this.style = $clear_with_button.css('visibility','hidden');
$input.value = "";
});
};
/**
* Nav Menu handler Function.
*
*/
var WidgethfeNavMenuHandler = function( $scope, $ ) {
if ( 'undefined' == typeof $scope )
return;
var id = $scope.data( 'id' );
var wrapper = $scope.find('.elementor-widget-hfe-nav-menu ');
var layout = $( '.elementor-element-' + id + ' .hfe-nav-menu' ).data( 'layout' );
var flyout_data = $( '.elementor-element-' + id + ' .hfe-flyout-wrapper' ).data( 'flyout-class' );
var last_item = $( '.elementor-element-' + id + ' .hfe-nav-menu' ).data( 'last-item' );
var last_item_flyout = $( '.elementor-element-' + id + ' .hfe-flyout-wrapper' ).data( 'last-item' );
var menu_items_links = $( '.elementor-element-' + id + ' .hfe-nav-menu nav li a' );
var menu_items_links_flyout = $( '.elementor-element-' + id + ' .hfe-flyout-wrapper li a' );
if (menu_items_links.length > 0) {
_handle_current_menu_item_class( menu_items_links );
}
if (menu_items_links_flyout.length > 0) {
_handle_current_menu_item_class( menu_items_links_flyout );
}
$( 'div.hfe-has-submenu-container' ).removeClass( 'sub-menu-active' );
_toggleClick( id );
_handlePolylangSwitcher( $scope );
_handleSinglePageMenu( id, layout );
if( 'horizontal' !== layout ){
_eventClick( id );
}else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 767px )" ).matches ) {
_eventClick( id );
}else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 1024px )" ).matches ) {
_eventClick( id );
}
$( '.elementor-element-' + id + ' .hfe-flyout-trigger .hfe-nav-menu-icon' ).off( 'click keyup' ).on( 'click keyup', function() {
_openMenu( id );
} );
$( '.elementor-element-' + id + ' .hfe-flyout-close' ).off( 'click keyup' ).on( 'click keyup', function() {
_closeMenu( id );
} );
$( '.elementor-element-' + id + ' .hfe-flyout-overlay' ).off( 'click' ).on( 'click', function() {
_closeMenu( id );
} );
$scope.find( '.sub-menu' ).each( function() {
var parent = $( this ).closest( '.menu-item' );
$scope.find( parent ).addClass( 'parent-has-child' );
$scope.find( parent ).removeClass( 'parent-has-no-child' );
});
if( ( 'cta' == last_item || 'cta' == last_item_flyout ) && 'expandible' != layout ){
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).parent().addClass( 'hfe-button-wrapper elementor-widget-button' );
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).addClass( 'elementor-button' );
}
_borderClass( id );
$( window ).on( 'resize', function(){
if( 'horizontal' !== layout ) {
_eventClick( id );
}else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 767px )" ).matches ) {
_eventClick( id );
}else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 1024px )" ).matches ) {
_eventClick( id );
}
if( 'horizontal' == layout && window.matchMedia( "( min-width: 977px )" ).matches){
$( '.elementor-element-' + id + ' div.hfe-has-submenu-container' ).next().css( 'position', 'absolute');
}
if( 'expandible' == layout || 'flyout' == layout ){
_toggleClick( id );
}else if ( 'vertical' == layout || 'horizontal' == layout ) {
if( window.matchMedia( "( max-width: 767px )" ).matches && ($( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile'))){
_toggleClick( id );
}else if ( window.matchMedia( "( max-width: 1024px )" ).matches && $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') ) {
_toggleClick( id );
}else{
var $toggle = $( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' );
var $nextElement= $toggle.next();
var width = $nextElement.parent().width();
if( $nextElement.length ){
$nextElement.css( 'width', width + 'px' );
$nextElement.css( 'left', '0' );
}
}
}
_borderClass( id );
});
// Acessibility functions
$scope.find( '.parent-has-child .hfe-has-submenu-container a').attr( 'aria-haspopup', 'true' );
$scope.find( '.parent-has-child .hfe-has-submenu-container a').attr( 'aria-expanded', 'false' );
var hef_navmenu_toggle = $scope.find( '.hfe-nav-menu__toggle' );
hef_navmenu_toggle.attr( 'aria-haspopup', 'true' );
hef_navmenu_toggle.attr( 'aria-expanded', 'false' );
if ( window.matchMedia( "( max-width: 1024px )" ).matches && $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') ) {
hef_navmenu_toggle.find('i').attr('aria-hidden', 'false');
}
if ( window.matchMedia( "( max-width: 768px )" ).matches && $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile') ) {
hef_navmenu_toggle.find('i').attr('aria-hidden', 'false');
}
// End of accessibility functions
$( document ).trigger( 'hfe_nav_menu_init', id );
// Add keyboard navigation for expandable menu
if ( 'expandible' === layout ) {
$( '.elementor-element-' + id + ' nav' ).on( 'keydown', function(e) {
var $currentElement = $( document.activeElement );
var $menuItems = $( this ).find( 'li > a:visible' );
var currentIndex = $menuItems.index( $currentElement );
switch( e.key ) {
case 'Escape': // Escape key - close menu
$( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' ).trigger( 'click' );
$( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' ).focus();
e.preventDefault();
break;
case 'ArrowDown': // Down arrow
if ( currentIndex < $menuItems.length - 1 ) {
$menuItems.eq( currentIndex + 1 ).focus();
}
e.preventDefault();
break;
case 'ArrowUp': // Up arrow
if ( currentIndex > 0 ) {
$menuItems.eq( currentIndex - 1 ).focus();
}
e.preventDefault();
break;
case 'Tab': // Tab key
// Let default tab behavior work but close menu when tabbing out
if ( e.shiftKey && currentIndex === 0 ) {
// Shift+Tab on first item - close menu
setTimeout(function() {
if ( !$( '.elementor-element-' + id + ' nav' ).find( ':focus' ).length ) {
$( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' ).trigger( 'click' );
}
}, 10);
} else if ( !e.shiftKey && currentIndex === $menuItems.length - 1 ) {
// Tab on last item - close menu
setTimeout(function() {
if ( !$( '.elementor-element-' + id + ' nav' ).find( ':focus' ).length ) {
$( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' ).trigger( 'click' );
}
}, 10);
}
break;
}
});
}
$( '.elementor-element-' + id + ' div.hfe-has-submenu-container' ).on( 'keyup', function(e){
var $this = $( this );
// Handle Enter and Space keys for submenu toggle
if ( e.key === 'Enter' || e.key === 'Space' ) {
e.preventDefault();
e.stopPropagation();
} else {
return; // Only handle Enter and Space keys
}
if( $this.parent().hasClass( 'menu-active' ) ) {
$this.parent().removeClass( 'menu-active' );
$this.attr( 'aria-expanded', 'false' );
$this.parent().next().find('ul').css( { 'visibility': 'hidden', 'opacity': '0', 'height': '0' } );
$this.parent().prev().find('ul').css( { 'visibility': 'hidden', 'opacity': '0', 'height': '0' } );
$this.parent().next().find( 'div.hfe-has-submenu-container' ).removeClass( 'sub-menu-active' );
$this.parent().prev().find( 'div.hfe-has-submenu-container' ).removeClass( 'sub-menu-active' );
}else {
$this.parent().next().find('ul').css( { 'visibility': 'hidden', 'opacity': '0', 'height': '0' } );
$this.parent().prev().find('ul').css( { 'visibility': 'hidden', 'opacity': '0', 'height': '0' } );
$this.parent().next().find( 'div.hfe-has-submenu-container' ).removeClass( 'sub-menu-active' );
$this.parent().prev().find( 'div.hfe-has-submenu-container' ).removeClass( 'sub-menu-active' );
$this.parent().siblings().find( '.hfe-has-submenu-container a' ).attr( 'aria-expanded', 'false' );
$this.parent().next().removeClass( 'menu-active' );
$this.parent().prev().removeClass( 'menu-active' );
event.preventDefault();
$this.parent().addClass( 'menu-active' );
if( 'horizontal' !== layout ){
$this.addClass( 'sub-menu-active' );
}
$this.find( 'a' ).attr( 'aria-expanded', 'true' );
$this.attr( 'aria-expanded', 'true' );
$this.next().css( { 'visibility': 'visible', 'opacity': '1', 'height': 'auto' } );
if ( 'horizontal' !== layout ) {
$this.next().css( 'position', 'relative');
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 767px )" ).matches && ($( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile'))) {
$this.next().css( 'position', 'relative');
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 1024px )" ).matches ) {
if ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') ) {
$this.next().css( 'position', 'relative');
} else if ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-none') ) {
$this.next().css( 'position', 'absolute');
}
}
}
});
$( '.elementor-element-' + id + ' li.menu-item' ).on( 'keyup', function(e){
var $this = $( this );
$this.next().find( 'a' ).attr( 'aria-expanded', 'false' );
$this.prev().find( 'a' ).attr( 'aria-expanded', 'false' );
$this.next().find('ul').css( { 'visibility': 'hidden', 'opacity': '0', 'height': '0' } );
$this.prev().find('ul').css( { 'visibility': 'hidden', 'opacity': '0', 'height': '0' } );
$this.siblings().removeClass( 'menu-active' );
$this.next().find( 'div.hfe-has-submenu-container' ).removeClass( 'sub-menu-active' );
$this.prev().find( 'div.hfe-has-submenu-container' ).removeClass( 'sub-menu-active' );
});
};
function _handle_current_menu_item_class( layout_links ) {
layout_links.each(
function () {
var $this = $( this );
if ($this.is( '[href*="#"]' )) {
var menu_item_parent = $this.parent();
menu_item_parent.removeClass( 'current-menu-item current-menu-ancestor' );
$this.click(
function () {
var current_index = menu_item_parent.index(),
parent_element = $this.closest( 'ul' );
parent_element.find( 'li' ).not( ':eq(' + current_index + ')' ).removeClass( 'current-menu-item current-menu-ancestor' );
menu_item_parent.addClass( 'current-menu-item current-menu-ancestor' );
}
)
}
}
);
}
function _openMenu( id ) {
var flyout_content = $( '#hfe-flyout-content-id-' + id );
var layout = $( '#hfe-flyout-content-id-' + id ).data( 'layout' );
var layout_type = $( '#hfe-flyout-content-id-' + id ).data( 'flyout-type' );
var wrap_width = flyout_content.width() + 'px';
var container = $( '.elementor-element-' + id + ' .hfe-flyout-container .hfe-side.hfe-flyout-' + layout );
$( '.elementor-element-' + id + ' .hfe-flyout-overlay' ).fadeIn( 100 );
if( 'left' == layout ) {
$( 'body' ).css( 'margin-left' , '0' );
container.css( 'left', '0' );
if( 'push' == layout_type ) {
$( 'body' ).addClass( 'hfe-flyout-animating' ).css({
position: 'absolute',
width: '100%',
'margin-left' : wrap_width,
'margin-right' : 'auto'
});
}
container.addClass( 'hfe-flyout-show' );
} else {
$( 'body' ).css( 'margin-right', '0' );
container.css( 'right', '0' );
if( 'push' == layout_type ) {
$( 'body' ).addClass( 'hfe-flyout-animating' ).css({
position: 'absolute',
width: '100%',
'margin-left' : '-' + wrap_width,
'margin-right' : 'auto',
});
}
container.addClass( 'hfe-flyout-show' );
}
}
function _closeMenu( id ) {
var flyout_content = $( '#hfe-flyout-content-id-' + id );
var layout = $( '#hfe-flyout-content-id-' + id ).data( 'layout' );
var wrap_width = flyout_content.width() + 'px';
var layout_type = $( '#hfe-flyout-content-id-' + id ).data( 'flyout-type' );
var container = $( '.elementor-element-' + id + ' .hfe-flyout-container .hfe-side.hfe-flyout-' + layout );
$( '.elementor-element-' + id + ' .hfe-flyout-overlay' ).fadeOut( 100 );
if( 'left' == layout ) {
container.css( 'left', '-' + wrap_width );
if( 'push' == layout_type ) {
$( 'body' ).css({
position: '',
'margin-left' : '',
'margin-right' : '',
});
setTimeout( function() {
$( 'body' ).removeClass( 'hfe-flyout-animating' ).css({
width: '',
});
});
}
container.removeClass( 'hfe-flyout-show' );
} else {
container.css( 'right', '-' + wrap_width );
if( 'push' == layout_type ) {
$( 'body' ).css({
position: '',
'margin-right' : '',
'margin-left' : '',
});
setTimeout( function() {
$( 'body' ).removeClass( 'hfe-flyout-animating' ).css({
width: '',
});
});
}
container.removeClass( 'hfe-flyout-show' );
}
}
function _eventClick( id ){
var layout = $( '.elementor-element-' + id + ' .hfe-nav-menu' ).data( 'layout' );
$( '.elementor-element-' + id + ' div.hfe-has-submenu-container' ).off( 'click' ).on( 'click', function( event ) {
var $this = $( this );
if( $( '.elementor-element-' + id ).hasClass( 'hfe-link-redirect-child' ) ) {
if( $this.hasClass( 'sub-menu-active' ) ) {
if( ! $this.next().hasClass( 'sub-menu-open' ) ) {
$this.find( 'a' ).attr( 'aria-expanded', 'false' );
if( 'horizontal' !== layout ){
event.preventDefault();
$this.next().css( 'position', 'relative' );
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 767px )" ).matches && ($( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile'))) {
event.preventDefault();
$this.next().css( 'position', 'relative' );
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 1024px )" ).matches && ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile'))) {
event.preventDefault();
$this.next().css( 'position', 'relative' );
}
$this.removeClass( 'sub-menu-active' );
$this.nextAll('.sub-menu').removeClass( 'sub-menu-open' );
$this.nextAll('.sub-menu').css( { 'visibility': 'hidden', 'opacity': '0', 'height': '0' } );
$this.nextAll('.sub-menu').css( { 'transition': 'none'} );
} else{
$this.find( 'a' ).attr( 'aria-expanded', 'false' );
$this.removeClass( 'sub-menu-active' );
$this.nextAll('.sub-menu').removeClass( 'sub-menu-open' );
$this.nextAll('.sub-menu').css( { 'visibility': 'hidden', 'opacity': '0', 'height': '0' } );
$this.nextAll('.sub-menu').css( { 'transition': 'none'} );
if ( 'horizontal' !== layout ){
$this.next().css( 'position', 'relative' );
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 767px )" ).matches && ($( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile'))) {
$this.next().css( 'position', 'relative' );
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 1024px )" ).matches && ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile'))) {
$this.next().css( 'position', 'absolute' );
}
}
} else {
$this.find( 'a' ).attr( 'aria-expanded', 'true' );
if ( 'horizontal' !== layout ) {
event.preventDefault();
$this.next().css( 'position', 'relative');
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 767px )" ).matches && ($( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile'))) {
event.preventDefault();
$this.next().css( 'position', 'relative');
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 1024px )" ).matches ) {
event.preventDefault();
if ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') ) {
$this.next().css( 'position', 'relative');
} else if ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-none') ) {
$this.next().css( 'position', 'absolute');
}
}
$this.addClass( 'sub-menu-active' );
$this.nextAll('.sub-menu').addClass( 'sub-menu-open' );
$this.nextAll('.sub-menu').css( { 'visibility': 'visible', 'opacity': '1', 'height': 'auto' } );
$this.nextAll('.sub-menu').css( { 'transition': '0.3s ease'} );
}
}
});
$( '.elementor-element-' + id + ' .hfe-menu-toggle' ).off( 'click keyup' ).on( 'click keyup',function( event ) {
var $this = $( this );
if( $this.parent().parent().hasClass( 'menu-active' ) ) {
event.preventDefault();
$this.parent().parent().removeClass( 'menu-active' );
$this.parent().parent().next().css( { 'visibility': 'hidden', 'opacity': '0', 'height': '0' } );
if ( 'horizontal' !== layout ) {
$this.parent().parent().next().css( 'position', 'relative');
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 767px )" ).matches && ($( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile'))) {
$this.parent().parent().next().css( 'position', 'relative');
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 1024px )" ).matches ) {
if ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') ) {
$this.parent().parent().next().css( 'position', 'relative');
} else if ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-none') ) {
$this.parent().parent().next().css( 'position', 'absolute');
}
}
}else {
event.preventDefault();
$this.parent().parent().addClass( 'menu-active' );
$this.parent().parent().next().css( { 'visibility': 'visible', 'opacity': '1', 'height': 'auto' } );
if ( 'horizontal' !== layout ) {
$this.parent().parent().next().css( 'position', 'relative');
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 767px )" ).matches && ($( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile'))) {
$this.parent().parent().next().css( 'position', 'relative');
} else if ( 'horizontal' === layout && window.matchMedia( "( max-width: 1024px )" ).matches ) {
if ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') ) {
$this.parent().parent().next().css( 'position', 'relative');
} else if ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-none') ) {
$this.parent().parent().next().css( 'position', 'absolute');
}
}
}
});
}
function _borderClass( id ){
var last_item = $( '.elementor-element-' + id + ' .hfe-nav-menu' ).data( 'last-item' );
var last_item_flyout = $( '.elementor-element-' + id + ' .hfe-flyout-wrapper' ).data( 'last-item' );
var layout = $( '.elementor-element-' + id + ' .hfe-nav-menu' ).data( 'layout' );
$( '.elementor-element-' + id + ' nav').removeClass('hfe-dropdown');
if ( window.matchMedia( "( max-width: 767px )" ).matches ) {
if( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile') || $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet')){
$( '.elementor-element-' + id + ' nav').addClass('hfe-dropdown');
if( ( 'cta' == last_item || 'cta' == last_item_flyout ) && 'expandible' != layout ){
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).parent().removeClass( 'hfe-button-wrapper elementor-widget-button' );
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).removeClass( 'elementor-button' );
}
}else{
$( '.elementor-element-' + id + ' nav').removeClass('hfe-dropdown');
if( ( 'cta' == last_item || 'cta' == last_item_flyout ) && 'expandible' != layout ){
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).parent().addClass( 'hfe-button-wrapper elementor-widget-button' );
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).addClass( 'elementor-button' );
}
}
}else if ( window.matchMedia( "( max-width: 1024px )" ).matches ) {
if( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') ) {
$( '.elementor-element-' + id + ' nav').addClass('hfe-dropdown');
if( ( 'cta' == last_item || 'cta' == last_item_flyout ) && 'expandible' != layout ){
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).parent().removeClass( 'hfe-button-wrapper elementor-widget-button' );
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).removeClass( 'elementor-button' );
}
}else{
$( '.elementor-element-' + id + ' nav').removeClass('hfe-dropdown');
if( ( 'cta' == last_item || 'cta' == last_item_flyout ) && 'expandible' != layout ){
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).parent().addClass( 'hfe-button-wrapper elementor-widget-button' );
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).addClass( 'elementor-button' );
}
}
}else {
var $parent_element = $( '.elementor-element-' + id );
$parent_element.find( 'nav').removeClass( 'hfe-dropdown' );
if( ( 'cta' == last_item || 'cta' == last_item_flyout ) && 'expandible' != layout ){
$parent_element.find( 'li.menu-item:last-child a.hfe-menu-item' ).parent().addClass( 'hfe-button-wrapper elementor-widget-button' );
$parent_element.find( 'li.menu-item:last-child a.hfe-menu-item' ).addClass( 'elementor-button' );
}
}
var layout = $( '.elementor-element-' + id + ' .hfe-nav-menu' ).data( 'layout' );
if( 'expandible' == layout ){
if( ( 'cta' == last_item || 'cta' == last_item_flyout ) && 'expandible' != layout ){
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).parent().removeClass( 'hfe-button-wrapper elementor-widget-button' );
$( '.elementor-element-' + id + ' li.menu-item:last-child a.hfe-menu-item' ).removeClass( 'elementor-button' );
}
}
}
function _toggleClick( id ){
if ( $( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' ).hasClass( 'hfe-active-menu-full-width' ) ){
var $toggle = $( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' );
var $nextElement= $toggle.next();
if( $nextElement.length ){
$nextElement.css( 'left', '0' );
var $section = $( '.elementor-element-' + id ).closest('.elementor-section, .e-con-boxed.e-parent, .e-con-full.e-parent');
if ( $section.length ) {
var width = $section.outerWidth();
var sec_pos = $section.offset().left - $toggle.next().offset().left;
$nextElement.css( 'width', width + 'px' );
$nextElement.css( 'left', sec_pos + 'px' );
}
}
}
$( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' ).off( 'click keyup' ).on( 'click keyup', function( event ) {
// Handle keyboard events properly
if ( event.type === 'keyup' && event.key !== 'Enter' && event.key !== 'Space' ) {
return; // Only handle Enter and Space keys
}
// Prevent default for keyboard events to avoid scrolling
if ( event.type === 'keyup' ) {
event.preventDefault();
}
var $this = $( this );
var $selector = $this.next();
if ( $this.hasClass( 'hfe-active-menu' ) ) {
var layout = $( '.elementor-element-' + id + ' .hfe-nav-menu' ).data( 'layout' );
var full_width = $selector.data( 'full-width' );
var toggle_icon = $( '.elementor-element-' + id + ' nav' ).data( 'toggle-icon' );
$( '.elementor-element-' + id).find( '.hfe-nav-menu-icon' ).html( toggle_icon );
$this.removeClass( 'hfe-active-menu' );
$this.attr( 'aria-expanded', 'false' );
if ( 'yes' == full_width ){
$this.removeClass( 'hfe-active-menu-full-width' );
$selector.css( 'width', 'auto' );
$selector.css( 'left', '0' );
$selector.css( 'z-index', '0' );
}
} else {
var layout = $( '.elementor-element-' + id + ' .hfe-nav-menu' ).data( 'layout' );
var full_width = $selector.data( 'full-width' );
var close_icon = $( '.elementor-element-' + id + ' nav' ).data( 'close-icon' );
$( '.elementor-element-' + id).find( '.hfe-nav-menu-icon' ).html( close_icon );
$this.addClass( 'hfe-active-menu' );
$this.attr( 'aria-expanded', 'true' );
if ( 'yes' == full_width ){
$this.addClass( 'hfe-active-menu-full-width' );
var closestElement = $( '.elementor-element-' + id ).closest('.elementor-section, .e-con-boxed.e-parent, .e-con-full.e-parent');
var width = closestElement.outerWidth();
var sec_pos = closestElement.offset().left - $selector.offset().left;
$selector.css( 'width', width + 'px' );
$selector.css( 'left', sec_pos + 'px' );
$selector.css( 'z-index', '9999' );
}
}
if( $( '.elementor-element-' + id + ' nav' ).hasClass( 'menu-is-active' ) ) {
$( '.elementor-element-' + id + ' nav' ).removeClass( 'menu-is-active' );
}else {
$( '.elementor-element-' + id + ' nav' ).addClass( 'menu-is-active' );
// Focus on first menu item when menu opens
if ( event.type === 'keyup' ) {
setTimeout(function() {
$selector.find('li:first-child > a').focus();
}, 100);
}
}
} );
}
function _handleSinglePageMenu( id, layout ) {
$( '.elementor-element-' + id + ' ul.hfe-nav-menu li a' ).on(
'click',
function ( event ) {
var $this = $( this );
var link = $this.attr( 'href' );
var linkValue = '';
// Check if this is an anchor link
if ( link && link.includes( '#' ) ) {
// Get the hash value
if ( link.charAt(0) === '#' ) {
event.preventDefault();
linkValue = link.slice( 1 );
} else {
var index = link.indexOf( '#' );
if ( index !== -1 ) {
linkValue = link.slice( index + 1 );
}
}
}
if ( linkValue.length > 0 ) {
var targetSection = $( '#' + linkValue );
if ( targetSection.length ) { // Check if the target section exists.
$('html, body').animate({
scrollTop: targetSection.offset().top
}, 800);
}
// Close the menu after clicking anchor link
setTimeout(function() {
if ( 'expandible' == layout ) {
// For expandible layout, trigger click on toggle if menu is open
var $toggle = $( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' );
if ( $toggle.hasClass( 'hfe-active-menu' ) ) {
$toggle.trigger( 'click' );
}
} else if ( 'flyout' == layout ) {
// For flyout layout, use the close menu function
_closeMenu( id );
} else {
// For horizontal and vertical layouts on mobile/tablet
if ( window.matchMedia( '(max-width: 1024px)' ).matches ) {
if ( $( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-tablet') ||
$( '.elementor-element-' + id ).hasClass('hfe-nav-menu__breakpoint-mobile') ) {
var $toggle = $( '.elementor-element-' + id + ' .hfe-nav-menu__toggle' );
if ( $toggle.hasClass( 'hfe-active-menu' ) ) {
$toggle.trigger( 'click' );
}
}
}
}
}, 100); // Small delay to ensure smooth scrolling starts first
}
}
);
}
/**
* This function handles polylang plugin's lang switcher if present in the menu.
*
* @param {Object} $scope The current element(hfe nav menu) wrapped with jQuery.
*/
function _handlePolylangSwitcher( $scope ) {
var polylangSwitcher = $scope.find( '.hfe-nav-menu nav .pll-parent-menu-item a.hfe-menu-item' );
var hrefProperty = polylangSwitcher.prop( 'href' );
if ( undefined !== hrefProperty && hrefProperty.includes( '#' ) ) {
var index = hrefProperty.indexOf( '#' );
var value = hrefProperty.slice( index );
if ( value === '#pll_switcher' ) {
polylangSwitcher.prop( 'href', '#' );
}
}
}
$( window ).on( 'elementor/frontend/init', function () {
elementorFrontend.hooks.addAction( 'frontend/element_ready/navigation-menu.default', WidgethfeNavMenuHandler );
elementorFrontend.hooks.addAction( 'frontend/element_ready/hfe-search-button.default', WidgethfeSearchButton );
});
} )( jQuery );
PK ���\�d�� � ) inc/js/hfe-elementor-pro-compatibility.jsnu �[��� (function($){
EHF_EPRO_Compatibility = {
/**
* Binds events for the Elementor Header Footer.
*
* @since 1.4.0
* @access private
* @method _bind
*/
init: function() {
elementor.on( "document:loaded", function() {
setTimeout( function() {
jQuery.each( elementorFrontend.documentsManager.documents, function ( index, document ) {
var $documentElement = document.$element;
var ids_array = JSON.parse( hfe_admin.ids_array );
ids_array.forEach( function( item, index ){
var elementor_id = $documentElement.data( 'elementor-id' );
if( elementor_id == ids_array[index].id ){
$documentElement.find( '.elementor-document-handle__title' ).text( elementor.translate('edit_element', [ids_array[index].value] ) );
}
} );
});
}, 1000 );
});
/**
* Scroll to Top.
*/
elementor.on("panel:init", function() {
function scrollToTop( changedValue ) {
var changedItem = Object.entries(this.model.changed)[0];
var attributes = this.model.attributes;
var scrolltop_data = {
'check': 'hfeMessage',
'changeValue': changedValue,
'changeItem': changedItem
};
if ('hfe_scroll_to_top_single_disable' != changedItem[0]) {
var data = {
'enable_global_hfe': attributes.hfe_scroll_to_top_global,
'media_type': attributes.hfe_scroll_to_top_media_type,
'icon': attributes.hfe_scroll_to_top_button_icon,
'image': attributes.hfe_scroll_to_top_button_image,
'text': attributes.hfe_scroll_to_top_button_text
};
scrolltop_data = Object.assign(scrolltop_data, data);
} else {
$e.run('document/save/update').then(_.debounce(function() {
elementor.reloadPreview();
}, 1500));
}
$("#elementor-preview-iframe")[0].contentWindow.postMessage(scrolltop_data);
}
var changeHandler = ["hfe_scroll_to_top_global", "hfe_scroll_to_top_media_type", "hfe_scroll_to_top_button_icon", "hfe_scroll_to_top_button_image", "hfe_scroll_to_top_button_text", "hfe_scroll_to_top_single_disable"];
$.each(changeHandler, function(index, value) {
elementor.settings.page.addChangeCallback(value, scrollToTop);
});
});
}
};
/**
* Initialize EHF_EPRO_Compatibility
*/
$(function(){
EHF_EPRO_Compatibility.init();
});
})(jQuery);
PK ���\^��g g inc/js/permalink-clear-notice.jsnu �[��� var ElementorEditorCheck = function() {
var isNoticeClosed = function() {
jQuery(document).on('click', '.uae-permalink-notice-close', function(e) {
var $notice = jQuery('#uae-permalink-clear-notice');
if ($notice.data('visible')) {
$notice.remove();
jQuery.ajax({
url: hfePermalinkClearNotice.ajaxurl,
type: 'POST',
data: {
action: 'update_permalink_notice_option',
nonce: hfePermalinkClearNotice.nonce,
},
success: function(response) {
if (response.success) {
console.log('Option updated successfully');
} else {
console.log('Error updating option: ' + response.data);
}
},
error: function(error) {
console.log('Error updating option');
}
});
}
});
}
var isPermalinkFlushed = function() {
jQuery(document).on('click', '.uae-permalink-flush-btn', function(e) {
var $loader = jQuery('.uae-notice-loader');
var $button = jQuery(this);
var $buttonText = $button.find('.uae-btn-main-text');
// Show loader and disable button
$loader.show();
$buttonText.text('Flushing...');
$button.prop('disabled', true);
jQuery.ajax({
url: hfePermalinkClearNotice.ajaxurl,
type: 'POST',
data: {
action: 'hfe_flush_permalink_notice',
nonce: hfePermalinkClearNotice.nonce,
},
success: function(response) {
// Hide the loader
$loader.hide();
$buttonText.text('Flushed Permalink');
if (response.success) {
console.log('Permalink refreshed successfully');
location.reload(true);
} else {
console.log('Error updating option: ' + response.data);
}
},
error: function(error) {
// Hide the loader
$loader.hide();
$buttonText.text('Flushed Permalink');
console.log('Error updating option');
}
});
});
}
var isElementorLoadedCheck = function() {
if ( 'undefined' === typeof elementor ) {
return false;
}
if ( ! elementor.loaded ) {
return false;
}
if ( jQuery( '#elementor-loading' ).is( ':visible' ) ) {
return false;
}
return true;
};
var permalinkNoticeCheck = function() {
var $notice = jQuery( '#uae-permalink-clear-notice' );
if ( isElementorLoadedCheck() ) {
$notice.remove();
return;
}
if ( ! $notice.data( 'visible' ) ) {
$notice.show().data( 'visible', true );
}
// Re-check after 500ms.
setTimeout( permalinkNoticeCheck, 500 );
};
var init = function() {
setTimeout( permalinkNoticeCheck, 30000 );
isNoticeClosed();
isPermalinkFlushed();
};
init();
};
new ElementorEditorCheck();PK ���\dD(��8 �8 inc/class-hfe-analytics.phpnu �[��� <?php
/**
* HFE Analytics.
*
* @package HFE
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* HFE Analytics.
*
* HFE Analytics. handler class is responsible for rolling back HFE to
* previous version.
*
* @since 2.3.0
*/
if ( ! class_exists( 'HFE_Analytics' ) ) {
class HFE_Analytics {
/**
* HFE Analytics constructor.
*
* Initializing HFE Analytics.
*
* @since 2.3.0
* @access public
*
* @param array $args Optional. HFE Analytics arguments. Default is an empty array.
*/
public function __construct() {
add_action( 'admin_init', [ $this, 'maybe_migrate_analytics_tracking' ] );
// Load analytics events class.
if ( ! class_exists( 'HFE_Analytics_Events' ) ) {
require_once HFE_DIR . 'inc/class-hfe-analytics-events.php';
}
// BSF Analytics Tracker.
if ( ! class_exists( 'BSF_Analytics_Loader' ) ) {
require_once HFE_DIR . 'admin/bsf-analytics/class-bsf-analytics-loader.php';
}
$bsf_analytics = BSF_Analytics_Loader::get_instance();
$bsf_analytics->set_entity(
[
'uae' => [
'product_name' => 'Ultimate Addons for Elementor',
'path' => HFE_DIR . 'admin/bsf-analytics',
'author' => 'Ultimate Addons for Elementor',
'time_to_display' => '+24 hours',
'deactivation_survey' => [
[
'id' => 'deactivation-survey-header-footer-elementor',
'popup_logo' => HFE_URL . 'assets/images/settings/logo.svg',
'plugin_slug' => 'header-footer-elementor',
'plugin_version' => HFE_VER,
'popup_title' => 'Quick Feedback',
'support_url' => 'https://ultimateelementor.com/contact/',
'popup_description' => 'If you have a moment, please share why you are deactivating Ultimate Addons for Elementor:',
'show_on_screens' => [ 'plugins' ],
],
],
'hide_optin_checkbox' => true,
],
]
);
add_filter( 'bsf_core_stats', [ $this, 'add_uae_analytics_data' ] );
// Event tracking hooks.
add_action( 'transition_post_status', [ $this, 'track_first_template_published' ], 10, 3 );
if ( ! HFE_Analytics_Events::is_tracked( 'first_widget_used' ) ) {
add_action( 'elementor/editor/after_save', [ $this, 'track_first_widget_on_save' ], 10, 2 );
}
// Detect state-based events only in admin context, throttled to once per day.
if ( is_admin() && false === get_transient( 'hfe_state_events_checked' ) ) {
$this->detect_state_events();
set_transient( 'hfe_state_events_checked', 1, DAY_IN_SECONDS );
}
}
/**
* Migrates analytics tracking option from 'bsf_usage_optin' to 'uae_usage_optin'.
*
* Checks if the old analytics tracking option ('bsf_usage_optin') is set to 'yes'
* and if the new option ('uae_usage_optin') is not already set.
* If so, updates the new tracking option to 'yes' to maintain user consent during migration.
*
* @since 2.3.2
* @access public
*
* @return void
*/
public function maybe_migrate_analytics_tracking() {
// Skip if already migrated or new option already set.
if ( false !== get_site_option( 'uae_usage_optin', false ) ) {
return;
}
$old_tracking = get_site_option( 'bsf_usage_optin', false );
if ( 'yes' === $old_tracking ) {
update_site_option( 'uae_usage_optin', 'yes' );
$time = get_site_option( 'bsf_usage_installed_time' );
if ( false !== $time ) {
update_site_option( 'uae_usage_installed_time', $time );
}
}
}
/**
* Callback function to add specific analytics data.
*
* @param array $stats_data existing stats_data.
* @since 2.3.0
* @return array
*/
public function add_uae_analytics_data( $stats_data ) {
// Check if $stats_data is empty or not an array.
if ( empty( $stats_data ) || ! is_array( $stats_data ) ) {
$stats_data = []; // Initialize as an empty array.
}
$stats_data['plugin_data']['uae'] = [
'free_version' => HFE_VER,
'pro_version' => ( defined( 'UAEL_VERSION' ) ? UAEL_VERSION : '' ),
'site_language' => get_locale(),
'elementor_version' => ( defined( 'ELEMENTOR_VERSION' ) ? ELEMENTOR_VERSION : '' ),
'elementor_pro_version' => ( defined( 'ELEMENTOR_PRO_VERSION' ) ? ELEMENTOR_PRO_VERSION : '' ),
'onboarding_triggered' => ( 'yes' === get_option( 'hfe_onboarding_triggered' ) ) ? 'yes' : 'no',
'uaelite_subscription' => ( 'done' === get_option( 'uaelite_subscription' ) ) ? 'yes' : 'no',
'active_theme' => get_template(),
'is_theme_supported' => (bool) get_option( 'hfe_is_theme_supported', false ),
'onboarding_analytics' => get_option( 'hfe_onboarding_analytics', [] ),
];
$template_counts = wp_count_posts( 'elementor-hf' );
$stats_data['plugin_data']['uae']['numeric_values'] = [
'total_hfe_templates' => isset( $template_counts->publish ) ? (int) $template_counts->publish : 0,
];
$widgets_usage = $this->hfe_get_widgets_usage();
foreach ( $widgets_usage as $key => $value ) {
$stats_data['plugin_data']['uae']['numeric_values'][ $key ] = $value;
}
$learn_progress = $this->get_learn_progress_analytics_data();
if ( ! empty( $learn_progress ) ) {
$stats_data['plugin_data']['uae']['learn_chapters_completed'] = $learn_progress;
}
// Add KPI tracking data.
$kpi_data = $this->get_kpi_tracking_data();
if ( ! empty( $kpi_data ) ) {
$stats_data['plugin_data']['uae']['kpi_records'] = $kpi_data;
}
// Flush pending events into payload (only if any exist).
$pending_events = HFE_Analytics_Events::flush_pending();
if ( ! empty( $pending_events ) ) {
$stats_data['plugin_data']['uae']['events_record'] = $pending_events;
}
return $stats_data;
}
/**
* Track first time a template is published.
*
* @param string $new_status New post status.
* @param string $old_status Old post status.
* @param \WP_Post $post Post object.
* @since 2.8.6
* @return void
*/
public function track_first_template_published( $new_status, $old_status, $post ) {
if ( 'publish' !== $new_status || 'publish' === $old_status || 'elementor-hf' !== $post->post_type ) {
return;
}
$template_type = get_post_meta( $post->ID, 'ehf_template_type', true );
$install_time = get_option( 'uae_usage_installed_time', 0 );
$days_since_install = 0;
if ( $install_time > 0 ) {
$days_since_install = (int) floor( ( time() - (int) $install_time ) / DAY_IN_SECONDS );
}
HFE_Analytics_Events::track(
'first_template_published',
(string) $post->ID,
[
'template_type' => ! empty( $template_type ) ? $template_type : 'unknown',
'days_since_install' => (string) $days_since_install,
]
);
}
/**
* Track first HFE widget usage on Elementor post save.
*
* Fires on elementor/editor/after_save. Checks if the saved post
* contains any HFE widget and tracks the first_widget_used event
* immediately instead of waiting for the daily cron scan.
*
* @since 2.8.7
* @param int $post_id Post ID.
* @param array $editor_data Elementor editor data.
* @return void
*/
public function track_first_widget_on_save( $post_id, $editor_data ) {
// Skip if already tracked — zero overhead after first detection.
if ( HFE_Analytics_Events::is_tracked( 'first_widget_used' ) ) {
return;
}
$allowed_widgets = [
'hfe-breadcrumbs-widget',
'hfe-cart',
'copyright',
'navigation-menu',
'page-title',
'post-info-widget',
'retina',
'hfe-search-button',
'site-logo',
'hfe-site-tagline',
'hfe-site-title',
'hfe-infocard',
'hfe-woo-product-grid',
'hfe-basic-posts',
'hfe-counter',
];
$elementor_data = get_post_meta( $post_id, '_elementor_data', true );
if ( empty( $elementor_data ) ) {
return;
}
$first_widget = '';
foreach ( $allowed_widgets as $widget ) {
if ( false !== strpos( $elementor_data, '"widgetType":"' . $widget . '"' ) ) {
$first_widget = $widget;
break;
}
}
if ( empty( $first_widget ) ) {
return;
}
$install_time = get_option( 'uae_usage_installed_time', 0 );
$days_since_install = 0;
if ( $install_time > 0 ) {
$days_since_install = (int) floor( ( time() - (int) $install_time ) / DAY_IN_SECONDS );
}
HFE_Analytics_Events::track(
'first_widget_used',
$first_widget,
[
'days_since_install' => (string) $days_since_install,
]
);
}
/**
* Detect state-based events that can't use direct hooks.
* Uses dedup in HFE_Analytics_Events::track() — safe to call repeatedly.
*
* @since 2.8.6
* @return void
*/
private function detect_state_events() {
// Read pushed + pending once to avoid repeated get_option calls per event.
$pushed = get_option( 'hfe_usage_events_pushed', [] );
$pushed = is_array( $pushed ) ? $pushed : [];
$pending = get_option( 'hfe_usage_events_pending', [] );
$pending = is_array( $pending ) ? $pending : [];
$tracked_names = array_merge( $pushed, array_column( $pending, 'event_name' ) );
// onboarding_completed: detect completed or early-exit state from the analytics blob.
if ( ! in_array( 'onboarding_completed', $tracked_names, true ) ) {
$onboarding_analytics = get_option( 'hfe_onboarding_analytics', [] );
$onboarding_done = 'yes' === get_option( 'hfe_onboarding_triggered' );
$onboarding_skipped = ! empty( $onboarding_analytics['exited_early'] ) && empty( $onboarding_analytics['completed'] );
if ( $onboarding_done || $onboarding_skipped ) {
HFE_Analytics_Events::track(
'onboarding_completed',
$onboarding_skipped ? 'no' : 'yes',
[ 'skipped' => (string) (int) $onboarding_skipped ]
);
}
}
// first_widget_used: tracked in real-time via elementor/editor/after_save hook.
// post_duplicator_used: fires once when the post duplicator feature has been used.
if ( ! in_array( 'post_duplicator_used', $tracked_names, true ) ) {
if ( (int) get_option( 'uae_duplicator_count', 0 ) > 0 ) {
$install_time = get_option( 'uae_usage_installed_time', 0 );
$days_since_install = 0;
if ( $install_time > 0 ) {
$days_since_install = (int) floor( ( time() - (int) $install_time ) / DAY_IN_SECONDS );
}
HFE_Analytics_Events::track(
'post_duplicator_used',
'yes',
[ 'days_since_install' => (string) $days_since_install ]
);
}
}
}
/**
* Fetch Elementor data.
*/
private function hfe_get_widgets_usage() {
return get_option( 'uae_widgets_usage_data_option', [] );
}
/**
* Get UAE learn progress analytics data.
*
* @return array
*/
private function get_learn_progress_analytics_data() {
global $wpdb;
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT meta_value FROM {$wpdb->usermeta} WHERE meta_key = %s LIMIT 100",
'hfe_learn_progress'
),
ARRAY_A
);
if ( empty( $results ) ) {
return [];
}
if ( ! class_exists( '\HFE\API\HFE_Learn_API' ) ) {
return [];
}
$chapters = \HFE\API\HFE_Learn_API::get_chapters_structure();
$completed_chapters = [];
foreach ( $results as $row ) {
$progress_data = maybe_unserialize( $row['meta_value'] );
// Guard against object injection — only accept arrays.
if ( ! is_array( $progress_data ) || is_object( $progress_data ) ) {
continue;
}
foreach ( $chapters as $chapter ) {
$chapter_id = $chapter['id'];
// Skip already counted.
if ( in_array( $chapter_id, $completed_chapters, true ) ) {
continue;
}
// Skip invalid chapters.
if ( empty( $chapter['steps'] ) || ! is_array( $chapter['steps'] ) ) {
continue;
}
// Skip if not present in user data.
if ( empty( $progress_data[ $chapter_id ] ) || ! is_array( $progress_data[ $chapter_id ] ) ) {
continue;
}
$all_steps_completed = true;
foreach ( $chapter['steps'] as $step ) {
$step_id = $step['id'];
if (
! isset( $progress_data[ $chapter_id ][ $step_id ] ) ||
! $progress_data[ $chapter_id ][ $step_id ]
) {
$all_steps_completed = false;
break;
}
}
if ( $all_steps_completed ) {
$completed_chapters[] = $chapter_id;
}
}
}
return array_values( array_unique( $completed_chapters ) );
}
/**
* Get KPI tracking data for the last 2 days (excluding today).
*
* Uses stored snapshots for state-based metrics (total_templates,
* widgets_count, total_widget_instances) and computes modified_templates
* fresh for each completed past day to ensure accurate counts.
*
* @since 2.8.4
* @return array KPI data organized by date.
*/
private function get_kpi_tracking_data() {
$snapshots = get_option( 'hfe_kpi_daily_snapshots', [] );
if ( empty( $snapshots ) || ! is_array( $snapshots ) ) {
return [];
}
$kpi_data = [];
$today = current_time( 'Y-m-d' );
// Only send data for dates that have actual per-day snapshots.
for ( $i = 1; $i <= 2; $i++ ) {
$date = wp_date( 'Y-m-d', strtotime( $today . ' -' . $i . ' days' ) );
if ( ! isset( $snapshots[ $date ]['numeric_values'] ) ) {
continue;
}
$kpi_data[ $date ] = [
'numeric_values' => array_merge(
$snapshots[ $date ]['numeric_values'],
[ 'modified_templates' => $this->get_modified_template_count( $date ) ]
),
];
}
return $kpi_data;
}
/**
* Get count of HFE templates modified on a given date.
*
* @since 2.8.4
* @param string $date Date in Y-m-d format.
* @return int Modified template count for the date.
*/
private function get_modified_template_count( $date ) {
$query = new WP_Query(
[
'post_type' => 'elementor-hf',
'post_status' => 'publish',
'posts_per_page' => 1,
'no_found_rows' => false,
'fields' => 'ids',
'date_query' => [
[
'column' => 'post_modified',
'after' => $date . ' 00:00:00',
'before' => $date . ' 23:59:59',
'inclusive' => true,
],
],
]
);
return (int) $query->found_posts;
}
}
}
new HFE_Analytics();
PK ���\�A̸y( y( inc/class-hfe-promotion.phpnu �[��� <?php
/**
* HFE Promotion Class
*
* Promotes Ultimate Elementor extensions within Header Footer Elementor
*
* @package header-footer-elementor
*/
namespace HFE\Extensions;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
use Elementor\Controls_Manager;
/**
* Class HFE_Promotion
*/
class HFE_Promotion {
/**
* Constructor
*/
public function __construct() {
// Only show promotions if Ultimate Elementor Pro is not active
if ( ! $this->is_ultimate_elementor_active() ) {
$this->init_hooks();
}
}
/**
* Initialize hooks
*/
private function init_hooks() {
// Particles Extension - Add to section/column/container background sections
add_action( 'elementor/element/section/section_background/after_section_end', [ $this, 'add_particles_promotion' ], 10 );
add_action( 'elementor/element/column/section_style/after_section_end', [ $this, 'add_particles_promotion' ], 10 );
add_action( 'elementor/element/container/section_background/after_section_end', [ $this, 'add_particles_promotion' ], 10 );
// Display Conditions - Add to section/column/container advanced sections and common widgets
add_action( 'elementor/element/section/section_advanced/after_section_end', [ $this, 'add_display_conditions_promotion' ], 10 );
add_action( 'elementor/element/column/section_advanced/after_section_end', [ $this, 'add_display_conditions_promotion' ], 10 );
add_action( 'elementor/element/container/section_layout/after_section_end', [ $this, 'add_display_conditions_promotion' ], 10 );
add_action( 'elementor/element/common/_section_style/after_section_end', [ $this, 'add_display_conditions_promotion' ], 10 );
// Party Propz Extension - Add to section/column/container advanced sections and common widgets
add_action( 'elementor/element/section/section_advanced/after_section_end', [ $this, 'add_party_propz_promotion' ], 10 );
add_action( 'elementor/element/column/section_advanced/after_section_end', [ $this, 'add_party_propz_promotion' ], 10 );
add_action( 'elementor/element/container/section_layout/after_section_end', [ $this, 'add_party_propz_promotion' ], 10 );
add_action( 'elementor/element/common/_section_style/after_section_end', [ $this, 'add_party_propz_promotion' ], 10 );
// Sticky Header - Only for header templates (check if we're in header context)
add_action( 'elementor/element/section/section_advanced/after_section_end', [ $this, 'add_sticky_header_promotion' ], 10 );
add_action( 'elementor/element/container/section_layout/after_section_end', [ $this, 'add_sticky_header_promotion' ], 10 );
}
/**
* Check if Ultimate Elementor Pro is active
*/
private function is_ultimate_elementor_active() {
return defined( 'UAEL_PRO' ) && UAEL_PRO;
}
/**
* Check if we're editing a header template
*/
private function is_header_template() {
global $post;
// Validate $post is an object and has ID property
if ( ! is_object( $post ) || ! isset( $post->ID ) || ! is_numeric( $post->ID ) ) {
return false;
}
// Sanitize post ID
$post_id = absint( $post->ID );
if ( ! $post_id ) {
return false;
}
$post_type = get_post_type( $post_id );
$template_type = get_post_meta( $post_id, 'ehf_template_type', true );
// Sanitize template type
$template_type = sanitize_text_field( $template_type );
return ( 'elementor-hf' === $post_type && 'type_header' === $template_type );
}
/**
* Generate promotional teaser template
*/
private function get_teaser_template( $args ) {
// Validate input is array
if ( ! is_array( $args ) ) {
$args = [];
}
$defaults = [
'description' => '',
'upgrade_text' => __( 'Upgrade Now', 'header-footer-elementor' ),
'upgrade_url' => '',
];
$args = wp_parse_args( $args, $defaults );
// Additional sanitization
$description = sanitize_text_field( $args['description'] );
$upgrade_text = sanitize_text_field( $args['upgrade_text'] );
$upgrade_url = esc_url_raw( $args['upgrade_url'] );
// Validate URL
if ( ! filter_var( $upgrade_url, FILTER_VALIDATE_URL ) ) {
$upgrade_url = '#';
}
$html = '
<div class="hfe-promotion-box">
<div class="hfe-promo-content">
<div class="hfe-promo-description">' . esc_html( $description ) . '</div>
<a href="' . esc_url( $upgrade_url ) . '" target="_blank" rel="noopener noreferrer" class="hfe-promo-button elementor-button e-accent dialog-button">
' . esc_html( $upgrade_text ) . '
</a>
</div>
</div>
<style>
.hfe-promo-description{
line-height: 19.5px;
font-size: 13px;
}
.hfe-promo-button{
margin-top:10px;
}
.hfe-lock.eicon-lock:hover{
color: #93003f;
}
</style>
';
return $html;
}
/**
* Get sanitized promotion label
*/
private function get_promotion_label( $feature_name ) {
$feature_name = sanitize_text_field( $feature_name );
$lock_icon = '<i class="hfe-lock eicon-lock"></i>';
// Using sprintf for better string formatting
return sprintf(
/* translators: %1$s: Feature name, %2$s: Lock icon */
__( 'UAE - %1$s %2$s', 'header-footer-elementor' ),
esc_html( $feature_name ),
$lock_icon // This is safe as it's hardcoded HTML
);
}
/**
* Add Particles extension promotion
*/
public function add_particles_promotion( $element ) {
$element->start_controls_section(
'hfe_particles_promo',
[
'label' => $this->get_promotion_label( __( 'Particle Backgrounds', 'header-footer-elementor' ) ),
'tab' => Controls_Manager::TAB_STYLE,
]
);
$element->add_control(
'hfe_particles_promo_content',
[
'type' => Controls_Manager::RAW_HTML,
'raw' => $this->get_teaser_template([
'description' => __( 'Use Particle Backgrounds and other Pro features to extend your toolbox with more control and flexibility.', 'header-footer-elementor' ),
'upgrade_url' => 'https://ultimateelementor.com/pricing/?utm_source=plugin-editor&utm_medium=particle-background-promo&utm_campaign=uae-upgrade',
]),
]
);
$element->end_controls_section();
}
/**
* Add Display Conditions extension promotion
*/
public function add_display_conditions_promotion( $element ) {
$element->start_controls_section(
'hfe_display_conditions_promo',
[
'label' => $this->get_promotion_label( __( 'Display Conditions', 'header-footer-elementor' ) ),
'tab' => Controls_Manager::TAB_ADVANCED,
]
);
$element->add_control(
'hfe_display_conditions_promo_content',
[
'type' => Controls_Manager::RAW_HTML,
'raw' => $this->get_teaser_template([
'description' => __( 'Use Advanced Display Condition and other Pro features to extend your toolbox with more control and flexibility.', 'header-footer-elementor' ),
'upgrade_url' => 'https://ultimateelementor.com/pricing/?utm_source=plugin-editor&utm_medium=display-conditions-promo&utm_campaign=uae-upgrade',
]),
]
);
$element->end_controls_section();
}
/**
* Add Party Propz extension promotion
*/
public function add_party_propz_promotion( $element ) {
$element->start_controls_section(
'hfe_party_propz_promo',
[
'label' => $this->get_promotion_label( __( 'Party Propz', 'header-footer-elementor' ) ),
'tab' => Controls_Manager::TAB_ADVANCED,
]
);
$element->add_control(
'hfe_party_propz_promo_content',
[
'type' => Controls_Manager::RAW_HTML,
'raw' => $this->get_teaser_template([
'description' => __( 'Use Party Propz and other Pro features to extend your toolbox with more control and flexibility.', 'header-footer-elementor' ),
'upgrade_url' => 'https://ultimateelementor.com/pricing/?utm_source=plugin-editor&utm_medium=party-propz-promo&utm_campaign=uae-upgrade',
]),
]
);
$element->end_controls_section();
}
/**
* Add Sticky Header extension promotion (only for header templates)
*/
public function add_sticky_header_promotion( $element ) {
// Only show for header templates
if ( ! $this->is_header_template() ) {
return;
}
$element->start_controls_section(
'hfe_sticky_header_promo',
[
'label' => $this->get_promotion_label( __( 'Sticky Header', 'header-footer-elementor' ) ),
'tab' => Controls_Manager::TAB_ADVANCED,
]
);
$element->add_control(
'hfe_sticky_header_promo_content',
[
'type' => Controls_Manager::RAW_HTML,
'raw' => $this->get_teaser_template([
'description' => __( 'Use Sticky Header and other Pro features to extend your toolbox with more control and flexibility.', 'header-footer-elementor' ),
'upgrade_url' => 'https://ultimateelementor.com/pricing/?utm_source=plugin-editor&utm_medium=sticky-header-promo&utm_campaign=uae-upgrade',
]),
]
);
$element->end_controls_section();
}
}
// Initialize the promotion class
new HFE_Promotion();
PK ���\;̕#(� (� inc/class-hfe-learn-api.phpnu �[��� <?php
/**
* HFE Learn API
*
* @package HFE
* @since 2.8.4
*/
namespace HFE\API;
use WP_REST_Controller;
use WP_REST_Server;
use WP_REST_Response;
use WP_Error;
/**
* Class HFE_Learn_API
*
* Handles the learn tab functionality including REST API endpoints and admin actions.
*
* @since 2.8.4
*/
class HFE_Learn_API extends WP_REST_Controller {
/**
* REST API namespace
*
* @since 2.8.4
* @var string
*/
protected $namespace = 'hfe/v1';
/**
* Constructor
*
* Initialize hooks and actions for the learn API.
*
* @since 2.8.4
*/
public function __construct() {
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
// Header.
add_action( 'admin_post_uae_create_header_elementor', array( $this, 'uae_create_header_elementor' ) );
add_action( 'admin_post_uae_edit_header_elementor', array( $this, 'uae_edit_header_elementor' ) );
// Footer.
add_action( 'admin_post_uae_create_footer_elementor', array( $this, 'uae_create_footer_elementor' ) );
add_action( 'admin_post_uae_edit_footer_elementor', array( $this, 'uae_edit_footer_elementor' ) );
// Page Builder.
add_action( 'admin_post_uae_create_page_elementor', array( $this, 'uae_create_page_and_open_elementor' ) );
add_action( 'admin_post_uae_open_extension', array( $this, 'uae_open_extension' ) );
add_action( 'admin_post_uae_enable_duplicator', array( $this, 'uae_enable_duplicator' ) );
add_action( 'elementor/editor/after_enqueue_scripts', array( $this, 'uae_auto_open_extension_tab' ) );
add_action( 'elementor/editor/after_enqueue_scripts', array( $this, 'uae_elementor_widget_search' ) );
}
/**
* Add Elementor widget search functionality.
*
* Enqueues inline JavaScript to handle widget search and auto-click in Elementor editor.
*
* @since 2.8.4
* @return void
*/
public function uae_elementor_widget_search() {
wp_add_inline_script(
'elementor-editor',
"(function () {
jQuery(window).on('elementor:init', function () {
const params = new URLSearchParams(window.location.search);
let keyword = params.get('uae_widgets');
if (!keyword) {
return;
}
const lowerKeyword = keyword.toLowerCase();
const skipClick = ( lowerKeyword === 'header' || lowerKeyword === 'footer' );
if ( skipClick ) {
keyword = 'uae';
}
let attempts = 0;
const maxAttempts = 40;
const interval = setInterval(function () {
attempts++;
const searchInput = document.querySelector(
'.elementor-panel input[type=\"search\"]'
);
if (!searchInput) {
if (attempts >= maxAttempts) {
clearInterval(interval);
}
return;
}
searchInput.value = keyword;
searchInput.dispatchEvent(
new Event('input', { bubbles: true })
);
if ( skipClick ) {
clearInterval(interval);
return;
}
setTimeout(function () {
const widgets = document.querySelectorAll(
'#elementor-panel-elements-wrapper .elementor-element'
);
for (const widget of widgets) {
const titleEl = widget.querySelector('.title');
if (
titleEl &&
titleEl.textContent
.toLowerCase()
.includes(lowerKeyword)
) {
widget.click();
clearInterval(interval);
return;
}
}
}, 300);
if (attempts >= maxAttempts) {
clearInterval(interval);
}
}, 250);
});
})();"
);
}
/**
* Handle header/footer template creation or editing.
*
* Creates or finds existing header/footer template and redirects to appropriate editor.
*
* @since 2.8.4
* @param string $type Template type ('header' or 'footer').
* @param bool $open_elementor Whether to open in Elementor editor.
* @return void
*/
private function handle_hf_template( $type = 'header', $open_elementor = true ) {
check_admin_referer( 'hfe_learn_action' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Permission denied.', 'header-footer-elementor' ) );
}
$title = ( 'footer' === $type )
? __( 'UAE Learn Footer', 'header-footer-elementor' )
: __( 'UAE Learn Header', 'header-footer-elementor' );
$existing = get_posts(
array(
'post_type' => 'elementor-hf',
'post_status' => array( 'draft', 'publish' ),
'posts_per_page' => 1,
'fields' => 'ids',
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'uae_learn',
'value' => 'yes',
),
array(
'key' => 'ehf_template_type',
'value' => 'type_' . $type,
),
),
)
);
if ( ! empty( $existing ) ) {
$post_id = $existing[0];
} else {
$post_id = wp_insert_post(
array(
'post_type' => 'elementor-hf',
'post_title' => $title,
'post_status' => 'draft',
)
);
$template_type = 'type_' . $type;
update_post_meta( $post_id, '_elementor_edit_mode', 'builder' );
update_post_meta( $post_id, '_wp_page_template', 'default' );
update_post_meta( $post_id, 'ehf_template_type', $template_type );
update_post_meta( $post_id, 'uae_learn', 'yes' );
}
if ( $open_elementor ) {
wp_safe_redirect(
admin_url(
'post.php?post=' . $post_id .
'&action=elementor' .
'&uae_widgets=' . $type
)
);
} else {
wp_safe_redirect(
admin_url(
'post.php?post=' . $post_id .
'&action=edit&open_metabox=ehf-meta-box'
)
);
}
exit;
}
/**
* Create Header and Redirect to Header screen.
*
* @since 2.8.4
* @return void
*/
public function uae_create_header_elementor() {
$this->handle_hf_template( 'header', false );
}
/**
* Create or check Header and Redirect to Elementor.
*
* @since 2.8.4
* @return void
*/
public function uae_edit_header_elementor() {
$this->handle_hf_template( 'header', true );
}
/**
* Create Footer and Redirect to Footer screen.
*
* @since 2.8.4
* @return void
*/
public function uae_create_footer_elementor() {
$this->handle_hf_template( 'footer', false );
}
/**
* Create or check Footer and Redirect to Elementor.
*
* @since 2.8.4
* @return void
*/
public function uae_edit_footer_elementor() {
$this->handle_hf_template( 'footer', true );
}
/**
* Create Page and Open Elementor showing UAE widgets.
*
* Creates or finds existing UAE learn page and opens it in Elementor editor
* with optional widget search functionality.
*
* @since 2.8.4
* @return void
*/
public function uae_create_page_and_open_elementor() {
check_admin_referer( 'hfe_learn_action' );
if ( ! current_user_can( 'edit_pages' ) ) {
wp_die( esc_html__( 'Permission denied.', 'header-footer-elementor' ) );
}
// Get keyword from request.
$uae_widgets = isset( $_GET['uae_widgets'] )
? sanitize_text_field( wp_unslash( $_GET['uae_widgets'] ) )
: '';
$existing = get_posts(
array(
'post_type' => 'page',
'post_status' => array( 'draft', 'publish', 'private' ),
'meta_key' => 'uae_learn',
'meta_value' => 'yes',
'posts_per_page' => 1,
'fields' => 'ids',
)
);
if ( ! empty( $existing ) ) {
$page_id = $existing[0];
wp_safe_redirect(
admin_url(
'post.php?post=' . $page_id .
'&action=elementor' .
'&uae_widgets=' . rawurlencode( $uae_widgets )
)
);
exit;
}
$page_id = wp_insert_post(
array(
'post_type' => 'page',
'post_title' => __( 'UAE Learn Page', 'header-footer-elementor' ),
'post_status' => 'draft',
)
);
if ( is_wp_error( $page_id ) ) {
wp_die( esc_html__( 'Page creation failed.', 'header-footer-elementor' ) );
}
update_post_meta( $page_id, '_elementor_edit_mode', 'builder' );
update_post_meta( $page_id, '_wp_page_template', 'elementor_canvas' );
update_post_meta( $page_id, 'uae_learn', 'yes' );
wp_safe_redirect(
admin_url(
'post.php?post=' . $page_id .
'&action=elementor' .
'&uae_widgets=' . rawurlencode( $uae_widgets )
)
);
exit;
}
/**
* Fetch elementor kit id and Redirect to elementor site setting.
*
* Opens specific extension tab in Elementor site settings.
*
* @since 2.8.4
* @return void
*/
public function uae_open_extension() {
check_admin_referer( 'hfe_learn_action' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Permission denied.', 'header-footer-elementor' ) );
}
$ext = isset( $_GET['ext'] )
? sanitize_key( $_GET['ext'] )
: '';
if ( empty( $ext ) ) {
wp_die( esc_html__( 'Invalid extension.', 'header-footer-elementor' ) );
}
// Active Elementor Kit.
$kit_id = get_option( 'elementor_active_kit' );
if ( empty( $kit_id ) ) {
wp_die( esc_html__( 'No active Elementor Kit found.', 'header-footer-elementor' ) );
}
wp_safe_redirect(
admin_url(
'post.php?post=' . absint( $kit_id ) .
'&action=elementor' .
'&open_ext=' . rawurlencode( $ext )
)
);
exit;
}
/**
* Enable UAE Duplicator and redirect to pages.
*
* Enables the post duplicator widget and redirects to the pages list.
*
* @since 2.8.4
* @return void
*/
public function uae_enable_duplicator() {
check_admin_referer( 'hfe_learn_action' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Permission denied.', 'header-footer-elementor' ) );
}
// Get current enabled widgets.
$enabled_widgets = get_option( '_hfe_widgets', array() );
if ( ! is_array( $enabled_widgets ) ) {
$enabled_widgets = array();
}
// Check if duplicator is already enabled.
if ( ! isset( $enabled_widgets['Post_Duplicator'] ) || 'Post_Duplicator' !== $enabled_widgets['Post_Duplicator'] ) {
// Enable the duplicator widget (set value to slug).
$enabled_widgets['Post_Duplicator'] = 'Post_Duplicator';
update_option( '_hfe_widgets', $enabled_widgets );
}
// Redirect to pages list.
wp_safe_redirect( admin_url( 'edit.php?post_type=page' ) );
exit;
}
/**
* Auto open extension tab in Elementor.
*
* Adds JavaScript to automatically open specific extension tabs in Elementor kit.
*
* @since 2.8.4
* @return void
*/
public function uae_auto_open_extension_tab() {
?>
<script>
(function(){
const MAP = {
reading_progress : '.elementor-panel-menu-item-hfe-reading-progress-bar',
scroll_to_top : '.elementor-panel-menu-item-hfe-scroll-to-top-settings'
};
function tryOpen( selector ) {
if ( ! window.elementor || ! elementor.config || ! elementor.config.document ) {
return;
}
if ( elementor.config.document.type !== 'kit' ) {
return;
}
const btn = document.querySelector( selector );
if ( btn ) {
btn.click();
return;
}
setTimeout( function(){
tryOpen( selector );
}, 200 );
}
window.addEventListener('elementor:init', function () {
const params = new URLSearchParams( window.location.search );
const ext = params.get('open_ext');
if ( ! ext || ! MAP[ ext ] ) {
return;
}
tryOpen( MAP[ ext ] );
});
})();
</script>
<?php
}
/**
* Register REST API routes
*
* Registers endpoints for learning chapters and progress tracking.
*
* @since 2.8.4
* @return void
*/
public function register_routes() {
// GET endpoint - fetch chapters with progress.
register_rest_route(
$this->namespace,
'get-learn-chapters',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_learn_chapters' ),
'permission_callback' => array( $this, 'get_permissions_check' ),
),
)
);
// POST endpoint - save progress.
register_rest_route(
$this->namespace,
'update-learn-progress',
array(
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'save_learn_progress' ),
'permission_callback' => array( $this, 'get_permissions_check' ),
'args' => array(
'chapterId' => array(
'required' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
),
'stepId' => array(
'required' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
),
'completed' => array(
'required' => true,
'type' => 'boolean',
),
),
),
)
);
}
/**
* Get default learn chapters structure.
*
* Returns the complete structure of all available chapters and their steps.
* This serves as the source of truth for chapter definitions used across
* the theme for both frontend display and analytics validation.
*
* @return array Array of chapter objects with their steps.
* @since 2.8.4
*/
public static function get_chapters_structure() {
// Define UAE learning chapters.
$chapters = array(
array(
'id' => 'create-header',
'title' => __( 'Create Your Header', 'header-footer-elementor' ),
'description' => __( 'Build a stunning header that showcases your brand on every page.', 'header-footer-elementor' ),
'steps' => array(
array(
'id' => 'setup-header',
'title' => __( 'Set Up Header Under 5 Mins!', 'header-footer-elementor' ),
'description' => __( 'Create a branded header that appears on every page and keeps your navigation consistent.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Create-Header.gif',
'alt' => __( 'Add header in Elementor', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Set Up Header', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_create_header_elementor' ) ),
'isExternal' => true,
),
'completed' => false,
),
// STEP 2.
array(
'id' => 'setup-display-conditions',
'title' => __( 'Control Where Your Template Appears', 'header-footer-elementor' ),
'description' => __( 'Use Display Conditions to choose exactly where this template shows — entire site, specific pages, posts, or archives.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Header-Display-Con.gif',
'alt' => __( 'Add Display conditions to your header', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Add Display Conditions', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_create_header_elementor' ) ),
'isExternal' => true,
),
'completed' => false,
),
// STEP 3.
array(
'id' => 'add-header-widgets',
'title' => __( 'Add Your Favorite UAE Widgets and Make it Live', 'header-footer-elementor' ),
'description' => __( 'Include logo, menu, CTA, and contact access for a complete header.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Edit-Header.gif',
'alt' => __( 'Add UAE widgets to your header', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Add Header Widgets', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_edit_header_elementor' ) ),
'isExternal' => true,
),
'completed' => false,
),
),
),
array(
'id' => 'create-footer',
'title' => __( 'Create Your Footer', 'header-footer-elementor' ),
'description' => __( 'Design a professional footer that builds trust and improves site navigation.', 'header-footer-elementor' ),
'steps' => array(
// STEP 1.
array(
'id' => 'setup-footer',
'title' => __( 'Set Up Footer in less than 5 mins!', 'header-footer-elementor' ),
'description' => __( 'Add a global footer for consistent links, policies, and brand presence on every page.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Create-Footer.gif',
'alt' => __( 'Set Up Footer Template', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Set Up Footer', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_create_footer_elementor' ) ),
'isExternal' => true,
),
'completed' => false,
),
array(
'id' => 'setup-display-conditions',
'title' => __( 'Control Where Your Template Appears', 'header-footer-elementor' ),
'description' => __( 'Use Display Conditions to choose exactly where this template shows — entire site, specific pages, posts, or archives.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Footer-Display-Con.gif',
'alt' => __( 'Add display conditons to your footer', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Add Display Conditions', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_create_footer_elementor' ) ),
'isExternal' => true,
),
'completed' => false,
),
// STEP 3.
array(
'id' => 'add-footer-widgets',
'title' => __( 'Add Your Footer Widgets and Make it live.', 'header-footer-elementor' ),
'description' => __( 'Insert essential elements like Social Icons, Contact Info, Copyright Text, and Navigation Links for complete site credibility.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Edit-Footer.gif',
'alt' => __( 'Footer Widgets in Elementor', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Add Footer Widgets', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_edit_footer_elementor' ) ),
'isExternal' => true,
),
'completed' => false,
),
),
),
array(
'id' => 'add-powerful-widgets',
'title' => __( 'Add More Powerful Widgets', 'header-footer-elementor' ),
'description' => __( 'Supercharge your pages with UAE\'s most popular content widgets for better engagement.', 'header-footer-elementor' ),
'steps' => array(
// STEP 1.
array(
'id' => 'add-info-card',
'title' => __( 'Create Eye-Catching Info Cards', 'header-footer-elementor' ),
'description' => __( 'Display key features, services, or benefits with beautiful Info Card widgets that convert visitors into customers.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Info-Card.gif',
'alt' => __( 'Info Card Widget in Elementor', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Add Info Card', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_create_page_elementor&uae_widgets=info card' ) ),
'isExternal' => true,
),
'completed' => false,
),
// STEP 2.
array(
'id' => 'add-posts-widget',
'title' => __( 'Showcase Dynamic Content with Posts', 'header-footer-elementor' ),
'description' => __( 'Automatically display your latest blog posts, news, or updates with the Basic Posts widget for fresh, engaging content.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Basic-Post.gif',
'alt' => __( 'Basic Posts Widget in Elementor', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Add Posts Widget', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_create_page_elementor&uae_widgets=basic posts' ) ),
'isExternal' => true,
),
'completed' => false,
),
),
),
array(
'id' => 'uae-power-extensions',
'title' => __( 'Power Extensions', 'header-footer-elementor' ),
'description' => __( 'Enable time-saving features that streamline your workflow and enhance user experience.', 'header-footer-elementor' ),
'steps' => array(
// STEP 1.
array(
'id' => 'enable-duplicator',
'title' => __( 'Duplicate Pages in One Click', 'header-footer-elementor' ),
'description' => __( 'Save hours by cloning any page or post instantly with Post Duplicator - perfect for creating template variations.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Duplicator.gif',
'alt' => __( 'Post Duplicator Extension', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Enable UAE Duplicator', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_enable_duplicator' ) ),
'isExternal' => true,
),
'completed' => false,
),
// STEP 2.
array(
'id' => 'enable-scroll-to-top',
'title' => __( 'Add Scroll to Top Button', 'header-footer-elementor' ),
'description' => __( 'Improve navigation on long pages with a floating button that helps visitors jump back to the top effortlessly.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Scroll-Button.gif',
'alt' => __( 'Scroll To Top Setting', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Enable Scroll Button', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_open_extension&ext=scroll_to_top' ) ),
'isExternal' => true,
),
'completed' => false,
),
array(
'id' => 'enable-reading-progres-bar',
'title' => __( 'Add Reading Progress Bar', 'header-footer-elementor' ),
'description' => __( 'Improve navigation on long pages with a floating button that helps visitors jump back to the top effortlessly.', 'header-footer-elementor' ),
'learn' => array(
'type' => 'dialog',
'content' => array(
'type' => 'image',
'data' => array(
'src' => 'https://ultimateelementor.com/wp-content/uploads/2026/02/Learn-Tab-Reading-Progress-Bar.gif',
'alt' => __( 'Reading Progress Bar', 'header-footer-elementor' ),
),
),
),
'action' => array(
'label' => __( 'Enable Reading Progress Bar', 'header-footer-elementor' ),
'url' => add_query_arg( '_wpnonce', wp_create_nonce( 'hfe_learn_action' ), admin_url( 'admin-post.php?action=uae_open_extension&ext=reading_progress' ) ),
'isExternal' => true,
),
'completed' => false,
),
),
),
);
// Add Pro features chapter if not Pro.
if ( ! defined( 'UAEL_PRO' ) ) {
$chapters[] = array(
'id' => 'pro-features',
'title' => __( 'Pro Features', 'header-footer-elementor' ),
'description' => __( 'Unlock advanced widgets and features with UAE Pro', 'header-footer-elementor' ),
'steps' => array(
array(
'id' => 'explore-pro',
'title' => __( 'Explore Pro Features', 'header-footer-elementor' ),
'description' => __( 'See what\'s available in the Pro version', 'header-footer-elementor' ),
'action' => array(
'label' => __( 'Upgrade to Pro', 'header-footer-elementor' ),
'url' => 'https://ultimateelementor.com/pricing/?utm_source=hfe-learn&utm_medium=learn-tab&utm_campaign=upgrade',
'isExternal' => true,
),
'completed' => false,
'isPro' => true,
),
),
);
}
/**
* Filter learn chapters structure.
*
* @param array $chapters Learn chapters data.
* @since 2.8.4
*/
return apply_filters( 'hfe_learn_chapters', $chapters );
}
/**
* Get learn chapters with user progress
*
* Retrieves all learning chapters with user-specific progress data.
*
* @since 2.8.4
* @param WP_REST_Request $request Request object.
* @return WP_REST_Response|array
*/
public function get_learn_chapters( $request ) {
// Get saved progress from user meta.
$user_id = get_current_user_id();
// Get chapters structure.
$chapters = self::get_chapters_structure();
// Get saved progress from user meta.
$saved_progress = get_user_meta( $user_id, 'hfe_learn_progress', true );
if ( ! is_array( $saved_progress ) ) {
$saved_progress = array();
}
// Merge saved progress with chapters.
foreach ( $chapters as &$chapter ) {
// Validate chapter structure.
if ( ! isset( $chapter['id'], $chapter['steps'] ) || ! is_array( $chapter['steps'] ) ) {
continue;
}
$chapter_id = $chapter['id'];
foreach ( $chapter['steps'] as &$step ) {
if ( ! isset( $step['id'] ) ) {
continue;
}
$step_id = $step['id'];
if ( isset( $saved_progress[ $chapter_id ][ $step_id ] ) ) {
$step['completed'] = $saved_progress[ $chapter_id ][ $step_id ];
}
}
}
return $chapters;
}
/**
* Save learn progress
*
* Updates user progress for a specific learning step.
*
* @since 2.8.4
* @param WP_REST_Request $request Request object.
* @return WP_REST_Response
*/
public function save_learn_progress( $request ) {
$chapter_id = $request->get_param( 'chapterId' );
$step_id = $request->get_param( 'stepId' );
$completed = $request->get_param( 'completed' );
// Get current progress.
$user_id = get_current_user_id();
$saved_progress = get_user_meta( $user_id, 'hfe_learn_progress', true );
if ( ! is_array( $saved_progress ) ) {
$saved_progress = array();
}
// Initialize chapter array if it doesn't exist.
if ( ! isset( $saved_progress[ $chapter_id ] ) || ! is_array( $saved_progress[ $chapter_id ] ) ) {
$saved_progress[ $chapter_id ] = array();
}
// Update progress for this step.
$saved_progress[ $chapter_id ][ $step_id ] = (bool) $completed;
// Save to user meta.
update_user_meta( $user_id, 'hfe_learn_progress', $saved_progress );
// Track event when ALL learn chapters are fully completed.
if ( (bool) $completed && class_exists( '\HFE_Analytics_Events' )
&& ! \HFE_Analytics_Events::is_tracked( 'learn_completed' )
) {
$chapters = self::get_chapters_structure();
$all_complete = true;
foreach ( $chapters as $chapter ) {
if ( empty( $chapter['steps'] ) || ! is_array( $chapter['steps'] ) ) {
continue;
}
if ( empty( $saved_progress[ $chapter['id'] ] ) || ! is_array( $saved_progress[ $chapter['id'] ] ) ) {
$all_complete = false;
break;
}
foreach ( $chapter['steps'] as $step ) {
if ( empty( $saved_progress[ $chapter['id'] ][ $step['id'] ] ) ) {
$all_complete = false;
break 2;
}
}
}
if ( $all_complete ) {
$install_time = get_option( 'uae_usage_installed_time', 0 );
$days_since_install = 0;
if ( $install_time > 0 ) {
$days_since_install = (int) floor( ( time() - (int) $install_time ) / DAY_IN_SECONDS );
}
\HFE_Analytics_Events::track(
'learn_completed',
(string) count( $chapters ),
[ 'days_since_install' => (string) $days_since_install ]
);
}
}
return new WP_REST_Response(
array(
'success' => true,
'message' => __( 'Progress saved successfully.', 'header-footer-elementor' ),
),
200
);
}
/**
* Permission check for API endpoints
*
* Checks if current user has permission to access learn API endpoints.
*
* @since 2.8.4
* @param WP_REST_Request $request Request object.
* @return bool|WP_Error
*/
public function get_permissions_check( $request ) {
if ( ! current_user_can( 'manage_options' ) ) {
return new WP_Error(
'rest_cannot_view',
__( 'Sorry, you cannot access this resource.', 'header-footer-elementor' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
}
// Initialize the API
new HFE_Learn_API();
PK ���\i���� � inc/settings/settings-app.phpnu �[��� <?php
/**
* Single page settings page
*
* @package HeaderFooterElementor
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<div id="hfe-settings-app" class="hfe-settings-app">
</div>
PK ���\dd��R R ! inc/settings/hfe-settings-api.phpnu �[��� <?php
/**
* HFE Settings API.
*
* @package HFE
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use HFE\WidgetsManager\Base\HFE_Helper;
/**
* Class HFE_Settings_Api.
*/
class HFE_Settings_Api {
/**
* Instance.
*
* @access private
* @var object Class object.
* @since 2.2.1
*/
private static $instance;
/**
* Get the singleton instance of the class.
*
* @return HFE_Settings_Api
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Initialize hooks.
*
* @since 2.2.1
* @return void
*/
private function __construct() {
// Log an error message to check if the file is loading.
add_action( 'rest_api_init', [ $this, 'register_routes' ] );
}
/**
* Register REST API routes.
*
* @since 2.2.1
* @return void
*/
public function register_routes() {
register_rest_route(
'hfe/v1',
'/widgets',
[
'methods' => 'GET',
'callback' => [ $this, 'get_hfe_widgets' ],
'permission_callback' => [ $this, 'get_items_permissions_check' ],
]
);
register_rest_route(
'hfe/v1',
'/plugins',
[
'methods' => 'GET',
'callback' => [ $this, 'get_plugins_list' ],
'permission_callback' => [ $this, 'get_items_permissions_check' ],
]
);
register_rest_route(
'hfe/v1',
'/templates',
[
'methods' => 'GET',
'callback' => [ $this, 'get_templates_status' ],
'permission_callback' => [ $this, 'get_items_permissions_check' ],
]
);
register_rest_route(
'hfe/v1',
'/email-webhook',
[
'methods' => 'POST',
'callback' => [ $this, 'send_email_to_webhook_api' ],
'permission_callback' => [ $this, 'get_items_permissions_check' ],
]
);
register_rest_route(
'hfe/v1',
'/recommended-plugins',
[
'methods' => 'GET',
'callback' => [ $this, 'get_recommended_plugins_list' ],
'permission_callback' => [ $this, 'get_items_permissions_check' ],
]
);
}
/**
* Check whether a given request has permission to read notes.
*
* @since 2.2.1
* @return WP_Error|boolean
*/
public function get_items_permissions_check() {
if ( ! current_user_can( 'manage_options' ) ) {
return new \WP_Error( 'uae_rest_not_allowed', __( 'Sorry, you are not authorized to perform this action.', 'header-footer-elementor' ), [ 'status' => 403 ] );
}
return true;
}
/**
* Get Starter Templates Status.
*
* @param WP_REST_Request $request Request object.
*/
public function get_templates_status( WP_REST_Request $request ) {
$nonce = $request->get_header( 'X-WP-Nonce' );
if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
return new WP_Error( 'invalid_nonce', __( 'Invalid nonce', 'header-footer-elementor' ), [ 'status' => 403 ] );
}
$templates_status = HFE_Helper::starter_templates_status();
$response_data = [
'templates_status' => $templates_status,
];
if ( 'Activated' === $templates_status ) {
$response_data['redirect_url'] = HFE_Helper::starter_templates_link();
}
return new WP_REST_Response( $response_data, 200 );
}
/**
* Callback function to return plugins list.
*
* @param WP_REST_Request $request Request object.
* @return WP_REST_Response
*/
public function get_plugins_list( $request ) {
$nonce = $request->get_header( 'X-WP-Nonce' );
if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
return new WP_Error( 'invalid_nonce', __( 'Invalid nonce', 'header-footer-elementor' ), [ 'status' => 403 ] );
}
// Fetch branding settings.
$plugins_list = HFE_Helper::get_bsf_plugins_list();
if ( ! is_array( $plugins_list ) ) {
return new WP_REST_Response( [ 'message' => __( 'Plugins list not found', 'header-footer-elementor' ) ], 404 );
}
return new WP_REST_Response( $plugins_list, 200 );
}
/**
*
* Callback function to return recommended plugins list.
*
* @param WP_REST_Request $request Request object.
*
* @return WP_REST_Response
*/
public function get_recommended_plugins_list( $request ) {
$nonce = $request->get_header( 'X-WP-Nonce' );
if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
return new WP_Error( 'invalid_nonce', __( 'Invalid nonce', 'header-footer-elementor' ), [ 'status' => 403 ] );
}
// Fetch recommended plugins list.
$recommended_plugins_list = HFE_Helper::get_recommended_bsf_plugins_list();
if ( ! is_array( $recommended_plugins_list ) ) {
return new WP_REST_Response( [ 'message' => __( 'Recommended plugins list not found', 'header-footer-elementor' ) ], 404 );
}
return new WP_REST_Response( $recommended_plugins_list, 200 );
}
/**
*
* Callback function to return widgets list.
*
* @param WP_REST_Request $request Request object.
*
* @return WP_REST_Response
*/
public function get_hfe_widgets( $request ) {
$nonce = $request->get_header( 'X-WP-Nonce' );
if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
return new WP_Error( 'invalid_nonce', __( 'Invalid nonce', 'header-footer-elementor' ), [ 'status' => 403 ] );
}
// Fetch widgets settings.
$widgets_list = HFE_Helper::get_all_widgets_list();
if ( ! is_array( $widgets_list ) ) {
return new WP_REST_Response( [ 'message' => __( 'Widgets list not found', 'header-footer-elementor' ) ], 404 );
}
return new WP_REST_Response( $widgets_list, 200 );
}
/**
* Get the API URL.
*
* @since 2.3.1
* @return string
*/
public function get_api_domain() {
return apply_filters( 'hfe_api_domain', 'https://websitedemos.net/' );
}
/**
* Send Email to Webhook.
* @param WP_REST_Request $request Request object.
*
*/
public function send_email_to_webhook_api( WP_REST_Request $request ) {
$nonce = $request->get_header( 'X-WP-Nonce' );
if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
return new WP_Error( 'invalid_nonce', __( 'Invalid nonce', 'header-footer-elementor' ), [ 'status' => 403 ] );
}
$email = sanitize_email( $request->get_param( 'email' ) );
$date = sanitize_text_field( $request->get_param( 'date' ) );
$fname = sanitize_text_field( $request->get_param( 'fname' ) );
$lname = sanitize_text_field( $request->get_param( 'lname' ) );
$isActive = sanitize_text_field( $request->get_param( 'isActive' ) );
$domain = sanitize_text_field( $request->get_param( 'domain' ) );
if ( ! empty( $domain ) && false === filter_var( $domain, FILTER_VALIDATE_URL ) ) {
return new WP_Error( 'invalid_domain', __( 'Invalid domain provided.', 'header-footer-elementor' ), [ 'status' => 400 ] );
}
$api_domain = trailingslashit( $this->get_api_domain() );
$api_domain_url = $api_domain . 'wp-json/uaelite/v1/subscribe/';
$validation_url = esc_url_raw( get_site_url() . '/wp-json/hfe/v1/email-response/' );
// Append session_id to track requests.
$body = array(
'email' => $email,
'date' => $date,
'fname' => $fname,
'lname' => $lname,
'isActive' => $isActive,
'domain' => $domain
);
$args = array(
'body' => $body,
'timeout' => 30,
);
$response = wp_remote_post( $api_domain_url, $args );
if ( is_wp_error( $response ) ) {
return new WP_Error( 'webhook_error', __( 'Error calling endpoint', 'header-footer-elementor' ), [ 'status' => 500 ] );
}
$response_code = wp_remote_retrieve_response_code( $response );
$response_body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! in_array( $response_code, [ 200, 201, 204 ], true ) ) {
error_log( 'HFE webhook API error: ' . ( isset( $response_body['message'] ) ? sanitize_text_field( $response_body['message'] ) : 'Unknown error' ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
return new WP_Error( 'webhook_error', __( 'Failed to send email. Please try again later.', 'header-footer-elementor' ), [ 'status' => $response_code ] );
}
update_option( 'uaelite_subscription', 'done' );
return new WP_REST_Response(
[
'message' => 'success'
],
200
);
}
}
// Initialize the HFE_Settings_Api class.
HFE_Settings_Api::get_instance();
PK ���\�L�_{ { inc/settings/admin-base.phpnu �[��� <?php
/**
* Admin Base HTML.
*
* @package header-footer-elementor
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<div class="hfe-menu-page-wrapper">
<div id="hfe-menu-page">
<div class="hfe-menu-page-content hfe-clear">
<?php
do_action( 'hfe_render_admin_page_content', $menu_page_slug, $page_action );
?>
</div>
</div>
</div>
PK ���\�pM� � 2 inc/compatibility/class-hfe-wpml-compatibility.phpnu �[��� <?php
/**
* WPML Compatibility for Header Footer Elementor.
*
* @package HFE
* @author HFE
* @copyright Copyright (c) 2018, HFE
* @link http://brainstormforce.com/
* @since HFE 1.0.9
*/
defined( 'ABSPATH' ) || exit;
/**
* Set up WPML Compatibiblity Class.
*/
class HFE_WPML_Compatibility {
/**
* Instance of HFE_WPML_Compatibility.
*
* @since 1.0.9
* @var null
*/
private static $_instance = null;
/**
* Get instance of HFE_WPML_Compatibility
*
* @since 1.0.9
* @return HFE_WPML_Compatibility
*/
public static function instance() {
if ( ! isset( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Setup actions and filters.
*
* @since 1.0.9
*/
private function __construct() {
add_filter( 'hfe_get_settings_type_header', [ $this, 'get_wpml_object' ] );
add_filter( 'hfe_get_settings_type_footer', [ $this, 'get_wpml_object' ] );
add_filter( 'hfe_get_settings_type_before_footer', [ $this, 'get_wpml_object' ] );
add_filter( 'hfe_render_template_id', [ $this, 'get_wpml_object' ] );
}
/**
* Pass the final header and footer ID from the WPML's object filter to allow strings to be translated.
*
* @since 1.0.9
* @param Int $id Post ID of the template being rendered.
* @return Int $id Post ID of the template being rendered, Passed through the `wpml_object_id` id.
*/
public function get_wpml_object( $id ) {
$translated_id = apply_filters( 'wpml_object_id', $id );
if ( defined( 'POLYLANG_BASENAME' ) ) {
if ( null === $translated_id ) {
// The current language is not defined yet or translation is not available.
return $id;
} else {
// Return translated post ID.
return $translated_id;
}
}
if ( null === $translated_id ) {
$translated_id = '';
}
return $translated_id;
}
}
/**
* Initiate the class.
*/
HFE_WPML_Compatibility::instance();
PK ���\��$ $ "