Skip to content

Commit 536aa68

Browse files
authored
Merge branch 'WordPress:trunk' into trunk
2 parents 6a67e45 + e8f519d commit 536aa68

4 files changed

Lines changed: 607 additions & 0 deletions

File tree

src/wp-admin/css/dashboard.css

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,35 @@ body #dashboard-widgets .postbox form .submit {
10171017
top: 0;
10181018
}
10191019

1020+
/* On This Day dashboard widget */
1021+
1022+
#wp_dashboard_on_this_day h3 {
1023+
font-weight: 600;
1024+
}
1025+
1026+
#wp_dashboard_on_this_day li {
1027+
margin: 0;
1028+
padding: 0;
1029+
}
1030+
1031+
#wp_dashboard_on_this_day ul ul {
1032+
margin: 0 0 0 18px;
1033+
padding: 0;
1034+
list-style: disc;
1035+
}
1036+
1037+
#wp_dashboard_on_this_day ul ul li + li {
1038+
margin-top: 6px;
1039+
}
1040+
1041+
#wp_dashboard_on_this_day .wp-on-this-day-widget > ul > li + li {
1042+
margin-top: 16px;
1043+
}
1044+
1045+
#wp_dashboard_on_this_day .wp-on-this-day-post-author {
1046+
color: #646970;
1047+
}
1048+
10201049
/* Browse happy box */
10211050

