394 $views = $this->get_views(); |
394 $views = $this->get_views(); |
395 /** |
395 /** |
396 * Filters the list of available list table views. |
396 * Filters the list of available list table views. |
397 * |
397 * |
398 * The dynamic portion of the hook name, `$this->screen->id`, refers |
398 * The dynamic portion of the hook name, `$this->screen->id`, refers |
399 * to the ID of the current screen, usually a string. |
399 * to the ID of the current screen. |
400 * |
400 * |
401 * @since 3.1.0 |
401 * @since 3.1.0 |
402 * |
402 * |
403 * @param string[] $views An array of available list table views. |
403 * @param string[] $views An array of available list table views. |
404 */ |
404 */ |
417 echo implode( " |</li>\n", $views ) . "</li>\n"; |
417 echo implode( " |</li>\n", $views ) . "</li>\n"; |
418 echo '</ul>'; |
418 echo '</ul>'; |
419 } |
419 } |
420 |
420 |
421 /** |
421 /** |
422 * Gets the list of bulk actions available on this table. |
422 * Retrieves the list of bulk actions available for this table. |
423 * |
423 * |
424 * The format is an associative array: |
424 * The format is an associative array where each element represents either a top level option value and label, or |
425 * - `'option_name' => 'option_title'` |
425 * an array representing an optgroup and its options. |
426 * |
426 * |
427 * @since 3.1.0 |
427 * For a standard option, the array element key is the field value and the array element value is the field label. |
|
428 * |
|
429 * For an optgroup, the array element key is the label and the array element value is an associative array of |
|
430 * options as above. |
|
431 * |
|
432 * Example: |
|
433 * |
|
434 * [ |
|
435 * 'edit' => 'Edit', |
|
436 * 'delete' => 'Delete', |
|
437 * 'Change State' => [ |
|
438 * 'feature' => 'Featured', |
|
439 * 'sale' => 'On Sale', |
|
440 * ] |
|
441 * ] |
|
442 * |
|
443 * @since 3.1.0 |
|
444 * @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup. |
428 * |
445 * |
429 * @return array |
446 * @return array |
430 */ |
447 */ |
431 protected function get_bulk_actions() { |
448 protected function get_bulk_actions() { |
432 return array(); |
449 return array(); |
443 protected function bulk_actions( $which = '' ) { |
460 protected function bulk_actions( $which = '' ) { |
444 if ( is_null( $this->_actions ) ) { |
461 if ( is_null( $this->_actions ) ) { |
445 $this->_actions = $this->get_bulk_actions(); |
462 $this->_actions = $this->get_bulk_actions(); |
446 |
463 |
447 /** |
464 /** |
448 * Filters the list table bulk actions drop-down. |
465 * Filters the items in the bulk actions menu of the list table. |
449 * |
466 * |
450 * The dynamic portion of the hook name, `$this->screen->id`, refers |
467 * The dynamic portion of the hook name, `$this->screen->id`, refers |
451 * to the ID of the current screen, usually a string. |
468 * to the ID of the current screen. |
452 * |
469 * |
453 * @since 3.1.0 |
470 * @since 3.1.0 |
|
471 * @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup. |
454 * |
472 * |
455 * @param string[] $actions An array of the available bulk actions. |
473 * @param array $actions An array of the available bulk actions. |
456 */ |
474 */ |
457 $this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
475 $this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
458 |
476 |
459 $two = ''; |
477 $two = ''; |
460 } else { |
478 } else { |
467 |
485 |
468 echo '<label for="bulk-action-selector-' . esc_attr( $which ) . '" class="screen-reader-text">' . __( 'Select bulk action' ) . '</label>'; |
486 echo '<label for="bulk-action-selector-' . esc_attr( $which ) . '" class="screen-reader-text">' . __( 'Select bulk action' ) . '</label>'; |
469 echo '<select name="action' . $two . '" id="bulk-action-selector-' . esc_attr( $which ) . "\">\n"; |
487 echo '<select name="action' . $two . '" id="bulk-action-selector-' . esc_attr( $which ) . "\">\n"; |
470 echo '<option value="-1">' . __( 'Bulk actions' ) . "</option>\n"; |
488 echo '<option value="-1">' . __( 'Bulk actions' ) . "</option>\n"; |
471 |
489 |
472 foreach ( $this->_actions as $name => $title ) { |
490 foreach ( $this->_actions as $key => $value ) { |
473 $class = 'edit' === $name ? ' class="hide-if-no-js"' : ''; |
491 if ( is_array( $value ) ) { |
474 |
492 echo "\t" . '<optgroup label="' . esc_attr( $key ) . '">' . "\n"; |
475 echo "\t" . '<option value="' . $name . '"' . $class . '>' . $title . "</option>\n"; |
493 |
|
494 foreach ( $value as $name => $title ) { |
|
495 $class = ( 'edit' === $name ) ? ' class="hide-if-no-js"' : ''; |
|
496 |
|
497 echo "\t\t" . '<option value="' . esc_attr( $name ) . '"' . $class . '>' . $title . "</option>\n"; |
|
498 } |
|
499 echo "\t" . "</optgroup>\n"; |
|
500 } else { |
|
501 $class = ( 'edit' === $key ) ? ' class="hide-if-no-js"' : ''; |
|
502 |
|
503 echo "\t" . '<option value="' . esc_attr( $key ) . '"' . $class . '>' . $value . "</option>\n"; |
|
504 } |
476 } |
505 } |
477 |
506 |
478 echo "</select>\n"; |
507 echo "</select>\n"; |
479 |
508 |
480 submit_button( __( 'Apply' ), 'action', '', false, array( 'id' => "doaction$two" ) ); |
509 submit_button( __( 'Apply' ), 'action', '', false, array( 'id' => "doaction$two" ) ); |
568 */ |
593 */ |
569 if ( apply_filters( 'disable_months_dropdown', false, $post_type ) ) { |
594 if ( apply_filters( 'disable_months_dropdown', false, $post_type ) ) { |
570 return; |
595 return; |
571 } |
596 } |
572 |
597 |
573 $extra_checks = "AND post_status != 'auto-draft'"; |
598 /** |
574 if ( ! isset( $_GET['post_status'] ) || 'trash' !== $_GET['post_status'] ) { |
599 * Filters to short-circuit performing the months dropdown query. |
575 $extra_checks .= " AND post_status != 'trash'"; |
600 * |
576 } elseif ( isset( $_GET['post_status'] ) ) { |
601 * @since 5.7.0 |
577 $extra_checks = $wpdb->prepare( ' AND post_status = %s', $_GET['post_status'] ); |
602 * |
578 } |
603 * @param object[]|false $months 'Months' drop-down results. Default false. |
579 |
604 * @param string $post_type The post type. |
580 $months = $wpdb->get_results( |
605 */ |
581 $wpdb->prepare( |
606 $months = apply_filters( 'pre_months_dropdown_query', false, $post_type ); |
582 " |
607 |
583 SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month |
608 if ( ! is_array( $months ) ) { |
584 FROM $wpdb->posts |
609 $extra_checks = "AND post_status != 'auto-draft'"; |
585 WHERE post_type = %s |
610 if ( ! isset( $_GET['post_status'] ) || 'trash' !== $_GET['post_status'] ) { |
586 $extra_checks |
611 $extra_checks .= " AND post_status != 'trash'"; |
587 ORDER BY post_date DESC |
612 } elseif ( isset( $_GET['post_status'] ) ) { |
588 ", |
613 $extra_checks = $wpdb->prepare( ' AND post_status = %s', $_GET['post_status'] ); |
589 $post_type |
614 } |
590 ) |
615 |
591 ); |
616 $months = $wpdb->get_results( |
|
617 $wpdb->prepare( |
|
618 " |
|
619 SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month |
|
620 FROM $wpdb->posts |
|
621 WHERE post_type = %s |
|
622 $extra_checks |
|
623 ORDER BY post_date DESC |
|
624 ", |
|
625 $post_type |
|
626 ) |
|
627 ); |
|
628 } |
592 |
629 |
593 /** |
630 /** |
594 * Filters the 'Months' drop-down results. |
631 * Filters the 'Months' drop-down results. |
595 * |
632 * |
596 * @since 3.7.0 |
633 * @since 3.7.0 |
606 return; |
643 return; |
607 } |
644 } |
608 |
645 |
609 $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0; |
646 $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0; |
610 ?> |
647 ?> |
611 <label for="filter-by-date" class="screen-reader-text"><?php _e( 'Filter by date' ); ?></label> |
648 <label for="filter-by-date" class="screen-reader-text"><?php echo get_post_type_object( $post_type )->labels->filter_by_date; ?></label> |
612 <select name="m" id="filter-by-date"> |
649 <select name="m" id="filter-by-date"> |
613 <option<?php selected( $m, 0 ); ?> value="0"><?php _e( 'All dates' ); ?></option> |
650 <option<?php selected( $m, 0 ); ?> value="0"><?php _e( 'All dates' ); ?></option> |
614 <?php |
651 <?php |
615 foreach ( $months as $arc_row ) { |
652 foreach ( $months as $arc_row ) { |
616 if ( 0 == $arc_row->year ) { |
653 if ( 0 == $arc_row->year ) { |
945 |
982 |
946 $pagination_links_class = 'pagination-links'; |
983 $pagination_links_class = 'pagination-links'; |
947 if ( ! empty( $infinite_scroll ) ) { |
984 if ( ! empty( $infinite_scroll ) ) { |
948 $pagination_links_class .= ' hide-if-js'; |
985 $pagination_links_class .= ' hide-if-js'; |
949 } |
986 } |
950 $output .= "\n<span class='$pagination_links_class'>" . join( "\n", $page_links ) . '</span>'; |
987 $output .= "\n<span class='$pagination_links_class'>" . implode( "\n", $page_links ) . '</span>'; |
951 |
988 |
952 if ( $total_pages ) { |
989 if ( $total_pages ) { |
953 $page_class = $total_pages < 2 ? ' one-page' : ''; |
990 $page_class = $total_pages < 2 ? ' one-page' : ''; |
954 } else { |
991 } else { |
955 $page_class = ' no-pages'; |
992 $page_class = ' no-pages'; |
1042 $default = $this->get_default_primary_column_name(); |
1079 $default = $this->get_default_primary_column_name(); |
1043 |
1080 |
1044 // If the primary column doesn't exist, |
1081 // If the primary column doesn't exist, |
1045 // fall back to the first non-checkbox column. |
1082 // fall back to the first non-checkbox column. |
1046 if ( ! isset( $columns[ $default ] ) ) { |
1083 if ( ! isset( $columns[ $default ] ) ) { |
1047 $default = WP_List_Table::get_default_primary_column_name(); |
1084 $default = self::get_default_primary_column_name(); |
1048 } |
1085 } |
1049 |
1086 |
1050 /** |
1087 /** |
1051 * Filters the name of the primary column for the current list table. |
1088 * Filters the name of the primary column for the current list table. |
1052 * |
1089 * |
1063 |
1100 |
1064 return $column; |
1101 return $column; |
1065 } |
1102 } |
1066 |
1103 |
1067 /** |
1104 /** |
1068 * Gets a list of all, hidden and sortable columns, with filter applied. |
1105 * Gets a list of all, hidden, and sortable columns, with filter applied. |
1069 * |
1106 * |
1070 * @since 3.1.0 |
1107 * @since 3.1.0 |
1071 * |
1108 * |
1072 * @return array |
1109 * @return array |
1073 */ |
1110 */ |
1074 protected function get_column_info() { |
1111 protected function get_column_info() { |
1075 // $_column_headers is already set / cached. |
1112 // $_column_headers is already set / cached. |
1076 if ( isset( $this->_column_headers ) && is_array( $this->_column_headers ) ) { |
1113 if ( isset( $this->_column_headers ) && is_array( $this->_column_headers ) ) { |
1077 // Back-compat for list tables that have been manually setting $_column_headers for horse reasons. |
1114 /* |
1078 // In 4.3, we added a fourth argument for primary column. |
1115 * Backward compatibility for `$_column_headers` format prior to WordPress 4.3. |
|
1116 * |
|
1117 * In WordPress 4.3 the primary column name was added as a fourth item in the |
|
1118 * column headers property. This ensures the primary column name is included |
|
1119 * in plugins setting the property directly in the three item format. |
|
1120 */ |
1079 $column_headers = array( array(), array(), array(), $this->get_primary_column_name() ); |
1121 $column_headers = array( array(), array(), array(), $this->get_primary_column_name() ); |
1080 foreach ( $this->_column_headers as $key => $value ) { |
1122 foreach ( $this->_column_headers as $key => $value ) { |
1081 $column_headers[ $key ] = $value; |
1123 $column_headers[ $key ] = $value; |
1082 } |
1124 } |
1083 |
1125 |
1090 $sortable_columns = $this->get_sortable_columns(); |
1132 $sortable_columns = $this->get_sortable_columns(); |
1091 /** |
1133 /** |
1092 * Filters the list table sortable columns for a specific screen. |
1134 * Filters the list table sortable columns for a specific screen. |
1093 * |
1135 * |
1094 * The dynamic portion of the hook name, `$this->screen->id`, refers |
1136 * The dynamic portion of the hook name, `$this->screen->id`, refers |
1095 * to the ID of the current screen, usually a string. |
1137 * to the ID of the current screen. |
1096 * |
1138 * |
1097 * @since 3.1.0 |
1139 * @since 3.1.0 |
1098 * |
1140 * |
1099 * @param array $sortable_columns An array of sortable columns. |
1141 * @param array $sortable_columns An array of sortable columns. |
1100 */ |
1142 */ |
1211 $tag = ( 'cb' === $column_key ) ? 'td' : 'th'; |
1253 $tag = ( 'cb' === $column_key ) ? 'td' : 'th'; |
1212 $scope = ( 'th' === $tag ) ? 'scope="col"' : ''; |
1254 $scope = ( 'th' === $tag ) ? 'scope="col"' : ''; |
1213 $id = $with_id ? "id='$column_key'" : ''; |
1255 $id = $with_id ? "id='$column_key'" : ''; |
1214 |
1256 |
1215 if ( ! empty( $class ) ) { |
1257 if ( ! empty( $class ) ) { |
1216 $class = "class='" . join( ' ', $class ) . "'"; |
1258 $class = "class='" . implode( ' ', $class ) . "'"; |
1217 } |
1259 } |
1218 |
1260 |
1219 echo "<$tag $scope $id $class>$column_display_name</$tag>"; |
1261 echo "<$tag $scope $id $class>$column_display_name</$tag>"; |
1220 } |
1262 } |
1221 } |
1263 } |
1341 /** |
1383 /** |
1342 * Generates content for a single row of the table. |
1384 * Generates content for a single row of the table. |
1343 * |
1385 * |
1344 * @since 3.1.0 |
1386 * @since 3.1.0 |
1345 * |
1387 * |
1346 * @param object $item The current item |
1388 * @param object|array $item The current item |
1347 */ |
1389 */ |
1348 public function single_row( $item ) { |
1390 public function single_row( $item ) { |
1349 echo '<tr>'; |
1391 echo '<tr>'; |
1350 $this->single_row_columns( $item ); |
1392 $this->single_row_columns( $item ); |
1351 echo '</tr>'; |
1393 echo '</tr>'; |
1352 } |
1394 } |
1353 |
1395 |
1354 /** |
1396 /** |
1355 * @param object $item |
1397 * @param object|array $item |
1356 * @param string $column_name |
1398 * @param string $column_name |
1357 */ |
1399 */ |
1358 protected function column_default( $item, $column_name ) {} |
1400 protected function column_default( $item, $column_name ) {} |
1359 |
1401 |
1360 /** |
1402 /** |
1361 * @param object $item |
1403 * @param object|array $item |
1362 */ |
1404 */ |
1363 protected function column_cb( $item ) {} |
1405 protected function column_cb( $item ) {} |
1364 |
1406 |
1365 /** |
1407 /** |
1366 * Generates the columns for a single row of the table. |
1408 * Generates the columns for a single row of the table. |
1367 * |
1409 * |
1368 * @since 3.1.0 |
1410 * @since 3.1.0 |
1369 * |
1411 * |
1370 * @param object $item The current item. |
1412 * @param object|array $item The current item. |
1371 */ |
1413 */ |
1372 protected function single_row_columns( $item ) { |
1414 protected function single_row_columns( $item ) { |
1373 list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); |
1415 list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); |
1374 |
1416 |
1375 foreach ( $columns as $column_name => $column_display_name ) { |
1417 foreach ( $columns as $column_name => $column_display_name ) { |
1381 if ( in_array( $column_name, $hidden, true ) ) { |
1423 if ( in_array( $column_name, $hidden, true ) ) { |
1382 $classes .= ' hidden'; |
1424 $classes .= ' hidden'; |
1383 } |
1425 } |
1384 |
1426 |
1385 // Comments column uses HTML in the display name with screen reader text. |
1427 // Comments column uses HTML in the display name with screen reader text. |
1386 // Instead of using esc_attr(), we strip tags to get closer to a user-friendly string. |
1428 // Strip tags to get closer to a user-friendly string. |
1387 $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"'; |
1429 $data = 'data-colname="' . esc_attr( wp_strip_all_tags( $column_display_name ) ) . '"'; |
1388 |
1430 |
1389 $attributes = "class='$classes' $data"; |
1431 $attributes = "class='$classes' $data"; |
1390 |
1432 |
1391 if ( 'cb' === $column_name ) { |
1433 if ( 'cb' === $column_name ) { |
1392 echo '<th scope="row" class="check-column">'; |
1434 echo '<th scope="row" class="check-column">'; |
1417 /** |
1459 /** |
1418 * Generates and display row actions links for the list table. |
1460 * Generates and display row actions links for the list table. |
1419 * |
1461 * |
1420 * @since 4.3.0 |
1462 * @since 4.3.0 |
1421 * |
1463 * |
1422 * @param object $item The item being acted upon. |
1464 * @param object|array $item The item being acted upon. |
1423 * @param string $column_name Current column name. |
1465 * @param string $column_name Current column name. |
1424 * @param string $primary Primary column name. |
1466 * @param string $primary Primary column name. |
1425 * @return string The row actions HTML, or an empty string |
1467 * @return string The row actions HTML, or an empty string |
1426 * if the current column is not the primary column. |
1468 * if the current column is not the primary column. |
1427 */ |
1469 */ |
1428 protected function handle_row_actions( $item, $column_name, $primary ) { |
1470 protected function handle_row_actions( $item, $column_name, $primary ) { |
1429 return $column_name === $primary ? '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>' : ''; |
1471 return $column_name === $primary ? '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>' : ''; |