Make WordPress Core


Ignore:
Timestamp:
08/22/2024 11:25:17 PM (6 weeks ago)
Author:
peterwilsoncc
Message:

Date/Time: Prevent type errors in current_time().

Prevents a potential type error when calling current_time( 'timestamp' ) by casting get_option( 'gmt_offset' ) to a float prior to performing calculations with the value.

This mainly accounts for incorrect storage of values, such as an empty string or city name.

Follow up to [45856], [55054], [55598].

Props hellofromtonya, peterwilsoncc, rarst, costdev, Nick_theGeek, SergeyBiryukov, johnbillion, desrosj, reputeinfosystems, audrasjb, oglekler.
Fixes #57035.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/date/currentTime.php

    r56971 r58923  
    9292    /**
    9393     * @ticket 40653
    94      */
    95     public function test_should_return_wp_timestamp() {
    96         update_option( 'timezone_string', 'Europe/Helsinki' );
     94     * @ticket 57998
     95     *
     96     * @dataProvider data_timezones
     97     *
     98     * @param string $timezone The timezone to test.
     99     */
     100    public function test_should_return_wp_timestamp( $timezone ) {
     101        update_option( 'timezone_string', $timezone );
    97102
    98103        $timestamp = time();
     
    102107
    103108        // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.RequestedUTC
    104         $this->assertEqualsWithDelta( $timestamp, current_time( 'timestamp', true ), 2, 'The dates should be equal' );
     109        $this->assertEqualsWithDelta( $timestamp, current_time( 'timestamp', true ), 2, 'When passing "timestamp", the date should be equal to time()' );
    105110        // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.RequestedUTC
    106         $this->assertEqualsWithDelta( $timestamp, current_time( 'U', true ), 2, 'The dates should be equal' );
    107 
    108         // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
    109         $this->assertEqualsWithDelta( $wp_timestamp, current_time( 'timestamp' ), 2, 'The dates should be equal' );
    110         // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
    111         $this->assertEqualsWithDelta( $wp_timestamp, current_time( 'U' ), 2, 'The dates should be equal' );
    112 
    113         // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
    114         $this->assertIsInt( current_time( 'timestamp' ) );
     111        $this->assertEqualsWithDelta( $timestamp, current_time( 'U', true ), 2, 'When passing "U", the date should be equal to time()' );
     112
     113        // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
     114        $this->assertEqualsWithDelta( $wp_timestamp, current_time( 'timestamp' ), 2, 'When passing "timestamp", the date should be equal to calculated timestamp' );
     115        // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
     116        $this->assertEqualsWithDelta( $wp_timestamp, current_time( 'U' ), 2, 'When passing "U", the date should be equal to calculated timestamp' );
     117
     118        // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
     119        $this->assertIsInt( current_time( 'timestamp' ), 'The returned timestamp should be an integer' );
    115120    }
    116121
    117122    /**
    118123     * @ticket 40653
    119      */
    120     public function test_should_return_correct_local_time() {
    121         update_option( 'timezone_string', 'Europe/Helsinki' );
     124     * @ticket 57998
     125     *
     126     * @dataProvider data_timezones
     127     *
     128     * @param string $timezone The timezone to test.
     129     */
     130    public function test_should_return_correct_local_time( $timezone ) {
     131        update_option( 'timezone_string', $timezone );
    122132
    123133        $timestamp      = time();
     
    128138
    129139        $this->assertEqualsWithDelta( strtotime( $datetime_local->format( DATE_W3C ) ), strtotime( current_time( DATE_W3C ) ), 2, 'The dates should be equal' );
    130         $this->assertEqualsWithDelta( strtotime( $datetime_utc->format( DATE_W3C ) ), strtotime( current_time( DATE_W3C, true ) ), 2, 'The dates should be equal' );
     140        $this->assertEqualsWithDelta( strtotime( $datetime_utc->format( DATE_W3C ) ), strtotime( current_time( DATE_W3C, true ) ), 2, 'When passing "timestamp", the dates should be equal' );
     141    }
     142
     143    /**
     144     * Data provider.
     145     *
     146     * @return array[]
     147     */
     148    public function data_timezones() {
     149        return array(
     150            array( 'Europe/Helsinki' ),
     151            array( 'Indian/Antananarivo' ),
     152            array( 'Australia/Adelaide' ),
     153        );
    131154    }
    132155
     
    159182        $this->assertSame( $datetime->format( $format ), $current_time, 'The dates should be equal [4]' );
    160183    }
     184
     185    /**
     186     * Ensures an empty offset does not cause a type error.
     187     *
     188     * @ticket 57998
     189     */
     190    public function test_empty_offset_does_not_cause_a_type_error() {
     191        // Ensure `wp_timezone_override_offset()` doesn't override offset.
     192        update_option( 'timezone_string', '' );
     193        update_option( 'gmt_offset', '' );
     194
     195        $expected = time();
     196
     197        // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
     198        $this->assertEqualsWithDelta( $expected, current_time( 'timestamp' ), 2, 'The timestamps should be equal' );
     199    }
     200
     201    /**
     202     * Ensures the offset applied in current_time() is correct.
     203     *
     204     * @ticket 57998
     205     *
     206     * @dataProvider data_partial_hour_timezones_with_timestamp
     207     *
     208     * @param float $partial_hour Partial hour GMT offset to test.
     209     */
     210    public function test_partial_hour_timezones_with_timestamp( $partial_hour ) {
     211        // Ensure `wp_timezone_override_offset()` doesn't override offset.
     212        update_option( 'timezone_string', '' );
     213        update_option( 'gmt_offset', $partial_hour );
     214
     215        $expected = time() + (int) ( $partial_hour * HOUR_IN_SECONDS );
     216
     217        // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
     218        $this->assertEqualsWithDelta( $expected, current_time( 'timestamp' ), 2, 'The timestamps should be equal' );
     219    }
     220
     221    /**
     222     * Tests the tests.
     223     *
     224     * Ensures the offsets match the stated timezones in the data provider.
     225     *
     226     * @ticket 57998
     227     *
     228     * @dataProvider data_partial_hour_timezones_with_timestamp
     229     *
     230     * @param float $partial_hour     Partial hour GMT offset to test.
     231     * @param string $timezone_string Timezone string to test.
     232     */
     233    public function test_partial_hour_timezones_match_datetime_offset( $partial_hour, $timezone_string ) {
     234        $timezone   = new DateTimeZone( $timezone_string );
     235        $datetime   = new DateTime( 'now', $timezone );
     236        $dst_offset = (int) $datetime->format( 'I' );
     237
     238        // Timezone offset in hours.
     239        $offset = $timezone->getOffset( $datetime ) / HOUR_IN_SECONDS;
     240
     241        /*
     242         * Adjust for daylight saving time.
     243         *
     244         * DST adds an hour to the offset, the partial hour offset
     245         * is set the the standard time offset so this removes the
     246         * DST offset to avoid false negatives.
     247         */
     248        $offset -= $dst_offset;
     249
     250        $this->assertSame( $partial_hour, $offset, 'The offset should match to timezone.' );
     251    }
     252
     253    /**
     254     * Data provider.
     255     *
     256     * @return array[]
     257     */
     258    public function data_partial_hour_timezones_with_timestamp() {
     259        return array(
     260            '+12:45' => array( 12.75, 'Pacific/Chatham' ), // New Zealand, Chatham Islands.
     261            '+9:30'  => array( 9.5, 'Australia/Darwin' ), // Australian Northern Territory.
     262            '+05:30' => array( 5.5, 'Asia/Kolkata' ), // India and Sri Lanka.
     263            '+05:45' => array( 5.75, 'Asia/Kathmandu' ), // Nepal.
     264            '-03:30' => array( -3.50, 'Canada/Newfoundland' ), // Canada, Newfoundland.
     265            '-09:30' => array( -9.50, 'Pacific/Marquesas' ), // French Polynesia, Marquesas Islands.
     266        );
     267    }
    161268}
Note: See TracChangeset for help on using the changeset viewer.