From 45da79e52e3252ddb8286ca0e6cd5db4522d874c Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Tue, 20 Sep 2022 01:00:24 +0000 Subject: [PATCH] Date/Time: Correct timezone dropdown list creation in `wp_timezone_choice()`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a bug where if the `timezone_string` is set to a timezone name which has since been deprecated, no option would be (pre-)selected in the generated dropdown list and when the form using the dropdown list is submitted, the “old”, originally saved value would be lost as the form would submit without a value being selected for the `timezone_string` field. The fix is a little hacky: it basically checks ahead of generating the actual dropdown list whether the `$selected_zone` value would be recognized and set to “selected” and if not, verifies that the value ''is'' a valid but outdated timezone name and if so, adds an extra dropdown entry to the top of the list with the original value and sets this value to “selected”. See the extensive write-up about this in ticket #56468. Also see: [https://www.php.net/manual/en/datetimezone.listidentifiers.php PHP Manual: timezone_identifiers_list()]. Note: There are no pre-existing tests at all for this method and adding a complete set of tests for this method is outside the scope of this ticket, so this fix does not contain any tests. Follow-up to [54207], [54217], [54227], [54229], [54230], [54232]. Props jrf, costdev, marcyoast. See #56468. git-svn-id: https://develop.svn.wordpress.org/trunk@54233 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/functions.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index 55f43cbe31..5d32afa578 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -6381,8 +6381,10 @@ function wp_timezone_choice( $selected_zone, $locale = null ) { $mo_loaded = true; } - $zonen = array(); - foreach ( timezone_identifiers_list() as $zone ) { + $tz_identifiers = timezone_identifiers_list(); + $zonen = array(); + + foreach ( $tz_identifiers as $zone ) { $zone = explode( '/', $zone ); if ( ! in_array( $zone[0], $continents, true ) ) { continue; @@ -6417,6 +6419,13 @@ function wp_timezone_choice( $selected_zone, $locale = null ) { $structure[] = ''; } + // If this is a deprecated, but valid, timezone string, display it at the top of the list as-is. + if ( in_array( $selected_zone, $tz_identifiers, true ) === false + && in_array( $selected_zone, timezone_identifiers_list( DateTimeZone::ALL_WITH_BC ), true ) + ) { + $structure[] = ''; + } + foreach ( $zonen as $key => $zone ) { // Build value in an array to join later. $value = array( $zone['continent'] );