PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / 3.51.0
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms v3.51.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.51.0, at inc/class.admin.php

1,564 lines 69.3 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_terms', '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_in_progress' => esc_html__('Merging terms. Please wait...', 'simple-tags'),
746 'merge_attached_data' => esc_html__('Merging %1$s terms attached to %2$s posts. Please wait...', 'simple-tags'),
747 'merge_large_data' => esc_html__('Large dataset detected, terms will be merged in batches of 20!', 'simple-tags'),
748 'merge_none_merged' => esc_html__('No terms were merged.', 'simple-tags'),
749 'batch_merge_progress' => esc_html__('Batch %1$s of %2$s merged.', 'simple-tags'),
750 'terms_merged_text' => esc_html__('terms merged', 'simple-tags'),
751 'posts_updated_text' => esc_html__('posts updated', 'simple-tags'),
752 'merge_success_update' => esc_html__('All terms merged into %s', 'simple-tags'),
753 'ajax_merge_terms_error' => esc_html__('AJAX error on batch', 'simple-tags'),
754 'batch_error_text' => esc_html__('Error on batch %1$s:', 'simple-tags'),
755 'enable_merge_terms_slug' => SimpleTags_Plugin::get_option_value('enable_merge_terms_slug'),
756 'enable_add_terms_slug' => SimpleTags_Plugin::get_option_value('enable_add_terms_slug'),
757 'enable_remove_terms_slug' => SimpleTags_Plugin::get_option_value('enable_remove_terms_slug'),
758 'enable_rename_terms_slug' => SimpleTags_Plugin::get_option_value('enable_rename_terms_slug'),
759 'enable_mass_edit_terms_slug' => SimpleTags_Plugin::get_option_value('enable_mass-edit_terms_slug'),
760 'select_post_label' => esc_html__('Search Posts...', 'simple-tags'),
761 'loading' => esc_html__('Loading...', 'simple-tags'),
762 'preview_error' => esc_html__('Error loading preview', 'simple-tags'),
763 'enable_ibm_watson_ai_source' => SimpleTags_Plugin::get_option_value('enable_ibm_watson_ai_source'),
764 'enable_dandelion_ai_source' => SimpleTags_Plugin::get_option_value('enable_dandelion_ai_source'),
765 'enable_lseg_ai_source' => SimpleTags_Plugin::get_option_value('enable_lseg_ai_source'),
766 'plugin_url' => STAGS_URL,
767 'using_default_text' => __('Using default TaxoPress image', 'simple-tags'),
768 'select_image_label' => esc_html__('Select Media', 'simple-tags'),
769 'change_image_label' => esc_html__('Change Media', 'simple-tags'),
770 'use_default_label' => esc_html__('Use Default', 'simple-tags'),
771 'see_more_suggestions' => esc_html__('See More', 'simple-tags'),
772 'see_less_suggestions' => esc_html__('See Less', 'simple-tags'),
773 'apply_selected' => esc_html__('Apply Selected', 'simple-tags'),
774 'close_suggestions' => esc_html__('Close', 'simple-tags'),
775 'select_suggestion_alert' => esc_html__('Please select at least one suggestion to apply.', 'simple-tags'),
776 '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'),
777 'no_merge_suggestions' => esc_html__('No merge suggestions found for this taxonomy.', 'simple-tags'),
778 'suggested_terms_title' => esc_html__('Suggested Terms to Merge:', 'simple-tags'),
779 'duplicates_text' => esc_html__('duplicates', 'simple-tags'),
780 'reason_text' => esc_html__('Reason:', 'simple-tags'),
781 'select_all_label' => esc_html__('Select All', 'simple-tags'),
782 'deselect_all_label' => esc_html__('Deselect All', 'simple-tags'),
783 'terms_to_merge_text' => esc_html__('Terms to Merge', 'simple-tags'),
784 'new_term_text' => esc_html__('New Term', 'simple-tags'),
785 'reasons_text' => esc_html__('Reasons', 'simple-tags'),
786 ]);
787
788
789 //Register remodal assets
790 wp_register_script('st-remodal-js', STAGS_URL . '/assets/js/remodal.min.js', array('jquery'), STAGS_VERSION);
791 wp_register_style('st-remodal-css', STAGS_URL . '/assets/css/remodal.css', array(), STAGS_VERSION, 'all');
792 wp_register_style('st-remodal-default-theme-css', STAGS_URL . '/assets/css/remodal-default-theme.css', array(), STAGS_VERSION, 'all');
793
794 // Register location
795 $wp_post_pages = array('post.php', 'post-new.php');
796 $wp_page_pages = array('page.php', 'page-new.php');
797
798 wp_enqueue_style('st-admin-global');
799
800 // Common Helper for Post, Page and Plugin Page
801 if (
802 in_array($pagenow, $wp_post_pages) ||
803 (in_array($pagenow, $wp_page_pages) && is_page_have_tags()) ||
804 (isset($_GET['page']) && in_array($_GET['page'], $taxopress_pages))
805 ) {
806 wp_enqueue_script('st-remodal-js');
807 wp_enqueue_style('st-remodal-css');
808 wp_enqueue_style('st-remodal-default-theme-css');
809 wp_enqueue_style('st-admin');
810
811 do_action('taxopress_admin_class_after_styles_enqueue');
812 }
813
814 // add jQuery tabs for options page. Use jQuery UI Tabs from WP
815 if (isset($_GET['page']) && in_array($_GET['page'], array('st_options', 'st_terms_display', 'st_post_tags', 'st_related_posts',))) {
816 wp_enqueue_script('jquery-ui-tabs');
817 wp_enqueue_script('st-helper-options');
818 }
819
820 do_action('taxopress_admin_class_after_assets_enqueue');
821 }
822
823 /**
824 * Add settings page on WordPress admin menu
825 *
826 * @return void
827 * @author WebFactory Ltd
828 */
829 public static function admin_menu()
830 {
831 self::$admin_url = admin_url('admin.php?page=' . self::MENU_SLUG);
832
833 add_menu_page(
834 __('TaxoPress: Options', 'simple-tags'),
835 __('TaxoPress', 'simple-tags'),
836 'admin_simple_tags',
837 self::MENU_SLUG,
838 array(
839 __CLASS__,
840 'page_options',
841 ),
842 'dashicons-tag',
843 69
844 );
845 add_submenu_page(
846 self::MENU_SLUG,
847 __('TaxoPress: Options', 'simple-tags'),
848 __('Settings', 'simple-tags'),
849 'admin_simple_tags',
850 self::MENU_SLUG,
851 array(
852 __CLASS__,
853 'page_options',
854 )
855 );
856 }
857
858 /**
859 * Build HTML for page options, manage also save/reset settings
860 *
861 * @return void
862 * @author WebFactory Ltd
863 */
864 public static function page_options()
865 {
866 // Get options
867 $options = (array) SimpleTags_Plugin::get_option();
868
869 if (current_user_can('admin_simple_tags')) {
870 // Update or reset options
871 if (isset($_POST['updateoptions'])) {
872 $dashboard_options = taxopress_dashboard_options();
873 $dashboard_option_keys = array_column($dashboard_options, 'option_key');
874
875 check_admin_referer('updateresetoptions-simpletags');
876
877 $sanitized_options = [];
878
879 $is_fast_update_submission = isset($_GET['page']) && $_GET['page'] === 'st_taxopress_ai';
880
881 // This settings has been migrated to fast update screen so only update from there
882 if ($is_fast_update_submission) {
883 // add taxopress ai post type and taxonomies options so we can have all post types. TODO: This need to be a filter
884 foreach (get_post_types(['public' => true], 'names') as $post_type => $post_type_object) {
885 if ($post_type == 'post') {
886 $opt_default_value = 'post_tag';
887 } else {
888 $opt_default_value = 0;
889 }
890 $options['taxopress_ai_' . $post_type . '_metabox_default_taxonomy'] = $opt_default_value;
891 $options['taxopress_ai_' . $post_type . '_metabox_display_option'] = 'default';
892 $options['taxopress_ai_' . $post_type . '_support_private_taxonomy'] = 0;
893
894 $options['taxopress_ai_' . $post_type . '_metabox_orderby'] = 'count';
895 $options['taxopress_ai_' . $post_type . '_metabox_order'] = 'desc';
896 $options['taxopress_ai_' . $post_type . '_metabox_maximum_terms'] = 45;
897 $options['taxopress_ai_' . $post_type . '_metabox_show_post_count'] = 0;
898 $options['taxopress_ai_' . $post_type . '_metabox_show_term_slug'] = 0;
899
900 $options['taxopress_ai_' . $post_type . '_minimum_term_length'] = 2;
901 $options['taxopress_ai_' . $post_type . '_maximum_term_length'] = 40;
902
903 $options['taxopress_ai_' . $post_type . '_exclusions'] = '';
904 $options['enable_taxopress_ai_' . $post_type . '_metabox'] = $opt_default_value;
905 $options['taxopress_ai_' . $post_type . '_metabox_filters'] = 1;
906 foreach (['post_terms', 'existing_terms', 'suggest_local_terms', 'create_terms'] as $taxopress_ai_tab) {
907 $options['enable_taxopress_ai_' . $post_type . '_' . $taxopress_ai_tab . '_tab'] = $opt_default_value;
908 }
909 }
910
911 // add metabox post type and taxonomies options so we can have all post types. TODO: This need to be a filter
912 foreach (taxopress_get_all_wp_roles() as $role_name => $role_info) {
913 if (in_array($role_name, ['administrator', 'editor', 'author', 'contributor'])) {
914 $enable_acess_default_value = 1;
915 } else {
916 $enable_acess_default_value = 0;
917 }
918 $options['enable_' . $role_name . '_metabox'] = $enable_acess_default_value;
919 $options['enable_restrict' . $role_name . '_metabox'] = $enable_acess_default_value;
920
921 // ONLY admin + editor default to can edit
922 if (!isset($options['enable_edit_' . $role_name . '_metabox'])) {
923 $options['enable_edit_' . $role_name . '_metabox'] = in_array($role_name, ['administrator', 'editor']) ? 1 : 0;
924 }
925
926 $options['enable_metabox_' . $role_name . ''] = [];
927 $options['remove_taxonomy_metabox_' . $role_name . ''] = [];
928 }
929 }
930
931 foreach ($options as $key => $value) {
932 // If this is NOT a Fast Update submission, preserve metabox/metabox-access keys
933 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)) {
934 // Keep existing value as-is
935 if (!is_array($value)) {
936 $sanitized_options[$key] = taxopress_sanitize_text_field($value);
937 } else {
938 $sanitized_options[$key] = map_deep($value, 'sanitize_text_field');
939 }
940 continue;
941 }
942
943 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
944 $post_value = isset($_POST[$key]) ? $_POST[$key] : '';
945
946 if (empty($post_value) && in_array($key, $dashboard_option_keys)) {
947 $post_value = SimpleTags_Plugin::get_option_value($key);
948 }
949
950 if (!is_array($post_value)) {
951 $sanitized_options[$key] = taxopress_sanitize_text_field($post_value);
952 } else {
953 $sanitized_options[$key] = map_deep($post_value, 'sanitize_text_field');
954 }
955 }
956 $options = $sanitized_options;
957
958 SimpleTags_Plugin::set_option($options);
959
960 do_action('simpletags_settings_save_general_end');
961 do_action('taxopress_settings_saved');
962
963 add_settings_error(__CLASS__, __CLASS__, esc_html__('Options saved', 'simple-tags'), 'updated taxopress-notice');
964 } elseif (isset($_POST['reset_options'])) {
965 check_admin_referer('updateresetoptions-simpletags');
966
967 SimpleTags_Plugin::set_default_option();
968
969 add_settings_error(__CLASS__, __CLASS__, esc_html__('TaxoPress options resetted to default options!', 'simple-tags'), 'updated taxopress-notice');
970 } else {
971 //add_settings_error(__CLASS__, __CLASS__, esc_html__('Settings updated', 'simple-tags'), 'updated');
972 }
973 }
974
975 settings_errors(__CLASS__);
976 include STAGS_DIR . '/views/admin/page-settings.php';
977 }
978
979 /**
980 * Get terms for a post, format terms for input and autocomplete usage
981 *
982 * @param string $taxonomy
983 * @param integer $post_id
984 *
985 * @return string
986 * @author WebFactory Ltd
987 */
988 public static function getTermsToEdit($taxonomy = 'post_tag', $post_id = 0)
989 {
990 $post_id = (int) $post_id;
991 if (!$post_id) {
992 return '';
993 }
994
995 $is_mass_edit_page = isset($_GET['page']) && $_GET['page'] === 'st_mass_terms';
996 $show_slug = SimpleTags_Plugin::get_option_value('enable_mass-edit_terms_slug');
997
998 if ($is_mass_edit_page) {
999 $term_objects = wp_get_post_terms($post_id, $taxonomy);
1000 if (empty($term_objects) || is_wp_error($term_objects)) {
1001 return '';
1002 }
1003
1004 $terms = array();
1005 foreach ($term_objects as $term) {
1006 if ($show_slug) {
1007 if (!empty($term->slug)) {
1008 $terms[] = $term->name . ' (' . $term->slug . ')';
1009 } else {
1010 $terms[] = $term->name;
1011 }
1012 } else {
1013 $terms[] = $term->name;
1014 }
1015 }
1016
1017 $terms = join(', ', $terms);
1018 } else {
1019
1020 $terms = wp_get_post_terms($post_id, $taxonomy, array('fields' => 'names'));
1021 if (empty($terms) || is_wp_error($terms)) {
1022 return '';
1023 }
1024
1025 $terms = array_unique($terms);
1026 $terms = join(', ', $terms);
1027 }
1028
1029 $terms = esc_attr($terms);
1030 $terms = apply_filters('tags_to_edit', $terms);
1031
1032 return $terms;
1033 }
1034
1035 /**
1036 * Default content for meta box of TaxoPress
1037 *
1038 * @return string
1039 * @author WebFactory Ltd
1040 */
1041 public static function getDefaultContentBox()
1042 {
1043 if ((int) wp_count_terms('post_tag', array('hide_empty' => false)) == 0) { // TODO: Custom taxonomy
1044 return esc_html__('This feature requires at least 1 tag to work. Begin by adding tags!', 'simple-tags');
1045 } else {
1046 return esc_html__('This feature works only with activated JavaScript. Activate it in your Web browser so you can!', 'simple-tags');
1047 }
1048 }
1049
1050 /**
1051 * A short public static function for display the same copyright on all admin pages
1052 *
1053 * @return void
1054 * @author WebFactory Ltd
1055 */
1056 public static function printAdminFooter()
1057 {
1058 /* ?>
1059 <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>
1060 <?php */
1061 }
1062
1063 /**
1064 * A short public static function for display the same copyright on all taxopress admin pages
1065 *
1066 * @return void
1067 * @author Olatechpro
1068 */
1069 public static function taxopress_admin_footer()
1070 {
1071
1072 $taxopress_pages = taxopress_admin_pages();
1073
1074 if (isset($_GET['page']) && in_array($_GET['page'], $taxopress_pages)) {
1075 ?>
1076 <p class="footer_st">
1077 <?php
1078 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1079 printf(__('Thanks for using TaxoPress | %1sTaxoPress.com%2s | Version %3s', 'simple-tags'), '<a href="https://taxopress.com/">', '</a>', esc_html(STAGS_VERSION)); ?>
1080 </p>
1081 <?php
1082 }
1083 }
1084
1085 /**
1086 * Ouput formatted options
1087 *
1088 * @param array $option_data
1089 *
1090 * @return string
1091 * @author WebFactory Ltd
1092 */
1093 public static function print_options($option_data)
1094 {
1095 // Get options
1096 $option_actual = SimpleTags_Plugin::get_option();
1097
1098 // Generate output
1099 $output = '';
1100 foreach ($option_data as $section => $options) {
1101 $colspan = count($options) > 1 ? 'colspan="2"' : '';
1102
1103 if ($section === 'legacy') {
1104 $table_sub_tab = '<div class="st-legacy-subtab">
1105 <span class="active" data-content=".legacy-tag-cloud-content">'. esc_html__("Tag Cloud", "simple-tags") .'</span> |
1106 <span data-content=".legacy-post-tags-content">'. esc_html__("Tags for Current Post", "simple-tags") .'</span> |
1107 <span data-content=".legacy-related-posts-content">'. esc_html__("Related Posts", "simple-tags") .'</span> |
1108 <span data-content=".legacy-auto-link-content">'. esc_html__("Auto Links", "simple-tags") .'</span>
1109 </div>' . PHP_EOL;
1110 } elseif ($section === 'taxopress-ai') {
1111 $table_sub_tab_lists = [];
1112 $pt_index = 0;
1113 foreach (TaxoPressAiUtilities::get_post_types_options() as $post_type => $post_type_object) {
1114
1115 if (!in_array($post_type, ['attachment'])) {
1116 $active_pt = ($pt_index === 0) ? 'active' : '';
1117 $table_sub_tab_lists[] = '<span class="' . $active_pt . '" data-content=".taxopress-ai-' . $post_type . '-content">' . esc_html($post_type_object->labels->name) . '</span>';
1118 $pt_index++;
1119 }
1120 }
1121 $table_sub_tab = '<div class="st-taxopress-ai-subtab">' . join(' | ', $table_sub_tab_lists). '</div>' . PHP_EOL;
1122 } elseif ($section === 'metabox') {
1123 $table_sub_tab_lists = [];
1124 $pt_index = 0;
1125 foreach (taxopress_get_all_wp_roles() as $role_name => $role_info) {
1126 $active_pt = ($pt_index === 0) ? 'active' : '';
1127 $table_sub_tab_lists[] = '<span class="' . $active_pt . '" data-content=".metabox-' . $role_name . '-content">' . esc_html(translate_user_role($role_info['name'])) . '</span>';
1128 $pt_index++;
1129 }
1130 $table_sub_tab = '<div class="st-metabox-subtab">' . join(' | ', $table_sub_tab_lists). '</div>' . PHP_EOL;
1131 } else {
1132 $table_sub_tab = '';
1133 }
1134
1135 $output .= '<div class="group" id="' . sanitize_title($section) . '">' . PHP_EOL;
1136 $output .= $table_sub_tab;
1137 $output .= '<fieldset class="options">' . PHP_EOL;
1138 $output .= '<legend>' . self::getNiceTitleOptions($section) . '</legend>' . PHP_EOL;
1139 $output .= '<table class="form-table">' . PHP_EOL;
1140 foreach ((array) $options as $option) {
1141
1142 $class = '';
1143 if (in_array($section, ['legacy', 'taxopress-ai', 'metabox'])) {
1144 $class = $option[5];
1145 }
1146
1147 // Helper
1148 if ($option[2] == 'helper') {
1149 $output .= '<tr style="vertical-align: middle;" class="' . $class . '"><td class="helper stpexplan" ' . $colspan . '>' . stripslashes($option[4]) . '</td></tr>' . PHP_EOL;
1150 continue;
1151 }
1152
1153 // Fix notices
1154 if (!isset($option_actual[$option[0]])) {
1155 $option_actual[$option[0]] = '';
1156 }
1157
1158 // Add our custom core_terms_promo type
1159 if ($option[2] == 'core_terms_promo') {
1160 if (isset($option[4]) && !empty($option[4])) {
1161 $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;
1162 }
1163 continue;
1164 }
1165
1166 $input_type = '';
1167 $desc_html_tag = 'div';
1168 switch ($option[2]) {
1169 case 'radio':
1170 $input_type = array();
1171 foreach ($option[3] as $value => $text) {
1172 $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;
1173 }
1174 $input_type = implode('<br />', $input_type);
1175 break;
1176
1177 case 'checkbox':
1178 $desc_html_tag = 'span';
1179 $input_type = '<input type="checkbox" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($option[3]) . '" ' . (($option_actual[$option[0]]) ? 'checked="checked"' : '') . ' />' . PHP_EOL;
1180 break;
1181
1182 case 'multiselect':
1183 $desc_html_tag = 'div';
1184 $input_type = array();
1185 foreach ($option[3] as $field_name => $text) {
1186 $selected_option = (is_array($option_actual[$option[0]]) && in_array($field_name, $option_actual[$option[0]])) ? true : false;
1187 $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;
1188 }
1189 $input_type = implode('<br />', $input_type);
1190 break;
1191
1192 case 'sub_multiple_checkbox':
1193 $desc_html_tag = 'div';
1194 $input_type = array();
1195 foreach ($option[3] as $field_name => $field_option) {
1196 $checked_option = !empty($option_actual[$field_name]) ? (int) $option_actual[$field_name] : 0;
1197 $selected_option = ($checked_option > 0) ? true : false;
1198 $field_description = !empty($field_option['description']) ? '<br /><span class="description stpexplan">' . $field_option['description'] . '</span>' : '';
1199 $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;
1200 }
1201 $input_type = implode('<br />', $input_type);
1202 break;
1203
1204 case 'dropdown':// legacy
1205 $selopts = explode('/', $option[3]);
1206 $seldata = '';
1207 foreach ((array) $selopts as $sel) {
1208 $seldata .= '<option value="' . esc_attr($sel) . '" ' . ((isset($option_actual[$option[0]]) && $option_actual[$option[0]] == $sel) ? 'selected="selected"' : '') . ' >' . ucfirst($sel) . '</option>' . PHP_EOL;
1209 }
1210 $input_type = '<select id="' . $option[0] . '" name="' . $option[0] . '">' . $seldata . '</select>' . PHP_EOL;
1211 break;
1212
1213
1214 case 'select':
1215 $selopts = $option[3];
1216 $seldata = '';
1217 foreach ((array) $selopts as $sel_key => $sel_label) {
1218 $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;
1219 }
1220 $input_type = '<select id="' . $option[0] . '" name="' . $option[0] . '">' . $seldata . '</select>' . PHP_EOL;
1221 break;
1222
1223 case 'select_with_icon':
1224 $selopts = $option[3];
1225 $seldata = '';
1226 foreach ((array) $selopts as $sel_key => $sel_label) {
1227 $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;
1228 }
1229
1230 $icon_class = isset($option[6]['icon']) ? $option[6]['icon'] : 'dashicons-lock';
1231 $modal_content = isset($option[6]['modal']) ? $option[6]['modal'] : '';
1232 $disabled = !empty($option[8]) && isset($option[8]['disabled']) ? 'disabled="disabled"' : '';
1233 $class_attr = isset($option[5]) ? esc_attr($option[5]) : '';
1234 $icon_wrapper_class = isset($option[6]['icon_wrapper_class']) ? esc_attr($option[6]['icon_wrapper_class']) : 'taxopress-select-icon';
1235 $modal_wrapper_class = isset($option[6]['modal_wrapper_class']) ? esc_attr($option[6]['modal_wrapper_class']) : 'taxopress-select-icon-modal';
1236
1237 $input_type = '<div class="' . $class_attr . '">
1238 <select id="' . $option[0] . '" name="' . $option[0] . '" ' . $disabled . '>' . $seldata . '</select>
1239 <span class="' . $icon_wrapper_class . ' dashicons ' . esc_attr($icon_class) . '">
1240 <div class="' . $modal_wrapper_class . '">' . $modal_content . '</div>
1241 </span>
1242 </div>' . PHP_EOL;
1243 break;
1244
1245 case 'multiselect_with_desc_top':
1246 $desc_html_tag = 'div';
1247 $input_type_array = array();
1248 $prefix = !empty($field_description) ? '<' . $desc_html_tag . ' class="stpexplan">' . $field_description . '</' . $desc_html_tag . '>' : '';
1249 foreach ($field_options as $option_key => $option_label) {
1250 $field_value = isset($option_actual[$field_id]) ? $option_actual[$field_id] : array();
1251 $selected_option = (is_array($field_value) && in_array($option_key, $field_value)) ? true : false;
1252 $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 />';
1253 }
1254 $input_type = $prefix . implode('', $input_type_array);
1255 $field_description = '';
1256 break;
1257
1258 case 'text-color':
1259 $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;
1260 break;
1261
1262 case 'text':
1263 $input_type = '<input type="text" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($option_actual[$option[0]]) . '" class="' . $option[3] . '" />' . PHP_EOL;
1264 break;
1265
1266 case 'licence_field':
1267 $input_type = '<input type="text" id="' . $option[0] . '" name="' . $option[0] . '" value="' . esc_attr($option[3]) . '" class="' . $option[5] . '" />' . PHP_EOL;
1268 break;
1269
1270 case 'number':
1271 $min_attr = isset($option[6]) ? ' min="' . esc_attr($option[6]) . '"' : '';
1272 $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;
1273 break;
1274
1275 case 'textarea':
1276 $rows_attr = isset($option[7]['rows']) ? ' rows="' . esc_attr($option[7]['rows']) . '"' : ' rows="4"';
1277 $placeholder_attr = isset($option[7]['placeholder']) ? ' placeholder="' . esc_attr($option[7]['placeholder']) . '"' : '';
1278 $width_attr = (!empty($option[7]['width'])) ? ' style="width:' . esc_attr($option[7]['width']) . ';"' : ' style="width:100%; max-width:600px;"';
1279 $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;
1280 break;
1281 }
1282
1283 if (is_array($option[2])) {
1284 $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;
1285 }
1286
1287 // Additional Information
1288 $extra_prefix = '';
1289 $extra_suffix = '';
1290 if (!empty($option[4])) {
1291 if ($option[2] == 'sub_multiple_checkbox') {
1292 $extra_prefix = '<' . $desc_html_tag . ' class="stpexplan">' . $option[4] . '</' . $desc_html_tag . '>' . PHP_EOL;
1293 } else {
1294 $extra_suffix = '<' . $desc_html_tag . ' class="stpexplan">' . $option[4] . '</' . $desc_html_tag . '>' . PHP_EOL;
1295 }
1296 }
1297
1298 // Output
1299 $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;
1300 }
1301 $output .= '</table>' . PHP_EOL;
1302 $output .= '</fieldset>' . PHP_EOL;
1303 $output .= '</div>' . PHP_EOL;
1304 }
1305
1306 return $output;
1307 }
1308
1309 /**
1310 * Get nice title for tabs title option
1311 *
1312 * @param string $id
1313 *
1314 * @return string
1315 */
1316 public static function getNiceTitleOptions($id = '')
1317 {
1318 switch ($id) {
1319 case 'administration':
1320 return esc_html__('Administration', 'simple-tags');
1321 case 'auto-links':
1322 return esc_html__('Auto link', 'simple-tags');
1323 case 'features':
1324 return esc_html__('Features', 'simple-tags');
1325 case 'embeddedtags':
1326 return esc_html__('Embedded Tags', 'simple-tags');
1327 case 'tagspost':
1328 return esc_html__('Tags for Current Post', 'simple-tags');
1329 case 'relatedposts':
1330 return esc_html__('Related Posts', 'simple-tags');
1331 case 'legacy':
1332 return esc_html__('Legacy', 'simple-tags');
1333 case 'posts':
1334 return esc_html__('Posts', 'simple-tags');
1335 case 'taxopress-ai':
1336 return esc_html__('Metaboxes', 'simple-tags');
1337 case 'metabox':
1338 return esc_html__('Metabox Access', 'simple-tags');
1339 case 'linked_terms':
1340 return esc_html__('Linked Terms', 'simple-tags');
1341 case 'synonyms':
1342 return esc_html__('Term Synonyms', 'simple-tags');
1343 case 'licence':
1344 return esc_html__('License', 'simple-tags');
1345 case 'hidden_terms':
1346 return esc_html__('Hidden Terms', 'simple-tags');
1347 case 'frontend_scripts':
1348 return esc_html__('Frontend Scripts', 'simple-tags');
1349 case 'manage_terms':
1350 return esc_html__('Manage Terms', 'simple-tags');
1351 case 'mass_edit_terms':
1352 return esc_html__('Mass Edit Terms', 'simple-tags');
1353 case 'core_linked_terms':
1354 return esc_html__('Linked Terms', 'simple-tags');
1355 case 'core_synonyms_terms':
1356 return esc_html__('Term Synonyms', 'simple-tags');
1357 case 'legacy_ai_sources':
1358 return esc_html__('Auto Terms', 'simple-tags');
1359 }
1360
1361 return '';
1362 }
1363
1364 /**
1365 * This method allow to check if the DB is up to date, and if a upgrade is need for options
1366 * TODO, useful or delete ?
1367 *
1368 * @return void
1369 * @author WebFactory Ltd
1370 */
1371 public static function upgrade()
1372 {
1373 // Get current version number
1374 $current_version = get_option(STAGS_OPTIONS_NAME . '-version');
1375
1376 // Upgrade needed ?
1377 if ($current_version == false || version_compare($current_version, STAGS_VERSION, '<')) {
1378 $current_options = get_option(STAGS_OPTIONS_NAME);
1379 $default_options = (array) include(STAGS_DIR . '/inc/helper.options.default.php');
1380
1381 // Add new options
1382 foreach ($default_options as $key => $default_value) {
1383 if (!isset($current_options[$key])) {
1384 $current_options[$key] = $default_value;
1385 }
1386 }
1387
1388 // Remove old options
1389 /*foreach ($current_options as $key => $current_value) {
1390 if (!isset($default_options[$key])) {
1391 unset($current_options[$key]);
1392 }
1393 }*/
1394
1395 update_option(STAGS_OPTIONS_NAME . '-version', STAGS_VERSION);
1396 update_option(STAGS_OPTIONS_NAME, $current_options);
1397 }
1398 }
1399
1400 /**
1401 * Make a simple SQL query with some args for get terms for ajax display
1402 *
1403 * @param string $taxonomy
1404 * @param string $search
1405 * @param string $order_by
1406 * @param string $order
1407 *
1408 * @return array
1409 * @author WebFactory Ltd
1410 */
1411 public static function getTermsForAjax($taxonomy = 'post_tag', $search = '', $order_by = 'name', $order = 'ASC', $limit = 0)
1412 {
1413 global $wpdb;
1414
1415 $order = strtoupper($order);
1416 if (!in_array($order, ['ASC', 'DESC'], true)) {
1417 $order = 'ASC';
1418 }
1419
1420 $allowed_orderby = [
1421 'name' => 't.name',
1422 'count' => 'tt.count',
1423 'random' => 'RAND()',
1424 ];
1425
1426 if (isset($allowed_orderby[$order_by])) {
1427 $order_by_sql = $allowed_orderby[$order_by];
1428 } else {
1429 $order_by_sql = $allowed_orderby['name'];
1430 }
1431
1432 $limit_sql = '';
1433 $limit = (int) $limit;
1434 if ($limit > 0) {
1435 $limit_sql = $wpdb->prepare('LIMIT 0, %d', $limit);
1436 }
1437
1438 if ($taxonomy == 'linked_term_taxonomies') {
1439 $taxonomies = SimpleTags_Plugin::get_option_value('linked_terms_taxonomies');
1440 if (empty($taxonomies) || !is_array($taxonomies)) {
1441 $taxonomies = ['category', 'post_tag'];
1442 }
1443 $taxonomies_list = "'" . implode("', '", $taxonomies) . "'";
1444 }
1445
1446 if (!empty($search)) {
1447 if ($taxonomy == 'linked_term_taxonomies') {
1448
1449 $query = $wpdb->prepare(
1450 "
1451 SELECT DISTINCT t.name, t.term_id, tt.taxonomy
1452 FROM {$wpdb->terms} AS t
1453 INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
1454 WHERE tt.taxonomy IN ($taxonomies_list)
1455 AND t.name LIKE %s
1456 ORDER BY $order_by_sql $order $limit_sql
1457 ",
1458 '%' . $wpdb->esc_like($search) . '%'
1459 );
1460 } else {
1461 $query = $wpdb->prepare(
1462 "
1463 SELECT DISTINCT t.name, t.slug, t.term_id, tt.taxonomy
1464 FROM {$wpdb->terms} AS t
1465 INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
1466 WHERE tt.taxonomy = %s
1467 AND t.name LIKE %s
1468 ORDER BY $order_by_sql $order $limit_sql
1469 ",
1470 $taxonomy,
1471 '%' . $wpdb->esc_like($search) . '%'
1472 );
1473 }
1474 return $wpdb->get_results($query);
1475 } else {
1476 if ($taxonomy == 'linked_term_taxonomies') {
1477 $query = "
1478 SELECT DISTINCT t.name, t.term_id, tt.taxonomy
1479 FROM {$wpdb->terms} AS t
1480 INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
1481 WHERE tt.taxonomy IN ($taxonomies_list)
1482 ORDER BY $order_by_sql $order $limit_sql
1483 ";
1484
1485 } else {
1486 $query = $wpdb->prepare("
1487 SELECT DISTINCT t.name, t.slug, t.term_id, tt.taxonomy
1488 FROM {$wpdb->terms} AS t
1489 INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
1490 WHERE tt.taxonomy = %s
1491 ORDER BY $order_by_sql $order $limit_sql
1492 ", $taxonomy);
1493 }
1494
1495 return $wpdb->get_results($query);
1496 }
1497 }
1498
1499 /**
1500 * Plugin installer/uograde code
1501 *
1502 * @return void
1503 */
1504 public static function plugin_installer_upgrade_code()
1505 {
1506 if (!get_option('taxopress_3_23_0_upgrade_completed')) {
1507
1508 $options = SimpleTags_Plugin::get_option();
1509
1510 // add metabox default values
1511 $tax_names = array_keys(get_taxonomies([], 'names'));
1512 foreach (taxopress_get_all_wp_roles() as $role_name => $role_info) {
1513 if (in_array($role_name, ['administrator', 'editor', 'author', 'contributor'])) {
1514 $enable_acess_default_value = 1;
1515 } else {
1516 $enable_acess_default_value = 0;
1517 }
1518 $options['enable_' . $role_name . '_metabox'] = $enable_acess_default_value;
1519 $options['enable_metabox_' . $role_name . ''] = $tax_names;
1520 $options['remove_taxonomy_metabox_' . $role_name . ''] = [];
1521 }
1522
1523 SimpleTags_Plugin::set_option($options);
1524
1525 update_option('taxopress_3_23_0_upgrade_completed', true);
1526 } elseif (!get_option('taxopress_3_28_0_upgrade_completed')) {
1527
1528 if (function_exists('taxopress_get_autoterm_data')) {
1529 $autoterms = taxopress_get_autoterm_data();
1530 foreach ($autoterms as $autoterm_index => $autoterm) {
1531 //enable when to fields
1532 $autoterms[$autoterm_index]['autoterm_for_post'] = 1;
1533 $autoterms[$autoterm_index]['autoterm_for_schedule'] = 1;
1534 $autoterms[$autoterm_index]['autoterm_for_existing_content'] = 1;
1535 $autoterms[$autoterm_index]['autoterm_for_metaboxes'] = 1;
1536 // update new cloned fields for other groups
1537 $autoterms[$autoterm_index]['schedule_terms_limit'] = !empty($autoterm['terms_limit']) ? $autoterm['terms_limit'] : 5;
1538 $autoterms[$autoterm_index]['schedule_autoterm_target'] = !empty($autoterm['autoterm_target']) ? $autoterm['autoterm_target'] : 0;
1539 $autoterms[$autoterm_index]['schedule_autoterm_word'] = !empty($autoterm['autoterm_word']) ? $autoterm['autoterm_word'] : 0;
1540 $autoterms[$autoterm_index]['schedule_autoterm_hash'] = !empty($autoterm['autoterm_hash']) ? $autoterm['autoterm_hash'] : 0;
1541
1542 $autoterms[$autoterm_index]['existing_content_terms_limit'] = !empty($autoterm['terms_limit']) ? $autoterm['terms_limit'] : 5;
1543 }
1544 update_option('taxopress_autoterms', $autoterms);
1545 }
1546 update_option('taxopress_3_28_0_upgrade_completed', true);
1547 }
1548 }
1549
1550 /**
1551 * Redirect user on plugin activation
1552 *
1553 * @return void
1554 */
1555 public static function redirect_on_activate()
1556 {
1557 if (get_option('taxopress_activate')) {
1558 delete_option('taxopress_activate');
1559 wp_redirect(admin_url("admin.php?page=st_dashboard&welcome"));
1560 exit;
1561 }
1562 }
1563 }
1564