10221051
#dashboard-widgets #dashboard_browser_nag.postbox .inside {
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
<?php
2+
/**
3+
* WordPress Dashboard "On This Day" widget.
4+
*
5+
* @package WordPress
6+
* @subpackage Administration
7+
* @since 7.1.0
8+
*/
9+
10+
/**
11+
* Registers the On This Day dashboard widget.
12+
*
13+
* Designed to be the single entry point called from the dashboard setup
14+
* routine. The widget is always registered so that it remains available in
15+
* Screen Options and keeps its user-customized position. When there are no
16+
* matching posts, a marker class is added to the postbox so the widget can be
17+
* hidden with CSS.
18+
*
19+
* @since 7.1.0
20+
*/
21+
function wp_dashboard_on_this_day_setup() {
22+
add_filter( 'postbox_classes_dashboard_wp_dashboard_on_this_day', 'wp_dashboard_on_this_day_postbox_classes' );
23+
24+
wp_add_dashboard_widget(
25+
'wp_dashboard_on_this_day',
26+
__( 'On This Day' ),
27+
'wp_dashboard_on_this_day'
28+
);
29+
}
30+
31+
/**
32+
* Hides the On This Day postbox when there are no posts to show.
33+
*
34+
* Adds the core `hidden` class so the widget stays registered — preserving its
35+
* Screen Options entry and user-customized position — while being hidden when
36+
* empty. A user can still reveal it via Screen Options, in which case the
37+
* placeholder message is shown.
38+
*
39+
* @since 7.1.0
40+
*
41+
* @param string[] $classes An array of postbox classes.
42+
* @return string[] Filtered postbox classes.
43+
*/
44+
function wp_dashboard_on_this_day_postbox_classes( $classes ) {
45+
if ( empty( wp_dashboard_on_this_day_get_posts() ) ) {
46+
$classes[] = 'hidden';
47+
}
48+
49+
return $classes;
50+
}
51+
52+
/**
53+
* Renders the On This Day dashboard widget.
54+
*
55+
* Outputs the matching posts grouped by publication year, newest year first.
56+
*
57+
* @since 7.1.0
58+
*/
59+
function wp_dashboard_on_this_day() {
60+
$posts = wp_dashboard_on_this_day_get_posts();
61+
62+
if ( empty( $posts ) ) {
63+
// Placeholder shown when a user reveals the hidden widget via Screen
64+
// Options on a day with no matching posts.
65+
echo '<p>' . esc_html__( 'No posts were published on this day in previous years.' ) . '</p>';
66+
return;
67+
}
68+
69+
$posts_by_year = array();
70+
$post_count = count( $posts );
71+
72+
foreach ( $posts as $post ) {
73+
$year = get_the_date( 'Y', $post );
74+
75+
if ( ! isset( $posts_by_year[ $year ] ) ) {
76+
$posts_by_year[ $year ] = array();
77+
}
78+
79+
$posts_by_year[ $year ][] = $post;
80+
}
81+
82+
/* translators: Date format for the On This Day widget date, without year. See https://www.php.net/manual/datetime.format.php */
83+
$date = '<strong>' . esc_html( wp_date( _x( 'F jS', 'on this day date format' ) ) ) . '</strong>';
84+
?>
85+
<div class="wp-on-this-day-widget">
86+
<p>
87+
<?php
88+
if ( 1 === $post_count ) {
89+
printf(
90+
/* translators: %s: Date, without year. */
91+
esc_html__( 'One post has been published on %s:' ),
92+
$date // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Date is escaped above.
93+
);
94+
} else {
95+
printf(
96+
esc_html(
97+
/* translators: 1: Number of posts, 2: Date, without year. */
98+
_n(
99+
'%1$s post has been published on %2$s:',
100+
'%1$s posts have been published on %2$s:',
101+
$post_count
102+
)
103+
),
104+
esc_html( number_format_i18n( $post_count ) ),
105+
$date // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Date is escaped above.
106+
);
107+
}
108+
?>
109+
</p>
110+
<ul>
111+
<?php foreach ( $posts_by_year as $year => $year_posts ) : ?>
112+
<li>
113+
<h3><?php echo esc_html( $year ); ?></h3>
114+
<ul>
115+
<?php foreach ( $year_posts as $year_post ) : ?>
116+
<?php
117+
$title = get_the_title( $year_post );
118+
119+
if ( '' === trim( $title ) ) {
120+
$title = __( '(no title)' );
121+
}
122+
123+
$author_id = (int) $year_post->post_author;
124+
$author_name = $author_id > 0 ? (string) get_the_author_meta( 'display_name', $author_id ) : '';
125+
$show_author = '' !== trim( $author_name ) && get_current_user_id() !== $author_id;
126+
?>
127+
<li>
128+
<a href="<?php echo esc_url( get_permalink( $year_post ) ); ?>"><?php echo esc_html( $title ); ?></a>
129+
<?php if ( $show_author ) : ?>
130+
<?php
131+
echo '<span class="wp-on-this-day-post-author">' . esc_html(
132+
sprintf(
133+
/* translators: %s: Post author's display name. */
134+
__( 'by %s' ),
135+
$author_name
136+
)
137+
) . '</span>';
138+
?>
139+
<?php endif; ?>
140+
</li>
141+
<?php endforeach; ?>
142+
</ul>
143+
</li>
144+
<?php endforeach; ?>
145+
</ul>
146+
</div>
147+
<?php
148+
}
149+
150+
/**
151+
* Retrieves published posts from all authors that were published on this
152+
* calendar day in previous years.
153+
*
154+
* The date constraint matches today's month and day, combined with a
155+
* `before` clause anchored to January 1 of the current year. Up to ten posts
156+
* are returned; use the `wp_dashboard_on_this_day_query_args` filter to change
157+
* the limit. Results are cached by WP_Query's native query caching.
158+
*
159+
* @since 7.1.0
160+
*
161+
* @return WP_Post[] Array of posts ordered by newest first.
162+
*/
163+
function wp_dashboard_on_this_day_get_posts() {
164+
$today = current_datetime();
165+
$year = (int) $today->format( 'Y' );
166+
$date_query = array(
167+
'relation' => 'AND',
168+
array(
169+
'before' => array( 'year' => $year ),
170+
),
171+
_wp_dashboard_on_this_day_date_query_clause( $today ),
172+
);
173+
174+
$args = array(
175+
'post_type' => 'post',
176+
'post_status' => array( 'publish' ),
177+
'posts_per_page' => 10,
178+
'ignore_sticky_posts' => true,
179+
'orderby' => 'date',
180+
'order' => 'DESC',
181+
'no_found_rows' => true,
182+
'update_post_term_cache' => false,
183+
'update_post_meta_cache' => false,
184+
'date_query' => $date_query,
185+
);
186+
187+
/**
188+
* Filters the arguments used to query posts for the On This Day dashboard widget.
189+
*
190+
* @since 7.1.0
191+
*
192+
* @param array $args WP_Query arguments.
193+
*/
194+
$args = apply_filters( 'wp_dashboard_on_this_day_query_args', $args );
195+
196+
$query = new WP_Query( $args );
197+
198+
return $query->posts;
199+
}
200+
201+
/**
202+
* Builds the date query clause for today's anniversary date.
203+
*
204+
* On February 28 in a non-leap year, February 29 posts are included so
205+
* leap-day anniversaries still appear.
206+
*
207+
* @since 7.1.0
208+
* @access private
209+
*
210+
* @param DateTimeInterface $date Date to build the clause for.
211+
* @return array Date query clause.
212+
*/
213+
function _wp_dashboard_on_this_day_date_query_clause( $date ) {
214+
$month = (int) $date->format( 'm' );
215+
$day = (int) $date->format( 'd' );
216+
$clause = array(
217+
'month' => $month,
218+
'day' => $day,
219+
);
220+
221+
// Display leap day posts on Feb 28 in non leap years.
222+
if (
223+
28 === $day
224+
&& 2 === $month
225+
&& false === (bool) $date->format( 'L' )
226+
) {
227+
$clause = array(
228+
'relation' => 'OR',
229+
$clause,
230+
array(
231+
'month' => 2,
232+
'day' => 29,
233+
),
234+
);
235+
}
236+
237+
return $clause;
238+
}

src/wp-admin/includes/dashboard.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ function wp_dashboard_setup() {
8888
wp_add_dashboard_widget( 'dashboard_quick_press', $quick_draft_title, 'wp_dashboard_quick_press' );
8989
}
9090

91+
// On This Day.
92+
if ( ! function_exists( 'wp_dashboard_on_this_day_setup' ) ) {
93+
require_once ABSPATH . 'wp-admin/includes/dashboard-on-this-day.php';
94+
}
95+
96+
wp_dashboard_on_this_day_setup();
97+
9198
// WordPress Events and News.
9299
wp_add_dashboard_widget( 'dashboard_primary', __( 'WordPress Events and News' ), 'wp_dashboard_events_news' );
93100

0 commit comments

Comments
 (0)