From 4c0c7fd7ba401869682008ee4dc87a9c26d8a262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helen=20Hou-Sand=C3=AD?= Date: Fri, 29 May 2015 02:41:25 +0000 Subject: [PATCH] List tables: introduce the concept of a "primary" column. This becomes the column that contains the row actions, and allows for a more flexibility, particularly with custom post types and list tables. To (re)define the primary column, use the `list_table_primary_column` filter, which receives the column name and the screen ID as arguments. props stephdau, DaveAl, jesin. see #25408. Built from https://develop.svn.wordpress.org/trunk@32644 git-svn-id: http://core.svn.wordpress.org/trunk@32614 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- .../includes/class-wp-comments-list-table.php | 147 ++++--- .../includes/class-wp-links-list-table.php | 142 ++++--- wp-admin/includes/class-wp-list-table.php | 73 +++- .../includes/class-wp-media-list-table.php | 368 +++++++++--------- .../includes/class-wp-ms-sites-list-table.php | 286 ++++++++------ .../class-wp-ms-themes-list-table.php | 28 +- .../includes/class-wp-ms-users-list-table.php | 171 ++++---- .../includes/class-wp-plugins-list-table.php | 48 ++- .../includes/class-wp-posts-list-table.php | 176 +++++---- .../includes/class-wp-terms-list-table.php | 110 ++++-- .../includes/class-wp-users-list-table.php | 110 +++--- wp-includes/version.php | 2 +- 12 files changed, 1006 insertions(+), 655 deletions(-) diff --git a/wp-admin/includes/class-wp-comments-list-table.php b/wp-admin/includes/class-wp-comments-list-table.php index 0c7b5129c4..fd92b03fcd 100644 --- a/wp-admin/includes/class-wp-comments-list-table.php +++ b/wp-admin/includes/class-wp-comments-list-table.php @@ -357,6 +357,18 @@ class WP_Comments_List_Table extends WP_List_Table { ); } + /** + * Get name of default primary column + * + * @since 4.3.0 + * @access protected + * + * @return string + */ + protected function get_default_primary_column_name() { + return 'comment'; + } + public function display() { wp_nonce_field( "fetch-list-" . get_class( $this ), '_ajax_fetch_list_nonce' ); @@ -415,62 +427,33 @@ class WP_Comments_List_Table extends WP_List_Table { echo "\n"; } - public function column_cb( $comment ) { - if ( $this->user_can ) { ?> - - - user_can ) { + return; + + } - /** - * - * @global string $comment_status - * @param object $comment - */ - public function column_comment( $comment ) { - global $comment_status; $post = get_post(); - $comment_url = esc_url( get_comment_link( $comment->comment_ID ) ); $the_comment_status = wp_get_comment_status( $comment->comment_ID ); - echo '
'; - $this->column_author( $comment ); - echo '
'; + $out = ''; - echo '
'; - /* translators: 2: comment date, 3: comment time */ - printf( __( 'Submitted on %2$s at %3$s' ), $comment_url, - /* translators: comment date format. See http://php.net/date */ - get_comment_date( __( 'Y/m/d' ) ), - get_comment_date( get_option( 'time_format' ) ) - ); - - if ( $comment->comment_parent ) { - $parent = get_comment( $comment->comment_parent ); - $parent_link = esc_url( get_comment_link( $comment->comment_parent ) ); - $name = get_comment_author( $parent->comment_ID ); - printf( ' | '.__( 'In reply to %2$s.' ), $parent_link, $name ); - } - - echo '
'; - comment_text(); - if ( $this->user_can ) { ?> - - user_can ) { + if( $primary === $column_name ) { $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) ); $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) ); @@ -536,7 +519,7 @@ class WP_Comments_List_Table extends WP_List_Table { $actions = apply_filters( 'comment_row_actions', array_filter( $actions ), $comment ); $i = 0; - echo '
'; + $out .= '
'; foreach ( $actions as $action => $link ) { ++$i; ( ( ( 'approve' == $action || 'unapprove' == $action ) && 2 === $i ) || 1 === $i ) ? $sep = '' : $sep = ' | '; @@ -551,9 +534,67 @@ class WP_Comments_List_Table extends WP_List_Table { $action .= ' unapprove'; } - echo "$sep$link"; + $out .= "$sep$link"; } - echo '
'; + $out .= '
'; + } + + return $out; + } + + public function column_cb( $comment ) { + if ( $this->user_can ) { ?> + + + comment_ID ) ); + $the_comment_status = wp_get_comment_status( $comment->comment_ID ); + + echo '
'; + $this->column_author( $comment ); + echo '
'; + + echo '
'; + /* translators: 2: comment date, 3: comment time */ + printf( __( 'Submitted on %2$s at %3$s' ), $comment_url, + /* translators: comment date format. See http://php.net/date */ + get_comment_date( __( 'Y/m/d' ) ), + get_comment_date( get_option( 'time_format' ) ) + ); + + if ( $comment->comment_parent ) { + $parent = get_comment( $comment->comment_parent ); + $parent_link = esc_url( get_comment_link( $comment->comment_parent ) ); + $name = get_comment_author( $parent->comment_ID ); + printf( ' | '.__( 'In reply to %2$s.' ), $parent_link, $name ); + } + + echo '
'; + comment_text(); + if ( $this->user_can ) { ?> + + link_id; ?>"> get_column_info(); + list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); foreach ( $columns as $column_name => $column_display_name ) { - $class = "class='column-$column_name'"; + $classes = "$column_name column-$column_name"; + if ( $primary === $column_name ) { + $classes .= ' has-row-actions column-primary'; + } $style = ''; - if ( in_array( $column_name, $hidden ) ) + if ( in_array( $column_name, $hidden ) ) { $style = ' style="display:none;"'; + } - $attributes = $class . $style; + $attributes = "class='$classes'$style"; - switch ( $column_name ) { - case 'cb': ?> - - - - - + + + + + "; - case 'name': - echo "link_name ) ) . "'>$link->link_name
"; - - $actions = array(); - $actions['edit'] = '' . __( 'Edit' ) . ''; - $actions['delete'] = "link_id ) . "' onclick=\"if ( confirm( '" . esc_js( sprintf( __( "You are about to delete this link '%s'\n 'Cancel' to stop, 'OK' to delete." ), $link->link_name ) ) . "' ) ) { return true;}return false;\">" . __( 'Delete' ) . ""; - echo $this->row_actions( $actions ); - - echo ''; - break; - case 'url': - echo "link_name ) )."'>$short_url"; - break; - case 'categories': - ?>>link_category as $category ) { - $cat = get_term( $category, 'link_category', OBJECT, 'display' ); - if ( is_wp_error( $cat ) ) - echo $cat->get_error_message(); - $cat_name = $cat->name; - if ( $cat_id != $category ) - $cat_name = "$cat_name"; - $cat_names[] = $cat_name; - } - echo implode( ', ', $cat_names ); - ?>>link_rel ) ? '
' : $link->link_rel; ?>>> - >link_name ) ) . "'>$link->link_name
"; + break; + case 'url': + echo "link_name ) )."'>$short_url"; + break; + case 'categories': + $cat_names = array(); + foreach ( $link->link_category as $category ) { + $cat = get_term( $category, 'link_category', OBJECT, 'display' ); + if ( is_wp_error( $cat ) ) + echo $cat->get_error_message(); + $cat_name = $cat->name; + if ( $cat_id != $category ) + $cat_name = "$cat_name"; + $cat_names[] = $cat_name; + } + echo implode( ', ', $cat_names ); + break; + case 'rel': + echo empty( $link->link_rel ) ? '
' : $link->link_rel; + break; + case 'visible': + echo $visible; + break; + case 'rating': + echo $rating; + break; + default: /** * Fires for each registered custom link column. * @@ -211,9 +218,11 @@ class WP_Links_List_Table extends WP_List_Table { * @param int $link_id Link ID. */ do_action( 'manage_link_custom_column', $column_name, $link->link_id ); - ?> - handle_row_actions( $link, $column_name, $primary ); + echo ''; } } ?> @@ -221,4 +230,27 @@ class WP_Links_List_Table extends WP_List_Table { ' . __('Edit') . ''; + $actions['delete'] = "link_id) . "' onclick=\"if ( confirm( '" . esc_js(sprintf(__("You are about to delete this link '%s'\n 'Cancel' to stop, 'OK' to delete."), $link->link_name)) . "' ) ) { return true;}return false;\">" . __('Delete') . ""; + return $this->row_actions($actions); + } + } } diff --git a/wp-admin/includes/class-wp-list-table.php b/wp-admin/includes/class-wp-list-table.php index 16c157cb5b..86b964b6be 100644 --- a/wp-admin/includes/class-wp-list-table.php +++ b/wp-admin/includes/class-wp-list-table.php @@ -794,6 +794,46 @@ class WP_List_Table { return array(); } + /** + * Get name of default primary column + * + * @since 4.3.0 + * @access protected + * + * @return string + */ + protected function get_default_primary_column_name() { + return ''; + } + + /** + * Get name of primary column. + * + * @since 4.3.0 + * @access protected + * + * @return string Filtered name of primary column + */ + protected function get_primary_column_name() { + $columns = $this->get_columns(); + $default = $this->get_default_primary_column_name(); + /** + * Filter the name of the primary column for the current list table, with context as argument (eg: 'plugins'). + * + * @since 4.3.0 + * + * @param string $default Column name default for the specific list table (eg: 'name') + * @param string $context Screen ID for specific list table (eg: 'plugins') + */ + $column = apply_filters( 'list_table_primary_column', $default, $this->screen->id ); + + if ( empty( $column ) || ! isset( $columns[ $column ] ) ) { + $column = $default; + } + + return $column; + } + /** * Get a list of all, hidden and sortable columns, with filter applied * @@ -834,7 +874,8 @@ class WP_List_Table { $sortable[$id] = $data; } - $this->_column_headers = array( $columns, $hidden, $sortable ); + $primary = $this->get_primary_column_name(); + $this->_column_headers = array( $columns, $hidden, $sortable, $primary ); return $this->_column_headers; } @@ -1062,16 +1103,20 @@ class WP_List_Table { * @param object $item The current item */ protected function single_row_columns( $item ) { - list( $columns, $hidden ) = $this->get_column_info(); + list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); foreach ( $columns as $column_name => $column_display_name ) { - $class = "class='$column_name column-$column_name'"; + $classes = "$column_name column-$column_name"; + if ( $primary === $column_name ) { + $classes .= ' has-row-actions column-primary'; + } $style = ''; - if ( in_array( $column_name, $hidden ) ) + if ( in_array( $column_name, $hidden ) ) { $style = ' style="display:none;"'; + } - $attributes = "$class$style"; + $attributes = "class='$classes'$style"; if ( 'cb' == $column_name ) { echo ''; @@ -1081,16 +1126,34 @@ class WP_List_Table { elseif ( method_exists( $this, 'column_' . $column_name ) ) { echo ""; echo call_user_func( array( $this, 'column_' . $column_name ), $item ); + echo $this->handle_row_actions( $item, $column_name, $primary ); echo ""; } else { echo ""; echo $this->column_default( $item, $column_name ); + echo $this->handle_row_actions( $item, $column_name, $primary ); echo ""; } } } + /** + * Generate and display row actions links + * + * @since 4.3.0 + * @access protected + * + * @param object $item Item being acted upon + * @param string $column_name Current column name + * @param string $primary Primary column name + * + * @return string + */ + protected function handle_row_actions( $item, $column_name, $primary ) { + return ''; + } + /** * Handle an incoming ajax request (called from admin-ajax.php) * diff --git a/wp-admin/includes/class-wp-media-list-table.php b/wp-admin/includes/class-wp-media-list-table.php index 9bcb375f59..264cfa5b2f 100644 --- a/wp-admin/includes/class-wp-media-list-table.php +++ b/wp-admin/includes/class-wp-media-list-table.php @@ -308,19 +308,22 @@ class WP_Media_List_Table extends WP_List_Table { get_column_info(); +list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); + foreach ( $columns as $column_name => $column_display_name ) { - $class = "class='$column_name column-$column_name'"; + $classes = "$column_name column-$column_name"; + if ( $primary === $column_name ) { + $classes .= ' has-row-actions column-primary'; + } $style = ''; - if ( in_array( $column_name, $hidden ) ) + if ( in_array( $column_name, $hidden ) ) { $style = ' style="display:none;"'; + } - $attributes = $class . $style; + $attributes = "class='$classes'$style"; - switch ( $column_name ) { - - case 'cb': + if ( 'cb' === $column_name ) { ?> @@ -329,190 +332,171 @@ foreach ( $columns as $column_name => $column_display_name ) { "; - case 'icon': - list( $mime ) = explode( '/', $post->post_mime_type ); - $attributes = 'class="column-icon media-icon ' . $mime . '-icon"' . $style; -?> - >ID, array( 80, 60 ), true ) ) { - if ( $this->is_trash || ! $user_can_edit ) { - echo $thumb; - } else { -?> - - - + switch ( $column_name ) { + case 'icon': + list( $mime ) = explode( '/', $post->post_mime_type ); + $attributes = 'class="column-icon media-icon ' . $mime . '-icon"' . $style; - - - - > - is_trash || ! $user_can_edit ) { - echo $att_title; - } else { ?> - - - -

