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
This commit is contained in:
davidbaumwald 2022-09-19 21:08:10 +00:00
parent 130e13e39e
commit be9b533e13
12 changed files with 177 additions and 105 deletions

View File

@ -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 ] = "<a href='$link'$current_link_attributes>" . sprintf(
translate_nooped_plural( $label, $num_comments->$status ),
sprintf(
'<span class="%s-count">%s</span>',
( 'moderated' === $status ) ? 'pending' : $status,
number_format_i18n( $num_comments->$status )
)
) . '</a>';
$status_links[ $status ] = array(
'url' => esc_url( $link ),
'label' => sprintf(
translate_nooped_plural( $label, $num_comments->$status ),
sprintf(
'<span class="%s-count">%s</span>',
( '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 ) );
}
/**

View File

@ -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 <code>%s</code> 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 <code>%1$s</code> argument must be a non-empty string for <code>%2$s</code>.' ),
'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 <code>%1$s</code> argument must be a non-empty string for <code>%2$s</code>.' ),
'label',
esc_html( $view )
),
'6.1.0'
);
continue;
}
$views_links[ $view ] = sprintf(
'<a href="%s"%s>%s</a>',
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.
*

View File

@ -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(
'<a href="%1$s"%2$s>%3$s</a>',
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 );
}
/**

View File

@ -444,16 +444,15 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
}
if ( 'search' !== $type ) {
$status_links[ $type ] = sprintf(
"<a href='%s'%s>%s</a>",
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 );
}
/**

View File

@ -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(
'<a href="%s"%s>%s</a>',
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 <span class="count">(%s)</span>',
@ -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(
'<a href="%s"%s>%s</a>',
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 <span class="count">(%s)</span>',
@ -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 );
}
/**

View File

@ -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 ] = "<a href='$href'$current_link_attributes>$text</a>";
$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 );
}
/**

View File

@ -576,16 +576,15 @@ class WP_Plugins_List_Table extends WP_List_Table {
}
if ( 'search' !== $type ) {
$status_links[ $type ] = sprintf(
"<a href='%s'%s>%s</a>",
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 );
}
/**

View File

@ -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 );
}
/**

View File

@ -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 <span class="count">(%s)</span>',
@ -165,11 +164,10 @@ abstract class WP_Privacy_Requests_Table extends WP_List_Table {
number_format_i18n( $total_requests )
);
$views['all'] = sprintf(
'<a href="%s"%s>%s</a>',
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(
'<a href="%s"%s>%s</a>',
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 );
}
/**

View File

@ -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 ] = "<a href='$href'$current_link_attributes>$text</a>";
$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 );
}
/**

View File

@ -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( '<a href="%s"%s>%s</a>', $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 ] = "<a href='" . esc_url( add_query_arg( 'role', $this_role, $url ) ) . "'$current_link_attributes>$name</a>";
$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'] = "<a href='" . esc_url( add_query_arg( 'role', 'none', $url ) ) . "'$current_link_attributes>$name</a>";
$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 );
}
/**

View File

@ -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.