Date/Time: Correct sanitization of localized default timezone_string in populate_options().

This fixes a bug where if the default `timezone_string` is set to a deprecated timezone name due to a localization providing an outdated timezone name string, this localized timezone string would be discarded and an empty string would be set as the timezone value instead.

By passing the `DateTimeZone::ALL_WITH_BC` constant as the `$timezoneGroup` parameter to the PHP native `timezone_identifiers_list()` function, a timezone name list is retrieved containing both current and deprecated timezone names, preventing the invalidation of the option value.

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()].

Includes:
* Expanding the translators comment to encourage translators to use “old” names over “new” names.
* Adding a dedicated test to the `Tests_Admin_IncludesSchema` test class.

Follow-up to [54207], [54217], [54227], [54229], [54230].

Props jrf, costdev.
See #56468.

git-svn-id: https://develop.svn.wordpress.org/trunk@54232 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Sergey Biryukov
2022-09-20 00:41:58 +00:00
parent faac282869
commit 09e619c648
2 changed files with 54 additions and 3 deletions

View File

@@ -388,13 +388,23 @@ function populate_options( array $options = array() ) {
/*
* translators: default GMT offset or timezone string. Must be either a valid offset (-12 to 14)
* or a valid timezone string (America/New_York). See https://www.php.net/manual/en/timezones.php
* for all timezone strings supported by PHP.
* for all timezone strings currently supported by PHP.
*
* Important: When a previous timezone string, like `Europe/Kiev`, has been superseded by an
* updated one, like `Europe/Kyiv`, as a rule of thumb, the **old** timezone name should be used
* in the "translation" to allow for the default timezone setting to be PHP cross-version compatible,
* as old timezone names will be recognized in new PHP versions, while new timezone names cannot
* be recognized in old PHP versions.
*
* To verify which timezone strings are available in the _oldest_ PHP version supported, you can
* use https://3v4l.org/6YQAt#v5.6.20 and replace the "BR" (Brazil) in the code line with the
* country code for which you want to look up the supported timezone names.
*/
$offset_or_tz = _x( '0', 'default GMT offset or timezone string' );
if ( is_numeric( $offset_or_tz ) ) {
$gmt_offset = $offset_or_tz;
} elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list(), true ) ) {
$timezone_string = $offset_or_tz;
} elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list( DateTimeZone::ALL_WITH_BC ), true ) ) {
$timezone_string = $offset_or_tz;
}
$defaults = array(

View File

@@ -177,6 +177,47 @@ class Tests_Admin_IncludesSchema extends WP_UnitTestCase {
);
}
/**
* Ensures that deprecated timezone strings set as a default in a translation are handled correctly.
*
* @ticket 56468
*/
public function test_populate_options_when_locale_uses_deprecated_timezone_string() {
global $wpdb;
// Back up.
$orig_options = $wpdb->options;
$wpdb->options = self::$options;
// Set the "default" value for the timezone to a deprecated timezone.
add_filter(
'gettext_with_context',
static function( $translation, $text, $context ) {
if ( '0' === $text && 'default GMT offset or timezone string' === $context ) {
return 'America/Buenos_Aires';
}
return $translation;
},
10,
3
);
// Test.
populate_options();
wp_cache_delete( 'alloptions', 'options' );
$result = get_option( 'timezone_string' );
// Reset.
$wpdb->query( "TRUNCATE TABLE {$wpdb->options}" );
$wpdb->options = $orig_options;
// Assert.
$this->assertSame( 'America/Buenos_Aires', $result );
}
/**
* @ticket 44896
* @group multisite