/home/websdxuk/merchantkeysonline.com/wp-content/plugins/royal-elementor-addons/plugin.php
<?php
namespace WprAddons;

use Elementor\Utils;
use Elementor\Controls_Manager;
use WprAddons\Includes\Controls\WprAjaxSelect2\WPR_Control_Ajax_Select2;
use WprAddons\Includes\Controls\WPR_Control_Animations;
use WprAddons\Includes\Controls\WPR_Control_Animations_Alt;
use WprAddons\Includes\Controls\WPR_Control_Button_Animations;
use WprAddons\Includes\Controls\WPR_Control_Arrow_Icons;
use WprAddons\Classes\Utilities;
use Elementor\Core\App\App;
use WP_REST_Response;

if ( ! defined( 'ABSPATH' ) ) {	exit; } // Exit if accessed directly

/**
 * Main class plugin
 */
class Plugin {

	/**
	 * @var Plugin
	 */
	private static $_instance;

	/**
	 * @var Manager
	 */
	private $_modules_manager;

	/**
	 * @var array
	 */
	private $_localize_settings = [];

	/**
	 * @return string
	 */
	public function get_version() {
		return WPR_ADDONS_VERSION;
	}

	/**
	 * Throw error on object clone
	 *
	 * The whole idea of the singleton design pattern is that there is a single
	 * object therefore, we don't want the object to be cloned.
	 *
	 * @since 1.0
	 * @return void
	 */
	public function __clone() {
		// Cloning instances of the class is forbidden
		_doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin huh?', 'wpr-addons' ), '1.0' );
	}

	/**
	 * Disable unserializing of the class
	 *
	 * @since 1.0
	 * @return void
	 */
	public function __wakeup() {
		// Unserializing instances of the class is forbidden
		_doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin huh?', 'wpr-addons' ), '1.0' );
	}

	/**
	 * @return Plugin
	 */
	public static function instance() {
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self();
		}

