Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/king-addons/includes/Admin.php
+++ b/king-addons/includes/Admin.php
@@ -355,27 +355,38 @@
function showHeaderFooterBuilder(): void
{
- $post_type = 'king-addons-el-hf';
- $menu_slug = 'edit.php?post_type=' . $post_type;
+ $menu_slug = 'king-addons-el-hf';
+ $callback = [King_AddonsHeader_Footer_Builder::instance(), 'renderAdminPage'];
- // Add Main Menu
+ // Add Main Menu (new unified UI)
add_menu_page(
esc_html__('Elementor Header & Footer Builder', 'king-addons'),
esc_html__('Header & Footer', 'king-addons'),
'manage_options',
- $menu_slug, // Menu slug points to the custom post type edit screen
- '', // No callback function needed
+ $menu_slug,
+ $callback,
KING_ADDONS_URL . 'includes/admin/img/icon-for-header-footer-builder.svg',
54.3
);
- // Add 'All Templates' Submenu - this will be the first submenu item
+ // Ensure the first submenu item is labeled "Templates"
add_submenu_page(
- $menu_slug, // Parent slug matches the main menu slug
- esc_html__('All Templates', 'king-addons'),
- esc_html__('All Templates', 'king-addons'),
- 'edit_posts',
- $menu_slug
+ $menu_slug,
+ esc_html__('Templates', 'king-addons'),
+ esc_html__('Templates', 'king-addons'),
+ 'manage_options',
+ $menu_slug,
+ $callback
+ );
+
+ // Display Settings submenu (same page, different tab)
+ add_submenu_page(
+ $menu_slug,
+ esc_html__('Display Settings', 'king-addons'),
+ esc_html__('Display Settings', 'king-addons'),
+ 'manage_options',
+ $menu_slug . '&tab=settings',
+ $callback
);
}
--- a/king-addons/includes/LibrariesMap.php
+++ b/king-addons/includes/LibrariesMap.php
@@ -125,6 +125,10 @@
'css' => [],
'js' => ['wpcolorpicker']
],
+ 'dompurify' => [
+ 'css' => [],
+ 'js' => ['purify.min']
+ ],
]
];
}
--- a/king-addons/includes/admin/shared/dark-theme.php
+++ b/king-addons/includes/admin/shared/dark-theme.php
@@ -359,6 +359,10 @@
color: #a5b4fc;
}
+ .ka-dark-theme a.ka-hf-btn-primary {
+ color: #fff;
+ }
+
.ka-dark-theme a.ka-wb-dropdown-item{
color: var(--ka-wb-text);
}
--- a/king-addons/includes/controls/Ajax_Select2/Ajax_Select2_API.php
+++ b/king-addons/includes/controls/Ajax_Select2/Ajax_Select2_API.php
@@ -49,6 +49,16 @@
'numberposts' => 10
];
+ // Load specific templates by IDs (for pre-populating selected values)
+ if (isset($request['ids']) && !empty($request['ids'])) {
+ $ids = array_filter(array_map('intval', explode(',', $request['ids'])));
+ if (!empty($ids)) {
+ $args['post__in'] = $ids;
+ $args['numberposts'] = -1;
+ unset($args['meta_key'], $args['meta_value']); // Allow any template type when loading by ID
+ }
+ }
+
if (isset($request['s'])) {
$args['s'] = $request['s'];
}
--- a/king-addons/includes/extensions/Header_Footer_Builder/ELHF_Settings_Page.php
+++ b/king-addons/includes/extensions/Header_Footer_Builder/ELHF_Settings_Page.php
@@ -22,11 +22,14 @@
public function __construct()
{
- if (is_admin() && current_user_can('manage_options')) {
- add_action('admin_menu', [$this, 'registerSettingsPage']);
- }
+ // Settings page is now integrated into the main Header & Footer Builder admin page.
+ // The submenu registration is disabled to avoid duplicate menu items.
+ // if (is_admin() && current_user_can('manage_options')) {
+ // add_action('admin_menu', [$this, 'registerSettingsPage']);
+ // }
add_action('admin_init', [$this, 'initSettings']);
- add_filter('views_edit-king-addons-el-hf', [$this, 'addTabs'], 10, 1);
+ // The tab filter is no longer needed since we have our own navigation
+ // add_filter('views_edit-king-addons-el-hf', [$this, 'addTabs'], 10, 1);
}
public function registerSettingsPage()
@@ -111,31 +114,38 @@
function renderCompatibilityOptionsDescription()
{
- echo esc_html__('To ensure compatibility with the current theme, two methods are available:', 'king-addons');
+ echo esc_html__('To ensure compatibility with the current theme, three methods are available:', 'king-addons');
}
function renderCompatibilityOptionsForm()
{
- $chosen_option = get_option('king_addons_el_hf_compatibility_option', '1');
+ $chosen_option = get_option('king_addons_el_hf_compatibility_option', '3');
wp_enqueue_style('king-addons-el-hf-admin', KING_ADDONS_URL . 'includes/extensions/Header_Footer_Builder/admin.css', '', KING_ADDONS_VERSION);
?>
- <label>
+ <label style="display: block; margin-bottom: 20px;">
+ <input type="radio" name="king_addons_el_hf_compatibility_option"
+ value="3" <?php checked($chosen_option, '3'); ?>>
+ <!--suppress HtmlUnknownTag -->
+ <strong class="king-addons-el-hf-radio-options"><?php esc_html_e('Method 3 - Universal (Recommended)', 'king-addons'); ?></strong>
+ <!--suppress HtmlUnknownTag -->
+ <p class="description"><?php esc_html_e('This method combines multiple approaches for maximum theme compatibility. It uses hooks, output buffering, CSS hiding of native theme headers/footers, and JavaScript fallback to ensure headers and footers display correctly on all themes.', 'king-addons'); ?></p>
+ </label>
+ <label style="display: block; margin-bottom: 20px;">
<input type="radio" name="king_addons_el_hf_compatibility_option"
- value=1 <?php checked($chosen_option, 1); ?>>
+ value="1" <?php checked($chosen_option, '1'); ?>>
<!--suppress HtmlUnknownTag -->
- <div class="king-addons-el-hf-radio-options"><?php esc_html_e('Method 1 (Recommended)', 'king-addons'); ?></div>
+ <strong class="king-addons-el-hf-radio-options"><?php esc_html_e('Method 1 - Replace Theme Templates', 'king-addons'); ?></strong>
<!--suppress HtmlUnknownTag -->
- <p class="description"><?php esc_html_e('This method replaces the theme header (header.php) and footer (footer.php) templates with custom templates. This option works well with most themes by default.', 'king-addons'); ?></p>
- <br>
+ <p class="description"><?php esc_html_e('This method replaces the theme header (header.php) and footer (footer.php) templates with custom templates. Works well with classic themes that use standard WordPress template structure.', 'king-addons'); ?></p>
</label>
- <label>
+ <label style="display: block; margin-bottom: 20px;">
<input type="radio" name="king_addons_el_hf_compatibility_option"
- value=2 <?php checked($chosen_option, 2); ?>>
+ value="2" <?php checked($chosen_option, '2'); ?>>
<!--suppress HtmlUnknownTag -->
- <div class="king-addons-el-hf-radio-options"><?php esc_html_e('Method 2', 'king-addons'); ?></div>
+ <strong class="king-addons-el-hf-radio-options"><?php esc_html_e('Method 2 - CSS Hide + Inject', 'king-addons'); ?></strong>
<!--suppress HtmlUnknownTag -->
<p class="description">
- <?php echo esc_html__('If there are issues with the header or footer templates, this alternative method can be used. It hides the theme header and footer using CSS (display: none;) and displays custom templates instead.', 'king-addons'); ?>
+ <?php echo esc_html__('This method hides the theme header and footer using CSS (display: none;) and injects custom templates via wp_body_open and wp_footer hooks.', 'king-addons'); ?>
</p>
</label>
<?php
--- a/king-addons/includes/extensions/Header_Footer_Builder/Header_Footer_Builder.php
+++ b/king-addons/includes/extensions/Header_Footer_Builder/Header_Footer_Builder.php
@@ -17,6 +17,13 @@
private static $location_selection;
private static $user_selection;
private static $elementor_instance;
+
+ /**
+ * Admin menu slug for the new page.
+ *
+ * @var string
+ */
+ private string $menu_slug = 'king-addons-el-hf';
public static function instance(): ?Header_Footer_Builder
{
@@ -29,8 +36,6 @@
public function __construct()
{
add_action('init', [$this, 'addPostType']);
- add_action('admin_notices', [$this, 'renderNoticeZeroPosts']);
- add_action('in_admin_header', [$this, 'renderAdminCustomHeader']);
add_action('add_meta_boxes', [$this, 'registerMetabox']);
add_action('save_post', [$this, 'saveMetaboxData']);
add_action('template_redirect', [$this, 'checkUserCanEdit']);
@@ -38,38 +43,2593 @@
require_once(KING_ADDONS_PATH . 'includes/extensions/Header_Footer_Builder/ELHF_Render_On_Canvas.php');
add_filter('single_template', [$this, 'loadElementorCanvasTemplate']);
+ add_filter('template_include', [$this, 'forceElementorCanvasTemplate'], 99);
self::setCompatibility();
add_action('admin_enqueue_scripts', array($this, 'enqueueScripts'));
add_action('admin_action_edit', array($this, 'initialize_options'));
add_action('wp_ajax_king_addons_el_hf_get_posts_by_query', array($this, 'king_addons_el_hf_get_posts_by_query'));
+ add_action('pre_get_posts', [$this, 'forcePreviewQuery']);
+
+ // Handle template creation and actions
+ add_action('admin_post_ka_hf_builder_create', [$this, 'handleCreateTemplate']);
+ add_action('admin_post_ka_hf_builder_quick_update', [$this, 'handleQuickUpdate']);
+
+ // AJAX handler for conditions popup
+ add_action('wp_ajax_ka_hf_save_conditions', [$this, 'handleAjaxSaveConditions']);
+
+ // AJAX handlers for rename and toggle status
+ add_action('wp_ajax_ka_hf_rename_template', [$this, 'handleAjaxRenameTemplate']);
+ add_action('wp_ajax_ka_hf_toggle_template_status', [$this, 'handleAjaxToggleTemplateStatus']);
if (is_admin()) {
add_action('manage_king-addons-el-hf_posts_custom_column', [$this, 'columnContent'], 10, 2);
add_filter('manage_king-addons-el-hf_posts_columns', [$this, 'columnHeadings']);
}
}
+
+ /**
+ * Register admin menu entry as top-level menu.
+ *
+ * @return void
+ */
+ public function registerAdminMenu(): void
+ {
+ global $menu;
+ $menu['54.6'] = array('', 'read', 'separator-king-addons-hf', '', 'wp-menu-separator');
+
+ add_menu_page(
+ esc_html__('Header & Footer Builder', 'king-addons'),
+ esc_html__('Header & Footer', 'king-addons'),
+ 'manage_options',
+ $this->menu_slug,
+ [$this, 'renderAdminPage'],
+ 'dashicons-align-full-width',
+ 54.7
+ );
+ }
+
+ /**
+ * Render modern admin page for Header & Footer Builder.
+ *
+ * @return void
+ */
+ public function renderAdminPage(): void
+ {
+ if (!current_user_can('manage_options')) {
+ return;
+ }
+
+ // Include shared dark theme support
+ include KING_ADDONS_PATH . 'includes/admin/shared/dark-theme.php';
+
+ // Handle tab navigation
+ $current_tab = isset($_GET['tab']) ? sanitize_key(wp_unslash($_GET['tab'])) : 'templates'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ if (!in_array($current_tab, ['templates', 'settings'], true)) {
+ $current_tab = 'templates';
+ }
+
+ $this->handleInlineActions();
+ $templates = $this->prepareAdminTemplates();
+
+ $base_url = admin_url('admin.php?page=' . $this->menu_slug);
+ $status_filter = 'all';
+ $filtered_templates = $templates;
+
+ $type_cards = [
+ 'header' => [
+ 'label' => esc_html__('Header', 'king-addons'),
+ 'desc' => esc_html__('Site header templates', 'king-addons'),
+ 'value' => 'king_addons_el_hf_type_header',
+ ],
+ 'footer' => [
+ 'label' => esc_html__('Footer', 'king-addons'),
+ 'desc' => esc_html__('Site footer templates', 'king-addons'),
+ 'value' => 'king_addons_el_hf_type_footer',
+ ],
+ ];
+
+ $this->renderModernStyles();
+
+ // Render dark theme styles and init
+ ka_render_dark_theme_styles();
+ ka_render_dark_theme_init();
+ ?>
+ <script>
+ if (document.body) {
+ document.body.classList.add('ka-admin-v3');
+ } else {
+ document.addEventListener('DOMContentLoaded', function() {
+ document.body.classList.add('ka-admin-v3');
+ });
+ }
+ </script>
+
+ <div class="ka-hf">
+ <header class="ka-hf-header">
+ <div class="ka-hf-header-content">
+ <span class="ka-hf-title-icon" aria-hidden="true">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+ <path d="M3 3h18v6H3zM3 15h18v6H3z" />
+ </svg>
+ </span>
+ <div class="ka-hf-header-titles">
+ <h1><span class="ka-hf-title-text"><?php esc_html_e('Header & Footer Builder', 'king-addons'); ?></span></h1>
+ <p><?php esc_html_e('Create custom headers and footers with display conditions', 'king-addons'); ?></p>
+ </div>
+ </div>
+ <div class="ka-hf-header-actions">
+ <?php if ('templates' === $current_tab) : ?>
+ <button type="button" id="ka-hf-add-new" class="ka-hf-btn ka-hf-btn-primary">
+ <span class="ka-hf-btn-icon" aria-hidden="true">+</span>
+ <?php esc_html_e('Add New Template', 'king-addons'); ?>
+ </button>
+ <?php endif; ?>
+ <?php ka_render_dark_theme_toggle(); ?>
+ </div>
+ </header>
+
+ <!-- Navigation Tabs -->
+ <nav class="ka-hf-nav-tabs">
+ <a href="<?php echo esc_url($base_url); ?>" class="ka-hf-nav-tab<?php echo 'templates' === $current_tab ? ' is-active' : ''; ?>">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18">
+ <path d="M3 3h18v6H3zM3 15h18v6H3z" />
+ </svg>
+ <?php esc_html_e('Templates', 'king-addons'); ?>
+ </a>
+ <a href="<?php echo esc_url(add_query_arg('tab', 'settings', $base_url)); ?>" class="ka-hf-nav-tab<?php echo 'settings' === $current_tab ? ' is-active' : ''; ?>">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18">
+ <circle cx="12" cy="12" r="3"/>
+ <path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"/>
+ </svg>
+ <?php esc_html_e('Display Settings', 'king-addons'); ?>
+ </a>
+ </nav>
+
+ <?php if ('templates' === $current_tab) : ?>
+
+ <div class="ka-hf-types" role="list">
+ <?php foreach ($type_cards as $type_slug => $data) : ?>
+ <?php $type_icon_svg = $this->getTypeIconSvg($type_slug); ?>
+ <button
+ type="button"
+ class="ka-hf-type"
+ role="listitem"
+ data-ka-hf-type="<?php echo esc_attr($data['value']); ?>"
+ >
+ <div class="ka-hf-type-icon" aria-hidden="true">
+ <?php echo $type_icon_svg; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
+ </div>
+ <div class="ka-hf-type-label"><?php echo esc_html($data['label']); ?></div>
+ <div class="ka-hf-type-desc"><?php echo esc_html($data['desc']); ?></div>
+ </button>
+ <?php endforeach; ?>
+ </div>
+
+ <section class="ka-hf-section">
+ <div class="ka-hf-section-header">
+ <h2 class="ka-hf-section-title"><?php esc_html_e('Templates', 'king-addons'); ?></h2>
+ <div class="ka-hf-section-actions">
+ <div class="ka-hf-filters" role="navigation">
+ <button type="button" class="ka-hf-filter is-active" data-filter="all"><?php esc_html_e('All', 'king-addons'); ?></button>
+ <button type="button" class="ka-hf-filter" data-filter="header"><?php esc_html_e('Headers', 'king-addons'); ?></button>
+ <button type="button" class="ka-hf-filter" data-filter="footer"><?php esc_html_e('Footers', 'king-addons'); ?></button>
+ </div>
+ <div class="ka-hf-section-count"><?php echo esc_html(count($filtered_templates) . ' ' . _n('item', 'items', count($filtered_templates), 'king-addons')); ?></div>
+ </div>
+ </div>
+
+ <div class="ka-hf-templates" role="list">
+ <?php if (empty($filtered_templates)) : ?>
+ <div class="ka-hf-empty">
+ <h3 class="ka-hf-empty-title"><?php esc_html_e('No templates yet', 'king-addons'); ?></h3>
+ <p class="ka-hf-empty-desc"><?php esc_html_e('Create your first header or footer template to get started.', 'king-addons'); ?></p>
+ <button type="button" class="ka-hf-btn ka-hf-btn-primary" id="ka-hf-add-new-empty">
+ <span class="ka-hf-btn-icon" aria-hidden="true">+</span>
+ <?php esc_html_e('Add New Template', 'king-addons'); ?>
+ </button>
+ </div>
+ <?php else : ?>
+ <?php foreach ($filtered_templates as $template) : ?>
+ <?php
+ $template_id = (int) ($template['id'] ?? 0);
+ if (!$template_id) {
+ continue;
+ }
+
+ $title = !empty($template['title']) ? (string) $template['title'] : sprintf(
+ esc_html__('Template #%d', 'king-addons'),
+ $template_id
+ );
+
+ $edit_elementor_url = admin_url('post.php?post=' . $template_id . '&action=elementor');
+ $edit_settings_url = admin_url('post.php?post=' . $template_id . '&action=edit');
+ $type_value = $template['type'] ?? '';
+ $type_label = 'king_addons_el_hf_type_header' === $type_value ? esc_html__('Header', 'king-addons') : ('king_addons_el_hf_type_footer' === $type_value ? esc_html__('Footer', 'king-addons') : esc_html__('Not Set', 'king-addons'));
+ $type_slug = 'king_addons_el_hf_type_header' === $type_value ? 'header' : ('king_addons_el_hf_type_footer' === $type_value ? 'footer' : 'unset');
+ $delete_url = wp_nonce_url(add_query_arg(['action' => 'delete_template', 'template_id' => $template_id], $base_url), 'ka_hf_delete_' . $template_id);
+ $conditions_text = $this->summarizeConditions($template);
+ $title_icon_svg = $this->getTypeIconSvg($type_slug);
+ $post_status = get_post_status($template_id);
+ $is_disabled = 'publish' !== $post_status;
+ $status_label = $is_disabled ? esc_html__('Disabled', 'king-addons') : $type_label;
+ ?>
+ <div class="ka-hf-template" role="listitem" data-template-type="<?php echo esc_attr($type_slug); ?>" data-template-id="<?php echo esc_attr($template_id); ?>" data-status="<?php echo esc_attr($post_status); ?>" data-type-label="<?php echo esc_attr($type_label); ?>">
+ <div class="ka-hf-template-status <?php echo $is_disabled ? 'is-disabled' : 'is-enabled'; ?>">
+ <?php echo esc_html($status_label); ?>
+ </div>
+ <div class="ka-hf-template-info">
+ <a class="ka-hf-template-title" href="<?php echo esc_url($edit_elementor_url); ?>">
+ <span class="ka-hf-template-title-icon" aria-hidden="true">
+ <?php echo $title_icon_svg; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
+ </span>
+ <span class="ka-hf-template-title-text"><?php echo esc_html($title); ?></span>
+ </a>
+ <div class="ka-hf-template-meta">
+ <span class="ka-hf-template-type"><?php echo esc_html($type_label); ?></span>
+ </div>
+ </div>
+ <?php
+ // Prepare conditions data for the popup
+ $include_locs = $template['include_locations'] ?? [];
+ $exclude_locs = $template['exclude_locations'] ?? [];
+ $user_roles_arr = $template['user_roles'] ?? [];
+ $template_data = [
+ 'id' => $template_id,
+ 'title' => $title,
+ 'type' => $type_value,
+ 'include' => $include_locs,
+ 'exclude' => $exclude_locs,
+ 'userRoles' => $user_roles_arr,
+ ];
+ ?>
+ <button type="button" class="ka-hf-template-condition ka-hf-open-conditions" title="<?php echo esc_attr__('Edit Display Conditions', 'king-addons'); ?>" data-template='<?php echo esc_attr(wp_json_encode($template_data)); ?>'>
+ <svg class="ka-hf-condition-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
+ <circle cx="12" cy="12" r="3"/>
+ <path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"/>
+ </svg>
+ <?php echo esc_html($conditions_text); ?>
+ </button>
+ <div class="ka-hf-template-actions">
+ <a class="ka-hf-btn ka-hf-btn-primary" href="<?php echo esc_url($edit_elementor_url); ?>"><?php esc_html_e('Edit with Elementor', 'king-addons'); ?></a>
+ <div class="ka-hf-dropdown" data-ka-dropdown>
+ <button type="button" class="ka-hf-dropdown-trigger" aria-label="<?php echo esc_attr(esc_html__('More actions', 'king-addons')); ?>">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
+ <circle cx="12" cy="5" r="1" />
+ <circle cx="12" cy="12" r="1" />
+ <circle cx="12" cy="19" r="1" />
+ </svg>
+ </button>
+ <div class="ka-hf-dropdown-menu" role="menu">
+ <button type="button" class="ka-hf-dropdown-item ka-hf-rename-btn" role="menuitem" data-id="<?php echo esc_attr($template_id); ?>" data-title="<?php echo esc_attr($title); ?>">
+ <?php esc_html_e('Rename', 'king-addons'); ?>
+ </button>
+ <a class="ka-hf-dropdown-item" role="menuitem" href="<?php echo esc_url($edit_settings_url); ?>">
+ <?php esc_html_e('WP Edit', 'king-addons'); ?>
+ </a>
+ <button type="button" class="ka-hf-dropdown-item ka-hf-toggle-status-btn" role="menuitem" data-id="<?php echo esc_attr($template_id); ?>" data-status="<?php echo esc_attr(get_post_status($template_id)); ?>">
+ <?php echo get_post_status($template_id) === 'publish' ? esc_html__('Disable', 'king-addons') : esc_html__('Enable', 'king-addons'); ?>
+ </button>
+ <a class="ka-hf-dropdown-item is-danger" role="menuitem" href="<?php echo esc_url($delete_url); ?>" onclick="return confirm('<?php echo esc_js(esc_html__('Move template to trash?', 'king-addons')); ?>');">
+ <?php esc_html_e('Delete', 'king-addons'); ?>
+ </a>
+ </div>
+ </div>
+ </div>
+ </div>
+ <?php endforeach; ?>
+ <?php endif; ?>
+ </div>
+
+ <div class="ka-hf-filter-empty" style="display: none;">
+ <h3 class="ka-hf-empty-title"><?php esc_html_e('No templates found', 'king-addons'); ?></h3>
+ <p class="ka-hf-empty-desc"><?php esc_html_e('Try a different filter or create a new template.', 'king-addons'); ?></p>
+ <button type="button" class="ka-hf-btn ka-hf-btn-primary" id="ka-hf-add-new-filter-empty">
+ <span class="ka-hf-btn-icon" aria-hidden="true">+</span>
+ <?php esc_html_e('Add New Template', 'king-addons'); ?>
+ </button>
+ </div>
+ </section>
+
+ <?php $this->renderAddNewModal(); ?>
+ <?php $this->renderRenameModal(); ?>
+ <?php $this->renderConditionsPopup(); ?>
+
+ <?php else : // settings tab ?>
+
+ <?php $this->renderDisplaySettingsTab(); ?>
+
+ <?php endif; ?>
+ </div>
+ <?php
+
+ // Render dark theme script at the end
+ ka_render_dark_theme_script();
+ }
+
+ /**
+ * Render the Display Settings tab content.
+ *
+ * @return void
+ */
+ private function renderDisplaySettingsTab(): void
+ {
+ $chosen_option = get_option('king_addons_el_hf_compatibility_option', '3');
+ ?>
+ <section class="ka-hf-section ka-hf-settings-section">
+ <div class="ka-hf-section-header">
+ <h2 class="ka-hf-section-title"><?php esc_html_e('Display Settings', 'king-addons'); ?></h2>
+ </div>
+
+ <form method="post" action="options.php" class="ka-hf-settings-form">
+ <?php settings_fields('king-addons-el-hf-ext-options'); ?>
+
+ <div class="ka-hf-settings-card">
+ <h3 class="ka-hf-settings-card-title"><?php esc_html_e('Compatibility Mode', 'king-addons'); ?></h3>
+ <p class="ka-hf-settings-card-desc"><?php esc_html_e('To ensure compatibility with the current theme, three methods are available:', 'king-addons'); ?></p>
+
+ <div class="ka-hf-settings-options">
+
+ <label class="ka-hf-settings-option">
+ <input type="radio" name="king_addons_el_hf_compatibility_option" value="1" <?php checked($chosen_option, '1'); ?>>
+ <div class="ka-hf-settings-option-content">
+ <span class="ka-hf-settings-option-title"><?php esc_html_e('Method 1 - Replace Theme Templates', 'king-addons'); ?></span>
+ <span class="ka-hf-settings-option-desc"><?php esc_html_e('This method replaces the theme header (header.php) and footer (footer.php) templates with custom templates. Works well with classic themes that use standard WordPress template structure.', 'king-addons'); ?></span>
+ </div>
+ </label>
+
+ <label class="ka-hf-settings-option">
+ <input type="radio" name="king_addons_el_hf_compatibility_option" value="2" <?php checked($chosen_option, '2'); ?>>
+ <div class="ka-hf-settings-option-content">
+ <span class="ka-hf-settings-option-title"><?php esc_html_e('Method 2 - CSS Hide + Inject', 'king-addons'); ?></span>
+ <span class="ka-hf-settings-option-desc"><?php esc_html_e('This method hides the theme header and footer using CSS (display: none;) and injects custom templates via wp_body_open and wp_footer hooks.', 'king-addons'); ?></span>
+ </div>
+ </label>
+
+ <label class="ka-hf-settings-option">
+ <input type="radio" name="king_addons_el_hf_compatibility_option" value="3" <?php checked($chosen_option, '3'); ?>>
+ <div class="ka-hf-settings-option-content">
+ <span class="ka-hf-settings-option-title"><?php esc_html_e('Method 3 - Universal (Recommended)', 'king-addons'); ?></span>
+ <span class="ka-hf-settings-option-desc"><?php esc_html_e('This method combines multiple approaches for maximum theme compatibility. It uses hooks, output buffering, CSS hiding of native theme headers/footers, and JavaScript fallback to ensure headers and footers display correctly on all themes including Block Themes (FSE).', 'king-addons'); ?></span>
+ </div>
+ </label>
+
+ </div>
+
+ <div class="ka-hf-settings-actions">
+ <button type="submit" class="ka-hf-btn ka-hf-btn-primary"><?php esc_html_e('Save Settings', 'king-addons'); ?></button>
+ </div>
+ </div>
+ </form>
+ </section>
+ <?php
+ }
+
+ /**
+ * Render the Add New Template modal.
+ *
+ * @return void
+ */
+ private function renderAddNewModal(): void
+ {
+ self::$location_selection = self::getLocationSelections();
+ self::$user_selection = self::get_user_selections();
+ ?>
+ <div id="ka-hf-modal" class="ka-hf-modal-overlay" aria-hidden="true">
+ <div class="ka-hf-modal" role="dialog" aria-modal="true" aria-labelledby="ka-hf-create-title">
+ <h3 id="ka-hf-create-title"><?php echo esc_html__('Create Header / Footer Template', 'king-addons'); ?></h3>
+ <p class="ka-hf-modal-desc"><?php echo esc_html__('Choose the template type and configure display conditions.', 'king-addons'); ?></p>
+
+ <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
+ <input type="hidden" name="action" value="ka_hf_builder_create" />
+ <?php wp_nonce_field('ka_hf_builder_create', 'ka_hf_builder_create_nonce'); ?>
+
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label" for="ka-hf-title"><?php echo esc_html__('Template Name', 'king-addons'); ?></label>
+ <input type="text" id="ka-hf-title" name="ka_hf_title" class="ka-hf-modal-input" value="<?php echo esc_attr__('My Template', 'king-addons'); ?>" />
+ </div>
+
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label" for="ka-hf-type"><?php echo esc_html__('Template Type', 'king-addons'); ?></label>
+ <select id="ka-hf-type" name="ka_hf_type" class="ka-hf-form-select">
+ <option value="king_addons_el_hf_type_header"><?php echo esc_html__('Header', 'king-addons'); ?></option>
+ <option value="king_addons_el_hf_type_footer"><?php echo esc_html__('Footer', 'king-addons'); ?></option>
+ </select>
+ </div>
+
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label"><?php echo esc_html__('Display On', 'king-addons'); ?></label>
+ <p class="ka-hf-form-desc"><?php echo esc_html__('Add locations where this template should appear', 'king-addons'); ?></p>
+ <div class="ka-hf-conditions-wrap">
+ <div class="ka-hf-create-rule-row">
+ <select id="ka-hf-display-rule" name="ka_hf_display_rule" class="ka-hf-form-select">
+ <?php foreach (self::$location_selection as $group_data) : ?>
+ <optgroup label="<?php echo esc_attr($group_data['label']); ?>">
+ <?php foreach ($group_data['value'] as $opt_key => $opt_value) : ?>
+ <option value="<?php echo esc_attr($opt_key); ?>" <?php selected($opt_key, 'basic-global'); ?>><?php echo esc_html($opt_value); ?></option>
+ <?php endforeach; ?>
+ </optgroup>
+ <?php endforeach; ?>
+ </select>
+ <input type="text" id="ka-hf-display-specific" name="ka_hf_display_specific" class="ka-hf-modal-input ka-hf-specific-input" placeholder="<?php echo esc_attr__('Enter page/post IDs (comma separated)', 'king-addons'); ?>" style="display: none;" />
+ </div>
+ </div>
+ </div>
+
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label"><?php echo esc_html__('User Roles (Optional)', 'king-addons'); ?></label>
+ <p class="ka-hf-form-desc"><?php echo esc_html__('Display template for specific user roles.', 'king-addons'); ?></p>
+ <div id="ka-hf-create-user-roles" class="ka-hf-rules-container">
+ <!-- Role rows will be added dynamically via JS -->
+ </div>
+ <button type="button" class="ka-hf-add-rule-btn" id="ka-hf-create-add-user-role">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M12 5v14M5 12h14"/></svg>
+ <?php echo esc_html__('Add User Role', 'king-addons'); ?>
+ </button>
+ </div>
+
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label">
+ <input type="checkbox" id="ka-hf-display-canvas" name="ka_hf_display_canvas" value="1" />
+ <?php echo esc_html__('Enable for Elementor Canvas Template', 'king-addons'); ?>
+ </label>
+ <p class="ka-hf-form-desc"><?php echo esc_html__('Show this template on pages using Elementor Canvas Template', 'king-addons'); ?></p>
+ </div>
+
+ <div class="ka-hf-modal-actions">
+ <button type="button" class="ka-hf-btn ka-hf-btn-secondary ka-hf-modal-close"><?php echo esc_html__('Cancel', 'king-addons'); ?></button>
+ <button type="submit" class="ka-hf-btn ka-hf-btn-primary"><?php echo esc_html__('Create and Edit with Elementor', 'king-addons'); ?></button>
+ </div>
+ </form>
+ </div>
+ </div>
+ <?php
+ }
+
+ /**
+ * Render the Rename Template modal.
+ *
+ * @return void
+ */
+ private function renderRenameModal(): void
+ {
+ ?>
+ <div id="ka-hf-rename-modal" class="ka-hf-modal-overlay" aria-hidden="true">
+ <div class="ka-hf-modal" role="dialog" aria-modal="true" aria-labelledby="ka-hf-rename-title">
+ <h3 id="ka-hf-rename-title"><?php echo esc_html__('Rename Template', 'king-addons'); ?></h3>
+ <p class="ka-hf-modal-desc"><?php echo esc_html__('Enter a new name for this template.', 'king-addons'); ?></p>
+
+ <input type="hidden" id="ka-hf-rename-id" value="" />
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label" for="ka-hf-rename-title-input"><?php echo esc_html__('Template Name', 'king-addons'); ?></label>
+ <input type="text" id="ka-hf-rename-title-input" class="ka-hf-modal-input" value="" />
+ </div>
+
+ <div class="ka-hf-modal-actions">
+ <button type="button" class="ka-hf-btn ka-hf-btn-secondary ka-hf-rename-close"><?php echo esc_html__('Cancel', 'king-addons'); ?></button>
+ <button type="button" class="ka-hf-btn ka-hf-btn-primary" id="ka-hf-rename-save"><?php echo esc_html__('Save', 'king-addons'); ?></button>
+ </div>
+ </div>
+ </div>
+ <?php
+ }
+
+ /**
+ * Render the Conditions Popup for editing existing templates.
+ *
+ * @return void
+ */
+ private function renderConditionsPopup(): void
+ {
+ self::$location_selection = self::getLocationSelections();
+ self::$user_selection = self::get_user_selections();
+
+ // Prepare location options JSON for JS
+ $location_options = [];
+ foreach (self::$location_selection as $group_key => $group_data) {
+ foreach ($group_data['value'] as $opt_key => $opt_value) {
+ $location_options[$opt_key] = $opt_value;
+ }
+ }
+
+ $user_options = [];
+ foreach (self::$user_selection as $group_data) {
+ foreach ($group_data['value'] as $opt_key => $opt_value) {
+ $user_options[$opt_key] = $opt_value;
+ }
+ }
+ ?>
+ <div id="ka-hf-conditions-modal" class="ka-hf-modal-overlay" aria-hidden="true">
+ <div class="ka-hf-modal ka-hf-modal-conditions" role="dialog" aria-modal="true" aria-labelledby="ka-hf-conditions-title">
+ <h3 id="ka-hf-conditions-title"><?php echo esc_html__('Template Settings', 'king-addons'); ?></h3>
+ <p class="ka-hf-modal-desc"><?php echo esc_html__('Configure template type and display conditions.', 'king-addons'); ?></p>
+
+ <input type="hidden" id="ka-hf-cond-template-id" value="" />
+
+ <!-- Template Type Section -->
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label"><?php echo esc_html__('Template Type', 'king-addons'); ?></label>
+ <select id="ka-hf-cond-template-type" class="ka-hf-form-select">
+ <option value="king_addons_el_hf_type_header"><?php echo esc_html__('Header', 'king-addons'); ?></option>
+ <option value="king_addons_el_hf_type_footer"><?php echo esc_html__('Footer', 'king-addons'); ?></option>
+ </select>
+ </div>
+
+ <!-- Include Rules Section -->
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label"><?php echo esc_html__('Display On', 'king-addons'); ?></label>
+ <div id="ka-hf-include-rules" class="ka-hf-rules-container">
+ <!-- Rules will be added dynamically via JS -->
+ </div>
+ <button type="button" class="ka-hf-add-rule-btn" data-rule-type="include">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M12 5v14M5 12h14"/></svg>
+ <?php echo esc_html__('Add Display Rule', 'king-addons'); ?>
+ </button>
+ </div>
+
+ <!-- Exclude Rules Section -->
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label"><?php echo esc_html__('Do Not Display On', 'king-addons'); ?></label>
+ <div id="ka-hf-exclude-rules" class="ka-hf-rules-container">
+ <!-- Exclusion rules will be added dynamically via JS -->
+ </div>
+ <button type="button" class="ka-hf-add-rule-btn" data-rule-type="exclude">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M12 5v14M5 12h14"/></svg>
+ <?php echo esc_html__('Add Exclusion Rule', 'king-addons'); ?>
+ </button>
+ </div>
+
+ <!-- User Roles Section -->
+ <div class="ka-hf-form-group">
+ <label class="ka-hf-form-label"><?php echo esc_html__('User Roles (Optional)', 'king-addons'); ?></label>
+ <div id="ka-hf-user-roles" class="ka-hf-rules-container">
+ <!-- User role rows will be added dynamically via JS -->
+ </div>
+ <button type="button" class="ka-hf-add-rule-btn" id="ka-hf-add-user-role">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M12 5v14M5 12h14"/></svg>
+ <?php echo esc_html__('Add User Role', 'king-addons'); ?>
+ </button>
+ </div>
+
+ <div class="ka-hf-modal-actions">
+ <button type="button" class="ka-hf-btn ka-hf-btn-secondary ka-hf-conditions-close"><?php echo esc_html__('Cancel', 'king-addons'); ?></button>
+ <button type="button" id="ka-hf-save-conditions" class="ka-hf-btn ka-hf-btn-primary"><?php echo esc_html__('Save Conditions', 'king-addons'); ?></button>
+ </div>
+
+ <div id="ka-hf-conditions-saving" class="ka-hf-saving-overlay" style="display: none;">
+ <span class="ka-hf-spinner"></span>
+ <?php echo esc_html__('Saving...', 'king-addons'); ?>
+ </div>
+ </div>
+ </div>
+
+ <!-- Rule template for JS cloning -->
+ <template id="ka-hf-rule-template">
+ <div class="ka-hf-rule-row">
+ <select class="ka-hf-form-select ka-hf-rule-select">
+ <?php foreach (self::$location_selection as $group_data) : ?>
+ <optgroup label="<?php echo esc_attr($group_data['label']); ?>">
+ <?php foreach ($group_data['value'] as $opt_key => $opt_value) : ?>
+ <option value="<?php echo esc_attr($opt_key); ?>"><?php echo esc_html($opt_value); ?></option>
+ <?php endforeach; ?>
+ </optgroup>
+ <?php endforeach; ?>
+ </select>
+ <input type="text" class="ka-hf-modal-input ka-hf-specific-input" placeholder="<?php echo esc_attr__('Specific IDs (comma separated)', 'king-addons'); ?>" style="display: none;" />
+ <button type="button" class="ka-hf-remove-rule-btn" title="<?php echo esc_attr__('Remove rule', 'king-addons'); ?>">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"><path d="M18 6L6 18M6 6l12 12"/></svg>
+ </button>
+ </div>
+ </template>
+ <!-- User role template for JS cloning -->
+ <template id="ka-hf-user-role-template">
+ <div class="ka-hf-rule-row ka-hf-user-role-row">
+ <select class="ka-hf-form-select ka-hf-user-role-select">
+ <?php foreach (self::$user_selection as $group_data) : ?>
+ <optgroup label="<?php echo esc_attr($group_data['label']); ?>">
+ <?php foreach ($group_data['value'] as $opt_key => $opt_value) : ?>
+ <option value="<?php echo esc_attr($opt_key); ?>"><?php echo esc_html($opt_value); ?></option>
+ <?php endforeach; ?>
+ </optgroup>
+ <?php endforeach; ?>
+ </select>
+ <button type="button" class="ka-hf-remove-rule-btn" title="<?php echo esc_attr__('Remove role', 'king-addons'); ?>">
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"><path d="M18 6L6 18M6 6l12 12"/></svg>
+ </button>
+ </div>
+ </template>
+
+ <script>
+ var kaHfLocationOptions = <?php echo wp_json_encode($location_options); ?>;
+ var kaHfUserOptions = <?php echo wp_json_encode($user_options); ?>;
+ var kaHfAjaxUrl = <?php echo wp_json_encode(admin_url('admin-ajax.php')); ?>;
+ var kaHfNonce = <?php echo wp_json_encode(wp_create_nonce('ka_hf_save_conditions')); ?>;
+ </script>
+ <?php
+ }
+
/**
- * Show an admin notice when there are zero "king-addons-el-hf" posts
+ * AJAX handler to save conditions for a template.
+ *
+ * @return void
*/
- function renderNoticeZeroPosts()
+ public function handleAjaxSaveConditions(): void
{
- global $pagenow, $post_type;
+ if (!current_user_can('manage_options')) {
+ wp_send_json_error(['message' => esc_html__('Permission denied.', 'king-addons')]);
+ }
+
+ if (!check_ajax_referer('ka_hf_save_conditions', 'nonce', false)) {
+ wp_send_json_error(['message' => esc_html__('Invalid nonce.', 'king-addons')]);
+ }
+
+ $template_id = isset($_POST['template_id']) ? (int) $_POST['template_id'] : 0;
+ if (!$template_id || 'king-addons-el-hf' !== get_post_type($template_id)) {
+ wp_send_json_error(['message' => esc_html__('Invalid template.', 'king-addons')]);
+ }
+
+ // Parse include rules
+ $include_rules = [];
+ $include_specific = [];
+ if (!empty($_POST['include_rules']) && is_array($_POST['include_rules'])) {
+ foreach ($_POST['include_rules'] as $rule) {
+ $rule_val = sanitize_text_field(wp_unslash($rule['rule'] ?? ''));
+ if ($rule_val) {
+ $include_rules[] = $rule_val;
+ if ('specifics' === $rule_val && !empty($rule['specific'])) {
+ $specific_ids = array_map('intval', array_filter(explode(',', sanitize_text_field(wp_unslash($rule['specific'])))));
+ $include_specific = array_merge($include_specific, $specific_ids);
+ }
+ }
+ }
+ }
+
+ // Parse exclude rules
+ $exclude_rules = [];
+ $exclude_specific = [];
+ if (!empty($_POST['exclude_rules']) && is_array($_POST['exclude_rules'])) {
+ foreach ($_POST['exclude_rules'] as $rule) {
+ $rule_val = sanitize_text_field(wp_unslash($rule['rule'] ?? ''));
+ if ($rule_val) {
+ $exclude_rules[] = $rule_val;
+ if ('specifics' === $rule_val && !empty($rule['specific'])) {
+ $specific_ids = array_map('intval', array_filter(explode(',', sanitize_text_field(wp_unslash($rule['specific'])))));
+ $exclude_specific = array_merge($exclude_specific, $specific_ids);
+ }
+ }
+ }
+ }
+
+ // Parse user roles (multiple)
+ $user_roles = [];
+ if (!empty($_POST['user_roles']) && is_array($_POST['user_roles'])) {
+ foreach ($_POST['user_roles'] as $role) {
+ $role_val = sanitize_text_field(wp_unslash($role));
+ if ($role_val) {
+ $user_roles[] = $role_val;
+ }
+ }
+ }
+ if (empty($user_roles)) {
+ $user_roles = ['all'];
+ }
+ $user_roles = array_values(array_unique($user_roles));
+ if (in_array('all', $user_roles, true)) {
+ $user_roles = ['all'];
+ }
+
+ // Parse template type
+ $template_type = isset($_POST['template_type']) ? sanitize_text_field(wp_unslash($_POST['template_type'])) : '';
+ if (!empty($template_type) && in_array($template_type, ['king_addons_el_hf_type_header', 'king_addons_el_hf_type_footer'], true)) {
+ update_post_meta($template_id, 'king_addons_el_hf_template_type', $template_type);
+ }
+
+ // Save meta
+ $include_locations = [
+ 'rule' => $include_rules,
+ 'specific' => $include_specific,
+ ];
+ $exclude_locations = [
+ 'rule' => $exclude_rules,
+ 'specific' => $exclude_specific,
+ ];
+
+ update_post_meta($template_id, 'king_addons_el_hf_target_include_locations', $include_locations);
+ update_post_meta($template_id, 'king_addons_el_hf_target_exclude_locations', $exclude_locations);
+ update_post_meta($template_id, 'king_addons_el_hf_target_user_roles', $user_roles);
+
+ wp_send_json_success(['message' => esc_html__('Settings saved successfully.', 'king-addons')]);
+ }
+
+ /**
+ * AJAX handler to rename a template.
+ *
+ * @return void
+ */
+ public function handleAjaxRenameTemplate(): void
+ {
+ if (!current_user_can('manage_options')) {
+ wp_send_json_error(['message' => esc_html__('Permission denied.', 'king-addons')]);
+ }
+
+ if (!check_ajax_referer('ka_hf_save_conditions', 'nonce', false)) {
+ wp_send_json_error(['message' => esc_html__('Invalid nonce.', 'king-addons')]);
+ }
+
+ $template_id = isset($_POST['template_id']) ? (int) $_POST['template_id'] : 0;
+ $new_title = isset($_POST['new_title']) ? sanitize_text_field(wp_unslash($_POST['new_title'])) : '';
+
+ if (!$template_id || 'king-addons-el-hf' !== get_post_type($template_id)) {
+ wp_send_json_error(['message' => esc_html__('Invalid template.', 'king-addons')]);
+ }
+
+ if (empty($new_title)) {
+ wp_send_json_error(['message' => esc_html__('Title cannot be empty.', 'king-addons')]);
+ }
+
+ $result = wp_update_post([
+ 'ID' => $template_id,
+ 'post_title' => $new_title,
+ ]);
+
+ if (is_wp_error($result)) {
+ wp_send_json_error(['message' => esc_html__('Failed to rename template.', 'king-addons')]);
+ }
+
+ wp_send_json_success(['message' => esc_html__('Template renamed successfully.', 'king-addons')]);
+ }
+
+ /**
+ * AJAX handler to toggle template status (publish/draft).
+ *
+ * @return void
+ */
+ public function handleAjaxToggleTemplateStatus(): void
+ {
+ if (!current_user_can('manage_options')) {
+ wp_send_json_error(['message' => esc_html__('Permission denied.', 'king-addons')]);
+ }
+
+ if (!check_ajax_referer('ka_hf_save_conditions', 'nonce', false)) {
+ wp_send_json_error(['message' => esc_html__('Invalid nonce.', 'king-addons')]);
+ }
+
+ $template_id = isset($_POST['template_id']) ? (int) $_POST['template_id'] : 0;
+ $new_status = isset($_POST['new_status']) ? sanitize_text_field(wp_unslash($_POST['new_status'])) : '';
+
+ if (!$template_id || 'king-addons-el-hf' !== get_post_type($template_id)) {
+ wp_send_json_error(['message' => esc_html__('Invalid template.', 'king-addons')]);
+ }
+
+ if (!in_array($new_status, ['publish', 'draft'], true)) {
+ wp_send_json_error(['message' => esc_html__('Invalid status.', 'king-addons')]);
+ }
+
+ $result = wp_update_post([
+ 'ID' => $template_id,
+ 'post_status' => $new_status,
+ ]);
+
+ if (is_wp_error($result)) {
+ wp_send_json_error(['message' => esc_html__('Failed to update template status.', 'king-addons')]);
+ }
+
+ wp_send_json_success(['message' => esc_html__('Template status updated.', 'king-addons')]);
+ }
+
+ /**
+ * Handle "Add New" template submission.
+ *
+ * @return void
+ */
+ public function handleCreateTemplate(): void
+ {
+ if (!current_user_can('manage_options')) {
+ wp_die(esc_html__('You do not have permission to perform this action.', 'king-addons'));
+ }
- // Check if we are on the "All posts" page for the custom post type
- if ('edit.php' === $pagenow && 'edit-king-addons-el-hf' === $post_type) {
+ if (!isset($_POST['ka_hf_builder_create_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['ka_hf_builder_create_nonce'])), 'ka_hf_builder_create')) {
+ wp_die(esc_html__('Invalid nonce.', 'king-addons'));
+ }
- // Count published posts of this CPT
- $count_posts = wp_count_posts('king-addons-el-hf');
- if ($count_posts->publish == 0) {
- echo '<div class="notice notice-info is-dismissible">';
- echo '<p>';
- echo esc_html__("Create the first header or footer by clicking the 'Create New' button above.", 'king addons');
- echo '</p>';
- echo '</div>';
+ $title = isset($_POST['ka_hf_title']) ? sanitize_text_field(wp_unslash($_POST['ka_hf_title'])) : esc_html__('My Template', 'king-addons');
+ $type = isset($_POST['ka_hf_type']) ? sanitize_text_field(wp_unslash($_POST['ka_hf_type'])) : 'king_addons_el_hf_type_header';
+ $display_rule = isset($_POST['ka_hf_display_rule']) ? sanitize_text_field(wp_unslash($_POST['ka_hf_display_rule'])) : 'basic-global';
+ $display_specific = isset($_POST['ka_hf_display_specific']) ? sanitize_text_field(wp_unslash($_POST['ka_hf_display_specific'])) : '';
+ $display_canvas = isset($_POST['ka_hf_display_canvas']) ? '1' : '';
+
+ // Parse user roles (multiple selection)
+ $user_roles = [];
+ if (!empty($_POST['ka_hf_user_role']) && is_array($_POST['ka_hf_user_role'])) {
+ foreach ($_POST['ka_hf_user_role'] as $role) {
+ $role_val = sanitize_text_field(wp_unslash($role));
+ if ($role_val) {
+ $user_roles[] = $role_val;
+ }
}
}
+ if (empty($user_roles)) {
+ $user_roles = ['all'];
+ }
+ $user_roles = array_values(array_unique($user_roles));
+ if (in_array('all', $user_roles, true)) {
+ $user_roles = ['all'];
+ }
+
+ // Validate type
+ if (!in_array($type, ['king_addons_el_hf_type_header', 'king_addons_el_hf_type_footer'], true)) {
+ $type = 'king_addons_el_hf_type_header';
+ }
+
+ // Create the post
+ $post_id = wp_insert_post([
+ 'post_type' => 'king-addons-el-hf',
+ 'post_status' => 'publish',
+ 'post_title' => $title,
+ ]);
+
+ if (is_wp_error($post_id)) {
+ wp_die(esc_html__('Unable to create template.', 'king-addons'));
+ }
+
+ // Save template type immediately
+ update_post_meta($post_id, 'king_addons_el_hf_template_type', $type);
+
+ // Save display conditions
+ $specific_ids = [];
+ if ('specifics' === $display_rule && !empty($display_specific)) {
+ $specific_ids = array_map('intval', array_filter(explode(',', $display_specific)));
+ }
+ $target_locations = [
+ 'rule' => [$display_rule],
+ 'specific' => $specific_ids,
+ ];
+ update_post_meta($post_id, 'king_addons_el_hf_target_include_locations', $target_locations);
+ update_post_meta($post_id, 'king_addons_el_hf_target_exclude_locations', []);
+
+ // Save user roles (multiple)
+ update_post_meta($post_id, 'king_addons_el_hf_target_user_roles', $user_roles);
+
+ // Save canvas display option
+ if ($display_canvas) {
+ update_post_meta($post_id, 'king-addons-el-hf-display-on-canvas', '1');
+ }
+
+ // Redirect to Elementor editor
+ wp_safe_redirect(admin_url('post.php?post=' . $post_id . '&action=elementor'));
+ exit;
+ }
+
+ /**
+ * Handle quick update submission.
+ *
+ * @return void
+ */
+ public function handleQuickUpdate(): void
+ {
+ if (!current_user_can('manage_options')) {
+ wp_die(esc_html__('You do not have permission t