PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / 3.44.0
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms v3.44.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 3.6.2 All 177 releases
simple-tags / inc / class.admin.php

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

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