guid ); ?>

-row_actions( $this->_get_row_actions( $post, $att_title ) ); -?> - - - >%s', - esc_url( add_query_arg( array( 'author' => get_the_author_meta('ID') ), 'upload.php' ) ), - get_the_author() - ); - ?> - - >post_excerpt : ''; ?> -post_date ) { - $h_time = __( 'Unpublished' ); - } else { - $m_time = $post->post_date; - $time = get_post_time( 'G', true, $post, false ); - if ( ( abs( $t_diff = time() - $time ) ) < DAY_IN_SECONDS ) { - if ( $t_diff < 0 ) - $h_time = sprintf( __( '%s from now' ), human_time_diff( $time ) ); - else - $h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) ); - } else { - $h_time = mysql2date( __( 'Y/m/d' ), $m_time ); - } - } -?> - > -post_parent > 0 ) - $parent = get_post( $post->post_parent ); - else - $parent = false; - - if ( $parent ) { - $title = _draft_or_post_title( $post->post_parent ); - $parent_type = get_post_type_object( $parent->post_type ); -?> - > - show_ui && current_user_can( 'edit_post', $post->post_parent ) ) { ?> - - , -
- $post->post_parent, - 'media[]' => $post->ID, - '_wpnonce' => wp_create_nonce( 'bulk-' . $this->_args['plural'] ) - ), 'upload.php' ); ?> - - - - - >
- - - - - - > -
-ID ); - - $this->comments_bubble( $post->ID, $pending_comments ); -?> -
- -'; - if ( $terms = get_the_terms( $post->ID, $taxonomy ) ) { - $out = array(); - foreach ( $terms as $t ) { - $posts_in_term_qv = array(); - $posts_in_term_qv['taxonomy'] = $taxonomy; - $posts_in_term_qv['term'] = $t->slug; - - $out[] = sprintf( '%s', - esc_url( add_query_arg( $posts_in_term_qv, 'upload.php' ) ), - esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) ) - ); + if ( $thumb = wp_get_attachment_image( $post->ID, array( 80, 60 ), true ) ) { + if ( $this->is_trash || ! $user_can_edit ) { + echo $thumb; + } else { ?> + + + '; - break; - } + break; + + case 'title': ?> - >ID ); - ?> + + is_trash || ! $user_can_edit ) { + echo $att_title; + } else { ?> + + + +

guid ); ?>

