PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / trunk
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms vtrunk
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 / posts-table.php

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

542 lines 18.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_tax_query,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- Legacy TaxoPress file: keep behavior unchanged while documenting existing PHPCS exceptions.
4
5 if (!class_exists('WP_List_Table')) {
6 require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
7 }
8
9 class Taxopress_Posts_List extends WP_List_Table
10 {
11 /**
12 * Current level for output.
13 *
14 * @since 4.3.0
15 * @var int
16 */
17 protected $current_level = 0;
18
19 /** Class constructor */
20 public function __construct()
21 {
22
23 parent::__construct([
24 'singular' => esc_html__('Post', 'simple-tags'), //singular name of the listed records
25 'plural' => esc_html__('Posts', 'simple-tags'), //plural name of the listed records
26 'ajax' => true //does this table support ajax?
27 ]);
28 }
29
30 /**
31 * Associative array of columns
32 *
33 * @return array
34 */
35 public function get_columns()
36 {
37 $columns = [
38 'title' => esc_html__('Title', 'simple-tags'),
39 'taxonomy_terms' => esc_html__('Terms', 'simple-tags'),
40 'post_types' => esc_html__('Post Type', 'simple-tags'),
41 'post_status' => esc_html__('Post Status', 'simple-tags'),
42 'author' => esc_html__('Author', 'simple-tags'),
43 'date' => esc_html__('Date', 'simple-tags')
44 ];
45
46 return $columns;
47 }
48
49 /**
50 * Columns to make sortable.
51 *
52 * @return array
53 */
54 protected function get_sortable_columns()
55 {
56 $sortable_columns = [
57 'title' => 'title',
58 'date' => ['date', true],
59 ];
60
61 return $sortable_columns;
62 }
63
64 public function get_all_posts()
65 {
66
67 $search = (!empty($_REQUEST['s'])) ? sanitize_text_field(wp_unslash($_REQUEST['s'])) : '';
68 $term_filter = (!empty($_REQUEST['posts_term_filter'])) ? (int) $_REQUEST['posts_term_filter'] : '';
69 $post_types = (!empty($_REQUEST['posts_post_type_filter'])) ? sanitize_text_field(wp_unslash($_REQUEST['posts_post_type_filter'])) : '';
70
71 $orderby = (!empty($_REQUEST['orderby'])) ? sanitize_text_field(wp_unslash($_REQUEST['orderby'])) : 'date';
72 $order = (!empty($_REQUEST['order'])) ? sanitize_text_field(wp_unslash($_REQUEST['order'])) : 'DESC';
73
74
75 $posts_per_page = $this->get_items_per_page('st_posts_per_page', 20);
76
77 $page = $this->get_pagenum();
78
79 if (empty($post_types)) {
80 $post_types = get_post_types(array('public' => true), 'names');
81 if (isset($post_types['attachment'])) {
82 unset($post_types['attachment']);
83 }
84 $post_types = array_keys($post_types);
85 }
86
87 $args = array(
88 'post_type' => $post_types,
89 'post_status' => 'any',
90 'posts_per_page' => $posts_per_page,
91 'order' => $order,
92 'orderby' => $orderby,
93 'paged' => $page
94 );
95
96 if (!empty($search)) {
97 $args['s'] = $search;
98 }
99
100 if (!empty($term_filter)) {
101 $term_filter_data = get_term($term_filter);
102 if ($term_filter_data instanceof WP_Term) {
103 $args['tax_query'] = array(
104 'relation' => 'AND',
105 array(
106 'taxonomy' => $term_filter_data->taxonomy,
107 'field' => 'term_id',
108 'terms' => $term_filter_data->term_id,
109 )
110 );
111 }
112 }
113
114 $query = new WP_Query($args);
115
116 $results = [
117 'posts' => [],
118 'max_num_posts' => 0,
119 'max_num_pages' => 1
120 ];
121
122 if ($query->have_posts()) {
123 $results['posts'] = $query->posts;
124 $results['max_num_posts'] = $query->found_posts;
125 $results['max_num_pages'] = $query->max_num_pages;
126 wp_reset_postdata();
127 }
128
129
130 return $results;
131 }
132
133 /**
134 * Show single row item
135 *
136 * @param object $post
137 */
138 public function single_row($post)
139 {
140 $class = ['st-posts-tr'];
141 $id = 'post-' . $post->post_id . '';
142 echo sprintf('<tr id="%s" class="%s">', esc_attr($id), esc_attr(implode(' ', $class)));
143 $this->single_row_columns($post);
144 echo '</tr>';
145 }
146
147 /**
148 * Add custom filter to tablenav
149 *
150 * @param string $which
151 */
152 protected function extra_tablenav($which)
153 {
154
155 if ('top' === $which) {
156 $post_types = get_post_types(['public' => true], 'objects');
157
158 $posts_term_filter = (!empty($_REQUEST['posts_term_filter'])) ? (int) $_REQUEST['posts_term_filter'] : '';
159 $posts_post_type_filter = (!empty($_REQUEST['posts_post_type_filter'])) ? sanitize_text_field(wp_unslash($_REQUEST['posts_post_type_filter'])) : '';
160 ?>
161
162
163 <div class="alignleft actions autoposts-posts-table-filter">
164 <select data-nonce="<?php echo esc_attr(wp_create_nonce('taxopress-term-search')); ?>"
165 class="posts-term-filter-select taxopress-select2 taxopress-term-search"
166 data-placeholder="<?php esc_attr_e('Terms Filter', 'simple-tags'); ?>"
167 name="posts_term_filter"
168 id="posts_term_filter"
169 >
170 <option value=""><?php esc_html_e('', 'simple-tags'); ?></option>
171 <?php
172 if (!empty($posts_term_filter)) {
173 $posts_term_filter_data = get_term($posts_term_filter);
174 if (is_object($posts_term_filter_data) && !is_wp_error($posts_term_filter_data) && isset($posts_term_filter_data->term_id)) {
175 echo '<option value="' . esc_attr($posts_term_filter_data->term_id) . '" selected>' . esc_html($posts_term_filter_data->name) . '</option>';
176 }
177 }
178 ?>
179 </select>
180
181 <select class="posts-post-type-filter-select taxopress-select2 taxopress-simple-select2"
182 name="posts_post_type_filter"
183 id="posts_post_type_filter"
184 data-placeholder="<?php esc_attr_e('Post Types Filter', 'simple-tags'); ?>">
185 <option value=""><?php esc_html_e('All Post Types', 'simple-tags'); ?></option>
186 <?php
187 foreach ($post_types as $post_type) {
188 echo '<option value="' . esc_attr($post_type->name) . '" ' . selected($posts_post_type_filter, $post_type->name, false) . '>' . esc_html($post_type->label) . '</option>';
189 }
190 ?>
191 </select>
192
193 <a href="javascript:void(0)" class="taxopress-posts-tablenav-filter button"><?php esc_html_e('Filter', 'simple-tags'); ?></a>
194
195 </div>
196 <?php
197 }
198 }
199
200 /**
201 * Render a column when no column specific method exist.
202 *
203 * @param object $post
204 * @param string $column_name
205 *
206 * @return mixed
207 */
208 public function column_default($post, $column_name)
209 {
210 return !empty($post->$column_name) ? $post->$column_name : '&mdash;';
211 }
212
213 /** Text displayed when no stpost data is available */
214 public function no_items()
215 {
216 esc_html_e('No posts found.', 'simple-tags');
217 }
218
219 /**
220 * Displays the search box.
221 *
222 * @param string $text The 'submit' button label.
223 * @param string $input_id ID attribute value for the search input field.
224 *
225 *
226 */
227 public function search_box($text, $input_id)
228 {
229 if (empty($_REQUEST['s']) && !$this->has_items()) {
230 //return;
231 }
232
233 $input_id = $input_id . '-search-input';
234
235 if (!empty($_REQUEST['orderby'])) {
236 echo '<input type="hidden" name="orderby" value="' . esc_attr(sanitize_text_field(wp_unslash($_REQUEST['orderby']))) . '" />';
237 }
238 if (!empty($_REQUEST['order'])) {
239 echo '<input type="hidden" name="order" value="' . esc_attr(sanitize_text_field(wp_unslash($_REQUEST['order']))) . '" />';
240 }
241 if (!empty($_REQUEST['page'])) {
242 echo '<input type="hidden" name="page" value="' . esc_attr(sanitize_text_field(wp_unslash($_REQUEST['page']))) . '" />';
243 }
244
245 $custom_filters = ['posts_term_filter', 'posts_post_type_filter'];
246
247 foreach ($custom_filters as $custom_filter) {
248 $filter_value = !empty($_REQUEST[$custom_filter]) ? sanitize_text_field(wp_unslash($_REQUEST[$custom_filter])) : '';
249 echo '<input type="hidden" name="' . esc_attr($custom_filter) . '" value="' . esc_attr($filter_value) . '" />';
250 }
251 ?>
252 <p class="search-box">
253 <label class="screen-reader-text" for="<?php echo esc_attr($input_id); ?>"><?php echo esc_html($text); ?>:</label>
254 <input type="search" id="<?php echo esc_attr($input_id); ?>" name="s" value="<?php _admin_search_query(); ?>" />
255 <?php submit_button($text, '', '', false, ['id' => 'taxopress-posts-search-submit']); ?>
256 </p>
257 <?php
258 }
259
260 /**
261 * Sets up the items (roles) to list.
262 */
263 public function prepare_items()
264 {
265
266 $this->_column_headers = $this->get_column_info();
267 $this->process_bulk_action();
268
269 /**
270 * First, lets decide how many records per page to show
271 */
272 $per_page = $this->get_items_per_page('st_posts_per_page', 20);
273
274 /**
275 * Fetch the data
276 */
277 $posts_data = $this->get_all_posts();
278 $data = $posts_data['posts'];
279
280 /**
281 * Pagination.
282 */
283 $current_page = $this->get_pagenum();
284 $total_items = $posts_data['max_num_posts'];
285
286 /**
287 * Now we can add the data to the items property, where it can be used by the rest of the class.
288 */
289 $this->items = $data;
290
291 /**
292 * We also have to register our pagination options & calculations.
293 */
294 $this->set_pagination_args([
295 'total_items' => $total_items, //calculate the total number of items
296 'per_page' => $per_page, //depostine how many items to show on a page
297 'total_pages' => ceil($total_items / $per_page) //calculate the total number of pages
298 ]);
299 }
300
301 /**
302 * Method for name column
303 *
304 * @param object $post
305 *
306 * @return string
307 */
308 protected function column_title($post)
309 {
310
311 if (current_user_can('edit_post', $post->ID)) {
312 $title = sprintf(
313 '<a href="%1$s"><strong><span class="row-title">%2$s</span></strong></a>',
314 add_query_arg(
315 [
316 'post' => $post->ID,
317 'action' => 'edit'
318 ],
319 admin_url('post.php')
320 ),
321 esc_html(get_the_title($post))
322 );
323 } else {
324 $title = '<strong><span class="row-title">' . get_the_title($post) . '</span></strong>';
325 }
326
327 return $title;
328 }
329
330 /**
331 * The action column
332 *
333 * @param $post
334 *
335 * @return string
336 */
337 protected function column_author($post)
338 {
339
340 if (function_exists(('get_post_authors'))) {
341 $authors = get_post_authors($post->ID, true);
342 $author_name = [];
343 foreach ($authors as $author) {
344 if (is_object($author) && isset($author->display_name)) {
345 $author_name[] = $author->display_name;
346 }
347 }
348 $out = join(', ', $author_name);
349 } else {
350 $out = get_the_author_meta('display_name', $post->post_author);
351 }
352
353 return $out;
354 }
355
356 /**
357 * The action column
358 *
359 * @param $post
360 *
361 * @return string
362 */
363 protected function column_post_types($post)
364 {
365 $post_type = $post->post_type;
366 $post_type_object = get_post_type_object($post->post_type);
367 if (is_object($post_type_object)) {
368 $post_type = $post_type_object->label;
369 }
370
371 $out = '<a href="' . $this->update_or_add_url_parameter('posts_post_type_filter', $post->post_type) . '">' . $post_type . '</a>';
372
373 return $out;
374 }
375
376 /**
377 * The action column
378 *
379 * @param $post
380 *
381 * @return string
382 */
383 protected function column_taxonomy_terms($post)
384 {
385 $out = '';
386
387 $taxonomy_type = SimpleTags_Plugin::get_option_value('post_terms_taxonomy_type');
388
389 // Get all the taxonomies for the post
390 $taxonomies = get_object_taxonomies($post->post_type, 'objects');
391
392 if (!empty($taxonomies)) {
393 foreach ($taxonomies as $taxonomy_slug => $taxonomy) {
394 // Check if the taxonomy should be displayed based on $taxonomy_type
395 if ($taxonomy_type === 'public' && $taxonomy->public === false) {
396 continue;
397 } elseif ($taxonomy_type === 'private' && $taxonomy->public === true) {
398 continue;
399 }
400
401 // Get the assigned terms for each taxonomy
402 $terms = get_the_terms($post->ID, $taxonomy_slug);
403 if (!empty($terms) && !is_wp_error($terms)) {
404 $out .= '<div class="taxopress-post-taxonomy">';
405 $out .= "<strong>{$taxonomy->labels->name}:</strong> ";
406 $out .= '<span class="taxopress-post-taxonomy-terms">';
407
408 $term_links = [];
409 foreach ($terms as $term) {
410 $link_label = esc_html(sanitize_term_field('name', $term->name, $term->term_id, $taxonomy_slug, 'display'));
411 $link_url = $this->update_or_add_url_parameter('posts_term_filter', $term->term_id);
412 $term_links[] = sprintf(
413 '<a href="%s">%s</a>',
414 esc_url($link_url),
415 esc_html($link_label)
416 );
417 }
418 $out .= implode(', ', $term_links);
419 $out .= "</span>";
420 $out .= '</div>';
421 }
422 }
423 }
424
425 return $out;
426 }
427
428 protected function update_or_add_url_parameter($param_name, $param_value)
429 {
430
431 $url = sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI']));
432
433 // Check if the parameter already exists in the URL
434 $existing_param = get_query_var($param_name);
435
436 if ($existing_param) {
437 // Update the parameter value
438 $url = add_query_arg($param_name, $param_value, $url);
439 } else {
440 // Add the parameter with its value
441 $url = add_query_arg(array($param_name => $param_value), $url);
442 }
443
444 return $url;
445 }
446
447 /**
448 * The action column
449 *
450 * @param $post
451 *
452 * @return string
453 */
454 protected function column_post_status($post)
455 {
456 $post_status = $post->post_status;
457 $post_status_object = get_post_status_object($post->post_status);
458 if (is_object($post_status_object)) {
459 $post_status = $post_status_object->label;
460 }
461
462 $out = $post_status;
463
464 return $out;
465 }
466
467 /**
468 * Handles the post date column output.
469 *
470 * @since 4.3.0
471 *
472 * @global string $mode List table view mode.
473 *
474 * @param WP_Post $post The current WP_Post object.
475 */
476 public function column_date($post)
477 {
478
479 $mode = get_user_setting('posts_list_mode', 'list');
480 if ('0000-00-00 00:00:00' === $post->post_date) {
481 $t_time = __('Unpublished');
482 $time_diff = 0;
483 } else {
484 $t_time = sprintf(
485 /* translators: 1: Post date, 2: Post time. */
486 __('%1$s at %2$s'),
487 /* translators: Post date format. See https://www.php.net/manual/datetime.format.php */
488 get_the_time(__('Y/m/d'), $post),
489 /* translators: Post time format. See https://www.php.net/manual/datetime.format.php */
490 get_the_time(__('g:i a'), $post)
491 );
492
493 $time = get_post_timestamp($post);
494 $time_diff = time() - $time;
495 }
496
497 if ('publish' === $post->post_status) {
498 $status = __('Published');
499 } elseif ('future' === $post->post_status) {
500 if ($time_diff > 0) {
501 $status = '<strong class="error-message">' . __('Missed schedule') . '</strong>';
502 } else {
503 $status = __('Scheduled');
504 }
505 } else {
506 $status = __('Last Modified');
507 }
508
509 /**
510 * Filters the status text of the post.
511 *
512 * @since 4.8.0
513 *
514 * @param string $status The status text.
515 * @param WP_Post $post Post object.
516 * @param string $column_name The column name.
517 * @param string $mode The list display mode ('excerpt' or 'list').
518 */
519 $status = apply_filters('post_date_column_status', $status, $post, 'date', $mode);
520
521 if ($status) {
522 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
523 echo $status . '<br />';
524 }
525
526 /**
527 * Filters the published time of the post.
528 *
529 * @since 2.5.1
530 * @since 5.5.0 Removed the difference between 'excerpt' and 'list' modes.
531 * The published time and date are both displayed now,
532 * which is equivalent to the previous 'excerpt' mode.
533 *
534 * @param string $t_time The published time.
535 * @param WP_Post $post Post object.
536 * @param string $column_name The column name.
537 * @param string $mode The list display mode ('excerpt' or 'list').
538 */
539 echo apply_filters('post_date_column_time', $t_time, $post, 'date', $mode); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
540 }
541 }
542