WordPress.org

Make WordPress Core

Changeset 49145


Ignore:
Timestamp:
10/14/2020 06:17:55 PM (11 months ago)
Author:
iandunn
Message:

Community Events: Trim events by Unix timestamp for accuracy.

The date and end_date fields are WP timestamps representing the venue's local time. As of meta:changeset:10270 (#meta4480), new start_unix_timestamp and end_unix_timestamp values are available, providing a proper Unix timestamp in the UTC timezone. Using those is more precise, and removes the time window where the event has expired but still appears in the Events Widget.

To simplify the function, it now only accepts and returns the events themselves, rather than the entire response body.

See #51130
See #meta4480
Related: https://make.wordpress.org/core/2019/09/23/date-time-improvements-wp-5-3/

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-community-events.php

    r48991 r49145  
    159159            }
    160160
     161            /*
     162             * Store the raw response, because events will expire before the cache does.
     163             * The response will need to be processed every page load.
     164             */
    161165            $this->cache_events( $response_body, $expiration );
    162166
    163             $response_body = $this->trim_events( $response_body );
     167            $response_body['events'] = $this->trim_events( $response_body['events'] );
    164168            $response_body = $this->format_event_data_time( $response_body );
    165169
     
    347351    public function get_cached_events() {
    348352        $cached_response = get_site_transient( $this->get_events_transient_key( $this->user_location ) );
    349         $cached_response = $this->trim_events( $cached_response );
     353
     354        if ( isset( $cached_response['events'] ) ) {
     355            $cached_response['events'] = $this->trim_events( $cached_response['events'] );
     356        }
    350357
    351358        return $this->format_event_data_time( $cached_response );
     
    436443     * @since 4.8.0
    437444     * @since 4.9.7 Stick a WordCamp to the final list.
    438      *
    439      * @param array $response_body The response body which contains the events.
     445     * @since 5.6.0 Accepts and returns only the events, rather than an entire HTTP response.
     446     *
     447     * @param array $events The events that will be prepared.
    440448     * @return array The response body with events trimmed.
    441449     */
    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;
     450    protected function trim_events( array $events ) {
     451        $future_events = array();
     452
     453        foreach ( $events as $event ) {
     454            /*
     455             * The API's `date` and `end_date` fields are in the _event's_ local timezone, but UTC is needed so
     456             * it can be converted to the _user's_ local time.
     457             */
     458            $end_time = (int) $event['end_unix_timestamp'];
     459
     460            if ( time() < $end_time ) {
     461                array_push( $future_events, $event );
     462            }
     463        }
     464
     465        $future_wordcamps = array_filter(
     466            $future_events,
     467            function( $wordcamp ) {
     468                return 'wordcamp' === $wordcamp['type'];
     469            }
     470        );
     471
     472        $future_wordcamps    = array_values( $future_wordcamps ); // Remove gaps in indices.
     473        $trimmed_events      = array_slice( $future_events, 0, 3 );
     474        $trimmed_event_types = wp_list_pluck( $trimmed_events, 'type' );
     475
     476        // Make sure the soonest upcoming WordCamp is pinned in the list.
     477        if ( $future_wordcamps && ! in_array( 'wordcamp', $trimmed_event_types, true ) ) {
     478            array_pop( $trimmed_events );
     479            array_push( $trimmed_events, $future_wordcamps[0] );
     480        }
     481
     482        return $trimmed_events;
    476483    }
    477484
  • trunk/tests/phpunit/tests/admin/includesCommunityEvents.php

    r48939 r49145  
    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->assertSameSetsWithIndex( $this->get_user_location(), $response['location'] );
    167         $this->assertSame( gmdate( 'l, M j, Y', strtotime( 'next Sunday 1pm' ) ), $response['events'][0]['formatted_date'] );
    168         $this->assertSame( '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->assertSameSetsWithIndex( $this->get_user_location(), $cached_events['location'] );
    188         $this->assertSame( gmdate( 'l, M j, Y', strtotime( 'next Sunday 1pm' ) ), $cached_events['events'][0]['formatted_date'] );
    189         $this->assertSame( '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(
     207                    'events'   => $this->get_valid_events(),
     208                )
     209            ),
     210            'response' => array(
     211                'code' => 200,
     212            ),
     213            'cookies'  => '',
     214            'filename' => '',
     215        );
     216    }
     217
     218    /**
     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.6.0
     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    /**
     307     * Test: get_events() should return the events with the WordCamp pinned in the prepared list.
     308     *
     309     * @covers WP_Community_Events::trim_events
     310     *
     311     * @since 4.9.7
     312     * @since 5.6.0 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() );
     319
     320        /*
     321         * San Diego was at index 3 in the mock API response, but pinning puts it at index 2,
     322         * so that it remains in the list. The other events should remain unchanged.
     323         */
     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.
     332     *
     333     * @since 4.9.7
     334     * @since 5.6.0 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(
    208340                        array(
    209341                            'type'       => 'meetup',
     
    212344                            'meetup'     => 'The East Bay WordPress Meetup Group',
    213345                            'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
    214                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Sunday 1pm' ) ),
     346                            'start_unix_timestamp' => strtotime( 'next Monday 1pm' ),
     347                            'end_unix_timestamp'   => strtotime( 'next Monday 2pm' ),
     348
    215349                            'location'   => array(
    216350                                'location'  => 'Oakland, CA, USA',
     
    226360                            'meetup'     => 'WordPress Bay Area Foothills Group',
    227361                            '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' ) ),
     362                            'start_unix_timestamp' => strtotime( 'next Tuesday 1:30pm' ),
     363                            'end_unix_timestamp'   => strtotime( 'next Tuesday 2:30pm' ),
     364
    229365                            'location'   => array(
    230366                                'location'  => 'Milpitas, CA, USA',
     
    235371                        ),
    236372                        array(
     373                            'type'       => 'meetup',
     374                            'title'      => 'WordPress Q&A',
     375                            'url'        => 'https://www.meetup.com/sanjosewp/events/245419844/',
     376                            'meetup'     => 'The San Jose WordPress Meetup',
     377                            'meetup_url' => 'https://www.meetup.com/sanjosewp/',
     378                            'start_unix_timestamp' => strtotime( 'next Wednesday 5:30pm' ),
     379                            'end_unix_timestamp'   => strtotime( 'next Wednesday 6:30pm' ),
     380
     381                            'location'   => array(
     382                                'location'  => 'Milpitas, CA, USA',
     383                                'country'   => 'us',
     384                                'latitude'  => 37.244194,
     385                                'longitude' => -121.889313,
     386                            ),
     387                        ),
     388                        array(
    237389                            'type'       => 'wordcamp',
    238                             'title'      => 'WordCamp Kansas City',
    239                             'url'        => 'https://2017.kansascity.wordcamp.org',
     390                            'title'      => 'WordCamp San Diego',
     391                            'url'        => 'https://2018.sandiego.wordcamp.org',
    240392                            'meetup'     => null,
    241393                            'meetup_url' => null,
    242                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Saturday' ) ),
    243                             'location'   => array(
    244                                 'location'  => 'Kansas City, MO',
     394                            'start_unix_timestamp' => strtotime( 'next Thursday 9am' ),
     395                            'end_unix_timestamp'   => strtotime( 'next Thursday 10am' ),
     396
     397                            'location'   => array(
     398                                'location'  => 'San Diego, CA',
    245399                                'country'   => 'US',
    246                                 'latitude'  => 39.0392325,
    247                                 'longitude' => -94.577076,
    248                             ),
    249                         ),
    250                     ),
    251                 )
    252             ),
    253             'response' => array(
    254                 'code' => 200,
    255             ),
    256             'cookies'  => '',
    257             'filename' => '',
    258         );
    259     }
    260 
    261     /**
    262      * Test: get_events() should return the events with the WordCamp pinned in the prepared list.
     400                                'latitude'  => 32.7220419,
     401                                'longitude' => -117.1534513,
     402                            ),
     403                        ),
     404        );
     405    }
     406
     407    /**
     408     * Test: get_events() shouldn't stick an extra WordCamp when there's already one that naturally
     409     * falls into the list.
     410     *
     411     * @covers WP_Community_Events::trim_events
    263412     *
    264413     * @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();
     414     * @since 5.6.0 Tests `trim_events()` directly instead of indirectly via `get_events()`.
     415     */
     416    public function test_trim_events_dont_pin_multiple_wordcamps() {
     417        $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
     418        $trim_events->setAccessible( true );
     419
     420        $actual = $trim_events->invoke( $this->instance, $this->_events_with_multiple_wordcamps() );
    270421
    271422        /*
    272          * San Diego was at position 3 in the mock API response, but pinning puts it at position 2,
    273          * so that it remains in the list. The other events should remain unchanged.
     423         * The first meetup should be removed because it's expired, while the next 3 events are selected.
     424         * WordCamp LA should not be stuck to the list, because San Diego already appears naturally.
    274425         */
    275         $this->assertCount( 3, $response_body['events'] );
    276         $this->assertSame( $response_body['events'][0]['title'], 'Flexbox + CSS Grid: Magic for Responsive Layouts' );
    277         $this->assertSame( $response_body['events'][1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
    278         $this->assertSame( $response_body['events'][2]['title'], 'WordCamp San Diego' );
    279 
    280         remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response_unpinned_wordcamp' ) );
     426        $this->assertCount( 3, $actual );
     427        $this->assertSame( $actual[0]['title'], 'WordCamp San Diego' );
     428        $this->assertSame( $actual[1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
     429        $this->assertSame( $actual[2]['title'], 'WordPress Q&A' );
    281430    }
    282431
    283432    /**
    284433     * Simulates a valid HTTP response where a WordCamp needs to be pinned higher than it's default position.
     434     * no need to pin extra camp b/c one already exists in response
    285435     *
    286436     * @since 4.9.7
     437     * @since 5.6.0 Tests `trim_events()` directly instead of indirectly via `get_events()`.
    287438     *
    288439     * @return array A mock HTTP response.
    289440     */
    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(
     441    public function _events_with_multiple_wordcamps() {
     442        return array(
    300443                        array(
    301444                            'type'       => 'meetup',
     
    304447                            'meetup'     => 'The East Bay WordPress Meetup Group',
    305448                            'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
    306                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Monday 1pm' ) ),
     449                            'start_unix_timestamp' => strtotime( '2 days ago' ) - HOUR_IN_SECONDS,
     450                            'end_unix_timestamp'   => strtotime( '2 days ago' ),
     451
    307452                            'location'   => array(
    308453                                'location'  => 'Oakland, CA, USA',
     
    312457                            ),
    313458                        ),
     459
     460                        array(
     461                            'type'       => 'wordcamp',
     462                            'title'      => 'WordCamp San Diego',
     463                            'url'        => 'https://2018.sandiego.wordcamp.org',
     464                            'meetup'     => null,
     465                            'meetup_url' => null,
     466                            'start_unix_timestamp' => strtotime( 'next Tuesday 9am' ),
     467                            'end_unix_timestamp'   => strtotime( 'next Tuesday 10am' ),
     468
     469                            'location'   => array(
     470                                'location'  => 'San Diego, CA',
     471                                'country'   => 'US',
     472                                'latitude'  => 32.7220419,
     473                                'longitude' => -117.1534513,
     474                            ),
     475                        ),
     476
    314477                        array(
    315478                            'type'       => 'meetup',
     
    318481                            'meetup'     => 'WordPress Bay Area Foothills Group',
    319482                            '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' ) ),
     483                            'start_unix_timestamp' => strtotime( 'next Wednesday 1:30pm' ),
     484                            'end_unix_timestamp'   => strtotime( 'next Wednesday 2:30pm' ),
     485
    321486                            'location'   => array(
    322487                                'location'  => 'Milpitas, CA, USA',
     
    326491                            ),
    327492                        ),
     493
    328494                        array(
    329495                            'type'       => 'meetup',
     
    332498                            'meetup'     => 'The San Jose WordPress Meetup',
    333499                            'meetup_url' => 'https://www.meetup.com/sanjosewp/',
    334                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 5:30pm' ) ),
     500                            'start_unix_timestamp' => strtotime( 'next Thursday 5:30pm' ),
     501                            'end_unix_timestamp'   => strtotime( 'next Thursday 6:30pm' ),
     502
    335503                            'location'   => array(
    336504                                'location'  => 'Milpitas, CA, USA',
     
    340508                            ),
    341509                        ),
    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                 )
    358             ),
    359         );
    360     }
    361 
    362     /**
    363      * Test: get_events() shouldn't stick an extra WordCamp when there's already one that naturally
    364      * falls into the list.
    365      *
    366      * @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();
    372 
    373         /*
    374          * The first meetup should be removed because it's expired, while the next 3 events are selected.
    375          * WordCamp LA should not be stuck to the list, because San Diego already appears naturally.
    376          */
    377         $this->assertCount( 3, $response_body['events'] );
    378         $this->assertSame( $response_body['events'][0]['title'], 'WordCamp San Diego' );
    379         $this->assertSame( $response_body['events'][1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
    380         $this->assertSame( $response_body['events'][2]['title'], 'WordPress Q&A' );
    381 
    382         remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response_multiple_wordcamps' ) );
    383     }
    384 
    385     /**
    386      * Simulates a valid HTTP response where a WordCamp needs to be pinned higher than it's default position.
    387      * no need to pin extra camp b/c one already exists in response
    388      *
    389      * @since 4.9.7
    390      *
    391      * @return array A mock HTTP response.
    392      */
    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                         ),
     510
    459511                        array(
    460512                            'type'       => 'wordcamp',
     
    463515                            'meetup'     => null,
    464516                            'meetup_url' => null,
    465                             'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Friday 9am' ) ),
     517                            'start_unix_timestamp' => strtotime( 'next Friday 9am' ),
     518                            'end_unix_timestamp'   => strtotime( 'next Friday 10am' ),
     519
    466520                            'location'   => array(
    467521                                'location'  => 'Los Angeles, CA',
     
    471525                            ),
    472526                        ),
    473                     ),
    474                 )
    475             ),
    476527        );
    477528    }
Note: See TracChangeset for help on using the changeset viewer.