%s', + esc_url( add_query_arg( array( 'author' => get_the_author_meta('ID') ), 'upload.php' ) ), + get_the_author() + ); + + break; + + case 'desc': + echo has_excerpt() ? $post->post_excerpt : ''; + break; + + case 'date': + if ( '0000-00-00 00:00:00' == $post->post_date ) { + $h_time = __( 'Unpublished' ); + } else { + $m_time = $post->post_date; + $time = get_post_time( 'G', true, $post, false ); + if ( ( abs( $t_diff = time() - $time ) ) < DAY_IN_SECONDS ) { + if ( $t_diff < 0 ) + $h_time = sprintf( __( '%s from now' ), human_time_diff( $time ) ); + else + $h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) ); + } else { + $h_time = mysql2date( __( 'Y/m/d' ), $m_time ); + } + } + + echo $h_time; + break; + + case 'parent': + if ( $post->post_parent > 0 ) + $parent = get_post( $post->post_parent ); + else + $parent = false; + + if ( $parent ) { + $title = _draft_or_post_title( $post->post_parent ); + $parent_type = get_post_type_object( $parent->post_type ); + ?> + + show_ui && current_user_can( 'edit_post', $post->post_parent ) ) { ?> + + , +
+ $post->post_parent, + 'media[]' => $post->ID, + '_wpnonce' => wp_create_nonce( 'bulk-' . $this->_args['plural'] ) + ), 'upload.php' ); ?> + +
+ + + + '; + + $pending_comments = get_pending_comments_num( $post->ID ); + $this->comments_bubble( $post->ID, $pending_comments ); + + echo ''; + + break; + + default: + if ( 'categories' == $column_name ) + $taxonomy = 'category'; + elseif ( 'tags' == $column_name ) + $taxonomy = 'post_tag'; + elseif ( 0 === strpos( $column_name, 'taxonomy-' ) ) + $taxonomy = substr( $column_name, 9 ); + else + $taxonomy = false; + + if ( $taxonomy ) { + if ( $terms = get_the_terms( $post->ID, $taxonomy ) ) { + $out = array(); + foreach ( $terms as $t ) { + $posts_in_term_qv = array(); + $posts_in_term_qv['taxonomy'] = $taxonomy; + $posts_in_term_qv['term'] = $t->slug; + + $out[] = sprintf( '%s', + esc_url( add_query_arg( $posts_in_term_qv, 'upload.php' ) ), + esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) ) + ); + } + /* translators: used between list items, there is a space after the comma */ + echo join( __( ', ' ), $out ); + } else { + echo '—'; + } + + break; + } + + /** + * Fires for each custom column in the Media list table. + * + * Custom columns are registered using the 'manage_media_columns' filter. + * + * @since 2.5.0 + * + * @param string $column_name Name of the custom column. + * @param int $post_id Attachment ID. + */ + do_action( 'manage_media_custom_column', $column_name, $post->ID ); + break; + } + + if( $primary === $column_name ) { + echo $this->row_actions( $this->_get_row_actions( $post, $att_title ) ); + } + + echo ''; } } ?> @@ -520,6 +504,18 @@ foreach ( $columns as $column_name => $column_display_name ) { domain, '', $blog['domain'] ) : $blog['path']; - list( $columns, $hidden ) = $this->get_column_info(); + list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); foreach ( $columns as $column_name => $column_display_name ) { + $classes = "$column_name column-$column_name"; + if ( $primary === $column_name ) { + $classes .= ' has-row-actions column-primary'; + } + $style = ''; - if ( in_array( $column_name, $hidden ) ) + if ( in_array( $column_name, $hidden ) ) { $style = ' style="display:none;"'; + } - switch ( $column_name ) { - case 'cb': ?> - - - - - - - - - - - + + + + + + + + + + +"; - case 'blogname': - echo ""; ?> + switch ( $column_name ) { + case 'blogname': + ?> ' . sprintf( __( '%1$s – %2$s' ), get_option( 'blogname' ), get_option( 'blogdescription ' ) ) . '

