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
21 changes: 20 additions & 1 deletion src/wp-admin/includes/class-wp-posts-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,8 @@ public function column_date( $post ) {
if ( '0000-00-00 00:00:00' === $post->post_date ) {
$t_time = __( 'Unpublished' );
$time_diff = 0;
} else {
} elseif ( 'publish' === $post->post_status || 'future' === $post->post_status ) {
// For published and scheduled posts, show the publication date and time.
$t_time = sprintf(
/* translators: 1: Post date, 2: Post time. */
__( '%1$s at %2$s' ),
Expand All @@ -1205,6 +1206,24 @@ public function column_date( $post ) {

$time = get_post_timestamp( $post );
$time_diff = time() - $time;
} else {
/*
* For all other statuses (draft, pending, etc.), the "Last Modified"
* label is shown below, so display the modified date and time to match.
* This avoids showing a future scheduled date labeled as "Last Modified",
* for example when a pending post has a future publication date.
*/
$t_time = sprintf(
/* translators: 1: Post modified date, 2: Post modified time. */
__( '%1$s at %2$s' ),
/* translators: Post modified date format. See https://www.php.net/manual/datetime.format.php */
get_the_modified_time( __( 'Y/m/d' ), $post ),
/* translators: Post modified time format. See https://www.php.net/manual/datetime.format.php */
get_the_modified_time( __( 'g:i a' ), $post )
);

$time = get_post_timestamp( $post, 'modified' );
$time_diff = time() - $time;
}

if ( 'publish' === $post->post_status ) {
Expand Down
107 changes: 107 additions & 0 deletions tests/phpunit/tests/admin/wpPostsListTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -330,4 +330,111 @@ public function test_get_views_should_return_views_by_default() {

$this->assertSame( $expected, $actual );
}

/**
* Ensures the Date column shows the modified date (not the future
* publication date) for a pending post scheduled in the future.
*
* @ticket 40860
*
* @covers WP_Posts_List_Table::column_date
*/
public function test_column_date_shows_modified_date_for_pending_scheduled_post() {
global $mode;

$mode = 'list';
$table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => 'edit-post' ) );

$future_gmt = gmdate( 'Y-m-d H:i:s', time() + WEEK_IN_SECONDS );
$now = current_time( 'mysql' );
$now_gmt = current_time( 'mysql', true );

$post_id = self::factory()->post->create(
array(
'post_status' => 'pending',
'post_date' => get_date_from_gmt( $future_gmt ),
'post_date_gmt' => $future_gmt,
)
);

// Force a modified date in the past (now), distinct from the future post_date.
global $wpdb;
$wpdb->update(
$wpdb->posts,
array(
'post_modified' => $now,
'post_modified_gmt' => $now_gmt,
),
array( 'ID' => $post_id )
);
clean_post_cache( $post_id );

$post = get_post( $post_id );

ob_start();
$table->column_date( $post );
$output = ob_get_clean();

$modified_date = get_the_modified_time( __( 'Y/m/d' ), $post );
$future_date = get_the_time( __( 'Y/m/d' ), $post );

$this->assertStringContainsString( 'Last Modified', $output, 'A pending post should display the "Last Modified" status.' );
$this->assertStringContainsString( $modified_date, $output, 'The Date column should display the post modified date.' );
$this->assertStringNotContainsString( $future_date, $output, 'The Date column should not display the future publication date for a pending post.' );
}

/**
* Ensures the Date column still shows the publication date for
* published and scheduled posts.
*
* @ticket 40860
*
* @covers WP_Posts_List_Table::column_date
*
* @dataProvider data_column_date_uses_publication_date_for_published_and_scheduled
*
* @param string $post_status The post status to test.
* @param string $expected_text The status label expected in the output.
*/
public function test_column_date_uses_publication_date_for_published_and_scheduled( $post_status, $expected_text ) {
global $mode;

$mode = 'list';
$table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => 'edit-post' ) );

if ( 'future' === $post_status ) {
$date_gmt = gmdate( 'Y-m-d H:i:s', time() + DAY_IN_SECONDS );
} else {
$date_gmt = gmdate( 'Y-m-d H:i:s', time() - DAY_IN_SECONDS );
}

$post_id = self::factory()->post->create(
array(
'post_status' => $post_status,
'post_date' => get_date_from_gmt( $date_gmt ),
'post_date_gmt' => $date_gmt,
)
);

$post = get_post( $post_id );

ob_start();
$table->column_date( $post );
$output = ob_get_clean();

$this->assertStringContainsString( $expected_text, $output, 'The Date column should display the expected status label.' );
$this->assertStringContainsString( get_the_time( __( 'Y/m/d' ), $post ), $output, 'The Date column should display the publication date.' );
}

/**
* Data provider.
*
* @return array[]
*/
public function data_column_date_uses_publication_date_for_published_and_scheduled() {
return array(
'published post' => array( 'publish', 'Published' ),
'scheduled post' => array( 'future', 'Scheduled' ),
);
}
}
Loading