PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / 3.38.0
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms v3.38.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.manage.php

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

1,323 lines 63.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class SimpleTags_Admin_Manage
4 {
5 const MENU_SLUG = 'st_options';
6
7 // class instance
8 public static $instance;
9
10 /**
11 * Constructor
12 *
13 * @return void
14 * @author WebFactory Ltd
15 */
16 public function __construct()
17 {
18 add_filter('set-screen-option', [ __CLASS__, 'set_screen' ], 10, 3);
19 // Admin menu
20 add_action('admin_menu', array( $this, 'admin_menu' ));
21
22 // Register taxo, parent method...
23 SimpleTags_Admin::register_taxonomy();
24
25 // Javascript
26 add_action('admin_enqueue_scripts', array( __CLASS__, 'admin_enqueue_scripts' ), 11);
27
28 //load ajax
29 add_action('wp_ajax_taxopress_check_delete_terms', array( $this, 'handle_taxopress_check_delete_terms_ajax'));
30 add_action('wp_ajax_taxopress_autocomplete_terms', [ $this, 'handle_taxopress_autocomplete_terms']);
31 add_action('wp_ajax_taxopress_merge_terms_batch', [$this, 'taxopress_merge_terms_batch']);
32
33 }
34
35 /**
36 * Init somes JS and CSS need for this feature
37 *
38 * @return void
39 * @author WebFactory Ltd
40 */
41 public static function admin_enqueue_scripts()
42 {
43 wp_register_script('st-helper-manage', STAGS_URL . '/assets/js/helper-manage.js', array( 'jquery' ), STAGS_VERSION);
44
45 // add JS for manage click tags
46 if (isset($_GET['page']) && $_GET['page'] == 'st_manage') {
47 wp_enqueue_script('st-helper-manage');
48 }
49 }
50
51 public static function set_screen($status, $option, $value)
52 {
53 return $value;
54 }
55
56 /**
57 * Add WP admin menu for Tags
58 *
59 * @return void
60 * @author WebFactory Ltd
61 */
62 public function admin_menu()
63 {
64 $hook = add_submenu_page(
65 self::MENU_SLUG,
66 __('TaxoPress: Manage Terms', 'simple-tags'),
67 __('Manage Terms', 'simple-tags'),
68 'simple_tags',
69 'st_manage',
70 array(
71 $this,
72 'page_manage_tags',
73 )
74 );
75 }
76
77 /**
78 * Method for build the page HTML manage tags
79 *
80 * @return void
81 * @author WebFactory Ltd
82 */
83 public function page_manage_tags()
84 {
85 $default_tab = '';
86 // Control Post data
87 if (isset($_POST['term_action'])) {
88 if (!current_user_can('simple_tags')) {
89 add_settings_error(__CLASS__, __CLASS__, esc_html__('Permission denied!', 'simple-tags'), 'error taxopress-notice');
90 } elseif (! wp_verify_nonce(sanitize_text_field($_POST['term_nonce']), 'simpletags_admin')) { // Origination and intention
91
92 add_settings_error(__CLASS__, __CLASS__, esc_html__('Security problem. Try again.', 'simple-tags'), 'error taxopress-notice');
93 } elseif (! isset(SimpleTags_Admin::$taxonomy) || ! taxonomy_exists(SimpleTags_Admin::$taxonomy)) { // Valid taxo ?
94
95 add_settings_error(__CLASS__, __CLASS__, esc_html__('Missing valid taxonomy for work. Try again.', 'simple-tags'), 'error taxopress-notice');
96 } elseif ($_POST['term_action'] == 'renameterm') {
97 $taxonomy = isset($_POST['current_taxo']) ? sanitize_text_field($_POST['current_taxo']) : 'post_tag';
98 $post_type = isset($_POST['current_cpt']) ? sanitize_text_field($_POST['current_cpt']) : 'post';
99
100 SimpleTags_Admin::$taxonomy = $taxonomy;
101 SimpleTags_Admin::$post_type = $post_type;
102
103 $oldtag = isset($_POST['renameterm_old']) ? sanitize_text_field($_POST['renameterm_old']) : '';
104 $newtag = isset($_POST['renameterm_new']) ? sanitize_text_field($_POST['renameterm_new']) : '';
105 self::renameTerms($taxonomy, $oldtag, $newtag);
106 $default_tab = '.st-rename-terms';
107 } elseif ($_POST['term_action'] == 'mergeterm') {
108 $taxonomy = isset($_POST['current_taxo']) ? sanitize_text_field($_POST['current_taxo']) : 'post_tag';
109 $post_type = isset($_POST['current_cpt']) ? sanitize_text_field($_POST['current_cpt']) : 'post';
110
111 SimpleTags_Admin::$taxonomy = $taxonomy;
112 SimpleTags_Admin::$post_type = $post_type;
113
114 $oldtag = isset($_POST['renameterm_old']) ? sanitize_text_field($_POST['renameterm_old']) : '';
115 $newtag = isset($_POST['renameterm_new']) ? sanitize_text_field($_POST['renameterm_new']) : '';
116 $merge_type = isset($_POST['mergeterm_type']) ? sanitize_text_field($_POST['mergeterm_type']) : '';
117 self::mergeTerms($taxonomy, $oldtag, $newtag, $merge_type);
118 $default_tab = '.st-merge-terms';
119 } elseif ($_POST['term_action'] == 'addterm') {
120 $taxonomy = isset($_POST['current_taxo']) ? sanitize_text_field($_POST['current_taxo']) : 'post_tag';
121 $post_type = isset($_POST['current_cpt']) ? sanitize_text_field($_POST['current_cpt']) : 'post';
122
123 SimpleTags_Admin::$taxonomy = $taxonomy;
124 SimpleTags_Admin::$post_type = $post_type;
125
126 $oldtag = isset($_POST['addterm_match']) ? sanitize_text_field($_POST['addterm_match']) : '';
127 $newtag = isset($_POST['addterm_new']) ? sanitize_text_field($_POST['addterm_new']) : '';
128 self::addMatchTerms($taxonomy, $oldtag, $newtag);
129 $default_tab = '.st-add-terms';
130 } elseif ($_POST['term_action'] == 'removeterm') {
131 $taxonomy = isset($_POST['current_taxo']) ? sanitize_text_field($_POST['current_taxo']) : 'post_tag';
132 $post_type = isset($_POST['current_cpt']) ? sanitize_text_field($_POST['current_cpt']) : 'post';
133
134 SimpleTags_Admin::$taxonomy = $taxonomy;
135 SimpleTags_Admin::$post_type = $post_type;
136
137 $matchtag = isset($_POST['removeterm_match']) ? sanitize_text_field($_POST['removeterm_match']) : '';
138 $removetag = isset($_POST['remove_term']) ? sanitize_text_field($_POST['remove_term']) : '';
139 self::removeMatchTerms($taxonomy, $matchtag, $removetag);
140 $default_tab = '.st-remove-terms';
141 } elseif ($_POST['term_action'] == 'remove-rarelyterms') {
142 $taxonomy = isset($_POST['current_taxo']) ? sanitize_text_field($_POST['current_taxo']) : 'post_tag';
143 $post_type = isset($_POST['current_cpt']) ? sanitize_text_field($_POST['current_cpt']) : 'post';
144
145 SimpleTags_Admin::$taxonomy = $taxonomy;
146 SimpleTags_Admin::$post_type = $post_type;
147
148 self::removeRarelyUsed($taxonomy, (int) $_POST['number-rarely']);
149 $default_tab = '.st-delete-unuused-terms';
150 } /* elseif ( $_POST['term_action'] == 'editslug' ) {
151
152 $matchtag = (isset($_POST['tagname_match'])) ? $_POST['tagname_match'] : '';
153 $newslug = (isset($_POST['tagslug_new'])) ? $_POST['tagslug_new'] : '';
154 self::editTermSlug( SimpleTags_Admin::$taxonomy, $matchtag, $newslug );
155
156 }*/
157 }
158
159 if ($default_tab && !empty($default_tab)) {
160 //trigger default tab click on load
161 echo '<div class="load-st-default-tab" data-page="'.esc_attr($default_tab).'"></div>';
162 }
163 $active_tab_slug = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'add-terms';
164
165 // Default order
166 if (! isset($_GET['order'])) {
167 $_GET['order'] = 'name-asc';
168 }
169
170 settings_errors(__CLASS__); ?>
171 <div class="clear"></div>
172 <div class="taxopress-block-wrap">
173 <div class="wrap st_wrap tagcloudui st-manage-terms-page admin-settings wrap st_wrap">
174
175 <h1><?php _e('Manage Terms', 'simple-tags'); ?>
176 </h1>
177 <div class="taxopress-description"><?php esc_html_e('This feature allows you to manage your content terms by adding, renaming, merging and deleting unused terms.', 'simple-tags'); ?></div>
178
179 <div class="clear"></div>
180
181 <hr class="wp-header-end">
182 <div class="clear"></div>
183
184 <div id="col-container" class="wp-clearfix">
185 <div class="col-wrap">
186 <div class="form-wrap">
187 <ul class="simple-tags-nav-tab-wrapper">
188 <li class="nav-tab <?php echo $active_tab_slug === 'add-terms' ? 'nav-tab-active' : ''; ?>" data-page=".st-add-terms">
189 <?php echo esc_html__('Add terms', 'simple-tags'); ?>
190 </li>
191 <li class="nav-tab <?php echo $active_tab_slug === 'remove-terms' ? 'nav-tab-active' : ''; ?>" data-page=".st-remove-terms">
192 <?php echo esc_html__('Remove terms', 'simple-tags'); ?>
193 </li>
194 <li class="nav-tab <?php echo $active_tab_slug === 'rename-terms' ? 'nav-tab-active' : ''; ?>" data-page=".st-rename-terms">
195 <?php echo esc_html__('Rename terms', 'simple-tags'); ?>
196 </li>
197 <li class="nav-tab <?php echo $active_tab_slug === 'merge-terms' ? 'nav-tab-active' : ''; ?>" data-page=".st-merge-terms">
198 <?php echo esc_html__('Merge terms', 'simple-tags'); ?>
199 </li>
200 <li class="nav-tab <?php echo $active_tab_slug === 'delete-unuused-terms' ? 'nav-tab-active' : ''; ?>" data-page=".st-delete-unuused-terms">
201 <?php echo esc_html__('Delete unused terms', 'simple-tags'); ?>
202 </li>
203 </ul>
204 <div class="clear"></div>
205
206
207
208 <table class="form-table">
209
210 <tr valign="top" class="auto-terms-content st-add-terms" style="<?php echo $active_tab_slug === 'add-terms' ? '' : 'display:none;'; ?>">
211 <td>
212 <?php SimpleTags_Admin::tabSelectorTaxonomy('add-terms', 'st_manage'); ?>
213 <h2><?php _e('Add Terms', 'simple-tags'); ?></h2>
214 <p><?php printf(esc_html__('This feature lets you add one or more new terms to all %s which match any of the terms given.', 'simple-tags'), esc_html(SimpleTags_Admin::$post_type_name)); ?></p>
215 <p><?php printf(esc_html__('Terms will be added to all %s If no "Term(s) to match" is specified.', 'simple-tags'), esc_html(SimpleTags_Admin::$post_type_name)); ?></p>
216
217 <fieldset>
218 <form action="" method="post">
219 <input type="hidden" name="term_action" value="addterm" />
220 <input type="hidden" name="term_nonce" value="<?php echo esc_attr(wp_create_nonce('simpletags_admin')); ?>" />
221 <input type="hidden" name="current_tab" value="add-terms" />
222 <input type="hidden" name="current_taxo" value="<?php echo esc_attr(get_option('add-terms_taxo')); ?>" />
223 <input type="hidden" name="current_cpt" value="<?php echo esc_attr(get_option('add-terms_cpt')); ?>" />
224
225 <p class="terms-type-options">
226 <label>
227 <input type="radio" id="addterm_type" class="addterm_type_all_posts" name="addterm_type" value="all_posts" checked="checked">
228 <?php printf(esc_html__('Add terms to all %s.', 'simple-tags'), esc_html(SimpleTags_Admin::$post_type_name)); ?>
229 </label><br>
230 <label>
231 <input type="radio" id="addterm_type" class="addterm_type_matched_only" name="addterm_type" value="matched_only">
232 <?php _e('Add terms only to posts with specific terms attached.', 'simple-tags'); ?>
233 </label>
234 </p>
235
236 <p class="terms-to-maatch-input" style="display: none;">
237 <label for="addterm_match"><?php _e('Term(s) to match:', 'simple-tags'); ?></label><br />
238 <textarea type="text" class="autocomplete-input tag-cloud-input taxopress-expandable-textarea add-terms-autocomplete" id="addterm_match" name="addterm_match" size="80" data-tab="add-terms"
239 data-taxo="<?php echo esc_attr(get_option('add-terms_taxo')); ?>"></textarea>
240 </p>
241
242 <p>
243 <label for="addterm_new"><?php _e('Term(s) to add:', 'simple-tags'); ?></label><br />
244 <textarea type="text" class="autocomplete-input taxopress-expandable-textarea add-terms-autocomplete" id="addterm_new" name="addterm_new" size="80" data-tab="add-terms"
245 data-taxo="<?php echo esc_attr(get_option('add-terms_taxo')); ?>"></textarea>
246 </p>
247
248 <input class="button-primary" type="submit" name="Add" value="<?php _e('Add', 'simple-tags'); ?>" />
249 </form>
250 </fieldset>
251 </td>
252 </tr>
253
254 <tr valign="top" class="auto-terms-content st-remove-terms" style="<?php echo $active_tab_slug === 'remove-terms' ? '' : 'display:none;'; ?>">
255 <td>
256 <?php SimpleTags_Admin::tabSelectorTaxonomy('remove-terms', 'st_manage'); ?>
257 <h2><?php _e('Remove Terms', 'simple-tags'); ?></h2>
258 <p><?php printf(esc_html__('This feature lets you remove one or more terms from all %s which match any of the terms given.', 'simple-tags'), esc_html(SimpleTags_Admin::$post_type_name)); ?></p>
259 <p><?php printf(esc_html__('Terms will be removed from all %s If no "Term(s) to match" is specified.', 'simple-tags'), esc_html(SimpleTags_Admin::$post_type_name)); ?></p>
260
261 <fieldset>
262 <form action="" method="post">
263 <input type="hidden" name="term_action" value="removeterm" />
264 <input type="hidden" name="term_nonce" value="<?php echo esc_attr(wp_create_nonce('simpletags_admin')); ?>" />
265 <input type="hidden" name="current_tab" value="remove-terms" />
266 <input type="hidden" name="current_taxo" value="<?php echo esc_attr(get_option('remove-terms_taxo')); ?>" />
267 <input type="hidden" name="current_cpt" value="<?php echo esc_attr(get_option('remove-terms_cpt')); ?>" />
268
269 <p class="terms-type-options">
270 <label>
271 <input type="radio" id="removeterm_type" class="removeterm_type_all_posts" name="removeterm_type" value="all_posts" checked="checked">
272 <?php printf(esc_html__('Remove terms from all %s.', 'simple-tags'), esc_html(SimpleTags_Admin::$post_type_name)); ?>
273 </label><br>
274 <label>
275 <input type="radio" id="removeterm_type" class="removeterm_type_matched_only" name="removeterm_type" value="matched_only">
276 <?php _e('Remove terms only from posts with specific terms attached.', 'simple-tags'); ?>
277 </label>
278 </p>
279
280 <p class="removeterms-to-match-input" style="display: none;">
281 <label for="removeterm_match"><?php _e('Term(s) to match:', 'simple-tags'); ?></label><br />
282 <textarea type="text" class="autocomplete-input tag-cloud-input taxopress-expandable-textarea remove-terms-autocomplete" id="removeterm_match" name="removeterm_match" size="80" data-tab="remove-terms"
283 data-taxo="<?php echo esc_attr(get_option('remove-terms_taxo')); ?>"></textarea>
284 </p>
285
286 <p>
287 <label for="remove_term"><?php _e('Term(s) to remove:', 'simple-tags'); ?></label><br />
288 <textarea type="text" class="autocomplete-input taxopress-expandable-textarea remove-terms-autocomplete" id="remove_term" name="remove_term" size="80" data-tab="remove-terms"
289 data-taxo="<?php echo esc_attr(get_option('remove-terms_taxo')); ?>"></textarea>
290 </p>
291
292 <input class="button-primary" type="submit" name="Remove" value="<?php _e('Remove', 'simple-tags'); ?>" />
293 </form>
294 </fieldset>
295 </td>
296 </tr>
297
298 <tr valign="top" class="auto-terms-content st-rename-terms" style="<?php echo $active_tab_slug === 'rename-terms' ? '' : 'display:none;'; ?>">
299 <td>
300 <?php SimpleTags_Admin::tabSelectorTaxonomy('rename-terms', 'st_manage'); ?>
301 <h2><?php _e('Rename Terms', 'simple-tags'); ?></h2>
302 <p><?php _e('Enter the terms to rename and their new names.', 'simple-tags'); ?></p>
303
304 <fieldset>
305 <form action="" method="post">
306 <input type="hidden" name="term_action" value="renameterm" />
307 <input type="hidden" name="term_nonce" value="<?php echo esc_attr(wp_create_nonce('simpletags_admin')); ?>" />
308 <input type="hidden" name="current_tab" value="rename-terms" />
309 <input type="hidden" name="current_taxo" value="<?php echo esc_attr(get_option('rename-terms_taxo')); ?>" />
310 <input type="hidden" name="current_cpt" value="<?php echo esc_attr(get_option('rename-terms_cpt')); ?>" />
311 <p>
312 <label for="renameterm_old"><?php _e('Term(s) to rename:', 'simple-tags'); ?></label><br />
313 <textarea type="text" class="autocomplete-input tag-cloud-input taxopress-expandable-textarea rename-terms-autocomplete" id="renameterm_old" name="renameterm_old" size="80" data-taxo="<?php echo esc_attr(get_option('rename-terms_taxo')); ?>"></textarea>
314 </p>
315
316 <p>
317 <label for="renameterm_new"><?php _e('New term name(s):', 'simple-tags'); ?></label><br />
318 <textarea type="text" class="autocomplete-input taxopress-expandable-textarea rename-terms-autocomplete" id="renameterm_new" name="renameterm_new" size="80" data-taxo="<?php echo esc_attr(get_option('rename-terms_taxo')); ?>"></textarea>
319 </p>
320
321 <input class="button-primary" type="submit" name="rename" value="<?php _e('Rename', 'simple-tags'); ?>" />
322 </form>
323 </fieldset>
324 </td>
325 </tr>
326
327 <tr valign="top" class="auto-terms-content st-merge-terms" style="<?php echo $active_tab_slug === 'merge-terms' ? '' : 'display:none;'; ?>">
328 <td>
329 <?php SimpleTags_Admin::tabSelectorTaxonomy('merge-terms', 'st_manage'); ?>
330 <h2><?php _e('Merge Terms', 'simple-tags'); ?></h2>
331 <p><?php esc_html_e('This feature will delete existing terms and replace them with another term.', 'simple-tags'); ?></p>
332
333 <fieldset>
334 <form action="" method="post" class="merge-terms-form">
335 <input type="hidden" name="term_action" value="mergeterm" />
336 <input type="hidden" name="term_nonce" value="<?php echo esc_attr(wp_create_nonce('simpletags_admin')); ?>" />
337 <input type="hidden" name="current_tab" value="merge-terms" />
338 <input type="hidden" name="current_taxo" value="<?php echo esc_attr(get_option('merge-terms_taxo')); ?>" />
339 <input type="hidden" name="current_cpt" value="<?php echo esc_attr(get_option('merge-terms_cpt')); ?>" />
340
341 <p class="terms-type-options">
342 <label><input type="radio" id="mergeterm_type" class="mergeterm_type_different_name" name="mergeterm_type" value="different_name" checked="checked"><?php _e('Merge terms with different name.', 'simple-tags'); ?></label><br>
343 <label><input type="radio" id="mergeterm_type" class="mergeterm_type_same_name" name="mergeterm_type" value="same_name"><?php esc_html_e('Merge terms with same name.', 'simple-tags'); ?></label>
344 </p>
345
346 <p>
347 <label for="renameterm_old"><?php _e('Term(s) to merge.', 'simple-tags'); ?></label><br />
348 <textarea type="text" class="autocomplete-input tag-cloud-input taxopress-expandable-textarea merge-feature-autocomplete" id="mergeterm_old" name="renameterm_old" size="80" data-taxo="<?php echo esc_attr(get_option('merge-terms_taxo')); ?>"></textarea>
349 </p>
350
351 <p class="new_name_input">
352 <label for="renameterm_new"><?php _e('New term. The Old terms will be deleted and any posts assigned to the old terms will be re-assigned to this term.', 'simple-tags'); ?></label><br />
353 <textarea type="text" class="autocomplete-input taxopress-expandable-textarea merge-feature-autocomplete" id="mergeterm_new" name="renameterm_new" size="80" data-taxo="<?php echo esc_attr(get_option('merge-terms_taxo')); ?>"></textarea>
354 </p>
355
356 <input class="button-primary" type="submit" name="merge" id="merge-terms" value="<?php _e('Merge', 'simple-tags'); ?>" />
357 <div id="merge-progress" style="margin-top: 10px;"></div>
358 </form>
359 </fieldset>
360 </td>
361 </tr>
362
363 <tr valign="top" class="auto-terms-content st-delete-unuused-terms" style="<?php echo $active_tab_slug === 'delete-unuused-terms' ? '' : 'display:none;'; ?>">
364 <td>
365 <?php SimpleTags_Admin::tabSelectorTaxonomy('delete-unuused-terms', 'st_manage'); ?>
366 <h2><?php esc_html_e('Remove rarely used terms', 'simple-tags'); ?></h2>
367 <p><?php esc_html_e('This feature allows you to remove rarely used terms.', 'simple-tags'); ?></p>
368 <p><?php printf(esc_html__('If you choose 5, Taxopress will delete all terms attached to less than 5 %s.', 'simple-tags'), esc_html(SimpleTags_Admin::$post_type_name)); ?></p>
369
370 <fieldset>
371 <form action="" method="post">
372 <input type="hidden" name="term_action" value="remove-rarelyterms" />
373 <input type="hidden" name="term_nonce" value="<?php echo esc_attr(wp_create_nonce('simpletags_admin')); ?>" />
374 <input type="hidden" name="current_tab" value="delete-unuused-terms" />
375 <input type="hidden" name="current_taxo" value="<?php echo esc_attr(get_option('delete-unuused-terms_taxo')); ?>" />
376 <input type="hidden" name="current_cpt" value="<?php echo esc_attr(get_option('delete-unuused-terms_cpt')); ?>" />
377
378 <p>
379 <label for="number-delete"><?php _e('Minimum number of uses for each term:', 'simple-tags'); ?></label><br />
380 <select name="number-rarely" id="number-delete">
381 <?php for ($i = 1; $i <= 100; $i++) : ?>
382 <option value="<?php echo esc_attr($i); ?>"><?php echo esc_html($i); ?></option>
383 <?php endfor; ?>
384 </select>
385 </p>
386
387 <label for="check-terms"><?php _e('Check how many terms will be deleted:', 'simple-tags'); ?></label><br />
388 <input style="margin-top: 2px;" id="check-terms-btn" class="button-primary" type="submit" name="Check" value="<?php esc_attr_e('Check Terms', 'simple-tags'); ?>" />
389 <div id="terms-feedback"></div>
390
391 <label for="terms-delete"><?php _e('Delete rarely used terms:', 'simple-tags'); ?></label><br />
392 <input style="margin-top: 2px;" class="button-secondary delete-unused-term" type="submit" name="Delete" value="<?php esc_attr_e('Delete Terms', 'simple-tags'); ?>" />
393 </form>
394 </fieldset>
395 </td>
396 </tr>
397
398 <?php /*
399 <tr valign="top">
400 <th scope="row"><strong><?php _e('Edit Term Slug', 'simple-tags'); ?></strong></th>
401 <td>
402 <p><?php _e('Enter the term name to edit and its new slug. <a href="http://codex.wordpress.org/Glossary#Slug">Slug definition</a>', 'simple-tags'); ?></p>
403
404 <fieldset>
405 <form action="" method="post">
406 <input type="hidden" name="taxo" value="<?php echo esc_attr(SimpleTags_Admin::$taxonomy); ?>" />
407 <input type="hidden" name="cpt" value="<?php echo esc_attr(SimpleTags_Admin::$post_type); ?>" />
408
409 <input type="hidden" name="term_action" value="editslug" />
410 <input type="hidden" name="term_nonce" value="<?php echo wp_create_nonce('simpletags_admin'); ?>" />
411
412 <p>
413 <label for="tagname_match"><?php _e('Term(s) to match:', 'simple-tags'); ?></label>
414 <br />
415 <input type="text" class="autocomplete-input" id="tagname_match" name="tagname_match" size="80" />
416 </p>
417
418 <p>
419 <label for="tagslug_new"><?php _e('Slug(s) to set:', 'simple-tags'); ?></label>
420 <br />
421 <input type="text" class="autocomplete-input" id="tagslug_new" name="tagslug_new" size="80" />
422 </p>
423
424 <input class="button-primary" type="submit" name="edit" value="<?php _e('Edit', 'simple-tags'); ?>" />
425 </form>
426 </fieldset>
427 </td>
428 </tr>
429 */
430 ?>
431
432 </table>
433
434
435
436 </div>
437 </div>
438
439
440 <div class="clear"></div>
441
442 </div>
443 </div>
444 <div class="taxopress-right-sidebar admin-settings-sidebar">
445 <?php do_action('taxopress_admin_after_sidebar'); ?>
446 </div>
447
448 </div>
449
450
451 <?php SimpleTags_Admin::printAdminFooter(); ?>
452
453
454
455 <?php
456 do_action('simpletags-manage_terms', SimpleTags_Admin::$taxonomy);
457 }
458
459 /**
460 * Method to merge tags
461 *
462 * @param string $taxonomy
463 * @param string $old
464 * @param string $new
465 *
466 * @return boolean
467 * @author olatechpro
468 */
469 public static function mergeTerms($taxonomy = 'post_tag', $old = '', $new = '', $merge_type = '')
470 {
471 // Helper function to extract term name (ignoring slug in brackets)
472 $extractTermName = function ($term) {
473 return trim(preg_replace('/\s*\(.*?\)$/', '', $term));
474 };
475
476 if ($merge_type === 'same_name') {
477 $old_terms = explode(',', $old);
478 $old_terms = array_map($extractTermName, $old_terms);
479 $old_terms = array_filter($old_terms, '_delete_empty_element');
480 $retained_slug_param = isset($_POST['retained_slug']) ? sanitize_title($_POST['retained_slug']) : '';
481
482 if (empty($old_terms)) {
483 add_settings_error(__CLASS__, __CLASS__, esc_html__('No terms provided for merging!', 'simple-tags'), 'error taxopress-notice');
484 return false;
485 }
486
487 $terms =[];
488 foreach ($old_terms as $term_name) {
489 $term_objects = get_terms([
490 'taxonomy' => $taxonomy,
491 'name' => sanitize_text_field($term_name),
492 'hide_empty' => false,
493 ]);
494
495 if (is_array($term_objects) && count($term_objects) > 1) {
496 $terms = array_merge($terms, $term_objects);
497 }
498 }
499
500 if (empty($terms)) {
501 add_settings_error(__CLASS__, __CLASS__, esc_html__('No terms with the same name found.', 'simple-tags'), 'error taxopress-notice');
502 return false;
503 }
504
505 usort($terms, function ($a, $b) use ($term_name, $retained_slug_param) {
506 // If a retained slug is provided, sort that term to the top
507 if ($retained_slug_param) {
508 if ($a->slug === $retained_slug_param) return -1;
509 if ($b->slug === $retained_slug_param) return 1;
510 }
511 // Score based on similarity to term name
512 similar_text($term_name, $a->slug, $similarity_a);
513 similar_text($term_name, $b->slug, $similarity_b);
514
515 if ($similarity_a === $similarity_b) {
516 // If similarity is the same, sort by length (shortest first)
517 return strlen($a->slug) - strlen($b->slug);
518 }
519
520 // Otherwise, sort by similarity (higher first)
521 return $similarity_b - $similarity_a;
522 });
523
524 // Retain the term with the highest similarity and shortest slug (first in sorted array)
525 $retained_term = $terms[0];
526 $retained_slug = $retained_term->slug;
527 $retained_id = $retained_term->term_id;
528
529 // Collect terms to delete
530 $terms_to_delete = array_filter($terms, function ($term) use ($retained_id) {
531 return $term->term_id !== $retained_id;
532 });
533
534 // Reassign objects and delete old terms (existing logic)
535 $terms_id = array_map(function ($term) {
536 return $term->term_id;
537 }, $terms_to_delete);
538
539 $objects_id = get_objects_in_term($terms_id, $taxonomy, ['fields' => 'ids']);
540 foreach ($objects_id as $object_id) {
541 // Check if the object already has the term assigned
542 $current_terms = wp_get_object_terms($object_id, $taxonomy, ['fields' => 'ids']);
543 if (!in_array($retained_id, $current_terms)) {
544 wp_set_object_terms($object_id, $retained_slug, $taxonomy, true);
545 }
546 }
547
548 foreach ($terms_to_delete as $term) {
549 wp_delete_term($term->term_id, $taxonomy);
550 }
551
552 // Clean caches
553 clean_object_term_cache($objects_id, $taxonomy);
554 clean_term_cache($terms_id, $taxonomy);
555
556 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('Merged term(s) with the same name "%s". %d posts updated.', 'simple-tags'), $retained_term->name, count($objects_id)), 'updated taxopress-notice');
557 return [
558 'success' => true,
559 'retained_slug' => $retained_slug,
560 'posts_updated' => count($objects_id),
561 'post_ids' => $objects_id,
562 'terms_merged' => count($terms_to_delete) + 1,
563 ];
564
565 } else {
566
567 if (trim(str_replace(',', '', stripslashes($new))) == '' && $merge_type !== 'same_name' ) {
568 add_settings_error(__CLASS__, __CLASS__, esc_html__('No new term specified!', 'simple-tags'), 'error taxopress-notice');
569
570 return false;
571 }
572
573 // String to array
574 $old_terms = explode(',', $old);
575 $new_terms = explode(',', $new);
576
577 $old_terms = array_map($extractTermName, $old_terms);
578 $new_terms = array_map($extractTermName, $new_terms);
579
580 // Remove empty element and trim
581 $old_terms = array_filter($old_terms, '_delete_empty_element');
582 $new_terms = array_filter($new_terms, '_delete_empty_element');
583 $common_elements = array_intersect($old_terms, $new_terms);
584
585 // If old/new tag are empty => exit !
586 if (empty($old_terms) || empty($new_terms)) {
587 add_settings_error(__CLASS__, __CLASS__, esc_html__('No new/old valid term specified!', 'simple-tags'), 'error taxopress-notice');
588
589 return false;
590 }
591
592 if (!empty($common_elements)) {
593 add_settings_error(__CLASS__, __CLASS__, esc_html__('Term to merge and New Term must not contain same term.', 'simple-tags'), 'error taxopress-notice');
594
595 return false;
596 }
597
598 $counter = 0;
599 if (count($new_terms) == 1) { // Merge
600 // Set new tag
601 $new_tag = sanitize_text_field($new_terms[0]);
602 if (empty($new_tag)) {
603 add_settings_error(__CLASS__, __CLASS__, esc_html__('No valid new term.', 'simple-tags'), 'error taxopress-notice');
604
605 return false;
606 }
607
608 // Ensure the new term exists or create it
609 $new_term = get_term_by('name', $new_tag, $taxonomy);
610 if (!$new_term) {
611 $new_term_info = wp_insert_term($new_tag, $taxonomy);
612 if (is_wp_error($new_term_info)) {
613 add_settings_error(__CLASS__, __CLASS__, esc_html__('Failed to create the new term.', 'simple-tags'), 'error taxopress-notice');
614 return false;
615 }
616 $new_term_id = $new_term_info['term_id'];
617 $new_term_slug = isset($new_term_info['slug']) ? $new_term_info['slug'] : sanitize_title($new_tag);
618 } else {
619 $new_term_id = $new_term->term_id;
620 $new_term_slug = $new_term->slug;
621 }
622
623 // Get terms ID from old terms names
624 $terms_id = array();
625 foreach ((array) $old_terms as $old_tag) {
626 $term = get_term_by('name', addslashes(sanitize_text_field($old_tag)), $taxonomy);
627 if ($term) {
628 $terms_id[] = (int) $term->term_id;
629 }
630 }
631
632 // Get objects from terms ID
633 $objects_id = get_objects_in_term($terms_id, $taxonomy, ['fields' => 'ids']);
634
635 // Use a set to track unique post IDs
636 $unique_objects = [];
637
638 // Assign the new term to all posts associated with the old terms
639 foreach ((array) $objects_id as $object_id) {
640 // Check if the object already has the term assigned
641 $current_terms = wp_get_object_terms($object_id, $taxonomy, ['fields' => 'ids']);
642 if (!in_array($new_term_id, $current_terms)) {
643 wp_set_object_terms($object_id, $new_term_slug, $taxonomy, true);
644 }
645 $unique_objects[$object_id] = true; // Add to unique set
646 }
647
648 // Count unique posts
649 $counter = count($unique_objects);
650
651 // Delete old terms
652 foreach ((array) $terms_id as $term_id) {
653 wp_delete_term($term_id, $taxonomy);
654 }
655
656 // Test if term is also a category
657 /*
658 if ( is_term($new_tag, 'category') ) {
659 // Edit the slug to use the new term
660 self::editTermSlug( $new_tag, sanitize_title($new_tag) );
661 }
662 */
663
664 // Clean cache
665 clean_object_term_cache($objects_id, $taxonomy);
666 clean_term_cache($terms_id, $taxonomy);
667
668 if ($counter == 0) {
669 add_settings_error(__CLASS__, __CLASS__, esc_html__('No term merged.', 'simple-tags'), 'updated taxopress-notice');
670 } else {
671 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('Merge term(s) "%1$s" to "%2$s". %3$s posts edited.', 'simple-tags'), rtrim($old, ','), rtrim($new, ','), $counter), 'updated taxopress-notice');
672 }
673 } else { // Error
674 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('Error. You need to enter a single term to merge to in new term name !', 'simple-tags'), $old), 'error taxopress-notice');
675 }
676 return [
677 'success' => true,
678 'merged_into' => $new_tag,
679 'posts_updated' => $counter,
680 'post_ids' => array_keys($unique_objects),
681 'terms_merged' => count($terms_id) + 1,
682 ];
683
684
685 }
686 }
687
688 public static function taxopress_merge_terms_batch() {
689 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'st-admin-js')) {
690 wp_send_json_error(['message' => __('Security check failed.', 'simple-tags')]);
691 wp_die();
692 }
693
694 $taxonomy = isset($_POST['taxonomy']) ? sanitize_text_field($_POST['taxonomy']) : '';
695 $new_term = isset($_POST['new_term']) ? sanitize_text_field($_POST['new_term']) : '';
696 $merge_type = isset($_POST['merge_type']) ? sanitize_text_field($_POST['merge_type']) : 'different_name';
697 $old_terms_input = isset($_POST['old_terms']) ? array_map('sanitize_text_field', (array) $_POST['old_terms']) : [];
698
699 $extractTermName = function ($term) {
700 return trim(preg_replace('/\s*\(.*?\)$/', '', $term));
701 };
702
703 $old_terms = [];
704
705 foreach ($old_terms_input as $term_name) {
706 $term_name_clean = $extractTermName($term_name);
707 $term = get_term_by('name', $term_name_clean, $taxonomy);
708 if ($term && !is_wp_error($term)) {
709 $old_terms[] = $term_name_clean;
710 }
711 }
712
713 if (empty($old_terms)) {
714 wp_send_json_error([
715 'message' => __('Please enter a valid term. Merge cancelled.', 'simple-tags')
716 ]);
717 wp_die();
718 }
719
720
721 // Execute the merge
722 $result = SimpleTags_Admin_Manage::mergeTerms($taxonomy, implode(',', $old_terms), $new_term, $merge_type);
723
724 if ($result === true || (is_array($result) && !empty($result['success']))) {
725 $response = ['message' => __('Merge successful', 'simple-tags')];
726
727 if (is_array($result)) {
728 $response = array_merge($response, $result);
729 }
730
731 wp_send_json_success($response);
732 } else {
733 global $wp_settings_errors;
734 $errors = [];
735
736 if (!empty($wp_settings_errors)) {
737 foreach ($wp_settings_errors as $error) {
738 if (!empty($error['message'])) {
739 $errors[] = $error['message'];
740 }
741 }
742 }
743
744 if (is_wp_error($result)) {
745 $errors[] = $result->get_error_message();
746 } elseif (is_array($result) && isset($result['message'])) {
747 $errors[] = $result['message'];
748 }
749
750 wp_send_json_error(['message' => implode(' ', $errors)]);
751 }
752
753 wp_die();
754 }
755
756 /**
757 * Method for remove tags
758 *
759 * @param string $taxonomy
760 * @param string $post_type
761 * @param string $tag
762 *
763 * @return boolean
764 * @author WebFactory Ltd
765 */
766 public static function removeTerms($taxonomy = 'post_tag', $post_type = 'posts', $new = '')
767 {
768 if (trim(str_replace(',', '', stripslashes($new))) == '') {
769 add_settings_error(__CLASS__, __CLASS__, esc_html__('No term specified!', 'simple-tags'), 'error taxopress-notice');
770
771 return false;
772 }
773
774 // String to array
775 $new_terms = explode(',', $new);
776
777 // Remove empty element and trim
778 $new_terms = array_filter($new_terms, '_delete_empty_element');
779
780 // If new tag are empty => exit !
781 if (empty($new_terms)) {
782 add_settings_error(__CLASS__, __CLASS__, esc_html__('No valid term specified!', 'simple-tags'), 'error taxopress-notice');
783
784 return false;
785 }
786
787 $counter = 0;
788 if (count($new_terms) > 0) {
789 foreach ((array) $new_terms as $term) {
790 $term = get_term_by('name', sanitize_text_field($term), $taxonomy);
791 if (empty($term) || !is_object($term)) {
792 continue;
793 }
794
795 $term = $term->term_id;
796
797 $args = array(
798 'post_type' => $post_type, // post_type
799 'posts_per_page' => -1,
800 'tax_query' => array(
801 array(
802 'taxonomy' => $taxonomy,
803 'field' => 'id',
804 'terms' => $term
805 )
806 )
807 );
808 $posts = get_posts($args);
809 foreach ($posts as $post) {
810 $remove = wp_remove_object_terms($post->ID, $term, $taxonomy);
811 if ($remove) {
812 clean_object_term_cache($post->ID, $taxonomy);
813 clean_term_cache($term, $taxonomy);
814 $counter ++;
815 }
816 }
817 }
818
819 if ($counter == 0) {
820 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('This term is not associated with any %1$s.', 'simple-tags'), SimpleTags_Admin::$post_type_name), 'error taxopress-notice');
821 } else {
822 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('Removed term(s) "%1$s" from %2$s %3$s', 'simple-tags'), $new, $counter, SimpleTags_Admin::$post_type_name), 'updated taxopress-notice');
823 }
824 } else { // Error
825 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('Error. No enough terms specified.', 'simple-tags'), $old), 'error taxopress-notice');
826 }
827
828 return true;
829 }
830
831 /**
832 * Method for rename tags
833 *
834 * @param string $taxonomy
835 * @param string $old
836 * @param string $new
837 *
838 * @return boolean
839 * @author WebFactory Ltd
840 */
841 public static function renameTerms($taxonomy = 'post_tag', $old = '', $new = '')
842 {
843 // Helper function to extract term name (ignoring slug in brackets)
844 $extractTermName = function ($term) {
845 return trim(preg_replace('/\s*\(.*?\)$/', '', $term));
846 };
847
848 if (trim(str_replace(',', '', stripslashes($new))) == '') {
849 add_settings_error(__CLASS__, __CLASS__, esc_html__('No new term specified!', 'simple-tags'), 'error taxopress-notice');
850
851 return false;
852 }
853
854 // String to array
855 $old_terms = explode(',', $old);
856 $new_terms = explode(',', $new);
857
858 // Clean up terms by removing slugs
859 $old_terms = array_map($extractTermName, $old_terms);
860 $new_terms = array_map($extractTermName, $new_terms);
861
862 // Remove empty element and trim
863 $old_terms = array_filter($old_terms, '_delete_empty_element');
864 $new_terms = array_filter($new_terms, '_delete_empty_element');
865
866 // If old/new tag are empty => exit !
867 if (empty($old_terms) || empty($new_terms)) {
868 add_settings_error(__CLASS__, __CLASS__, esc_html__('No new/old valid term specified!', 'simple-tags'), 'error taxopress-notice');
869
870 return false;
871 }
872
873 $counter = 0;
874 if (count($old_terms) === count($new_terms)) { // Rename only
875 foreach ((array) $old_terms as $i => $old_tag) {
876 $new_name = sanitize_text_field($new_terms[ $i ]);
877
878 // Get term by name
879 $term = get_term_by('name', sanitize_text_field($old_tag), $taxonomy);
880 if (! $term) {
881 continue;
882 }
883
884 // Get objects from term ID
885 $objects_id = get_objects_in_term($term->term_id, $taxonomy, array( 'fields' => 'all_with_object_id' ));
886
887 // Create the new term
888 if (! $term_info = term_exists($new_name, $taxonomy)) {
889 $term_info = wp_insert_term($new_name, $taxonomy);
890 }
891
892 // If default category, update the ID for new term...
893 if ('category' == $taxonomy && $term->term_id == get_option('default_category')) {
894 update_option('default_category', $term_info['term_id']);
895 clean_term_cache($term_info['term_id'], $taxonomy);
896 }
897
898 // Delete old term
899 wp_delete_term($term->term_id, $taxonomy);
900
901 // Set objects to new term ! (Append no replace)
902 foreach ((array) $objects_id as $object_id) {
903 wp_set_object_terms($object_id, $new_name, $taxonomy, true);
904 }
905
906 // Clean cache
907 clean_object_term_cache($objects_id, $taxonomy);
908 clean_term_cache($term->term_id, $taxonomy);
909
910 // Increment
911 $counter ++;
912 }
913
914 if ($counter == 0) {
915 add_settings_error(__CLASS__, __CLASS__, esc_html__('No term renamed.', 'simple-tags'), 'updated taxopress-notice');
916 } else {
917 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('Renamed term(s) "%1$s" to "%2$s"', 'simple-tags'), rtrim($old, ','), rtrim($new, ',')), 'updated taxopress-notice');
918 }
919 } else { // Error
920 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('Error. No enough terms for rename.', 'simple-tags'), $old), 'error taxopress-notice');
921 }
922
923 return true;
924 }
925
926 /**
927 * Method for delete a list of terms
928 *
929 * @param string $taxonomy
930 * @param string $delete
931 *
932 * @return boolean
933 * @author WebFactory Ltd
934 */
935 public static function deleteTermsByTermList($taxonomy = 'post_tag', $delete = '')
936 {
937 if (trim(str_replace(',', '', stripslashes($delete))) == '') {
938 add_settings_error(__CLASS__, __CLASS__, esc_html__('No term specified!', 'simple-tags'), 'error taxopress-notice');
939
940 return false;
941 }
942
943 // In array + filter
944 $delete_terms = explode(',', $delete);
945 $delete_terms = array_filter($delete_terms, '_delete_empty_element');
946
947 // Delete tags
948 $counter = 0;
949 foreach ((array) $delete_terms as $term) {
950 $term = get_term_by('name', sanitize_text_field($term), $taxonomy);
951 $term_id = (int) $term->term_id;
952
953 if ($term_id != 0) {
954 wp_delete_term($term_id, $taxonomy);
955 clean_term_cache($term_id, $taxonomy);
956 $counter ++;
957 }
958 }
959
960 if ($counter == 0) {
961 add_settings_error(__CLASS__, __CLASS__, esc_html__('No term deleted.', 'simple-tags'), 'updated taxopress-notice');
962 } else {
963 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('%1s term(s) deleted.', 'simple-tags'), $counter), 'updated taxopress-notice');
964 }
965
966 return true;
967 }
968
969 /**
970 * Method for add terms for all or specified posts
971 *
972 * @param string $taxonomy
973 * @param string $match
974 * @param string $new
975 *
976 * @return boolean
977 * @author WebFactory Ltd
978 */
979 public static function addMatchTerms($taxonomy = 'post_tag', $match = '', $new = '')
980 {
981 // Helper function to extract term name (ignoring slug in brackets)
982 $extractTermName = function ($term) {
983 return trim(preg_replace('/\s*\(.*?\)$/', '', $term));
984 };
985
986 if (trim(str_replace(',', '', stripslashes($new))) == '') {
987 add_settings_error(__CLASS__, __CLASS__, esc_html__('No new term(s) specified!', 'simple-tags'), 'error taxopress-notice');
988
989 return false;
990 }
991
992 $match_terms = explode(',', $match);
993 $new_terms = explode(',', $new);
994
995 // Clean up terms by removing slugs
996 $match_terms = array_map($extractTermName, $match_terms);
997 $new_terms = array_map($extractTermName, $new_terms);
998
999 $match_terms = array_filter($match_terms, '_delete_empty_element');
1000 $new_terms = array_filter($new_terms, '_delete_empty_element');
1001
1002 $counter = 0;
1003 if (! empty($match_terms)) { // Match and add
1004 // Get terms ID from old match names
1005 $terms_id = array();
1006 foreach ((array) $match_terms as $match_term) {
1007 $term = get_term_by('name', sanitize_text_field($match_term), $taxonomy);
1008 $terms_id[] = (int) $term->term_id;
1009 }
1010
1011 // Get object ID with terms ID
1012 $objects_id = get_objects_in_term($terms_id, $taxonomy, array( 'fields' => 'all_with_object_id' ));
1013
1014 // Add new tags for specified post
1015 foreach ((array) $objects_id as $object_id) {
1016 wp_set_object_terms($object_id, $new_terms, $taxonomy, true); // Append terms
1017 $counter ++;
1018 }
1019
1020 // Clean cache
1021 clean_object_term_cache($objects_id, $taxonomy);
1022 clean_term_cache($terms_id, $taxonomy);
1023 } else { // Add for all posts
1024 // Page or not ?
1025 $post_type_sql = "(post_status = 'publish' OR post_status = 'inherit') AND post_type = '".SimpleTags_Admin::$post_type."'";
1026
1027 // Get all posts ID
1028 global $wpdb;
1029 $objects_id = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE {$post_type_sql}");
1030
1031 // Add new tags for all posts
1032 foreach ((array) $objects_id as $object_id) {
1033 wp_set_object_terms($object_id, $new_terms, $taxonomy, true); // Append terms
1034 clean_object_term_cache($object_id, $taxonomy);
1035 clean_term_cache($new_terms, $taxonomy);
1036 $counter ++;
1037 }
1038
1039 // Clean cache
1040 clean_object_term_cache($objects_id, $taxonomy);
1041 }
1042
1043 if ($counter == 0) {
1044 add_settings_error(__CLASS__, __CLASS__, esc_html__('No term added.', 'simple-tags'), 'updated taxopress-notice');
1045 } else {
1046 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('Term(s) added to %1s %2s.', 'simple-tags'), $counter, SimpleTags_Admin::$post_type_name), 'updated taxopress-notice');
1047 }
1048
1049 return true;
1050 }
1051
1052 /**
1053 * Delete terms when counter if inferior to a specific number
1054 *
1055 * @param string $taxonomy
1056 * @param integer $number
1057 *
1058 * @return boolean
1059 * @author WebFactory Ltd
1060 */
1061 public static function removeRarelyUsed($taxonomy = 'post_tag', $number = 0)
1062 {
1063 global $wpdb;
1064
1065 if ((int) $number > 100) {
1066 wp_die('Tcheater ?');
1067 }
1068
1069 // Get terms with counter inferior to...
1070 $terms_id = $wpdb->get_col($wpdb->prepare("SELECT term_id FROM $wpdb->term_taxonomy WHERE taxonomy = %s AND count < %d", $taxonomy, (int) $number));
1071
1072 // Delete terms
1073 $counter = 0;
1074 foreach ((array) $terms_id as $term_id) {
1075 if ($term_id != 0) {
1076 wp_delete_term($term_id, $taxonomy);
1077 clean_term_cache($term_id, $taxonomy);
1078 $counter ++;
1079 }
1080 }
1081
1082 if ($counter == 0) {
1083 add_settings_error(__CLASS__, __CLASS__, esc_html__('No term deleted.', 'simple-tags'), 'updated taxopress-notice');
1084 } else {
1085 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('%1s term(s) deleted.', 'simple-tags'), $counter), 'updated taxopress-notice');
1086 }
1087
1088 return true;
1089 }
1090
1091 function handle_taxopress_check_delete_terms_ajax() {
1092
1093 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'st-admin-js')) {
1094 wp_send_json_error(array('message' => __('Nonce verification failed.', 'simple-tags')));
1095 wp_die();
1096 }
1097
1098 global $wpdb;
1099
1100 $taxonomy = isset($_POST['taxonomy']) ? sanitize_text_field($_POST['taxonomy']) : 'post_tag';
1101 $number = isset($_POST['number']) ? intval($_POST['number']) : 0;
1102
1103 if ((int) $number > 100) {
1104 wp_die('Tcheater ?');
1105 }
1106
1107 if ($number > 0) {
1108 $terms = $wpdb->get_col($wpdb->prepare("
1109 SELECT term_id FROM $wpdb->term_taxonomy
1110 WHERE taxonomy = %s AND count < %d",
1111 $taxonomy, (int) $number));
1112
1113 $term_count = count($terms);
1114
1115 if ($term_count > 0) {
1116 wp_send_json_success(array('message' => sprintf(__('%d terms will be deleted.', 'simple-tags'), $term_count)));
1117 } else {
1118 wp_send_json_error(array('message' => __('No terms will be deleted.', 'simple-tags')));
1119 }
1120 } else {
1121 wp_send_json_error(array('message' => __('Invalid number specified.', 'simple-tags')));
1122 }
1123
1124 wp_die();
1125 }
1126
1127 /**
1128 * Method for removing terms from all or specified posts
1129 *
1130 * @param string $taxonomy
1131 * @param string $match
1132 * @param string $remove
1133 *
1134 * @return boolean
1135 * @author WebFactory Ltd
1136 */
1137 public static function removeMatchTerms($taxonomy = 'post_tag', $match = '', $remove = '')
1138 {
1139 // Helper function to extract term name (ignoring slug in brackets)
1140 $extractTermName = function ($term) {
1141 return trim(preg_replace('/\s*\(.*?\)$/', '', $term));
1142 };
1143
1144 if (trim(str_replace(',', '', stripslashes($remove))) == '') {
1145 add_settings_error(__CLASS__, __CLASS__, esc_html__('No term(s) specified for removal!', 'simple-tags'), 'error taxopress-notice');
1146 return false;
1147 }
1148
1149 $match_terms = explode(',', $match);
1150 $remove_terms = explode(',', $remove);
1151
1152 // Clean up terms by removing slugs
1153 $match_terms = array_map($extractTermName, $match_terms);
1154 $remove_terms = array_map($extractTermName, $remove_terms);
1155
1156 $match_terms = array_filter($match_terms, '_delete_empty_element');
1157 $remove_terms = array_filter($remove_terms, '_delete_empty_element');
1158
1159 // Arrays to track if terms entered is valid
1160 $valid_remove_terms = array();
1161 $invalid_remove_terms = array();
1162
1163 foreach ((array) $remove_terms as $remove_term) {
1164 $term = get_term_by('name', sanitize_text_field($remove_term), $taxonomy);
1165 if ($term) {
1166 $valid_remove_terms[] = $remove_term; // Add to valid list if the term exists
1167 } else {
1168 $invalid_remove_terms[] = $remove_term; // Collect invalid remove terms
1169 }
1170 }
1171
1172 if (empty($valid_remove_terms)) {
1173 add_settings_error(__CLASS__, __CLASS__, esc_html__('Term(s) does not exist.', 'simple-tags'), 'error taxopress-notice');
1174 return false;
1175 }
1176
1177 $counter = 0;
1178 if (!empty($match_terms)) {
1179 // Get terms ID from match terms
1180 $terms_id = array();
1181 foreach ((array) $match_terms as $match_term) {
1182 $term = get_term_by('name', sanitize_text_field($match_term), $taxonomy);
1183 if ($term) {
1184 $terms_id[] = (int) $term->term_id;
1185 }
1186 }
1187
1188 // Get object ID with terms ID
1189 $objects_id = get_objects_in_term($terms_id, $taxonomy, array('fields' => 'all_with_object_id'));
1190
1191 // Remove specified terms from matched posts
1192 foreach ((array) $objects_id as $object_id) {
1193 wp_remove_object_terms($object_id, $valid_remove_terms, $taxonomy);
1194 $counter++;
1195 }
1196
1197 clean_object_term_cache($objects_id, $taxonomy);
1198 clean_term_cache($terms_id, $taxonomy);
1199 } else {
1200 // Get all posts if no match terms were provided
1201 global $wpdb;
1202 $post_type_sql = "(post_status = 'publish' OR post_status = 'inherit') AND post_type = '".SimpleTags_Admin::$post_type."'";
1203 $objects_id = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE {$post_type_sql}");
1204
1205 // Remove valid terms for all posts
1206 foreach ((array) $objects_id as $object_id) {
1207 wp_remove_object_terms($object_id, $valid_remove_terms, $taxonomy);
1208 clean_object_term_cache($object_id, $taxonomy);
1209 clean_term_cache($valid_remove_terms, $taxonomy);
1210 $counter++;
1211 }
1212
1213 clean_object_term_cache($objects_id, $taxonomy);
1214 }
1215
1216 if ($counter == 0) {
1217 add_settings_error(__CLASS__, __CLASS__, esc_html__('No matching term found.', 'simple-tags'), 'updated taxopress-notice');
1218 } else {
1219 add_settings_error(__CLASS__, __CLASS__, sprintf(esc_html__('Term(s) removed from %1s %2s.', 'simple-tags'), $counter, SimpleTags_Admin::$post_type_name), 'updated taxopress-notice');
1220 }
1221
1222 return true;
1223 }
1224
1225 public static function handle_taxopress_autocomplete_terms() {
1226 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'st-admin-js')) {
1227 wp_send_json_error(['message' => __('Nonce verification failed.', 'simple-tags')]);
1228 wp_die();
1229 }
1230
1231 $taxonomy = isset($_POST['taxonomy']) ? sanitize_text_field($_POST['taxonomy']) : 'post_tag';
1232 $term = isset($_POST['term']) ? sanitize_text_field($_POST['term']) : '';
1233
1234 $terms = get_terms([
1235 'taxonomy' => $taxonomy,
1236 'name__like' => $term,
1237 'hide_empty' => false,
1238 ]);
1239
1240 $results = [];
1241 foreach ($terms as $term) {
1242 $results[] = [
1243 'name' => $term->name,
1244 'slug' => $term->slug
1245 ];
1246 }
1247
1248 wp_send_json($results);
1249 wp_die();
1250 }
1251
1252
1253 /**
1254 * Method for edit one or more terms slug
1255 *
1256 * @param string $taxonomy
1257 * @param string $names
1258 * @param string $slugs
1259 *
1260 * @return boolean
1261 * @author WebFactory Ltd
1262 */
1263 /*
1264 public static function editTermSlug( $taxonomy = 'post_tag', $names = '', $slugs = '') {
1265 if ( trim( str_replace(',', '', stripslashes($slugs)) ) == '' ) {
1266 add_settings_error( __CLASS__, __CLASS__, esc_html__('No new slug(s) specified!', 'simple-tags'), 'error' );
1267 return false;
1268 }
1269
1270 $match_names = explode(',', $names);
1271 $new_slugs = explode(',', $slugs);
1272
1273 $match_names = array_filter($match_names, '_delete_empty_element');
1274 $new_slugs = array_filter($new_slugs, '_delete_empty_element');
1275
1276 if ( count($match_names) != count($new_slugs) ) {
1277 add_settings_error( __CLASS__, __CLASS__, esc_html__('Terms number and slugs number isn\'t the same!', 'simple-tags'), 'error' );
1278 return false;
1279 } else {
1280 $counter = 0;
1281 foreach ( (array) $match_names as $i => $match_name ) {
1282 // Sanitize slug + Escape
1283 $new_slug = sanitize_title($new_slugs[$i]);
1284
1285 // Get term by name
1286 $term = get_term_by('name', $match_name, $taxonomy);
1287 if ( !$term ) {
1288 continue;
1289 }
1290
1291 // Increment
1292 $counter++;
1293
1294 // Update term
1295 wp_update_term($term->term_id, $taxonomy, array('slug' => $new_slug));
1296
1297 // Clean cache
1298 clean_term_cache($term->term_id, $taxonomy);
1299 }
1300 }
1301
1302 if ( $counter == 0 ) {
1303 add_settings_error( __CLASS__, __CLASS__, esc_html__('No slug edited.', 'simple-tags'), 'updated' );
1304 } else {
1305 add_settings_error( __CLASS__, __CLASS__, sprintf(esc_html__('%s slug(s) edited.', 'simple-tags'), $counter), 'updated' );
1306 }
1307
1308 return true;
1309 }
1310 */
1311
1312
1313 /** Singleton instance */
1314 public static function get_instance()
1315 {
1316 if (! isset(self::$instance)) {
1317 self::$instance = new self();
1318 }
1319
1320 return self::$instance;
1321 }
1322 }
1323 ?>