		return self::$_instance;
	}

	private function _includes() {
		// Modules Manager
		require WPR_ADDONS_PATH . 'includes/modules-manager.php';

		// Custom Controls
		require WPR_ADDONS_PATH . 'includes/controls/wpr-ajax-select2/wpr-control-ajax-select2.php';
		require WPR_ADDONS_PATH . 'includes/controls/wpr-ajax-select2/wpr-control-ajax-select2-api.php';
		require WPR_ADDONS_PATH . 'includes/controls/wpr-control-animations.php';
		require WPR_ADDONS_PATH . 'includes/controls/wpr-control-icons.php';

		// Templates Library
		require WPR_ADDONS_PATH . 'admin/includes/wpr-templates-library.php';

		// Post Likes
		require WPR_ADDONS_PATH . 'classes/modules/wpr-post-likes.php';

		// Ajax Search
		require WPR_ADDONS_PATH . 'classes/modules/wpr-ajax-search.php';

		// Instagram
		require WPR_ADDONS_PATH . 'classes/modules/wpr-load-more-instagram-posts.php';

		// Twitter
		require WPR_ADDONS_PATH . 'classes/modules/wpr-load-more-tweets.php';
		
		// Meta Keys
		require WPR_ADDONS_PATH . 'classes/wpr-custom-meta-keys.php';

		// Grid
		require WPR_ADDONS_PATH . 'classes/modules/wpr-grid-helpers.php';
		
		// Woo Grid
		require WPR_ADDONS_PATH . 'classes/modules/wpr-woo-grid-helpers.php';

		// Media Grid
		require WPR_ADDONS_PATH . 'classes/modules/wpr-filter-grid-media.php';

		// Particles
		if ( 'on' === get_option('wpr-particles', 'on') ) {//TODO: make this check automatic(loop through) for all extensions
			require WPR_ADDONS_PATH . 'extensions/wpr-particles.php';
		}

		// Parallax
		if ( 'on' === get_option('wpr-parallax-background', 'on') || 'on' === get_option('wpr-parallax-multi-layer', 'on') ) {
			require WPR_ADDONS_PATH . 'extensions/wpr-parallax.php';
		}

		// Sticky Header
		if ( 'on' === get_option('wpr-sticky-section', 'on') ) {
			require WPR_ADDONS_PATH . 'extensions/wpr-sticky-section.php';
		}

		// Custom CSS
		if ( 'on' === get_option('wpr-custom-css', 'on') ) {
			require WPR_ADDONS_PATH . 'extensions/wpr-custom-css.php';
		}

		// Mega Menu
		require WPR_ADDONS_PATH . 'admin/mega-menu.php';


		// Form Builder
		// TODO:: ommit if form builder turned off if possible
		require WPR_ADDONS_PATH . 'classes/modules/wpr-form-handlers.php';
		
		// Admin Files
		if ( is_admin() ) {
			// Plugin Options
			require WPR_ADDONS_PATH . 'admin/plugin-options.php';

			// Templates Kit
			require WPR_ADDONS_PATH . 'admin/templates-kit.php';

			// Theme Builder
			require WPR_ADDONS_PATH . 'admin/theme-builder.php';

			// Premade Blocks
			require WPR_ADDONS_PATH . 'admin/premade-blocks.php';

			// Theme Builder
			require WPR_ADDONS_PATH . 'admin/popups.php';

			// Secondary Image
			require WPR_ADDONS_PATH . 'admin/metabox/wpr-secondary-image.php';

			// Dropdown Category Filter for Wpr Templates
			require WPR_ADDONS_PATH . 'admin/includes/wpr-templates-category-filter.php';

			// Editor Hooks
			require WPR_ADDONS_PATH . 'admin/includes/wpr-editor-hooks.php';

			// Hide Theme Notice
			// TODO: Remove this and fix with Transients
			add_action( 'admin_enqueue_scripts', [ $this, 'hide_theme_notice' ] );
		}

		if ( class_exists('WooCommerce') ) {
			 if ( 'on' === get_option('wpr_override_woo_templates', 'on') ) {
				 require WPR_ADDONS_PATH . 'includes/woocommerce/woocommerce-config.php';
			 }

			// Add Remove From Wishlist
			require WPR_ADDONS_PATH . 'classes/woocommerce/wpr-add-remove-from-wishlist.php';

			// Add Remove From Compare
			require WPR_ADDONS_PATH . 'classes/woocommerce/wpr-add-remove-from-compare.php';

			// Update Mini Wishlist
			require WPR_ADDONS_PATH . 'classes/woocommerce/wpr-update-mini-wishlist.php';

			// Compare Popup Action
			require WPR_ADDONS_PATH . 'classes/woocommerce/wpr-compare-popup-action.php';

			// Add Remove From Compare
			require WPR_ADDONS_PATH . 'classes/woocommerce/wpr-update-mini-compare.php';

			// Count Wishlist Items
			require WPR_ADDONS_PATH . 'classes/woocommerce/wpr-count-wishlist-compare-items.php';
			require WPR_ADDONS_PATH . 'classes/woocommerce/wpr-check-product-in-wc.php';
		}
	}

	public function autoload( $class ) {
		if ( 0 !== strpos( $class, __NAMESPACE__ ) ) {
			return;
		}

		$filename = strtolower(
			preg_replace(
				[ '/^' . __NAMESPACE__ . '\\\/', '/([a-z])([A-Z])/', '/_/', '/\\\/' ],
				[ '', '$1-$2', '-', DIRECTORY_SEPARATOR ],
				$class
			)
		);
		$filename = WPR_ADDONS_PATH . $filename . '.php';

		if ( is_readable( $filename ) ) {
			include( $filename );
		}
	}

	public function get_localize_settings() {
		return $this->_localize_settings;
	}

	public function add_localize_settings( $setting_key, $setting_value = null ) {
		if ( is_array( $setting_key ) ) {
			$this->_localize_settings = array_replace_recursive( $this->_localize_settings, $setting_key );

			return;
		}

		if ( ! is_array( $setting_value ) || ! isset( $this->_localize_settings[ $setting_key ] ) || ! is_array( $this->_localize_settings[ $setting_key ] ) ) {
			$this->_localize_settings[ $setting_key ] = $setting_value;

			return;
		}

		$this->_localize_settings[ $setting_key ] = array_replace_recursive( $this->_localize_settings[ $setting_key ], $setting_value );
	}

	public function script_suffix() {
		// $dir = is_rtl() ? '-rtl' : '';
		return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
	}

	public function register_ajax_hooks() {
        add_action( 'wp_ajax_mailchimp_subscribe', [new Utilities, 'ajax_mailchimp_subscribe'] );
        add_action( 'wp_ajax_nopriv_mailchimp_subscribe', [new Utilities, 'ajax_mailchimp_subscribe'] );
	}

	public function mega_menu_ajax_loading() {
		$elementor = \Elementor\Plugin::instance();
		$mega_id = get_post_meta( $_GET['item_id'], 'wpr-mega-menu-item', true);
		$type = get_post_meta(get_the_ID(), '_wpr_template_type', true) || get_post_meta($mega_id, '_elementor_template_type', true);
		$has_css = 'internal' === get_option( 'elementor_css_print_method' ) || '' !== $type;
		
		$content = $elementor->frontend->get_builder_content_for_display($mega_id, $has_css);

		wp_send_json( $content );
	}

	public function register_megamenu_route() {
		add_action( 'rest_api_init', function() {
			register_rest_route(
				'wpraddons/v1',
				'/wprmegamenu/',
				[
					'methods' => 'GET',
					'callback' =>  [$this, 'mega_menu_ajax_loading'],
					'permission_callback' => '__return_true'
				]
			);
		} );
	}

	public function register_custom_controls() {

		$controls_manager = \Elementor\Plugin::$instance->controls_manager;
		$controls_manager->register( new WPR_Control_Ajax_Select2() );
		$controls_manager->register( new WPR_Control_Animations() );
		$controls_manager->register( new WPR_Control_Animations_Alt() );
		$controls_manager->register( new WPR_Control_Button_Animations() );
		$controls_manager->register( new WPR_Control_Arrow_Icons() );

	}

	public function register_elementor_document_type( $documents_manager ) {
		// Theme Builder
		require WPR_ADDONS_PATH . 'modules/theme-builder/wpr-theme-builder.php';
		$documents_manager->register_document_type( 'wpr-theme-builder', 'Wpr_Theme_Builder' );

		// Popups
		require WPR_ADDONS_PATH . 'modules/popup/wpr-popup.php';

        if ( defined('WPR_ADDONS_PRO_VERSION') && wpr_fs()->can_use_premium_code() ) {
        	require WPR_ADDONS_PRO_PATH . 'modules/popup-pro/wpr-popup-pro.php';
        	$documents_manager->register_document_type( 'wpr-popups', 'Wpr_Popup_Pro' );
        } else {
        	$documents_manager->register_document_type( 'wpr-popups', 'Wpr_Popup' );
        }
	}

	public function enqueue_styles() {

		wp_register_style(
			'wpr-animations-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/wpr-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_register_style(
			'wpr-link-animations-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/wpr-link-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_register_style(
			'wpr-loading-animations-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/loading-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_register_style(
			'wpr-button-animations-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/button-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		// GOGA - enqueue instead of register (because of animations)
		wp_enqueue_style(
			'wpr-text-animations-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/text-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_register_style(
			'wpr-lightgallery-css',
			WPR_ADDONS_URL . 'assets/css/lib/lightgallery/lightgallery'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		// Posts Timeline
		wp_register_style( 
			'wpr-aos-css', 
			WPR_ADDONS_URL  . 'assets/css/lib/aos/aos.min.css',
			[]
		);

		wp_register_style(
			'wpr-flipster-css',
			WPR_ADDONS_URL . 'assets/css/lib/flipster/jquery.flipster.min.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_register_style(
			'wpr-date-picker-css',
			WPR_ADDONS_URL . 'assets/css/lib/air-datepicker/air-datepicker.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_enqueue_style(
			'wpr-addons-css',
			WPR_ADDONS_URL . 'assets/css/frontend'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

    	// Load FontAwesome - TODO: Check if necessary (maybe elementor is already loading this)
    	wp_enqueue_style(
			'font-awesome-5-all',
			ELEMENTOR_ASSETS_URL . 'lib/font-awesome/css/all'. $this->script_suffix() .'.css',
			false,
			Plugin::instance()->get_version()
		);

    	if ( \Elementor\Plugin::$instance->preview->is_preview_mode() ) {
			wp_enqueue_style(
				'wpr-addons-library-frontend-css',
				WPR_ADDONS_URL . 'assets/css/admin/library-frontend'. $this->script_suffix() .'.css',
				[],
				Plugin::instance()->get_version()
			);
		}
	}

	public function enqueue_editor_styles() {

		wp_enqueue_style(
			'wpr-animations-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/wpr-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_enqueue_style(
			'wpr-animations-link-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/wpr-link-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_enqueue_style(
			'wpr-loading-animations-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/loading-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_enqueue_style(
			'wpr-button-animations-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/button-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		wp_enqueue_style(
			'wpr-text-animations-css',
			WPR_ADDONS_URL . 'assets/css/lib/animations/text-animations'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);
		
		wp_enqueue_style( 
			'wpr-aos-css', 
			WPR_ADDONS_URL  . 'assets/css/lib/aos/aos.min.css',
			[]
		);

		wp_enqueue_style(
			'wpr-flipster-css',
			WPR_ADDONS_URL . 'assets/css/lib/flipster/jquery.flipster.min.css',
			[],
			Plugin::instance()->get_version()
		);
	}
	
	public function wpr_some_init_actions() {
		load_plugin_textdomain('wpr-addons', false, dirname(plugin_basename(__FILE__)) . '/languages/');
		
		if ( get_option('wpr_hide_banners') !== 'on' ) {
			// Pro Features Notice
			require WPR_ADDONS_PATH . 'admin/notices/pro-features-notice.php';

			// Plugin Update Notice
			require WPR_ADDONS_PATH . 'admin/notices/plugin-update-notice.php';
			
			// Plugin Sale Notice
			require WPR_ADDONS_PATH . 'admin/notices/plugin-sale-notice.php';
			
			// Rating Notice 
			require WPR_ADDONS_PATH . 'admin/notices/rating-notice.php';
		}

		// if ( defined('REST_REQUEST') && REST_REQUEST ) {
		// 	return;
		// }

		// if ( ! isset( $_COOKIE['wpr_guest_token'] ) && !headers_sent() ) {
		// 	// Generate a unique token and store it in a cookie
		// 	$guest_id = bin2hex(random_bytes(32)); // Secure random string as guest "session"
		// 	$secure = ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] === 'on' );
		// 	setcookie( 'wpr_guest_token', $guest_id, time() + 3600, '/', '', $secure, true ); // 1 hour expiration
		// 	$_COOKIE['wpr_guest_token'] = $guest_id; // Ensure it's immediately available in PHP
		// }
	}

	public function wpr_generate_custom_token() {
		if ( is_user_logged_in() ) {
			// For logged-in users, use their user ID to store a token
			$user_id = get_current_user_id();
			$token = bin2hex(\random_bytes(32)); // Secure token generation
			set_transient( 'wpr_custom_token_' . $user_id, $token, HOUR_IN_SECONDS ); // Store token for 1 hour
			return $token;
		} else {
			// For non-logged-in users, check if the guest token cookie exists
			if ( isset( $_COOKIE['wpr_guest_token'] ) ) {
				$guest_id = sanitize_text_field( $_COOKIE['wpr_guest_token'] );
			} else {
				// If somehow the cookie isn't set, handle appropriately
				return null;
			}
	
			// Check if a token already exists for this guest
			$existing_token = get_transient( 'wpr_custom_guest_token_' . $guest_id );
			if ( $existing_token ) {
				return $existing_token;
			}
	
			// Only create new token if one doesn't exist
			$token = bin2hex(\random_bytes(32)); // Secure token generation
			set_transient( 'wpr_custom_guest_token_' . $guest_id, $token, HOUR_IN_SECONDS ); // Store token for 1 hour
			
			// Clean up old guest tokens periodically (1% chance)
			if ( rand(1, 100) === 1 ) {
				$this->cleanup_guest_tokens();
			}
			
			return $token;
		}
	}
	
	private function cleanup_guest_tokens() {
		global $wpdb;
		$wpdb->query(
			"DELETE FROM {$wpdb->options} 
			WHERE option_name LIKE '_transient_wpr_custom_guest_token_%'
			AND option_value = ''
			LIMIT 100"
		);
	}

	public function hide_theme_notice() {
		wp_enqueue_style( 'hide-theme-notice', WPR_ADDONS_URL .'assets/css/admin/wporg-theme-notice.css', [] );

		wp_enqueue_script(
			'wpr-plugin-notice-js',
			WPR_ADDONS_URL . 'assets/js/admin/plugin-update-notice.js',
			[
				'jquery'
			]
		);

		// if ( ! wp_script_is( 'wpr-wrong-update-js', 'enqueued' ) ) {
		// 	wp_enqueue_script(
		// 		'wpr-wrong-update-js',
		// 		WPR_ADDONS_URL . 'assets/js/admin/wrong-update.js',
		// 		[
		// 			'jquery'
		// 		]
		// 	);
		// }	

		wp_localize_script(
			'wpr-plugin-notice-js',
			'WprPluginNotice',
			[
				'ajaxurl' => admin_url( 'admin-ajax.php' ),
				'nonce' => wp_create_nonce( 'wpr-plugin-notice-js' ),
			]
		);
	}

	public function enqueue_scripts() {

		// Register DOMPurify
		wp_enqueue_script(
			'dompurify',
			WPR_ADDONS_URL . 'assets/js/lib/dompurify/dompurify.min.js',
			['jquery', 'elementor-frontend'],
			'3.0.6',
		);

		wp_enqueue_script(
			'wpr-addons-js',
			WPR_ADDONS_URL . 'assets/js/frontend'. $this->script_suffix() .'.js',
			[
				'jquery',
				'elementor-frontend',
				'dompurify'
			],
			Plugin::instance()->get_version(),
			true
		);

		wp_enqueue_script(
			'wpr-modal-popups-js',
			WPR_ADDONS_URL . 'assets/js/modal-popups'. $this->script_suffix() .'.js',
			[
				'jquery',
			],
			Plugin::instance()->get_version(),
			true
		);

		// $custom_token = $this->wpr_generate_custom_token();

		wp_localize_script(
			'wpr-addons-js',
			'WprConfig', // This is used in the js file to group all of your scripts together
			[
				'ajaxurl' => admin_url( 'admin-ajax.php' ),
				'resturl' => get_rest_url() . 'wpraddons/v1',
				'nonce' => wp_create_nonce( 'wpr-addons-js' ),
				'addedToCartText' => esc_html__('was added to cart', 'wpr-addons'),
				'viewCart' => esc_html__('View Cart', 'wpr-addons'),
				'comparePageID' => get_option('wpr_compare_page'),
				'comparePageURL' => get_permalink(get_option('wpr_compare_page')),
				'wishlistPageID' => get_option('wpr_wishlist_page'),
				'wishlistPageURL' => get_permalink(get_option('wpr_wishlist_page')),
				'chooseQuantityText' => esc_html__('Please select the required number of items.', 'wpr-addons'),
				'site_key' => get_option('wpr_recaptcha_v3_site_key'),
				'is_admin' => current_user_can('manage_options'),
				'input_empty' => esc_html__('Please fill out this field', 'wpr-addons'),
				'select_empty' => esc_html__('Nothing selected', 'wpr-addons'),
				'file_empty' => esc_html__('Please upload a file', 'wpr-addons'),
				'recaptcha_error' => esc_html__('Recaptcha Error', 'wpr-addons'),
				'woo_shop_ppp' => get_option('wpr_woo_shop_ppp', 9),
				'woo_shop_cat_ppp' => get_option('wpr_woo_shop_cat_ppp', 9),
				'woo_shop_tag_ppp' => get_option('wpr_woo_shop_tag_ppp', 9),
				'is_product_category' => function_exists('is_product_category') ? is_product_category() : false,
				'is_product_tag' => function_exists('is_product_tag') ? is_product_tag() : false,
				// 'token' => $custom_token
			]
		);
	}	

	public function register_scripts() {

		wp_register_script(
			'wpr-infinite-scroll',
			WPR_ADDONS_URL . 'assets/js/lib/infinite-scroll/infinite-scroll.min.js',
			[
				'jquery',
			],
			'3.0.5',
			true
		);
		
		wp_register_script(
			'imagesloaded',
			WPR_ADDONS_URL . 'assets/js/lib/isotope/imagesloaded'. $this->script_suffix() .'.js',
			[
				'jquery'
			],
			'5.0.0',
			true
		);

		wp_register_script(
			'wpr-isotope',
			WPR_ADDONS_URL . 'assets/js/lib/isotope/isotope'. $this->script_suffix() .'.js',
			[
				'jquery',
				'imagesloaded'
			],
			'3.0.8',
			true
		);

		wp_register_script(
			'wpr-date-picker-js',
			WPR_ADDONS_URL . 'assets/js/lib/air-datepicker/air-datepicker.js',
			[
				'jquery',
			],
			'',
			true
		);

		wp_register_script(
			'wpr-slick',
			WPR_ADDONS_URL . 'assets/js/lib/slick/slick'. $this->script_suffix() .'.js',
			[
				'jquery',
			],
			'1.8.1',
			true
		);

		wp_register_script(
			'wpr-lightgallery',
			WPR_ADDONS_URL . 'assets/js/lib/lightgallery/lightgallery'. $this->script_suffix() .'.js',
			[
				'jquery',
			],
			'1.6.12',
			true
		);

		wp_register_script(
			'wpr-marquee',
			WPR_ADDONS_URL . 'assets/js/lib/marquee/marquee'. $this->script_suffix() .'.js',
			[
				'jquery',
			],
			'1.0',
			true
		);

		wp_register_script(
			'wpr-google-maps',
			'https://maps.googleapis.com/maps/api/js?key='. esc_attr(get_option('wpr_google_map_api_key')) . '&language='. esc_attr(get_option('wpr_google_map_language')),
			[],
			'',
			true
		);

		wp_register_script(
			'wpr-google-maps-clusters',
			WPR_ADDONS_URL . 'assets/js/lib/gmap/markerclusterer'. $this->script_suffix() .'.js',
			[],
			'1.0.3',
			true
		);

		wp_register_script(
			'jquery-event-move',
			WPR_ADDONS_URL . 'assets/js/lib/jquery-event-move/jquery.event.move'. $this->script_suffix() .'.js',
			[],
			'2.0',
			true
		);

		wp_register_script(
			'wpr-lottie-animations',
			WPR_ADDONS_URL . 'assets/js/lib/lottie/lottie.min.js',
			[],
			'5.8.0',
			true
		);

		wp_register_script( 
			'wpr-table-to-excel-js',
			 WPR_ADDONS_URL  . 'assets/js/lib/tableToExcel/tableToExcel.js',
			 [],
			 null, 
			 true 
		);
		
		wp_register_script(
			'wpr-aos-js',
			 WPR_ADDONS_URL  . 'assets/js/lib/aos/aos.min.js',
			 [], 
			 null, 
			 true
		);
		
		wp_register_script(
			'wpr-charts',
			WPR_ADDONS_URL . 'assets/js/lib/charts/charts.min.js',
			[],
			'3.7.0',
			true
		);

		wp_register_script(
			'wpr-flipster',
			WPR_ADDONS_URL . 'assets/js/lib/flipster/jquery.flipster.min.js',
			[],
			'2.0',
			true
		);

		wp_register_script( 
			'wpr-perfect-scroll-js',
			 WPR_ADDONS_URL .'assets/js/lib/perfect-scrollbar/perfect-scrollbar.min.js', 
			 [ 'jquery' ], 
			 '0.4.9' 
		);
	}

	public function enqueue_panel_scripts() {

		wp_enqueue_script(
			'wpr-addons-editor-js',
			WPR_ADDONS_URL . 'assets/js/admin/editor'. $this->script_suffix() .'.js',
			[ 'jquery', 'wp-i18n' ],
			Plugin::instance()->get_version(),
			true
		);

		$args = ['nonce' => wp_create_nonce( 'wpr-addons-editor-js' ), 'adminURL' => admin_url(), 'isWooCommerceActive' => class_exists('WooCommerce') ? true : false];

		$args = array_merge($args, Utilities::get_registered_modules());

		wp_localize_script(
			'wpr-addons-editor-js',
			'registered_modules',
			$args
		);
	}

	public function enqueue_inner_panel_scripts() {

		wp_enqueue_script(
			'wpr-macy-js',
			WPR_ADDONS_URL . 'assets/js/lib/macy/macy.js',
			[],
			'3.0.6',
			true
		);

		wp_enqueue_script(
			'wpr-addons-library-frontend-js',
			WPR_ADDONS_URL . 'assets/js/admin/library-frontend'. $this->script_suffix() .'.js',
			[ 'jquery', 'wpr-macy-js' ],
			Plugin::instance()->get_version(),
			true
		);

		wp_localize_script(
			'wpr-addons-library-frontend-js',
			'white_label',
			[
				'logo_url' => !empty(get_option('wpr_wl_plugin_logo')) ? esc_url(wp_get_attachment_image_src(get_option('wpr_wl_plugin_logo'), 'full')[0]) : WPR_ADDONS_ASSETS_URL .'img/logo-40x40.png'
			]
		);

		wp_localize_script(
			'wpr-addons-library-frontend-js',
			'WprLibFrontLoc',
			[
				'nonce' => wp_create_nonce('wpr-addons-library-frontend-js')
			]
		);

		wp_enqueue_script(
			'wpr-addons-library-editor-js',
			WPR_ADDONS_URL . 'assets/js/admin/library-editor'. $this->script_suffix() .'.js',
			[ 'jquery' ],
			Plugin::instance()->get_version(),
			true
		);
	}

	public function enqueue_panel_styles() {
		wp_enqueue_style(
			'wpr-addons-library-editor-css',
			WPR_ADDONS_URL . 'assets/css/admin/editor'. $this->script_suffix() .'.css',
			[],
			Plugin::instance()->get_version()
		);

		$custom_css = "
			.wpr-pro-notice {
				background: #404349 !important;
				border-color: #323232 !important;
			}
			.elementor-control select option[value*=pro-] {
				background: #60646e !important;
			}
			.elementor-panel .wpr-icon:after {
				box-shadow: 0 0 2px 2px #6985ee !important;
			}
			.wpr-pro-notice > span {
				color: #fff !important;
				font-weight: bold;
			}
		";
		
		$ui_theme = isset(get_user_meta(get_current_user_id(), 'elementor_preferences')[0]['ui_theme']) ? get_user_meta(get_current_user_id(), 'elementor_preferences')[0]['ui_theme'] : '';
		
		if ( $ui_theme && $ui_theme === 'dark' ) {
			wp_add_inline_style( 'elementor-editor-dark-mode', $custom_css );
		}
	}

	// Lightbox Styles
	public function lightbox_styles() {
	    echo '<style id="wpr_lightbox_styles">
				.lg-backdrop {
					background-color: '. esc_html(get_option('wpr_lb_bg_color','rgba(0,0,0,0.6)')) .' !important;
				}
				.lg-toolbar,
				.lg-dropdown {
					background-color: '. esc_html(get_option('wpr_lb_toolbar_color','rgba(0,0,0,0.8)')) .' !important;
				}
				.lg-dropdown:after {
					border-bottom-color: '. esc_html(get_option('wpr_lb_toolbar_color','rgba(0,0,0,0.8)')) .' !important;
				}
				.lg-sub-html {
					background-color: '. esc_html(get_option('wpr_lb_caption_color','rgba(0,0,0,0.8)')) .' !important;
				}
				.lg-thumb-outer,
				.lg-progress-bar {
					background-color: '. esc_html(get_option('wpr_lb_gallery_color','#444444')) .' !important;
				}
				.lg-progress {
					background-color: '. esc_html(get_option('wpr_lb_pb_color','#a90707')) .' !important;
				}
				.lg-icon {
					color: '. esc_html(get_option('wpr_lb_ui_color','#efefef')) .' !important;
					font-size: '. esc_html(get_option('wpr_lb_icon_size',20)) .'px !important;
				}
				.lg-icon.lg-toogle-thumb {
					font-size: '. esc_html((get_option('wpr_lb_icon_size',20) + 4)) .'px !important;
				}
				.lg-icon:hover,
				.lg-dropdown-text:hover {
					color: '. esc_html(get_option('wpr_lb_ui_hr_color','#ffffff')) .' !important;
				}
				.lg-sub-html,
				.lg-dropdown-text {
					color: '. esc_html(get_option('wpr_lb_text_color','#efefef')) .' !important;
					font-size: '. esc_html(get_option('wpr_lb_text_size',14)) .'px !important;
				}
				#lg-counter {
					color: '. esc_html(get_option('wpr_lb_text_color','#efefef')) .' !important;
					font-size: '. esc_html(get_option('wpr_lb_text_size',14)) .'px !important;
				}
				.lg-prev,
				.lg-next {
					font-size: '. esc_html(get_option('wpr_lb_arrow_size',35)) .'px !important;
				}

				/* Defaults */
				.lg-icon {
				background-color: transparent !important;
				}

				#lg-counter {
				opacity: 0.9;
				}

				.lg-thumb-outer {
				padding: 0 10px;
				}

				.lg-thumb-item {
				border-radius: 0 !important;
				border: none !important;
				opacity: 0.5;
				}

				.lg-thumb-item.active {
					opacity: 1;
				}
	         </style>';
	}

	public function elementor_init() {
		$this->_modules_manager = new Manager();
	}

	public function register_widget_categories() {
		// Add element category in panel
		\Elementor\Plugin::instance()->elements_manager->add_category(
			'wpr-widgets',
			[
				'title' => Utilities::get_plugin_name(true),
				'icon' => 'font',
			]
		);

		// Add Woo element category in panel
		if ( Utilities::is_theme_builder_template() ) {
			\Elementor\Plugin::instance()->elements_manager->add_category(
				'wpr-theme-builder-widgets',
				[
					'title' => sprintf(esc_html__( '%s Theme Builder', 'wpr-addons' ), Utilities::get_plugin_name()),
					'icon' => 'font',
				]
			);
		}
		
		// Add Woocommerce Builder category in panel
		if ( Utilities::is_theme_builder_template() ) {
			\Elementor\Plugin::instance()->elements_manager->add_category(
				'wpr-woocommerce-builder-widgets',
				[
					'title' => sprintf(esc_html__( '%s Woocommerce Builder', 'wpr-addons' ), Utilities::get_plugin_name()),
					'icon' => 'font',
				]
			);
		}
		
		// Add Premium Widtgets category in panel
		\Elementor\Plugin::instance()->elements_manager->add_category(
			'wpr-premium-widgets',
			[
				'title' => sprintf(esc_html__( '%s Premium Widgets', 'wpr-addons' ), Utilities::get_plugin_name()),
				'icon' => 'font',
			]
		);
	}

    public function promote_premium_widgets($config) {

		// if ( is_plugin_active('elementor-pro/elementor-pro.php') || is_plugin_active('pro-elements/pro-elements.php') ) {
		// }
		$config['promotionWidgets'] = [];

		$category = Utilities::is_theme_builder_template() ? 'wpr-woocommerce-builder-widgets' : 'wpr-premium-widgets';

		if ( !defined('WPR_ADDONS_PRO_VERSION') || !wpr_fs()->can_use_premium_code() ) {
			$promotion_widgets = [
				[
					'name' => 'wpr-woo-category-grid',
					'title' => __('Woo Category Grid', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-gallery-grid',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-my-account',
					'title' => __('My Account', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-my-account',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-product-filters',
					'title' => __('Product Filters', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-filter',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-product-breadcrumbs',
					'title' => __('Product Breadcrumbs', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-product-breadcrumbs',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-breadcrumbs',
					'title' => __('Post Breadcrumbs', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-product-breadcrumbs',
					'categories' => '["'. $category .'"]',
				],
			];
			
			$config['promotionWidgets'] = array_merge( $config['promotionWidgets'], $promotion_widgets );
		}
		
		if ( !defined('WPR_ADDONS_PRO_VERSION') || !wpr_fs()->is_plan( 'expert' ) ) {
			$expert_widgets = [
				[
					'name' => 'wpr-category-grid',
					'title' => __('Category Grid', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-gallery-grid',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-wishlist-button',
					'title' => __('Wishlist Button', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-heart',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-mini-wishlist',
					'title' => __('Mini Wishlist', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-heart',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-wishlist',
					'title' => __('Wishlist Table', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-heart',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-compare-button',
					'title' => __('Compare Button', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-exchange', // GOGA - new icon needed for compare
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-mini-compare',
					'title' => __('Mini Compare', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-exchange',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-compare',
					'title' => __('Compare Table', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-exchange',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-custom-field',
					'title' => __('Custom Field', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-database',
					'categories' => '["'. $category .'"]',
				],
				[
					'name' => 'wpr-advanced-filters',
					'title' => __('Advanced Filters', 'wpr-addons'),
					'icon' => 'wpr-icon eicon-filter',
					'categories' => '["'. $category .'"]',
				],
			];

			$config['promotionWidgets'] = array_merge( $config['promotionWidgets'], $expert_widgets );
		}

        return $config;
    }

	protected function add_actions() {

		// User Cookie
		add_action( 'init', [$this, 'wpr_some_init_actions' ]);

		// Register Widgets
		add_action( 'elementor/init', [ $this, 'elementor_init' ] );

		// Register Categories
		add_action( 'elementor/elements/categories_registered', [ $this, 'register_widget_categories' ] );

		// Register Ajax Hooks
		$this->register_ajax_hooks();

		// Register Mega Menu Route
		$this->register_megamenu_route();

		// $this->register_compare_custom_routes();

		// Register Custom Controls
		add_action( 'elementor/controls/controls_registered', [ $this, 'register_custom_controls' ] );

		// Register Document Type
		add_action( 'elementor/documents/register', [ $this, 'register_elementor_document_type' ] );

		// Frontend CSS
		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_styles' ], 998 );

		// Editor CSS
		add_action( 'elementor/preview/enqueue_styles', [ $this, 'enqueue_editor_styles' ], 998 );

		// Register Scripts
		add_action( 'elementor/frontend/before_register_scripts', [ $this, 'register_scripts' ], 998 );

		// Frontend JS
		add_action( 'elementor/frontend/before_enqueue_scripts', [ $this, 'enqueue_scripts' ], 998 );

		// Editor CSS/JS
		add_action( 'elementor/editor/after_enqueue_styles', [ $this, 'enqueue_panel_styles' ], 988 );
		add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'enqueue_inner_panel_scripts' ], 988 );
		add_action( 'elementor/editor/after_enqueue_scripts', [ $this, 'enqueue_panel_scripts' ], 988 );

		// Lightbox Styles
		add_action( 'wp_head', [ $this, 'lightbox_styles' ], 988 );

		// Promote Premium Widgets
		if ( current_user_can('administrator') ) {
			add_filter('elementor/editor/localize_settings', [$this, 'promote_premium_widgets'], 999);
		}

		add_filter( 'pre_get_posts', [$this, 'wpr_custom_posts_per_page'] );
		add_filter('excerpt_more', [$this, 'wpr_custom_excerpt_more']);
		add_filter('excerpt_length', [$this, 'wpr_custom_excerpt_length']);
	}
	
	/*
	** Custom function to modify excerpt more text
	*/
	function wpr_custom_excerpt_more($more) { // TODO: check
		return ''; // Change to '...' or any other text if desired
	}

	/*
	** Custom function to modify excerpt more length
	*/
	function wpr_custom_excerpt_length($length) {
		return 999;
	}

	public function wpr_custom_posts_per_page( $query ) {
		if ( $query->is_main_query() && isset($query->query['post_type']) ) {
			if (is_admin() ) {
				if (\Elementor\Plugin::$instance->editor && !\Elementor\Plugin::$instance->editor->is_edit_mode()) {
					return;
				}
			}
			$query_post_type = $query->query['post_type'];
			if ( is_string($query_post_type) && is_post_type_archive($query_post_type) && get_option('wpr_cpt_ppp_'. $query_post_type ) ) {
				$query->set( 'posts_per_page', get_option('wpr_cpt_ppp_'. $query_post_type ) );
			}
		}
	
		return $query;
	}

	/**
	 * Plugin constructor.
	 */
	private function __construct() {
		spl_autoload_register( [ $this, 'autoload' ] );
		
		$this->_includes();
		$this->add_actions();
	}
	
}

if ( ! defined( 'WPR_ADDONS_TESTS' ) ) {
	// In tests we run the instance manually.
	Plugin::instance();
}
My Blog – My WordPress Blog

Navigating Your Journey, Relocating Your World

Elevate Your Move, Experience Seamless Relocations.

A leading innovator in orchestrating top-notch Moving Solutions and Ensuring Seamless Relocations across the USA.

Booked Your Movement

Goods Packing Service

Goods Unpacking Service

Moving Goods Service

Goods Unloading Service

Service

Choose Your Movement Service

Start From 10 USD/Hour

Complete Goods Packing Service for House

All aspects of your software assets including purchasing, deployment & maintenance.

Start From 15 USD/Hour

Complete Goods Unpacking Service for House

All aspects of your software assets including purchasing, deployment & maintenance.

Start From 100 USD/Month

Complete Storage Solution For Your Goods

All aspects of your software assets including purchasing, deployment & maintenance.

Start From 100 USD/Month

Complete Unloading Solution For Your Goods

All aspects of your software assets including purchasing, deployment & maintenance.

Get 10% Discount For Every First of Order. 

View All Our Service Here

WHY CHOOSE US

Explore Why Our Company is Preferable

At [Your Company Name], we pride ourselves on delivering exceptional value, unparalleled service, and innovative solutions tailored to meet your needs.

No Hidden Price

Free Unloading

Clean No Trash

Warehouse

Fast Truck

About Us

Swift Your Transitions With Unmatched Service

At [Your Company Name], we are more than just a business—we are a team of passionate professionals dedicated to delivering excellence. With [X] years of experience in [your industry], we’ve built a reputation for [key strengths, e.g., innovation, reliability, customer-centric solutions].

Thinking insights, verified driven research, and metrics data help you make the right decisions!

Achievments

Moving You Forward By Moving with Care

At [Your Company Name], we take pride in our milestones and the impact we’ve made. Our journey is marked by dedication, innovation, and a relentless pursuit of excellence. Here’s a glimpse of what we’ve accomplished:

Every achievement reflects our commitment to excellence and the trust our clients and partners place in us. We’re not just celebrating the past—we’re building an even brighter future.

0 +

Clients

0 +

Miles

0 +

Movers

Study Case

Learn Our Successfull Study Cases

Urban, Relocations

From City to Suburbs: A Smooth Urban Relocation

Corporate, Precision

Corporate Precision: Streamlining Office Moves

Senior, Transitions

Senior Transitions: Compassionate Moves for Aging Loved Onesz

Cross, Country

Cross-Country Adventure: A Transcontinental Move

Booked Form

Don't Let Your Back Hurt, Let Us Move Your Things!

Our easy-to-use booking form ensures a seamless experience, allowing you to choose your preferred date, time, and options without any hassle.

Why book with us?
✓ Instant Confirmation – Receive immediate booking details via email/SMS.
✓ Flexible Scheduling – Pick a slot that fits your schedule.
✓ 100% Secure – Your information is safe with us.

Booked Your Movement

Booked Your Movement