'; restore_current_blog(); } + break; - // Preordered. - $actions = array( - 'edit' => '', 'backend' => '', - 'activate' => '', 'deactivate' => '', - 'archive' => '', 'unarchive' => '', - 'spam' => '', 'unspam' => '', - 'delete' => '', - 'visit' => '', - ); + case 'lastupdated': + echo ( $blog['last_updated'] == '0000-00-00 00:00:00' ) ? __( 'Never' ) : mysql2date( $date, $blog['last_updated'] ); + break; - $actions['edit'] = '' . __( 'Edit' ) . ''; - $actions['backend'] = "" . __( 'Dashboard' ) . ''; - if ( get_current_site()->blog_id != $blog['blog_id'] ) { - if ( $blog['deleted'] == '1' ) { - $actions['activate'] = '' . __( 'Activate' ) . ''; - } else { - $actions['deactivate'] = '' . __( 'Deactivate' ) . ''; - } - - if ( $blog['archived'] == '1' ) { - $actions['unarchive'] = '' . __( 'Unarchive' ) . ''; - } else { - $actions['archive'] = '' . _x( 'Archive', 'verb; site' ) . ''; - } - - if ( $blog['spam'] == '1' ) { - $actions['unspam'] = '' . _x( 'Not Spam', 'site' ) . ''; - } else { - $actions['spam'] = '' . _x( 'Spam', 'site' ) . ''; - } - - if ( current_user_can( 'delete_site', $blog['blog_id'] ) ) { - $actions['delete'] = '' . __( 'Delete' ) . ''; - } + case 'registered': + if ( $blog['registered'] == '0000-00-00 00:00:00' ) { + echo '—'; + } else { + echo mysql2date( $date, $blog['registered'] ); } + break; - $actions['visit'] = "" . __( 'Visit' ) . ''; - - /** - * Filter the action links displayed for each site in the Sites list table. - * - * The 'Edit', 'Dashboard', 'Delete', and 'Visit' links are displayed by - * default for each site. The site's status determines whether to show the - * 'Activate' or 'Deactivate' link, 'Unarchive' or 'Archive' links, and - * 'Not Spam' or 'Spam' link for each site. - * - * @since 3.1.0 - * - * @param array $actions An array of action links to be displayed. - * @param int $blog_id The site ID. - * @param string $blogname Site path, formatted depending on whether it is a sub-domain - * or subdirectory multisite install. - */ - $actions = apply_filters( 'manage_sites_action_links', array_filter( $actions ), $blog['blog_id'], $blogname ); - echo $this->row_actions( $actions ); - ?> - - "; - echo ( $blog['last_updated'] == '0000-00-00 00:00:00' ) ? __( 'Never' ) : mysql2date( $date, $blog['last_updated'] ); ?> - - "; - if ( $blog['registered'] == '0000-00-00 00:00:00' ) - echo '—'; - else - echo mysql2date( $date, $blog['registered'] ); - ?> - - "; + case 'users': $blogusers = get_users( array( 'blog_id' => $blog['blog_id'], 'number' => 6) ); if ( is_array( $blogusers ) ) { $blogusers_warning = ''; @@ -376,41 +321,38 @@ class WP_MS_Sites_List_Table extends WP_List_Table { if ( $blogusers_warning != '' ) echo '' . $blogusers_warning . '
'; } - ?> - - - "; - /** - * Fires inside the auxiliary 'Actions' column of the Sites list table. - * - * By default this column is hidden unless something is hooked to the action. - * - * @since MU - * - * @param int $blog_id The site ID. - */ - do_action( 'wpmublogsaction', $blog['blog_id'] ); ?> - - "; - /** - * Fires for each registered custom column in the Sites list table. - * - * @since 3.1.0 - * - * @param string $column_name The name of the column to display. - * @param int $blog_id The site ID. - */ - do_action( 'manage_sites_custom_column', $column_name, $blog['blog_id'] ); - echo ""; - break; + default: + /** + * Fires for each registered custom column in the Sites list table. + * + * @since 3.1.0 + * + * @param string $column_name The name of the column to display. + * @param int $blog_id The site ID. + */ + do_action( 'manage_sites_custom_column', $column_name, $blog['blog_id'] ); + break; + } + + echo $this->handle_row_actions( $blog, $column_name, $primary ); + echo ''; } } ?> @@ -418,4 +360,92 @@ class WP_MS_Sites_List_Table extends WP_List_Table { domain, '', $blog['domain'] ) : $blog['path']; + + // Preordered. + $actions = array( + 'edit' => '', 'backend' => '', + 'activate' => '', 'deactivate' => '', + 'archive' => '', 'unarchive' => '', + 'spam' => '', 'unspam' => '', + 'delete' => '', + 'visit' => '', + ); + + $actions['edit'] = '' . __( 'Edit' ) . ''; + $actions['backend'] = "" . __( 'Dashboard' ) . ''; + if ( get_current_site()->blog_id != $blog['blog_id'] ) { + if ( $blog['deleted'] == '1' ) { + $actions['activate'] = '' . __( 'Activate' ) . ''; + } else { + $actions['deactivate'] = '' . __( 'Deactivate' ) . ''; + } + + if ( $blog['archived'] == '1' ) { + $actions['unarchive'] = '' . __( 'Unarchive' ) . ''; + } else { + $actions['archive'] = '' . _x( 'Archive', 'verb; site' ) . ''; + } + + if ( $blog['spam'] == '1' ) { + $actions['unspam'] = '' . _x( 'Not Spam', 'site' ) . ''; + } else { + $actions['spam'] = '' . _x( 'Spam', 'site' ) . ''; + } + + if ( current_user_can( 'delete_site', $blog['blog_id'] ) ) { + $actions['delete'] = '' . __( 'Delete' ) . ''; + } + } + + $actions['visit'] = "" . __( 'Visit' ) . ''; + + /** + * Filter the action links displayed for each site in the Sites list table. + * + * The 'Edit', 'Dashboard', 'Delete', and 'Visit' links are displayed by + * default for each site. The site's status determines whether to show the + * 'Activate' or 'Deactivate' link, 'Unarchive' or 'Archive' links, and + * 'Not Spam' or 'Spam' link for each site. + * + * @since 3.1.0 + * + * @param array $actions An array of action links to be displayed. + * @param int $blog_id The site ID. + * @param string $blogname Site path, formatted depending on whether it is a sub-domain + * or subdirectory multisite install. + */ + $actions = apply_filters( 'manage_sites_action_links', array_filter( $actions ), $blog['blog_id'], $blogname ); + return $this->row_actions( $actions ); + } + } } 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 9e94e8493e..e78270ba2b 100644 --- a/wp-admin/includes/class-wp-ms-themes-list-table.php +++ b/wp-admin/includes/class-wp-ms-themes-list-table.php @@ -229,6 +229,18 @@ class WP_MS_Themes_List_Table extends WP_List_Table { ); } + /** + * Get name of default primary column + * + * @since 4.3.0 + * @access protected + * + * @return string + */ + protected function get_default_primary_column_name() { + return 'name'; + } + /** * * @global array $totals @@ -400,7 +412,7 @@ class WP_MS_Themes_List_Table extends WP_List_Table { echo ""; - list( $columns, $hidden ) = $this->get_column_info(); + list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); foreach ( $columns as $column_name => $column_display_name ) { $style = ''; @@ -413,7 +425,9 @@ class WP_MS_Themes_List_Table extends WP_List_Table { break; case 'name': echo "" . $theme->display('Name') . ""; - echo $this->row_actions( $actions, true ); + if ( $primary === $column_name ) { + echo $this->row_actions($actions, true); + } echo ""; break; case 'description': @@ -451,7 +465,11 @@ class WP_MS_Themes_List_Table extends WP_List_Table { $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $stylesheet, $theme, $status ); echo implode( ' | ', $theme_meta ); - echo ""; + echo ''; + if ( $primary === $column_name ) { + echo $this->row_actions($actions, true); + } + echo ''; break; default: @@ -467,6 +485,10 @@ class WP_MS_Themes_List_Table extends WP_List_Table { * @param WP_Theme $theme Current WP_Theme object. */ do_action( 'manage_themes_custom_column', $column_name, $stylesheet, $theme ); + + if ( $primary === $column_name ) { + echo $this->row_actions($actions, true); + } echo ""; } } 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 55ca80a703..0da586dbda 100644 --- a/wp-admin/includes/class-wp-ms-users-list-table.php +++ b/wp-admin/includes/class-wp-ms-users-list-table.php @@ -180,81 +180,66 @@ class WP_MS_Users_List_Table extends WP_List_Table { get_column_info(); + list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); foreach ( $columns as $column_name => $column_display_name ) : - $class = "class='$column_name column-$column_name'"; + $classes = "$column_name column-$column_name"; + if ( $primary === $column_name || 'blogs' === $column_name ) { + $classes .= ' has-row-actions'; + } + + if ( $primary === $column_name ) { + $classes .= ' column-primary'; + } $style = ''; - if ( in_array( $column_name, $hidden ) ) + if ( in_array( $column_name, $hidden ) ) { $style = ' style="display:none;"'; + } - $attributes = "$class$style"; + $attributes = "class='$classes'$style"; - switch ( $column_name ) { - case 'cb': ?> - - - - + if ( 'cb' === $column_name ){ + ?> + + + + "; + + switch ( $column_name ) { + case 'username': + $avatar = get_avatar( $user->user_email, 32 ); + $edit_link = esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), get_edit_user_link( $user->ID ) ) ); - case 'username': - $avatar = get_avatar( $user->user_email, 32 ); - $edit_link = esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), get_edit_user_link( $user->ID ) ) ); - - echo ""; ?> - user_login; ?>user_login; ?>user_login, $super_admins ) ) echo ' - ' . __( 'Super Admin' ); ?> -
- ' . __( 'Edit' ) . ''; + ID ) && ! in_array( $user->user_login, $super_admins ) ) { - $actions['delete'] = '' . __( 'Delete' ) . ''; - } + case 'name': + echo "$user->first_name $user->last_name"; + break; - /** - * Filter the action links displayed under each user - * in the Network Admin Users list table. - * - * @since 3.2.0 - * - * @param array $actions An array of action links to be displayed. - * Default 'Edit', 'Delete'. - * @param WP_User $user WP_User object. - */ - $actions = apply_filters( 'ms_user_row_actions', $actions, $user ); - echo $this->row_actions( $actions ); - ?> - - user_email'>$user->user_email"; + break; - case 'name': - echo "$user->first_name $user->last_name"; - break; + case 'registered': + if ( 'list' == $mode ) + $date = __( 'Y/m/d' ); + else + $date = __( 'Y/m/d g:i:s a' ); - case 'email': - echo "$user->user_email"; - break; + echo mysql2date( $date, $user->user_registered ); + break; - case 'registered': - if ( 'list' == $mode ) - $date = __( 'Y/m/d' ); - else - $date = __( 'Y/m/d g:i:s a' ); - - echo "" . mysql2date( $date, $user->user_registered ) . ""; - break; - - case 'blogs': - $blogs = get_blogs_of_user( $user->ID, true ); - echo ""; + case 'blogs': + $blogs = get_blogs_of_user( $user->ID, true ); if ( is_array( $blogs ) ) { foreach ( (array) $blogs as $key => $val ) { if ( !can_edit_network( $val->site_id ) ) @@ -305,17 +290,16 @@ class WP_MS_Users_List_Table extends WP_List_Table { echo '
'; } } - ?> - - "; - /** This filter is documented in wp-admin/includes/class-wp-users-list-table.php */ - echo apply_filters( 'manage_users_custom_column', '', $column_name, $user->ID ); - echo ""; - break; + default: + /** This filter is documented in wp-admin/includes/class-wp-users-list-table.php */ + echo apply_filters( 'manage_users_custom_column', '', $column_name, $user->ID ); + break; + } + + echo $this->handle_row_actions( $user, $column_name, $primary ); + echo ''; } endforeach ?> @@ -323,4 +307,55 @@ class WP_MS_Users_List_Table extends WP_List_Table { ID ) ) ); + + if ( $primary === $column_name ) { + $actions = array(); + $actions['edit'] = '' . __( 'Edit' ) . ''; + + if ( current_user_can( 'delete_user', $user->ID ) && ! in_array( $user->user_login, $super_admins ) ) { + $actions['delete'] = '' . __( 'Delete' ) . ''; + } + + /** + * Filter the action links displayed under each user + * in the Network Admin Users list table. + * + * @since 3.2.0 + * + * @param array $actions An array of action links to be displayed. + * Default 'Edit', 'Delete'. + * @param WP_User $user WP_User object. + */ + $actions = apply_filters( 'ms_user_row_actions', $actions, $user ); + return $this->row_actions( $actions ); + } + } } diff --git a/wp-admin/includes/class-wp-plugins-list-table.php b/wp-admin/includes/class-wp-plugins-list-table.php index 387f80b49d..1b3c6d3449 100644 --- a/wp-admin/includes/class-wp-plugins-list-table.php +++ b/wp-admin/includes/class-wp-plugins-list-table.php @@ -568,24 +568,36 @@ class WP_Plugins_List_Table extends WP_List_Table { $plugin_slug ); - list( $columns, $hidden ) = $this->get_column_info(); + list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); + + $extra_class = ' has-row-actions column-primary'; foreach ( $columns as $column_name => $column_display_name ) { $style = ''; - if ( in_array( $column_name, $hidden ) ) + if ( in_array( $column_name, $hidden ) ) { $style = ' style="display:none;"'; + } switch ( $column_name ) { case 'cb': echo "$checkbox"; break; case 'name': - echo "$plugin_name"; - echo $this->row_actions( $actions, true ); + if ( $primary === $column_name || ! isset( $columns[ $primary ] ) ) { + echo "$plugin_name"; + echo $this->row_actions( $actions, true ); + } else { + echo "$plugin_name"; + } echo ""; break; case 'description': - echo " + $classes = 'column-description desc'; + if ( $primary === $column_name ) { + $classes .= " $extra_class"; + } + + echo "
$description
"; @@ -632,10 +644,18 @@ class WP_Plugins_List_Table extends WP_List_Table { $plugin_meta = apply_filters( 'plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $status ); echo implode( ' | ', $plugin_meta ); + if ( $primary === $column_name ) { + echo $this->row_actions( $actions, true ); + } echo "
"; break; default: - echo ""; + $classes = "$column_name column-$column_name$class"; + if ( $primary === $column_name ) { + $classes .= " $extra_class"; + } + + echo ""; /** * Fires inside each custom column of the Plugins list table. @@ -647,6 +667,10 @@ class WP_Plugins_List_Table extends WP_List_Table { * @param array $plugin_data An array of plugin data. */ do_action( 'manage_plugins_custom_column', $column_name, $plugin_file, $plugin_data ); + + if ( $primary === $column_name ) { + echo $this->row_actions( $actions, true ); + } echo ""; } } @@ -682,4 +706,16 @@ class WP_Plugins_List_Table extends WP_List_Table { */ do_action( "after_plugin_row_$plugin_file", $plugin_file, $plugin_data, $status ); } + + /** + * Get name of default primary column for this specific list table. + * + * @since 4.3.0 + * @access protected + * + * @return string + */ + protected function get_default_primary_column_name() { + return 'plugin'; + } } diff --git a/wp-admin/includes/class-wp-posts-list-table.php b/wp-admin/includes/class-wp-posts-list-table.php index 6389b1d5b4..7786e94e0e 100644 --- a/wp-admin/includes/class-wp-posts-list-table.php +++ b/wp-admin/includes/class-wp-posts-list-table.php @@ -684,16 +684,20 @@ class WP_Posts_List_Table extends WP_List_Table { get_column_info(); + list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); foreach ( $columns as $column_name => $column_display_name ) { - $class = "class=\"$column_name column-$column_name\""; + $classes = "$column_name column-$column_name"; + if ( $primary === $column_name ) { + $classes .= ' has-row-actions column-primary'; + } $style = ''; - if ( in_array( $column_name, $hidden ) ) + if ( in_array( $column_name, $hidden ) ) { $style = ' style="display:none;"'; + } - $attributes = "$class$style"; + $attributes = "class='$classes'$style"; switch ( $column_name ) { @@ -715,7 +719,8 @@ class WP_Posts_List_Table extends WP_List_Table { break; case 'title': - $attributes = 'class="post-title page-title column-title"' . $style; + $classes .= ' page-title'; // Special addition for title column + $attributes = "class='$classes'$style"; if ( $this->hierarchical_display ) { if ( 0 == $level && (int) $post->post_parent > 0 ) { // Sent level 0 by accident, by default, or because we don't know the actual level. @@ -772,65 +777,7 @@ class WP_Posts_List_Table extends WP_List_Table { if ( ! $this->hierarchical_display && 'excerpt' == $mode && current_user_can( 'read_post', $post->ID ) ) the_excerpt(); - $actions = array(); - if ( $can_edit_post && 'trash' != $post->post_status ) { - $actions['edit'] = '' . __( 'Edit' ) . ''; - $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit' ) . ''; - } - if ( current_user_can( 'delete_post', $post->ID ) ) { - if ( 'trash' == $post->post_status ) - $actions['untrash'] = "ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore' ) . ""; - elseif ( EMPTY_TRASH_DAYS ) - $actions['trash'] = "" . __( 'Trash' ) . ""; - if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS ) - $actions['delete'] = "" . __( 'Delete Permanently' ) . ""; - } - if ( $post_type_object->public ) { - if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) { - if ( $can_edit_post ) { - $preview_link = set_url_scheme( get_permalink( $post->ID ) ); - /** This filter is documented in wp-admin/includes/meta-boxes.php */ - $preview_link = apply_filters( 'preview_post_link', add_query_arg( 'preview', 'true', $preview_link ), $post ); - $actions['view'] = '' . __( 'Preview' ) . ''; - } - } elseif ( 'trash' != $post->post_status ) { - $actions['view'] = '' . __( 'View' ) . ''; - } - } - - if ( is_post_type_hierarchical( $post->post_type ) ) { - - /** - * Filter the array of row action links on the Pages list table. - * - * The filter is evaluated only for hierarchical post types. - * - * @since 2.8.0 - * - * @param array $actions An array of row action links. Defaults are - * 'Edit', 'Quick Edit', 'Restore, 'Trash', - * 'Delete Permanently', 'Preview', and 'View'. - * @param WP_Post $post The post object. - */ - $actions = apply_filters( 'page_row_actions', $actions, $post ); - } else { - - /** - * Filter the array of row action links on the Posts list table. - * - * The filter is evaluated only for non-hierarchical post types. - * - * @since 2.8.0 - * - * @param array $actions An array of row action links. Defaults are - * 'Edit', 'Quick Edit', 'Restore, 'Trash', - * 'Delete Permanently', 'Preview', and 'View'. - * @param WP_Post $post The post object. - */ - $actions = apply_filters( 'post_row_actions', $actions, $post ); - } - - echo $this->row_actions( $actions ); + echo $this->handle_row_actions( $post, $column_name, $primary ); get_inline_data( $post ); echo ''; @@ -887,6 +834,7 @@ class WP_Posts_List_Table extends WP_List_Table { } else { _e( 'Last Modified' ); } + echo $this->handle_row_actions( $post, $column_name, $primary ); echo ''; break; @@ -898,7 +846,7 @@ class WP_Posts_List_Table extends WP_List_Table { $this->comments_bubble( $post->ID, $pending_comments ); ?> - + handle_row_actions( $post, $column_name, $primary ); ?> $post->post_type, 'author' => get_the_author_meta( 'ID' ) ), 'edit.php' )), get_the_author() ); + echo $this->handle_row_actions( $post, $column_name, $primary ); ?> handle_row_actions( $post, $column_name, $primary ); echo ''; break; } @@ -995,6 +945,7 @@ class WP_Posts_List_Table extends WP_List_Table { * @param int $post_id The current post ID. */ do_action( "manage_{$post->post_type}_posts_custom_column", $column_name, $post->ID ); + echo $this->handle_row_actions( $post, $column_name, $primary ); ?> post_type ); + $can_edit_post = current_user_can( 'edit_post', $post->ID ); + $actions = array(); + + if ( $can_edit_post && 'trash' != $post->post_status ) { + $actions['edit'] = '' . __( 'Edit' ) . ''; + $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit' ) . ''; + } + + if ( current_user_can( 'delete_post', $post->ID ) ) { + if ( 'trash' == $post->post_status ) + $actions['untrash'] = "ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore' ) . ""; + elseif ( EMPTY_TRASH_DAYS ) + $actions['trash'] = "" . __( 'Trash' ) . ""; + if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS ) + $actions['delete'] = "" . __( 'Delete Permanently' ) . ""; + } + + if ( $post_type_object->public ) { + if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) { + if ( $can_edit_post ) { + $preview_link = set_url_scheme( get_permalink( $post->ID ) ); + /** This filter is documented in wp-admin/includes/meta-boxes.php */ + $preview_link = apply_filters( 'preview_post_link', add_query_arg( 'preview', 'true', $preview_link ), $post ); + $actions['view'] = '' . __( 'Preview' ) . ''; + } + } elseif ( 'trash' != $post->post_status ) { + $actions['view'] = '' . __( 'View' ) . ''; + } + } + + if ( is_post_type_hierarchical( $post->post_type ) ) { + + /** + * Filter the array of row action links on the Pages list table. + * + * The filter is evaluated only for hierarchical post types. + * + * @since 2.8.0 + * + * @param array $actions An array of row action links. Defaults are + * 'Edit', 'Quick Edit', 'Restore, 'Trash', + * 'Delete Permanently', 'Preview', and 'View'. + * @param WP_Post $post The post object. + */ + $actions = apply_filters( 'page_row_actions', $actions, $post ); + } else { + + /** + * Filter the array of row action links on the Posts list table. + * + * The filter is evaluated only for non-hierarchical post types. + * + * @since 2.8.0 + * + * @param array $actions An array of row action links. Defaults are + * 'Edit', 'Quick Edit', 'Restore, 'Trash', + * 'Delete Permanently', 'Preview', and 'View'. + * @param WP_Post $post The post object. + */ + $actions = apply_filters( 'post_row_actions', $actions, $post ); + } + + return $this->row_actions( $actions ); + } + } + /** * Outputs the hidden row displayed when inline editing * diff --git a/wp-admin/includes/class-wp-terms-list-table.php b/wp-admin/includes/class-wp-terms-list-table.php index 25485bb8aa..046971b263 100644 --- a/wp-admin/includes/class-wp-terms-list-table.php +++ b/wp-admin/includes/class-wp-terms-list-table.php @@ -307,9 +307,6 @@ class WP_Terms_List_Table extends WP_List_Table { */ public function column_name( $tag ) { $taxonomy = $this->screen->taxonomy; - $tax = get_taxonomy( $taxonomy ); - - $default_term = get_option( 'default_' . $taxonomy ); $pad = str_repeat( '— ', max( 0, $this->level ) ); @@ -333,42 +330,6 @@ class WP_Terms_List_Table extends WP_List_Table { $out = '' . $name . '
'; - $actions = array(); - if ( current_user_can( $tax->cap->edit_terms ) ) { - $actions['edit'] = '' . __( 'Edit' ) . ''; - $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit' ) . ''; - } - if ( current_user_can( $tax->cap->delete_terms ) && $tag->term_id != $default_term ) - $actions['delete'] = "term_id ) . "'>" . __( 'Delete' ) . ""; - if ( $tax->public ) - $actions['view'] = '' . __( 'View' ) . ''; - - /** - * Filter the action links displayed for each term in the Tags list table. - * - * @since 2.8.0 - * @deprecated 3.0.0 Use {$taxonomy}_row_actions instead. - * - * @param array $actions An array of action links to be displayed. Default - * 'Edit', 'Quick Edit', 'Delete', and 'View'. - * @param object $tag Term object. - */ - $actions = apply_filters( 'tag_row_actions', $actions, $tag ); - - /** - * Filter the action links displayed for each term in the terms list table. - * - * The dynamic portion of the hook name, `$taxonomy`, refers to the taxonomy slug. - * - * @since 3.0.0 - * - * @param array $actions An array of action links to be displayed. Default - * 'Edit', 'Quick Edit', 'Delete', and 'View'. - * @param object $tag Term object. - */ - $actions = apply_filters( "{$taxonomy}_row_actions", $actions, $tag ); - - $out .= $this->row_actions( $actions ); $out .= '