PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / 3.50.0
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms v3.50.0
3.54.0 3.53.0 3.52.0 3.51.0 3.50.0 3.45.0 3.38.0 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.40.0 3.40.1 3.41.0 3.42.0 3.43.0 3.44.0 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 All 178 releases
simple-tags / inc / class.admin.php

class.admin.php in Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms 3.50.0, at inc/class.admin.php

1,562 lines 67.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Include modules
3 require_once(TAXOPRESS_ABSPATH . '/modules/taxopress-ai/taxopress-ai.php');
4
5 class SimpleTags_Admin
6 {
7 // CPT and Taxonomy support
8 public static $post_type = 'post';
9 public static $post_type_name = '';
10 public static $taxonomy = '';
11 public static $taxo_name = '';
12 public static $admin_url = '';
13 public static $enabled_menus = [];
14
15 public const MENU_SLUG = 'st_options';
16
17 /**
18 * Initialize Admin
19 *
20 * @return void
21 * @author WebFactory Ltd
22 */
23 public function __construct()
24 {
25 // DB Upgrade ?
26 self::upgrade();
27
28 // Which taxo ?
29 self::register_taxonomy();
30
31 // Plugin installer
32 add_action('admin_init', array(__CLASS__, 'plugin_installer_upgrade_code'));
33
34 // Redirect on plugin activation
35 add_action('admin_init', array(__CLASS__, 'redirect_on_activate'));
36
37 // Admin menu
38 add_action('admin_menu', array(__CLASS__, 'admin_menu'));
39
40 //Admin footer credit
41 add_action('in_admin_footer', array(__CLASS__, 'taxopress_admin_footer'));
42
43 // Load JavaScript and CSS
44 add_action('admin_enqueue_scripts', array(__CLASS__, 'admin_enqueue_scripts'));
45
46 add_action('admin_enqueue_scripts', [$this, 'maybe_enqueue_frontend_assets_in_admin']);
47
48 add_action('admin_head', array($this, 'taxopress_hide_other_plugin_notices'));
49
50 add_action('wp_ajax_taxopress_search_posts', [$this, 'taxopress_search_posts_ajax']);
51
52 //ui class is used accross many pages. So, it should be here
53 require STAGS_DIR . '/inc/class.admin.taxonomies.ui.php';
54
55 $dashboard_screen = (isset($_GET['page']) && $_GET['page'] === 'st_dashboard') ? true : false;
56
57 //dashboard
58 require STAGS_DIR . '/inc/dashboard.php';
59 SimpleTags_Dashboard::get_instance();
60 self::$enabled_menus['st_dashboard'] = esc_html__('Dashboard', 'simple-tags');
61 if (1 === (int) SimpleTags_Plugin::get_option_value('active_taxonomies')) {
62 self::$enabled_menus['st_taxonomies'] = esc_html__('Taxonomies', 'simple-tags');
63 }
64
65 //hidden-terms
66 if (1 === (int) SimpleTags_Plugin::get_option_value('enable_hidden_terms')) {
67 require STAGS_DIR . '/inc/hidden-terms.php';
68 SimpleTags_Hidden_Terms::get_instance();
69 }
70
71 //terms
72 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_st_terms')) {
73 require STAGS_DIR . '/inc/terms-table.php';
74 require STAGS_DIR . '/inc/terms.php';
75 SimpleTags_Terms::get_instance();
76 self::$enabled_menus['st_terms'] = esc_html__('Terms', 'simple-tags');
77 }
78
79 //posts
80 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_st_posts')) {
81 require STAGS_DIR . '/inc/posts-table.php';
82 require STAGS_DIR . '/inc/posts.php';
83 SimpleTags_Posts::get_instance();
84 self::$enabled_menus['st_posts'] = esc_html__('Posts', 'simple-tags');
85 }
86
87 //tag clouds/ terms display
88 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_terms_display')) {
89 require_once STAGS_DIR . '/inc/tag-clouds-action.php';
90 require STAGS_DIR . '/inc/tag-clouds-table.php';
91 require STAGS_DIR . '/inc/tag-clouds.php';
92 SimpleTags_Tag_Clouds::get_instance();
93 }
94
95 //post tags
96 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_post_tags')) {
97 require_once STAGS_DIR . '/inc/post-tags-action.php';
98 require STAGS_DIR . '/inc/post-tags-table.php';
99 require STAGS_DIR . '/inc/post-tags.php';
100 SimpleTags_Post_Tags::get_instance();
101 }
102
103 //Related Posts
104 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_related_posts_new')) {
105 require_once STAGS_DIR . '/inc/related-posts-action.php';
106 require STAGS_DIR . '/inc/related-posts-table.php';
107 require STAGS_DIR . '/inc/related-posts.php';
108 SimpleTags_Related_Post::get_instance();
109 }
110
111 //Auto Links
112 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_auto_links')) {
113 require STAGS_DIR . '/inc/autolinks-table.php';
114 require STAGS_DIR . '/inc/autolinks.php';
115 SimpleTags_Autolink::get_instance();
116 }
117
118 //Auto Terms
119 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_auto_terms')) {
120 require STAGS_DIR . '/inc/autoterms-table.php';
121 require STAGS_DIR . '/inc/autoterms-logs-table.php';
122 require STAGS_DIR . '/inc/autoterms.php';
123 require STAGS_DIR . '/inc/autoterms_content.php';
124 require STAGS_DIR . '/inc/schedule.php';
125 require STAGS_DIR . '/inc/schedule-logs-table.php';
126 SimpleTags_Autoterms::get_instance();
127 SimpleTags_Autoterms_Content::get_instance();
128 SimpleTags_Autoterms_Schedule::get_instance();
129 self::$enabled_menus['st_autoterms'] = esc_html__('Auto Terms', 'simple-tags');
130 }
131
132 TaxoPress_AI_Module::get_instance();
133
134 //click terms option
135 require STAGS_DIR . '/inc/class.admin.clickterms.php';
136 new SimpleTags_Admin_ClickTags();
137
138 require STAGS_DIR . '/inc/class.admin.autocomplete.php';
139 new SimpleTags_Admin_Autocomplete();
140
141 // Mass edit terms
142 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_mass_edit')) {
143 require STAGS_DIR . '/inc/class.admin.mass.php';
144 new SimpleTags_Admin_Mass();
145 }
146
147 // Manage terms
148 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_manage')) {
149 require STAGS_DIR . '/inc/class-tag-table.php';
150 require STAGS_DIR . '/inc/class.admin.manage.php';
151 SimpleTags_Admin_Manage::get_instance();
152 }
153
154 require STAGS_DIR . '/inc/class.admin.post.php';
155 new SimpleTags_Admin_Post_Settings();
156
157 //taxonomies
158 if ($dashboard_screen || 1 === (int) SimpleTags_Plugin::get_option_value('active_taxonomies')) {
159 require_once STAGS_DIR . '/inc/taxonomies-action.php';
160 require STAGS_DIR . '/inc/class-taxonomies-table.php';
161 require STAGS_DIR . '/inc/taxonomies.php';
162 SimpleTags_Admin_Taxonomies::get_instance();
163 }
164
165 do_action('taxopress_admin_class_after_includes');
166
167 // Ajax action, JS Helper and admin action
168 add_action('wp_ajax_simpletags', array(__CLASS__, 'ajax_check'));
169 // Save dashboard feature
170 add_action('wp_ajax_save_taxopress_dashboard_feature_by_ajax', [__CLASS__, 'saveDashboardFeature']);
171 // Plugin action links
172 add_filter('plugin_action_links_' . plugin_basename(TAXOPRESS_FILE), [__CLASS__, 'plugin_settings_link']);
173 }
174
175 public function taxopress_hide_other_plugin_notices()
176 {
177 global $pagenow;
178
179 $taxopress_pages = taxopress_admin_pages();
180
181 if (isset($_GET['page']) && in_array($_GET['page'], $taxopress_pages)) {
182 echo '<style>
183 .notice:not(.taxopress-notice) {
184 display: none !important;
185 }
186 </style>';
187 }
188 }
189
190 /**
191 * Plugin action links
192 */
193 public static function plugin_settings_link($links)
194 {
195
196 foreach (self::$enabled_menus as $menu_slug => $menu_title) {
197 $links[] = '<a href="' . admin_url('admin.php?page=' . $menu_slug) . '">'. $menu_title .'</a>';
198 }
199
200 return $links;
201 }
202
203 /**
204 * Ajax for saving a feature from dashboard page
205 *
206 * Copied from PublishPress Blocks
207 *
208 * @return boolean,void Return false if failure, echo json on success
209 */
210 public static function saveDashboardFeature()
211 {
212 if (!current_user_can('admin_simple_tags')) {
213 wp_send_json(__('No permission!', 'simple-tags'), 403);
214 return false;
215 }
216
217 if (
218 !wp_verify_nonce(
219 sanitize_key($_POST['nonce']),
220 'st-admin-js'
221 )
222 ) {
223 wp_send_json(__('Invalid nonce token!', 'simple-tags'), 400);
224 return false;
225 }
226
227 if (empty($_POST['feature']) || !$_POST['feature']) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
228 wp_send_json(__('Error: wrong data', 'simple-tags'), 400);
229 return false;
230 }
231
232 $feature = sanitize_text_field($_POST['feature']);
233 $new_state = sanitize_text_field($_POST['new_state']);
234
235 SimpleTags_Plugin::set_option_value($feature, $new_state);
236
237 wp_send_json(true, 200);
238 }
239
240 /**
241 * Ajax Dispatcher
242 */
243 public static function ajax_check()
244 {
245 if (isset($_GET['stags_action']) && 'maybe_create_tag' === $_GET['stags_action'] && isset($_GET['tag'])) {
246 self::maybe_create_tag(wp_unslash(sanitize_text_field($_GET['tag'])));
247 }
248 }
249
250 /**
251 * Maybe create a tag, and return the term_id
252 *
253 * @param string $tag_name
254 */
255 public static function maybe_create_tag($tag_name = '')
256 {
257 $term_id = 0;
258 //restore & in tag post
259 $tag_name = sanitize_text_field(str_replace("simpletagand", "&", $tag_name));
260 $result_term = term_exists($tag_name, 'post_tag', 0);
261 if (empty($result_term)) {
262 $result_term = wp_insert_term(
263 $tag_name,
264 'post_tag'
265 );
266
267 if (!is_wp_error($result_term)) {
268 $term_id = (int) $result_term['term_id'];
269 }
270 } else {
271 $term_id = (int) $result_term['term_id'];
272 }
273
274 wp_send_json_success(['term_id' => $term_id]);
275 }
276
277 /**
278 * Ajax for search posts
279 *
280 * @return void
281 */
282 public static function taxopress_search_posts_ajax()
283 {
284 if (!check_ajax_referer('st-admin-js', 'nonce', false)) {
285 wp_send_json_error(['message' => __('Security check failed.', 'simple-tags')]);
286 }
287
288 if (!current_user_can('simple_tags')) {
289 wp_send_json_error(['message' => __('Permission denied.', 'simple-tags')]);
290 }
291
292 $search = isset($_GET['search']) ? sanitize_text_field($_GET['search']) : '';
293 $paged = max(1, intval($_GET['page'] ?? 1));
294 $post_type = 'post';
295
296
297 $query = new WP_Query([
298 'post_type' => $post_type,
299 'post_status' => 'publish',
300 'posts_per_page' => 10,
301 'paged' => $paged,
302 'orderby' => 'date',
303 'order' => 'DESC',
304 'fields' => 'ids'
305 ]);
306
307 $results = [];
308 foreach ($query->posts as $post_id) {
309 $results[] = [
310 'id' => $post_id,
311 'text' => get_the_title($post_id)
312 ];
313 }
314
315 wp_send_json([
316 'results' => $results,
317 'more' => $paged < $query->max_num_pages
318 ]);
319 }
320
321 /**
322 * Test if current URL is not a DEV environnement
323 *
324 * Copy from monsterinsights_is_dev_url(), thanks !
325 *
326 * @param string $url
327 *
328 * @return bool
329 */
330 private static function is_dev_url($url = '')
331 {
332 $is_local_url = false;
333
334 // Trim it up
335 $url = strtolower(trim($url));
336 // Need to get the host...so let's add the scheme so we can use parse_url
337 if (false === strpos($url, 'http://') && false === strpos($url, 'https://')) {
338 $url = 'http://' . $url;
339 }
340
341 $url_parts = wp_parse_url($url);
342 $host = !empty($url_parts['host']) ? $url_parts['host'] : false;
343 if (!empty($url) && !empty($host)) {
344 if (false !== ip2long($host)) {
345 if (!filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
346 $is_local_url = true;
347 }
348 } elseif ('localhost' === $host) {
349 $is_local_url = true;
350 }
351
352 $tlds_to_check = array('.local', ':8888', ':8080', ':8081', '.invalid', '.example', '.test');
353 foreach ($tlds_to_check as $tld) {
354 if (false !== strpos($host, $tld)) {
355 $is_local_url = true;
356 break;
357 }
358 }
359
360 if (substr_count($host, '.') > 1) {
361 $subdomains_to_check = array('dev.', '*.staging.', 'beta.', 'test.');
362 foreach ($subdomains_to_check as $subdomain) {
363 $subdomain = str_replace('.', '(.)', $subdomain);
364 $subdomain = str_replace(array('*', '(.)'), '(.*)', $subdomain);
365 if (preg_match('/^(' . $subdomain . ')/', $host)) {
366 $is_local_url = true;
367 break;
368 }
369 }
370 }
371 }
372
373 return $is_local_url;
374 }
375
376 /**
377 * Init taxonomy class variable, load this action after all actions on init !
378 * Make a public static function for call it from children class...
379 *
380 * @return void
381 * @author WebFactory Ltd
382 */
383 public static function register_taxonomy()
384 {
385 add_action('init', array(__CLASS__, 'init'), 99999999);
386 }
387
388 /**
389 * Put in var class the current taxonomy choose by the user
390 *
391 * @return void
392 * @author WebFactory Ltd
393 */
394 public static function init()
395 {
396 self::$taxo_name = esc_html__('Post tags', 'simple-tags');
397 self::$post_type_name = esc_html__('Posts', 'simple-tags');
398
399 // Custom CPT ?
400 if (isset($_GET['cpt']) && !empty($_GET['cpt']) && post_type_exists(sanitize_text_field($_GET['cpt']))) {
401 $cpt = get_post_type_object(sanitize_text_field($_GET['cpt']));
402 self::$post_type = $cpt->name;
403 self::$post_type_name = $cpt->labels->name;
404 }
405
406 // Get compatible taxo for current post type
407 $compatible_taxonomies = get_object_taxonomies(self::$post_type);
408
409 // Custom taxo ?
410 if (isset($_GET['taxo']) && !empty($_GET['taxo']) && taxonomy_exists(sanitize_text_field($_GET['taxo']))) {
411 $taxo = get_taxonomy(sanitize_text_field($_GET['taxo']));
412
413 // Taxo is compatible ?
414 if (in_array($taxo->name, $compatible_taxonomies)) {
415 self::$taxonomy = $taxo->name;
416 self::$taxo_name = $taxo->labels->name;
417 } else {
418 unset($taxo);
419 }
420 }
421
422 // Default taxo from CPT...
423 if (!isset($taxo) && is_array($compatible_taxonomies) && !empty($compatible_taxonomies)) {
424 // Take post_tag before category
425 if (in_array('post_tag', $compatible_taxonomies, true)) {
426 $taxo = get_taxonomy('post_tag');
427 } else {
428 $taxo = get_taxonomy(current($compatible_taxonomies));
429 }
430
431 self::$taxonomy = $taxo->name;
432 self::$taxo_name = $taxo->labels->name;
433
434 // TODO: Redirect for help user that see the URL...
435 } elseif (!isset($taxo)) {
436 // TODO: We can't wp_die on init as it affect all pages
437 //wp_die(esc_html__('This custom post type not have taxonomies.', 'simple-tags'));
438 }
439
440 // Free memory
441 unset($cpt, $taxo);
442 }
443
444 /**
445 * Build HTML form for allow user to change taxonomy for the current page.
446 *
447 * @param string $page_value
448 *
449 * @return void
450 * @author Olatechpro
451 */
452 public static function boxSelectorTaxonomy($page_value = '')
453 {
454 echo '<div class="box-selector-taxonomy">' . PHP_EOL;
455
456 echo '<div class="change-taxo">' . PHP_EOL;
457 echo '<form action="" method="get">' . PHP_EOL;
458 if (!empty($page_value)) {
459 echo '<input type="hidden" name="page" value="' . esc_attr($page_value) . '" />' . PHP_EOL;
460 }
461 $taxonomies = [];
462 echo '<select name="cpt" id="cpt-select" class="st-cpt-select">' . PHP_EOL;
463 foreach (get_post_types(array('show_ui' => true), 'objects') as $post_type) {
464 $taxonomies_children = get_object_taxonomies($post_type->name);
465 if (empty($taxonomies_children)) {
466 continue;
467 }
468 $taxonomies[$post_type->name] = $taxonomies_children;
469 echo '<option ' . selected($post_type->name, self::$post_type, false) . ' value="' . esc_attr($post_type->name) . '">' . esc_html($post_type->labels->name) . '</option>' . PHP_EOL;
470 }
471 echo '</select>' . PHP_EOL;
472
473 echo '<select name="taxo" id="taxonomy-select" class="st-taxonomy-select">' . PHP_EOL;
474 foreach ($taxonomies as $parent_post => $taxonomy) {
475 if (count($taxonomy) > 0) {
476 foreach ($taxonomy as $tax_name) {
477 $taxonomy = get_taxonomy($tax_name);
478 if (false === (bool) $taxonomy->show_ui) {
479 continue;
480 }
481
482 if (self::$post_type == $parent_post) {
483 $class = "";
484 } else {
485 $class = "st-hide-content";
486 }
487
488 echo '<option ' . selected($tax_name, self::$taxonomy, false) . ' value="' . esc_attr($tax_name) . '" data-post="' . esc_attr($parent_post) . '" class="' . esc_attr($class) . '">' . esc_html($taxonomy->labels->name) . '</option>' . PHP_EOL;
489 }
490 }
491 }
492 echo '</select>' . PHP_EOL;
493
494 echo '<input type="submit" class="button" id="submit-change-taxo" value="' . esc_attr__('Change selection', 'simple-tags') . '" />' . PHP_EOL;
495 echo '</form>' . PHP_EOL;
496 echo '</div>' . PHP_EOL;
497 echo '</div>' . PHP_EOL;
498 }
499
500 public static function tabSelectorTaxonomy($tab_slug = '', $page_slug = '')
501 {
502 $current_taxo = isset($_GET["{$tab_slug}_taxo"]) ? sanitize_text_field($_GET["{$tab_slug}_taxo"]) : get_option("{$tab_slug}_taxo", '');
503 $current_cpt = isset($_GET["{$tab_slug}_cpt"]) ? sanitize_text_field($_GET["{$tab_slug}_cpt"]) : get_option("{$tab_slug}_cpt", '');
504
505 // Fallbacks if not yet set
506 if (empty($current_cpt)) {
507 foreach (get_post_types(['show_ui' => true], 'objects') as $pt) {
508 if (!empty(get_object_taxonomies($pt->name))) {
509 $current_cpt = $pt->name;
510 break;
511 }
512 }
513 }
514 if (empty($current_taxo) && $current_cpt) {
515 $possible_taxos = get_object_taxonomies($current_cpt);
516 if (!empty($possible_taxos)) {
517 $current_taxo = $possible_taxos[0];
518 }
519 }
520
521 // Save for use elsewhere
522 self::$post_type = $current_cpt;
523 self::$taxonomy = $current_taxo;
524
525 // Update $post_type_name dynamically
526 if ($current_cpt) {
527 $post_type_object = get_post_type_object($current_cpt);
528 if ($post_type_object) {
529 self::$post_type_name = $post_type_object->labels->name;
530 }
531 }
532
533 // Save to DB for persistence
534 update_option("{$tab_slug}_taxo", $current_taxo);
535 update_option("{$tab_slug}_cpt", $current_cpt);
536
537 // Build list of post types and taxonomies (only CPTs with taxonomies)
538 $taxonomies = [];
539 echo '<div class="box-selector-taxonomy tab-taxo-filter tab-taxo-filter-' . esc_attr($tab_slug) . '">' . PHP_EOL;
540 echo '<div class="change-taxo">' . PHP_EOL;
541
542 echo '<form action="' . esc_url(admin_url('admin.php')) . '" method="get">' . PHP_EOL;
543 $page = !empty($page_slug) ? $page_slug : (isset($_GET['page']) ? sanitize_text_field($_GET['page']) : 'st_manage');
544 echo '<input type="hidden" name="page" value="' . esc_attr($page) . '" />' . PHP_EOL;
545 echo '<input type="hidden" name="page" value="st_manage" />' . PHP_EOL;
546
547 if (!empty($tab_slug)) {
548 echo '<input type="hidden" name="tab" value="' . esc_attr($tab_slug) . '" />' . PHP_EOL;
549 }
550
551 // CPT dropdown
552 echo '<select name="' . esc_attr($tab_slug) . '_cpt" class="st-cpt-select st-cpt-select-' . esc_attr($tab_slug) . '">' . PHP_EOL;
553 foreach (get_post_types(['show_ui' => true], 'objects') as $post_type) {
554 $taxonomies_children = get_object_taxonomies($post_type->name);
555 if (empty($taxonomies_children)) {
556 continue;
557 }
558 $taxonomies[$post_type->name] = $taxonomies_children;
559 echo '<option ' . selected($post_type->name, $current_cpt, false) . ' value="' . esc_attr($post_type->name) . '">' . esc_html($post_type->labels->name) . '</option>' . PHP_EOL;
560 }
561 echo '</select>' . PHP_EOL;
562
563 // Taxonomy dropdown
564 echo '<select name="' . esc_attr($tab_slug) . '_taxo" class="st-taxonomy-select st-taxonomy-select-' . esc_attr($tab_slug) . '">' . PHP_EOL;
565 foreach ($taxonomies as $parent_post => $taxonomy_list) {
566 foreach ($taxonomy_list as $tax_name) {
567 $taxonomy = get_taxonomy($tax_name);
568 if (false === (bool) $taxonomy->show_ui) {
569 continue;
570 }
571 $class = ($parent_post === $current_cpt) ? '' : 'st-hide-content';
572
573 echo '<option ' . selected($tax_name, $current_taxo, false) .
574 ' value="' . esc_attr($tax_name) . '"' .
575 ' data-post="' . esc_attr($parent_post) . '"' .
576 ' class="' . esc_attr($class) . '">' .
577 esc_html($taxonomy->labels->name) .
578 '</option>' . PHP_EOL;
579 }
580 }
581 echo '</select>' . PHP_EOL;
582
583 echo '<input type="submit" class="button" value="' . esc_attr__('Change selection', 'simple-tags') . '" />' . PHP_EOL;
584 echo '</form>' . PHP_EOL;
585 echo '</div>' . PHP_EOL;
586 echo '</div>' . PHP_EOL;
587 }
588
589 public function maybe_enqueue_frontend_assets_in_admin()
590 {
591
592 $screen = get_current_screen();
593 if (!$screen) {
594 return;
595 }
596
597 if (strpos($screen->id, 'taxopress_page_') === false) {
598 return;
599 }
600
601 $is_edit_mode = isset($_GET['action']) && in_array($_GET['action'], ['edit'], true);
602 if (!$is_edit_mode) {
603 return;
604 }
605
606 $current_page = isset($_GET['page']) ? sanitize_text_field($_GET['page']) : '';
607
608 // List of pages that need preview functionality
609 $preview_pages = [
610 'st_terms_display',
611 'st_related_posts',
612 'st_post_tags',
613 ];
614
615 if (!in_array($current_page, $preview_pages, true)) {
616 return;
617 }
618
619 if ((int) SimpleTags_Plugin::get_option_value('disable_admin_frontend_scripts') === 1) {
620 return;
621 }
622
623 if (! apply_filters('taxopress_load_admin_frontend_scripts', true)) {
624 return;
625 }
626
627 // Register and enqueue assets
628 wp_register_script('taxopress-frontend-js', STAGS_URL . '/assets/frontend/js/frontend.js', array('jquery'), STAGS_VERSION);
629 wp_register_style('taxopress-frontend-css', STAGS_URL . '/assets/frontend/css/frontend.css', array(), STAGS_VERSION, 'all');
630
631 // Enqueue the assets
632 wp_enqueue_script('taxopress-frontend-js');
633 wp_enqueue_style('taxopress-frontend-css');
634 }
635 /**
636 * Init somes JS and CSS need for TaxoPress.
637 *
638 * @return void
639 * @author WebFactory Ltd
640 */
641 public static function admin_enqueue_scripts()
642 {
643 global $pagenow;
644
645 $select_2_page = false;
646 if ((isset($_GET['page']) && in_array($_GET['page'], ['st_posts', 'st_autolinks', 'st_autoterms', 'st_autoterms_schedule', 'st_terms_display', 'st_related_posts', 'st_post_tags', 'st_mass_terms'])) || in_array($pagenow, ['post.php', 'edit.php', 'post-new.php'])) {
647 $select_2_page = true;
648 }
649
650 do_action('taxopress_admin_class_before_assets_register');
651
652 //color picker style
653 wp_enqueue_style('wp-color-picker');
654
655 // Helper TaxoPress
656 wp_register_script('st-helper-add-tags', STAGS_URL . '/assets/js/helper-add-tags.js', array('jquery'), STAGS_VERSION);
657 wp_register_script('st-helper-options', STAGS_URL . '/assets/js/helper-options.js', array('jquery', 'wp-color-picker'), STAGS_VERSION);
658
659 // Register CSS
660 wp_register_style('st-admin', STAGS_URL . '/assets/css/admin.css', array(), STAGS_VERSION, 'all');
661 wp_register_style('st-admin-global', STAGS_URL . '/assets/css/admin-global.css', array(), STAGS_VERSION, 'all');
662
663 // Register tooltip
664 wp_register_script(
665 'taxopress-admin-tooltip',
666 STAGS_URL . '/assets/lib/tooltip/js/tooltip.min.js',
667 ['jquery'],
668 STAGS_VERSION
669 );
670
671 wp_register_style(
672 'taxopress-admin-tooltip',
673 STAGS_URL . '/assets/lib/tooltip/css/tooltip.min.css',
674 [],
675 STAGS_VERSION
676 );
677
678 //enqueue tooltip
679 wp_enqueue_script('taxopress-admin-tooltip');
680 wp_enqueue_style('taxopress-admin-tooltip');
681
682 // Register Select 2
683 wp_register_script(
684 'taxopress-admin-select2',
685 STAGS_URL . '/assets/lib/select2/js/select2.full.min.js',
686 ['jquery'],
687 STAGS_VERSION
688 );
689
690 wp_register_style(
691 'taxopress-admin-select2',
692 STAGS_URL . '/assets/lib/select2/css/select2.min.css',
693 [],
694 STAGS_VERSION
695 );
696
697 if ($select_2_page) {
698 wp_enqueue_script('taxopress-admin-select2');
699 wp_enqueue_style('taxopress-admin-select2');
700 }
701
702 //Register and enqueue admin js
703 $script_dependencies = ['jquery'];
704 if ($select_2_page) {
705 $script_dependencies[] = 'taxopress-admin-select2';
706 $script_dependencies[] = 'wp-util';
707 }
708
709 $taxopress_pages = taxopress_admin_pages();
710
711 if (isset($_GET['page']) && in_array($_GET['page'], $taxopress_pages)) {
712 wp_enqueue_media();
713 }
714
715 wp_register_script('st-admin-js', STAGS_URL . '/assets/js/admin.js', $script_dependencies, STAGS_VERSION);
716 wp_enqueue_script('st-admin-js');
717 //localize script
718 wp_localize_script('st-admin-js', 'st_admin_localize', [
719 'ajaxurl' => admin_url('admin-ajax.php'),
720 'select_valid' => esc_html__('Please select a valid', 'simple-tags'),
721 'check_nonce' => wp_create_nonce('st-admin-js'),
722 'select_default_label' => esc_html__('Select Default Post Thumb', 'simple-tags'),
723 'use_media_label' => esc_html__('Use this media', 'simple-tags'),
724 'existing_content_admin_label' => esc_html__('Edit the current setting.', 'simple-tags'),
725 'autoterm_admin_url' => admin_url('admin.php?page=st_autoterms'),
726 'no_terms_message' => esc_html__('No terms will be deleted', 'simple-tags'),
727 'terms_count_message' => esc_html__(' terms will be deleted.', 'simple-tags'),
728 'checking_terms_message' => esc_html__('Checking terms...', 'simple-tags'),
729 'terms_error' => esc_html__('An error occurred while checking terms.', 'simple-tags'),
730 'post_required' => esc_html__('Select a post to see a preview.', 'simple-tags'),
731 'save_settings' => esc_html__('Auto Term ID missing. Kindly save the auto term before using this feature.', 'simple-tags'),
732 'delete_label' => esc_html__('Delete', 'simple-tags'),
733 'ai_nonce' => wp_create_nonce('taxopress-ai-ajax-nonce'),
734 'post_title' => '%post_title%',
735 'post_permalink' => '%post_permalink%',
736 'post_date' => '%post_date%',
737 'post_thumb_url' => '%post_thumb_url%',
738 'post_category' => '%post_category%',
739 'post_size' => '%post_size%',
740 'post_color' => '%post_color%',
741 'merge_cancelled' => esc_html__('Merge has been cancelled.', 'simple-tags'),
742 'cancel_label' => esc_html__('Cancel', 'simple-tags'),
743 'paused_label' => esc_html__('Pause.', 'simple-tags'),
744 'continue_label' => esc_html__('Continue', 'simple-tags'),
745 'merge_large_data' => esc_html__('Large dataset detected, terms will be merged in batches of 20!', 'simple-tags'),
746 'merge_none_merged' => esc_html__('No terms were merged.', 'simple-tags'),
747 'batch_merge_progress' => esc_html__('Batch %1$s of %2$s merged.', 'simple-tags'),
748 'terms_merged_text' => esc_html__('terms merged', 'simple-tags'),
749 'posts_updated_text' => esc_html__('posts updated', 'simple-tags'),
750 'merge_success_update' => esc_html__('All terms merged into %s', 'simple-tags'),
751 'ajax_merge_terms_error' => esc_html__('AJAX error on batch', 'simple-tags'),
752 'batch_error_text' => esc_html__('Error on batch %1$s:', 'simple-tags'),
753 'enable_merge_terms_slug' => SimpleTags_Plugin::get_option_value('enable_merge_terms_slug'),
754 'enable_add_terms_slug' => SimpleTags_Plugin::get_option_value('enable_add_terms_slug'),
755 'enable_remove_terms_slug' => SimpleTags_Plugin::get_option_value('enable_remove_terms_slug'),
756 'enable_rename_terms_slug' => SimpleTags_Plugin::get_option_value('enable_rename_terms_slug'),
757 'enable_mass_edit_terms_slug' => SimpleTags_Plugin::get_option_value('enable_mass-edit_terms_slug'),
758 'select_post_label' => esc_html__('Search Posts...', 'simple-tags'),
759 'loading' => esc_html__('Loading...', 'simple-tags'),
760 'preview_error' => esc_html__('Error loading preview', 'simple-tags'),
761 'enable_ibm_watson_ai_source' => SimpleTags_Plugin::get_option_value('enable_ibm_watson_ai_source'),
762 'enable_dandelion_ai_source' => SimpleTags_Plugin::get_option_value('enable_dandelion_ai_source'),
763 'enable_lseg_ai_source' => SimpleTags_Plugin::get_option_value('enable_lseg_ai_source'),
764 'plugin_url' => STAGS_URL,
765 'using_default_text' => __('Using default TaxoPress image', 'simple-tags'),
766 'select_image_label' => esc_html__('Select Media', 'simple-tags'),
767 'change_image_label' => esc_html__('Change Media', 'simple-tags'),
768 'use_default_label' => esc_html__('Use Default', 'simple-tags'),
769 'see_more_suggestions' => esc_html__('See More', 'simple-tags'),
770 'see_less_suggestions' => esc_html__('See Less', 'simple-tags'),
771 'apply_selected' => esc_html__('Apply Selected', 'simple-tags'),
772 'close_suggestions' => esc_html__('Close', 'simple-tags'),
773 'select_suggestion_alert' => esc_html__('Please select at least one suggestion to apply.', 'simple-tags'),
774 'multiple_merge_warning' => esc_html__('You have selected multiple merge suggestions. All selected terms will be merged into a single new term. Do you want to continue?', 'simple-tags'),
775 'no_merge_suggestions' => esc_html__('No merge suggestions found for this taxonomy.', 'simple-tags'),
776 'suggested_terms_title' => esc_html__('Suggested Terms to Merge:', 'simple-tags'),
777 'duplicates_text' => esc_html__('duplicates', 'simple-tags'),
778 'reason_text' => esc_html__('Reason:', 'simple-tags'),
779 'select_all_label' => esc_html__('Select All', 'simple-tags'),
780 'deselect_all_label' => esc_html__('Deselect All', 'simple-tags'),
781 'terms_to_merge_text' => esc_html__('Terms to Merge', 'simple-tags'),
782 'new_term_text' => esc_html__('New Term', 'simple-tags'),
783 'reasons_text' => esc_html__('Reasons', 'simple-tags'),
784 ]);
785
786
787 //Register remodal assets
788 wp_register_script('st-remodal-js', STAGS_URL . '/assets/js/remodal.min.js', array('jquery'), STAGS_VERSION);
789 wp_register_style('st-remodal-css', STAGS_URL . '/assets/css/remodal.css', array(), STAGS_VERSION, 'all');
790 wp_register_style('st-remodal-default-theme-css', STAGS_URL . '/assets/css/remodal-default-theme.css', array(), STAGS_VERSION, 'all');
791
792 // Register location
793 $wp_post_pages = array('post.php', 'post-new.php');
794 $wp_page_pages = array('page.php', 'page-new.php');
795
796 wp_enqueue_style('st-admin-global');
797
798 // Common Helper for Post, Page and Plugin Page
799 if (
800 in_array($pagenow, $wp_post_pages) ||
801 (in_array($pagenow, $wp_page_pages) && is_page_have_tags()) ||
802 (isset($_GET['page']) && in_array($_GET['page'], $taxopress_pages))
803 ) {
804 wp_enqueue_script('st-remodal-js');
805 wp_enqueue_style('st-remodal-css');
806 wp_enqueue_style('st-remodal-default-theme-css');
807 wp_enqueue_style('st-admin');
808
809 do_action('taxopress_admin_class_after_styles_enqueue');
810 }
811
812 // add jQuery tabs for options page. Use jQuery UI Tabs from WP
813 if (isset($_GET['page']) && in_array($_GET['page'], array('st_options', 'st_terms_display', 'st_post_tags', 'st_related_posts',))) {
814 wp_enqueue_script('jquery-ui-tabs');
815 wp_enqueue_script('st-helper-options');
816 }
817
818 do_action('taxopress_admin_class_after_assets_enqueue');
819 }
820
821 /**
822 * Add settings page on WordPress admin menu
823 *
824 * @return void
825 * @author WebFactory Ltd
826 */
827 public static function admin_menu()
828 {
829 self::$admin_url = admin_url('admin.php?page=' . self::MENU_SLUG);
830
831 add_menu_page(
832 __('TaxoPress: Options', 'simple-tags'),
833 __('TaxoPress', 'simple-tags'),
834 'admin_simple_tags',
835 self::MENU_SLUG,
836 array(
837 __CLASS__,
838 'page_options',
839 ),
840 'dashicons-tag',
841 69
842 );
843 add_submenu_page(
844 self::MENU_SLUG,
845 __('TaxoPress: Options', 'simple-tags'),
846 __('Settings', 'simple-tags'),
847 'admin_simple_tags',
848 self::MENU_SLUG,
849 array(
850 __CLASS__,
851 'page_options',
852 )
853 );
854 }
855
856 /**
857 * Build HTML for page options, manage also save/reset settings
858 *
859 * @return void
860 * @author WebFactory Ltd
861 */
862 public static function page_options()
863 {
864 // Get options
865 $options = (array) SimpleTags_Plugin::get_option();
866
867 if (current_user_can('admin_simple_tags')) {
868 // Update or reset options
869 if (isset($_POST['updateoptions'])) {
870 $dashboard_options = taxopress_dashboard_options();
871 $dashboard_option_keys = array_column($dashboard_options, 'option_key');
872
873 check_admin_referer('updateresetoptions-simpletags');
874
875 $sanitized_options = [];
876
877 $is_fast_update_submission = isset($_GET['page']) && $_GET['page'] === 'st_taxopress_ai';
878
879 // This settings has been migrated to fast update screen so only update from there
880 if ($is_fast_update_submission) {
881 // add taxopress ai post type and taxonomies options so we can have all post types. TODO: This need to be a filter
882 foreach (get_post_types(['public' => true], 'names') as $post_type => $post_type_object) {
883 if ($post_type == 'post') {
884 $opt_default_value = 'post_tag';
885 } else {
886 $opt_default_value = 0;
887 }
888 $options['taxopress_ai_' . $post_type . '_metabox_default_taxonomy'] = $opt_default_value;
889 $options['taxopress_ai_' . $post_type . '_metabox_display_option'] = 'default';
890 $options['taxopress_ai_' . $post_type . '_support_private_taxonomy'] = 0;
891
892 $options['taxopress_ai_' . $post_type . '_metabox_orderby'] = 'count';
893 $options['taxopress_ai_' . $post_type . '_metabox_order'] = 'desc';
894 $options['taxopress_ai_' . $post_type . '_metabox_maximum_terms'] = 45;
895 $options['taxopress_ai_' . $post_type . '_metabox_show_post_count'] = 0;
896 $options['taxopress_ai_' . $post_type . '_metabox_show_term_slug'] = 0;
897
898 $options['taxopress_ai_' . $post_type . '_minimum_term_length'] = 2;
899 $options['taxopress_ai_' . $post_type . '_maximum_term_length'] = 40;
900
901 $options['taxopress_ai_' . $post_type . '_exclusions'] = '';
902 $options['enable_taxopress_ai_' . $post_type . '_metabox'] = $opt_default_value;
903 $options['taxopress_ai_' . $post_type . '_metabox_filters'] = 1;
904 foreach (['post_terms', 'existing_terms', 'suggest_local_terms', 'create_terms'] as $taxopress_ai_tab) {
905 $options['enable_taxopress_ai_' . $post_type . '_' . $taxopress_ai_tab . '_tab'] = $opt_default_value;
906 }
907 }
908
909 // add metabox post type and taxonomies options so we can have all post types. TODO: This need to be a filter
910 foreach (taxopress_get_all_wp_roles() as $role_name => $role_info) {
911 if (in_array($role_name, ['administrator', 'editor', 'author', 'contributor'])) {
912 $enable_acess_default_value = 1;
913 } else {
914 $enable_acess_default_value = 0;
915 }
916 $options['enable_' . $role_name . '_metabox'] = $enable_acess_default_value;
917 $options['enable_restrict' . $role_name . '_metabox'] = $enable_acess_default_value;
918
919 // ONLY admin + editor default to can edit
920 if (!isset($options['enable_edit_' . $role_name . '_metabox'])) {
921 $options['enable_edit_' . $role_name . '_metabox'] = in_array($role_name, ['administrator', 'editor']) ? 1 : 0;
922 }
923
924 $options['enable_metabox_' . $role_name . ''] = [];
925 $options['remove_taxonomy_metabox_' . $role_name . ''] = [];
926 }
927 }
928
929 foreach ($options as $key => $value) {
930 // If this is NOT a Fast Update submission, preserve metabox/metabox-access keys
931 if (!$is_fast_update_submission && preg_match('/^(enable_taxopress_ai_|taxopress_ai_|enable_.*_metabox|enable_restrict.*_metabox|enable_edit_.*_metabox|enable_metabox_|remove_taxonomy_metabox_)/', $key)) {
932 // Keep existing value as-is
933 if (!is_array($value)) {
934 $sanitized_options[$key] = taxopress_sanitize_text_field($value);
935 } else {
936 $sanitized_options[$key] = map_deep($value, 'sanitize_text_field');
937 }
938 continue;
939 }
940
941 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
942 $post_value = isset($_POST[$key]) ? $_POST[$key] : '';
943
944 if (empty($post_value) && in_array($key, $dashboard_option_keys)) {
945 $post_value = SimpleTags_Plugin::get_option_value($key);
946 }
947
948 if (!is_array($post_value)) {
949 $sanitized_options[$key] = taxopress_sanitize_text_field($post_value);
950 } else {
951 $sanitized_options[$key] = map_deep($post_value, 'sanitize_text_field');
952 }
953 }
954 $options = $sanitized_options;
955
956 SimpleTags_Plugin::set_option($options);
957
958 do_action('simpletags_settings_save_general_end');
959 do_action('taxopress_settings_saved');
960
961 add_settings_error(__CLASS__, __CLASS__, esc_html__('Options saved', 'simple-tags'), 'updated taxopress-notice');
962 } elseif (isset($_POST['reset_options'])) {
963 check_admin_referer('updateresetoptions-simpletags');
964
965 SimpleTags_Plugin::set_default_option();
966
967 add_settings_error(__CLASS__, __CLASS__, esc_html__('TaxoPress options resetted to default options!', 'simple-tags'), 'updated taxopress-notice');
968 } else {
969 //add_settings_error(__CLASS__, __CLASS__, esc_html__('Settings updated', 'simple-tags'), 'updated');
970 }
971 }
972
973 settings_errors(__CLASS__);
974 include STAGS_DIR . '/views/admin/page-settings.php';
975 }
976
977 /**
978 * Get terms for a post, format terms for input and autocomplete usage
979 *
980 * @param string $taxonomy
981 * @param integer $post_id
982 *
983 * @return string
984 * @author WebFactory Ltd
985 */
986 public static function getTermsToEdit($taxonomy = 'post_tag', $post_id = 0)
987 {
988 $post_id = (int) $post_id;
989 if (!$post_id) {
990 return '';
991 }
992
993 $is_mass_edit_page = isset($_GET['page']) && $_GET['page'] === 'st_mass_terms';
994 $show_slug = SimpleTags_Plugin::get_option_value('enable_mass-edit_terms_slug');
995
996 if ($is_mass_edit_page) {
997 $term_objects = wp_get_post_terms($post_id, $taxonomy);
998 if (empty($term_objects) || is_wp_error($term_objects)) {
999 return '';
1000 }
1001
1002 $terms = array();
1003 foreach ($term_objects as $term) {
1004 if ($show_slug) {
1005 if (!empty($term->slug)) {
1006 $terms[] = $term->name . ' (' . $term->slug . ')';
1007 } else {
1008 $terms[] = $term->name;
1009 }
1010 } else {
1011 $terms[] = $term->name;
1012 }
1013 }
1014
1015 $terms = join(', ', $terms);
1016 } else {
1017
1018 $terms = wp_get_post_terms($post_id, $taxonomy, array('fields' => 'names'));
1019 if (empty($terms) || is_wp_error($terms)) {
1020 return '';
1021 }
1022
1023 $terms = array_unique($terms);
1024 $terms = join(', ', $terms);
1025 }
1026
1027 $terms = esc_attr($terms);
1028 $terms = apply_filters('tags_to_edit', $terms);
1029
1030 return $terms;
1031 }
1032
1033 /**
1034 * Default content for meta box of TaxoPress
1035 *
1036 * @return string
1037 * @author WebFactory Ltd
1038 */
1039 public static function getDefaultContentBox()
1040 {
1041 if ((int) wp_count_terms('post_tag', array('hide_empty' => false)) == 0) { // TODO: Custom taxonomy
1042 return esc_html__('This feature requires at least 1 tag to work. Begin by adding tags!', 'simple-tags');
1043 } else {
1044 return esc_html__('This feature works only with activated JavaScript. Activate it in your Web browser so you can!', 'simple-tags');
1045 }
1046 }
1047
1048 /**
1049 * A short public static function for display the same copyright on all admin pages
1050 *
1051 * @return void
1052 * @author WebFactory Ltd
1053 */
1054 public static function printAdminFooter()
1055 {
1056 /* ?>
1057 <p class="footer_st"><?php printf( __( 'Thanks for using TaxoPress | <a href="https://taxopress.com/">TaxoPress.com</a> | Version %s', 'simple-tags' ), STAGS_VERSION ); ?></p>
1058 <?php */
1059 }
1060
1061 /**
1062 * A short public static function for display the same copyright on all taxopress admin pages
1063 *
1064 * @return void
1065 * @author Olatechpro
1066 */
1067 public static function taxopress_admin_footer()
1068 {
1069
1070 $taxopress_pages = taxopress_admin_pages();
1071
1072 if (isset($_GET['page']) && in_array($_GET['page'], $taxopress_pages)) {
1073 ?>
1074 <p class="footer_st">
1075 <?php
1076 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1077 printf(__('Thanks for using TaxoPress | %1sTaxoPress.com%2s | Version %3s', 'simple-tags'), '<a href="https://taxopress.com/">', '</a>', esc_html(STAGS_VERSION)); ?>
1078 </p>
1079 <?php
1080 }
1081 }
1082
1083 /**
1084 * Ouput formatted options
1085 *
1086 * @param array $option_data
1087 *
1088 * @return string
1089 * @author WebFactory Ltd
1090 */
1091 public static function print_options($option_data)
1092 {
1093 // Get options
1094 $option_actual = SimpleTags_Plugin::get_option();
1095
1096 // Generate output
1097 $output = '';
1098 foreach ($option_data as $section => $options) {
1099 $colspan = count($options) > 1 ? 'colspan="2"' : '';
1100
1101 if ($section === 'legacy') {
1102 $table_sub_tab = '<div class="st-legacy-subtab">
1103 <span class="active" data-content=".legacy-tag-cloud-content">'. esc_html__("Tag Cloud", "simple-tags") .'</span> |
1104 <span data-content=".legacy-post-tags-content">'. esc_html__("Tags for Current Post", "simple-tags") .'</span> |
1105 <span data-content=".legacy-related-posts-content">'. esc_html__("Related Posts", "simple-tags") .'</span> |
1106 <span data-content=".legacy-auto-link-content">'. esc_html__("Auto Links", "simple-tags") .'</span>
1107 </div>' . PHP_EOL;
1108 } elseif ($section === 'taxopress-ai') {
1109 $table_sub_tab_lists = [];
1110 $pt_index = 0;
1111 foreach (TaxoPressAiUtilities::get_post_types_options() as $post_type => $post_type_object) {
1112
1113 if (!in_array($post_type, ['attachment'])) {
1114 $active_pt = ($pt_index === 0) ? 'active' : '';
1115 $table_sub_tab_lists[] = '<span class="' . $active_pt . '" data-content=".taxopress-ai-' . $post_type . '-content">' . esc_html($post_type_object->labels->name) . '</span>';
1116 $pt_index++;
1117 }
1118 }
1119 $table_sub_tab = '<div class="st-taxopress-ai-subtab">' . join(' | ', $table_sub_tab_lists). '</div>' . PHP_EOL;
1120 } elseif ($section === 'metabox') {
1121 $table_sub_tab_lists = [];
1122 $pt_index = 0;
1123 foreach (taxopress_get_all_wp_roles() as $role_name => $role_info) {
1124 $active_pt = ($pt_index === 0) ? 'active' : '';
1125 $table_sub_tab_lists[] = '<span class="' . $active_pt . '" data-content=".metabox-' . $role_name . '-content">' . esc_html(translate_user_role($role_info['name'])) . '</span>';
1126 $pt_index++;
1127 }
1128 $table_sub_tab = '<div class="st-metabox-subtab">' . join(' | ', $table_sub_tab_lists). '</div>' . PHP_EOL;
1129 } else {
1130 $table_sub_tab = '';
1131 }
1132
1133 $output .= '<div class="group" id="' . sanitize_title($section) . '">' . PHP_EOL;
1134 $output .= $table_sub_tab;
1135 $output .= '<fieldset class="options">' . PHP_EOL;
1136 $output .= '<legend>' . self::getNiceTitleOptions($section) . '</legend>' . PHP_EOL;
1137 $output .= '<table class="form-table">' . PHP_EOL;
1138 foreach ((array) $options as $option) {
1139
1140 $class = '';
1141 if (in_array($section, ['legacy', 'taxopress-ai', 'metabox'])) {
1142 $class = $option[5];
1143 }
1144
1145 // Helper
1146 if ($option[2] == 'helper') {
1147 $output .= '<tr style="vertical-align: middle;" class="' . $class . '"><td class="helper stpexplan" ' . $colspan . '>' . stripslashes($option[4]) . '</td></tr>' . PHP_EOL;
1148 continue;
1149 }
1150
1151 // Fix notices
1152 if (!isset($option_actual[$option[0]])) {
1153 $option_actual[$option[0]] = '';
1154 }
1155
1156 // Add our custom core_terms_promo type
1157 if ($option[2] == 'core_terms_promo') {
1158 if (isset($option[4]) && !empty($option[4])) {
1159 $output .= '<tr style="vertical-align: middle;" class="' . $class . '"><td class="helper" ' . $colspan . '>' . apply_filters('taxopress_admin_manage_' . $option[0], $option[4]) . '</td></tr>' . PHP_EOL;
1160 }
1161 continue;
1162 }
1163
1164 $input_type = '';
1165 $desc_html_tag = 'div';
1166 switch ($option[2]) {
1167 case 'radio':
1168 $input_type = array();
1169 foreach ($option[3] as $value => $text) {
1170 $input_type[] = '<label><input type="radio" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($value) . '" ' . checked($value, $option_actual[$option[0]], false) . ' /> ' . $text . '</label>' . PHP_EOL;
1171 }
1172 $input_type = implode('<br />', $input_type);
1173 break;
1174
1175 case 'checkbox':
1176 $desc_html_tag = 'span';
1177 $input_type = '<input type="checkbox" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($option[3]) . '" ' . (($option_actual[$option[0]]) ? 'checked="checked"' : '') . ' />' . PHP_EOL;
1178 break;
1179
1180 case 'multiselect':
1181 $desc_html_tag = 'div';
1182 $input_type = array();
1183 foreach ($option[3] as $field_name => $text) {
1184 $selected_option = (is_array($option_actual[$option[0]]) && in_array($field_name, $option_actual[$option[0]])) ? true : false;
1185 $input_type[] = '<label><input type="checkbox" id="' . $option[0] . '-' . $field_name . '" name="' . $option[0] . '[]" value="' . $field_name . '" ' . checked($selected_option, true, false) . ' /> ' . $text . '</label> <br />' . PHP_EOL;
1186 }
1187 $input_type = implode('<br />', $input_type);
1188 break;
1189
1190 case 'sub_multiple_checkbox':
1191 $desc_html_tag = 'div';
1192 $input_type = array();
1193 foreach ($option[3] as $field_name => $field_option) {
1194 $checked_option = !empty($option_actual[$field_name]) ? (int) $option_actual[$field_name] : 0;
1195 $selected_option = ($checked_option > 0) ? true : false;
1196 $field_description = !empty($field_option['description']) ? '<br /><span class="description stpexplan">' . $field_option['description'] . '</span>' : '';
1197 $input_type[] = '<label><input type="checkbox" id="' . $option[0] . '" name="' . $field_name . '" value="1" ' . checked($selected_option, true, false) . ' /> ' . $field_option['label'] . '</label> '. $field_description .'<br />' . PHP_EOL;
1198 }
1199 $input_type = implode('<br />', $input_type);
1200 break;
1201
1202 case 'dropdown':// legacy
1203 $selopts = explode('/', $option[3]);
1204 $seldata = '';
1205 foreach ((array) $selopts as $sel) {
1206 $seldata .= '<option value="' . esc_attr($sel) . '" ' . ((isset($option_actual[$option[0]]) && $option_actual[$option[0]] == $sel) ? 'selected="selected"' : '') . ' >' . ucfirst($sel) . '</option>' . PHP_EOL;
1207 }
1208 $input_type = '<select id="' . $option[0] . '" name="' . $option[0] . '">' . $seldata . '</select>' . PHP_EOL;
1209 break;
1210
1211
1212 case 'select':
1213 $selopts = $option[3];
1214 $seldata = '';
1215 foreach ((array) $selopts as $sel_key => $sel_label) {
1216 $seldata .= '<option value="' . esc_attr($sel_key) . '" ' . ((isset($option_actual[$option[0]]) && $option_actual[$option[0]] == $sel_key) ? 'selected="selected"' : '') . ' >' . ucfirst($sel_label) . '</option>' . PHP_EOL;
1217 }
1218 $input_type = '<select id="' . $option[0] . '" name="' . $option[0] . '">' . $seldata . '</select>' . PHP_EOL;
1219 break;
1220
1221 case 'select_with_icon':
1222 $selopts = $option[3];
1223 $seldata = '';
1224 foreach ((array) $selopts as $sel_key => $sel_label) {
1225 $seldata .= '<option value="' . esc_attr($sel_key) . '" ' . ((isset($option_actual[$option[0]]) && $option_actual[$option[0]] == $sel_key) ? 'selected="selected"' : '') . ' >' . ucfirst($sel_label) . '</option>' . PHP_EOL;
1226 }
1227
1228 $icon_class = isset($option[6]['icon']) ? $option[6]['icon'] : 'dashicons-lock';
1229 $modal_content = isset($option[6]['modal']) ? $option[6]['modal'] : '';
1230 $disabled = !empty($option[8]) && isset($option[8]['disabled']) ? 'disabled="disabled"' : '';
1231 $class_attr = isset($option[5]) ? esc_attr($option[5]) : '';
1232 $icon_wrapper_class = isset($option[6]['icon_wrapper_class']) ? esc_attr($option[6]['icon_wrapper_class']) : 'taxopress-select-icon';
1233 $modal_wrapper_class = isset($option[6]['modal_wrapper_class']) ? esc_attr($option[6]['modal_wrapper_class']) : 'taxopress-select-icon-modal';
1234
1235 $input_type = '<div class="' . $class_attr . '">
1236 <select id="' . $option[0] . '" name="' . $option[0] . '" ' . $disabled . '>' . $seldata . '</select>
1237 <span class="' . $icon_wrapper_class . ' dashicons ' . esc_attr($icon_class) . '">
1238 <div class="' . $modal_wrapper_class . '">' . $modal_content . '</div>
1239 </span>
1240 </div>' . PHP_EOL;
1241 break;
1242
1243 case 'multiselect_with_desc_top':
1244 $desc_html_tag = 'div';
1245 $input_type_array = array();
1246 $prefix = !empty($field_description) ? '<' . $desc_html_tag . ' class="stpexplan">' . $field_description . '</' . $desc_html_tag . '>' : '';
1247 foreach ($field_options as $option_key => $option_label) {
1248 $field_value = isset($option_actual[$field_id]) ? $option_actual[$field_id] : array();
1249 $selected_option = (is_array($field_value) && in_array($option_key, $field_value)) ? true : false;
1250 $input_type_array[] = '<label><input type="checkbox" id="' . esc_attr($field_id . '-' . $option_key) . '" name="' . esc_attr($field_id) . '[]" value="' . esc_attr($option_key) . '" ' . checked($selected_option, true, false) . ' /> ' . esc_html($option_label) . '</label><br />';
1251 }
1252 $input_type = $prefix . implode('', $input_type_array);
1253 $field_description = '';
1254 break;
1255
1256 case 'text-color':
1257 $input_type = '<input type="text" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($option_actual[$option[0]]) . '" class="text-color ' . $option[3] . '" />' . PHP_EOL;
1258 break;
1259
1260 case 'text':
1261 $input_type = '<input type="text" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($option_actual[$option[0]]) . '" class="' . $option[3] . '" />' . PHP_EOL;
1262 break;
1263
1264 case 'licence_field':
1265 $input_type = '<input type="text" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($option[3]) . '" class="' . $option[5] . '" />' . PHP_EOL;
1266 break;
1267
1268 case 'number':
1269 $min_attr = isset($option[6]) ? ' min="' . esc_attr($option[6]) . '"' : '';
1270 $input_type = '<input type="number" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($option_actual[$option[0]]) . '" class="' . $option[3] . '"' . $min_attr . ' />' . PHP_EOL;
1271 break;
1272
1273 case 'textarea':
1274 $rows_attr = isset($option[7]['rows']) ? ' rows="' . esc_attr($option[7]['rows']) . '"' : ' rows="4"';
1275 $placeholder_attr = isset($option[7]['placeholder']) ? ' placeholder="' . esc_attr($option[7]['placeholder']) . '"' : '';
1276 $width_attr = (!empty($option[7]['width'])) ? ' style="width:' . esc_attr($option[7]['width']) . ';"' : ' style="width:100%; max-width:600px;"';
1277 $input_type = '<textarea id="' . $option[0] . '" name="' . $option[0] . '"' . $rows_attr . $placeholder_attr . $width_attr . ' class="' . $option[3] . '">' . esc_textarea($option_actual[$option[0]]) . '</textarea>' . PHP_EOL;
1278 break;
1279 }
1280
1281 if (is_array($option[2])) {
1282 $input_type = '<input type="' . $option[2]["type"] . '" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($option_actual[$option[0]]) . '" class="' . $option[3] . '" ' . $option[2]["attr"] . ' />' . PHP_EOL;
1283 }
1284
1285 // Additional Information
1286 $extra_prefix = '';
1287 $extra_suffix = '';
1288 if (!empty($option[4])) {
1289 if ($option[2] == 'sub_multiple_checkbox') {
1290 $extra_prefix = '<' . $desc_html_tag . ' class="stpexplan">' . $option[4] . '</' . $desc_html_tag . '>' . PHP_EOL;
1291 } else {
1292 $extra_suffix = '<' . $desc_html_tag . ' class="stpexplan">' . $option[4] . '</' . $desc_html_tag . '>' . PHP_EOL;
1293 }
1294 }
1295
1296 // Output
1297 $output .= '<tr style="vertical-align: top;" class="' . $class . '"><th scope="row"><label for="' . $option[0] . '">' . $option[1] . '</label></th><td>'. $extra_prefix .' ' . $input_type . ' ' . $extra_suffix . '</td></tr>' . PHP_EOL;
1298 }
1299 $output .= '</table>' . PHP_EOL;
1300 $output .= '</fieldset>' . PHP_EOL;
1301 $output .= '</div>' . PHP_EOL;
1302 }
1303
1304 return $output;
1305 }
1306
1307 /**
1308 * Get nice title for tabs title option
1309 *
1310 * @param string $id
1311 *
1312 * @return string
1313 */
1314 public static function getNiceTitleOptions($id = '')
1315 {
1316 switch ($id) {
1317 case 'administration':
1318 return esc_html__('Administration', 'simple-tags');
1319 case 'auto-links':
1320 return esc_html__('Auto link', 'simple-tags');
1321 case 'features':
1322 return esc_html__('Features', 'simple-tags');
1323 case 'embeddedtags':
1324 return esc_html__('Embedded Tags', 'simple-tags');
1325 case 'tagspost':
1326 return esc_html__('Tags for Current Post', 'simple-tags');
1327 case 'relatedposts':
1328 return esc_html__('Related Posts', 'simple-tags');
1329 case 'legacy':
1330 return esc_html__('Legacy', 'simple-tags');
1331 case 'posts':
1332 return esc_html__('Posts', 'simple-tags');
1333 case 'taxopress-ai':
1334 return esc_html__('Metaboxes', 'simple-tags');
1335 case 'metabox':
1336 return esc_html__('Metabox Access', 'simple-tags');
1337 case 'linked_terms':
1338 return esc_html__('Linked Terms', 'simple-tags');
1339 case 'synonyms':
1340 return esc_html__('Term Synonyms', 'simple-tags');
1341 case 'licence':
1342 return esc_html__('License', 'simple-tags');
1343 case 'hidden_terms':
1344 return esc_html__('Hidden Terms', 'simple-tags');
1345 case 'frontend_scripts':
1346 return esc_html__('Frontend Scripts', 'simple-tags');
1347 case 'manage_terms':
1348 return esc_html__('Manage Terms', 'simple-tags');
1349 case 'mass_edit_terms':
1350 return esc_html__('Mass Edit Terms', 'simple-tags');
1351 case 'core_linked_terms':
1352 return esc_html__('Linked Terms', 'simple-tags');
1353 case 'core_synonyms_terms':
1354 return esc_html__('Term Synonyms', 'simple-tags');
1355 case 'legacy_ai_sources':
1356 return esc_html__('Auto Terms', 'simple-tags');
1357 }
1358
1359 return '';
1360 }
1361
1362 /**
1363 * This method allow to check if the DB is up to date, and if a upgrade is need for options
1364 * TODO, useful or delete ?
1365 *
1366 * @return void
1367 * @author WebFactory Ltd
1368 */
1369 public static function upgrade()
1370 {
1371 // Get current version number
1372 $current_version = get_option(STAGS_OPTIONS_NAME . '-version');
1373
1374 // Upgrade needed ?
1375 if ($current_version == false || version_compare($current_version, STAGS_VERSION, '<')) {
1376 $current_options = get_option(STAGS_OPTIONS_NAME);
1377 $default_options = (array) include(STAGS_DIR . '/inc/helper.options.default.php');
1378
1379 // Add new options
1380 foreach ($default_options as $key => $default_value) {
1381 if (!isset($current_options[$key])) {
1382 $current_options[$key] = $default_value;
1383 }
1384 }
1385
1386 // Remove old options
1387 /*foreach ($current_options as $key => $current_value) {
1388 if (!isset($default_options[$key])) {
1389 unset($current_options[$key]);
1390 }
1391 }*/
1392
1393 update_option(STAGS_OPTIONS_NAME . '-version', STAGS_VERSION);
1394 update_option(STAGS_OPTIONS_NAME, $current_options);
1395 }
1396 }
1397
1398 /**
1399 * Make a simple SQL query with some args for get terms for ajax display
1400 *
1401 * @param string $taxonomy
1402 * @param string $search
1403 * @param string $order_by
1404 * @param string $order
1405 *
1406 * @return array
1407 * @author WebFactory Ltd
1408 */
1409 public static function getTermsForAjax($taxonomy = 'post_tag', $search = '', $order_by = 'name', $order = 'ASC', $limit = 0)
1410 {
1411 global $wpdb;
1412
1413 $order = strtoupper($order);
1414 if (!in_array($order, ['ASC', 'DESC'], true)) {
1415 $order = 'ASC';
1416 }
1417
1418 $allowed_orderby = [
1419 'name' => 't.name',
1420 'count' => 'tt.count',
1421 'random' => 'RAND()',
1422 ];
1423
1424 if (isset($allowed_orderby[$order_by])) {
1425 $order_by_sql = $allowed_orderby[$order_by];
1426 } else {
1427 $order_by_sql = $allowed_orderby['name'];
1428 }
1429
1430 $limit_sql = '';
1431 $limit = (int) $limit;
1432 if ($limit > 0) {
1433 $limit_sql = $wpdb->prepare('LIMIT 0, %d', $limit);
1434 }
1435
1436 if ($taxonomy == 'linked_term_taxonomies') {
1437 $taxonomies = SimpleTags_Plugin::get_option_value('linked_terms_taxonomies');
1438 if (empty($taxonomies) || !is_array($taxonomies)) {
1439 $taxonomies = ['category', 'post_tag'];
1440 }
1441 $taxonomies_list = "'" . implode("', '", $taxonomies) . "'";
1442 }
1443
1444 if (!empty($search)) {
1445 if ($taxonomy == 'linked_term_taxonomies') {
1446
1447 $query = $wpdb->prepare(
1448 "
1449 SELECT DISTINCT t.name, t.term_id, tt.taxonomy
1450 FROM {$wpdb->terms} AS t
1451 INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
1452 WHERE tt.taxonomy IN ($taxonomies_list)
1453 AND t.name LIKE %s
1454 ORDER BY $order_by_sql $order $limit_sql
1455 ",
1456 '%' . $wpdb->esc_like($search) . '%'
1457 );
1458 } else {
1459 $query = $wpdb->prepare(
1460 "
1461 SELECT DISTINCT t.name, t.slug, t.term_id, tt.taxonomy
1462 FROM {$wpdb->terms} AS t
1463 INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
1464 WHERE tt.taxonomy = %s
1465 AND t.name LIKE %s
1466 ORDER BY $order_by_sql $order $limit_sql
1467 ",
1468 $taxonomy,
1469 '%' . $wpdb->esc_like($search) . '%'
1470 );
1471 }
1472 return $wpdb->get_results($query);
1473 } else {
1474 if ($taxonomy == 'linked_term_taxonomies') {
1475 $query = "
1476 SELECT DISTINCT t.name, t.term_id, tt.taxonomy
1477 FROM {$wpdb->terms} AS t
1478 INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
1479 WHERE tt.taxonomy IN ($taxonomies_list)
1480 ORDER BY $order_by_sql $order $limit_sql
1481 ";
1482
1483 } else {
1484 $query = $wpdb->prepare("
1485 SELECT DISTINCT t.name, t.slug, t.term_id, tt.taxonomy
1486 FROM {$wpdb->terms} AS t
1487 INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
1488 WHERE tt.taxonomy = %s
1489 ORDER BY $order_by_sql $order $limit_sql
1490 ", $taxonomy);
1491 }
1492
1493 return $wpdb->get_results($query);
1494 }
1495 }
1496
1497 /**
1498 * Plugin installer/uograde code
1499 *
1500 * @return void
1501 */
1502 public static function plugin_installer_upgrade_code()
1503 {
1504 if (!get_option('taxopress_3_23_0_upgrade_completed')) {
1505
1506 $options = SimpleTags_Plugin::get_option();
1507
1508 // add metabox default values
1509 $tax_names = array_keys(get_taxonomies([], 'names'));
1510 foreach (taxopress_get_all_wp_roles() as $role_name => $role_info) {
1511 if (in_array($role_name, ['administrator', 'editor', 'author', 'contributor'])) {
1512 $enable_acess_default_value = 1;
1513 } else {
1514 $enable_acess_default_value = 0;
1515 }
1516 $options['enable_' . $role_name . '_metabox'] = $enable_acess_default_value;
1517 $options['enable_metabox_' . $role_name . ''] = $tax_names;
1518 $options['remove_taxonomy_metabox_' . $role_name . ''] = [];
1519 }
1520
1521 SimpleTags_Plugin::set_option($options);
1522
1523 update_option('taxopress_3_23_0_upgrade_completed', true);
1524 } elseif (!get_option('taxopress_3_28_0_upgrade_completed')) {
1525
1526 if (function_exists('taxopress_get_autoterm_data')) {
1527 $autoterms = taxopress_get_autoterm_data();
1528 foreach ($autoterms as $autoterm_index => $autoterm) {
1529 //enable when to fields
1530 $autoterms[$autoterm_index]['autoterm_for_post'] = 1;
1531 $autoterms[$autoterm_index]['autoterm_for_schedule'] = 1;
1532 $autoterms[$autoterm_index]['autoterm_for_existing_content'] = 1;
1533 $autoterms[$autoterm_index]['autoterm_for_metaboxes'] = 1;
1534 // update new cloned fields for other groups
1535 $autoterms[$autoterm_index]['schedule_terms_limit'] = !empty($autoterm['terms_limit']) ? $autoterm['terms_limit'] : 5;
1536 $autoterms[$autoterm_index]['schedule_autoterm_target'] = !empty($autoterm['autoterm_target']) ? $autoterm['autoterm_target'] : 0;
1537 $autoterms[$autoterm_index]['schedule_autoterm_word'] = !empty($autoterm['autoterm_word']) ? $autoterm['autoterm_word'] : 0;
1538 $autoterms[$autoterm_index]['schedule_autoterm_hash'] = !empty($autoterm['autoterm_hash']) ? $autoterm['autoterm_hash'] : 0;
1539
1540 $autoterms[$autoterm_index]['existing_content_terms_limit'] = !empty($autoterm['terms_limit']) ? $autoterm['terms_limit'] : 5;
1541 }
1542 update_option('taxopress_autoterms', $autoterms);
1543 }
1544 update_option('taxopress_3_28_0_upgrade_completed', true);
1545 }
1546 }
1547
1548 /**
1549 * Redirect user on plugin activation
1550 *
1551 * @return void
1552 */
1553 public static function redirect_on_activate()
1554 {
1555 if (get_option('taxopress_activate')) {
1556 delete_option('taxopress_activate');
1557 wp_redirect(admin_url("admin.php?page=st_dashboard&welcome"));
1558 exit;
1559 }
1560 }
1561 }
1562