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

terms-table.php in Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms 3.44.0, at inc/terms-table.php

1,087 lines 41.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!class_exists('WP_List_Table')) {
3 require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
4 }
5
6 class Taxopress_Terms_List extends WP_List_Table
7 {
8
9 /** Class constructor */
10 public function __construct()
11 {
12
13 parent::__construct([
14 'singular' => 'Term', //singular name of the listed records
15 'plural' => 'Terms', //plural name of the listed records
16 'ajax' => true //does this table support ajax?
17 ]);
18 }
19
20 /**
21 * Flatten a hierarchical terms array into a flat array.
22 *
23 * @param array $terms Array of term objects.
24 * @param int $max_depth Maximum depth to traverse (default 10).
25 * @return array Flattened array of term objects.
26 */
27 function taxopress_flatten_terms_tree($terms, $max_depth = 7) {
28 $flat = [];
29 $map = [];
30 $children_map = [];
31 $visited = [];
32
33 // Build a map of terms by ID and their children
34 foreach ($terms as $term) {
35 $map[$term->term_id] = $term;
36 $children_map[$term->parent][] = $term;
37 }
38
39 // Initialize stack with root-level terms (no valid parent)
40 $stack = [];
41 foreach ($terms as $term) {
42 if ($term->parent === 0 || !isset($map[$term->parent])) {
43 $stack[] = ['term' => $term, 'depth' => 0];
44 }
45 }
46
47 // Iterative depth-first traversal
48 while (!empty($stack)) {
49 $node = array_pop($stack);
50 $term = $node['term'];
51 $depth = $node['depth'];
52
53 if ($depth > $max_depth) {
54 continue;
55 }
56 if (isset($visited[$term->term_id])) {
57 continue; // Prevent cycles
58 }
59 $visited[$term->term_id] = true;
60
61 $flat[] = $term;
62
63 // Use pre-indexed children map
64 if (!empty($children_map[$term->term_id])) {
65 foreach (array_reverse($children_map[$term->term_id]) as $child) {
66 $stack[] = ['term' => $child, 'depth' => $depth + 1];
67 }
68 }
69 }
70
71 return $flat;
72 }
73
74 /**
75 * Arrange terms in hierarchical order with depth info for dash prefixing.
76 */
77 function taxopress_arrange_terms_hierarchically($terms) {
78 $terms_by_id = [];
79 $children = [];
80 foreach ($terms as $term) {
81 $terms_by_id[$term->term_id] = $term;
82 $children[$term->parent][] = $term->term_id;
83 }
84
85 $ordered = [];
86 $add_term = function($term_id, $depth) use (&$add_term, &$terms_by_id, &$children, &$ordered) {
87 $term = $terms_by_id[$term_id];
88 $term->taxopress_depth = $depth;
89 $ordered[] = $term;
90 if (!empty($children[$term_id])) {
91 foreach ($children[$term_id] as $child_id) {
92 $add_term($child_id, $depth + 1);
93 }
94 }
95 };
96
97 // Start with root terms
98 foreach ($terms as $term) {
99 if ($term->parent == 0 || !isset($terms_by_id[$term->parent])) {
100 $add_term($term->term_id, 0);
101 }
102 }
103 return $ordered;
104 }
105
106 public function get_all_terms($count = false)
107 {
108
109 $taxonomies = array_keys(get_all_taxopress_taxonomies_request());
110 $taxonomy_settings = taxopress_get_all_edited_taxonomy_data();
111
112 $search = (!empty($_REQUEST['s'])) ? sanitize_text_field($_REQUEST['s']) : '';
113
114 $items_per_page = $this->get_items_per_page('st_terms_per_page', 20);
115 $page = $this->get_pagenum();
116 $offset = ($page - 1) * $items_per_page;
117
118 $selected_post_type = (!empty($_REQUEST['terms_filter_post_type'])) ? [sanitize_text_field($_REQUEST['terms_filter_post_type'])] : '';
119 $selected_taxonomy = (!empty($_REQUEST['terms_filter_taxonomy'])) ? sanitize_text_field($_REQUEST['terms_filter_taxonomy']) : '';
120
121 $allowed_orderby = ['name', 'slug', 'taxonomy', 'count', 'id'];
122 $allowed_order = ['asc', 'desc'];
123
124 $requested_orderby = !empty($_REQUEST['orderby']) ? sanitize_key($_REQUEST['orderby']) : '';
125 $requested_order = !empty($_REQUEST['order']) ? strtolower(sanitize_text_field($_REQUEST['order'])) : '';
126
127 if (!in_array($requested_orderby, $allowed_orderby, true)) {
128 $requested_orderby = '';
129 }
130 if (!in_array($requested_order, $allowed_order, true)) {
131 $requested_order = '';
132 }
133
134 $order_setting = isset($taxonomy_settings[$selected_taxonomy]['order']) ? strtolower($taxonomy_settings[$selected_taxonomy]['order']) : 'desc';
135 $orderby_setting = isset($taxonomy_settings[$selected_taxonomy]['orderby']) ? $taxonomy_settings[$selected_taxonomy]['orderby'] : 'ID';
136
137 $orderby_setting = strtolower($orderby_setting);
138 if ($orderby_setting === 'id' || $orderby_setting === 'term_id') {
139 $orderby_setting = 'id';
140 }
141
142 if ($requested_orderby) {
143 $orderby_setting = $requested_orderby;
144 }
145 if ($requested_order) {
146 $order_setting = $requested_order;
147 }
148
149 // If viewing via taxopress_terms_taxonomy, override to show all terms in that taxonomy
150 if (!empty($_REQUEST['taxopress_terms_taxonomy'])) {
151 $selected_taxonomy = sanitize_text_field($_REQUEST['taxopress_terms_taxonomy']);
152 $taxonomies = [$selected_taxonomy];
153 $show_all_terms_in_taxonomy = false;
154 } else {
155 $show_all_terms_in_taxonomy = false;
156 if (!empty($selected_taxonomy)) {
157 $taxonomies = [$selected_taxonomy];
158 }
159 }
160
161 // Check if any taxonomy uses manual ordering
162 $manual_order = false;
163 foreach ($taxonomies as $taxonomy) {
164 $order_setting = isset($taxonomy_settings[$taxonomy]['order']) ? $taxonomy_settings[$taxonomy]['order'] : 'desc';
165 $orderby_setting = isset($taxonomy_settings[$selected_taxonomy]['orderby']) ? $taxonomy_settings[$selected_taxonomy]['orderby'] : 'ID';
166 if ($requested_orderby) {
167 $orderby_setting = $requested_orderby;
168 }
169 if ($requested_order) {
170 $order_setting = $requested_order;
171 }
172 if ($order_setting === 'taxopress_term_order') {
173 $manual_order = true;
174 break;
175 }
176 }
177
178 // If any taxonomy uses manual order, use the original per-taxonomy logic
179 if ($manual_order) {
180 $terms = [];
181 foreach ($taxonomies as $taxonomy) {
182 $custom_order = get_option('taxopress_term_order_' . $taxonomy, []);
183 $order_setting = isset($taxonomy_settings[$taxonomy]['order']) ? $taxonomy_settings[$taxonomy]['order'] : 'desc';
184 $orderby_setting = isset($taxonomy_settings[$taxonomy]['orderby']) ? $taxonomy_settings[$taxonomy]['orderby'] : 'ID';
185 $use_custom_order = ($order_setting === 'taxopress_term_order');
186
187 $terms_attr = [
188 'taxonomy' => [$taxonomy],
189 'post_types' => $selected_post_type,
190 'hide_empty' => false,
191 'pad_counts' => true,
192 'update_term_meta_cache' => true,
193 'search' => $search,
194 ];
195
196 if (!$use_custom_order) {
197 $terms_attr['orderby'] = $orderby_setting;
198 $terms_attr['order'] = $order_setting;
199 }
200
201 // Only paginate after merging all terms
202 $taxonomy_terms = get_terms($terms_attr);
203
204 if (empty($taxonomy_terms) || is_wp_error($taxonomy_terms)) {
205 continue;
206 }
207
208 if ($use_custom_order) {
209 // Manual custom ordering
210 $terms_by_id = [];
211 $new_terms = [];
212 $ordered_terms = [];
213
214 foreach ($taxonomy_terms as $term) {
215 $terms_by_id[$term->term_id] = $term;
216 }
217
218 // Terms not in custom order
219 foreach ($terms_by_id as $term_id => $term) {
220 if (!in_array($term_id, $custom_order)) {
221 $new_terms[] = $term;
222 }
223 }
224
225 // Ordered terms
226 foreach ($custom_order as $term_id) {
227 if (isset($terms_by_id[$term_id])) {
228 $ordered_terms[] = $terms_by_id[$term_id];
229 }
230 }
231
232 // Merge: new (unordered) terms first, then custom-ordered ones
233 $terms = array_merge($terms, $new_terms, $ordered_terms);
234 } else {
235 if ($orderby_setting === 'random') {
236 shuffle($taxonomy_terms);
237 if ($order_setting === 'desc') {
238 $taxonomy_terms = array_reverse($taxonomy_terms);
239 }
240 }
241 $terms = array_merge($terms, $taxonomy_terms);
242 }
243 }
244
245 // Paginate after merging, unless showing all terms in taxonomy
246 if (!$count) {
247 $terms = array_slice($terms, $offset, $items_per_page);
248 }
249
250 // HIERARCHY SUPPORT
251 if (!empty($selected_taxonomy)) {
252 $terms = $this->taxopress_arrange_terms_hierarchically($terms);
253 } else {
254 $terms = $this->taxopress_flatten_terms_tree($terms);
255 }
256
257 return $terms;
258 }
259
260 // If no manual ordering, use the efficient all-in-one get_terms
261 $terms_attr = [
262 'taxonomy' => $taxonomies,
263 'post_types' => $selected_post_type,
264 'orderby' => $orderby_setting,
265 'order' => $order_setting,
266 'search' => $search,
267 'hide_empty' => false,
268 'pad_counts' => true,
269 'update_term_meta_cache' => true,
270 ];
271 if ($count || $show_all_terms_in_taxonomy) {
272 $terms_attr['number'] = 0;
273 } else {
274 $terms_attr['offset'] = $offset;
275 $terms_attr['number'] = $items_per_page;
276 }
277
278 $terms = get_terms($terms_attr);
279
280 if (empty($terms) || is_wp_error($terms)) {
281 return [];
282 }
283
284 if (!empty($requested_orderby) && $requested_orderby === 'taxonomy') {
285 usort($terms, function ($a, $b) use ($order_setting) {
286 $cmp = strcmp($a->taxonomy, $b->taxonomy);
287 return ($order_setting === 'desc') ? -$cmp : $cmp;
288 });
289 }
290
291 if ($orderby_setting === 'random') {
292 shuffle($terms);
293 if ($order_setting === 'desc') {
294 $terms = array_reverse($terms);
295 }
296 }
297
298 // HIERARCHY SUPPORT
299 if (!empty($selected_taxonomy)) {
300 $terms = $this->taxopress_arrange_terms_hierarchically($terms);
301 } else {
302 $terms = $this->taxopress_flatten_terms_tree($terms);
303 }
304
305 return $terms;
306 }
307
308 /**
309 * Retrieve st_Terms data from the database
310 *
311 * @param int $per_page
312 * @param int $page_number
313 *
314 * @return mixed
315 */
316 public function get_st_Terms()
317 {
318 return $this->get_all_terms();
319 }
320
321 /**
322 * Returns the count of records in the database.
323 *
324 * @return null|string
325 */
326 public function record_count()
327 {
328 return count($this->get_all_terms(true));
329 }
330
331 /**
332 * Show single row item
333 *
334 * @param array $item
335 */
336 public function single_row($item)
337 {
338 $class = ['st-terms-tr'];
339 $id = 'term-' . $item->term_id . '';
340 echo sprintf('<tr id="%s" class="%s">', esc_attr($id), esc_attr(implode(' ', $class)));
341 $this->single_row_columns($item);
342 echo '</tr>';
343 }
344
345 /**
346 * Associative array of columns
347 *
348 * @return array
349 */
350 function get_columns()
351 {
352
353 if (!empty($_REQUEST['taxopress_terms_taxonomy'])) {
354 return [
355 'name' => esc_html__('Title', 'simple-tags'),
356 'description' => esc_html__('Description', 'simple-tags'),
357 'count' => esc_html__('Count', 'simple-tags'),
358 ];
359 }
360 $columns = [
361 'cb' => '<input type="checkbox" />',
362 'name' => esc_html__('Title', 'simple-tags'),
363 'slug' => esc_html__('Slug', 'simple-tags'),
364 'description' => esc_html__('Description', 'simple-tags'),
365 'taxonomy' => esc_html__('Taxonomy', 'simple-tags'),
366 'posttypes' => esc_html__('Post Types', 'simple-tags'),
367 'taxopress_custom_url' => esc_html__('Custom URL', 'simple-tags'),
368 'synonyms' => esc_html__('Synonyms', 'simple-tags'),
369 'linked_terms' => esc_html__('Linked Terms', 'simple-tags'),
370 'hidden_status' => esc_html__('Status', 'simple-tags'),
371 'count' => esc_html__('Count', 'simple-tags')
372 ];
373
374 if (!taxopress_is_pro_version()) {
375 unset($columns['synonyms']);
376 unset($columns['linked_terms']);
377 }
378
379 if (!(int) SimpleTags_Plugin::get_option_value('enable_hidden_terms')) {
380 unset($columns['hidden_status']);
381 }
382
383 return $columns;
384 }
385
386 /**
387 * Columns to make sortable.
388 *
389 * @return array
390 */
391 protected function get_sortable_columns()
392 {
393 $sortable_columns = [
394 'name' => ['name', true],
395 'slug' => ['slug', true],
396 'taxonomy' => ['taxonomy', true],
397 'count' => ['count', true],
398 ];
399
400 return $sortable_columns;
401 }
402
403 /**
404 * Render the bulk edit checkbox
405 *
406 * @param array $item
407 *
408 * @return string
409 */
410 function column_cb($item)
411 {
412 return sprintf('<input type="checkbox" name="%1$s[]" value="%2$s" />', 'taxopress_terms', $item->term_id);
413 }
414
415 /**
416 * Get the bulk actions to show in the top page dropdown
417 *
418 * @return array
419 */
420 protected function get_bulk_actions()
421 {
422 $actions = [
423 'taxopress-terms-delete-terms' => esc_html__('Delete', 'simple-tags'),
424 'taxopress-terms-copy-terms' => esc_html__('Copy', 'simple-tags')
425 ];
426
427 return $actions;
428 }
429
430 /**
431 * Add custom filter to tablenav
432 *
433 * @param string $which
434 */
435 protected function extra_tablenav($which)
436 {
437 // Hide filters if taxopress_show_all=1
438 if ('top' === $which && empty($_REQUEST['taxopress_show_all'])) {
439
440 $post_types = get_post_types(['public' => true], 'objects');
441
442 $taxonomies = get_all_taxopress_taxonomies_request();
443
444 $selected_post_type = (!empty($_REQUEST['terms_filter_post_type'])) ? sanitize_text_field($_REQUEST['terms_filter_post_type']) : '';
445 $selected_taxonomy = (!empty($_REQUEST['terms_filter_taxonomy'])) ? sanitize_text_field($_REQUEST['terms_filter_taxonomy']) : '';
446 $selected_post = (!empty($_REQUEST['destination_post'])) ? sanitize_text_field($_REQUEST['destination_post']) : '';
447
448 $selected_option = 'public';
449 if (isset($_GET['taxonomy_type']) && $_GET['taxonomy_type'] === 'all') {
450 $selected_option = 'all';
451 } elseif (isset($_GET['taxonomy_type']) && $_GET['taxonomy_type'] === 'private') {
452 $selected_option = 'private';
453 }
454 ?>
455
456 <div class="alignleft actions autoterms-terms-table-copy" id="taxopress-copy-selection-boxes" style="display: none;">
457 <select class="auto-terms-terms-copy-select" name="taxopress_destination_taxonomy" id="terms_copy_select_destination_taxonomy">
458 <option value=""><?php esc_html_e('Select Destination Taxonomy', 'simple-tags'); ?></option> <?php
459 foreach ($taxonomies as $taxonomy) {
460 echo '<option value="' . esc_attr($taxonomy->name) . '">' . esc_html($taxonomy->labels->name) . '</option>';
461 } ?>
462 </select>
463
464 <select class="auto-terms-terms-copy-select" name="taxopress_destination_post_type" id="terms_copy_select_destination_post">
465 <?php
466 $post_type_label = !empty($selected_post_type) ? esc_html($selected_post_type) : esc_html__('post type', 'simple-tags');
467 ?>
468 <option value=""><?php printf(esc_html__('Select Destination %s', 'simple-tags'), $post_type_label); ?></option>
469 <option value="all" <?php selected($selected_post, 'all'); ?>><?php printf(esc_html__('All %s', 'simple-tags'), $post_type_label); ?></option>.
470 <?php
471 // I want to show all posts when no post type is selected
472 if (empty($selected_post_type)) {
473 $all_posts = get_posts(['post_type' => 'any', 'numberposts' => -1]);
474 foreach ($all_posts as $post): ?>
475 <option value="<?php echo esc_attr($post->ID); ?>" <?php selected($selected_post, $post->ID); ?>>
476 <?php echo esc_html($post->post_title); ?>
477 </option>
478 <?php endforeach;
479 } else {
480 // Show posts only for selected post type
481 $posts = get_posts(['post_type' => $selected_post_type, 'numberposts' => -1]);
482 foreach ($posts as $post): ?>
483 <option value="<?php echo esc_attr($post->ID); ?>" <?php selected($selected_post, $post->ID); ?>>
484 <?php echo esc_html($post->post_title); ?>
485 </option>
486 <?php endforeach;
487 }
488 ?>
489 </select>
490 </div>
491 <div class="alignleft actions autoterms-terms-table-filter">
492
493 <select class="auto-terms-terms-filter-select" name="terms_filter_select_post_type" id="terms_filter_select_post_type">
494 <option value=""><?php esc_html_e('Post type', 'simple-tags'); ?></option>
495 <?php
496 foreach ($post_types as $post_type) {
497 echo '<option value="' . esc_attr($post_type->name) . '" ' . selected($selected_post_type, $post_type->name, false) . '>' . esc_html($post_type->label) . '</option>';
498 }
499 ?>
500 </select>
501
502 <select class="auto-terms-terms-filter-select" name="terms_filter_select_taxonomy" id="terms_filter_select_taxonomy">
503 <option value=""><?php esc_html_e('Taxonomy', 'simple-tags'); ?></option>
504 <?php
505 foreach ($taxonomies as $taxonomy) {
506 echo '<option value="' . esc_attr($taxonomy->name) . '" ' . selected($selected_taxonomy, $taxonomy->name, false) . '>' . esc_html($taxonomy->labels->name) . '</option>';
507 }
508 ?>
509 </select>
510
511 <select class="auto-terms-terms-filter-select" name="terms_filter_select_taxonomy_type" id="terms_filter_select_taxonomy_type">
512 <option value="all" <?php echo ($selected_option === 'all' ? 'selected="selected"' : ''); ?>><?php echo esc_html__('All Taxonomies', 'simple-tags'); ?></option>
513 <option value="public" <?php echo ($selected_option === 'public' ? 'selected="selected"' : ''); ?>><?php echo esc_html__('Public Taxonomies', 'simple-tags'); ?></option>
514 <option value="private" <?php echo ($selected_option === 'private' ? 'selected="selected"' : ''); ?>><?php echo esc_html__('Private Taxonomies', 'simple-tags'); ?></option>
515 </select>
516
517 <a href="javascript:void(0)" class="taxopress-terms-tablenav-filter button"><?php esc_html_e('Filter', 'simple-tags'); ?></a>
518
519 </div>
520 <?php
521 }
522 }
523
524 /**
525 * Process bulk actions
526 */
527 public function process_bulk_action()
528 {
529
530 $query_arg = '_wpnonce';
531 $action = 'bulk-' . $this->_args['plural'];
532 $checked = isset($_REQUEST[$query_arg]) ? wp_verify_nonce(sanitize_key($_REQUEST[$query_arg]), $action) : false;
533
534 if (!$checked || !current_user_can('simple_tags')) {
535 return;
536 }
537
538 if ($this->current_action() === 'taxopress-terms-delete-terms') {
539 $taxopress_terms = array_map('sanitize_text_field', (array)$_REQUEST['taxopress_terms']);
540 if (!empty($taxopress_terms)) {
541 foreach ($taxopress_terms as $taxopress_term) {
542 $term = get_term($taxopress_term);
543 wp_delete_term($term->term_id, $term->taxonomy);
544 }
545 if (count($taxopress_terms) > 1) {
546 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
547 echo taxopress_admin_notices_helper(esc_html__('Terms deleted successfully.', 'simple-tags'), false);
548 } else {
549 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
550 echo taxopress_admin_notices_helper(esc_html__('Term deleted successfully.', 'simple-tags'), false);
551 }
552 }
553 }
554 if ($this->current_action() === 'taxopress-terms-copy-terms') {
555 $taxopress_terms = array_map('sanitize_text_field', (array)$_REQUEST['taxopress_terms']);
556 $destination_taxonomy = sanitize_text_field($_REQUEST['taxopress_destination_taxonomy']);
557 $destination_post = sanitize_text_field($_REQUEST['taxopress_destination_post_type']);
558
559 if (!empty($taxopress_terms) && !empty($destination_taxonomy)) {
560 foreach ($taxopress_terms as $taxopress_term) {
561 $term = get_term($taxopress_term);
562 wp_insert_term($term->name, $destination_taxonomy, [
563 'slug' => $term->slug,
564 'description' => $term->description,
565 ]);
566 if (!empty($destination_post) && $destination_post !== 'all') {
567 wp_set_object_terms($destination_post, [$term->term_id], $destination_taxonomy, true);
568 }
569
570 if ($destination_post === 'all') {
571 $all_posts = get_posts(['post_type' => 'any', 'numberposts' => -1]);
572 foreach ($all_posts as $post) {
573 wp_set_object_terms($post->ID, [$term->term_id], $destination_taxonomy, true);
574 }
575 }
576 }
577 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
578 echo taxopress_admin_notices_helper(esc_html__('Term(s) copied successfully.', 'simple-tags'), true);
579 }
580 }
581 }
582
583 protected function column_taxopress_custom_url($item) {
584 $taxopress_custom_url = get_term_meta($item->term_id, 'taxopress_custom_url', true);
585 return (!empty($taxopress_custom_url) && filter_var($taxopress_custom_url, FILTER_VALIDATE_URL))
586 ? sprintf('<a href="%s" target="_blank">%s</a>', esc_url($taxopress_custom_url), esc_html($taxopress_custom_url))
587 : '-';
588 }
589
590 protected function column_hidden_status($item) {
591 $hidden_terms = get_transient('taxopress_hidden_terms_' . $item->taxonomy);
592
593 if (!empty($hidden_terms) && in_array($item->term_id, $hidden_terms)) {
594 return esc_html__('Hidden', 'simple-tags');
595 }
596
597 return esc_html__('Live', 'simple-tags');
598 }
599
600 /**
601 * Render a column when no column specific method exist.
602 *
603 * @param array $item
604 * @param string $column_name
605 *
606 * @return mixed
607 */
608 public function column_default($item, $column_name)
609 {
610 return !empty($item->$column_name) ? $item->$column_name : '&mdash;';
611 }
612
613 /** Text displayed when no stterm data is available */
614 public function no_items()
615 {
616 esc_html_e('No terms found.', 'simple-tags');
617 }
618
619 /**
620 * Displays the search box.
621 *
622 * @param string $text The 'submit' button label.
623 * @param string $input_id ID attribute value for the search input field.
624 *
625 *
626 */
627 public function search_box($text, $input_id)
628 {
629 // Hide search box if taxopress_show_all=1
630 if ((!empty($_REQUEST['taxopress_show_all']) && $_REQUEST['taxopress_show_all'] == '1')) {
631 return;
632 }
633
634 if (empty($_REQUEST['s']) && !$this->has_items()) {
635 //return;
636 }
637
638 $input_id = $input_id . '-search-input';
639
640 if (!empty($_REQUEST['orderby'])) {
641 echo '<input type="hidden" name="orderby" value="' . esc_attr(sanitize_text_field($_REQUEST['orderby'])) . '" />';
642 }
643 if (!empty($_REQUEST['order'])) {
644 echo '<input type="hidden" name="order" value="' . esc_attr(sanitize_text_field($_REQUEST['order'])) . '" />';
645 }
646 if (!empty($_REQUEST['page'])) {
647 echo '<input type="hidden" name="page" value="' . esc_attr(sanitize_text_field($_REQUEST['page'])) . '" />';
648 }
649
650 $custom_filters = ['terms_filter_post_type', 'terms_filter_taxonomy', 'taxonomy_type'];
651
652 foreach ($custom_filters as $custom_filter) {
653 $filter_value = !empty($_REQUEST[$custom_filter]) ? sanitize_text_field($_REQUEST[$custom_filter]) : '';
654 echo '<input type="hidden" name="' . esc_attr($custom_filter) . '" value="' . esc_attr($filter_value) . '" />';
655 }
656 ?>
657 <p class="search-box">
658 <label class="screen-reader-text" for="<?php echo esc_attr($input_id); ?>"><?php echo esc_html($text); ?>:</label>
659 <input type="search" id="<?php echo esc_attr($input_id); ?>" name="s" value="<?php _admin_search_query(); ?>" />
660 <?php submit_button($text, '', '', false, ['id' => 'taxopress-terms-search-submit']); ?>
661 </p>
662 <?php
663 }
664
665 /**
666 * Sets up the items (roles) to list.
667 */
668 public function prepare_items()
669 {
670
671 $this->_column_headers = $this->get_column_info();
672 $this->process_bulk_action();
673
674 /**
675 * First, lets decide how many records per page to show
676 */
677 $per_page = $this->get_items_per_page('st_terms_per_page', 20);
678
679 /**
680 * Fetch the data
681 */
682 $data = $this->get_st_Terms();
683
684 /**
685 * Pagination.
686 */
687 $current_page = $this->get_pagenum();
688 $total_items = $this->record_count();
689
690 /**
691 * Now we can add the data to the items property, where it can be used by the rest of the class.
692 */
693 $this->items = $data;
694
695 /**
696 * We also have to register our pagination options & calculations.
697 */
698 $this->set_pagination_args([
699 'total_items' => $total_items, //calculate the total number of items
700 'per_page' => $per_page, //determine how many items to show on a page
701 'total_pages' => ceil($total_items / $per_page) //calculate the total number of pages
702 ]);
703 }
704
705 /**
706 * Generates and display row actions links for the list table.
707 *
708 * @param object $item The item being acted upon.
709 * @param string $column_name Current column name.
710 * @param string $primary Primary column name.
711 *
712 * @return string The row actions HTML, or an empty string if the current column is the primary column.
713 */
714 protected function handle_row_actions($item, $column_name, $primary)
715 {
716 $taxonomy = get_taxonomy($item->taxonomy);
717
718 //Build row actions
719 $actions = [];
720
721 if (current_user_can('edit_term', $item->term_id)) {
722 $actions['edit'] = sprintf(
723 '<a href="%s">%s</a>',
724 add_query_arg(
725 [
726 'taxonomy' => $item->taxonomy,
727 'tag_ID' => $item->term_id,
728 'post_type' => isset($taxonomy->object_type[0]) ? $taxonomy->object_type[0] : 'post',
729 ],
730 admin_url('term.php')
731 ),
732 esc_html__('Edit', 'simple-tags')
733 );
734 }
735
736 // Only add other actions if not viewing via taxopress_terms_taxonomy
737 if (empty($_REQUEST['taxopress_terms_taxonomy'])) {
738 if (current_user_can('edit_term', $item->term_id)) {
739 $actions['inline hide-if-no-js'] = sprintf(
740 '<button type="button" class="button-link editinline" aria-label="%s" aria-expanded="false" data-taxonomy="' . $taxonomy->name . '" data-term-id="' . $item->term_id . '">%s</button>',
741 /* translators: %s: Taxonomy term name. */
742 esc_attr(sprintf(esc_html__('Quick edit &#8220;%s&#8221; inline', 'simple-tags'), $item->name)),
743 esc_html__('Quick&nbsp;Edit', 'simple-tags')
744 );
745 }
746
747 if (current_user_can('edit_term', $item->term_id)) {
748 $actions['remove_posts'] = sprintf(
749 '<a href="%s">%s</a>',
750 add_query_arg(
751 [
752 'page' => 'st_terms',
753 'action' => 'taxopress-remove-from-posts',
754 'taxopress_terms' => esc_attr($item->term_id),
755 '_wpnonce' => wp_create_nonce('terms-action-request-nonce')
756 ],
757 admin_url('admin.php')
758 ),
759 esc_html__('Remove From All Posts', 'simple-tags')
760 );
761 }
762
763 if (current_user_can('delete_term', $item->term_id)) {
764 $actions['delete'] = sprintf(
765 '<a href="%s" class="delete-terms">%s</a>',
766 add_query_arg(
767 [
768 'page' => 'st_terms',
769 'action' => 'taxopress-delete-terms',
770 'taxopress_terms' => esc_attr($item->term_id),
771 '_wpnonce' => wp_create_nonce('terms-action-request-nonce')
772 ],
773 admin_url('admin.php')
774 ),
775 esc_html__('Delete', 'simple-tags')
776 );
777 }
778
779 if (is_taxonomy_viewable($item->taxonomy)) {
780 $actions['view'] = sprintf(
781 '<a href="%s">%s</a>',
782 get_term_link($item->term_id),
783 esc_html__('View', 'simple-tags')
784 );
785 }
786
787 $actions['copy_term'] = sprintf(
788 '<a href="%s">%s</a>',
789 add_query_arg(
790 [
791 'page' => 'st_terms',
792 'action' => 'taxopress-copy-term',
793 'taxopress_terms' => esc_attr($item->term_id),
794 '_wpnonce' => wp_create_nonce('terms-action-request-nonce')
795 ],
796 admin_url('admin.php')
797 ),
798 esc_html__('Copy', 'simple-tags')
799 );
800 $actions = apply_filters('taxopress_terms_row_actions', $actions, $item);
801 }
802 return $column_name === $primary ? $this->row_actions($actions, false) : '';
803 }
804
805 /**
806 * Method for synonyms column
807 *
808 * @param array $item
809 *
810 * @return string
811 */
812 protected function column_synonyms($item)
813 {
814 $term_synonyms = taxopress_get_term_synonyms($item->term_id);
815 if (!empty($term_synonyms)) {
816 return join(', ', $term_synonyms);
817 } else {
818 return '-';
819 }
820 }
821
822 /**
823 * Method for linked_terms column
824 *
825 * @param array $item
826 *
827 * @return string
828 */
829 protected function column_linked_terms($item)
830 {
831 $term_linked_terms = taxopress_get_linked_terms($item->term_id);
832 if (!empty($term_linked_terms)) {
833 $term_linked_term_names = [];
834 foreach ($term_linked_terms as $term_linked_term) {
835 $linked_term_data = taxopress_get_linked_term_data($term_linked_term, $item->term_id);
836 $term_linked_term_names[] = $linked_term_data->term_name . ' ('. $linked_term_data->term_taxonomy .')';
837 }
838 return join(', ', $term_linked_term_names);
839 } else {
840 return '-';
841 }
842 }
843
844 /**
845 * Method for name column
846 *
847 * @param array $item
848 *
849 * @return string
850 */
851 protected function column_name($item)
852 {
853 $taxonomy = get_taxonomy($item->taxonomy);
854
855 // Add dashes for hierarchy
856 $depth = isset($item->taxopress_depth) ? (int)$item->taxopress_depth : 0;
857 $dash = $depth > 0 ? str_repeat('&mdash; ', $depth) : '';
858
859 $title = sprintf(
860 '<a href="%1$s"><strong><span class="row-title">%2$s%3$s</span></strong></a>',
861 add_query_arg(
862 [
863 'taxonomy' => $item->taxonomy,
864 'tag_ID' => $item->term_id,
865 'post_type' => isset($taxonomy->object_type[0]) ? $taxonomy->object_type[0] : 'post',
866 ],
867 admin_url('term.php')
868 ),
869 $dash,
870 esc_html($item->name)
871 );
872
873 $title .= ' <span class="taxopress-term-spinner" style="display:none;vertical-align:middle;"><span class="spinner is-active"></span></span>';
874
875 //for inline edit
876 $qe_data = get_term($item->term_id, $item->taxonomy, OBJECT, 'edit');
877
878 $title .= '<div class="hidden" id="inline_' . $qe_data->term_id . '">';
879 $title .= '<div class="taxonomy">' . $item->taxonomy . '</div>';
880 $title .= '<div class="name">' . $qe_data->name . '</div>';
881
882 $title .= '<div class="slug">' . apply_filters('editable_slug', $qe_data->slug, $qe_data) . '</div>';
883 $title .= '<div class="parent">' . $qe_data->parent . '</div>
884 </div>';
885
886 return $title;
887 }
888
889 /**
890 * The action column
891 *
892 * @param $item
893 *
894 * @return string
895 */
896 protected function column_slug($item)
897 {
898 return !empty($item->slug) ? $item->slug : '&mdash;';
899 }
900
901 /**
902 * The action column
903 *
904 * @param $item
905 *
906 * @return string
907 */
908 protected function column_posttypes($item)
909 {
910 $posttype = '';
911 $sn = 0;
912 $taxonomy = get_taxonomy($item->taxonomy);
913 foreach ($taxonomy->object_type as $objecttype) {
914 $sn++;
915 $post_type_object = get_post_type_object($objecttype);
916 if (is_object($post_type_object)) {
917 $posttype .= $post_type_object->label;
918 if ($sn < count($taxonomy->object_type)) {
919 $posttype .= ', ';
920 }
921 }
922 }
923
924 return $posttype;
925 }
926
927 /**
928 * The action column
929 *
930 * @param $item
931 *
932 * @return string
933 */
934 protected function column_count($item)
935 {
936 $term_counts = $this->count_posts_by_term($item->term_id, $item->taxonomy);
937
938 return sprintf(
939 '<a href="%s" class="">%s</a>',
940 add_query_arg(
941 [
942 'page' => 'st_posts',
943 'posts_term_filter' => (int) $item->term_id,
944 ],
945 admin_url('admin.php')
946 ),
947 number_format_i18n($term_counts)
948 );
949 }
950
951 protected function count_posts_by_term($term_id, $taxonomy) {
952
953 $args = array(
954 'post_type' => array_keys(get_post_types(array('public' => true), 'names')),
955 'post_status' => 'any',
956 'posts_per_page' => 1,
957 'tax_query' => array(
958 'relation' => 'AND',
959 array(
960 'taxonomy' => $taxonomy,
961 'field' => 'id',
962 'terms' => $term_id,
963 ),
964 ),
965 );
966
967 $term_count = new WP_Query($args);
968
969 if ($term_count->have_posts()) {
970 return $term_count->found_posts;
971 } else {
972 return 0;
973 }
974 }
975
976
977 /**
978 * The action column
979 *
980 * @param $item
981 *
982 * @return string
983 */
984 protected function column_description($item)
985 {
986
987 return term_description($item->term_id);
988 }
989
990 /**
991 * Method for taxonomy column
992 *
993 * @param array $item
994 *
995 * @return string
996 */
997 protected function column_taxonomy($item)
998 {
999 $taxonomy = get_taxonomy($item->taxonomy);
1000
1001 if ($taxonomy) {
1002 $return = sprintf(
1003 '<a href="%1$s">%2$s</a>',
1004 add_query_arg(
1005 [
1006 'page' => 'st_taxonomies',
1007 'add' => 'taxonomy',
1008 'action' => 'edit',
1009 'taxopress_taxonomy' => $taxonomy->name,
1010 ],
1011 taxopress_admin_url('admin.php')
1012 ),
1013 esc_html($taxonomy->labels->name)
1014 );
1015 } else {
1016 $return = '&mdash;';
1017 }
1018
1019 return $return;
1020 }
1021
1022 /**
1023 * Outputs the hidden row displayed when inline editing
1024 *
1025 * @since 3.1.0
1026 */
1027 public function inline_edit()
1028 {
1029 ?>
1030
1031 <form method="get">
1032 <table style="display: none">
1033 <tbody id="inlineedit">
1034
1035 <tr id="inline-edit" class="inline-edit-row" style="display: none">
1036 <td colspan="<?php echo esc_attr($this->get_column_count()); ?>" class="colspanchange">
1037
1038 <fieldset>
1039 <legend class="inline-edit-legend"><?php esc_html_e('Quick Edit', 'simple-tags'); ?></legend>
1040 <div class="inline-edit-col">
1041 <label>
1042 <span class="title"><?php _ex('Name', 'term name', 'simple-tags'); ?></span>
1043 <span class="input-text-wrap"><input type="text" name="name" class="ptitle" value="" /></span>
1044 </label>
1045
1046 <label>
1047 <span class="title"><?php esc_html_e('Slug', 'simple-tags'); ?></span>
1048 <span class="input-text-wrap"><input type="text" name="slug" class="ptitle" value="" /></span>
1049 </label>
1050 <label>
1051 <span class="taxonomy"><?php _ex('Taxonomy', 'term name', 'simple-tags'); ?></span>
1052
1053 <?php $taxonomies = get_all_taxopress_taxonomies(); ?>
1054 <select class="input-text-wrap edit-tax edit_taxonomy" name="edit_taxonomy">
1055 <?php
1056 foreach ($taxonomies as $taxonomy) {
1057 echo '<option value="' . esc_attr($taxonomy->name) . '">' . esc_html($taxonomy->labels->name) . '</option>';
1058 }
1059 ?>
1060 </select>
1061 </label>
1062 </div>
1063 </fieldset>
1064
1065 <div class="inline-edit-save submit">
1066 <button type="button" class="cancel button alignleft"><?php esc_html_e('Cancel', 'simple-tags'); ?></button>
1067 <button type="button" class="taxopress-save button button-primary alignright"><?php esc_html_e('Update', 'simple-tags'); ?></button>
1068 <span class="spinner"></span>
1069
1070 <?php wp_nonce_field('taxinlineeditnonce', '_inline_edit', false); ?>
1071 <br class="clear" />
1072
1073 <div class="notice notice-error notice-alt inline hidden taxopress-notice">
1074 <p class="error"></p>
1075 </div>
1076 </div>
1077
1078 </td>
1079 </tr>
1080
1081 </tbody>
1082 </table>
1083 </form>
1084 <?php
1085 }
1086 }
1087