Make WordPress Core

Changeset 54232


Ignore:
Timestamp:
09/20/2022 12:41:58 AM (22 months ago)
Author:
SergeyBiryukov
Message:

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: 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.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/schema.php

    r53815 r54232  
    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 cannot
     397     * be recognized in old PHP versions.
     398     *
     399     * To verify which timezone strings are available in the _oldest_ PHP version supported, you can
     400     * use https://3v4l.org/6YQAt#v5.6.20 and replace the "BR" (Brazil) in the code line with the
     401     * country code for which you want to look up the supported timezone names.
    392402     */
    393403    $offset_or_tz = _x( '0', 'default GMT offset or timezone string' );
    394404    if ( is_numeric( $offset_or_tz ) ) {
    395405        $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;
     406    } elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list( DateTimeZone::ALL_WITH_BC ), true ) ) {
     407        $timezone_string = $offset_or_tz;
    398408    }
    399409
  • trunk/tests/phpunit/tests/admin/includesSchema.php

    r52010 r54232  
    179179
    180180    /**
     181     * Ensures 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        // Set the "default" value for the timezone to a deprecated timezone.
     193        add_filter(
     194            'gettext_with_context',
     195            static 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
     221    /**
    181222     * @ticket 44896
    182223     * @group multisite
Note: See TracChangeset for help on using the changeset viewer.