Skip to content

Commit e0e2541

Browse files
committed
populate_options(): fix bug in sanitization of localized default timezone_string
This fixes a bug where if the default `timezone_string` would be 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 Trac#56468. Also see: https://www.php.net/manual/en/datetimezone.listidentifiers.php Includes an expansion of the translators comment to encourage translators to use "old" names over "new" names. Includes adding a dedicated test to the `Tests_Admin_IncludesSchema` test class.
1 parent 41a1690 commit e0e2541

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

src/wp-admin/includes/schema.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,13 +388,22 @@ function populate_options( array $options = array() ) {
388388
/*
389389
* translators: default GMT offset or timezone string. Must be either a valid offset (-12 to 14)
390390
* or a valid timezone string (America/New_York). See https://www.php.net/manual/en/timezones.php
391-
* for all timezone strings supported by PHP.
391+
* for all timezone strings currently supported by PHP.
392+
*
393+
* Important: When a previous timezone string, like `Europe/Kiev`, has been superseded by an
394+
* updated one, like `Europe/Kyiv`, as a rule of thumb, the **old** timezone name should be used
395+
* in the "translation" to allow for the default timezone setting to be PHP cross-version compatible,
396+
* as old timezone names will be recognized in new PHP versions, while new timezone names can not
397+
* be recognized in old PHP versions.
398+
* To verify which timezone strings are available in the _oldest_ PHP version supported, you can
399+
* use https://3v4l.org/6YQAt#v5.6.20 and replace the "BR" (Brazil) in the code line with the
400+
* country code for which you want to look up the supported timezone names.
392401
*/
393402
$offset_or_tz = _x( '0', 'default GMT offset or timezone string' );
394403
if ( is_numeric( $offset_or_tz ) ) {
395404
$gmt_offset = $offset_or_tz;
396-
} elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list(), true ) ) {
397-
$timezone_string = $offset_or_tz;
405+
} elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list( DateTimeZone::ALL_WITH_BC ), true ) ) {
406+
$timezone_string = $offset_or_tz;
398407
}
399408

400409
$defaults = array(

tests/phpunit/tests/admin/includesSchema.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,47 @@ public function data_populate_options() {
177177
);
178178
}
179179

180+
/**
181+
* Safeguards that deprecated timezone strings set as a default in a translation are handled correctly.
182+
*
183+
* @ticket 56468
184+
*/
185+
public function test_populate_options_when_locale_uses_deprecated_timezone_string() {
186+
global $wpdb;
187+
188+
// Back up.
189+
$orig_options = $wpdb->options;
190+
$wpdb->options = self::$options;
191+
192+
// Ensure the "default" value for the timezone will be set to a deprecated timezone.
193+
add_filter(
194+
'gettext_with_context',
195+
function( $translation, $text, $context ) {
196+
if ( '0' === $text && 'default GMT offset or timezone string' === $context ) {
197+
return 'America/Buenos_Aires';
198+
}
199+
200+
return $translation;
201+
},
202+
10,
203+
3
204+
);
205+
206+
// Test.
207+
populate_options();
208+
209+
wp_cache_delete( 'alloptions', 'options' );
210+
211+
$result = get_option( 'timezone_string' );
212+
213+
// Reset.
214+
$wpdb->query( "TRUNCATE TABLE {$wpdb->options}" );
215+
$wpdb->options = $orig_options;
216+
217+
// Assert.
218+
$this->assertSame( 'America/Buenos_Aires', $result );
219+
}
220+
180221
/**
181222
* @ticket 44896
182223
* @group multisite

0 commit comments

Comments
 (0)