PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / 3.40.0
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms v3.40.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 / terms-table.php

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

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