diff --git a/src/wp-admin/css/dashboard.css b/src/wp-admin/css/dashboard.css
index 860fe9696b873..bad19e5a82e3d 100644
--- a/src/wp-admin/css/dashboard.css
+++ b/src/wp-admin/css/dashboard.css
@@ -1054,6 +1054,11 @@ body #dashboard-widgets .postbox form .submit {
color: #646970;
}
+/* Align the pagination with the widget content instead of the list table default. */
+#wp_dashboard_on_this_day .tablenav-pages {
+ float: none;
+}
+
/* Browse happy box */
#dashboard-widgets #dashboard_browser_nag.postbox .inside {
diff --git a/src/wp-admin/includes/dashboard-on-this-day.php b/src/wp-admin/includes/dashboard-on-this-day.php
index e9557a60720c8..d88824e6e840d 100644
--- a/src/wp-admin/includes/dashboard-on-this-day.php
+++ b/src/wp-admin/includes/dashboard-on-this-day.php
@@ -53,11 +53,28 @@ function wp_dashboard_on_this_day_postbox_classes( $classes ) {
* Renders the On This Day dashboard widget.
*
* Outputs the matching posts grouped by publication year, newest year first.
+ * Posts are paginated, with the requested page read from the
+ * `on-this-day-page` query argument.
*
* @since 7.1.0
*/
function wp_dashboard_on_this_day() {
- $posts = wp_dashboard_on_this_day_get_posts();
+ $current_page = isset( $_GET['on-this-day-page'] ) ? max( 1, absint( $_GET['on-this-day-page'] ) ) : 1;
+ $query = _wp_dashboard_on_this_day_get_posts_query(
+ array(
+ 'paged' => $current_page,
+ )
+ );
+
+ // A page number past the last page falls back to the first page.
+ if ( empty( $query->posts ) && $current_page > 1 ) {
+ $current_page = 1;
+ $query = _wp_dashboard_on_this_day_get_posts_query();
+ }
+
+ $posts = $query->posts;
+ $post_count = (int) $query->found_posts;
+ $total_pages = (int) $query->max_num_pages;
if ( empty( $posts ) ) {
// Placeholder shown when a user reveals the hidden widget via Screen
@@ -66,19 +83,6 @@ function wp_dashboard_on_this_day() {
return;
}
- $posts_by_year = array();
- $post_count = count( $posts );
-
- foreach ( $posts as $post ) {
- $year = get_the_date( 'Y', $post );
-
- if ( ! isset( $posts_by_year[ $year ] ) ) {
- $posts_by_year[ $year ] = array();
- }
-
- $posts_by_year[ $year ][] = $post;
- }
-
/* translators: Date format for the On This Day widget date, without year. See https://www.php.net/manual/datetime.format.php */
$date = '' . esc_html( wp_date( _x( 'F jS', 'on this day date format' ) ) ) . '';
?>
@@ -107,60 +111,135 @@ function wp_dashboard_on_this_day() {
}
?>
-
- $year_posts ) : ?>
- -
-
-
+ 1 ) :
+ // The fragment scrolls back to the widget once the dashboard reloads.
+ $page_url = admin_url( 'index.php' ) . '#wp_dashboard_on_this_day';
- if ( '' === trim( $title ) ) {
- $title = __( '(no title)' );
+ /*
+ * The page field and total page count are combined with the same
+ * string list tables use, so the order can be translated.
+ */
+ $paging_text = sprintf(
+ /* translators: 1: Current page number field, 2: Total number of pages. */
+ _x( '%1$s of %2$s', 'paging' ),
+ sprintf(
+ '',
+ esc_attr( $current_page ),
+ strlen( (string) $total_pages )
+ ),
+ '' . esc_html( number_format_i18n( $total_pages ) ) . ''
+ );
+ ?>
+
+
+
+ ID ) && ! post_password_required( $year_post ) ) {
- $excerpt = get_the_excerpt( $year_post );
+/**
+ * Renders On This Day posts grouped by publication year.
+ *
+ * @since 7.1.0
+ * @access private
+ *
+ * @param WP_Post[] $posts Posts to render.
+ */
+function _wp_dashboard_on_this_day_render_posts( $posts ) {
+ $posts_by_year = array();
- if ( is_string( $excerpt ) && '' !== $excerpt ) {
- $no_title_excerpt = wp_trim_words( $excerpt, 15 );
- }
- }
+ foreach ( $posts as $post ) {
+ $year = get_the_date( 'Y', $post );
+
+ if ( ! isset( $posts_by_year[ $year ] ) ) {
+ $posts_by_year[ $year ] = array();
+ }
+
+ $posts_by_year[ $year ][] = $post;
+ }
+
+ foreach ( $posts_by_year as $year => $year_posts ) {
+ ?>
+
-
+
+
+
+ ID ) && ! post_password_required( $year_post ) ) {
+ $excerpt = get_the_excerpt( $year_post );
+
+ if ( is_string( $excerpt ) && '' !== $excerpt ) {
+ $no_title_excerpt = wp_trim_words( $excerpt, 15 );
}
+ }
+ }
- $author_id = (int) $year_post->post_author;
- $author_name = $author_id > 0 ? (string) get_the_author_meta( 'display_name', $author_id ) : '';
- $show_author = '' !== trim( $author_name ) && get_current_user_id() !== $author_id;
+ $author_id = (int) $year_post->post_author;
+ $author_name = $author_id > 0 ? (string) get_the_author_meta( 'display_name', $author_id ) : '';
+ $show_author = '' !== trim( $author_name ) && get_current_user_id() !== $author_id;
+ ?>
+ -
+
+
+
-
-
-
-
-
-
-
- ' . esc_html(
- sprintf(
- /* translators: %s: Post author's display name. */
- __( 'by %s' ),
- $author_name
- )
- ) . '';
- ?>
-
-
-
-
-
-
-
-
-
+
+ ' . esc_html(
+ sprintf(
+ /* translators: %s: Post author's display name. */
+ __( 'by %s' ),
+ $author_name
+ )
+ ) . '';
+ ?>
+
+
+
+
+
+ true,
+ )
+ );
+
+ return $query->posts;
+}
+
+/**
+ * Retrieves the WP_Query for On This Day posts.
+ *
+ * @since 7.1.0
+ * @access private
+ *
+ * @param array $query_args Additional query arguments.
+ * @return WP_Query Query for matching posts.
+ */
+function _wp_dashboard_on_this_day_get_posts_query( $query_args = array() ) {
$today = current_datetime();
$year = (int) $today->format( 'Y' );
$date_query = array(
@@ -187,17 +285,20 @@ function wp_dashboard_on_this_day_get_posts() {
_wp_dashboard_on_this_day_date_query_clause( $today ),
);
- $args = array(
- 'post_type' => 'post',
- 'post_status' => array( 'publish' ),
- 'posts_per_page' => 10,
- 'ignore_sticky_posts' => true,
- 'orderby' => 'date',
- 'order' => 'DESC',
- 'no_found_rows' => true,
- 'update_post_term_cache' => false,
- 'update_post_meta_cache' => false,
- 'date_query' => $date_query,
+ $args = array_merge(
+ array(
+ 'post_type' => 'post',
+ 'post_status' => array( 'publish' ),
+ 'posts_per_page' => 10,
+ 'ignore_sticky_posts' => true,
+ 'orderby' => 'date',
+ 'order' => 'DESC',
+ 'no_found_rows' => false,
+ 'update_post_term_cache' => false,
+ 'update_post_meta_cache' => false,
+ 'date_query' => $date_query,
+ ),
+ $query_args
);
/**
@@ -209,9 +310,7 @@ function wp_dashboard_on_this_day_get_posts() {
*/
$args = apply_filters( 'wp_dashboard_on_this_day_query_args', $args );
- $query = new WP_Query( $args );
-
- return $query->posts;
+ return new WP_Query( $args );
}
/**
diff --git a/tests/phpunit/tests/admin/wpDashboardOnThisDay.php b/tests/phpunit/tests/admin/wpDashboardOnThisDay.php
index a2b1cdbfaff1f..88b5b387b7ba1 100644
--- a/tests/phpunit/tests/admin/wpDashboardOnThisDay.php
+++ b/tests/phpunit/tests/admin/wpDashboardOnThisDay.php
@@ -34,6 +34,7 @@ public static function wpTearDownAfterClass() {
public function tear_down() {
unset( $GLOBALS['wp_meta_boxes']['dashboard'] );
+ unset( $_GET['on-this-day-page'] );
parent::tear_down();
}
@@ -499,13 +500,15 @@ public function test_widget_hides_untitled_post_excerpt_for_password_protected_p
}
/**
+ * @ticket 65116
+ *
* @covers ::wp_dashboard_on_this_day
- * @covers ::wp_dashboard_on_this_day_get_posts
+ * @covers ::_wp_dashboard_on_this_day_get_posts_query
*/
- public function test_widget_limits_posts_to_ten() {
+ public function test_widget_paginates_posts() {
wp_set_current_user( self::$user_id );
- for ( $years_ago = 1; $years_ago <= 11; $years_ago++ ) {
+ for ( $years_ago = 1; $years_ago <= 22; $years_ago++ ) {
$this->create_matching_post( self::$user_id, 'Anniversary post ' . $years_ago, $years_ago );
}
@@ -513,10 +516,67 @@ public function test_widget_limits_posts_to_ten() {
wp_dashboard_on_this_day();
$output = ob_get_clean();
- $this->assertStringContainsString( '10 posts have been published on ' . wp_date( 'F jS' ) . ':', $output );
+ $this->assertStringContainsString( '22 posts have been published on ' . wp_date( 'F jS' ) . ':', $output );
$this->assertMatchesRegularExpression( '/>\s*Anniversary post 1\s*<\/a>/', $output );
$this->assertMatchesRegularExpression( '/>\s*Anniversary post 10\s*<\/a>/', $output );
$this->assertStringNotContainsString( 'Anniversary post 11', $output );
+ $this->assertStringContainsString( '