Make WordPress Core

Changeset 49275


Ignore:
Timestamp:
10/22/2020 04:03:25 AM (6 years ago)
Author:
tellyworth
Message:

Community Events: Display dates and times in the user's time zone.

Fixes #51130
Merges [49145], [49146], [49147], [49152], and [49201] to the 5.5 branch.
Props sippis, hlashbrooke, audrasjb, Rarst, iandunn

Location:
branches/5.5
Files:
7 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/5.5

  • branches/5.5/src/js/_enqueues/wp/dashboard.js

    r48168 r49275  
    267267
    268268        var communityEventsData = window.communityEventsData || {},
     269                dateI18n = wp.date.dateI18n,
     270                format = wp.date.format,
     271                sprintf = wp.i18n.sprintf,
     272                __ = wp.i18n.__,
     273                _x = wp.i18n._x,
    269274                app;
    270275
     
    442447                                        app.renderEventsTemplate({
    443448                                                'location' : false,
     449                                                'events'   : [],
    444450                                                'error'    : true
    445451                                        }, initiatedBy );
     
    465471                                $locationMessage = $( '#community-events-location-message' ),
    466472                                $results         = $( '.community-events-results' );
     473
     474                        templateParams.events = app.populateDynamicEventFields(
     475                                templateParams.events,
     476                                communityEventsData.time_format
     477                        );
    467478
    468479                        /*
     
    577588                                app.toggleLocationForm( 'show' );
    578589                        }
     590                },
     591
     592                /**
     593                 * Populate event fields that have to be calculated on the fly.
     594                 *
     595                 * These can't be stored in the database, because they're dependent on
     596                 * the user's current time zone, locale, etc.
     597                 *
     598                 * @since 5.5.2
     599                 *
     600                 * @param {Array}  rawEvents  The events that should have dynamic fields added to them.
     601                 * @param {string} timeFormat A time format acceptable by `wp.date.dateI18n()`.
     602                 *
     603                 * @returns {Array}
     604                 */
     605                populateDynamicEventFields: function( rawEvents, timeFormat ) {
     606                        // Clone the parameter to avoid mutating it, so that this can remain a pure function.
     607                        var populatedEvents = JSON.parse( JSON.stringify( rawEvents ) );
     608
     609                        $.each( populatedEvents, function( index, event ) {
     610                                var timeZone = app.getTimeZone( event.start_unix_timestamp * 1000 );
     611
     612                                event.user_formatted_date = app.getFormattedDate(
     613                                        event.start_unix_timestamp * 1000,
     614                                        event.end_unix_timestamp * 1000,
     615                                        timeZone
     616                                );
     617
     618                                event.user_formatted_time = dateI18n(
     619                                        timeFormat,
     620                                        event.start_unix_timestamp * 1000,
     621                                        timeZone
     622                                );
     623
     624                                event.timeZoneAbbreviation = app.getTimeZoneAbbreviation( event.start_unix_timestamp * 1000 );
     625                        } );
     626
     627                        return populatedEvents;
     628                },
     629
     630                /**
     631                 * Returns the user's local/browser time zone, in a form suitable for `wp.date.i18n()`.
     632                 *
     633                 * @since 5.5.2
     634                 *
     635                 * @param startTimestamp
     636                 *
     637                 * @returns {string|number}
     638                 */
     639                getTimeZone: function( startTimestamp ) {
     640                        /*
     641                         * Prefer a name like `Europe/Helsinki`, since that automatically tracks daylight savings. This
     642                         * doesn't need to take `startTimestamp` into account for that reason.
     643                         */
     644                        var timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
     645
     646                        /*
     647                         * Fall back to an offset for IE11, which declares the property but doesn't assign a value.
     648                         */
     649                        if ( 'undefined' === typeof timeZone ) {
     650                                /*
     651                                 * It's important to use the _event_ time, not the _current_
     652                                 * time, so that daylight savings time is accounted for.
     653                                 */
     654                                timeZone = app.getFlippedTimeZoneOffset( startTimestamp );
     655                        }
     656
     657                        return timeZone;
     658                },
     659
     660                /**
     661                 * Get intuitive time zone offset.
     662                 *
     663                 * `Data.prototype.getTimezoneOffset()` returns a positive value for time zones
     664                 * that are _behind_ UTC, and a _negative_ value for ones that are ahead.
     665                 *
     666                 * See https://stackoverflow.com/questions/21102435/why-does-javascript-date-gettimezoneoffset-consider-0500-as-a-positive-off.
     667                 *
     668                 * @since 5.5.2
     669                 *
     670                 * @param {number} startTimestamp
     671                 *
     672                 * @returns {number}
     673                 */
     674                getFlippedTimeZoneOffset: function( startTimestamp ) {
     675                        return new Date( startTimestamp ).getTimezoneOffset() * -1;
     676                },
     677
     678                /**
     679                 * Get a short time zone name, like `PST`.
     680                 *
     681                 * @since 5.5.2
     682                 *
     683                 * @param {number} startTimestamp
     684                 *
     685                 * @returns {string}
     686                 */
     687                getTimeZoneAbbreviation: function( startTimestamp ) {
     688                        var timeZoneAbbreviation,
     689                                eventDateTime = new Date( startTimestamp );
     690
     691                        /*
     692                         * Leaving the `locales` argument undefined is important, so that the browser
     693                         * displays the abbreviation that's most appropriate for the current locale. For
     694                         * some that will be `UTC{+|-}{n}`, and for others it will be a code like `PST`.
     695                         *
     696                         * This doesn't need to take `startTimestamp` into account, because a name like
     697                         * `America/Chicago` automatically tracks daylight savings.
     698                         */
     699                        var shortTimeStringParts = eventDateTime.toLocaleTimeString( undefined, { timeZoneName : 'short' } ).split( ' ' );
     700
     701                        if ( 3 === shortTimeStringParts.length ) {
     702                                timeZoneAbbreviation = shortTimeStringParts[2];
     703                        }
     704
     705                        if ( 'undefined' === typeof timeZoneAbbreviation ) {
     706                                /*
     707                                 * It's important to use the _event_ time, not the _current_
     708                                 * time, so that daylight savings time is accounted for.
     709                                 */
     710                                var timeZoneOffset = app.getFlippedTimeZoneOffset( startTimestamp ),
     711                                        sign = -1 === Math.sign( timeZoneOffset ) ? '' : '+';
     712
     713                                // translators: Used as part of a string like `GMT+5` in the Events Widget.
     714                                timeZoneAbbreviation = _x( 'GMT', 'Events widget offset prefix' ) + sign + ( timeZoneOffset / 60 );
     715                        }
     716
     717                        return timeZoneAbbreviation;
     718                },
     719
     720                /**
     721                 * Format a start/end date in the user's local time zone and locale.
     722                 *
     723                 * @since 5.5.2
     724                 *
     725                 * @param {int}    startDate   The Unix timestamp in milliseconds when the the event starts.
     726                 * @param {int}    endDate     The Unix timestamp in milliseconds when the the event ends.
     727                 * @param {string} timeZone    A time zone string or offset which is parsable by `wp.date.i18n()`.
     728                 *
     729                 * @returns {string}
     730                 */
     731                getFormattedDate: function( startDate, endDate, timeZone ) {
     732                        var formattedDate;
     733
     734                        /*
     735                         * The `date_format` option is not used because it's important
     736                         * in this context to keep the day of the week in the displayed date,
     737                         * so that users can tell at a glance if the event is on a day they
     738                         * are available, without having to open the link.
     739                         *
     740                         * The case of crossing a year boundary is intentionally not handled.
     741                         * It's so rare in practice that it's not worth the complexity
     742                         * tradeoff. The _ending_ year should be passed to
     743                         * `multiple_month_event`, though, just in case.
     744                         */
     745                        /* translators: Date format for upcoming events on the dashboard. Include the day of the week. See https://www.php.net/manual/datetime.format.php */
     746                        var singleDayEvent = __( 'l, M j, Y' ),
     747                                /* translators: Date string for upcoming events. 1: Month, 2: Starting day, 3: Ending day, 4: Year. */
     748                                multipleDayEvent = __( '%1$s %2$d–%3$d, %4$d' ),
     749                                /* translators: Date string for upcoming events. 1: Starting month, 2: Starting day, 3: Ending month, 4: Ending day, 5: Ending year. */
     750                                multipleMonthEvent = __( '%1$s %2$d – %3$s %4$d, %5$d' );
     751
     752                        // Detect single-day events.
     753                        if ( ! endDate || format( 'Y-m-d', startDate ) === format( 'Y-m-d', endDate ) ) {
     754                                formattedDate = dateI18n( singleDayEvent, startDate, timeZone );
     755
     756                        // Multiple day events.
     757                        } else if ( format( 'Y-m', startDate ) === format( 'Y-m', endDate ) ) {
     758                                formattedDate = sprintf(
     759                                        multipleDayEvent,
     760                                        dateI18n( _x( 'F', 'upcoming events month format' ), startDate, timeZone ),
     761                                        dateI18n( _x( 'j', 'upcoming events day format' ), startDate, timeZone ),
     762                                        dateI18n( _x( 'j', 'upcoming events day format' ), endDate, timeZone ),
     763                                        dateI18n( _x( 'Y', 'upcoming events year format' ), endDate, timeZone )
     764                                );
     765
     766                        // Multi-day events that cross a month boundary.
     767                        } else {
     768                                formattedDate = sprintf(
     769                                        multipleMonthEvent,
     770                                        dateI18n( _x( 'F', 'upcoming events month format' ), startDate, timeZone ),
     771                                        dateI18n( _x( 'j', 'upcoming events day format' ), startDate, timeZone ),
     772                                        dateI18n( _x( 'F', 'upcoming events month format' ), endDate, timeZone ),
     773                                        dateI18n( _x( 'j', 'upcoming events day format' ), endDate, timeZone ),
     774                                        dateI18n( _x( 'Y', 'upcoming events year format' ), endDate, timeZone )
     775                                );
     776                        }
     777
     778                        return formattedDate;
    579779                }
    580780        };
  • branches/5.5/src/wp-admin/includes/class-wp-community-events.php

    r48110 r49275  
    7878         *
    7979         * @since 4.8.0
     80         * @since 5.5.2 Response no longer contains formatted date field. They're added
     81         *              in `wp.communityEvents.populateDynamicEventFields()` now.
    8082         *
    8183         * @param string $location_search Optional. City name to help determine the location.
     
    159161                        }
    160162
     163                        /*
     164                         * Store the raw response, because events will expire before the cache does.
     165                         * The response will need to be processed every page load.
     166                         */
    161167                        $this->cache_events( $response_body, $expiration );
    162168
    163                         $response_body = $this->trim_events( $response_body );
    164                         $response_body = $this->format_event_data_time( $response_body );
     169                        $response_body['events'] = $this->trim_events( $response_body['events'] );
    165170
    166171                        return $response_body;
     
    341346         *
    342347         * @since 4.8.0
     348         * @since 5.5.2 Response no longer contains formatted date field. They're added
     349         *              in `wp.communityEvents.populateDynamicEventFields()` now.
    343350         *
    344351         * @return array|false An array containing `location` and `events` items
     
    347354        public function get_cached_events() {
    348355                $cached_response = get_site_transient( $this->get_events_transient_key( $this->user_location ) );
    349                 $cached_response = $this->trim_events( $cached_response );
    350 
    351                 return $this->format_event_data_time( $cached_response );
     356
     357                if ( isset( $cached_response['events'] ) ) {
     358                        $cached_response['events'] = $this->trim_events( $cached_response['events'] );
     359                }
     360
     361                return $cached_response;
    352362        }
    353363
     
    361371         *
    362372         * @since 4.8.0
     373         * @deprecated 5.6.0 No longer used in core.
    363374         *
    364375         * @param array $response_body The response which contains the events.
     
    366377         */
    367378        protected function format_event_data_time( $response_body ) {
     379                _deprecated_function(
     380                        __METHOD__,
     381                        '5.5.2',
     382                        'This is no longer used by core, and only kept for backward compatibility.'
     383                );
     384
    368385                if ( isset( $response_body['events'] ) ) {
    369386                        foreach ( $response_body['events'] as $key => $event ) {
     
    436453         * @since 4.8.0
    437454         * @since 4.9.7 Stick a WordCamp to the final list.
    438          *
    439          * @param array $response_body The response body which contains the events.
     455         * @since 5.5.2 Accepts and returns only the events, rather than an entire HTTP response.
     456         *
     457         * @param array $events The events that will be prepared.
    440458         * @return array The response body with events trimmed.
    441459         */
    442         protected function trim_events( $response_body ) {
    443                 if ( isset( $response_body['events'] ) ) {
    444                         $wordcamps = array();
    445                         $today     = current_time( 'Y-m-d' );
    446 
    447                         foreach ( $response_body['events'] as $key => $event ) {
    448                                 /*
    449                                  * Skip WordCamps, because they might be multi-day events.
    450                                  * Save a copy so they can be pinned later.
    451                                  */
    452                                 if ( 'wordcamp' === $event['type'] ) {
    453                                         $wordcamps[] = $event;
    454                                         continue;
    455                                 }
    456 
    457                                 // We don't get accurate time with timezone from API, so we only take the date part (Y-m-d).
    458                                 $event_date = substr( $event['date'], 0, 10 );
    459 
    460                                 if ( $today > $event_date ) {
    461                                         unset( $response_body['events'][ $key ] );
    462                                 }
    463                         }
    464 
    465                         $response_body['events'] = array_slice( $response_body['events'], 0, 3 );
    466                         $trimmed_event_types     = wp_list_pluck( $response_body['events'], 'type' );
    467 
    468                         // Make sure the soonest upcoming WordCamp is pinned in the list.
    469                         if ( ! in_array( 'wordcamp', $trimmed_event_types, true ) && $wordcamps ) {
    470                                 array_pop( $response_body['events'] );
    471                                 array_push( $response_body['events'], $wordcamps[0] );
    472                         }
    473                 }
    474 
    475                 return $response_body;
     460        protected function trim_events( array $events ) {
     461                $future_events = array();
     462
     463                foreach ( $events as $event ) {
     464                        /*
     465                         * The API's `date` and `end_date` fields are in the _event's_ local timezone, but UTC is needed so
     466                         * it can be converted to the _user's_ local time.
     467                         */
     468                        $end_time = (int) $event['end_unix_timestamp'];
     469
     470                        if ( time() < $end_time ) {
     471                                array_push( $future_events, $event );
     472                        }
     473                }
     474
     475                $future_wordcamps = array_filter(
     476                        $future_events,
     477                        function( $wordcamp ) {
     478                                return 'wordcamp' === $wordcamp['type'];
     479                        }
     480                );
     481
     482                $future_wordcamps    = array_values( $future_wordcamps ); // Remove gaps in indices.
     483                $trimmed_events      = array_slice( $future_events, 0, 3 );
     484                $trimmed_event_types = wp_list_pluck( $trimmed_events, 'type' );
     485
     486                // Make sure the soonest upcoming WordCamp is pinned in the list.
     487                if ( $future_wordcamps && ! in_array( 'wordcamp', $trimmed_event_types, true ) ) {
     488                        array_pop( $trimmed_events );
     489                        array_push( $trimmed_events, $future_wordcamps[0] );
     490                }
     491
     492                return $trimmed_events;
    476493        }
    477494
  • branches/5.5/src/wp-admin/includes/dashboard.php

    r48586 r49275  
    13801380
    13811381                                <div class="event-date-time">
    1382                                         <span class="event-date">{{ event.formatted_date }}</span>
     1382                                        <span class="event-date">{{ event.user_formatted_date }}</span>
    13831383                                        <# if ( 'meetup' === event.type ) { #>
    1384                                                 <span class="event-time">{{ event.formatted_time }}</span>
     1384                                                <span class="event-time">
     1385                                                        {{ event.user_formatted_time }} {{ event.timeZoneAbbreviation }}
     1386                                                </span>
    13851387                                        <# } #>
    13861388                                </div>
  • branches/5.5/src/wp-includes/script-loader.php

    r48925 r49275  
    12781278                $scripts->set_translations( 'wp-color-picker' );
    12791279
    1280                 $scripts->add( 'dashboard', "/wp-admin/js/dashboard$suffix.js", array( 'jquery', 'admin-comments', 'postbox', 'wp-util', 'wp-a11y' ), false, 1 );
     1280                $scripts->add( 'dashboard', "/wp-admin/js/dashboard$suffix.js", array( 'jquery', 'admin-comments', 'postbox', 'wp-util', 'wp-a11y', 'wp-date' ), false, 1 );
     1281                $scripts->set_translations( 'dashboard' );
    12811282
    12821283                $scripts->add( 'list-revisions', "/wp-includes/js/wp-list-revisions$suffix.js" );
     
    17231724                'communityEventsData',
    17241725                array(
    1725                         'nonce' => wp_create_nonce( 'community_events' ),
    1726                         'cache' => $events_client->get_cached_events(),
    1727 
    1728                         'l10n'  => array(
     1726                        'nonce'       => wp_create_nonce( 'community_events' ),
     1727                        'cache'       => $events_client->get_cached_events(),
     1728                        'time_format' => get_option( 'time_format' ),
     1729
     1730                        'l10n'        => array(
    17291731                                'enter_closest_city'              => __( 'Enter your closest city to find nearby events.' ),
    17301732                                'error_occurred_please_try_again' => __( 'An error occurred. Please try again.' ),
  • branches/5.5/tests/phpunit/tests/admin/includesCommunityEvents.php

    r48576 r49275  
    154154        /**
    155155         * Test: With a valid response, get_events() should return an associative array containing a location array and
    156          * an events array with individual events that have formatted time and date.
     156         * an events array with individual events that have Unix start/end timestamps.
    157157         *
    158158         * @since 4.8.0
     
    165165                $this->assertNotWPError( $response );
    166166                $this->assertEqualSetsWithIndex( $this->get_user_location(), $response['location'] );
    167                 $this->assertEquals( gmdate( 'l, M j, Y', strtotime( 'next Sunday 1pm' ) ), $response['events'][0]['formatted_date'] );
    168                 $this->assertEquals( '1:00 pm', $response['events'][0]['formatted_time'] );
     167                $this->assertSame( strtotime( 'next Sunday 1pm' ), $response['events'][0]['start_unix_timestamp'] );
     168                $this->assertSame( strtotime( 'next Sunday 2pm' ), $response['events'][0]['end_unix_timestamp'] );
    169169
    170170                remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response' ) );
     
    172172
    173173        /**
    174          * Test: get_cached_events() should return the same data as get_events(), including formatted time
    175          * and date values for each event.
     174         * Test: `get_cached_events()` should return the same data as get_events(), including Unix start/end
     175         * timestamps for each event.
    176176         *
    177177         * @since 4.8.0
     
    186186                $this->assertNotWPError( $cached_events );
    187187                $this->assertEqualSetsWithIndex( $this->get_user_location(), $cached_events['location'] );
    188                 $this->assertEquals( gmdate( 'l, M j, Y', strtotime( 'next Sunday 1pm' ) ), $cached_events['events'][0]['formatted_date'] );
    189                 $this->assertEquals( '1:00 pm', $cached_events['events'][0]['formatted_time'] );
     188                $this->assertSame( strtotime( 'next Sunday 1pm' ), $cached_events['events'][0]['start_unix_timestamp'] );
     189                $this->assertSame( strtotime( 'next Sunday 2pm' ), $cached_events['events'][0]['end_unix_timestamp'] );
    190190
    191191                remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response' ) );
     
    205205                                array(
    206206                                        'location' => $this->get_user_location(),
    207                                         'events'   => array(
    208                                                 array(
    209                                                         'type'       => 'meetup',
    210                                                         'title'      => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
    211                                                         'url'        => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
    212                                                         'meetup'     => 'The East Bay WordPress Meetup Group',
    213                                                         'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
    214                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Sunday 1pm' ) ),
    215                                                         'location'   => array(
    216                                                                 'location'  => 'Oakland, CA, USA',
    217                                                                 'country'   => 'us',
    218                                                                 'latitude'  => 37.808453,
    219                                                                 'longitude' => -122.26593,
    220                                                         ),
    221                                                 ),
    222                                                 array(
    223                                                         'type'       => 'meetup',
    224                                                         'title'      => 'Part 3- Site Maintenance - Tools to Make It Easy',
    225                                                         'url'        => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
    226                                                         'meetup'     => 'WordPress Bay Area Foothills Group',
    227                                                         'meetup_url' => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
    228                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 1:30pm' ) ),
    229                                                         'location'   => array(
    230                                                                 'location'  => 'Milpitas, CA, USA',
    231                                                                 'country'   => 'us',
    232                                                                 'latitude'  => 37.432813,
    233                                                                 'longitude' => -121.907095,
    234                                                         ),
    235                                                 ),
    236                                                 array(
    237                                                         'type'       => 'wordcamp',
    238                                                         'title'      => 'WordCamp Kansas City',
    239                                                         'url'        => 'https://2017.kansascity.wordcamp.org',
    240                                                         'meetup'     => null,
    241                                                         'meetup_url' => null,
    242                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Saturday' ) ),
    243                                                         'location'   => array(
    244                                                                 'location'  => 'Kansas City, MO',
    245                                                                 'country'   => 'US',
    246                                                                 'latitude'  => 39.0392325,
    247                                                                 'longitude' => -94.577076,
    248                                                         ),
    249                                                 ),
    250                                         ),
     207                                        'events'   => $this->get_valid_events(),
    251208                                )
    252209                        ),
     
    260217
    261218        /**
     219         * Get a sample of valid events.
     220         *
     221         * @return array[]
     222         */
     223        protected function get_valid_events() {
     224                return array(
     225                        array(
     226                                'type'                 => 'meetup',
     227                                'title'                => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
     228                                'url'                  => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
     229                                'meetup'               => 'The East Bay WordPress Meetup Group',
     230                                'meetup_url'           => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
     231                                'start_unix_timestamp' => strtotime( 'next Sunday 1pm' ),
     232                                'end_unix_timestamp'   => strtotime( 'next Sunday 2pm' ),
     233
     234                                'location'             => array(
     235                                        'location'  => 'Oakland, CA, USA',
     236                                        'country'   => 'us',
     237                                        'latitude'  => 37.808453,
     238                                        'longitude' => -122.26593,
     239                                ),
     240                        ),
     241
     242                        array(
     243                                'type'                 => 'meetup',
     244                                'title'                => 'Part 3- Site Maintenance - Tools to Make It Easy',
     245                                'url'                  => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
     246                                'meetup'               => 'WordPress Bay Area Foothills Group',
     247                                'meetup_url'           => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
     248                                'start_unix_timestamp' => strtotime( 'next Wednesday 1:30pm' ),
     249                                'end_unix_timestamp'   => strtotime( 'next Wednesday 2:30pm' ),
     250
     251                                'location'             => array(
     252                                        'location'  => 'Milpitas, CA, USA',
     253                                        'country'   => 'us',
     254                                        'latitude'  => 37.432813,
     255                                        'longitude' => -121.907095,
     256                                ),
     257                        ),
     258
     259                        array(
     260                                'type'                 => 'wordcamp',
     261                                'title'                => 'WordCamp San Francisco',
     262                                'url'                  => 'https://sf.wordcamp.org/2020/',
     263                                'meetup'               => null,
     264                                'meetup_url'           => null,
     265                                'start_unix_timestamp' => strtotime( 'next Saturday' ),
     266                                'end_unix_timestamp'   => strtotime( 'next Saturday 8pm' ),
     267
     268                                'location'             => array(
     269                                        'location'  => 'San Francisco, CA',
     270                                        'country'   => 'US',
     271                                        'latitude'  => 37.432813,
     272                                        'longitude' => -121.907095,
     273                                ),
     274                        ),
     275                );
     276        }
     277
     278        /**
     279         * Test: `trim_events()` should immediately remove expired events.
     280         *
     281         * @covers WP_Community_Events::trim_events
     282         *
     283         * @since 5.5.2
     284         */
     285        public function test_trim_expired_events() {
     286                $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
     287                $trim_events->setAccessible( true );
     288
     289                $events = $this->get_valid_events();
     290
     291                // This should be removed because it's already ended.
     292                $events[0]['start_unix_timestamp'] = strtotime( '1 hour ago' );
     293                $events[0]['end_unix_timestamp']   = strtotime( '2 seconds ago' );
     294
     295                // This should remain because it hasn't ended yet.
     296                $events[1]['start_unix_timestamp'] = strtotime( '2 seconds ago' );
     297                $events[1]['end_unix_timestamp']   = strtotime( '+1 hour' );
     298
     299                $actual = $trim_events->invoke( $this->instance, $events );
     300
     301                $this->assertCount( 2, $actual );
     302                $this->assertSame( $actual[0]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
     303                $this->assertSame( $actual[1]['title'], 'WordCamp San Francisco' );
     304        }
     305
     306        /**
    262307         * Test: get_events() should return the events with the WordCamp pinned in the prepared list.
    263308         *
     309         * @covers WP_Community_Events::trim_events
     310         *
    264311         * @since 4.9.7
    265          */
    266         public function test_get_events_pin_wordcamp() {
    267                 add_filter( 'pre_http_request', array( $this, '_http_request_valid_response_unpinned_wordcamp' ) );
    268 
    269                 $response_body = $this->instance->get_events();
     312         * @since 5.5.2 Tests `trim_events()` directly instead of indirectly via `get_events()`.
     313         */
     314        public function test_trim_events_pin_wordcamp() {
     315                $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
     316                $trim_events->setAccessible( true );
     317
     318                $actual = $trim_events->invoke( $this->instance, $this->_events_with_unpinned_wordcamp() );
    270319
    271320                /*
    272                  * San Diego was at position 3 in the mock API response, but pinning puts it at position 2,
     321                 * San Diego was at index 3 in the mock API response, but pinning puts it at index 2,
    273322                 * so that it remains in the list. The other events should remain unchanged.
    274323                 */
    275                 $this->assertCount( 3, $response_body['events'] );
    276                 $this->assertEquals( $response_body['events'][0]['title'], 'Flexbox + CSS Grid: Magic for Responsive Layouts' );
    277                 $this->assertEquals( $response_body['events'][1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
    278                 $this->assertEquals( $response_body['events'][2]['title'], 'WordCamp San Diego' );
    279 
    280                 remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response_unpinned_wordcamp' ) );
    281         }
    282 
    283         /**
    284          * Simulates a valid HTTP response where a WordCamp needs to be pinned higher than it's default position.
     324                $this->assertCount( 3, $actual );
     325                $this->assertSame( $actual[0]['title'], 'Flexbox + CSS Grid: Magic for Responsive Layouts' );
     326                $this->assertSame( $actual[1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
     327                $this->assertSame( $actual[2]['title'], 'WordCamp San Diego' );
     328        }
     329
     330        /**
     331         * Simulates a scenario where a WordCamp needs to be pinned higher than it's default position.
    285332         *
    286333         * @since 4.9.7
    287          *
    288          * @return array A mock HTTP response.
    289          */
    290         public function _http_request_valid_response_unpinned_wordcamp() {
    291                 return array(
    292                         'headers'  => '',
    293                         'response' => array( 'code' => 200 ),
    294                         'cookies'  => '',
    295                         'filename' => '',
    296                         'body'     => wp_json_encode(
    297                                 array(
    298                                         'location' => $this->get_user_location(),
    299                                         'events'   => array(
    300                                                 array(
    301                                                         'type'       => 'meetup',
    302                                                         'title'      => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
    303                                                         'url'        => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
    304                                                         'meetup'     => 'The East Bay WordPress Meetup Group',
    305                                                         'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
    306                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Monday 1pm' ) ),
    307                                                         'location'   => array(
    308                                                                 'location'  => 'Oakland, CA, USA',
    309                                                                 'country'   => 'us',
    310                                                                 'latitude'  => 37.808453,
    311                                                                 'longitude' => -122.26593,
    312                                                         ),
    313                                                 ),
    314                                                 array(
    315                                                         'type'       => 'meetup',
    316                                                         'title'      => 'Part 3- Site Maintenance - Tools to Make It Easy',
    317                                                         'url'        => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
    318                                                         'meetup'     => 'WordPress Bay Area Foothills Group',
    319                                                         'meetup_url' => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
    320                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Tuesday 1:30pm' ) ),
    321                                                         'location'   => array(
    322                                                                 'location'  => 'Milpitas, CA, USA',
    323                                                                 'country'   => 'us',
    324                                                                 'latitude'  => 37.432813,
    325                                                                 'longitude' => -121.907095,
    326                                                         ),
    327                                                 ),
    328                                                 array(
    329                                                         'type'       => 'meetup',
    330                                                         'title'      => 'WordPress Q&A',
    331                                                         'url'        => 'https://www.meetup.com/sanjosewp/events/245419844/',
    332                                                         'meetup'     => 'The San Jose WordPress Meetup',
    333                                                         'meetup_url' => 'https://www.meetup.com/sanjosewp/',
    334                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 5:30pm' ) ),
    335                                                         'location'   => array(
    336                                                                 'location'  => 'Milpitas, CA, USA',
    337                                                                 'country'   => 'us',
    338                                                                 'latitude'  => 37.244194,
    339                                                                 'longitude' => -121.889313,
    340                                                         ),
    341                                                 ),
    342                                                 array(
    343                                                         'type'       => 'wordcamp',
    344                                                         'title'      => 'WordCamp San Diego',
    345                                                         'url'        => 'https://2018.sandiego.wordcamp.org',
    346                                                         'meetup'     => null,
    347                                                         'meetup_url' => null,
    348                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Thursday 9am' ) ),
    349                                                         'location'   => array(
    350                                                                 'location'  => 'San Diego, CA',
    351                                                                 'country'   => 'US',
    352                                                                 'latitude'  => 32.7220419,
    353                                                                 'longitude' => -117.1534513,
    354                                                         ),
    355                                                 ),
    356                                         ),
    357                                 )
     334         * @since 5.5.2 Accepts and returns only the events, rather than an entire HTTP response.
     335         *
     336         * @return array A list of mock events.
     337         */
     338        public function _events_with_unpinned_wordcamp() {
     339                return array(
     340                        array(
     341                                'type'                 => 'meetup',
     342                                'title'                => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
     343                                'url'                  => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
     344                                'meetup'               => 'The East Bay WordPress Meetup Group',
     345                                'meetup_url'           => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
     346                                'start_unix_timestamp' => strtotime( 'next Monday 1pm' ),
     347                                'end_unix_timestamp'   => strtotime( 'next Monday 2pm' ),
     348
     349                                'location'             => array(
     350                                        'location'  => 'Oakland, CA, USA',
     351                                        'country'   => 'us',
     352                                        'latitude'  => 37.808453,
     353                                        'longitude' => -122.26593,
     354                                ),
     355                        ),
     356
     357                        array(
     358                                'type'                 => 'meetup',
     359                                'title'                => 'Part 3- Site Maintenance - Tools to Make It Easy',
     360                                'url'                  => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
     361                                'meetup'               => 'WordPress Bay Area Foothills Group',
     362                                'meetup_url'           => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
     363                                'start_unix_timestamp' => strtotime( 'next Tuesday 1:30pm' ),
     364                                'end_unix_timestamp'   => strtotime( 'next Tuesday 2:30pm' ),
     365
     366                                'location'             => array(
     367                                        'location'  => 'Milpitas, CA, USA',
     368                                        'country'   => 'us',
     369                                        'latitude'  => 37.432813,
     370                                        'longitude' => -121.907095,
     371                                ),
     372                        ),
     373
     374                        array(
     375                                'type'                 => 'meetup',
     376                                'title'                => 'WordPress Q&A',
     377                                'url'                  => 'https://www.meetup.com/sanjosewp/events/245419844/',
     378                                'meetup'               => 'The San Jose WordPress Meetup',
     379                                'meetup_url'           => 'https://www.meetup.com/sanjosewp/',
     380                                'start_unix_timestamp' => strtotime( 'next Wednesday 5:30pm' ),
     381                                'end_unix_timestamp'   => strtotime( 'next Wednesday 6:30pm' ),
     382
     383                                'location'             => array(
     384                                        'location'  => 'Milpitas, CA, USA',
     385                                        'country'   => 'us',
     386                                        'latitude'  => 37.244194,
     387                                        'longitude' => -121.889313,
     388                                ),
     389                        ),
     390
     391                        array(
     392                                'type'                 => 'wordcamp',
     393                                'title'                => 'WordCamp San Diego',
     394                                'url'                  => 'https://2018.sandiego.wordcamp.org',
     395                                'meetup'               => null,
     396                                'meetup_url'           => null,
     397                                'start_unix_timestamp' => strtotime( 'next Thursday 9am' ),
     398                                'end_unix_timestamp'   => strtotime( 'next Thursday 10am' ),
     399
     400                                'location'             => array(
     401                                        'location'  => 'San Diego, CA',
     402                                        'country'   => 'US',
     403                                        'latitude'  => 32.7220419,
     404                                        'longitude' => -117.1534513,
     405                                ),
    358406                        ),
    359407                );
     
    364412         * falls into the list.
    365413         *
     414         * @covers WP_Community_Events::trim_events
     415         *
    366416         * @since 4.9.7
    367          */
    368         public function test_get_events_dont_pin_multiple_wordcamps() {
    369                 add_filter( 'pre_http_request', array( $this, '_http_request_valid_response_multiple_wordcamps' ) );
    370 
    371                 $response_body = $this->instance->get_events();
     417         * @since 5.5.2 Tests `trim_events()` directly instead of indirectly via `get_events()`.
     418         */
     419        public function test_trim_events_dont_pin_multiple_wordcamps() {
     420                $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
     421                $trim_events->setAccessible( true );
     422
     423                $actual = $trim_events->invoke( $this->instance, $this->_events_with_multiple_wordcamps() );
    372424
    373425                /*
     
    375427                 * WordCamp LA should not be stuck to the list, because San Diego already appears naturally.
    376428                 */
    377                 $this->assertCount( 3, $response_body['events'] );
    378                 $this->assertEquals( $response_body['events'][0]['title'], 'WordCamp San Diego' );
    379                 $this->assertEquals( $response_body['events'][1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
    380                 $this->assertEquals( $response_body['events'][2]['title'], 'WordPress Q&A' );
    381 
    382                 remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response_multiple_wordcamps' ) );
     429                $this->assertCount( 3, $actual );
     430                $this->assertSame( $actual[0]['title'], 'WordCamp San Diego' );
     431                $this->assertSame( $actual[1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
     432                $this->assertSame( $actual[2]['title'], 'WordPress Q&A' );
    383433        }
    384434
     
    388438         *
    389439         * @since 4.9.7
     440         * @since 5.5.2 Tests `trim_events()` directly instead of indirectly via `get_events()`.
    390441         *
    391442         * @return array A mock HTTP response.
    392443         */
    393         public function _http_request_valid_response_multiple_wordcamps() {
    394                 return array(
    395                         'headers'  => '',
    396                         'response' => array( 'code' => 200 ),
    397                         'cookies'  => '',
    398                         'filename' => '',
    399                         'body'     => wp_json_encode(
    400                                 array(
    401                                         'location' => $this->get_user_location(),
    402                                         'events'   => array(
    403                                                 array(
    404                                                         'type'       => 'meetup',
    405                                                         'title'      => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
    406                                                         'url'        => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
    407                                                         'meetup'     => 'The East Bay WordPress Meetup Group',
    408                                                         'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
    409                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( '2 days ago' ) ),
    410                                                         'location'   => array(
    411                                                                 'location'  => 'Oakland, CA, USA',
    412                                                                 'country'   => 'us',
    413                                                                 'latitude'  => 37.808453,
    414                                                                 'longitude' => -122.26593,
    415                                                         ),
    416                                                 ),
    417                                                 array(
    418                                                         'type'       => 'wordcamp',
    419                                                         'title'      => 'WordCamp San Diego',
    420                                                         'url'        => 'https://2018.sandiego.wordcamp.org',
    421                                                         'meetup'     => null,
    422                                                         'meetup_url' => null,
    423                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Tuesday 9am' ) ),
    424                                                         'location'   => array(
    425                                                                 'location'  => 'San Diego, CA',
    426                                                                 'country'   => 'US',
    427                                                                 'latitude'  => 32.7220419,
    428                                                                 'longitude' => -117.1534513,
    429                                                         ),
    430                                                 ),
    431                                                 array(
    432                                                         'type'       => 'meetup',
    433                                                         'title'      => 'Part 3- Site Maintenance - Tools to Make It Easy',
    434                                                         'url'        => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
    435                                                         'meetup'     => 'WordPress Bay Area Foothills Group',
    436                                                         'meetup_url' => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
    437                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 1:30pm' ) ),
    438                                                         'location'   => array(
    439                                                                 'location'  => 'Milpitas, CA, USA',
    440                                                                 'country'   => 'us',
    441                                                                 'latitude'  => 37.432813,
    442                                                                 'longitude' => -121.907095,
    443                                                         ),
    444                                                 ),
    445                                                 array(
    446                                                         'type'       => 'meetup',
    447                                                         'title'      => 'WordPress Q&A',
    448                                                         'url'        => 'https://www.meetup.com/sanjosewp/events/245419844/',
    449                                                         'meetup'     => 'The San Jose WordPress Meetup',
    450                                                         'meetup_url' => 'https://www.meetup.com/sanjosewp/',
    451                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Thursday 5:30pm' ) ),
    452                                                         'location'   => array(
    453                                                                 'location'  => 'Milpitas, CA, USA',
    454                                                                 'country'   => 'us',
    455                                                                 'latitude'  => 37.244194,
    456                                                                 'longitude' => -121.889313,
    457                                                         ),
    458                                                 ),
    459                                                 array(
    460                                                         'type'       => 'wordcamp',
    461                                                         'title'      => 'WordCamp Los Angeles',
    462                                                         'url'        => 'https://2018.la.wordcamp.org',
    463                                                         'meetup'     => null,
    464                                                         'meetup_url' => null,
    465                                                         'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Friday 9am' ) ),
    466                                                         'location'   => array(
    467                                                                 'location'  => 'Los Angeles, CA',
    468                                                                 'country'   => 'US',
    469                                                                 'latitude'  => 34.050888,
    470                                                                 'longitude' => -118.285426,
    471                                                         ),
    472                                                 ),
    473                                         ),
    474                                 )
     444        public function _events_with_multiple_wordcamps() {
     445                return array(
     446                        array(
     447                                'type'                 => 'meetup',
     448                                'title'                => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
     449                                'url'                  => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
     450                                'meetup'               => 'The East Bay WordPress Meetup Group',
     451                                'meetup_url'           => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
     452                                'start_unix_timestamp' => strtotime( '2 days ago' ) - HOUR_IN_SECONDS,
     453                                'end_unix_timestamp'   => strtotime( '2 days ago' ),
     454
     455                                'location'             => array(
     456                                        'location'  => 'Oakland, CA, USA',
     457                                        'country'   => 'us',
     458                                        'latitude'  => 37.808453,
     459                                        'longitude' => -122.26593,
     460                                ),
     461                        ),
     462
     463                        array(
     464                                'type'                 => 'wordcamp',
     465                                'title'                => 'WordCamp San Diego',
     466                                'url'                  => 'https://2018.sandiego.wordcamp.org',
     467                                'meetup'               => null,
     468                                'meetup_url'           => null,
     469                                'start_unix_timestamp' => strtotime( 'next Tuesday 9am' ),
     470                                'end_unix_timestamp'   => strtotime( 'next Tuesday 10am' ),
     471
     472                                'location'             => array(
     473                                        'location'  => 'San Diego, CA',
     474                                        'country'   => 'US',
     475                                        'latitude'  => 32.7220419,
     476                                        'longitude' => -117.1534513,
     477                                ),
     478                        ),
     479
     480                        array(
     481                                'type'                 => 'meetup',
     482                                'title'                => 'Part 3- Site Maintenance - Tools to Make It Easy',
     483                                'url'                  => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
     484                                'meetup'               => 'WordPress Bay Area Foothills Group',
     485                                'meetup_url'           => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
     486                                'start_unix_timestamp' => strtotime( 'next Wednesday 1:30pm' ),
     487                                'end_unix_timestamp'   => strtotime( 'next Wednesday 2:30pm' ),
     488
     489                                'location'             => array(
     490                                        'location'  => 'Milpitas, CA, USA',
     491                                        'country'   => 'us',
     492                                        'latitude'  => 37.432813,
     493                                        'longitude' => -121.907095,
     494                                ),
     495                        ),
     496
     497                        array(
     498                                'type'                 => 'meetup',
     499                                'title'                => 'WordPress Q&A',
     500                                'url'                  => 'https://www.meetup.com/sanjosewp/events/245419844/',
     501                                'meetup'               => 'The San Jose WordPress Meetup',
     502                                'meetup_url'           => 'https://www.meetup.com/sanjosewp/',
     503                                'start_unix_timestamp' => strtotime( 'next Thursday 5:30pm' ),
     504                                'end_unix_timestamp'   => strtotime( 'next Thursday 6:30pm' ),
     505
     506                                'location'             => array(
     507                                        'location'  => 'Milpitas, CA, USA',
     508                                        'country'   => 'us',
     509                                        'latitude'  => 37.244194,
     510                                        'longitude' => -121.889313,
     511                                ),
     512                        ),
     513
     514                        array(
     515                                'type'                 => 'wordcamp',
     516                                'title'                => 'WordCamp Los Angeles',
     517                                'url'                  => 'https://2018.la.wordcamp.org',
     518                                'meetup'               => null,
     519                                'meetup_url'           => null,
     520                                'start_unix_timestamp' => strtotime( 'next Friday 9am' ),
     521                                'end_unix_timestamp'   => strtotime( 'next Friday 10am' ),
     522
     523                                'location'             => array(
     524                                        'location'  => 'Los Angeles, CA',
     525                                        'country'   => 'US',
     526                                        'latitude'  => 34.050888,
     527                                        'longitude' => -118.285426,
     528                                ),
    475529                        ),
    476530                );
  • branches/5.5/tests/qunit/index.html

    r48177 r49275  
    8484
    8585                <!-- Tested files -->
     86                <script src="../../build/wp-admin/js/dashboard.js"></script>
    8687                <script src="../../build/wp-admin/js/password-strength-meter.js"></script>
     88                <script src="../../build/wp-admin/js/postbox.js"></script>
     89                <script src="../../build/wp-includes/js/dist/vendor/moment.js"></script>
     90                <script src="../../build/wp-includes/js/dist/date.js"></script>
     91                <script src="../../build/wp-includes/js/dist/i18n.js"></script>
    8792                <script src="../../build/wp-includes/js/customize-base.js"></script>
    8893                <script src="../../build/wp-includes/js/customize-models.js"></script>
     
    142147                <script src="wp-admin/js/customize-base.js"></script>
    143148                <script src="wp-admin/js/customize-header.js"></script>
     149                <script src="wp-admin/js/dashboard.js"></script>
    144150                <script src="wp-includes/js/shortcode.js"></script>
    145151                <script src="wp-includes/js/api-request.js"></script>
Note: See TracChangeset for help on using the changeset viewer.