@@ -71,7 +71,7 @@ class WP_On_This_Day {
7171 * @since 7.1.0
7272 * @var int
7373 */
74- const CACHE_VERSION = 7 ;
74+ const CACHE_VERSION = 8 ;
7575
7676 /**
7777 * Registers the dashboard widget and its supporting hooks and assets.
@@ -89,11 +89,13 @@ public static function register_widget() {
8989 add_action ( 'admin_notices ' , array ( __CLASS__ , 'render_window_updated_notice ' ) );
9090
9191 wp_enqueue_style ( 'on-this-day ' );
92+
93+ // Apply the date range label to the widget header via CSS.
9294 wp_add_inline_style (
9395 'on-this-day ' ,
9496 sprintf (
9597 '#dashboard_on_this_day{--otd-today:%s;} ' ,
96- wp_json_encode ( self ::get_window_label ( self ::get_window_days () ) )
98+ self :: esc_css_string ( self ::get_window_label ( self ::get_window_days () ) )
9799 )
98100 );
99101
@@ -172,7 +174,7 @@ public static function render_dashboard_widget() {
172174 * @return WP_Post[] Array of posts ordered by newest first.
173175 */
174176 public static function get_posts ( $ user_id , $ window_days = self ::DEFAULT_WINDOW_DAYS ) {
175- $ window_days = self ::sanitize_window_days ( $ window_days );
177+ $ window_days = self ::clamp_window_days ( $ window_days );
176178 $ year = (int ) current_time ( 'Y ' );
177179 $ date_query = array (
178180 'relation ' => 'AND ' ,
@@ -230,7 +232,7 @@ public static function handle_window_days_submission() {
230232 check_admin_referer ( 'set-on-this-day-window ' );
231233
232234 $ window_days = isset ( $ _POST ['on_this_day_window_days ' ] ) ? wp_unslash ( $ _POST ['on_this_day_window_days ' ] ) : self ::DEFAULT_WINDOW_DAYS ;
233- $ window_days = self ::sanitize_window_days ( $ window_days );
235+ $ window_days = self ::clamp_window_days ( $ window_days );
234236
235237 update_user_meta ( get_current_user_id (), self ::WINDOW_DAYS_META_KEY , $ window_days );
236238
@@ -292,7 +294,7 @@ public static function get_window_days( $user_id = 0 ) {
292294
293295 $ window_days = get_user_meta ( $ user_id , self ::WINDOW_DAYS_META_KEY , true );
294296
295- return self ::sanitize_window_days ( $ window_days );
297+ return self ::clamp_window_days ( $ window_days );
296298 }
297299
298300 /**
@@ -304,7 +306,7 @@ public static function get_window_days( $user_id = 0 ) {
304306 * @return string Date or date range label.
305307 */
306308 public static function get_window_label ( $ window_days ) {
307- $ window_days = self ::sanitize_window_days ( $ window_days );
309+ $ window_days = self ::clamp_window_days ( $ window_days );
308310 $ start = current_datetime ();
309311 $ start_label = wp_date ( 'F j ' , $ start ->getTimestamp (), $ start ->getTimezone () );
310312
@@ -324,21 +326,37 @@ public static function get_window_label( $window_days ) {
324326 }
325327
326328 /**
327- * Sanitizes the date window size.
329+ * Clamps the date window size to the supported range .
328330 *
329331 * @since 7.1.0
330332 *
331333 * @param mixed $window_days Raw window size.
332334 * @return int Number of days to include, between 1 and 7.
333335 */
334- protected static function sanitize_window_days ( $ window_days ) {
335- $ window_days = absint ( $ window_days );
336+ protected static function clamp_window_days ( $ window_days ) {
337+ return min (
338+ max ( (int ) $ window_days , self ::MIN_WINDOW_DAYS ),
339+ self ::MAX_WINDOW_DAYS
340+ );
341+ }
336342
337- if ( $ window_days < self ::MIN_WINDOW_DAYS || $ window_days > self ::MAX_WINDOW_DAYS ) {
338- return self ::DEFAULT_WINDOW_DAYS ;
339- }
343+ /**
344+ * Escapes a string for use as a quoted CSS string token.
345+ *
346+ * @since 7.1.0
347+ *
348+ * @param string $value String to escape.
349+ * @return string Quoted CSS string.
350+ */
351+ protected static function esc_css_string ( $ value ) {
352+ $ value = wp_check_invalid_utf8 ( (string ) $ value );
353+ $ value = str_replace (
354+ array ( '\\' , '" ' , "\n" , "\r" , "\f" ),
355+ array ( '\\\\' , '\" ' , '\a ' , '\d ' , '\c ' ),
356+ $ value
357+ );
340358
341- return $ window_days ;
359+ return ' " ' . $ value . ' " ' ;
342360 }
343361
344362 /**
@@ -372,6 +390,10 @@ protected static function get_window_date_query_clauses( $window_days ) {
372390 * @param int $window_days Number of days included in the date window.
373391 */
374392 protected static function render_empty_state ( $ window_days ) {
393+ $ window_days = self ::clamp_window_days ( $ window_days );
394+ $ start = current_datetime ();
395+ $ start_date = wp_date ( 'Y-m-d ' , $ start ->getTimestamp (), $ start ->getTimezone () );
396+ $ start_label = wp_date ( 'F j ' , $ start ->getTimestamp (), $ start ->getTimezone () );
375397 ?>
376398 <div class="on-this-day-empty">
377399 <div class="on-this-day-empty-icon" aria-hidden="true">
@@ -381,19 +403,41 @@ protected static function render_empty_state( $window_days ) {
381403 <circle cx="12" cy="15" r="1.5" fill="currentColor" stroke="none"></circle>
382404 </svg>
383405 </div>
384- <h3 class="on-this-day-empty-title"><?php _e ( 'Your story starts here. ' ); ?> </h3>
406+ <h3 class="on-this-day-empty-title"><?php esc_html_e ( 'Your story starts here. ' ); ?> </h3>
385407 <p class="on-this-day-empty-text">
386408 <?php
387- printf (
388- /* translators: %s: Current date or date range, e.g. "April 22" or "April 22 - April 28". */
389- __ ( ' You haven’t published anything on %s in previous years. Write something today and check back next year! ' ),
390- ' <strong> ' . esc_html ( self :: get_window_label ( $ window_days ) ) . ' </strong> '
409+ $ start_time = sprintf (
410+ ' <time datetime="%1$s">%2$s</time> ' ,
411+ esc_attr ( $ start_date ),
412+ esc_html ( $ start_label )
391413 );
414+
415+ if ( self ::MIN_WINDOW_DAYS === $ window_days ) {
416+ printf (
417+ /* translators: %s: Current date, e.g. "April 22". */
418+ esc_html__ ( 'You haven \'t published anything on %s in previous years. Write something today and check back next year! ' ),
419+ '<strong> ' . $ start_time . '</strong> '
420+ );
421+ } else {
422+ $ end = $ start ->modify ( '+ ' . ( $ window_days - 1 ) . ' days ' );
423+ $ end_time = sprintf (
424+ '<time datetime="%1$s">%2$s</time> ' ,
425+ esc_attr ( wp_date ( 'Y-m-d ' , $ end ->getTimestamp (), $ end ->getTimezone () ) ),
426+ esc_html ( wp_date ( 'F j ' , $ end ->getTimestamp (), $ end ->getTimezone () ) )
427+ );
428+
429+ printf (
430+ /* translators: 1: Start date, 2: End date. */
431+ esc_html__ ( 'You haven \'t published anything between %1$s and %2$s in previous years. Write something today and check back next year! ' ),
432+ '<strong> ' . $ start_time . '</strong> ' ,
433+ '<strong> ' . $ end_time . '</strong> '
434+ );
435+ }
392436 ?>
393437 </p>
394438 <p class="on-this-day-empty-cta">
395439 <a href="<?php echo esc_url ( admin_url ( 'post-new.php ' ) ); ?> " class="button button-primary">
396- <?php _e ( 'Write a new post ' ); ?>
440+ <?php esc_html_e ( 'Write a new post ' ); ?>
397441 </a>
398442 </p>
399443 </div>
@@ -553,17 +597,17 @@ protected static function render_post( $post, $window_days ) {
553597
554598 <?php if ( $ is_private ) : ?>
555599 <span class="on-this-day-post-sep" aria-hidden="true">·</span>
556- <span class="on-this-day-post-private"><?php _e ( 'Private ' ); ?> </span>
600+ <span class="on-this-day-post-private"><?php esc_html_e ( 'Private ' ); ?> </span>
557601 <?php endif ; ?>
558602 </div>
559603
560604 <?php if ( $ edit_link || ( 'publish ' === $ status && $ view_link ) ) : ?>
561605 <div class="on-this-day-post-actions">
562606 <?php if ( $ edit_link ) : ?>
563- <a class="on-this-day-post-action button button-secondary button-compact" href="<?php echo esc_url ( $ edit_link ); ?> "><?php _e ( 'Edit ' ); ?> </a>
607+ <a class="on-this-day-post-action button button-secondary button-compact" href="<?php echo esc_url ( $ edit_link ); ?> "><?php esc_html_e ( 'Edit ' ); ?> </a>
564608 <?php endif ; ?>
565609 <?php if ( 'publish ' === $ status && $ view_link ) : ?>
566- <a class="on-this-day-post-action button-link is-compact" href="<?php echo esc_url ( $ view_link ); ?> " target="_blank" rel="noopener"><?php _e ( 'View ' ); ?> </a>
610+ <a class="on-this-day-post-action button-link is-compact" href="<?php echo esc_url ( $ view_link ); ?> " target="_blank" rel="noopener"><?php esc_html_e ( 'View ' ); ?> </a>
567611 <?php endif ; ?>
568612 </div>
569613 <?php endif ; ?>
@@ -585,7 +629,7 @@ protected static function render_window_control( $window_days ) {
585629 <?php wp_nonce_field ( 'set-on-this-day-window ' , '_wpnonce ' , false ); ?>
586630 <input type="hidden" name="action" value="set_on_this_day_window" />
587631 <div class="on-this-day-window-control">
588- <span class="on-this-day-window-scale" aria-hidden="true"><?php _e ( '1 day ' ); ?> </span>
632+ <span class="on-this-day-window-scale" aria-hidden="true"><?php esc_html_e ( '1 day ' ); ?> </span>
589633 <input
590634 type="range"
591635 id="on-this-day-window-days"
@@ -598,7 +642,7 @@ protected static function render_window_control( $window_days ) {
598642 aria-label="<?php esc_attr_e ( 'Duration ' ); ?> "
599643 onchange="this.form.submit();"
600644 />
601- <span class="on-this-day-window-scale" aria-hidden="true"><?php _e ( '7 days ' ); ?> </span>
645+ <span class="on-this-day-window-scale" aria-hidden="true"><?php esc_html_e ( '7 days ' ); ?> </span>
602646 </div>
603647 </form>
604648 <?php
0 commit comments