From be9b533e13290316be1f9c9552460d20c23e6911 Mon Sep 17 00:00:00 2001 From: davidbaumwald Date: Mon, 19 Sep 2022 21:08:10 +0000 Subject: [PATCH] Administration: Add new `get_views_links` method to `WP_List_Table`. Many `WP_List_Table` child classes in core use mostly the same code to create their "view" links markup. To DRY-up the code, a new `WP_List_Table->get_view_links` method is being introduced to consolidate the HTML link generation when provided an array of links. This change also implements this new method in the relevant `WP_List_Table_xxx` child classes `get_views` methods. Finally, unit tests are being added to validate view links markup and test for some "unhappy paths". Props afercia, costdev, garrett-eclipse, Dharm1025, juhise, peterwilsoncc. Fixes #42066. Built from https://develop.svn.wordpress.org/trunk@54215 git-svn-id: http://core.svn.wordpress.org/trunk@53774 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- .../includes/class-wp-comments-list-table.php | 28 ++++---- wp-admin/includes/class-wp-list-table.php | 72 +++++++++++++++++++ .../includes/class-wp-ms-sites-list-table.php | 14 ++-- .../class-wp-ms-themes-list-table.php | 11 ++- .../includes/class-wp-ms-users-list-table.php | 29 ++++---- .../class-wp-plugin-install-list-table.php | 10 +-- .../includes/class-wp-plugins-list-table.php | 11 ++- .../includes/class-wp-posts-list-table.php | 30 +++++--- .../class-wp-privacy-requests-table.php | 26 +++---- .../class-wp-theme-install-list-table.php | 10 +-- .../includes/class-wp-users-list-table.php | 39 +++++----- wp-includes/version.php | 2 +- 12 files changed, 177 insertions(+), 105 deletions(-) diff --git a/wp-admin/includes/class-wp-comments-list-table.php b/wp-admin/includes/class-wp-comments-list-table.php index 46558cc5ba..6c07dfc697 100644 --- a/wp-admin/includes/class-wp-comments-list-table.php +++ b/wp-admin/includes/class-wp-comments-list-table.php @@ -293,12 +293,6 @@ class WP_Comments_List_Table extends WP_List_Table { } foreach ( $stati as $status => $label ) { - $current_link_attributes = ''; - - if ( $status === $comment_status ) { - $current_link_attributes = ' class="current" aria-current="page"'; - } - if ( 'mine' === $status ) { $current_user_id = get_current_user_id(); $num_comments->mine = get_comments( @@ -329,14 +323,18 @@ class WP_Comments_List_Table extends WP_List_Table { $link = add_query_arg( 's', esc_attr( wp_unslash( $_REQUEST['s'] ) ), $link ); */ - $status_links[ $status ] = "" . sprintf( - translate_nooped_plural( $label, $num_comments->$status ), - sprintf( - '%s', - ( 'moderated' === $status ) ? 'pending' : $status, - number_format_i18n( $num_comments->$status ) - ) - ) . ''; + $status_links[ $status ] = array( + 'url' => esc_url( $link ), + 'label' => sprintf( + translate_nooped_plural( $label, $num_comments->$status ), + sprintf( + '%s', + ( 'moderated' === $status ) ? 'pending' : $status, + number_format_i18n( $num_comments->$status ) + ) + ), + 'current' => $status === $comment_status, + ); } /** @@ -348,7 +346,7 @@ class WP_Comments_List_Table extends WP_List_Table { * @param string[] $status_links An associative array of fully-formed comment status links. Includes 'All', 'Mine', * 'Pending', 'Approved', 'Spam', and 'Trash'. */ - return apply_filters( 'comment_status_links', $status_links ); + return apply_filters( 'comment_status_links', $this->get_views_links( $status_links ) ); } /** diff --git a/wp-admin/includes/class-wp-list-table.php b/wp-admin/includes/class-wp-list-table.php index 046e9515d8..fd24141a2c 100644 --- a/wp-admin/includes/class-wp-list-table.php +++ b/wp-admin/includes/class-wp-list-table.php @@ -1513,6 +1513,78 @@ class WP_List_Table { die( wp_json_encode( $response ) ); } + /** + * Generates views links. + * + * @since 6.1.0 + * + * @param array $link_data { + * An array of link data. + * + * @type string $url The link URL. + * @type string $label The link label. + * @type bool $current Optional. Whether this is the currently selected view. + * } + * @return array An array of link markup. Keys match the $link_data input array. + */ + protected function get_views_links( $link_data = array() ) { + if ( ! is_array( $link_data ) ) { + _doing_it_wrong( + __METHOD__, + sprintf( + /* translators: %s: The $link_data argument. */ + __( 'The %s argument must be an array.' ), + '$link_data' + ), + '6.1.0' + ); + + return array( '' ); + } + + $views_links = array(); + foreach ( $link_data as $view => $link ) { + if ( empty( $link['url'] ) || ! is_string( $link['url'] ) || '' === trim( $link['url'] ) ) { + _doing_it_wrong( + __METHOD__, + sprintf( + /* translators: %1$s: The argument name. %2$s: The view name. */ + __( 'The %1$s argument must be a non-empty string for %2$s.' ), + 'url', + esc_html( $view ) + ), + '6.1.0' + ); + + continue; + } + + if ( empty( $link['label'] ) || ! is_string( $link['label'] ) || '' === trim( $link['label'] ) ) { + _doing_it_wrong( + __METHOD__, + sprintf( + /* translators: %1$s: The argument name. %2$s: The view name. */ + __( 'The %1$s argument must be a non-empty string for %2$s.' ), + 'label', + esc_html( $view ) + ), + '6.1.0' + ); + + continue; + } + + $views_links[ $view ] = sprintf( + '%s', + esc_url( $link['url'] ), + isset( $link['current'] ) && true === $link['current'] ? ' class="current" aria-current="page"' : '', + $link['label'] + ); + } + + return $views_links; + } + /** * Sends required variables to JavaScript land. * diff --git a/wp-admin/includes/class-wp-ms-sites-list-table.php b/wp-admin/includes/class-wp-ms-sites-list-table.php index b7d8b0e955..1dc1458879 100644 --- a/wp-admin/includes/class-wp-ms-sites-list-table.php +++ b/wp-admin/includes/class-wp-ms-sites-list-table.php @@ -262,23 +262,19 @@ class WP_MS_Sites_List_Table extends WP_List_Table { $url = 'sites.php'; foreach ( $statuses as $status => $label_count ) { - $current_link_attributes = $requested_status === $status || ( '' === $requested_status && 'all' === $status ) - ? ' class="current" aria-current="page"' - : ''; if ( (int) $counts[ $status ] > 0 ) { $label = sprintf( translate_nooped_plural( $label_count, $counts[ $status ] ), number_format_i18n( $counts[ $status ] ) ); $full_url = 'all' === $status ? $url : add_query_arg( 'status', $status, $url ); - $view_links[ $status ] = sprintf( - '%3$s', - esc_url( $full_url ), - $current_link_attributes, - $label + $view_links[ $status ] = array( + 'url' => esc_url( $full_url ), + 'label' => $label, + 'current' => $requested_status === $status || ( '' === $requested_status && 'all' === $status ), ); } } - return $view_links; + return $this->get_views_links( $view_links ); } /** diff --git a/wp-admin/includes/class-wp-ms-themes-list-table.php b/wp-admin/includes/class-wp-ms-themes-list-table.php index e87da5ca7a..70073e8130 100644 --- a/wp-admin/includes/class-wp-ms-themes-list-table.php +++ b/wp-admin/includes/class-wp-ms-themes-list-table.php @@ -444,16 +444,15 @@ class WP_MS_Themes_List_Table extends WP_List_Table { } if ( 'search' !== $type ) { - $status_links[ $type ] = sprintf( - "%s", - esc_url( add_query_arg( 'theme_status', $type, $url ) ), - ( $type === $status ) ? ' class="current" aria-current="page"' : '', - sprintf( $text, number_format_i18n( $count ) ) + $status_links[ $type ] = array( + 'url' => esc_url( add_query_arg( 'theme_status', $type, $url ) ), + 'label' => sprintf( $text, number_format_i18n( $count ) ), + 'current' => $type === $status, ); } } - return $status_links; + return $this->get_views_links( $status_links ); } /** diff --git a/wp-admin/includes/class-wp-ms-users-list-table.php b/wp-admin/includes/class-wp-ms-users-list-table.php index e440281c09..e99e92822f 100644 --- a/wp-admin/includes/class-wp-ms-users-list-table.php +++ b/wp-admin/includes/class-wp-ms-users-list-table.php @@ -137,13 +137,10 @@ class WP_MS_Users_List_Table extends WP_List_Table { $super_admins = get_super_admins(); $total_admins = count( $super_admins ); - $current_link_attributes = 'super' !== $role ? ' class="current" aria-current="page"' : ''; - $role_links = array(); - $role_links['all'] = sprintf( - '%s', - network_admin_url( 'users.php' ), - $current_link_attributes, - sprintf( + $role_links = array(); + $role_links['all'] = array( + 'url' => network_admin_url( 'users.php' ), + 'label' => sprintf( /* translators: Number of users. */ _nx( 'All (%s)', @@ -152,14 +149,13 @@ class WP_MS_Users_List_Table extends WP_List_Table { 'users' ), number_format_i18n( $total_users ) - ) + ), + 'current' => 'super' !== $role, ); - $current_link_attributes = 'super' === $role ? ' class="current" aria-current="page"' : ''; - $role_links['super'] = sprintf( - '%s', - network_admin_url( 'users.php?role=super' ), - $current_link_attributes, - sprintf( + + $role_links['super'] = array( + 'url' => network_admin_url( 'users.php?role=super' ), + 'label' => sprintf( /* translators: Number of users. */ _n( 'Super Admin (%s)', @@ -167,10 +163,11 @@ class WP_MS_Users_List_Table extends WP_List_Table { $total_admins ), number_format_i18n( $total_admins ) - ) + ), + 'current' => 'super' === $role, ); - return $role_links; + return $this->get_views_links( $role_links ); } /** diff --git a/wp-admin/includes/class-wp-plugin-install-list-table.php b/wp-admin/includes/class-wp-plugin-install-list-table.php index c213b6675a..fea5c8388c 100644 --- a/wp-admin/includes/class-wp-plugin-install-list-table.php +++ b/wp-admin/includes/class-wp-plugin-install-list-table.php @@ -310,14 +310,16 @@ class WP_Plugin_Install_List_Table extends WP_List_Table { $display_tabs = array(); foreach ( (array) $tabs as $action => $text ) { - $current_link_attributes = ( $action === $tab ) ? ' class="current" aria-current="page"' : ''; - $href = self_admin_url( 'plugin-install.php?tab=' . $action ); - $display_tabs[ 'plugin-install-' . $action ] = "$text"; + $display_tabs[ 'plugin-install-' . $action ] = array( + 'url' => self_admin_url( 'plugin-install.php?tab=' . $action ), + 'label' => $text, + 'current' => $action === $tab, + ); } // No longer a real tab. unset( $display_tabs['plugin-install-upload'] ); - return $display_tabs; + return $this->get_views_links( $display_tabs ); } /** diff --git a/wp-admin/includes/class-wp-plugins-list-table.php b/wp-admin/includes/class-wp-plugins-list-table.php index 217689ef91..b3ffa5bc6c 100644 --- a/wp-admin/includes/class-wp-plugins-list-table.php +++ b/wp-admin/includes/class-wp-plugins-list-table.php @@ -576,16 +576,15 @@ class WP_Plugins_List_Table extends WP_List_Table { } if ( 'search' !== $type ) { - $status_links[ $type ] = sprintf( - "%s", - add_query_arg( 'plugin_status', $type, 'plugins.php' ), - ( $type === $status ) ? ' class="current" aria-current="page"' : '', - sprintf( $text, number_format_i18n( $count ) ) + $status_links[ $type ] = array( + 'url' => add_query_arg( 'plugin_status', $type, 'plugins.php' ), + 'label' => sprintf( $text, number_format_i18n( $count ) ), + 'current' => $type === $status, ); } } - return $status_links; + return $this->get_views_links( $status_links ); } /** diff --git a/wp-admin/includes/class-wp-posts-list-table.php b/wp-admin/includes/class-wp-posts-list-table.php index a3fcf9ba01..97525bb7ef 100644 --- a/wp-admin/includes/class-wp-posts-list-table.php +++ b/wp-admin/includes/class-wp-posts-list-table.php @@ -331,16 +331,16 @@ class WP_Posts_List_Table extends WP_List_Table { number_format_i18n( $this->user_posts_count ) ); - $mine = $this->get_edit_link( $mine_args, $mine_inner_html, $class ); + $mine = array( + 'url' => esc_url( add_query_arg( $mine_args, 'edit.php' ) ), + 'label' => $mine_inner_html, + 'current' => isset( $_GET['author'] ) && ( $current_user_id === (int) $_GET['author'] ), + ); $all_args['all_posts'] = 1; $class = ''; } - if ( empty( $class ) && ( $this->is_base_request() || isset( $_REQUEST['all_posts'] ) ) ) { - $class = 'current'; - } - $all_inner_html = sprintf( /* translators: %s: Number of posts. */ _nx( @@ -352,7 +352,11 @@ class WP_Posts_List_Table extends WP_List_Table { number_format_i18n( $total_posts ) ); - $status_links['all'] = $this->get_edit_link( $all_args, $all_inner_html, $class ); + $status_links['all'] = array( + 'url' => esc_url( add_query_arg( $all_args, 'edit.php' ) ), + 'label' => $all_inner_html, + 'current' => empty( $class ) && ( $this->is_base_request() || isset( $_REQUEST['all_posts'] ) ), + ); if ( $mine ) { $status_links['mine'] = $mine; @@ -381,7 +385,11 @@ class WP_Posts_List_Table extends WP_List_Table { number_format_i18n( $num_posts->$status_name ) ); - $status_links[ $status_name ] = $this->get_edit_link( $status_args, $status_label, $class ); + $status_links[ $status_name ] = array( + 'url' => esc_url( add_query_arg( $status_args, 'edit.php' ) ), + 'label' => $status_label, + 'current' => isset( $_REQUEST['post_status'] ) && $status_name === $_REQUEST['post_status'], + ); } if ( ! empty( $this->sticky_posts_count ) ) { @@ -404,7 +412,11 @@ class WP_Posts_List_Table extends WP_List_Table { ); $sticky_link = array( - 'sticky' => $this->get_edit_link( $sticky_args, $sticky_inner_html, $class ), + 'sticky' => array( + 'url' => esc_url( add_query_arg( $sticky_args, 'edit.php' ) ), + 'label' => $sticky_inner_html, + 'current' => ! empty( $_REQUEST['show_sticky'] ), + ), ); // Sticky comes after Publish, or if not listed, after All. @@ -412,7 +424,7 @@ class WP_Posts_List_Table extends WP_List_Table { $status_links = array_merge( array_slice( $status_links, 0, $split ), $sticky_link, array_slice( $status_links, $split ) ); } - return $status_links; + return $this->get_views_links( $status_links ); } /** diff --git a/wp-admin/includes/class-wp-privacy-requests-table.php b/wp-admin/includes/class-wp-privacy-requests-table.php index 05dbcbc031..3061b73375 100644 --- a/wp-admin/includes/class-wp-privacy-requests-table.php +++ b/wp-admin/includes/class-wp-privacy-requests-table.php @@ -153,8 +153,7 @@ abstract class WP_Privacy_Requests_Table extends WP_List_Table { // Normalized admin URL. $admin_url = $this->get_admin_url(); - $current_link_attributes = empty( $current_status ) ? ' class="current" aria-current="page"' : ''; - $status_label = sprintf( + $status_label = sprintf( /* translators: %s: Number of requests. */ _nx( 'All (%s)', @@ -165,11 +164,10 @@ abstract class WP_Privacy_Requests_Table extends WP_List_Table { number_format_i18n( $total_requests ) ); - $views['all'] = sprintf( - '%s', - esc_url( $admin_url ), - $current_link_attributes, - $status_label + $views['all'] = array( + 'url' => esc_url( $admin_url ), + 'label' => $status_label, + 'current' => empty( $current_status ), ); foreach ( $statuses as $status => $label ) { @@ -178,8 +176,7 @@ abstract class WP_Privacy_Requests_Table extends WP_List_Table { continue; } - $current_link_attributes = $status === $current_status ? ' class="current" aria-current="page"' : ''; - $total_status_requests = absint( $counts->{$status} ); + $total_status_requests = absint( $counts->{$status} ); if ( ! $total_status_requests ) { continue; @@ -192,15 +189,14 @@ abstract class WP_Privacy_Requests_Table extends WP_List_Table { $status_link = add_query_arg( 'filter-status', $status, $admin_url ); - $views[ $status ] = sprintf( - '%s', - esc_url( $status_link ), - $current_link_attributes, - $status_label + $views[ $status ] = array( + 'url' => esc_url( $status_link ), + 'label' => $status_label, + 'current' => $status === $current_status, ); } - return $views; + return $this->get_views_links( $views ); } /** diff --git a/wp-admin/includes/class-wp-theme-install-list-table.php b/wp-admin/includes/class-wp-theme-install-list-table.php index 17f8f8598c..a02767f277 100644 --- a/wp-admin/includes/class-wp-theme-install-list-table.php +++ b/wp-admin/includes/class-wp-theme-install-list-table.php @@ -186,12 +186,14 @@ class WP_Theme_Install_List_Table extends WP_Themes_List_Table { $display_tabs = array(); foreach ( (array) $tabs as $action => $text ) { - $current_link_attributes = ( $action === $tab ) ? ' class="current" aria-current="page"' : ''; - $href = self_admin_url( 'theme-install.php?tab=' . $action ); - $display_tabs[ 'theme-install-' . $action ] = "$text"; + $display_tabs[ 'theme-install-' . $action ] = array( + 'url' => self_admin_url( 'theme-install.php?tab=' . $action ), + 'label' => $text, + 'current' => $action === $tab, + ); } - return $display_tabs; + return $this->get_views_links( $display_tabs ); } /** diff --git a/wp-admin/includes/class-wp-users-list-table.php b/wp-admin/includes/class-wp-users-list-table.php index 35310805eb..c19173428e 100644 --- a/wp-admin/includes/class-wp-users-list-table.php +++ b/wp-admin/includes/class-wp-users-list-table.php @@ -185,10 +185,9 @@ class WP_Users_List_Table extends WP_List_Table { $url = 'users.php'; } - $role_links = array(); - $avail_roles = array(); - $all_text = __( 'All' ); - $current_link_attributes = empty( $role ) ? ' class="current" aria-current="page"' : ''; + $role_links = array(); + $avail_roles = array(); + $all_text = __( 'All' ); if ( $count_users ) { if ( $this->is_site_users ) { @@ -215,19 +214,17 @@ class WP_Users_List_Table extends WP_List_Table { ); } - $role_links['all'] = sprintf( '%s', $url, $current_link_attributes, $all_text ); + $role_links['all'] = array( + 'url' => $url, + 'label' => $all_text, + 'current' => empty( $role ), + ); foreach ( $wp_roles->get_names() as $this_role => $name ) { if ( $count_users && ! isset( $avail_roles[ $this_role ] ) ) { continue; } - $current_link_attributes = ''; - - if ( $this_role === $role ) { - $current_link_attributes = ' class="current" aria-current="page"'; - } - $name = translate_user_role( $name ); if ( $count_users ) { $name = sprintf( @@ -238,17 +235,15 @@ class WP_Users_List_Table extends WP_List_Table { ); } - $role_links[ $this_role ] = "$name"; + $role_links[ $this_role ] = array( + 'url' => esc_url( add_query_arg( 'role', $this_role, $url ) ), + 'label' => $name, + 'current' => $this_role === $role, + ); } if ( ! empty( $avail_roles['none'] ) ) { - $current_link_attributes = ''; - - if ( 'none' === $role ) { - $current_link_attributes = ' class="current" aria-current="page"'; - } - $name = __( 'No role' ); $name = sprintf( /* translators: 1: User role name, 2: Number of users. */ @@ -257,10 +252,14 @@ class WP_Users_List_Table extends WP_List_Table { number_format_i18n( $avail_roles['none'] ) ); - $role_links['none'] = "$name"; + $role_links['none'] = array( + 'url' => esc_url( add_query_arg( 'role', 'none', $url ) ), + 'label' => $name, + 'current' => 'none' === $role, + ); } - return $role_links; + return $this->get_views_links( $role_links ); } /** diff --git a/wp-includes/version.php b/wp-includes/version.php index 1f7e77a5a0..6f6efe63ff 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.1-alpha-54214'; +$wp_version = '6.1-alpha-54215'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.