Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions src/wp-admin/includes/class-wp-posts-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,21 +83,25 @@ public function __construct( $args = array() ) {
$post_type = $this->screen->post_type;
$post_type_object = get_post_type_object( $post_type );

$exclude_states = get_post_stati(
$include_states = get_post_stati(
array(
'show_in_admin_all_list' => false,
'show_in_admin_all_list' => true,
)
);

/*
* List the statuses to count rather than the ones to skip, so the database can
* use the post_author part of the type_status_author index and only read the
* rows of the current user.
*/
$this->user_posts_count = (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT( 1 )
FROM $wpdb->posts
WHERE post_type = %s
AND post_status NOT IN ( '" . implode( "','", $exclude_states ) . "' )
AND post_author = %d",
$post_type,
get_current_user_id()
AND post_status IN ( " . implode( ', ', array_fill( 0, count( $include_states ), '%s' ) ) . ' )
AND post_author = %d',
array_merge( array( $post_type ), array_values( $include_states ), array( get_current_user_id() ) )
)
);

Expand Down
45 changes: 45 additions & 0 deletions tests/phpunit/tests/admin/wpPostsListTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -720,4 +720,49 @@ public function test_checkbox_label_includes_no_title_excerpt() {

$this->assertStringContainsString( 'Select (no title) Hello world example excerpt.', $output );
}

/**
* Tests that the "Mine" count only counts the current user's posts in statuses shown in the All list.
*
* @ticket 58593
*
* @covers WP_Posts_List_Table::__construct
*/
public function test_user_posts_count_counts_statuses_shown_in_all_list() {
$user_id = self::factory()->user->create( array( 'role' => 'editor' ) );
$other_id = self::factory()->user->create( array( 'role' => 'editor' ) );

foreach ( array( 'publish', 'publish', 'draft', 'pending', 'private', 'future', 'trash', 'auto-draft' ) as $status ) {
self::factory()->post->create(
array(
'post_author' => $user_id,
'post_status' => $status,
'post_date' => 'future' === $status ? gmdate( 'Y-m-d H:i:s', time() + DAY_IN_SECONDS ) : gmdate( 'Y-m-d H:i:s' ),
)
);
}
self::factory()->post->create_many( 3, array( 'post_author' => $other_id ) );

wp_set_current_user( $user_id );

$queries = array();
$logger = static function ( $query ) use ( &$queries ) {
if ( str_contains( $query, 'COUNT( 1 )' ) && str_contains( $query, 'post_author' ) ) {
$queries[] = $query;
}
return $query;
};
add_filter( 'query', $logger );
$table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => 'edit-post' ) );
remove_filter( 'query', $logger );

$count = new ReflectionProperty( $table, 'user_posts_count' );
if ( PHP_VERSION_ID < 80100 ) {
$count->setAccessible( true );
}

$this->assertSame( 6, $count->getValue( $table ), 'Only posts in statuses shown in the All list should be counted.' );
$this->assertCount( 1, $queries, 'The count should run a single query.' );
$this->assertStringNotContainsString( 'NOT IN', $queries[0], 'The statuses to count should be listed so the post_author index part can be used.' );
}
}
Loading