PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.44
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.44
51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 All 40 releases
king-addons / includes / extensions / Header_Footer_Builder / Header_Footer_Builder.php

Header_Footer_Builder.php in King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder 51.1.44, at includes/extensions/Header_Footer_Builder/Header_Footer_Builder.php

1,819 lines 74.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php /** @noinspection PhpMissingFieldTypeInspection, DuplicatedCode */
2
3 namespace King_Addons;
4
5 use Elementor;
6 use WP_Query;
7
8 if (!defined('ABSPATH')) {
9 exit;
10 }
11
12 final class Header_Footer_Builder
13 {
14 private static ?Header_Footer_Builder $instance = null;
15 private static ?string $current_page_type = null;
16 private static array $current_page_data = array();
17 private static $location_selection;
18 private static $user_selection;
19 private static $elementor_instance;
20
21 public static function instance(): ?Header_Footer_Builder
22 {
23 if (is_null(self::$instance)) {
24 self::$instance = new self();
25 }
26 return self::$instance;
27 }
28
29 public function __construct()
30 {
31 add_action('init', [$this, 'addPostType']);
32 add_action('admin_notices', [$this, 'renderNoticeZeroPosts']);
33 add_action('in_admin_header', [$this, 'renderAdminCustomHeader']);
34 add_action('add_meta_boxes', [$this, 'registerMetabox']);
35 add_action('save_post', [$this, 'saveMetaboxData']);
36 add_action('template_redirect', [$this, 'checkUserCanEdit']);
37 add_filter('screen_options_show_screen', [$this, 'disableScreenOptions'], 10, 2);
38
39 require_once(KING_ADDONS_PATH . 'includes/extensions/Header_Footer_Builder/ELHF_Render_On_Canvas.php');
40 add_filter('single_template', [$this, 'loadElementorCanvasTemplate']);
41
42 self::setCompatibility();
43 add_action('admin_enqueue_scripts', array($this, 'enqueueScripts'));
44 add_action('admin_action_edit', array($this, 'initialize_options'));
45 add_action('wp_ajax_king_addons_el_hf_get_posts_by_query', array($this, 'king_addons_el_hf_get_posts_by_query'));
46
47 if (is_admin()) {
48 add_action('manage_king-addons-el-hf_posts_custom_column', [$this, 'columnContent'], 10, 2);
49 add_filter('manage_king-addons-el-hf_posts_columns', [$this, 'columnHeadings']);
50 }
51 }
52
53 /**
54 * Show an admin notice when there are zero "king-addons-el-hf" posts
55 */
56 function renderNoticeZeroPosts()
57 {
58 global $pagenow, $post_type;
59
60 // Check if we are on the "All posts" page for the custom post type
61 if ('edit.php' === $pagenow && 'edit-king-addons-el-hf' === $post_type) {
62
63 // Count published posts of this CPT
64 $count_posts = wp_count_posts('king-addons-el-hf');
65 if ($count_posts->publish == 0) {
66 echo '<div class="notice notice-info is-dismissible">';
67 echo '<p>';
68 echo esc_html__("Create the first header or footer by clicking the 'Create New' button above.", 'king addons');
69 echo '</p>';
70 echo '</div>';
71 }
72 }
73 }
74
75 public function disableScreenOptions($show_screen, $screen)
76 {
77 if ($screen->id === 'edit-king-addons-el-hf') {
78 return false;
79 }
80 return $show_screen;
81 }
82
83 function king_addons_el_hf_get_posts_by_query()
84 {
85 // Security fix: Add authorization check
86 if (!current_user_can('edit_posts')) {
87 wp_send_json_error('Insufficient permissions');
88 return;
89 }
90
91 check_ajax_referer('king-addons-el-hf-get-posts-by-query', 'nonce');
92
93 $search_string = isset($_POST['q']) ? sanitize_text_field($_POST['q']) : '';
94 $result = array();
95
96 $args = array(
97 'public' => true,
98 '_builtin' => false,
99 );
100
101 $output = 'names';
102 $operator = 'and';
103 $post_types = get_post_types($args, $output, $operator);
104
105 unset($post_types['elementor-hf']);
106
107 $post_types['Posts'] = 'post';
108 $post_types['Pages'] = 'page';
109
110 foreach ($post_types as $key => $post_type) {
111 $data = array();
112
113 add_filter('posts_search', array($this, 'search_only_titles'), 10, 2);
114
115 $query = new WP_Query(
116 array(
117 's' => $search_string,
118 'post_type' => $post_type,
119 'posts_per_page' => -1,
120 )
121 );
122
123 if ($query->have_posts()) {
124 while ($query->have_posts()) {
125 $query->the_post();
126 $title = get_the_title();
127 $title .= (0 != $query->post->post_parent) ? ' (' . get_the_title($query->post->post_parent) . ')' : '';
128 $id = get_the_id();
129 $data[] = array(
130 'id' => 'post-' . $id,
131 'text' => $title,
132 );
133 }
134 }
135
136 if (is_array($data) && !empty($data)) {
137 $result[] = array(
138 'text' => $key,
139 'children' => $data,
140 );
141 }
142 }
143
144 wp_reset_postdata();
145
146 $args = array(
147 'public' => true,
148 );
149
150 $output = 'objects';
151 $taxonomies = get_taxonomies($args, $output, $operator);
152
153 foreach ($taxonomies as $taxonomy) {
154 $terms = get_terms(
155 $taxonomy->name,
156 array(
157 'orderby' => 'count',
158 'hide_empty' => 0,
159 'name__like' => $search_string,
160 )
161 );
162
163 $data = array();
164
165 $label = ucwords($taxonomy->label);
166
167 if (!empty($terms)) {
168 foreach ($terms as $term) {
169
170 $data[] = array(
171 'id' => 'tax-' . $term->term_id,
172 'text' => $term->name . ' archive page',
173 );
174
175 $data[] = array(
176 'id' => 'tax-' . $term->term_id . '-single-' . $taxonomy->name,
177 'text' => 'All singulars from ' . $term->name,
178 );
179 }
180 }
181
182 if (is_array($data) && !empty($data)) {
183 $result[] = array(
184 'text' => $label,
185 'children' => $data,
186 );
187 }
188 }
189
190 wp_send_json($result);
191 }
192
193 public function initialize_options()
194 {
195 self::$user_selection = self::get_user_selections();
196 self::$location_selection = self::getLocationSelections();
197 }
198
199 public function renderAdminCustomHeader()
200 {
201 $current_screen = get_current_screen()->id;
202 if ($current_screen !== 'edit-king-addons-el-hf'
203 && $current_screen !== 'header-footer_page_king-addons-el-hf-settings') {
204 return;
205 }
206
207 ?>
208 <div class="king-addons-pb-settings-page-header">
209 <h1><?php esc_html_e('Elementor Header & Footer Builder', 'king-addons'); ?></h1>
210 <p>
211 <?php esc_html_e('Create fully customizable headers and footers with display conditions to control where they appear', 'king-addons'); ?>
212 </p>
213 <div class="king-addons-pb-preview-buttons">
214 <a href="<?php echo admin_url('post-new.php?post_type=king-addons-el-hf'); ?>">
215 <div class="king-addons-pb-user-template">
216 <span><?php esc_html_e('Create New', 'king-addons'); ?></span>
217 <span class="plus-icon">+</span>
218 </div>
219 </a>
220 <?php if (!king_addons_freemius()->can_use_premium_code__premium_only()): ?>
221 <div class="kng-promo-btn-wrap">
222 <a href="https://kingaddons.com/pricing/?utm_source=king-addons-hf-builder" target="_blank">
223 <div class="kng-promo-btn-txt">
224 <?php esc_html_e('Unlock Premium Features & 650+ Templates Today!', 'king-addons'); ?>
225 </div>
226 <img width="16px"
227 src="<?php echo esc_url(KING_ADDONS_URL) . 'includes/admin/img/share-v2.svg'; ?>"
228 alt="<?php echo esc_html__('Open link in the new tab', 'king-addons'); ?>">
229 </a>
230 </div>
231 <?php endif; ?>
232 </div>
233 </div>
234 <?php
235
236 $counts = wp_count_posts('king-addons-el-hf');
237 $total = (int)$counts->publish + (int)$counts->draft;
238
239 if (0 === $total) {
240 echo '<div class="notice notice-info">';
241 echo '<p>';
242 echo esc_html__("Create the first header or footer by clicking the 'Create New' button above.", 'king addons');
243 echo '</p>';
244 echo '</div>';
245 }
246
247 }
248
249 function addPostType(): void
250 {
251 if (!current_user_can('manage_options')) {
252 return;
253 }
254
255 $labels = [
256 'name' => esc_html__('Elementor Header & Footer Builder', 'king-addons'),
257 'singular_name' => esc_html__('Elementor Header & Footer Builder', 'king-addons'),
258 'menu_name' => esc_html__('Elementor Header & Footer Builder', 'king-addons'),
259 'name_admin_bar' => esc_html__('Elementor Header & Footer Builder', 'king-addons'),
260 'add_new' => esc_html__('Add New', 'king-addons'),
261 'add_new_item' => esc_html__('Add New', 'king-addons'),
262 'new_item' => esc_html__('New Template', 'king-addons'),
263 'edit_item' => esc_html__('Edit Template', 'king-addons'),
264 'view_item' => esc_html__('View Template', 'king-addons'),
265 'all_items' => esc_html__('All Templates', 'king-addons'),
266 'search_items' => esc_html__('Search Templates', 'king-addons'),
267 'parent_item_colon' => esc_html__('Parent Templates:', 'king-addons'),
268 'not_found' => esc_html__('No Templates found.', 'king-addons'),
269 'not_found_in_trash' => esc_html__('No Templates found in Trash.', 'king-addons'),
270 ];
271
272 $args = [
273 'labels' => $labels,
274 'public' => true,
275 'show_ui' => true,
276 'show_in_menu' => false,
277 'show_in_nav_menus' => false,
278 'exclude_from_search' => true,
279 'capability_type' => 'post',
280 'hierarchical' => false,
281 'menu_icon' => 'dashicons-editor-kitchensink',
282 'supports' => ['title', 'thumbnail', 'elementor'],
283 'show_in_rest' => true,
284 ];
285
286 register_post_type('king-addons-el-hf', $args);
287
288 if (false === get_option('king_addons_HFB_flushed_rewrite_rules')) {
289 add_option('king_addons_HFB_flushed_rewrite_rules', true);
290 flush_rewrite_rules();
291 }
292 }
293
294 function registerMetabox()
295 {
296 add_meta_box(
297 'king-addons-el-hf-meta-box',
298 esc_html__('Elementor Header & Footer Builder Options', 'king-addons'),
299 [$this, 'renderMetabox'],
300 'king-addons-el-hf',
301 'normal',
302 'high'
303 );
304 }
305
306 function renderMetabox($post)
307 {
308 $values = get_post_custom($post->ID);
309 $template_type = isset($values['king_addons_el_hf_template_type']) ? esc_attr(sanitize_text_field($values['king_addons_el_hf_template_type'][0])) : '';
310 $display_on_canvas = isset($values['king-addons-el-hf-display-on-canvas']);
311
312 wp_nonce_field('king_addons_el_hf_meta_nounce', 'king_addons_el_hf_meta_nounce');
313 ?>
314 <table class="king-addons-el-hf-options-table widefat">
315 <tbody>
316 <tr class="king-addons-el-hf-options-row type-of-template">
317 <td class="king-addons-el-hf-options-row-heading">
318 <label for="king_addons_el_hf_template_type"><strong><?php esc_html_e('Type of Template', 'king-addons'); ?></strong></label>
319 </td>
320 <td class="king-addons-el-hf-options-row-content">
321 <select name="king_addons_el_hf_template_type" id="king_addons_el_hf_template_type">
322 <option value="king_addons_el_hf_not_selected" <?php selected($template_type, ''); ?>><?php esc_html_e('Select Option', 'king-addons'); ?></option>
323 <option value="king_addons_el_hf_type_header" <?php selected($template_type, 'king_addons_el_hf_type_header'); ?>><?php esc_html_e('Header', 'king-addons'); ?></option>
324 <option value="king_addons_el_hf_type_footer" <?php selected($template_type, 'king_addons_el_hf_type_footer'); ?>><?php esc_html_e('Footer', 'king-addons'); ?></option>
325 </select>
326 </td>
327 </tr>
328 <?php
329 $this->display_rules_tab();
330
331 ?>
332 <tr class="king-addons-el-hf-options-row enable-for-canvas">
333 <td class="king-addons-el-hf-options-row-heading">
334 <label for="king-addons-el-hf-display-on-canvas">
335 <strong><?php esc_html_e('Enable Layout for Elementor Canvas Template?', 'king-addons'); ?></strong>
336 </label>
337 <p><?php esc_html_e('Enabling this option will display this layout on pages using Elementor Canvas Template', 'king-addons'); ?></p>
338 </td>
339 <td class="king-addons-el-hf-options-row-content">
340 <input type="checkbox" id="king-addons-el-hf-display-on-canvas"
341 name="king-addons-el-hf-display-on-canvas"
342 value="1" <?php checked($display_on_canvas); ?> />
343 </td>
344 </tr>
345 </tbody>
346 </table>
347 <?php
348 }
349
350
351 public function admin_styles()
352 {
353 wp_enqueue_script('king-addons-el-hf-select2', KING_ADDONS_URL . 'includes/extensions/Header_Footer_Builder/select2.js', array('jquery'), KING_ADDONS_VERSION, true);
354
355 wp_register_script(
356 'king-addons-el-hf-target-rule',
357 KING_ADDONS_URL . 'includes/extensions/Header_Footer_Builder/conditions-target.js',
358 array(
359 'jquery',
360 'king-addons-el-hf-select2',
361 ),
362 KING_ADDONS_VERSION,
363 true
364 );
365
366 wp_enqueue_script('king-addons-el-hf-target-rule');
367
368 wp_register_script(
369 'king-addons-el-hf-user-role',
370 KING_ADDONS_URL . 'includes/extensions/Header_Footer_Builder/conditions-user.js',
371 array(
372 'jquery',
373 ),
374 KING_ADDONS_VERSION,
375 true
376 );
377
378 wp_enqueue_script('king-addons-el-hf-user-role');
379
380 wp_register_style('king-addons-el-hf-select2', KING_ADDONS_URL . 'includes/extensions/Header_Footer_Builder/select2.css', '', KING_ADDONS_VERSION);
381 wp_enqueue_style('king-addons-el-hf-select2');
382 wp_register_style('king-addons-el-hf-target-rule', KING_ADDONS_URL . 'includes/extensions/Header_Footer_Builder/conditions.css', '', KING_ADDONS_VERSION);
383 wp_enqueue_style('king-addons-el-hf-target-rule');
384 wp_enqueue_script('king-addons-el-hf-script', KING_ADDONS_URL . 'includes/extensions/Header_Footer_Builder/admin.js', array('jquery'), KING_ADDONS_VERSION);
385
386 $localize_vars = array(
387 'please_enter' => __('Please enter', 'king-addons'),
388 'please_delete' => __('Please delete', 'king-addons'),
389 'more_char' => __('or more characters', 'king-addons'),
390 'character' => __('character', 'king-addons'),
391 'loading' => __('Loading more results…', 'king-addons'),
392 'only_select' => __('You can only select', 'king-addons'),
393 'item' => __('item', 'king-addons'),
394 'char_s' => __('s', 'king-addons'),
395 'no_result' => __('No results found', 'king-addons'),
396 'searching' => __('Searching…', 'king-addons'),
397 'not_loader' => __('The results could not be loaded.', 'king-addons'),
398 'search' => __('Search pages / post / categories', 'king-addons'),
399 'ajax_nonce' => wp_create_nonce('king-addons-el-hf-get-posts-by-query'),
400 );
401 wp_localize_script('king-addons-el-hf-select2', 'kngRules', $localize_vars);
402
403 }
404
405 public function display_rules_tab()
406 {
407 $this->admin_styles();
408 $include_locations = get_post_meta(get_the_id(), 'king_addons_el_hf_target_include_locations', true);
409 $exclude_locations = get_post_meta(get_the_id(), 'king_addons_el_hf_target_exclude_locations', true);
410 $users = get_post_meta(get_the_id(), 'king_addons_el_hf_target_user_roles', true);
411 ?>
412 <tr class="king-addons-el-hf-target-rules-row king-addons-el-hf-options-row">
413 <td class="king-addons-el-hf-target-rules-row-heading king-addons-el-hf-options-row-heading">
414 <label><strong><?php esc_html_e('Display On', 'king-addons'); ?></strong></label>
415 <p><?php esc_html_e('Add locations for where this template should appear', 'king-addons'); ?></p>
416 </td>
417 <td class="king-addons-el-hf-target-rules-row-content king-addons-el-hf-options-row-content">
418 <?php
419 self::target_rule_settings_field(
420 'king-addons-el-hf-target-rules-location',
421 [
422 'title' => __('Display Rules', 'king-addons'),
423 'value' => '[{"type":"basic-global","specific":null}]',
424 'tags' => 'site,enable,target,pages',
425 'rule_type' => 'display',
426 'add_rule_label' => __('Add Display Rule', 'king-addons'),
427 ],
428 $include_locations
429 );
430 ?>
431 </td>
432 </tr>
433 <tr class="king-addons-el-hf-target-rules-row king-addons-el-hf-options-row">
434 <td class="king-addons-el-hf-target-rules-row-heading king-addons-el-hf-options-row-heading">
435 <label><strong><?php esc_html_e('Do Not Display On', 'king-addons'); ?></strong></label>
436 <p><?php esc_html_e('Add locations for where this template should not appear', 'king-addons'); ?></p>
437 </td>
438 <td class="king-addons-el-hf-target-rules-row-content king-addons-el-hf-options-row-content">
439 <?php
440 self::target_rule_settings_field(
441 'king-addons-el-hf-target-rules-exclusion',
442 [
443 'title' => __('Exclude On', 'king-addons'),
444 'value' => '[]',
445 'tags' => 'site,enable,target,pages',
446 'add_rule_label' => __('Add Exclusion Rule', 'king-addons'),
447 'rule_type' => 'exclude',
448 ],
449 $exclude_locations
450 );
451 ?>
452 </td>
453 </tr>
454 <tr class="king-addons-el-hf-target-rules-row king-addons-el-hf-options-row">
455 <td class="king-addons-el-hf-target-rules-row-heading king-addons-el-hf-options-row-heading">
456 <label><strong><?php esc_html_e('User Roles', 'king-addons'); ?></strong></label>
457 <p><?php esc_html_e('Display custom template based on user role', 'king-addons'); ?></p>
458 </td>
459 <td class="king-addons-el-hf-target-rules-row-content king-addons-el-hf-options-row-content">
460 <?php
461 self::target_user_role_settings_field(
462 'king-addons-el-hf-target-rules-users',
463 [
464 'title' => __('Users', 'king-addons'),
465 'value' => '[]',
466 'tags' => 'site,enable,target,pages',
467 'add_rule_label' => __('Add User Rule', 'king-addons'),
468 ],
469 $users
470 );
471 ?>
472 </td>
473 </tr>
474 <?php
475 }
476
477 public static function get_user_selections()
478 {
479 $selection_options = array(
480 'basic' => array(
481 'label' => __('Basic', 'king-addons'),
482 'value' => array(
483 'all' => __('All', 'king-addons'),
484 'logged-in' => __('Logged In', 'king-addons'),
485 'logged-out' => __('Logged Out', 'king-addons'),
486 ),
487 ),
488
489 'advanced' => array(
490 'label' => __('Advanced', 'king-addons'),
491 'value' => array(),
492 ),
493 );
494
495 /* User roles */
496 $roles = get_editable_roles();
497
498 foreach ($roles as $slug => $data) {
499 $selection_options['advanced']['value'][$slug] = $data['name'];
500 }
501
502 /**
503 * Filter options displayed in the user select field of Display conditions.
504 *
505 * @since 1.5.0
506 */
507 return apply_filters('king-addons-el-hf_user_roles_list', $selection_options);
508 }
509
510 public static function target_user_role_settings_field($name, $settings, $value)
511 {
512 $input_name = $name;
513 $add_rule_label = $settings['add_rule_label'] ?? __('Add Rule', 'king-addons');
514 $saved_values = $value;
515 $output = '';
516
517 if (!isset(self::$user_selection) || empty(self::$user_selection)) {
518 self::$user_selection = self::get_user_selections();
519 }
520 $selection_options = self::$user_selection;
521
522 $output .= '<script type="text/html" id="tmpl-king-addons-el-hf-user-role-condition">';
523 $output .= '<div class="king-addons-el-hf-user-role-condition king-addons-el-hf-user-role-{{data.id}}" data-rule="{{data.id}}" >';
524 $output .= '<span class="user_role-condition-delete dashicons dashicons-dismiss"></span>';
525
526 $output .= '<div class="user_role-condition-wrap" >';
527 $output .= '<select name="' . esc_attr($input_name) . '[{{data.id}}]" class="user_role-condition form-control king-addons-el-hf-input">';
528 $output .= '<option value="">' . __('Select', 'king-addons') . '</option>';
529
530 foreach ($selection_options as $group_data) {
531 $output .= '<optgroup label="' . $group_data['label'] . '">';
532 foreach ($group_data['value'] as $opt_key => $opt_value) {
533 $output .= '<option value="' . $opt_key . '">' . $opt_value . '</option>';
534 }
535 $output .= '</optgroup>';
536 }
537 $output .= '</select>';
538 $output .= '</div>';
539 $output .= '</div> <!-- king-addons-el-hf-user-role-condition -->';
540 $output .= '</script>';
541
542 /** @noinspection PhpConditionAlreadyCheckedInspection */
543 if (!is_array($saved_values) || (is_array($saved_values) && empty($saved_values))) {
544 $saved_values = array();
545 $saved_values[0] = '';
546 }
547
548 $index = 0;
549
550 $output .= '<div class="king-addons-el-hf-user-role-wrapper king-addons-el-hf-user-role-display-on-wrap" data-type="display">';
551 $output .= '<div class="king-addons-el-hf-user-role-selector-wrapper king-addons-el-hf-user-role-display-on">';
552 $output .= '<div class="user_role-builder-wrap">';
553 foreach ($saved_values as $index => $data) {
554 $output .= '<div class="king-addons-el-hf-user-role-condition king-addons-el-hf-user-role-' . $index . '" data-rule="' . $index . '" >';
555 $output .= '<span class="user_role-condition-delete dashicons dashicons-dismiss"></span>';
556 /* Condition Selection */
557 $output .= '<div class="user_role-condition-wrap" >';
558 $output .= '<select name="' . esc_attr($input_name) . '[' . $index . ']" class="user_role-condition form-control king-addons-el-hf-input">';
559 $output .= '<option value="">' . __('Select', 'king-addons') . '</option>';
560
561 foreach ($selection_options as $group_data) {
562 $output .= '<optgroup label="' . $group_data['label'] . '">';
563 foreach ($group_data['value'] as $opt_key => $opt_value) {
564 $output .= '<option value="' . $opt_key . '" ' . selected($data, $opt_key, false) . '>' . $opt_value . '</option>';
565 }
566 $output .= '</optgroup>';
567 }
568 $output .= '</select>';
569 $output .= '</div>';
570 $output .= '</div> <!-- king-addons-el-hf-user-role-condition -->';
571 }
572 $output .= '</div>';
573 /* Add new rule */
574 $output .= '<div class="user_role-add-rule-wrap">';
575 $output .= '<a href="#" class="button" data-rule-id="' . absint($index) . '">' . $add_rule_label . '</a>';
576 $output .= '</div>';
577 $output .= '</div>';
578 $output .= '</div>';
579
580 echo $output;
581 }
582
583 public static function target_rule_settings_field($name, $settings, $value)
584 {
585 $input_name = $name;
586 $rule_type = $settings['rule_type'] ?? 'target_rule';
587 $add_rule_label = $settings['add_rule_label'] ?? __('Add Rule', 'king-addons');
588 $saved_values = $value;
589 $output = '';
590
591 if (isset(self::$location_selection) || empty(self::$location_selection)) {
592 self::$location_selection = self::getLocationSelections();
593 }
594 $selection_options = self::$location_selection;
595
596 $output .= '<script type="text/html" id="tmpl-king-addons-el-hf-target-rule-' . $rule_type . '-condition">';
597
598 $output .= '<div class="king-addons-el-hf-target-rule-condition king-addons-el-hf-target-rule-{{data.id}}" data-rule="{{data.id}}" >';
599 $output .= '<span class="target_rule-condition-delete dashicons dashicons-dismiss"></span>';
600 $output .= '<div class="target_rule-condition-wrap" >';
601
602 $output .= '<select name="' . esc_attr($input_name) . '[rule][{{data.id}}]" class="target_rule-condition form-control king-addons-el-hf-input">';
603 $output .= '<option value="">' . __('Select', 'king-addons') . '</option>';
604
605 foreach ($selection_options as $group_data) {
606 $output .= '<optgroup label="' . $group_data['label'] . '">';
607 foreach ($group_data['value'] as $opt_key => $opt_value) {
608 $output .= '<option value="' . $opt_key . '">' . $opt_value . '</option>';
609 }
610 $output .= '</optgroup>';
611 }
612 $output .= '</select>';
613
614 $output .= '</div>';
615 $output .= '</div> <!-- king-addons-el-hf-target-rule-condition -->';
616
617 $output .= '<div class="target_rule-specific-page-wrap" style="display:none">';
618 $output .= '<select name="' . esc_attr($input_name) . '[specific][]" class="target-rule-select2 target_rule-specific-page form-control king-addons-el-hf-input " multiple="multiple">';
619 $output .= '</select>';
620 $output .= '</div>';
621
622 $output .= '</script>';
623
624 $output .= '<div class="king-addons-el-hf-target-rule-wrapper king-addons-el-hf-target-rule-' . $rule_type . '-on-wrap" data-type="' . $rule_type . '">';
625 $output .= '<div class="king-addons-el-hf-target-rule-selector-wrapper king-addons-el-hf-target-rule-' . $rule_type . '-on">';
626 $output .= self::generate_target_rule_selector($rule_type, $selection_options, $input_name, $saved_values, $add_rule_label);
627 $output .= '</div>';
628 $output .= '</div>';
629
630 echo $output;
631 }
632
633 public static function generate_target_rule_selector($type, $selection_options, $input_name, $saved_values, $add_rule_label)
634 {
635 $output = '<div class="target_rule-builder-wrap">';
636
637 /** @noinspection PhpConditionAlreadyCheckedInspection */
638 if (!is_array($saved_values) || (is_array($saved_values) && empty($saved_values))) {
639 $saved_values = array();
640 $saved_values['rule'][0] = '';
641 $saved_values['specific'][0] = '';
642 }
643
644 $index = 0;
645 if (is_array($saved_values) && is_array($saved_values['rule'])) {
646 foreach ($saved_values['rule'] as $index => $data) {
647 $output .= '<div class="king-addons-el-hf-target-rule-condition king-addons-el-hf-target-rule-' . $index . '" data-rule="' . $index . '" >';
648
649 $output .= '<span class="target_rule-condition-delete dashicons dashicons-dismiss"></span>';
650 $output .= '<div class="target_rule-condition-wrap" >';
651 $output .= '<select name="' . esc_attr($input_name) . '[rule][' . $index . ']" class="target_rule-condition form-control king-addons-el-hf-input">';
652 $output .= '<option value="">' . __('Select', 'king-addons') . '</option>';
653
654 foreach ($selection_options as $group_data) {
655 $output .= '<optgroup label="' . $group_data['label'] . '">';
656 foreach ($group_data['value'] as $opt_key => $opt_value) {
657
658 $selected = '';
659
660 if ($data == $opt_key) {
661 $selected = 'selected="selected"';
662 }
663
664 $output .= '<option value="' . $opt_key . '" ' . $selected . '>' . $opt_value . '</option>';
665 }
666 $output .= '</optgroup>';
667 }
668 $output .= '</select>';
669 $output .= '</div>';
670
671 $output .= '</div>';
672
673 $output .= '<div class="target_rule-specific-page-wrap" style="display:none">';
674 $output .= '<select name="' . esc_attr($input_name) . '[specific][]" class="target-rule-select2 target_rule-specific-page form-control king-addons-el-hf-input " multiple="multiple">';
675
676 if ('specifics' == $data && isset($saved_values['specific']) && null != $saved_values['specific'] && is_array($saved_values['specific'])) {
677 foreach ($saved_values['specific'] as $sel_value) {
678
679 if (strpos($sel_value, 'post-') !== false) {
680 $post_id = (int)str_replace('post-', '', $sel_value);
681 $post_title = get_the_title($post_id);
682 $output .= '<option value="post-' . $post_id . '" selected="selected" >' . $post_title . '</option>';
683 }
684
685 if (strpos($sel_value, 'tax-') !== false) {
686 $tax_data = explode('-', $sel_value);
687
688 $tax_id = (int)str_replace('tax-', '', $sel_value);
689 $term = get_term($tax_id);
690 $term_name = '';
691
692 if (!is_wp_error($term)) {
693 $term_taxonomy = ucfirst(str_replace('_', ' ', $term->taxonomy));
694
695 if (isset($tax_data[2]) && 'single' === $tax_data[2]) {
696 $term_name = 'All singulars from ' . $term->name;
697 } else {
698 $term_name = $term->name . ' - ' . $term_taxonomy;
699 }
700 }
701
702 $output .= '<option value="' . $sel_value . '" selected="selected" >' . $term_name . '</option>';
703 }
704 }
705 }
706 $output .= '</select>';
707 $output .= '</div>';
708 }
709 }
710
711 $output .= '</div>';
712
713 $output .= '<div class="target_rule-add-rule-wrap">';
714 $output .= '<a href="#" class="button" data-rule-id="' . absint($index) . '" data-rule-type="' . $type . '">' . $add_rule_label . '</a>';
715 $output .= '</div>';
716
717 if ('display' == $type) {
718 $output .= '<div class="target_rule-add-exclusion-rule">';
719 $output .= '<a href="#" class="button">' . __('Add Exclusion Rule', 'king-addons') . '</a>';
720 $output .= '</div>';
721 }
722
723 return $output;
724 }
725
726 function saveMetaboxData($post_id)
727 {
728 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
729 return;
730 }
731
732 if (!isset($_POST['king_addons_el_hf_meta_nounce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['king_addons_el_hf_meta_nounce'])), 'king_addons_el_hf_meta_nounce')) {
733 return;
734 }
735
736 if (!current_user_can('edit_posts')) {
737 return;
738 }
739
740 if (!isset($_POST['king-addons-el-hf-target-rules-location'])) {
741 $target_locations = array(
742 'rule' => array('basic-global'),
743 'specific' => array(),
744 );
745 } else {
746 $target_locations = self::getFormatRuleValue($_POST, 'king-addons-el-hf-target-rules-location');
747 if (empty($target_locations)) {
748 $target_locations = array(
749 'rule' => array('basic-global'),
750 'specific' => array(),
751 );
752 }
753 }
754
755 $target_exclusion = self::getFormatRuleValue($_POST, 'king-addons-el-hf-target-rules-exclusion');
756 $target_users = [];
757
758 if (isset($_POST['king-addons-el-hf-target-rules-users'])) {
759 $target_users = array_map('sanitize_text_field', wp_unslash($_POST['king-addons-el-hf-target-rules-users']));
760 }
761
762 update_post_meta($post_id, 'king_addons_el_hf_target_include_locations', $target_locations);
763 update_post_meta($post_id, 'king_addons_el_hf_target_exclude_locations', $target_exclusion);
764 update_post_meta($post_id, 'king_addons_el_hf_target_user_roles', $target_users);
765
766 if (isset($_POST['king_addons_el_hf_template_type'])) {
767 update_post_meta($post_id, 'king_addons_el_hf_template_type', sanitize_text_field(wp_unslash($_POST['king_addons_el_hf_template_type'])));
768 }
769
770 if (isset($_POST['king-addons-el-hf-display-on-canvas'])) {
771 update_post_meta($post_id, 'king-addons-el-hf-display-on-canvas', sanitize_text_field(wp_unslash($_POST['king-addons-el-hf-display-on-canvas'])));
772 } else {
773 delete_post_meta($post_id, 'king-addons-el-hf-display-on-canvas');
774 }
775 }
776
777 function setCompatibility()
778 {
779 $template = get_template();
780 $is_elementor_callable = defined('ELEMENTOR_VERSION') && is_callable('Elementor\Plugin::instance');
781
782 if ($is_elementor_callable) {
783 self::$elementor_instance = Elementor\Plugin::instance();
784
785 // TODO: Add popular themes
786 switch ($template) {
787 case 'hello-elementor':
788 require_once(KING_ADDONS_PATH . 'includes/extensions/Header_Footer_Builder/themes/hello-elementor/ELHF_Hello_Elementor.php');
789 break;
790 default:
791 add_action('init', [$this, 'setupSettingsPage']);
792 add_filter('king_addons_el_hf_settings_tabs', [$this, 'setupUnsupportedTheme']);
793 add_action('init', [$this, 'setupFallbackSupport']);
794 break;
795 }
796 }
797 }
798
799 public function setupUnsupportedTheme($settings_tabs = [])
800 {
801 if (!current_theme_supports('king-addons-elementor-header-footer')) {
802 $settings_tabs['king_addons_el_hf_settings'] = [
803 'name' => esc_html__('Display Settings', 'king-addons'),
804 'url' => admin_url('edit.php?post_type=king-addons-el-hf&page=king-addons-el-hf-settings'),
805 ];
806 }
807 return $settings_tabs;
808 }
809
810 public function setupFallbackSupport()
811 {
812 if (!current_theme_supports('king-addons-elementor-header-footer')) {
813 $compatibility_option = get_option('king_addons_el_hf_compatibility_option', '1');
814
815 if ('1' === $compatibility_option) {
816 if (!class_exists('ELHF_Default_Method_1')) {
817 require_once(KING_ADDONS_PATH . 'includes/extensions/Header_Footer_Builder/themes/default/ELHF_Default_Method_1.php');
818 }
819 } elseif ('2' === $compatibility_option) {
820 if (!class_exists('ELHF_Default_Method_2')) {
821 require_once(KING_ADDONS_PATH . 'includes/extensions/Header_Footer_Builder/themes/default/ELHF_Default_Method_2.php');
822 }
823 }
824 }
825 }
826
827 function setupSettingsPage()
828 {
829 require_once(KING_ADDONS_PATH . 'includes/extensions/Header_Footer_Builder/ELHF_Settings_Page.php');
830 }
831
832 public static function renderHeader()
833 {
834 /** @noinspection SpellCheckingInspection */
835 echo '<header id="masthead" itemscope="itemscope" itemtype="https://schema.org/WPHeader">';
836 ?><p class="main-title" style="display: none;" itemprop="headline"><a
837 href="<?php echo esc_url(get_bloginfo('url')); ?>"
838 title="<?php echo esc_attr(get_bloginfo('name', 'display')); ?>"
839 rel="home"><?php echo esc_html(get_bloginfo('name')); ?></a></p><?php
840 self::getHeaderContent();
841 echo '</header>';
842 }
843
844 public static function renderFooter()
845 {
846 /** @noinspection SpellCheckingInspection */
847 echo '<footer id="colophon" itemscope="itemscope" itemtype="https://schema.org/WPFooter" role="contentinfo">';
848 self::getFooterContent();
849 echo '</footer>';
850 }
851
852 public static function getHeaderContent()
853 {
854 $header_id = self::getHeaderID();
855 if ($header_id) {
856 echo self::$elementor_instance->frontend->get_builder_content_for_display($header_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
857 }
858 }
859
860 public static function getFooterContent()
861 {
862 $footer_id = self::getFooterID();
863 if ($footer_id) {
864 echo '<div style="width: 100%;">';
865 echo self::$elementor_instance->frontend->get_builder_content_for_display($footer_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
866 echo '</div>';
867 }
868 }
869
870 public static function getHeaderID()
871 {
872 $header_id = self::getSettings('king_addons_el_hf_type_header');
873
874 if ('' === $header_id) {
875 $header_id = false;
876 }
877
878 return apply_filters('king_addons_el_hf_get_header_id', $header_id);
879 }
880
881 public static function isHeaderEnabled()
882 {
883 $header_id = self::getSettings('king_addons_el_hf_type_header');
884 $status = false;
885
886 if ('' !== $header_id) {
887 $status = true;
888 }
889
890 return apply_filters('king_addons_el_hf_header_enabled', $status);
891 }
892
893 public static function isFooterEnabled()
894 {
895 $footer_id = self::getSettings('king_addons_el_hf_type_footer');
896 $status = false;
897
898 if ('' !== $footer_id) {
899 $status = true;
900 }
901
902 return apply_filters('king_addons_el_hf_footer_enabled', $status);
903 }
904
905 public static function getFooterID()
906 {
907 $footer_id = self::getSettings('king_addons_el_hf_type_footer');
908
909 if ('' === $footer_id) {
910 $footer_id = false;
911 }
912
913 return apply_filters('king_addons_el_hf_get_footer_id', $footer_id);
914 }
915
916
917 public static function getSettings($setting = '')
918 {
919 if ('king_addons_el_hf_type_header' == $setting || 'king_addons_el_hf_type_footer' == $setting) {
920 $templates = self::getTemplateID($setting);
921 $template = !is_array($templates) ? $templates : $templates[0];
922 return apply_filters("king_addons_el_hf_get_settings_$setting", $template);
923 }
924
925 return null;
926 }
927
928 public static function getTemplateID($type)
929 {
930 $option = [
931 'location' => 'king_addons_el_hf_target_include_locations',
932 'exclusion' => 'king_addons_el_hf_target_exclude_locations',
933 'users' => 'king_addons_el_hf_target_user_roles',
934 ];
935
936 $templates = self::getPostsByConditions('king-addons-el-hf', $option);
937
938 // Prime meta cache to avoid N+1 queries when calling get_post_meta in loops below.
939 // getPostsByConditions() may already have populated template IDs; caching is safe and cheap.
940 if (!empty($templates)) {
941 $template_ids = array_map(static function ($template) {
942 return isset($template['id']) ? absint($template['id']) : 0;
943 }, $templates);
944 $template_ids = array_values(array_filter($template_ids));
945 if (!empty($template_ids)) {
946 update_meta_cache('post', $template_ids);
947 }
948 }
949
950 foreach ($templates as $template) {
951 if (get_post_meta(absint($template['id']), 'king_addons_el_hf_template_type', true) === $type) {
952 // Polylang check - https://polylang.pro/doc/function-reference/
953 if (function_exists('pll_current_language')) {
954 if (pll_current_language('slug') == pll_get_post_language($template['id'], 'slug')) {
955 return $template['id'];
956 }
957 } else {
958 return $template['id'];
959 }
960 }
961 }
962
963 return '';
964 }
965
966 public static function getPostsByConditions($post_type, $option)
967 {
968 global $wpdb;
969 global $post;
970
971 // Security fix: Validate and sanitize post_type
972 $post_type = $post_type ? sanitize_key($post_type) : sanitize_key($post->post_type);
973 if (empty($post_type)) {
974 return [];
975 }
976
977 if (is_array(self::$current_page_data) && isset(self::$current_page_data[$post_type])) {
978 return apply_filters('king_addons_el_hf_get_display_posts_by_conditions', self::$current_page_data[$post_type], $post_type);
979 }
980
981 $current_page_type = self::getCurrentPageType();
982
983 self::$current_page_data[$post_type] = array();
984
985 $option['current_post_id'] = self::$current_page_data['ID'];
986 $meta_header = self::getMetaOptionPost($post_type, $option);
987
988 if (false === $meta_header) {
989 $current_post_type = sanitize_key(get_post_type());
990 $current_post_id = false;
991 $q_obj = get_queried_object();
992
993 $current_id = absint(get_the_id());
994
995 // Check if WPML is active. Find WPML Object ID for current page.
996 /** @noinspection SpellCheckingInspection */
997 if (defined('ICL_SITEPRESS_VERSION')) {
998 $default_lang = apply_filters('wpml_default_language', '');
999 $current_lang = apply_filters('wpml_current_language', '');
1000
1001 if ($default_lang !== $current_lang) {
1002 $current_post_type = get_post_type($current_id);
1003 $current_id = apply_filters('wpml_object_id', $current_id, $current_post_type, true, $default_lang);
1004 }
1005 }
1006
1007 // Security fix: Sanitize location parameter
1008 $location = isset($option['location']) ? sanitize_key($option['location']) : '';
1009 if (empty($location)) {
1010 return [];
1011 }
1012
1013 // Security fix: Use prepared statement to prevent SQL injection
1014 $query = $wpdb->prepare(
1015 "SELECT p.ID, pm.meta_value FROM {$wpdb->postmeta} as pm
1016 INNER JOIN {$wpdb->posts} as p ON pm.post_id = p.ID
1017 WHERE pm.meta_key = %s
1018 AND p.post_type = %s
1019 AND p.post_status = 'publish'",
1020 $location,
1021 $post_type
1022 );
1023
1024 $orderby = ' ORDER BY p.post_date DESC';
1025
1026 // Security fix: Build meta_args using safe placeholders and prepared statements
1027 $meta_conditions = ["pm.meta_value LIKE %s"];
1028 $meta_values = ['%"basic-global"%'];
1029
1030 switch ($current_page_type) {
1031 case 'is_404':
1032 $meta_conditions[] = "pm.meta_value LIKE %s";
1033 $meta_values[] = '%"special-404"%';
1034 break;
1035 case 'is_search':
1036 $meta_conditions[] = "pm.meta_value LIKE %s";
1037 $meta_values[] = '%"special-search"%';
1038 break;
1039 case 'is_archive':
1040 case 'is_tax':
1041 case 'is_date':
1042 case 'is_author':
1043 $meta_conditions[] = "pm.meta_value LIKE %s";
1044 $meta_values[] = '%"basic-archives"%';
1045 $meta_conditions[] = "pm.meta_value LIKE %s";
1046 $meta_values[] = '%"' . sanitize_key($current_post_type) . '|all|archive"%';
1047
1048 if ('is_tax' == $current_page_type && (is_category() || is_tag() || is_tax())) {
1049 if (is_object($q_obj) && isset($q_obj->taxonomy) && isset($q_obj->term_id)) {
1050 $meta_conditions[] = "pm.meta_value LIKE %s";
1051 $meta_values[] = '%"' . sanitize_key($current_post_type) . '|all|taxarchive|' . sanitize_key($q_obj->taxonomy) . '"%';
1052 $meta_conditions[] = "pm.meta_value LIKE %s";
1053 $meta_values[] = '%"tax-' . absint($q_obj->term_id) . '"%';
1054 }
1055 } elseif ('is_date' == $current_page_type) {
1056 $meta_conditions[] = "pm.meta_value LIKE %s";
1057 $meta_values[] = '%"special-date"%';
1058 } elseif ('is_author' == $current_page_type) {
1059 $meta_conditions[] = "pm.meta_value LIKE %s";
1060 $meta_values[] = '%"special-author"%';
1061 }
1062 break;
1063 case 'is_home':
1064 $meta_conditions[] = "pm.meta_value LIKE %s";
1065 $meta_values[] = '%"special-blog"%';
1066 break;
1067 case 'is_front_page':
1068 $current_post_id = $current_id;
1069 $meta_conditions[] = "pm.meta_value LIKE %s";
1070 $meta_values[] = '%"special-front"%';
1071 $meta_conditions[] = "pm.meta_value LIKE %s";
1072 $meta_values[] = '%"' . sanitize_key($current_post_type) . '|all"%';
1073 $meta_conditions[] = "pm.meta_value LIKE %s";
1074 $meta_values[] = '%"post-' . absint($current_id) . '"%';
1075 break;
1076 case 'is_singular':
1077 $current_post_id = $current_id;
1078 $meta_conditions[] = "pm.meta_value LIKE %s";
1079 $meta_values[] = '%"basic-singulars"%';
1080 $meta_conditions[] = "pm.meta_value LIKE %s";
1081 $meta_values[] = '%"' . sanitize_key($current_post_type) . '|all"%';
1082 $meta_conditions[] = "pm.meta_value LIKE %s";
1083 $meta_values[] = '%"post-' . absint($current_id) . '"%';
1084
1085 if (is_object($q_obj) && isset($q_obj->post_type) && isset($q_obj->ID)) {
1086 $taxonomies = get_object_taxonomies($q_obj->post_type);
1087 $terms = wp_get_post_terms($q_obj->ID, $taxonomies);
1088 foreach ($terms as $term) {
1089 if (isset($term->term_id) && isset($term->taxonomy)) {
1090 $meta_conditions[] = "pm.meta_value LIKE %s";
1091 $meta_values[] = '%"tax-' . absint($term->term_id) . '-single-' . sanitize_key($term->taxonomy) . '"%';
1092 }
1093 }
1094 }
1095 break;
1096 case 'is_woo_shop_page':
1097 if (function_exists('is_shop')) {
1098 $meta_conditions[] = "pm.meta_value LIKE %s";
1099 $meta_values[] = '%"special-woocommerce-shop"%';
1100 }
1101 break;
1102 case '':
1103 $current_post_id = $current_id;
1104 break;
1105 }
1106
1107 // Build the final meta_args string using prepare
1108 $meta_args = '(' . implode(' OR ', $meta_conditions) . ')';
1109
1110 // Security fix: Use prepared statement for the complete query
1111 $full_query = $wpdb->prepare(
1112 $query . ' AND ' . $meta_args . $orderby,
1113 ...$meta_values
1114 );
1115
1116 $posts = $wpdb->get_results($full_query);
1117
1118 foreach ($posts as $local_post) {
1119 $unserialized_location = maybe_unserialize($local_post->meta_value);
1120 if ($unserialized_location !== false) {
1121 self::$current_page_data[$post_type][$local_post->ID] = array(
1122 'id' => $local_post->ID,
1123 'location' => $unserialized_location,
1124 );
1125 }
1126 }
1127
1128 // Prime meta cache for all candidate templates to avoid repeated get_post_meta queries
1129 // in removeExclusionRulePosts/removeUserRulePosts and getTemplateID.
1130 if (!empty(self::$current_page_data[$post_type])) {
1131 $candidate_ids = array_map('absint', array_keys(self::$current_page_data[$post_type]));
1132 $candidate_ids = array_values(array_filter($candidate_ids));
1133 if (!empty($candidate_ids)) {
1134 update_meta_cache('post', $candidate_ids);
1135 }
1136 }
1137
1138 $option['current_post_id'] = $current_post_id;
1139
1140 self::removeExclusionRulePosts($post_type, $option);
1141 self::removeUserRulePosts($post_type, $option);
1142 }
1143
1144 return apply_filters('king_addons_el_hf_get_display_posts_by_conditions', self::$current_page_data[$post_type], $post_type);
1145 }
1146
1147 public static function getCurrentPageType(): ?string
1148 {
1149 if (null === self::$current_page_type) {
1150 $page_type = '';
1151 $current_id = false;
1152
1153 if (is_404()) {
1154 $page_type = 'is_404';
1155 } elseif (is_search()) {
1156 $page_type = 'is_search';
1157 } elseif (is_archive()) {
1158 $page_type = 'is_archive';
1159 if (is_category() || is_tag() || is_tax()) {
1160 $page_type = 'is_tax';
1161 } elseif (is_date()) {
1162 $page_type = 'is_date';
1163 } elseif (is_author()) {
1164 $page_type = 'is_author';
1165 } elseif (function_exists('is_shop')) {
1166 /** @noinspection PhpUndefinedFunctionInspection */
1167 if (is_shop()) {
1168 $page_type = 'is_woo_shop_page';
1169 }
1170 }
1171 } elseif (is_home()) {
1172 $page_type = 'is_home';
1173 } elseif (is_front_page()) {
1174 $page_type = 'is_front_page';
1175 $current_id = get_the_id();
1176 } elseif (is_singular()) {
1177 $page_type = 'is_singular';
1178 $current_id = get_the_id();
1179 } else {
1180 $current_id = get_the_id();
1181 }
1182
1183 self::$current_page_data['ID'] = $current_id;
1184 self::$current_page_type = $page_type;
1185 }
1186
1187 return self::$current_page_type;
1188 }
1189
1190 public static function getMetaOptionPost($post_type, $option)
1191 {
1192 $page_meta = (isset($option['page_meta']) && '' != $option['page_meta']) ? $option['page_meta'] : false;
1193
1194 if (false !== $page_meta) {
1195 $current_post_id = $option['current_post_id'] ?? false;
1196 $meta_id = get_post_meta($current_post_id, $option['page_meta'], true);
1197
1198 if (false !== $meta_id && '' != $meta_id) {
1199 self::$current_page_data[$post_type][$meta_id] = array(
1200 'id' => $meta_id,
1201 'location' => '',
1202 );
1203
1204 return self::$current_page_data[$post_type];
1205 }
1206 }
1207
1208 return false;
1209 }
1210
1211 public static function removeExclusionRulePosts($post_type, $option)
1212 {
1213 $exclusion = $option['exclusion'] ?? '';
1214 $current_post_id = $option['current_post_id'] ?? false;
1215 foreach (self::$current_page_data[$post_type] as $c_post_id => $c_data) {
1216 $exclusion_rules = get_post_meta($c_post_id, $exclusion, true);
1217 $is_exclude = self::parseLayoutDisplayCondition($current_post_id, $exclusion_rules);
1218 if ($is_exclude) {
1219 unset(self::$current_page_data[$post_type][$c_post_id]);
1220 }
1221 }
1222 }
1223
1224 public static function removeUserRulePosts($post_type, $option)
1225 {
1226 $users = $option['users'] ?? '';
1227
1228 foreach (self::$current_page_data[$post_type] as $c_post_id => $c_data) {
1229 $user_rules = get_post_meta($c_post_id, $users, true);
1230 $is_user = self::parseUserRoleCondition($user_rules);
1231
1232 if (!$is_user) {
1233 unset(self::$current_page_data[$post_type][$c_post_id]);
1234 }
1235 }
1236 }
1237
1238 public static function parseLayoutDisplayCondition($post_id, $rules): bool
1239 {
1240 $display = false;
1241
1242 /** @noinspection PhpConditionCheckedByNextConditionInspection */
1243 if (isset($rules['rule']) && is_array($rules['rule']) && !empty($rules['rule'])) {
1244 foreach ($rules['rule'] as $rule) {
1245 if (strrpos($rule, 'all') !== false) {
1246 $rule_case = 'all';
1247 } else {
1248 $rule_case = $rule;
1249 }
1250
1251 switch ($rule_case) {
1252 case 'basic-global':
1253 $display = true;
1254 break;
1255
1256 case 'basic-singulars':
1257 if (is_singular()) {
1258 $display = true;
1259 }
1260 break;
1261
1262 case 'basic-archives':
1263 if (is_archive()) {
1264 $display = true;
1265 }
1266 break;
1267
1268 case 'special-404':
1269 if (is_404()) {
1270 $display = true;
1271 }
1272 break;
1273
1274 case 'special-search':
1275 if (is_search()) {
1276 $display = true;
1277 }
1278 break;
1279
1280 case 'special-blog':
1281 if (is_home()) {
1282 $display = true;
1283 }
1284 break;
1285
1286 case 'special-front':
1287 if (is_front_page()) {
1288 $display = true;
1289 }
1290 break;
1291
1292 case 'special-date':
1293 if (is_date()) {
1294 $display = true;
1295 }
1296 break;
1297
1298 case 'special-author':
1299 if (is_author()) {
1300 $display = true;
1301 }
1302 break;
1303
1304 case 'special-woocommerce-shop':
1305 if (function_exists('is_shop')) {
1306 if (is_shop()) {
1307 $display = true;
1308 }
1309 }
1310 break;
1311
1312 case 'all':
1313 $rule_data = explode('|', $rule);
1314
1315 $post_type = $rule_data[0] ?? false;
1316 $archive_type = $rule_data[2] ?? false;
1317 $taxonomy = $rule_data[3] ?? false;
1318 if (false === $archive_type) {
1319 $current_post_type = get_post_type($post_id);
1320 if (false !== $post_id && $current_post_type == $post_type) {
1321 $display = true;
1322 }
1323 } else {
1324 if (is_archive()) {
1325 $current_post_type = get_post_type();
1326 if ($current_post_type == $post_type) {
1327 if ('archive' == $archive_type) {
1328 $display = true;
1329 } elseif ('taxarchive' == $archive_type) {
1330 $obj = get_queried_object();
1331 $current_taxonomy = '';
1332 if ('' !== $obj && null !== $obj) {
1333 $current_taxonomy = $obj->taxonomy;
1334 }
1335
1336 if ($current_taxonomy == $taxonomy) {
1337 $display = true;
1338 }
1339 }
1340 }
1341 }
1342 }
1343 break;
1344
1345 case 'specifics':
1346 if (isset($rules['specific']) && is_array($rules['specific'])) {
1347 foreach ($rules['specific'] as $specific_page) {
1348 $specific_data = explode('-', $specific_page);
1349 $specific_post_type = $specific_data[0] ?? false;
1350 $specific_post_id = $specific_data[1] ?? false;
1351 if ('post' == $specific_post_type) {
1352 if ($specific_post_id == $post_id) {
1353 $display = true;
1354 }
1355 } elseif (isset($specific_data[2]) && ('single' == $specific_data[2]) && 'tax' == $specific_post_type) {
1356 if (is_singular()) {
1357 $term_details = get_term($specific_post_id);
1358
1359 if (isset($term_details->taxonomy)) {
1360 $has_term = has_term((int)$specific_post_id, $term_details->taxonomy, $post_id);
1361
1362 if ($has_term) {
1363 $display = true;
1364 }
1365 }
1366 }
1367 } elseif ('tax' == $specific_post_type) {
1368 $tax_id = get_queried_object_id();
1369 if ($specific_post_id == $tax_id) {
1370 $display = true;
1371 }
1372 }
1373 }
1374 }
1375 break;
1376
1377 default:
1378 break;
1379 }
1380
1381 if ($display) {
1382 break;
1383 }
1384 }
1385 }
1386
1387 return $display;
1388 }
1389
1390 public static function parseUserRoleCondition($rules): bool
1391 {
1392 $show_popup = true;
1393
1394 if (is_array($rules) && !empty($rules)) {
1395 $show_popup = false;
1396
1397 foreach ($rules as $rule) {
1398 switch ($rule) {
1399 case '':
1400 case 'all':
1401 $show_popup = true;
1402 break;
1403
1404 case 'logged-in':
1405 if (is_user_logged_in()) {
1406 $show_popup = true;
1407 }
1408 break;
1409
1410 case 'logged-out':
1411 if (!is_user_logged_in()) {
1412 $show_popup = true;
1413 }
1414 break;
1415
1416 default:
1417 if (is_user_logged_in()) {
1418 $current_user = wp_get_current_user();
1419
1420 if (isset($current_user->roles)
1421 && is_array($current_user->roles)
1422 && in_array($rule, $current_user->roles)
1423 ) {
1424 $show_popup = true;
1425 }
1426 }
1427 break;
1428 }
1429
1430 if ($show_popup) {
1431 break;
1432 }
1433 }
1434 }
1435
1436 return $show_popup;
1437 }
1438
1439 public static function checkUserCanEdit()
1440 {
1441 if (is_singular('king-addons-el-hf') && !current_user_can('edit_posts')) {
1442 wp_redirect(site_url(), 301);
1443 die;
1444 }
1445 }
1446
1447 public static function loadElementorCanvasTemplate($single_template)
1448 {
1449 global $post;
1450
1451 if ('king-addons-el-hf' == $post->post_type) {
1452 if (defined('ELEMENTOR_VERSION')) {
1453 $elementor_2_0_canvas = ELEMENTOR_PATH . '/modules/page-templates/templates/canvas.php';
1454
1455 if (file_exists($elementor_2_0_canvas)) {
1456 return $elementor_2_0_canvas;
1457 } else {
1458 return ELEMENTOR_PATH . '/includes/page-templates/canvas.php';
1459 }
1460 }
1461 }
1462
1463 return $single_template;
1464 }
1465
1466 public static function enqueueScripts(): void
1467 {
1468 $screen = get_current_screen();
1469 if ($screen->id === 'edit-king-addons-el-hf') {
1470 // todo - styles
1471 // wp_enqueue_style('king-addons-el-hf-style', KING_ADDONS_URL . 'includes/extensions/Header_Footer_Builder/header-footer-builder.css', '', KING_ADDONS_VERSION);
1472 wp_enqueue_style('king-addons-el-hf-style', KING_ADDONS_URL . 'includes/extensions/Header_Footer_Builder/admin.css', '', KING_ADDONS_VERSION);
1473 }
1474 }
1475
1476 public static function columnHeadings($columns)
1477 {
1478 unset($columns['date']);
1479 $columns['king_addons_el_hf_edit_template'] = esc_html__('Edit Template', 'king-addons');
1480 $columns['king_addons_el_hf_type_of_template'] = esc_html__('Type of Template', 'king-addons');
1481 $columns['king_addons_el_hf_display_rules'] = esc_html__('Display Rules', 'king-addons');
1482 $columns['date'] = esc_html__('Date', 'king-addons');
1483 return $columns;
1484 }
1485
1486 public static function columnContent($column, $post_id)
1487 {
1488 // Edit Template
1489 if ('king_addons_el_hf_edit_template' === $column) {
1490 echo '<a class="king-addons-el-hf-edit-template-btn" href="';
1491 echo './post.php?post=' . esc_attr($post_id) . '&action=edit';
1492 echo '">' . esc_html__('Edit Template', 'king-addons') . '</a>';
1493 }
1494
1495 // Display Rules
1496 if ('king_addons_el_hf_display_rules' === $column) {
1497
1498 $locations = get_post_meta($post_id, 'king_addons_el_hf_target_include_locations', true);
1499 if (!empty($locations)) {
1500 echo '<div style="margin-bottom: 5px;">';
1501 echo '<strong>';
1502 echo esc_html__('Display: ', 'king-addons');
1503 echo '</strong>';
1504 self::columnDisplayLocation($locations);
1505 echo '</div>';
1506 }
1507
1508 $locations = get_post_meta($post_id, 'king_addons_el_hf_target_exclude_locations', true);
1509 if (!empty($locations)) {
1510 echo '<div style="margin-bottom: 5px;">';
1511 echo '<strong>';
1512 echo esc_html__('Exclusion: ', 'king-addons');
1513 echo '</strong>';
1514 self::columnDisplayLocation($locations);
1515 echo '</div>';
1516 }
1517
1518 $users = get_post_meta($post_id, 'king_addons_el_hf_target_user_roles', true);
1519 if (isset($users) && is_array($users)) {
1520 if (!empty($users[0])) {
1521 $user_label = [];
1522 foreach ($users as $user) {
1523 $user_label[] = self::get_user_by_key($user);
1524 }
1525 echo '<div>';
1526 echo '<strong>Users: </strong>';
1527 echo esc_html(join(', ', $user_label));
1528 echo '</div>';
1529 }
1530 }
1531
1532 }
1533
1534 // Type of Template
1535 if ('king_addons_el_hf_type_of_template' === $column) {
1536 $template_type = get_post_meta($post_id, 'king_addons_el_hf_template_type', true);
1537 if (!empty($template_type)) {
1538 echo '<div style="margin-bottom: 5px;">';
1539 echo '<strong>';
1540 switch ($template_type) {
1541 case 'king_addons_el_hf_type_header':
1542 echo esc_html__('Header', 'king-addons');
1543 break;
1544 case 'king_addons_el_hf_type_footer':
1545 echo esc_html__('Footer', 'king-addons');
1546 break;
1547 default:
1548 echo esc_html__('Not selected', 'king-addons');
1549 break;
1550 }
1551 echo '</strong>';
1552 echo '</div>';
1553 }
1554 }
1555 }
1556
1557 public static function get_user_by_key($key)
1558 {
1559 if (!isset(self::$user_selection) || empty(self::$user_selection)) {
1560 self::$user_selection = self::get_user_selections();
1561 }
1562 $user_selection = self::$user_selection;
1563
1564 if (isset($user_selection['basic']['value'][$key])) {
1565 return $user_selection['basic']['value'][$key];
1566 } elseif ($user_selection['advanced']['value'][$key]) {
1567 return $user_selection['advanced']['value'][$key];
1568 }
1569 return $key;
1570 }
1571
1572 public static function columnDisplayLocation($locations)
1573 {
1574 $location_label = [];
1575 /** @noinspection PhpConditionAlreadyCheckedInspection */
1576 if (is_array($locations) && is_array($locations['rule']) && isset($locations['rule'])) {
1577 /** @noinspection PhpArraySearchInBooleanContextInspection */
1578 $index = array_search('specifics', $locations['rule']);
1579 /** @noinspection PhpConditionCheckedByNextConditionInspection */
1580 if (false !== $index && !empty($index)) {
1581 unset($locations['rule'][$index]);
1582 }
1583 }
1584
1585 if (isset($locations['rule']) && is_array($locations['rule'])) {
1586 foreach ($locations['rule'] as $location) {
1587 $location_label[] = self::getLocation($location);
1588 }
1589 }
1590
1591 if (isset($locations['specific']) && is_array($locations['specific'])) {
1592 foreach ($locations['specific'] as $location) {
1593 $location_label[] = self::getLocation($location);
1594 }
1595 }
1596
1597 echo esc_html(join(', ', $location_label));
1598 }
1599
1600 public static function getLocation($key)
1601 {
1602 if (!isset(self::$location_selection) || empty(self::$location_selection)) {
1603 self::$location_selection = self::getLocationSelections();
1604 }
1605
1606 $location_selection = self::$location_selection;
1607
1608 foreach ($location_selection as $location_grp) {
1609 if (isset($location_grp['value'][$key])) {
1610 return $location_grp['value'][$key];
1611 }
1612 }
1613
1614 if (strpos($key, 'post-') !== false) {
1615 $post_id = (int)str_replace('post-', '', $key);
1616 return get_the_title($post_id);
1617 }
1618
1619 if (strpos($key, 'tax-') !== false) {
1620 $tax_id = (int)str_replace('tax-', '', $key);
1621 $term = get_term($tax_id);
1622
1623 if (!is_wp_error($term)) {
1624 $term_taxonomy = ucfirst(str_replace('_', ' ', $term->taxonomy));
1625 return $term->name . ' - ' . $term_taxonomy;
1626 } else {
1627 return '';
1628 }
1629 }
1630
1631 return $key;
1632 }
1633
1634 public static function getLocationSelections()
1635 {
1636 $args = array(
1637 'public' => true,
1638 '_builtin' => true,
1639 );
1640
1641 $post_types = get_post_types($args, 'objects');
1642 unset($post_types['attachment']);
1643
1644 $args['_builtin'] = false;
1645 $custom_post_type = get_post_types($args, 'objects');
1646
1647 $post_types = apply_filters('king_addons_el_hf_location_rule_post_types', array_merge($post_types, $custom_post_type));
1648
1649 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
1650 $special_pages = array(
1651 'special-404-none' => esc_html__('404 Page (Available in PRO)', 'king-addons'),
1652 'special-search' => esc_html__('Search Page', 'king-addons'),
1653 'special-blog-none' => esc_html__('Blog / Posts Page (Available in PRO)', 'king-addons'),
1654 'special-front' => esc_html__('Front Page', 'king-addons'),
1655 'special-date' => esc_html__('Date Archive', 'king-addons'),
1656 'special-author' => esc_html__('Author Archive', 'king-addons'),
1657 );
1658 } else {
1659 $special_pages = array(
1660 'special-404' => esc_html__('404 Page', 'king-addons'),
1661 'special-search' => esc_html__('Search Page', 'king-addons'),
1662 'special-blog' => esc_html__('Blog / Posts Page', 'king-addons'),
1663 'special-front' => esc_html__('Front Page', 'king-addons'),
1664 'special-date' => esc_html__('Date Archive', 'king-addons'),
1665 'special-author' => esc_html__('Author Archive', 'king-addons'),
1666 );
1667 }
1668
1669 if (class_exists('WooCommerce')) {
1670 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
1671 $special_pages['special-woocommerce-shop-none'] = esc_html__('WooCommerce Shop Page (Available in PRO)', 'king-addons');
1672 } else {
1673 $special_pages['special-woocommerce-shop'] = esc_html__('WooCommerce Shop Page', 'king-addons');
1674 }
1675 }
1676
1677 $selection_options = array(
1678 'basic' => array(
1679 'label' => esc_html__('Basic', 'king-addons'),
1680 'value' => array(
1681 'basic-global' => esc_html__('Entire Website', 'king-addons'),
1682 'basic-singulars' => esc_html__('All Singulars', 'king-addons'),
1683 'basic-archives' => esc_html__('All Archives', 'king-addons'),
1684 ),
1685 ),
1686
1687 'special-pages' => array(
1688 'label' => esc_html__('Special Pages', 'king-addons'),
1689 'value' => $special_pages,
1690 ),
1691 );
1692
1693 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
1694 $selection_options['specific-target'] = array(
1695 'label' => esc_html__('Specific Target', 'king-addons'),
1696 'value' => array(
1697 'specifics-none' => esc_html__('Specific Pages / Posts / Taxonomies, etc. (Available in PRO)', 'king-addons'),
1698 ),
1699 );
1700 } else {
1701 $selection_options['specific-target'] = array(
1702 'label' => esc_html__('Specific Target', 'king-addons'),
1703 'value' => array(
1704 'specifics' => esc_html__('Specific Pages / Posts / Taxonomies, etc.', 'king-addons'),
1705 ),
1706 );
1707 }
1708
1709 $args = array(
1710 'public' => true,
1711 );
1712
1713 $taxonomies = get_taxonomies($args, 'objects');
1714
1715 if (!empty($taxonomies)) {
1716 foreach ($taxonomies as $taxonomy) {
1717
1718 if ('post_format' == $taxonomy->name) {
1719 continue;
1720 }
1721
1722 foreach ($post_types as $post_type) {
1723 $post_opt = self::getPostTargetRuleOptions($post_type, $taxonomy);
1724
1725 if (isset($selection_options[$post_opt['post_key']])) {
1726 if (!empty($post_opt['value']) && is_array($post_opt['value'])) {
1727 foreach ($post_opt['value'] as $key => $value) {
1728 if (!in_array($value, $selection_options[$post_opt['post_key']]['value'])) {
1729 $selection_options[$post_opt['post_key']]['value'][$key] = $value;
1730 }
1731 }
1732 }
1733 } else {
1734 $selection_options[$post_opt['post_key']] = array(
1735 'label' => $post_opt['label'],
1736 'value' => $post_opt['value'],
1737 );
1738 }
1739 }
1740 }
1741 }
1742
1743 return apply_filters('king_addons_el_hf_display_on_list', $selection_options);
1744 }
1745
1746 public static function getPostTargetRuleOptions($post_type, $taxonomy): array
1747 {
1748 $post_key = str_replace(' ', '-', strtolower($post_type->label));
1749 $post_label = ucwords($post_type->label);
1750 $post_name = $post_type->name;
1751 $post_option = array();
1752
1753 /* translators: %s is post label */
1754 $all_posts = sprintf(esc_html__('All %s', 'king-addons'), $post_label);
1755 $post_option[$post_name . '|all'] = $all_posts;
1756
1757 if ('pages' != $post_key) {
1758 /* translators: %s is post label */
1759 $all_archive = sprintf(esc_html__('All %s Archive', 'king-addons'), $post_label);
1760 $post_option[$post_name . '|all|archive'] = $all_archive;
1761 }
1762
1763 if (in_array($post_type->name, $taxonomy->object_type)) {
1764 $tax_label = ucwords($taxonomy->label);
1765 $tax_name = $taxonomy->name;
1766
1767 /* translators: %s is taxonomy label */
1768 $tax_archive = sprintf(esc_html__('All %s Archive', 'king-addons'), $tax_label);
1769
1770 $post_option[$post_name . '|all|taxarchive|' . $tax_name] = $tax_archive;
1771 }
1772
1773 $post_output['post_key'] = $post_key;
1774 $post_output['label'] = $post_label;
1775 $post_output['value'] = $post_option;
1776
1777 return $post_output;
1778 }
1779
1780 public static function getFormatRuleValue($save_data, $key): array
1781 {
1782 $meta_value = array();
1783
1784 if (isset($save_data[$key]['rule'])) {
1785 $save_data[$key]['rule'] = array_unique($save_data[$key]['rule']);
1786 if (isset($save_data[$key]['specific'])) {
1787 $save_data[$key]['specific'] = array_unique($save_data[$key]['specific']);
1788 }
1789
1790 $index = array_search('', $save_data[$key]['rule']);
1791 if (false !== $index) {
1792 unset($save_data[$key]['rule'][$index]);
1793 }
1794 $index = array_search('specifics', $save_data[$key]['rule']);
1795 if (false !== $index) {
1796 unset($save_data[$key]['rule'][$index]);
1797
1798 if (isset($save_data[$key]['specific']) && is_array($save_data[$key]['specific'])) {
1799 $save_data[$key]['rule'][] = 'specifics';
1800 }
1801 }
1802
1803 foreach ($save_data[$key] as $meta_key => $value) {
1804 if (!empty($value)) {
1805 $meta_value[$meta_key] = array_map('esc_attr', $value);
1806 }
1807 }
1808 if (!isset($meta_value['rule']) || !in_array('specifics', $meta_value['rule'])) {
1809 $meta_value['specific'] = array();
1810 }
1811
1812 if (empty($meta_value['rule'])) {
1813 $meta_value = array();
1814 }
1815 }
1816
1817 return $meta_value;
1818 }
1819 }