run:R W Run
7.85 KB
2026-03-11 16:18:51
R W Run
3.54 KB
2026-03-11 16:18:51
R W Run
148.33 KB
2026-03-11 16:18:51
R W Run
11.45 KB
2026-03-11 16:18:51
R W Run
3.58 KB
2026-03-11 16:18:51
R W Run
2.53 KB
2026-03-11 16:18:51
R W Run
2.6 KB
2026-03-11 16:18:51
R W Run
6.59 KB
2026-03-11 16:18:51
R W Run
14.83 KB
2026-03-11 16:18:51
R W Run
21.18 KB
2026-03-11 16:18:51
R W Run
48.13 KB
2026-03-11 16:18:51
R W Run
4.07 KB
2026-03-11 16:18:51
R W Run
5.3 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
26.73 KB
2026-03-11 16:18:51
R W Run
2.8 KB
2026-03-11 16:18:51
R W Run
15.2 KB
2026-03-11 16:18:51
R W Run
192.08 KB
2026-03-11 16:18:51
R W Run
11.77 KB
2026-03-11 16:18:51
R W Run
3.2 KB
2026-03-11 16:18:51
R W Run
22.89 KB
2026-03-11 16:18:51
R W Run
12.77 KB
2026-03-11 16:18:51
R W Run
4.08 KB
2026-03-11 16:18:51
R W Run
26.27 KB
2026-03-11 16:18:51
R W Run
4.97 KB
2026-03-11 16:18:51
R W Run
5.57 KB
2026-03-11 16:18:51
R W Run
13.93 KB
2026-03-11 16:18:51
R W Run
4.09 KB
2026-03-11 16:18:51
R W Run
6.79 KB
2026-03-11 16:18:51
R W Run
60.45 KB
2026-03-11 16:18:51
R W Run
32.4 KB
2026-03-11 16:18:51
R W Run
18.24 KB
2026-03-11 16:18:51
R W Run
66.01 KB
2026-03-11 16:18:51
R W Run
23.84 KB
2026-03-11 16:18:51
R W Run
17.72 KB
2026-03-11 16:18:51
R W Run
22.71 KB
2026-03-11 16:18:51
R W Run
18.05 KB
2026-03-11 16:18:51
R W Run
22.76 KB
2026-03-11 16:18:51
R W Run
7.34 KB
2026-03-11 16:18:51
R W Run
4.51 KB
2026-03-11 16:18:51
R W Run
9.02 KB
2026-03-11 16:18:51
R W Run
1.46 KB
2026-03-11 16:18:51
R W Run
51.76 KB
2026-03-11 16:18:51
R W Run
25.29 KB
2026-03-11 16:18:51
R W Run
21.61 KB
2026-03-11 16:18:51
R W Run
27.77 KB
2026-03-11 16:18:51
R W Run
15.35 KB
2026-03-11 16:18:51
R W Run
24.54 KB
2026-03-11 16:18:51
R W Run
56.44 KB
2026-03-11 16:18:51
R W Run
1.42 KB
2026-03-11 16:18:51
R W Run
63.66 KB
2026-03-11 16:18:51
R W Run
31.9 KB
2026-03-11 16:18:51
R W Run
14.44 KB
2026-03-11 16:18:51
R W Run
36.47 KB
2026-03-11 16:18:51
R W Run
14 KB
2026-03-11 16:18:51
R W Run
121.89 KB
2026-03-11 16:18:51
R W Run
6.26 KB
2026-03-11 16:18:51
R W Run
20.73 KB
2026-03-11 16:18:51
R W Run
15.23 KB
2026-03-11 16:18:51
R W Run
10.14 KB
2026-03-11 16:18:51
R W Run
6.94 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
46.85 KB
2026-03-11 16:18:51
R W Run
18.61 KB
2026-03-11 16:18:51
R W Run
6.08 KB
2026-03-11 16:18:51
R W Run
20.06 KB
2026-03-11 16:18:51
R W Run
5.73 KB
2026-03-11 16:18:51
R W Run
68.18 KB
2026-03-11 16:18:51
R W Run
40.8 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
25.26 KB
2026-03-11 16:18:51
R W Run
95.94 KB
2026-03-11 16:18:51
R W Run
43.12 KB
2026-03-11 16:18:51
R W Run
41.73 KB
2026-03-11 16:18:51
R W Run
6.46 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
116.31 KB
2026-03-11 16:18:51
R W Run
9.39 KB
2026-03-11 16:18:51
R W Run
64.34 KB
2026-03-11 16:18:51
R W Run
44.73 KB
2026-03-11 16:18:51
R W Run
1.27 KB
2026-03-11 16:18:51
R W Run
3.68 KB
2026-03-11 16:18:51
R W Run
33.53 KB
2026-03-11 16:18:51
R W Run
48.84 KB
2026-03-11 16:18:51
R W Run
26.35 KB
2026-03-11 16:18:51
R W Run
1.12 KB
2026-03-11 16:18:51
R W Run
4.19 KB
2026-03-11 16:18:51
R W Run
38.19 KB
2026-03-11 16:18:51
R W Run
91.33 KB
2026-03-11 16:18:51
R W Run
80.39 KB
2026-03-11 16:18:51
R W Run
32.67 KB
2026-03-11 16:18:51
R W Run
16.18 KB
2026-03-11 16:18:51
R W Run
44.46 KB
2026-03-11 16:18:51
R W Run
6.23 KB
2026-03-11 16:18:51
R W Run
8.23 KB
2026-03-11 16:18:51
R W Run
96.96 KB
2026-03-11 16:18:51
R W Run
6.83 KB
2026-03-11 16:18:51
R W Run
46.62 KB
2026-03-11 16:18:51
R W Run
10.82 KB
2026-03-11 16:18:51
R W Run
68.86 KB
2026-03-11 16:18:51
R W Run
33.63 KB
2026-03-11 16:18:51
R W Run
113.3 KB
2026-03-11 16:18:51
R W Run
22.98 KB
2026-03-11 16:18:51
R W Run
10.66 KB
2026-03-11 16:18:51
R W Run
error_log
📄class-wp-posts-list-table.php
1<?php
2/**
3 * List Table API: WP_Posts_List_Table class
4 *
5 * @package WordPress
6 * @subpackage Administration
7 * @since 3.1.0
8 */
9
10/**
11 * Core class used to implement displaying posts in a list table.
12 *
13 * @since 3.1.0
14 *
15 * @see WP_List_Table
16 */
17class WP_Posts_List_Table extends WP_List_Table {
18
19 /**
20 * Whether the items should be displayed hierarchically or linearly.
21 *
22 * @since 3.1.0
23 * @var bool
24 */
25 protected $hierarchical_display;
26
27 /**
28 * Holds the number of pending comments for each post.
29 *
30 * @since 3.1.0
31 * @var array
32 */
33 protected $comment_pending_count;
34
35 /**
36 * Holds the number of posts for this user.
37 *
38 * @since 3.1.0
39 * @var int
40 */
41 private $user_posts_count;
42
43 /**
44 * Holds the number of posts which are sticky.
45 *
46 * @since 3.1.0
47 * @var int
48 */
49 private $sticky_posts_count = 0;
50
51 private $is_trash;
52
53 /**
54 * Current level for output.
55 *
56 * @since 4.3.0
57 * @var int
58 */
59 protected $current_level = 0;
60
61 /**
62 * Constructor.
63 *
64 * @since 3.1.0
65 *
66 * @see WP_List_Table::__construct() for more information on default arguments.
67 *
68 * @global WP_Post_Type $post_type_object Global post type object.
69 * @global wpdb $wpdb WordPress database abstraction object.
70 *
71 * @param array $args An associative array of arguments.
72 */
73 public function __construct( $args = array() ) {
74 global $post_type_object, $wpdb;
75
76 parent::__construct(
77 array(
78 'plural' => 'posts',
79 'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
80 )
81 );
82
83 $post_type = $this->screen->post_type;
84 $post_type_object = get_post_type_object( $post_type );
85
86 $exclude_states = get_post_stati(
87 array(
88 'show_in_admin_all_list' => false,
89 )
90 );
91
92 $this->user_posts_count = (int) $wpdb->get_var(
93 $wpdb->prepare(
94 "SELECT COUNT( 1 )
95 FROM $wpdb->posts
96 WHERE post_type = %s
97 AND post_status NOT IN ( '" . implode( "','", $exclude_states ) . "' )
98 AND post_author = %d",
99 $post_type,
100 get_current_user_id()
101 )
102 );
103
104 if ( $this->user_posts_count
105 && ! current_user_can( $post_type_object->cap->edit_others_posts )
106 && empty( $_REQUEST['post_status'] ) && empty( $_REQUEST['all_posts'] )
107 && empty( $_REQUEST['author'] ) && empty( $_REQUEST['show_sticky'] )
108 ) {
109 $_GET['author'] = get_current_user_id();
110 }
111
112 $sticky_posts = get_option( 'sticky_posts' );
113
114 if ( 'post' === $post_type && $sticky_posts ) {
115 $sticky_posts = implode( ', ', array_map( 'absint', (array) $sticky_posts ) );
116
117 $this->sticky_posts_count = (int) $wpdb->get_var(
118 $wpdb->prepare(
119 "SELECT COUNT( 1 )
120 FROM $wpdb->posts
121 WHERE post_type = %s
122 AND post_status NOT IN ('trash', 'auto-draft')
123 AND ID IN ($sticky_posts)",
124 $post_type
125 )
126 );
127 }
128 }
129
130 /**
131 * Sets whether the table layout should be hierarchical or not.
132 *
133 * @since 4.2.0
134 *
135 * @param bool $display Whether the table layout should be hierarchical.
136 */
137 public function set_hierarchical_display( $display ) {
138 $this->hierarchical_display = $display;
139 }
140
141 /**
142 * @return bool
143 */
144 public function ajax_user_can() {
145 return current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_posts );
146 }
147
148 /**
149 * @global string $mode List table view mode.
150 * @global array $avail_post_stati
151 * @global WP_Query $wp_query WordPress Query object.
152 * @global int $per_page
153 */
154 public function prepare_items() {
155 global $mode, $avail_post_stati, $wp_query, $per_page;
156
157 if ( ! empty( $_REQUEST['mode'] ) ) {
158 $mode = 'excerpt' === $_REQUEST['mode'] ? 'excerpt' : 'list';
159 set_user_setting( 'posts_list_mode', $mode );
160 } else {
161 $mode = get_user_setting( 'posts_list_mode', 'list' );
162 }
163
164 // Is going to call wp().
165 $avail_post_stati = wp_edit_posts_query();
166
167 $this->set_hierarchical_display(
168 is_post_type_hierarchical( $this->screen->post_type )
169 && 'menu_order title' === $wp_query->query['orderby']
170 );
171
172 $post_type = $this->screen->post_type;
173 $per_page = $this->get_items_per_page( 'edit_' . $post_type . '_per_page' );
174
175 /** This filter is documented in wp-admin/includes/post.php */
176 $per_page = apply_filters( 'edit_posts_per_page', $per_page, $post_type );
177
178 if ( $this->hierarchical_display ) {
179 $total_items = $wp_query->post_count;
180 } elseif ( $wp_query->found_posts || $this->get_pagenum() === 1 ) {
181 $total_items = $wp_query->found_posts;
182 } else {
183 $post_counts = (array) wp_count_posts( $post_type, 'readable' );
184
185 if ( isset( $_REQUEST['post_status'] ) && in_array( $_REQUEST['post_status'], $avail_post_stati, true ) ) {
186 $total_items = $post_counts[ $_REQUEST['post_status'] ];
187 } elseif ( isset( $_REQUEST['show_sticky'] ) && $_REQUEST['show_sticky'] ) {
188 $total_items = $this->sticky_posts_count;
189 } elseif ( isset( $_GET['author'] ) && get_current_user_id() === (int) $_GET['author'] ) {
190 $total_items = $this->user_posts_count;
191 } else {
192 $total_items = array_sum( $post_counts );
193
194 // Subtract post types that are not included in the admin all list.
195 foreach ( get_post_stati( array( 'show_in_admin_all_list' => false ) ) as $state ) {
196 $total_items -= $post_counts[ $state ];
197 }
198 }
199 }
200
201 $this->is_trash = isset( $_REQUEST['post_status'] ) && 'trash' === $_REQUEST['post_status'];
202
203 $this->set_pagination_args(
204 array(
205 'total_items' => $total_items,
206 'per_page' => $per_page,
207 )
208 );
209 }
210
211 /**
212 * @return bool
213 */
214 public function has_items() {
215 return have_posts();
216 }
217
218 /**
219 */
220 public function no_items() {
221 if ( isset( $_REQUEST['post_status'] ) && 'trash' === $_REQUEST['post_status'] ) {
222 echo get_post_type_object( $this->screen->post_type )->labels->not_found_in_trash;
223 } else {
224 echo get_post_type_object( $this->screen->post_type )->labels->not_found;
225 }
226 }
227
228 /**
229 * Determines if the current view is the "All" view.
230 *
231 * @since 4.2.0
232 *
233 * @return bool Whether the current view is the "All" view.
234 */
235 protected function is_base_request() {
236 $vars = $_GET;
237 unset( $vars['paged'] );
238
239 if ( empty( $vars ) ) {
240 return true;
241 } elseif ( 1 === count( $vars ) && ! empty( $vars['post_type'] ) ) {
242 return $this->screen->post_type === $vars['post_type'];
243 }
244
245 return 1 === count( $vars ) && ! empty( $vars['mode'] );
246 }
247
248 /**
249 * Creates a link to edit.php with params.
250 *
251 * @since 4.4.0
252 *
253 * @param string[] $args Associative array of URL parameters for the link.
254 * @param string $link_text Link text.
255 * @param string $css_class Optional. Class attribute. Default empty string.
256 * @return string The formatted link string.
257 */
258 protected function get_edit_link( $args, $link_text, $css_class = '' ) {
259 $url = add_query_arg( $args, 'edit.php' );
260
261 $class_html = '';
262 $aria_current = '';
263
264 if ( ! empty( $css_class ) ) {
265 $class_html = sprintf(
266 ' class="%s"',
267 esc_attr( $css_class )
268 );
269
270 if ( 'current' === $css_class ) {
271 $aria_current = ' aria-current="page"';
272 }
273 }
274
275 return sprintf(
276 '<a href="%s"%s%s>%s</a>',
277 esc_url( $url ),
278 $class_html,
279 $aria_current,
280 $link_text
281 );
282 }
283
284 /**
285 * @global array $locked_post_status This seems to be deprecated.
286 * @global array $avail_post_stati
287 * @return array
288 */
289 protected function get_views() {
290 global $locked_post_status, $avail_post_stati;
291
292 $post_type = $this->screen->post_type;
293
294 if ( ! empty( $locked_post_status ) ) {
295 return array();
296 }
297
298 $status_links = array();
299 $num_posts = wp_count_posts( $post_type, 'readable' );
300 $total_posts = array_sum( (array) $num_posts );
301 $class = '';
302
303 $current_user_id = get_current_user_id();
304 $all_args = array( 'post_type' => $post_type );
305 $mine = '';
306
307 // Subtract post types that are not included in the admin all list.
308 foreach ( get_post_stati( array( 'show_in_admin_all_list' => false ) ) as $state ) {
309 $total_posts -= $num_posts->$state;
310 }
311
312 if ( $this->user_posts_count && $this->user_posts_count !== $total_posts ) {
313 if ( isset( $_GET['author'] ) && ( $current_user_id === (int) $_GET['author'] ) ) {
314 $class = 'current';
315 }
316
317 $mine_args = array(
318 'post_type' => $post_type,
319 'author' => $current_user_id,
320 );
321
322 $mine_inner_html = sprintf(
323 /* translators: %s: Number of posts. */
324 _nx(
325 'Mine <span class="count">(%s)</span>',
326 'Mine <span class="count">(%s)</span>',
327 $this->user_posts_count,
328 'posts'
329 ),
330 number_format_i18n( $this->user_posts_count )
331 );
332
333 $mine = array(
334 'url' => esc_url( add_query_arg( $mine_args, 'edit.php' ) ),
335 'label' => $mine_inner_html,
336 'current' => isset( $_GET['author'] ) && ( $current_user_id === (int) $_GET['author'] ),
337 );
338
339 $all_args['all_posts'] = 1;
340 $class = '';
341 }
342
343 $all_inner_html = sprintf(
344 /* translators: %s: Number of posts. */
345 _nx(
346 'All <span class="count">(%s)</span>',
347 'All <span class="count">(%s)</span>',
348 $total_posts,
349 'posts'
350 ),
351 number_format_i18n( $total_posts )
352 );
353
354 $status_links['all'] = array(
355 'url' => esc_url( add_query_arg( $all_args, 'edit.php' ) ),
356 'label' => $all_inner_html,
357 'current' => empty( $class ) && ( $this->is_base_request() || isset( $_REQUEST['all_posts'] ) ),
358 );
359
360 if ( $mine ) {
361 $status_links['mine'] = $mine;
362 }
363
364 foreach ( get_post_stati( array( 'show_in_admin_status_list' => true ), 'objects' ) as $status ) {
365 $class = '';
366
367 $status_name = $status->name;
368
369 if ( ! in_array( $status_name, $avail_post_stati, true ) || empty( $num_posts->$status_name ) ) {
370 continue;
371 }
372
373 if ( isset( $_REQUEST['post_status'] ) && $status_name === $_REQUEST['post_status'] ) {
374 $class = 'current';
375 }
376
377 $status_args = array(
378 'post_status' => $status_name,
379 'post_type' => $post_type,
380 );
381
382 $status_label = sprintf(
383 translate_nooped_plural( $status->label_count, $num_posts->$status_name ),
384 number_format_i18n( $num_posts->$status_name )
385 );
386
387 $status_links[ $status_name ] = array(
388 'url' => esc_url( add_query_arg( $status_args, 'edit.php' ) ),
389 'label' => $status_label,
390 'current' => isset( $_REQUEST['post_status'] ) && $status_name === $_REQUEST['post_status'],
391 );
392 }
393
394 if ( ! empty( $this->sticky_posts_count ) ) {
395 $class = ! empty( $_REQUEST['show_sticky'] ) ? 'current' : '';
396
397 $sticky_args = array(
398 'post_type' => $post_type,
399 'show_sticky' => 1,
400 );
401
402 $sticky_inner_html = sprintf(
403 /* translators: %s: Number of posts. */
404 _nx(
405 'Sticky <span class="count">(%s)</span>',
406 'Sticky <span class="count">(%s)</span>',
407 $this->sticky_posts_count,
408 'posts'
409 ),
410 number_format_i18n( $this->sticky_posts_count )
411 );
412
413 $sticky_link = array(
414 'sticky' => array(
415 'url' => esc_url( add_query_arg( $sticky_args, 'edit.php' ) ),
416 'label' => $sticky_inner_html,
417 'current' => ! empty( $_REQUEST['show_sticky'] ),
418 ),
419 );
420
421 // Sticky comes after Publish, or if not listed, after All.
422 $split = 1 + array_search( ( isset( $status_links['publish'] ) ? 'publish' : 'all' ), array_keys( $status_links ), true );
423 $status_links = array_merge( array_slice( $status_links, 0, $split ), $sticky_link, array_slice( $status_links, $split ) );
424 }
425
426 return $this->get_views_links( $status_links );
427 }
428
429 /**
430 * @return array
431 */
432 protected function get_bulk_actions() {
433 $actions = array();
434 $post_type_obj = get_post_type_object( $this->screen->post_type );
435
436 if ( current_user_can( $post_type_obj->cap->edit_posts ) ) {
437 if ( $this->is_trash ) {
438 $actions['untrash'] = __( 'Restore' );
439 } else {
440 $actions['edit'] = __( 'Edit' );
441 }
442 }
443
444 if ( current_user_can( $post_type_obj->cap->delete_posts ) ) {
445 if ( $this->is_trash || ! EMPTY_TRASH_DAYS ) {
446 $actions['delete'] = __( 'Delete permanently' );
447 } else {
448 $actions['trash'] = __( 'Move to Trash' );
449 }
450 }
451
452 return $actions;
453 }
454
455 /**
456 * Displays a categories drop-down for filtering on the Posts list table.
457 *
458 * @since 4.6.0
459 *
460 * @global int $cat Currently selected category.
461 *
462 * @param string $post_type Post type slug.
463 */
464 protected function categories_dropdown( $post_type ) {
465 global $cat;
466
467 /**
468 * Filters whether to remove the 'Categories' drop-down from the post list table.
469 *
470 * @since 4.6.0
471 *
472 * @param bool $disable Whether to disable the categories drop-down. Default false.
473 * @param string $post_type Post type slug.
474 */
475 if ( false !== apply_filters( 'disable_categories_dropdown', false, $post_type ) ) {
476 return;
477 }
478
479 if ( is_object_in_taxonomy( $post_type, 'category' ) ) {
480 $dropdown_options = array(
481 'show_option_all' => get_taxonomy( 'category' )->labels->all_items,
482 'hide_empty' => 0,
483 'hierarchical' => 1,
484 'show_count' => 0,
485 'orderby' => 'name',
486 'selected' => $cat,
487 );
488
489 echo '<label class="screen-reader-text" for="cat">' . get_taxonomy( 'category' )->labels->filter_by_item . '</label>';
490
491 wp_dropdown_categories( $dropdown_options );
492 }
493 }
494
495 /**
496 * Displays a formats drop-down for filtering items.
497 *
498 * @since 5.2.0
499 *
500 * @param string $post_type Post type slug.
501 */
502 protected function formats_dropdown( $post_type ) {
503 /**
504 * Filters whether to remove the 'Formats' drop-down from the post list table.
505 *
506 * @since 5.2.0
507 * @since 5.5.0 The `$post_type` parameter was added.
508 *
509 * @param bool $disable Whether to disable the drop-down. Default false.
510 * @param string $post_type Post type slug.
511 */
512 if ( apply_filters( 'disable_formats_dropdown', false, $post_type ) ) {
513 return;
514 }
515
516 // Return if the post type doesn't have post formats or if we're in the Trash.
517 if ( ! is_object_in_taxonomy( $post_type, 'post_format' ) || $this->is_trash ) {
518 return;
519 }
520
521 // Make sure the dropdown shows only formats with a post count greater than 0.
522 $used_post_formats = get_terms(
523 array(
524 'taxonomy' => 'post_format',
525 'hide_empty' => true,
526 )
527 );
528
529 // Return if there are no posts using formats.
530 if ( ! $used_post_formats ) {
531 return;
532 }
533
534 $displayed_post_format = isset( $_GET['post_format'] ) ? $_GET['post_format'] : '';
535 ?>
536 <label for="filter-by-format" class="screen-reader-text">
537 <?php
538 /* translators: Hidden accessibility text. */
539 _e( 'Filter by post format' );
540 ?>
541 </label>
542 <select name="post_format" id="filter-by-format">
543 <option<?php selected( $displayed_post_format, '' ); ?> value=""><?php _e( 'All formats' ); ?></option>
544 <?php
545 foreach ( $used_post_formats as $used_post_format ) {
546 // Post format slug.
547 $slug = str_replace( 'post-format-', '', $used_post_format->slug );
548 // Pretty, translated version of the post format slug.
549 $pretty_name = get_post_format_string( $slug );
550
551 // Skip the standard post format.
552 if ( 'standard' === $slug ) {
553 continue;
554 }
555 ?>
556 <option<?php selected( $displayed_post_format, $slug ); ?> value="<?php echo esc_attr( $slug ); ?>"><?php echo esc_html( $pretty_name ); ?></option>
557 <?php
558 }
559 ?>
560 </select>
561 <?php
562 }
563
564 /**
565 * @param string $which
566 */
567 protected function extra_tablenav( $which ) {
568 ?>
569 <div class="alignleft actions">
570 <?php
571 if ( 'top' === $which ) {
572 ob_start();
573
574 $this->months_dropdown( $this->screen->post_type );
575 $this->categories_dropdown( $this->screen->post_type );
576 $this->formats_dropdown( $this->screen->post_type );
577
578 /**
579 * Fires before the Filter button on the Posts and Pages list tables.
580 *
581 * The Filter button allows sorting by date and/or category on the
582 * Posts list table, and sorting by date on the Pages list table.
583 *
584 * @since 2.1.0
585 * @since 4.4.0 The `$post_type` parameter was added.
586 * @since 4.6.0 The `$which` parameter was added.
587 *
588 * @param string $post_type The post type slug.
589 * @param string $which The location of the extra table nav markup:
590 * 'top' or 'bottom' for WP_Posts_List_Table,
591 * 'bar' for WP_Media_List_Table.
592 */
593 do_action( 'restrict_manage_posts', $this->screen->post_type, $which );
594
595 $output = ob_get_clean();
596
597 if ( ! empty( $output ) ) {
598 echo $output;
599 submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
600 }
601 }
602
603 if ( $this->is_trash && $this->has_items()
604 && current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_others_posts )
605 ) {
606 submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false );
607 }
608 ?>
609 </div>
610 <?php
611 /**
612 * Fires immediately following the closing "actions" div in the tablenav for the posts
613 * list table.
614 *
615 * @since 4.4.0
616 *
617 * @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
618 */
619 do_action( 'manage_posts_extra_tablenav', $which );
620 }
621
622 /**
623 * @return string
624 */
625 public function current_action() {
626 if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) {
627 return 'delete_all';
628 }
629
630 return parent::current_action();
631 }
632
633 /**
634 * @global string $mode List table view mode.
635 *
636 * @return array
637 */
638 protected function get_table_classes() {
639 global $mode;
640
641 $mode_class = esc_attr( 'table-view-' . $mode );
642
643 return array(
644 'widefat',
645 'fixed',
646 'striped',
647 $mode_class,
648 is_post_type_hierarchical( $this->screen->post_type ) ? 'pages' : 'posts',
649 );
650 }
651
652 /**
653 * @return string[] Array of column titles keyed by their column name.
654 */
655 public function get_columns() {
656 $post_type = $this->screen->post_type;
657
658 $posts_columns = array();
659
660 $posts_columns['cb'] = '<input type="checkbox" />';
661
662 /* translators: Posts screen column name. */
663 $posts_columns['title'] = _x( 'Title', 'column name' );
664
665 if ( post_type_supports( $post_type, 'author' ) ) {
666 $posts_columns['author'] = __( 'Author' );
667 }
668
669 $taxonomies = get_object_taxonomies( $post_type, 'objects' );
670 $taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' );
671
672 /**
673 * Filters the taxonomy columns in the Posts list table.
674 *
675 * The dynamic portion of the hook name, `$post_type`, refers to the post
676 * type slug.
677 *
678 * Possible hook names include:
679 *
680 * - `manage_taxonomies_for_post_columns`
681 * - `manage_taxonomies_for_page_columns`
682 *
683 * @since 3.5.0
684 *
685 * @param string[] $taxonomies Array of taxonomy names to show columns for.
686 * @param string $post_type The post type.
687 */
688 $taxonomies = apply_filters( "manage_taxonomies_for_{$post_type}_columns", $taxonomies, $post_type );
689 $taxonomies = array_filter( $taxonomies, 'taxonomy_exists' );
690
691 foreach ( $taxonomies as $taxonomy ) {
692 if ( 'category' === $taxonomy ) {
693 $column_key = 'categories';
694 } elseif ( 'post_tag' === $taxonomy ) {
695 $column_key = 'tags';
696 } else {
697 $column_key = 'taxonomy-' . $taxonomy;
698 }
699
700 $posts_columns[ $column_key ] = get_taxonomy( $taxonomy )->labels->name;
701 }
702
703 $post_status = ! empty( $_REQUEST['post_status'] ) ? $_REQUEST['post_status'] : 'all';
704
705 if ( post_type_supports( $post_type, 'comments' )
706 && ! in_array( $post_status, array( 'pending', 'draft', 'future' ), true )
707 ) {
708 $posts_columns['comments'] = sprintf(
709 '<span class="vers comment-grey-bubble" title="%1$s" aria-hidden="true"></span><span class="screen-reader-text">%2$s</span>',
710 esc_attr__( 'Comments' ),
711 /* translators: Hidden accessibility text. */
712 __( 'Comments' )
713 );
714 }
715
716 $posts_columns['date'] = __( 'Date' );
717
718 if ( 'page' === $post_type ) {
719
720 /**
721 * Filters the columns displayed in the Pages list table.
722 *
723 * @since 2.5.0
724 *
725 * @param string[] $posts_columns An associative array of column headings.
726 */
727 $posts_columns = apply_filters( 'manage_pages_columns', $posts_columns );
728 } else {
729
730 /**
731 * Filters the columns displayed in the Posts list table.
732 *
733 * @since 1.5.0
734 *
735 * @param string[] $posts_columns An associative array of column headings.
736 * @param string $post_type The post type slug.
737 */
738 $posts_columns = apply_filters( 'manage_posts_columns', $posts_columns, $post_type );
739 }
740
741 /**
742 * Filters the columns displayed in the Posts list table for a specific post type.
743 *
744 * The dynamic portion of the hook name, `$post_type`, refers to the post type slug.
745 *
746 * Possible hook names include:
747 *
748 * - `manage_post_posts_columns`
749 * - `manage_page_posts_columns`
750 *
751 * @since 3.0.0
752 *
753 * @param string[] $posts_columns An associative array of column headings.
754 */
755 return apply_filters( "manage_{$post_type}_posts_columns", $posts_columns );
756 }
757
758 /**
759 * @return array
760 */
761 protected function get_sortable_columns() {
762
763 $post_type = $this->screen->post_type;
764
765 if ( 'page' === $post_type ) {
766 if ( isset( $_GET['orderby'] ) ) {
767 $title_orderby_text = __( 'Table ordered by Title.' );
768 } else {
769 $title_orderby_text = __( 'Table ordered by Hierarchical Menu Order and Title.' );
770 }
771
772 $sortables = array(
773 'title' => array( 'title', false, __( 'Title' ), $title_orderby_text, 'asc' ),
774 'parent' => array( 'parent', false ),
775 'comments' => array( 'comment_count', false, __( 'Comments' ), __( 'Table ordered by Comments.' ) ),
776 'date' => array( 'date', true, __( 'Date' ), __( 'Table ordered by Date.' ) ),
777 );
778 } else {
779 $sortables = array(
780 'title' => array( 'title', false, __( 'Title' ), __( 'Table ordered by Title.' ) ),
781 'parent' => array( 'parent', false ),
782 'comments' => array( 'comment_count', false, __( 'Comments' ), __( 'Table ordered by Comments.' ) ),
783 'date' => array( 'date', true, __( 'Date' ), __( 'Table ordered by Date.' ), 'desc' ),
784 );
785 }
786 // Custom Post Types: there's a filter for that, see get_column_info().
787
788 return $sortables;
789 }
790
791 /**
792 * Generates the list table rows.
793 *
794 * @since 3.1.0
795 *
796 * @global WP_Query $wp_query WordPress Query object.
797 * @global int $per_page
798 *
799 * @param array $posts
800 * @param int $level
801 */
802 public function display_rows( $posts = array(), $level = 0 ) {
803 global $wp_query, $per_page;
804
805 if ( empty( $posts ) ) {
806 $posts = $wp_query->posts;
807 }
808
809 add_filter( 'the_title', 'esc_html' );
810
811 if ( $this->hierarchical_display ) {
812 $this->_display_rows_hierarchical( $posts, $this->get_pagenum(), $per_page );
813 } else {
814 $this->_display_rows( $posts, $level );
815 }
816 }
817
818 /**
819 * @param array $posts
820 * @param int $level
821 */
822 private function _display_rows( $posts, $level = 0 ) {
823 $post_type = $this->screen->post_type;
824
825 // Create array of post IDs.
826 $post_ids = array();
827
828 foreach ( $posts as $a_post ) {
829 $post_ids[] = $a_post->ID;
830 }
831
832 if ( post_type_supports( $post_type, 'comments' ) ) {
833 $this->comment_pending_count = get_pending_comments_num( $post_ids );
834 }
835 update_post_author_caches( $posts );
836
837 foreach ( $posts as $post ) {
838 $this->single_row( $post, $level );
839 }
840 }
841
842 /**
843 * @global wpdb $wpdb WordPress database abstraction object.
844 * @global WP_Post $post Global post object.
845 * @param array $pages
846 * @param int $pagenum
847 * @param int $per_page
848 */
849 private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ) {
850 global $wpdb;
851
852 $level = 0;
853
854 if ( ! $pages ) {
855 $pages = get_pages( array( 'sort_column' => 'menu_order' ) );
856
857 if ( ! $pages ) {
858 return;
859 }
860 }
861
862 /*
863 * Arrange pages into two parts: top level pages and children_pages.
864 * children_pages is two dimensional array. Example:
865 * children_pages[10][] contains all sub-pages whose parent is 10.
866 * It only takes O( N ) to arrange this and it takes O( 1 ) for subsequent lookup operations
867 * If searching, ignore hierarchy and treat everything as top level
868 */
869 if ( empty( $_REQUEST['s'] ) ) {
870 $top_level_pages = array();
871 $children_pages = array();
872
873 foreach ( $pages as $page ) {
874 // Catch and repair bad pages.
875 if ( $page->post_parent === $page->ID ) {
876 $page->post_parent = 0;
877 $wpdb->update( $wpdb->posts, array( 'post_parent' => 0 ), array( 'ID' => $page->ID ) );
878 clean_post_cache( $page );
879 }
880
881 if ( $page->post_parent > 0 ) {
882 $children_pages[ $page->post_parent ][] = $page;
883 } else {
884 $top_level_pages[] = $page;
885 }
886 }
887
888 $pages = &$top_level_pages;
889 }
890
891 $count = 0;
892 $start = ( $pagenum - 1 ) * $per_page;
893 $end = $start + $per_page;
894 $to_display = array();
895
896 foreach ( $pages as $page ) {
897 if ( $count >= $end ) {
898 break;
899 }
900
901 if ( $count >= $start ) {
902 $to_display[ $page->ID ] = $level;
903 }
904
905 ++$count;
906
907 if ( isset( $children_pages ) ) {
908 $this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page, $to_display );
909 }
910 }
911
912 // If it is the last pagenum and there are orphaned pages, display them with paging as well.
913 if ( isset( $children_pages ) && $count < $end ) {
914 foreach ( $children_pages as $orphans ) {
915 foreach ( $orphans as $op ) {
916 if ( $count >= $end ) {
917 break;
918 }
919
920 if ( $count >= $start ) {
921 $to_display[ $op->ID ] = 0;
922 }
923
924 ++$count;
925 }
926 }
927 }
928
929 $ids = array_keys( $to_display );
930 _prime_post_caches( $ids );
931 $_posts = array_map( 'get_post', $ids );
932 update_post_author_caches( $_posts );
933
934 if ( ! isset( $GLOBALS['post'] ) ) {
935 $GLOBALS['post'] = reset( $ids );
936 }
937
938 foreach ( $to_display as $page_id => $level ) {
939 echo "\t";
940 $this->single_row( $page_id, $level );
941 }
942 }
943
944 /**
945 * Displays the nested hierarchy of sub-pages together with paging
946 * support, based on a top level page ID.
947 *
948 * @since 3.1.0 (Standalone function exists since 2.6.0)
949 * @since 4.2.0 Added the `$to_display` parameter.
950 *
951 * @param array $children_pages
952 * @param int $count
953 * @param int $parent_page
954 * @param int $level
955 * @param int $pagenum
956 * @param int $per_page
957 * @param array $to_display List of pages to be displayed. Passed by reference.
958 */
959 private function _page_rows( &$children_pages, &$count, $parent_page, $level, $pagenum, $per_page, &$to_display ) {
960 if ( ! isset( $children_pages[ $parent_page ] ) ) {
961 return;
962 }
963
964 $start = ( $pagenum - 1 ) * $per_page;
965 $end = $start + $per_page;
966
967 foreach ( $children_pages[ $parent_page ] as $page ) {
968 if ( $count >= $end ) {
969 break;
970 }
971
972 // If the page starts in a subtree, print the parents.
973 if ( $count === $start && $page->post_parent > 0 ) {
974 $my_parents = array();
975 $my_parent = $page->post_parent;
976
977 while ( $my_parent ) {
978 // Get the ID from the list or the attribute if my_parent is an object.
979 $parent_id = $my_parent;
980
981 if ( is_object( $my_parent ) ) {
982 $parent_id = $my_parent->ID;
983 }
984
985 $my_parent = get_post( $parent_id );
986 $my_parents[] = $my_parent;
987
988 if ( ! $my_parent->post_parent ) {
989 break;
990 }
991
992 $my_parent = $my_parent->post_parent;
993 }
994
995 $num_parents = count( $my_parents );
996
997 while ( $my_parent = array_pop( $my_parents ) ) {
998 $to_display[ $my_parent->ID ] = $level - $num_parents;
999 --$num_parents;
1000 }
1001 }
1002
1003 if ( $count >= $start ) {
1004 $to_display[ $page->ID ] = $level;
1005 }
1006
1007 ++$count;
1008
1009 $this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page, $to_display );
1010 }
1011
1012 unset( $children_pages[ $parent_page ] ); // Required in order to keep track of orphans.
1013 }
1014
1015 /**
1016 * Handles the checkbox column output.
1017 *
1018 * @since 4.3.0
1019 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
1020 *
1021 * @param WP_Post $item The current WP_Post object.
1022 */
1023 public function column_cb( $item ) {
1024 // Restores the more descriptive, specific name for use within this method.
1025 $post = $item;
1026
1027 $show = current_user_can( 'edit_post', $post->ID );
1028
1029 /**
1030 * Filters whether to show the bulk edit checkbox for a post in its list table.
1031 *
1032 * By default the checkbox is only shown if the current user can edit the post.
1033 *
1034 * @since 5.7.0
1035 *
1036 * @param bool $show Whether to show the checkbox.
1037 * @param WP_Post $post The current WP_Post object.
1038 */
1039 if ( apply_filters( 'wp_list_table_show_post_checkbox', $show, $post ) ) :
1040 ?>
1041 <input id="cb-select-<?php the_ID(); ?>" type="checkbox" name="post[]" value="<?php the_ID(); ?>" />
1042 <label for="cb-select-<?php the_ID(); ?>">
1043 <span class="screen-reader-text">
1044 <?php
1045 /* translators: %s: Post title. */
1046 printf( __( 'Select %s' ), _draft_or_post_title() );
1047 ?>
1048 </span>
1049 </label>
1050 <div class="locked-indicator">
1051 <span class="locked-indicator-icon" aria-hidden="true"></span>
1052 <span class="screen-reader-text">
1053 <?php
1054 printf(
1055 /* translators: Hidden accessibility text. %s: Post title. */
1056 __( '&#8220;%s&#8221; is locked' ),
1057 _draft_or_post_title()
1058 );
1059 ?>
1060 </span>
1061 </div>
1062 <?php
1063 endif;
1064 }
1065
1066 /**
1067 * @since 4.3.0
1068 *
1069 * @param WP_Post $post
1070 * @param string $classes
1071 * @param string $data
1072 * @param string $primary
1073 */
1074 protected function _column_title( $post, $classes, $data, $primary ) {
1075 echo '<td class="' . $classes . ' page-title" ', $data, '>';
1076 echo $this->column_title( $post );
1077 echo $this->handle_row_actions( $post, 'title', $primary );
1078 echo '</td>';
1079 }
1080
1081 /**
1082 * Handles the title column output.
1083 *
1084 * @since 4.3.0
1085 *
1086 * @global string $mode List table view mode.
1087 *
1088 * @param WP_Post $post The current WP_Post object.
1089 */
1090 public function column_title( $post ) {
1091 global $mode;
1092
1093 if ( $this->hierarchical_display ) {
1094 if ( 0 === $this->current_level && (int) $post->post_parent > 0 ) {
1095 // Sent level 0 by accident, by default, or because we don't know the actual level.
1096 $find_main_page = (int) $post->post_parent;
1097
1098 while ( $find_main_page > 0 ) {
1099 $parent = get_post( $find_main_page );
1100
1101 if ( is_null( $parent ) ) {
1102 break;
1103 }
1104
1105 ++$this->current_level;
1106 $find_main_page = (int) $parent->post_parent;
1107
1108 if ( ! isset( $parent_name ) ) {
1109 /** This filter is documented in wp-includes/post-template.php */
1110 $parent_name = apply_filters( 'the_title', $parent->post_title, $parent->ID );
1111 }
1112 }
1113 }
1114 }
1115
1116 $can_edit_post = current_user_can( 'edit_post', $post->ID );
1117
1118 if ( $can_edit_post && 'trash' !== $post->post_status ) {
1119 $lock_holder = wp_check_post_lock( $post->ID );
1120
1121 if ( $lock_holder ) {
1122 $lock_holder = get_userdata( $lock_holder );
1123 $locked_avatar = get_avatar( $lock_holder->ID, 18 );
1124 /* translators: %s: User's display name. */
1125 $locked_text = esc_html( sprintf( __( '%s is currently editing' ), $lock_holder->display_name ) );
1126 } else {
1127 $locked_avatar = '';
1128 $locked_text = '';
1129 }
1130
1131 echo '<div class="locked-info"><span class="locked-avatar">' . $locked_avatar . '</span> <span class="locked-text">' . $locked_text . "</span></div>\n";
1132 }
1133
1134 $pad = str_repeat( '&#8212; ', $this->current_level );
1135 echo '<strong>';
1136
1137 $title = _draft_or_post_title();
1138
1139 if ( $can_edit_post && 'trash' !== $post->post_status ) {
1140 printf(
1141 '<a class="row-title" href="%s" aria-label="%s">%s%s</a>',
1142 get_edit_post_link( $post->ID ),
1143 /* translators: %s: Post title. */
1144 esc_attr( sprintf( __( '&#8220;%s&#8221; (Edit)' ), $title ) ),
1145 $pad,
1146 $title
1147 );
1148 } else {
1149 printf(
1150 '<span>%s%s</span>',
1151 $pad,
1152 $title
1153 );
1154 }
1155 _post_states( $post );
1156
1157 if ( isset( $parent_name ) ) {
1158 $post_type_object = get_post_type_object( $post->post_type );
1159 echo ' | ' . $post_type_object->labels->parent_item_colon . ' ' . esc_html( $parent_name );
1160 }
1161
1162 echo "</strong>\n";
1163
1164 if ( 'excerpt' === $mode
1165 && ! is_post_type_hierarchical( $this->screen->post_type )
1166 && current_user_can( 'read_post', $post->ID )
1167 ) {
1168 if ( post_password_required( $post ) ) {
1169 echo '<span class="protected-post-excerpt">' . esc_html( get_the_excerpt() ) . '</span>';
1170 } else {
1171 echo esc_html( get_the_excerpt() );
1172 }
1173 }
1174
1175 /** This filter is documented in wp-admin/includes/class-wp-posts-list-table.php */
1176 $quick_edit_enabled = apply_filters( 'quick_edit_enabled_for_post_type', true, $post->post_type );
1177
1178 if ( $quick_edit_enabled ) {
1179 get_inline_data( $post );
1180 }
1181 }
1182
1183 /**
1184 * Handles the post date column output.
1185 *
1186 * @since 4.3.0
1187 *
1188 * @global string $mode List table view mode.
1189 *
1190 * @param WP_Post $post The current WP_Post object.
1191 */
1192 public function column_date( $post ) {
1193 global $mode;
1194
1195 if ( '0000-00-00 00:00:00' === $post->post_date ) {
1196 $t_time = __( 'Unpublished' );
1197 $time_diff = 0;
1198 } else {
1199 $t_time = sprintf(
1200 /* translators: 1: Post date, 2: Post time. */
1201 __( '%1$s at %2$s' ),
1202 /* translators: Post date format. See https://www.php.net/manual/datetime.format.php */
1203 get_the_time( __( 'Y/m/d' ), $post ),
1204 /* translators: Post time format. See https://www.php.net/manual/datetime.format.php */
1205 get_the_time( __( 'g:i a' ), $post )
1206 );
1207
1208 $time = get_post_timestamp( $post );
1209 $time_diff = time() - $time;
1210 }
1211
1212 if ( 'publish' === $post->post_status ) {
1213 $status = __( 'Published' );
1214 } elseif ( 'future' === $post->post_status ) {
1215 if ( $time_diff > 0 ) {
1216 $status = '<strong class="error-message">' . __( 'Missed schedule' ) . '</strong>';
1217 } else {
1218 $status = __( 'Scheduled' );
1219 }
1220 } else {
1221 $status = __( 'Last Modified' );
1222 }
1223
1224 /**
1225 * Filters the status text of the post.
1226 *
1227 * @since 4.8.0
1228 *
1229 * @param string $status The status text.
1230 * @param WP_Post $post Post object.
1231 * @param string $column_name The column name.
1232 * @param string $mode The list display mode ('excerpt' or 'list').
1233 */
1234 $status = apply_filters( 'post_date_column_status', $status, $post, 'date', $mode );
1235
1236 if ( $status ) {
1237 echo $status . '<br />';
1238 }
1239
1240 /**
1241 * Filters the published, scheduled, or unpublished time of the post.
1242 *
1243 * @since 2.5.1
1244 * @since 5.5.0 Removed the difference between 'excerpt' and 'list' modes.
1245 * The published time and date are both displayed now,
1246 * which is equivalent to the previous 'excerpt' mode.
1247 *
1248 * @param string $t_time The published time.
1249 * @param WP_Post $post Post object.
1250 * @param string $column_name The column name.
1251 * @param string $mode The list display mode ('excerpt' or 'list').
1252 */
1253 echo apply_filters( 'post_date_column_time', $t_time, $post, 'date', $mode );
1254 }
1255
1256 /**
1257 * Handles the comments column output.
1258 *
1259 * @since 4.3.0
1260 *
1261 * @param WP_Post $post The current WP_Post object.
1262 */
1263 public function column_comments( $post ) {
1264 ?>
1265 <div class="post-com-count-wrapper">
1266 <?php
1267 $pending_comments = isset( $this->comment_pending_count[ $post->ID ] ) ? $this->comment_pending_count[ $post->ID ] : 0;
1268
1269 $this->comments_bubble( $post->ID, $pending_comments );
1270 ?>
1271 </div>
1272 <?php
1273 }
1274
1275 /**
1276 * Handles the post author column output.
1277 *
1278 * @since 4.3.0
1279 * @since 6.8.0 Added fallback text when author's name is unknown.
1280 *
1281 * @param WP_Post $post The current WP_Post object.
1282 */
1283 public function column_author( $post ) {
1284 $author = get_the_author();
1285
1286 if ( ! empty( $author ) ) {
1287 $args = array(
1288 'post_type' => $post->post_type,
1289 'author' => get_the_author_meta( 'ID' ),
1290 );
1291 echo $this->get_edit_link( $args, esc_html( $author ) );
1292 } else {
1293 echo '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">' . __( '(no author)' ) . '</span>';
1294 }
1295 }
1296
1297 /**
1298 * Handles the default column output.
1299 *
1300 * @since 4.3.0
1301 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
1302 *
1303 * @param WP_Post $item The current WP_Post object.
1304 * @param string $column_name The current column name.
1305 */
1306 public function column_default( $item, $column_name ) {
1307 // Restores the more descriptive, specific name for use within this method.
1308 $post = $item;
1309
1310 if ( 'categories' === $column_name ) {
1311 $taxonomy = 'category';
1312 } elseif ( 'tags' === $column_name ) {
1313 $taxonomy = 'post_tag';
1314 } elseif ( str_starts_with( $column_name, 'taxonomy-' ) ) {
1315 $taxonomy = substr( $column_name, 9 );
1316 } else {
1317 $taxonomy = false;
1318 }
1319
1320 if ( $taxonomy ) {
1321 $taxonomy_object = get_taxonomy( $taxonomy );
1322 $terms = get_the_terms( $post->ID, $taxonomy );
1323
1324 if ( is_array( $terms ) ) {
1325 $term_links = array();
1326
1327 foreach ( $terms as $t ) {
1328 $posts_in_term_qv = array();
1329
1330 if ( 'post' !== $post->post_type ) {
1331 $posts_in_term_qv['post_type'] = $post->post_type;
1332 }
1333
1334 if ( $taxonomy_object->query_var ) {
1335 $posts_in_term_qv[ $taxonomy_object->query_var ] = $t->slug;
1336 } else {
1337 $posts_in_term_qv['taxonomy'] = $taxonomy;
1338 $posts_in_term_qv['term'] = $t->slug;
1339 }
1340
1341 $label = esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) );
1342
1343 $term_links[] = $this->get_edit_link( $posts_in_term_qv, $label );
1344 }
1345
1346 /**
1347 * Filters the links in `$taxonomy` column of edit.php.
1348 *
1349 * @since 5.2.0
1350 *
1351 * @param string[] $term_links Array of term editing links.
1352 * @param string $taxonomy Taxonomy name.
1353 * @param WP_Term[] $terms Array of term objects appearing in the post row.
1354 */
1355 $term_links = apply_filters( 'post_column_taxonomy_links', $term_links, $taxonomy, $terms );
1356
1357 echo implode( wp_get_list_item_separator(), $term_links );
1358 } else {
1359 echo '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">' . $taxonomy_object->labels->no_terms . '</span>';
1360 }
1361 return;
1362 }
1363
1364 if ( is_post_type_hierarchical( $post->post_type ) ) {
1365
1366 /**
1367 * Fires in each custom column on the Posts list table.
1368 *
1369 * This hook only fires if the current post type is hierarchical,
1370 * such as pages.
1371 *
1372 * @since 2.5.0
1373 *
1374 * @param string $column_name The name of the column to display.
1375 * @param int $post_id The current post ID.
1376 */
1377 do_action( 'manage_pages_custom_column', $column_name, $post->ID );
1378 } else {
1379
1380 /**
1381 * Fires in each custom column in the Posts list table.
1382 *
1383 * This hook only fires if the current post type is non-hierarchical,
1384 * such as posts.
1385 *
1386 * @since 1.5.0
1387 *
1388 * @param string $column_name The name of the column to display.
1389 * @param int $post_id The current post ID.
1390 */
1391 do_action( 'manage_posts_custom_column', $column_name, $post->ID );
1392 }
1393
1394 /**
1395 * Fires for each custom column of a specific post type in the Posts list table.
1396 *
1397 * The dynamic portion of the hook name, `$post->post_type`, refers to the post type.
1398 *
1399 * Possible hook names include:
1400 *
1401 * - `manage_post_posts_custom_column`
1402 * - `manage_page_posts_custom_column`
1403 *
1404 * @since 3.1.0
1405 *
1406 * @param string $column_name The name of the column to display.
1407 * @param int $post_id The current post ID.
1408 */
1409 do_action( "manage_{$post->post_type}_posts_custom_column", $column_name, $post->ID );
1410 }
1411
1412 /**
1413 * @global WP_Post $post Global post object.
1414 *
1415 * @param int|WP_Post $post
1416 * @param int $level
1417 */
1418 public function single_row( $post, $level = 0 ) {
1419 $global_post = get_post();
1420
1421 $post = get_post( $post );
1422 $this->current_level = $level;
1423
1424 $GLOBALS['post'] = $post;
1425 setup_postdata( $post );
1426
1427 $classes = 'iedit author-' . ( get_current_user_id() === (int) $post->post_author ? 'self' : 'other' );
1428
1429 $lock_holder = wp_check_post_lock( $post->ID );
1430
1431 if ( $lock_holder ) {
1432 $classes .= ' wp-locked';
1433 }
1434
1435 if ( $post->post_parent ) {
1436 $count = count( get_post_ancestors( $post->ID ) );
1437 $classes .= ' level-' . $count;
1438 } else {
1439 $classes .= ' level-0';
1440 }
1441 ?>
1442 <tr id="post-<?php echo $post->ID; ?>" class="<?php echo implode( ' ', get_post_class( $classes, $post->ID ) ); ?>">
1443 <?php $this->single_row_columns( $post ); ?>
1444 </tr>
1445 <?php
1446 $GLOBALS['post'] = $global_post;
1447 }
1448
1449 /**
1450 * Gets the name of the default primary column.
1451 *
1452 * @since 4.3.0
1453 *
1454 * @return string Name of the default primary column, in this case, 'title'.
1455 */
1456 protected function get_default_primary_column_name() {
1457 return 'title';
1458 }
1459
1460 /**
1461 * Generates and displays row action links.
1462 *
1463 * @since 4.3.0
1464 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
1465 *
1466 * @param WP_Post $item Post being acted upon.
1467 * @param string $column_name Current column name.
1468 * @param string $primary Primary column name.
1469 * @return string Row actions output for posts, or an empty string
1470 * if the current column is not the primary column.
1471 */
1472 protected function handle_row_actions( $item, $column_name, $primary ) {
1473 if ( $primary !== $column_name ) {
1474 return '';
1475 }
1476
1477 // Restores the more descriptive, specific name for use within this method.
1478 $post = $item;
1479
1480 $post_type_object = get_post_type_object( $post->post_type );
1481 $can_edit_post = current_user_can( 'edit_post', $post->ID );
1482 $actions = array();
1483 $title = _draft_or_post_title();
1484
1485 if ( $can_edit_post && 'trash' !== $post->post_status ) {
1486 $actions['edit'] = sprintf(
1487 '<a href="%s" aria-label="%s">%s</a>',
1488 get_edit_post_link( $post->ID ),
1489 /* translators: %s: Post title. */
1490 esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $title ) ),
1491 __( 'Edit' )
1492 );
1493
1494 /**
1495 * Filters whether Quick Edit should be enabled for the given post type.
1496 *
1497 * @since 6.4.0
1498 *
1499 * @param bool $enable Whether to enable the Quick Edit functionality. Default true.
1500 * @param string $post_type Post type name.
1501 */
1502 $quick_edit_enabled = apply_filters( 'quick_edit_enabled_for_post_type', true, $post->post_type );
1503
1504 if ( $quick_edit_enabled && 'wp_block' !== $post->post_type ) {
1505 $actions['inline hide-if-no-js'] = sprintf(
1506 '<button type="button" class="button-link editinline" aria-label="%s" aria-expanded="false">%s</button>',
1507 /* translators: %s: Post title. */
1508 esc_attr( sprintf( __( 'Quick edit &#8220;%s&#8221; inline' ), $title ) ),
1509 __( 'Quick&nbsp;Edit' )
1510 );
1511 }
1512 }
1513
1514 if ( current_user_can( 'delete_post', $post->ID ) ) {
1515 if ( 'trash' === $post->post_status ) {
1516 $actions['untrash'] = sprintf(
1517 '<a href="%s" aria-label="%s">%s</a>',
1518 wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ),
1519 /* translators: %s: Post title. */
1520 esc_attr( sprintf( __( 'Restore &#8220;%s&#8221; from the Trash' ), $title ) ),
1521 __( 'Restore' )
1522 );
1523 } elseif ( EMPTY_TRASH_DAYS ) {
1524 $actions['trash'] = sprintf(
1525 '<a href="%s" class="submitdelete" aria-label="%s">%s</a>',
1526 get_delete_post_link( $post->ID ),
1527 /* translators: %s: Post title. */
1528 esc_attr( sprintf( __( 'Move &#8220;%s&#8221; to the Trash' ), $title ) ),
1529 _x( 'Trash', 'verb' )
1530 );
1531 }
1532
1533 if ( 'trash' === $post->post_status || ! EMPTY_TRASH_DAYS ) {
1534 $actions['delete'] = sprintf(
1535 '<a href="%s" class="submitdelete" aria-label="%s">%s</a>',
1536 get_delete_post_link( $post->ID, '', true ),
1537 /* translators: %s: Post title. */
1538 esc_attr( sprintf( __( 'Delete &#8220;%s&#8221; permanently' ), $title ) ),
1539 __( 'Delete Permanently' )
1540 );
1541 }
1542 }
1543
1544 if ( is_post_type_viewable( $post_type_object ) ) {
1545 if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ), true ) ) {
1546 if ( $can_edit_post ) {
1547 $preview_link = get_preview_post_link( $post );
1548 $actions['view'] = sprintf(
1549 '<a href="%s" rel="bookmark" aria-label="%s">%s</a>',
1550 esc_url( $preview_link ),
1551 /* translators: %s: Post title. */
1552 esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;' ), $title ) ),
1553 __( 'Preview' )
1554 );
1555 }
1556 } elseif ( 'trash' !== $post->post_status ) {
1557 $actions['view'] = sprintf(
1558 '<a href="%s" rel="bookmark" aria-label="%s">%s</a>',
1559 get_permalink( $post->ID ),
1560 /* translators: %s: Post title. */
1561 esc_attr( sprintf( __( 'View &#8220;%s&#8221;' ), $title ) ),
1562 __( 'View' )
1563 );
1564 }
1565 }
1566
1567 if ( 'wp_block' === $post->post_type ) {
1568 $actions['export'] = sprintf(
1569 '<button type="button" class="wp-list-reusable-blocks__export button-link" data-id="%s" aria-label="%s">%s</button>',
1570 $post->ID,
1571 /* translators: %s: Post title. */
1572 esc_attr( sprintf( __( 'Export &#8220;%s&#8221; as JSON' ), $title ) ),
1573 __( 'Export as JSON' )
1574 );
1575 }
1576
1577 if ( is_post_type_hierarchical( $post->post_type ) ) {
1578
1579 /**
1580 * Filters the array of row action links on the Pages list table.
1581 *
1582 * The filter is evaluated only for hierarchical post types.
1583 *
1584 * @since 2.8.0
1585 *
1586 * @param string[] $actions An array of row action links. Defaults are
1587 * 'Edit', 'Quick Edit', 'Restore', 'Trash',
1588 * 'Delete Permanently', 'Preview', and 'View'.
1589 * @param WP_Post $post The post object.
1590 */
1591 $actions = apply_filters( 'page_row_actions', $actions, $post );
1592 } else {
1593
1594 /**
1595 * Filters the array of row action links on the Posts list table.
1596 *
1597 * The filter is evaluated only for non-hierarchical post types.
1598 *
1599 * @since 2.8.0
1600 *
1601 * @param string[] $actions An array of row action links. Defaults are
1602 * 'Edit', 'Quick Edit', 'Restore', 'Trash',
1603 * 'Delete Permanently', 'Preview', and 'View'.
1604 * @param WP_Post $post The post object.
1605 */
1606 $actions = apply_filters( 'post_row_actions', $actions, $post );
1607 }
1608
1609 return $this->row_actions( $actions );
1610 }
1611
1612 /**
1613 * Outputs the hidden row displayed when inline editing
1614 *
1615 * @since 3.1.0
1616 *
1617 * @global string $mode List table view mode.
1618 */
1619 public function inline_edit() {
1620 global $mode;
1621
1622 $screen = $this->screen;
1623
1624 $post = get_default_post_to_edit( $screen->post_type );
1625 $post_type_object = get_post_type_object( $screen->post_type );
1626
1627 $taxonomy_names = get_object_taxonomies( $screen->post_type );
1628 $hierarchical_taxonomies = array();
1629 $flat_taxonomies = array();
1630
1631 foreach ( $taxonomy_names as $taxonomy_name ) {
1632 $taxonomy = get_taxonomy( $taxonomy_name );
1633
1634 $show_in_quick_edit = $taxonomy->show_in_quick_edit;
1635
1636 /**
1637 * Filters whether the current taxonomy should be shown in the Quick Edit panel.
1638 *
1639 * @since 4.2.0
1640 *
1641 * @param bool $show_in_quick_edit Whether to show the current taxonomy in Quick Edit.
1642 * @param string $taxonomy_name Taxonomy name.
1643 * @param string $post_type Post type of current Quick Edit post.
1644 */
1645 if ( ! apply_filters( 'quick_edit_show_taxonomy', $show_in_quick_edit, $taxonomy_name, $screen->post_type ) ) {
1646 continue;
1647 }
1648
1649 if ( $taxonomy->hierarchical ) {
1650 $hierarchical_taxonomies[] = $taxonomy;
1651 } else {
1652 $flat_taxonomies[] = $taxonomy;
1653 }
1654 }
1655
1656 $m = ( isset( $mode ) && 'excerpt' === $mode ) ? 'excerpt' : 'list';
1657 $can_publish = current_user_can( $post_type_object->cap->publish_posts );
1658 $core_columns = array(
1659 'cb' => true,
1660 'date' => true,
1661 'title' => true,
1662 'categories' => true,
1663 'tags' => true,
1664 'comments' => true,
1665 'author' => true,
1666 );
1667 ?>
1668
1669 <form method="get">
1670 <table style="display: none"><tbody id="inlineedit">
1671 <?php
1672 $hclass = count( $hierarchical_taxonomies ) ? 'post' : 'page';
1673 $inline_edit_classes = "inline-edit-row inline-edit-row-$hclass";
1674 $bulk_edit_classes = "bulk-edit-row bulk-edit-row-$hclass bulk-edit-{$screen->post_type}";
1675 $quick_edit_classes = "quick-edit-row quick-edit-row-$hclass inline-edit-{$screen->post_type}";
1676
1677 $bulk = 0;
1678
1679 while ( $bulk < 2 ) :
1680 $classes = $inline_edit_classes . ' ';
1681 $classes .= $bulk ? $bulk_edit_classes : $quick_edit_classes;
1682 ?>
1683 <tr id="<?php echo $bulk ? 'bulk-edit' : 'inline-edit'; ?>" class="<?php echo $classes; ?>" style="display: none">
1684 <td colspan="<?php echo $this->get_column_count(); ?>" class="colspanchange">
1685 <div class="inline-edit-wrapper" role="region" aria-labelledby="<?php echo $bulk ? 'bulk' : 'quick'; ?>-edit-legend">
1686 <fieldset class="inline-edit-col-left">
1687 <legend class="inline-edit-legend" id="<?php echo $bulk ? 'bulk' : 'quick'; ?>-edit-legend"><?php echo $bulk ? __( 'Bulk Edit' ) : __( 'Quick Edit' ); ?></legend>
1688 <div class="inline-edit-col">
1689
1690 <?php if ( post_type_supports( $screen->post_type, 'title' ) ) : ?>
1691
1692 <?php if ( $bulk ) : ?>
1693
1694 <div id="bulk-title-div">
1695 <div id="bulk-titles"></div>
1696 </div>
1697
1698 <?php else : // $bulk ?>
1699
1700 <label>
1701 <span class="title"><?php _e( 'Title' ); ?></span>
1702 <span class="input-text-wrap"><input type="text" name="post_title" class="ptitle" value="" /></span>
1703 </label>
1704
1705 <?php if ( is_post_type_viewable( $screen->post_type ) ) : ?>
1706
1707 <label>
1708 <span class="title"><?php _e( 'Slug' ); ?></span>
1709 <span class="input-text-wrap"><input type="text" name="post_name" value="" autocomplete="off" spellcheck="false" /></span>
1710 </label>
1711
1712 <?php endif; // is_post_type_viewable() ?>
1713
1714 <?php endif; // $bulk ?>
1715
1716 <?php endif; // post_type_supports( ... 'title' ) ?>
1717
1718 <?php if ( ! $bulk ) : ?>
1719 <fieldset class="inline-edit-date">
1720 <legend><span class="title"><?php _e( 'Date' ); ?></span></legend>
1721 <?php touch_time( 1, 1, 0, 1 ); ?>
1722 </fieldset>
1723 <br class="clear" />
1724 <?php endif; // $bulk ?>
1725
1726 <?php
1727 if ( post_type_supports( $screen->post_type, 'author' ) ) {
1728 $authors_dropdown = '';
1729
1730 if ( current_user_can( $post_type_object->cap->edit_others_posts ) ) {
1731 $dropdown_name = 'post_author';
1732 $dropdown_class = 'authors';
1733 if ( wp_is_large_user_count() ) {
1734 $authors_dropdown = sprintf( '<select name="%s" class="%s hidden"></select>', esc_attr( $dropdown_name ), esc_attr( $dropdown_class ) );
1735 } else {
1736 $users_opt = array(
1737 'hide_if_only_one_author' => false,
1738 'capability' => array( $post_type_object->cap->edit_posts ),
1739 'name' => $dropdown_name,
1740 'class' => $dropdown_class,
1741 'multi' => 1,
1742 'echo' => 0,
1743 'show' => 'display_name_with_login',
1744 );
1745
1746 if ( $bulk ) {
1747 $users_opt['show_option_none'] = __( '&mdash; No Change &mdash;' );
1748 }
1749
1750 /**
1751 * Filters the arguments used to generate the Quick Edit authors drop-down.
1752 *
1753 * @since 5.6.0
1754 *
1755 * @see wp_dropdown_users()
1756 *
1757 * @param array $users_opt An array of arguments passed to wp_dropdown_users().
1758 * @param bool $bulk A flag to denote if it's a bulk action.
1759 */
1760 $users_opt = apply_filters( 'quick_edit_dropdown_authors_args', $users_opt, $bulk );
1761
1762 $authors = wp_dropdown_users( $users_opt );
1763
1764 if ( $authors ) {
1765 $authors_dropdown = '<label class="inline-edit-author">';
1766 $authors_dropdown .= '<span class="title">' . __( 'Author' ) . '</span>';
1767 $authors_dropdown .= $authors;
1768 $authors_dropdown .= '</label>';
1769 }
1770 }
1771 } // current_user_can( 'edit_others_posts' )
1772
1773 if ( ! $bulk ) {
1774 echo $authors_dropdown;
1775 }
1776 } // post_type_supports( ... 'author' )
1777 ?>
1778
1779 <?php if ( ! $bulk && $can_publish ) : ?>
1780
1781 <div class="inline-edit-group wp-clearfix">
1782 <label class="alignleft">
1783 <span class="title"><?php _e( 'Password' ); ?></span>
1784 <span class="input-text-wrap"><input type="text" name="post_password" class="inline-edit-password-input" value="" /></span>
1785 </label>
1786
1787 <span class="alignleft inline-edit-or">
1788 <?php
1789 /* translators: Between password field and private checkbox on post quick edit interface. */
1790 _e( '&ndash;OR&ndash;' );
1791 ?>
1792 </span>
1793 <label class="alignleft inline-edit-private">
1794 <input type="checkbox" name="keep_private" value="private" />
1795 <span class="checkbox-title"><?php _e( 'Private' ); ?></span>
1796 </label>
1797 </div>
1798
1799 <?php endif; ?>
1800
1801 </div>
1802 </fieldset>
1803
1804 <?php if ( count( $hierarchical_taxonomies ) && ! $bulk ) : ?>
1805
1806 <fieldset class="inline-edit-col-center inline-edit-categories">
1807 <div class="inline-edit-col">
1808
1809 <?php foreach ( $hierarchical_taxonomies as $taxonomy ) : ?>
1810
1811 <span class="title inline-edit-categories-label"><?php echo esc_html( $taxonomy->labels->name ); ?></span>
1812 <input type="hidden" name="<?php echo ( 'category' === $taxonomy->name ) ? 'post_category[]' : 'tax_input[' . esc_attr( $taxonomy->name ) . '][]'; ?>" value="0" />
1813 <ul class="cat-checklist <?php echo esc_attr( $taxonomy->name ); ?>-checklist">
1814 <?php wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy->name ) ); ?>
1815 </ul>
1816
1817 <?php endforeach; // $hierarchical_taxonomies as $taxonomy ?>
1818
1819 </div>
1820 </fieldset>
1821
1822 <?php endif; // count( $hierarchical_taxonomies ) && ! $bulk ?>
1823
1824 <fieldset class="inline-edit-col-right">
1825 <div class="inline-edit-col">
1826
1827 <?php
1828 if ( post_type_supports( $screen->post_type, 'author' ) && $bulk ) {
1829 echo $authors_dropdown;
1830 }
1831 ?>
1832
1833 <?php if ( post_type_supports( $screen->post_type, 'page-attributes' ) ) : ?>
1834
1835 <?php if ( $post_type_object->hierarchical ) : ?>
1836
1837 <label>
1838 <span class="title"><?php _e( 'Parent' ); ?></span>
1839 <?php
1840 $dropdown_args = array(
1841 'post_type' => $post_type_object->name,
1842 'selected' => $post->post_parent,
1843 'name' => 'post_parent',
1844 'show_option_none' => __( 'Main Page (no parent)' ),
1845 'option_none_value' => 0,
1846 'sort_column' => 'menu_order, post_title',
1847 );
1848
1849 if ( $bulk ) {
1850 $dropdown_args['show_option_no_change'] = __( '&mdash; No Change &mdash;' );
1851 $dropdown_args['id'] = 'bulk_edit_post_parent';
1852 }
1853
1854 /**
1855 * Filters the arguments used to generate the Quick Edit page-parent drop-down.
1856 *
1857 * @since 2.7.0
1858 * @since 5.6.0 The `$bulk` parameter was added.
1859 *
1860 * @see wp_dropdown_pages()
1861 *
1862 * @param array $dropdown_args An array of arguments passed to wp_dropdown_pages().
1863 * @param bool $bulk A flag to denote if it's a bulk action.
1864 */
1865 $dropdown_args = apply_filters( 'quick_edit_dropdown_pages_args', $dropdown_args, $bulk );
1866
1867 wp_dropdown_pages( $dropdown_args );
1868 ?>
1869 </label>
1870
1871 <?php endif; // hierarchical ?>
1872
1873 <?php if ( ! $bulk ) : ?>
1874
1875 <label>
1876 <span class="title"><?php _e( 'Order' ); ?></span>
1877 <span class="input-text-wrap"><input type="text" name="menu_order" class="inline-edit-menu-order-input" value="<?php echo $post->menu_order; ?>" /></span>
1878 </label>
1879
1880 <?php endif; // ! $bulk ?>
1881
1882 <?php endif; // post_type_supports( ... 'page-attributes' ) ?>
1883
1884 <?php if ( 0 < count( get_page_templates( null, $screen->post_type ) ) ) : ?>
1885
1886 <label>
1887 <span class="title"><?php _e( 'Template' ); ?></span>
1888 <select name="page_template">
1889 <?php if ( $bulk ) : ?>
1890 <option value="-1"><?php _e( '&mdash; No Change &mdash;' ); ?></option>
1891 <?php endif; // $bulk ?>
1892 <?php
1893 /** This filter is documented in wp-admin/includes/meta-boxes.php */
1894 $default_title = apply_filters( 'default_page_template_title', __( 'Default template' ), 'quick-edit' );
1895 ?>
1896 <option value="default"><?php echo esc_html( $default_title ); ?></option>
1897 <?php page_template_dropdown( '', $screen->post_type ); ?>
1898 </select>
1899 </label>
1900
1901 <?php endif; ?>
1902
1903 <?php if ( count( $flat_taxonomies ) && ! $bulk ) : ?>
1904
1905 <?php foreach ( $flat_taxonomies as $taxonomy ) : ?>
1906
1907 <?php if ( current_user_can( $taxonomy->cap->assign_terms ) ) : ?>
1908 <?php $taxonomy_name = esc_attr( $taxonomy->name ); ?>
1909 <div class="inline-edit-tags-wrap">
1910 <label class="inline-edit-tags">
1911 <span class="title"><?php echo esc_html( $taxonomy->labels->name ); ?></span>
1912 <textarea data-wp-taxonomy="<?php echo $taxonomy_name; ?>" cols="22" rows="1" name="tax_input[<?php echo esc_attr( $taxonomy->name ); ?>]" class="tax_input_<?php echo esc_attr( $taxonomy->name ); ?>" aria-describedby="inline-edit-<?php echo esc_attr( $taxonomy->name ); ?>-desc"></textarea>
1913 </label>
1914 <p class="howto" id="inline-edit-<?php echo esc_attr( $taxonomy->name ); ?>-desc"><?php echo esc_html( $taxonomy->labels->separate_items_with_commas ); ?></p>
1915 </div>
1916 <?php endif; // current_user_can( 'assign_terms' ) ?>
1917
1918 <?php endforeach; // $flat_taxonomies as $taxonomy ?>
1919
1920 <?php endif; // count( $flat_taxonomies ) && ! $bulk ?>
1921
1922 <?php if ( post_type_supports( $screen->post_type, 'comments' ) || post_type_supports( $screen->post_type, 'trackbacks' ) ) : ?>
1923
1924 <?php if ( $bulk ) : ?>
1925
1926 <div class="inline-edit-group wp-clearfix">
1927
1928 <?php if ( post_type_supports( $screen->post_type, 'comments' ) ) : ?>
1929
1930 <label class="alignleft">
1931 <span class="title"><?php _e( 'Comments' ); ?></span>
1932 <select name="comment_status">
1933 <option value=""><?php _e( '&mdash; No Change &mdash;' ); ?></option>
1934 <option value="open"><?php _e( 'Allow' ); ?></option>
1935 <option value="closed"><?php _e( 'Do not allow' ); ?></option>
1936 </select>
1937 </label>
1938
1939 <?php endif; ?>
1940
1941 <?php if ( post_type_supports( $screen->post_type, 'trackbacks' ) ) : ?>
1942
1943 <label class="alignright">
1944 <span class="title"><?php _e( 'Pings' ); ?></span>
1945 <select name="ping_status">
1946 <option value=""><?php _e( '&mdash; No Change &mdash;' ); ?></option>
1947 <option value="open"><?php _e( 'Allow' ); ?></option>
1948 <option value="closed"><?php _e( 'Do not allow' ); ?></option>
1949 </select>
1950 </label>
1951
1952 <?php endif; ?>
1953
1954 </div>
1955
1956 <?php else : // $bulk ?>
1957
1958 <div class="inline-edit-group wp-clearfix">
1959
1960 <?php if ( post_type_supports( $screen->post_type, 'comments' ) ) : ?>
1961
1962 <label class="alignleft">
1963 <input type="checkbox" name="comment_status" value="open" />
1964 <span class="checkbox-title"><?php _e( 'Allow Comments' ); ?></span>
1965 </label>
1966
1967 <?php endif; ?>
1968
1969 <?php if ( post_type_supports( $screen->post_type, 'trackbacks' ) ) : ?>
1970
1971 <label class="alignleft">
1972 <input type="checkbox" name="ping_status" value="open" />
1973 <span class="checkbox-title"><?php _e( 'Allow Pings' ); ?></span>
1974 </label>
1975
1976 <?php endif; ?>
1977
1978 </div>
1979
1980 <?php endif; // $bulk ?>
1981
1982 <?php endif; // post_type_supports( ... comments or pings ) ?>
1983
1984 <div class="inline-edit-group wp-clearfix">
1985
1986 <label class="inline-edit-status alignleft">
1987 <span class="title"><?php _e( 'Status' ); ?></span>
1988 <select name="_status">
1989 <?php
1990 $inline_edit_statuses = array();
1991 if ( $bulk ) {
1992 $inline_edit_statuses['-1'] = __( '&mdash; No Change &mdash;' );
1993 }
1994 // Contributors only get "Unpublished" and "Pending Review".
1995 if ( $can_publish ) {
1996 $inline_edit_statuses['publish'] = __( 'Published' );
1997 $inline_edit_statuses['future'] = __( 'Scheduled' );
1998 // There is already a checkbox for Private in Single Post Quick Edit. See #63612.
1999 if ( $bulk ) {
2000 $inline_edit_statuses['private'] = __( 'Private' );
2001 }
2002 }
2003
2004 $inline_edit_statuses['pending'] = __( 'Pending Review' );
2005 $inline_edit_statuses['draft'] = __( 'Draft' );
2006
2007 /**
2008 * Filters the statuses available in the Quick Edit and Bulk Edit UI.
2009 *
2010 * @since 6.9.0
2011 *
2012 * @param array<string,string> $inline_edit_statuses An array of statuses available in the Quick Edit UI.
2013 * @param string $post_type The post type slug.
2014 * @param bool $bulk A flag to denote if it's a bulk action.
2015 * @param bool $can_publish A flag to denote if the user can publish posts.
2016 */
2017 $inline_edit_statuses = apply_filters( 'quick_edit_statuses', $inline_edit_statuses, $screen->post_type, $bulk, $can_publish );
2018
2019 foreach ( $inline_edit_statuses as $inline_status_value => $inline_status_text ) :
2020 ?>
2021 <option value="<?php echo esc_attr( $inline_status_value ); ?>"><?php echo esc_attr( $inline_status_text ); ?></option>
2022 <?php
2023 endforeach;
2024 ?>
2025 </select>
2026 </label>
2027
2028 <?php if ( 'post' === $screen->post_type && $can_publish && current_user_can( $post_type_object->cap->edit_others_posts ) ) : ?>
2029
2030 <?php if ( $bulk ) : ?>
2031
2032 <label class="alignright">
2033 <span class="title"><?php _e( 'Sticky' ); ?></span>
2034 <select name="sticky">
2035 <option value="-1"><?php _e( '&mdash; No Change &mdash;' ); ?></option>
2036 <option value="sticky"><?php _e( 'Sticky' ); ?></option>
2037 <option value="unsticky"><?php _e( 'Not Sticky' ); ?></option>
2038 </select>
2039 </label>
2040
2041 <?php else : // $bulk ?>
2042
2043 <label class="alignleft">
2044 <input type="checkbox" name="sticky" value="sticky" />
2045 <span class="checkbox-title"><?php _e( 'Make this post sticky' ); ?></span>
2046 </label>
2047
2048 <?php endif; // $bulk ?>
2049
2050 <?php endif; // 'post' && $can_publish && current_user_can( 'edit_others_posts' ) ?>
2051
2052 </div>
2053
2054 <?php if ( $bulk && current_theme_supports( 'post-formats' ) && post_type_supports( $screen->post_type, 'post-formats' ) ) : ?>
2055 <?php $post_formats = get_theme_support( 'post-formats' ); ?>
2056
2057 <label class="alignleft">
2058 <span class="title"><?php _ex( 'Format', 'post format' ); ?></span>
2059 <select name="post_format">
2060 <option value="-1"><?php _e( '&mdash; No Change &mdash;' ); ?></option>
2061 <option value="0"><?php echo get_post_format_string( 'standard' ); ?></option>
2062 <?php if ( is_array( $post_formats[0] ) ) : ?>
2063 <?php foreach ( $post_formats[0] as $format ) : ?>
2064 <option value="<?php echo esc_attr( $format ); ?>"><?php echo esc_html( get_post_format_string( $format ) ); ?></option>
2065 <?php endforeach; ?>
2066 <?php endif; ?>
2067 </select>
2068 </label>
2069
2070 <?php endif; ?>
2071
2072 </div>
2073 </fieldset>
2074
2075 <?php
2076 list( $columns ) = $this->get_column_info();
2077
2078 foreach ( $columns as $column_name => $column_display_name ) {
2079 if ( isset( $core_columns[ $column_name ] ) ) {
2080 continue;
2081 }
2082
2083 if ( $bulk ) {
2084
2085 /**
2086 * Fires once for each column in Bulk Edit mode.
2087 *
2088 * @since 2.7.0
2089 *
2090 * @param string $column_name Name of the column to edit.
2091 * @param string $post_type The post type slug.
2092 */
2093 do_action( 'bulk_edit_custom_box', $column_name, $screen->post_type );
2094 } else {
2095
2096 /**
2097 * Fires once for each column in Quick Edit mode.
2098 *
2099 * @since 2.7.0
2100 *
2101 * @param string $column_name Name of the column to edit.
2102 * @param string $post_type The post type slug, or current screen name if this is a taxonomy list table.
2103 * @param string $taxonomy The taxonomy name, if any.
2104 */
2105 do_action( 'quick_edit_custom_box', $column_name, $screen->post_type, '' );
2106 }
2107 }
2108 ?>
2109
2110 <div class="submit inline-edit-save">
2111 <?php if ( ! $bulk ) : ?>
2112 <?php wp_nonce_field( 'inlineeditnonce', '_inline_edit', false ); ?>
2113 <button type="button" class="button button-primary save"><?php _e( 'Update' ); ?></button>
2114 <?php else : ?>
2115 <?php submit_button( __( 'Update' ), 'primary', 'bulk_edit', false ); ?>
2116 <?php endif; ?>
2117
2118 <button type="button" class="button cancel"><?php _e( 'Cancel' ); ?></button>
2119
2120 <?php if ( ! $bulk ) : ?>
2121 <span class="spinner"></span>
2122 <?php endif; ?>
2123
2124 <input type="hidden" name="post_view" value="<?php echo esc_attr( $m ); ?>" />
2125 <input type="hidden" name="screen" value="<?php echo esc_attr( $screen->id ); ?>" />
2126 <?php if ( ! $bulk && ! post_type_supports( $screen->post_type, 'author' ) ) : ?>
2127 <input type="hidden" name="post_author" value="<?php echo esc_attr( $post->post_author ); ?>" />
2128 <?php endif; ?>
2129
2130 <?php
2131 wp_admin_notice(
2132 '<p class="error"></p>',
2133 array(
2134 'type' => 'error',
2135 'additional_classes' => array( 'notice-alt', 'inline', 'hidden' ),
2136 'paragraph_wrap' => false,
2137 )
2138 );
2139 ?>
2140 </div>
2141 </div> <!-- end of .inline-edit-wrapper -->
2142
2143 </td></tr>
2144
2145 <?php
2146 ++$bulk;
2147 endwhile;
2148 ?>
2149 </tbody></table>
2150 </form>
2151 <?php
2152 }
2153}
2154
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1