Commit c812ac0090 for wordpress.org
commit c812ac00908a0dbdcf0bb275fe281392f014dce0
Author: westonruter <westonruter@git.wordpress.org>
Date: Fri Nov 13 23:32:54 2026 +0000
Date/Time: Pass only valid weekday numbers to `WP_Locale`.
The PHP warning that `WP_Locale::get_weekday()` raises for an out-of-range weekday is already useful feedback, so no runtime validation is added. Instead, its parameter type is narrowed for static analysis, along with those of `get_month_genitive()` and `get_meridiem()`. The core callers that the narrower types exposed are fixed. The parameter of `get_month()` is left as is, since in r59870 it was made to tolerate unvalidated input.
The fixes change behavior in a few edge cases. A post whose date cannot be parsed is no longer labeled as Sunday by `the_weekday()` and `the_weekday_date()`; both filters still run. A numeric timestamp that passes the `is_numeric()` check but cannot be parsed now makes `wp_date()` return false instead of causing a fatal error. The calendar keeps wrapping an out-of-range `start_of_week` value modulo 7, so a value of 7 still means Sunday, consistent with the weekly archive query.
To let the weekday type flow through, the return type of `get_post_time()` is narrowed per date format, and the `get_post_time` filter now documents that its value must match what the format produces.
Developed in https://github.com/WordPress/wordpress-develop/pull/14827.
Follow-up to r36292, r45379, r45901, r59870, r63941.
Props raulsalvat, westonruter, shishir1, swissspidy.
See #34688.
Fixes #64522.
Built from https://develop.svn.wordpress.org/trunk@65525
git-svn-id: http://core.svn.wordpress.org/trunk@64598 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/class-wp-locale.php b/wp-includes/class-wp-locale.php
index 3671c1b279..cd022fdaf9 100644
--- a/wp-includes/class-wp-locale.php
+++ b/wp-includes/class-wp-locale.php
@@ -264,6 +264,8 @@ class WP_Locale {
*
* @param int $weekday_number 0 for Sunday through 6 Saturday.
* @return string Full translated weekday.
+ *
+ * @phpstan-param int<0, 6> $weekday_number
*/
public function get_weekday( $weekday_number ) {
return $this->weekday[ $weekday_number ];
@@ -355,6 +357,8 @@ class WP_Locale {
*
* @param string|int $month_number '01' through '12'.
* @return string Translated genitive month name.
+ *
+ * @phpstan-param int<1, 12>|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|'10'|'11'|'12'|'01'|'02'|'03'|'04'|'05'|'06'|'07'|'08'|'09' $month_number
*/
public function get_month_genitive( $month_number ) {
return $this->month_genitive[ zeroise( $month_number, 2 ) ];
@@ -369,6 +373,8 @@ class WP_Locale {
*
* @param string $meridiem Either 'am', 'pm', 'AM', or 'PM'. Not translated version.
* @return string Translated version
+ *
+ * @phpstan-param 'am'|'pm'|'AM'|'PM' $meridiem
*/
public function get_meridiem( $meridiem ) {
return $this->meridiem[ $meridiem ];
diff --git a/wp-includes/functions.php b/wp-includes/functions.php
index 10449deeba..d9927baffb 100644
--- a/wp-includes/functions.php
+++ b/wp-includes/functions.php
@@ -258,6 +258,11 @@ function wp_date( $format, $timestamp = null, $timezone = null ) {
}
$datetime = date_create( '@' . $timestamp );
+
+ if ( false === $datetime ) {
+ return false;
+ }
+
$datetime->setTimezone( $timezone );
if ( empty( $wp_locale->month ) || empty( $wp_locale->weekday ) ) {
@@ -269,7 +274,7 @@ function wp_date( $format, $timestamp = null, $timezone = null ) {
$new_format = '';
$format_length = strlen( $format );
$month = $wp_locale->get_month( $datetime->format( 'm' ) );
- $weekday = $wp_locale->get_weekday( $datetime->format( 'w' ) );
+ $weekday = $wp_locale->get_weekday( (int) $datetime->format( 'w' ) );
for ( $i = 0; $i < $format_length; $i++ ) {
switch ( $format[ $i ] ) {
diff --git a/wp-includes/general-template.php b/wp-includes/general-template.php
index 4c6945a626..bfb400cbda 100644
--- a/wp-includes/general-template.php
+++ b/wp-includes/general-template.php
@@ -2666,7 +2666,7 @@ function get_calendar( $args = array() ) {
}
// week_begins = 0 stands for Sunday.
- $week_begins = (int) get_option( 'start_of_week' );
+ $week_begins = absint( get_option( 'start_of_week' ) ) % 7;
// Read the current date.
list( $current_year, $current_month, $current_day ) = array_map( 'intval', explode( '-', current_time( 'Y-m-j' ) ) );
@@ -3181,7 +3181,21 @@ function get_the_time( $format = '', $post = null ) {
* @return string|int|false Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
* False on failure.
*
- * @phpstan-return ( $format is 'U'|'G' ? int|false : string|false )
+ * @phpstan-return (
+ * $format is 'U'|'G' ? int|false : (
+ * $format is 'w' ? '0'|'1'|'2'|'3'|'4'|'5'|'6'|false : (
+ * $format is 'N' ? '1'|'2'|'3'|'4'|'5'|'6'|'7'|false : (
+ * $format is 'L'|'I' ? '0'|'1'|false : (
+ * $format is 't' ? '28'|'29'|'30'|'31'|false : (
+ * $format is 'm'|'h' ? '01'|'02'|'03'|'04'|'05'|'06'|'07'|'08'|'09'|'10'|'11'|'12'|false : (
+ * $format is 'n'|'g' ? '1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|'10'|'11'|'12'|false : (
+ * $format is 'H' ? '00'|'01'|'02'|'03'|'04'|'05'|'06'|'07'|'08'|'09'|'10'|'11'|'12'|'13'|'14'|'15'|'16'|'17'|'18'|'19'|'20'|'21'|'22'|'23'|false : (
+ * $format is 'd' ? '01'|'02'|'03'|'04'|'05'|'06'|'07'|'08'|'09'|'10'|'11'|'12'|'13'|'14'|'15'|'16'|'17'|'18'|'19'|'20'|'21'|'22'|'23'|'24'|'25'|'26'|'27'|'28'|'29'|'30'|'31'|false : (
+ * $format is 'j' ? '1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|'10'|'11'|'12'|'13'|'14'|'15'|'16'|'17'|'18'|'19'|'20'|'21'|'22'|'23'|'24'|'25'|'26'|'27'|'28'|'29'|'30'|'31'|false : (
+ * $format is 'z'|'W'|'o'|'Y'|'y'|'B'|'i'|'s'|'u'|'v'|'Z' ? numeric-string|false :
+ * string|false
+ * ) ) ) ) ) ) ) ) ) )
+ * )
*/
function get_post_time( $format = 'U', $gmt = false, $post = null, $translate = false ) {
$post = get_post( $post );
@@ -3217,8 +3231,14 @@ function get_post_time( $format = 'U', $gmt = false, $post = null, $translate =
/**
* Filters the localized time of the post.
*
+ * The filtered value should match the type and values that `$format` produces,
+ * for example, an integer for 'U' or 'G', or a numeric string from '0' to '6' for 'w'.
+ *
* @since 2.6.0
*
+ * @see get_post_time()
+ * @link https://www.php.net/manual/en/datetime.format.php
+ *
* @param string|int $time Formatted date string or Unix timestamp if `$format` is 'U' or 'G'.
* @param string $format Format to use for retrieving the date of the post.
* Accepts 'G', 'U', or PHP date format.
@@ -3424,6 +3444,7 @@ function get_post_modified_time( $format = 'U', $gmt = false, $post = null, $tra
* Displays the localized weekday for the post.
*
* @since 0.71
+ * @since 7.2.0 Passes an empty string to the filter instead of 'Sunday' if the post date is invalid.
*
* @global WP_Locale $wp_locale WordPress date and time locale object.
*/
@@ -3436,7 +3457,12 @@ function the_weekday() {
return;
}
- $the_weekday = $wp_locale->get_weekday( get_post_time( 'w', false, $post ) );
+ $the_weekday = '';
+ $weekday_number = get_post_time( 'w', false, $post );
+
+ if ( false !== $weekday_number ) {
+ $the_weekday = $wp_locale->get_weekday( (int) $weekday_number );
+ }
/**
* Filters the localized weekday of the post, for display.
@@ -3455,6 +3481,7 @@ function the_weekday() {
* the previous one output.
*
* @since 0.71
+ * @since 7.2.0 Outputs nothing instead of 'Sunday' if the post date is invalid.
*
* @global WP_Locale $wp_locale WordPress date and time locale object.
* @global string $currentday The day of the current post in the loop.
@@ -3475,10 +3502,15 @@ function the_weekday_date( $before = '', $after = '' ) {
$the_weekday_date = '';
if ( $currentday !== $previousweekday ) {
- $the_weekday_date .= $before;
- $the_weekday_date .= $wp_locale->get_weekday( get_post_time( 'w', false, $post ) );
- $the_weekday_date .= $after;
- $previousweekday = $currentday;
+ $weekday_number = get_post_time( 'w', false, $post );
+
+ if ( false !== $weekday_number ) {
+ $the_weekday_date .= $before;
+ $the_weekday_date .= $wp_locale->get_weekday( (int) $weekday_number );
+ $the_weekday_date .= $after;
+ }
+
+ $previousweekday = $currentday;
}
/**
diff --git a/wp-includes/version.php b/wp-includes/version.php
index e01110c13b..38d2c0162a 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-beta5-65524';
+$wp_version = '7.2-beta5-65525';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.