! $is_uae_pro_active, 'iconUrl' => HFE_URL . 'assets/images/settings/logo-white.svg', 'strings' => array( 'headerFooterBuilder' => __( 'Header Footer Builder', 'header-footer-elementor' ) ) )); wp_enqueue_script( 'hfe-elementor' ); } /** * Constructor * * @return void */ private function __construct() { add_action( 'init', [ $this, 'header_footer_posttype' ] ); if ( is_admin() && current_user_can( 'manage_options' ) ) { add_action( 'admin_menu', [ $this, 'register_admin_menu' ], 50 ); } $is_elementor_callable = ( defined( 'ELEMENTOR_VERSION' ) && is_callable( 'Elementor\Plugin::instance' ) ) ? true : false; if ( $is_elementor_callable ) { self::$elementor_instance = Elementor\Plugin::instance(); } add_action( 'add_meta_boxes', [ $this, 'ehf_register_metabox' ] ); add_action( 'save_post', [ $this, 'ehf_save_meta' ] ); add_action( 'admin_notices', [ $this, 'location_notice' ] ); add_action( 'template_redirect', [ $this, 'block_template_frontend' ] ); add_filter( 'single_template', [ $this, 'load_canvas_template' ] ); add_filter( 'manage_elementor-hf_posts_columns', [ $this, 'set_shortcode_columns' ] ); add_action( 'manage_elementor-hf_posts_custom_column', [ $this, 'render_shortcode_column' ], 10, 2 ); if ( defined( 'ELEMENTOR_PRO_VERSION' ) && ELEMENTOR_PRO_VERSION > 2.8 ) { add_action( 'elementor/editor/footer', [ $this, 'register_hfe_epro_script' ], 99 ); } add_action( 'admin_notices', [ $this, 'hide_admin_notices' ], 1 ); add_action( 'all_admin_notices', [ $this, 'hide_admin_notices' ], 1 ); if ( is_admin() ) { add_action( 'manage_elementor-hf_posts_custom_column', [ $this, 'column_content' ], 10, 2 ); add_filter( 'manage_elementor-hf_posts_columns', [ $this, 'column_headings' ] ); require_once HFE_DIR . 'admin/class-hfe-addons-actions.php'; } add_action( 'elementor/editor/footer', [ $this, 'print_permalink_clear_notice' ] ); add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'enqueue_permalink_clear_notice_js' ] ); add_action( 'elementor/editor/before_enqueue_styles', [ $this, 'enqueue_permalink_clear_notice_css' ] ); // Hook into Elementor's editor styles add_action('elementor/editor/before_enqueue_scripts', [$this, 'enqueue_editor_scripts']); if ( 'yes' === get_option( 'uae_usage_optin', false ) ) { add_action( 'init', array( $this, 'hfe_schedule_usage_cron' ) ); add_action( 'hfe_widgets_usage_cron', array( $this, 'hfe_check_widgets_data_usage' ) ); } } /** * Enqueuing Promotion widget scripts. */ public function enqueue_editor_scripts() { wp_enqueue_script( 'uae-pro-promotion', HFE_URL . 'build/promotion-widget.js', [ 'jquery', 'wp-element', 'wp-dom-ready' ], HFE_VER, true ); } /** * Schedule the daily cron event for widget usage data collection. * * @since 2.8.5 * @return void */ public function hfe_schedule_usage_cron() { if ( ! wp_next_scheduled( 'hfe_widgets_usage_cron' ) ) { wp_schedule_event( time(), 'daily', 'hfe_widgets_usage_cron' ); } } /** * Collect widgets usage data via WP-Cron. * * Runs in a background cron context instead of on every page load, * preventing timeouts on content-heavy sites. * * @since 2.8.5 */ public function hfe_check_widgets_data_usage() { $transient_key = 'uae_widgets_usage_data'; $widgets_usage = get_transient( $transient_key ); $needs_widget_refresh = false === $widgets_usage || false === get_option( 'uae_widgets_usage_data_option' ); $needs_kpi_init = false === get_option( 'hfe_kpi_daily_snapshots', false ); if ( $needs_widget_refresh || $needs_kpi_init ) { $filtered_widgets_usage = HFE_Helper::get_used_widget(); set_transient( $transient_key, $filtered_widgets_usage, DAY_IN_SECONDS ); update_option( 'uae_widgets_usage_data_option', $filtered_widgets_usage ); $this->save_kpi_snapshot( $filtered_widgets_usage ); } } /** * Save a daily KPI snapshot alongside widget usage refresh. * * Computes aggregated metrics from widget usage and template data, * stores them keyed by today's date, and keeps only the last 3 days. * * @since 2.8.4 * @param array $widgets_usage Filtered widget usage data. * @return void */ private function save_kpi_snapshot( $widgets_usage ) { $today = current_time( 'Y-m-d' ); // Total published templates. $total_templates = $this->get_total_template_count(); // Widget metrics. $total_hfe_widget_instances = 0; if ( is_array( $widgets_usage ) ) { foreach ( $widgets_usage as $slug => $count ) { $total_hfe_widget_instances += (int) $count; } } $snapshot = [ 'numeric_values' => [ 'total_templates' => $total_templates, 'total_hfe_widget_instances' => $total_hfe_widget_instances, ], ]; // Read existing snapshots, add today's, keep last 3 days. $snapshots = get_option( 'hfe_kpi_daily_snapshots', [] ); if ( ! is_array( $snapshots ) ) { $snapshots = []; } $snapshots[ $today ] = $snapshot; krsort( $snapshots ); $snapshots = array_slice( $snapshots, 0, 3, true ); update_option( 'hfe_kpi_daily_snapshots', $snapshots, false ); } /** * Get count of published HFE templates. * * @since 2.8.4 * @return int Total published template count. */ private function get_total_template_count() { $posts = get_posts( [ 'post_type' => 'elementor-hf', 'post_status' => 'publish', 'numberposts' => -1, 'fields' => 'ids', ] ); return count( $posts ); } /** * Enqueue notice style based on option and posttype. * * @since 2.2.1 */ public function enqueue_permalink_clear_notice_css() { if ( get_user_meta( get_current_user_id(), 'hfe_permalink_notice_option', true ) === 'notice-dismissed' ) { return; } if(isset(self::$elementor_instance)){ $current_post_type = get_post_type( self::$elementor_instance->editor->get_post_id() ); if ( $current_post_type !== 'elementor-hf' ) { return; } } wp_enqueue_style( 'hfe-permalink-clear-notice', HFE_URL . 'inc/widgets-css/permalink-clear-notice.css', [], HFE_VER ); } /** * Enqueue and localize notice script based on option and posttype. * * @since 2.2.1 */ public function enqueue_permalink_clear_notice_js() { if ( get_user_meta( get_current_user_id(), 'hfe_permalink_notice_option', true ) === 'notice-dismissed' ) { return; } if(isset(self::$elementor_instance)){ $current_post_type = get_post_type( self::$elementor_instance->editor->get_post_id() ); if ( $current_post_type !== 'elementor-hf' ) { return; } } wp_enqueue_script( 'hfe-permalink-clear-notice', HFE_URL . 'inc/js/permalink-clear-notice.js', [ 'jquery' ], HFE_VER ); wp_localize_script( 'hfe-permalink-clear-notice', 'hfePermalinkClearNotice', [ 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'hfe_permalink_clear_notice_nonce' ), ] ); } /** * Creating notice for permaliink reset in Elementor Editor. * * @since 2.2.1 */ public function print_permalink_clear_notice() { if ( is_admin() ) { if ( get_user_meta( get_current_user_id(), 'hfe_permalink_notice_option', true ) === 'notice-dismissed' ) { return; } if(isset(self::$elementor_instance)){ $current_post_type = get_post_type( self::$elementor_instance->editor->get_post_id() ); if ( $current_post_type !== 'elementor-hf' ) { return; } } ?> id, $pages_to_hide_notices ) || 'toplevel_page_hfe' === $screen->id ) { remove_all_actions( 'admin_notices' ); remove_all_actions( 'all_admin_notices' ); } } /** * Script for Elementor Pro full site editing support. * * @since 1.4.0 * * @return void */ public function register_hfe_epro_script() { $ids_array = [ [ 'id' => get_hfe_header_id(), 'value' => 'Header', ], [ 'id' => get_hfe_footer_id(), 'value' => 'Footer', ], [ 'id' => hfe_get_before_footer_id(), 'value' => 'Before Footer', ], ]; wp_enqueue_script( 'hfe-elementor-pro-compatibility', HFE_URL . 'inc/js/hfe-elementor-pro-compatibility.js', [ 'jquery' ], HFE_VER, true ); wp_localize_script( 'hfe-elementor-pro-compatibility', 'hfe_admin', [ 'ids_array' => wp_json_encode( $ids_array ), ] ); } /** * Adds or removes list table column headings. * * @param array $columns Array of columns. * @return array */ public function column_headings( $columns ) { unset( $columns['date'] ); $columns['elementor_hf_display_rules'] = __( 'Display Rules', 'header-footer-elementor' ); $columns['date'] = __( 'Date', 'header-footer-elementor' ); return $columns; } /** * Adds the custom list table column content. * * @since 1.2.0 * @param array $column Name of column. * @param int $post_id Post id. * @return void */ public function column_content( $column, $post_id ) { if ( 'elementor_hf_display_rules' === $column ) { $locations = get_post_meta( $post_id, 'ehf_target_include_locations', true ); if ( ! empty( $locations ) ) { echo '
'; echo 'Display: '; $this->column_display_location_rules( $locations ); echo '
'; } $locations = get_post_meta( $post_id, 'ehf_target_exclude_locations', true ); if ( ! empty( $locations ) ) { echo '
'; echo 'Exclusion: '; $this->column_display_location_rules( $locations ); echo '
'; } $users = get_post_meta( $post_id, 'ehf_target_user_roles', true ); if ( isset( $users ) && is_array( $users ) ) { if ( isset( $users[0] ) && ! empty( $users[0] ) ) { $user_label = []; foreach ( $users as $user ) { $user_label[] = Astra_Target_Rules_Fields::get_user_by_key( $user ); } echo '
'; echo 'Users: '; echo esc_html( join( ', ', $user_label ) ); echo '
'; } } } } /** * Get Markup of Location rules for Display rule column. * * @param array $locations Array of locations. * @return void */ public function column_display_location_rules( $locations ) { $location_label = []; if ( is_array( $locations ) && is_array( $locations['rule'] ) && isset( $locations['rule'] ) ) { $index = array_search( 'specifics', $locations['rule'] ); if ( false !== $index && ! empty( $index ) ) { unset( $locations['rule'][ $index ] ); } } if ( isset( $locations['rule'] ) && is_array( $locations['rule'] ) ) { foreach ( $locations['rule'] as $location ) { $location_label[] = Astra_Target_Rules_Fields::get_location_by_key( $location ); } } if ( isset( $locations['specific'] ) && is_array( $locations['specific'] ) ) { foreach ( $locations['specific'] as $location ) { $location_label[] = Astra_Target_Rules_Fields::get_location_by_key( $location ); } } echo esc_html( join( ', ', $location_label ) ); } /** * Register Post type for Elementor Header & Footer Builder templates * * @return void */ public function header_footer_posttype() { $setting_location = $this->is_pro_active() ? 'uaepro' : 'hfe'; $labels = [ 'name' => esc_html__( 'Elementor Header & Footer Builder', 'header-footer-elementor' ), 'singular_name' => esc_html__( 'Elementor Header & Footer Builder', 'header-footer-elementor' ), 'menu_name' => esc_html__( 'Elementor Header & Footer Builder', 'header-footer-elementor' ), 'name_admin_bar' => esc_html__( 'Elementor Header & Footer Builder', 'header-footer-elementor' ), 'add_new' => esc_html__( 'Add New', 'header-footer-elementor' ), 'add_new_item' => esc_html__( 'Add New', 'header-footer-elementor' ), 'new_item' => esc_html__( 'New Template', 'header-footer-elementor' ), 'edit_item' => esc_html__( 'Edit Template', 'header-footer-elementor' ), 'view_item' => esc_html__( 'View Template', 'header-footer-elementor' ), 'all_items' => esc_html__( 'View All', 'header-footer-elementor' ), 'search_items' => esc_html__( 'Search Templates', 'header-footer-elementor' ), 'parent_item_colon' => esc_html__( 'Parent Templates:', 'header-footer-elementor' ), 'not_found' => esc_html__( 'No Templates found.', 'header-footer-elementor' ), 'not_found_in_trash' => esc_html__( 'No Templates found in Trash.', 'header-footer-elementor' ), ]; $args = [ 'labels' => $labels, 'public' => true, 'show_ui' => true, 'show_in_menu' => false, 'show_in_nav_menus' => false, 'exclude_from_search' => true, 'capability_type' => 'post', 'hierarchical' => false, 'menu_icon' => 'dashicons-editor-kitchensink', 'supports' => [ 'title', 'thumbnail', 'elementor' ], 'menu_position' => 5, 'capabilities' => [ 'edit_post' => 'manage_options', 'read_post' => 'read', 'delete_post' => 'manage_options', 'edit_posts' => 'manage_options', 'edit_others_posts' => 'manage_options', 'publish_posts' => 'manage_options', 'read_private_posts' => 'manage_options', 'delete_posts' => 'manage_options', 'delete_others_posts' => 'manage_options', 'delete_private_posts' => 'manage_options', 'delete_published_posts' => 'manage_options', 'create_posts' => 'manage_options', ], ]; register_post_type( 'elementor-hf', $args ); } /** * Register the admin menu for Elementor Header & Footer Builder. * * @since 1.0.0 * @since 1.0.1 * Moved the menu under Appearance -> Elementor Header & Footer Builder * @return void */ public function register_admin_menu() { $setting_location = $this->is_pro_active() ? 'uaepro' : 'hfe'; add_submenu_page( $setting_location, __( 'Create New', 'header-footer-elementor' ), __( 'Create New', 'header-footer-elementor' ), 'edit_pages', 'post-new.php?post_type=elementor-hf', '', 1 ); add_submenu_page( $setting_location, __( 'Header/Footer Builder', 'header-footer-elementor' ), __( 'Header & Footer', 'header-footer-elementor' ), 'edit_pages', 'edit.php?post_type=elementor-hf', '', 2 ); } /** * Check if UAE Pro is active. * * @return bool True if UAE Pro is active, false otherwise. */ public function is_pro_active() { if ( is_plugin_active( 'ultimate-elementor/ultimate-elementor.php' ) && defined( 'UAEL_PRO' ) && UAEL_PRO ) { return true; } return false; } /** * Register meta box(es). * * @return void */ public function ehf_register_metabox() { add_meta_box( 'ehf-meta-box', __( 'Elementor Header & Footer Builder Options', 'header-footer-elementor' ), [ $this, 'efh_metabox_render', ], 'elementor-hf', 'normal', 'high' ); } /** * Render Meta field. * * @param array $post Currennt post object which is being displayed. * @return void */ public function efh_metabox_render( $post ) { $values = get_post_custom( $post->ID ); $template_type = isset( $values['ehf_template_type'] ) ? esc_attr( sanitize_text_field( $values['ehf_template_type'][0] ) ) : ''; $display_on_canvas = isset( $values['display-on-canvas-template'] ) ? true : false; // We'll use this nonce field later on when saving. wp_nonce_field( 'ehf_meta_nounce', 'ehf_meta_nounce' ); ?> display_rules_tab(); ?>
/>
admin_styles(); $include_locations = get_post_meta( get_the_id(), 'ehf_target_include_locations', true ); $exclude_locations = get_post_meta( get_the_id(), 'ehf_target_exclude_locations', true ); $users = get_post_meta( get_the_id(), 'ehf_target_user_roles', true ); ?> __( 'Display Rules', 'header-footer-elementor' ), 'value' => '[{"type":"basic-global","specific":null}]', 'tags' => 'site,enable,target,pages', 'rule_type' => 'display', 'add_rule_label' => __( 'Add Display Rule', 'header-footer-elementor' ), ], $include_locations ); ?> __( 'Exclude On', 'header-footer-elementor' ), 'value' => '[]', 'tags' => 'site,enable,target,pages', 'add_rule_label' => __( 'Add Exclusion Rule', 'header-footer-elementor' ), 'rule_type' => 'exclude', ], $exclude_locations ); ?> __( 'Users', 'header-footer-elementor' ), 'value' => '[]', 'tags' => 'site,enable,target,pages', 'add_rule_label' => __( 'Add User Rule', 'header-footer-elementor' ), ], $users ); ?> post_type ) { return; } $template_type = get_post_meta( $post->ID, 'ehf_template_type', true ); if ( '' !== $template_type ) { $templates = Header_Footer_Elementor::get_template_id( $template_type ); // Check if more than one template is selected for current template type. if ( is_array( $templates ) && isset( $templates[1] ) && $post->ID != $templates[0] ) { $post_title = '' . esc_html( get_the_title( $templates[0] ) ) . ''; $template_location = '' . esc_html( $this->template_location( $template_type ) ) . ''; /* Translators: Post title, Template Location */ $message = sprintf( __( 'Template %1$s is already assigned to the location %2$s', 'header-footer-elementor' ), $post_title, $template_location ); echo '

'; echo esc_html( $message ); echo '

'; } } } /** * Convert the Template name to be added in the notice. * * @since 1.0.0 * * @param string $template_type Template type name. * * @return string $template_type Template type name. */ public function template_location( $template_type ) { $template_type = ucfirst( str_replace( 'type_', '', $template_type ) ); return $template_type; } /** * Don't display the elementor Elementor Header & Footer Builder templates on the frontend for non edit_posts capable users. * * @since 1.0.0 * @return void */ public function block_template_frontend() { if ( is_singular( 'elementor-hf' ) && ! current_user_can( 'edit_posts' ) ) { wp_safe_redirect( site_url(), 301 ); die; } } /** * Single template function which will choose our template * * @since 1.0.1 * * @param string $single_template Single template. * @return string */ public function load_canvas_template( $single_template ) { global $post; if ( 'elementor-hf' == $post->post_type ) { $elementor_2_0_canvas = ELEMENTOR_PATH . '/modules/page-templates/templates/canvas.php'; if ( file_exists( $elementor_2_0_canvas ) ) { return $elementor_2_0_canvas; } else { return ELEMENTOR_PATH . '/includes/page-templates/canvas.php'; } } return $single_template; } /** * Set shortcode column for template list. * * @param array $columns template list columns. * @return array */ public function set_shortcode_columns( $columns ) { $date_column = $columns['date']; unset( $columns['date'] ); $columns['shortcode'] = __( 'Shortcode', 'header-footer-elementor' ); $columns['date'] = $date_column; return $columns; } /** * Display shortcode in template list column. * * @param array $column template list column. * @param int $post_id post id. * @return void */ public function render_shortcode_column( $column, $post_id ) { switch ( $column ) { case 'shortcode': ob_start(); ?>