<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[49145] trunk: Community Events: Trim events by Unix timestamp for accuracy.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/49145">49145</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/49145","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>iandunn</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2020-10-14 18:17:55 +0000 (Wed, 14 Oct 2020)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>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 <a href="https://core.trac.wordpress.org/ticket/51130">#51130</a>
See #meta4480
Related: https://make.wordpress.org/core/2019/09/23/date-time-improvements-wp-5-3/</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadminincludesclasswpcommunityeventsphp">trunk/src/wp-admin/includes/class-wp-community-events.php</a></li>
<li><a href="#trunktestsphpunittestsadminincludesCommunityEventsphp">trunk/tests/phpunit/tests/admin/includesCommunityEvents.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadminincludesclasswpcommunityeventsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-community-events.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-community-events.php 2020-10-14 02:14:34 UTC (rev 49144)
+++ trunk/src/wp-admin/includes/class-wp-community-events.php   2020-10-14 18:17:55 UTC (rev 49145)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -158,9 +158,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $response_body['location']['description'] = $this->user_location['description'];
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        /*
+                        * Store the raw response, because events will expire before the cache does.
+                        * The response will need to be processed every page load.
+                        */
</ins><span class="cx" style="display: block; padding: 0 10px">                         $this->cache_events( $response_body, $expiration );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $response_body = $this->trim_events( $response_body );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $response_body['events'] = $this->trim_events( $response_body['events'] );
</ins><span class="cx" style="display: block; padding: 0 10px">                         $response_body = $this->format_event_data_time( $response_body );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        return $response_body;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -346,8 +350,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        public function get_cached_events() {
</span><span class="cx" style="display: block; padding: 0 10px">                $cached_response = get_site_transient( $this->get_events_transient_key( $this->user_location ) );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $cached_response = $this->trim_events( $cached_response );
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( isset( $cached_response['events'] ) ) {
+                       $cached_response['events'] = $this->trim_events( $cached_response['events'] );
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 return $this->format_event_data_time( $cached_response );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -435,44 +442,44 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.8.0
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.9.7 Stick a WordCamp to the final list.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 5.6.0 Accepts and returns only the events, rather than an entire HTTP response.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @param array $response_body The response body which contains the events.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * @param array $events The events that will be prepared.
</ins><span class="cx" style="display: block; padding: 0 10px">          * @return array The response body with events trimmed.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        protected function trim_events( $response_body ) {
-               if ( isset( $response_body['events'] ) ) {
-                       $wordcamps = array();
-                       $today     = current_time( 'Y-m-d' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ protected function trim_events( array $events ) {
+               $future_events = array();
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        foreach ( $response_body['events'] as $key => $event ) {
-                               /*
-                                * Skip WordCamps, because they might be multi-day events.
-                                * Save a copy so they can be pinned later.
-                                */
-                               if ( 'wordcamp' === $event['type'] ) {
-                                       $wordcamps[] = $event;
-                                       continue;
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         foreach ( $events as $event ) {
+                       /*
+                        * The API's `date` and `end_date` fields are in the _event's_ local timezone, but UTC is needed so
+                        * it can be converted to the _user's_ local time.
+                        */
+                       $end_time = (int) $event['end_unix_timestamp'];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // We don't get accurate time with timezone from API, so we only take the date part (Y-m-d).
-                               $event_date = substr( $event['date'], 0, 10 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( time() < $end_time ) {
+                               array_push( $future_events, $event );
+                       }
+               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( $today > $event_date ) {
-                                       unset( $response_body['events'][ $key ] );
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $future_wordcamps = array_filter(
+                       $future_events,
+                       function( $wordcamp ) {
+                               return 'wordcamp' === $wordcamp['type'];
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $response_body['events'] = array_slice( $response_body['events'], 0, 3 );
-                       $trimmed_event_types     = wp_list_pluck( $response_body['events'], 'type' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $future_wordcamps    = array_values( $future_wordcamps ); // Remove gaps in indices.
+               $trimmed_events      = array_slice( $future_events, 0, 3 );
+               $trimmed_event_types = wp_list_pluck( $trimmed_events, 'type' );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // Make sure the soonest upcoming WordCamp is pinned in the list.
-                       if ( ! in_array( 'wordcamp', $trimmed_event_types, true ) && $wordcamps ) {
-                               array_pop( $response_body['events'] );
-                               array_push( $response_body['events'], $wordcamps[0] );
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Make sure the soonest upcoming WordCamp is pinned in the list.
+               if ( $future_wordcamps && ! in_array( 'wordcamp', $trimmed_event_types, true ) ) {
+                       array_pop( $trimmed_events );
+                       array_push( $trimmed_events, $future_wordcamps[0] );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return $response_body;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return $trimmed_events;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span></span></pre></div>
<a id="trunktestsphpunittestsadminincludesCommunityEventsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/admin/includesCommunityEvents.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/admin/includesCommunityEvents.php       2020-10-14 02:14:34 UTC (rev 49144)
+++ trunk/tests/phpunit/tests/admin/includesCommunityEvents.php 2020-10-14 18:17:55 UTC (rev 49145)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -153,7 +153,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="cx" style="display: block; padding: 0 10px">         * Test: With a valid response, get_events() should return an associative array containing a location array and
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * an events array with individual events that have formatted time and date.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * an events array with individual events that have Unix start/end timestamps.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.8.0
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -164,15 +164,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertNotWPError( $response );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSameSetsWithIndex( $this->get_user_location(), $response['location'] );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertSame( gmdate( 'l, M j, Y', strtotime( 'next Sunday 1pm' ) ), $response['events'][0]['formatted_date'] );
-               $this->assertSame( '1:00 pm', $response['events'][0]['formatted_time'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertSame( strtotime( 'next Sunday 1pm' ), $response['events'][0]['start_unix_timestamp'] );
+               $this->assertSame( strtotime( 'next Sunday 2pm' ), $response['events'][0]['end_unix_timestamp'] );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response' ) );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * Test: get_cached_events() should return the same data as get_events(), including formatted time
-        * and date values for each event.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * Test: `get_cached_events()` should return the same data as get_events(), including Unix start/end
+        * timestamps for each event.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.8.0
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -185,8 +185,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertNotWPError( $cached_events );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSameSetsWithIndex( $this->get_user_location(), $cached_events['location'] );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertSame( gmdate( 'l, M j, Y', strtotime( 'next Sunday 1pm' ) ), $cached_events['events'][0]['formatted_date'] );
-               $this->assertSame( '1:00 pm', $cached_events['events'][0]['formatted_time'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertSame( strtotime( 'next Sunday 1pm' ), $cached_events['events'][0]['start_unix_timestamp'] );
+               $this->assertSame( strtotime( 'next Sunday 2pm' ), $cached_events['events'][0]['end_unix_timestamp'] );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response' ) );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -204,50 +204,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'body'     => wp_json_encode(
</span><span class="cx" style="display: block; padding: 0 10px">                                array(
</span><span class="cx" style="display: block; padding: 0 10px">                                        'location' => $this->get_user_location(),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        'events'   => array(
-                                               array(
-                                                       'type'       => 'meetup',
-                                                       'title'      => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
-                                                       'url'        => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
-                                                       'meetup'     => 'The East Bay WordPress Meetup Group',
-                                                       'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
-                                                       'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Sunday 1pm' ) ),
-                                                       'location'   => array(
-                                                               'location'  => 'Oakland, CA, USA',
-                                                               'country'   => 'us',
-                                                               'latitude'  => 37.808453,
-                                                               'longitude' => -122.26593,
-                                                       ),
-                                               ),
-                                               array(
-                                                       'type'       => 'meetup',
-                                                       'title'      => 'Part 3- Site Maintenance - Tools to Make It Easy',
-                                                       'url'        => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
-                                                       'meetup'     => 'WordPress Bay Area Foothills Group',
-                                                       'meetup_url' => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
-                                                       'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 1:30pm' ) ),
-                                                       'location'   => array(
-                                                               'location'  => 'Milpitas, CA, USA',
-                                                               'country'   => 'us',
-                                                               'latitude'  => 37.432813,
-                                                               'longitude' => -121.907095,
-                                                       ),
-                                               ),
-                                               array(
-                                                       'type'       => 'wordcamp',
-                                                       'title'      => 'WordCamp Kansas City',
-                                                       'url'        => 'https://2017.kansascity.wordcamp.org',
-                                                       'meetup'     => null,
-                                                       'meetup_url' => null,
-                                                       'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Saturday' ) ),
-                                                       'location'   => array(
-                                                               'location'  => 'Kansas City, MO',
-                                                               'country'   => 'US',
-                                                               'latitude'  => 39.0392325,
-                                                               'longitude' => -94.577076,
-                                                       ),
-                                               ),
-                                       ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 'events'   => $this->get_valid_events(),
</ins><span class="cx" style="display: block; padding: 0 10px">                                 )
</span><span class="cx" style="display: block; padding: 0 10px">                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                        'response' => array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -259,44 +216,127 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Get a sample of valid events.
+        *
+        * @return array[]
+        */
+       protected function get_valid_events() {
+               return array(
+                       array(
+                               'type'                 => 'meetup',
+                               'title'                => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
+                               'url'                  => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
+                               'meetup'               => 'The East Bay WordPress Meetup Group',
+                               'meetup_url'           => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
+                               'start_unix_timestamp' => strtotime( 'next Sunday 1pm' ),
+                               'end_unix_timestamp'   => strtotime( 'next Sunday 2pm' ),
+
+                               'location'             => array(
+                                       'location'  => 'Oakland, CA, USA',
+                                       'country'   => 'us',
+                                       'latitude'  => 37.808453,
+                                       'longitude' => -122.26593,
+                               ),
+                       ),
+
+                       array(
+                               'type'                 => 'meetup',
+                               'title'                => 'Part 3- Site Maintenance - Tools to Make It Easy',
+                               'url'                  => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
+                               'meetup'               => 'WordPress Bay Area Foothills Group',
+                               'meetup_url'           => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
+                               'start_unix_timestamp' => strtotime( 'next Wednesday 1:30pm' ),
+                               'end_unix_timestamp'   => strtotime( 'next Wednesday 2:30pm' ),
+
+                               'location'             => array(
+                                       'location'  => 'Milpitas, CA, USA',
+                                       'country'   => 'us',
+                                       'latitude'  => 37.432813,
+                                       'longitude' => -121.907095,
+                               ),
+                       ),
+
+                       array(
+                               'type'                 => 'wordcamp',
+                               'title'                => 'WordCamp San Francisco',
+                               'url'                  => 'https://sf.wordcamp.org/2020/',
+                               'meetup'               => null,
+                               'meetup_url'           => null,
+                               'start_unix_timestamp' => strtotime( 'next Saturday' ),
+                               'end_unix_timestamp'   => strtotime( 'next Saturday 8pm' ),
+
+                               'location'             => array(
+                                       'location'  => 'San Francisco, CA',
+                                       'country'   => 'US',
+                                       'latitude'  => 37.432813,
+                                       'longitude' => -121.907095,
+                               ),
+                       ),
+               );
+       }
+
+       /**
+        * Test: `trim_events()` should immediately remove expired events.
+        *
+        * @covers WP_Community_Events::trim_events
+        *
+        * @since 5.6.0
+        */
+       public function test_trim_expired_events() {
+               $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
+               $trim_events->setAccessible( true );
+
+               $events = $this->get_valid_events();
+
+               // This should be removed because it's already ended.
+               $events[0]['start_unix_timestamp'] = strtotime( '1 hour ago' );
+               $events[0]['end_unix_timestamp']   = strtotime( '2 seconds ago' );
+
+               // This should remain because it hasn't ended yet.
+               $events[1]['start_unix_timestamp'] = strtotime( '2 seconds ago' );
+               $events[1]['end_unix_timestamp']   = strtotime( '+1 hour' );
+
+               $actual = $trim_events->invoke( $this->instance, $events );
+
+               $this->assertCount( 2, $actual );
+               $this->assertSame( $actual[0]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
+               $this->assertSame( $actual[1]['title'], 'WordCamp San Francisco' );
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Test: get_events() should return the events with the WordCamp pinned in the prepared list.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @covers WP_Community_Events::trim_events
+        *
</ins><span class="cx" style="display: block; padding: 0 10px">          * @since 4.9.7
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 5.6.0 Tests `trim_events()` directly instead of indirectly via `get_events()`.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function test_get_events_pin_wordcamp() {
-               add_filter( 'pre_http_request', array( $this, '_http_request_valid_response_unpinned_wordcamp' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_trim_events_pin_wordcamp() {
+               $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
+               $trim_events->setAccessible( true );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $response_body = $this->instance->get_events();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $actual = $trim_events->invoke( $this->instance, $this->_events_with_unpinned_wordcamp() );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /*
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * San Diego was at position 3 in the mock API response, but pinning puts it at position 2,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * San Diego was at index 3 in the mock API response, but pinning puts it at index 2,
</ins><span class="cx" style="display: block; padding: 0 10px">                  * so that it remains in the list. The other events should remain unchanged.
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertCount( 3, $response_body['events'] );
-               $this->assertSame( $response_body['events'][0]['title'], 'Flexbox + CSS Grid: Magic for Responsive Layouts' );
-               $this->assertSame( $response_body['events'][1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
-               $this->assertSame( $response_body['events'][2]['title'], 'WordCamp San Diego' );
-
-               remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response_unpinned_wordcamp' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertCount( 3, $actual );
+               $this->assertSame( $actual[0]['title'], 'Flexbox + CSS Grid: Magic for Responsive Layouts' );
+               $this->assertSame( $actual[1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
+               $this->assertSame( $actual[2]['title'], 'WordCamp San Diego' );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * Simulates a valid HTTP response where a WordCamp needs to be pinned higher than it's default position.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * Simulates a scenario where a WordCamp needs to be pinned higher than it's default position.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.9.7
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 5.6.0 Accepts and returns only the events, rather than an entire HTTP response.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @return array A mock HTTP response.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * @return array A list of mock events.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function _http_request_valid_response_unpinned_wordcamp() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function _events_with_unpinned_wordcamp() {
</ins><span class="cx" style="display: block; padding: 0 10px">                 return array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'headers'  => '',
-                       'response' => array( 'code' => 200 ),
-                       'cookies'  => '',
-                       'filename' => '',
-                       'body'     => wp_json_encode(
-                               array(
-                                       'location' => $this->get_user_location(),
-                                       'events'   => array(
</del><span class="cx" style="display: block; padding: 0 10px">                                                 array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'type'       => 'meetup',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'title'      => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -303,7 +343,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'url'        => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup'     => 'The East Bay WordPress Meetup Group',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Monday 1pm' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'start_unix_timestamp' => strtotime( 'next Monday 1pm' ),
+                                                       'end_unix_timestamp'   => strtotime( 'next Monday 2pm' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'location'   => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'location'  => 'Oakland, CA, USA',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'country'   => 'us',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -317,7 +359,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'url'        => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup'     => 'WordPress Bay Area Foothills Group',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup_url' => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Tuesday 1:30pm' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'start_unix_timestamp' => strtotime( 'next Tuesday 1:30pm' ),
+                                                       'end_unix_timestamp'   => strtotime( 'next Tuesday 2:30pm' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'location'   => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'location'  => 'Milpitas, CA, USA',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'country'   => 'us',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -331,7 +375,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'url'        => 'https://www.meetup.com/sanjosewp/events/245419844/',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup'     => 'The San Jose WordPress Meetup',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup_url' => 'https://www.meetup.com/sanjosewp/',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 5:30pm' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'start_unix_timestamp' => strtotime( 'next Wednesday 5:30pm' ),
+                                                       'end_unix_timestamp'   => strtotime( 'next Wednesday 6:30pm' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'location'   => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'location'  => 'Milpitas, CA, USA',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'country'   => 'us',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -345,7 +391,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'url'        => 'https://2018.sandiego.wordcamp.org',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup'     => null,
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup_url' => null,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Thursday 9am' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'start_unix_timestamp' => strtotime( 'next Thursday 9am' ),
+                                                       'end_unix_timestamp'   => strtotime( 'next Thursday 10am' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'location'   => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'location'  => 'San Diego, CA',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'country'   => 'US',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -353,9 +401,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'longitude' => -117.1534513,
</span><span class="cx" style="display: block; padding: 0 10px">                                                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        ),
-                               )
-                       ),
</del><span class="cx" style="display: block; padding: 0 10px">                 );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -363,23 +408,25 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * Test: get_events() shouldn't stick an extra WordCamp when there's already one that naturally
</span><span class="cx" style="display: block; padding: 0 10px">         * falls into the list.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @covers WP_Community_Events::trim_events
+        *
</ins><span class="cx" style="display: block; padding: 0 10px">          * @since 4.9.7
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 5.6.0 Tests `trim_events()` directly instead of indirectly via `get_events()`.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function test_get_events_dont_pin_multiple_wordcamps() {
-               add_filter( 'pre_http_request', array( $this, '_http_request_valid_response_multiple_wordcamps' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_trim_events_dont_pin_multiple_wordcamps() {
+               $trim_events = new ReflectionMethod( $this->instance, 'trim_events' );
+               $trim_events->setAccessible( true );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $response_body = $this->instance->get_events();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $actual = $trim_events->invoke( $this->instance, $this->_events_with_multiple_wordcamps() );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /*
</span><span class="cx" style="display: block; padding: 0 10px">                 * The first meetup should be removed because it's expired, while the next 3 events are selected.
</span><span class="cx" style="display: block; padding: 0 10px">                 * WordCamp LA should not be stuck to the list, because San Diego already appears naturally.
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertCount( 3, $response_body['events'] );
-               $this->assertSame( $response_body['events'][0]['title'], 'WordCamp San Diego' );
-               $this->assertSame( $response_body['events'][1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
-               $this->assertSame( $response_body['events'][2]['title'], 'WordPress Q&A' );
-
-               remove_filter( 'pre_http_request', array( $this, '_http_request_valid_response_multiple_wordcamps' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertCount( 3, $actual );
+               $this->assertSame( $actual[0]['title'], 'WordCamp San Diego' );
+               $this->assertSame( $actual[1]['title'], 'Part 3- Site Maintenance - Tools to Make It Easy' );
+               $this->assertSame( $actual[2]['title'], 'WordPress Q&A' );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -387,19 +434,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * no need to pin extra camp b/c one already exists in response
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.9.7
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 5.6.0 Tests `trim_events()` directly instead of indirectly via `get_events()`.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @return array A mock HTTP response.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function _http_request_valid_response_multiple_wordcamps() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function _events_with_multiple_wordcamps() {
</ins><span class="cx" style="display: block; padding: 0 10px">                 return array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'headers'  => '',
-                       'response' => array( 'code' => 200 ),
-                       'cookies'  => '',
-                       'filename' => '',
-                       'body'     => wp_json_encode(
-                               array(
-                                       'location' => $this->get_user_location(),
-                                       'events'   => array(
</del><span class="cx" style="display: block; padding: 0 10px">                                                 array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'type'       => 'meetup',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'title'      => 'Flexbox + CSS Grid: Magic for Responsive Layouts',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -406,7 +446,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'url'        => 'https://www.meetup.com/Eastbay-WordPress-Meetup/events/236031233/',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup'     => 'The East Bay WordPress Meetup Group',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup_url' => 'https://www.meetup.com/Eastbay-WordPress-Meetup/',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'date'       => gmdate( 'Y-m-d H:i:s', strtotime( '2 days ago' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'start_unix_timestamp' => strtotime( '2 days ago' ) - HOUR_IN_SECONDS,
+                                                       'end_unix_timestamp'   => strtotime( '2 days ago' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'location'   => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'location'  => 'Oakland, CA, USA',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'country'   => 'us',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -414,6 +456,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'longitude' => -122.26593,
</span><span class="cx" style="display: block; padding: 0 10px">                                                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'type'       => 'wordcamp',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'title'      => 'WordCamp San Diego',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -420,7 +463,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'url'        => 'https://2018.sandiego.wordcamp.org',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup'     => null,
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup_url' => null,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Tuesday 9am' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'start_unix_timestamp' => strtotime( 'next Tuesday 9am' ),
+                                                       'end_unix_timestamp'   => strtotime( 'next Tuesday 10am' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'location'   => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'location'  => 'San Diego, CA',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'country'   => 'US',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -428,6 +473,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'longitude' => -117.1534513,
</span><span class="cx" style="display: block; padding: 0 10px">                                                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'type'       => 'meetup',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'title'      => 'Part 3- Site Maintenance - Tools to Make It Easy',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -434,7 +480,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'url'        => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/events/237706839/',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup'     => 'WordPress Bay Area Foothills Group',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup_url' => 'https://www.meetup.com/Wordpress-Bay-Area-CA-Foothills/',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Wednesday 1:30pm' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'start_unix_timestamp' => strtotime( 'next Wednesday 1:30pm' ),
+                                                       'end_unix_timestamp'   => strtotime( 'next Wednesday 2:30pm' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'location'   => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'location'  => 'Milpitas, CA, USA',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'country'   => 'us',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -442,6 +490,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'longitude' => -121.907095,
</span><span class="cx" style="display: block; padding: 0 10px">                                                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'type'       => 'meetup',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'title'      => 'WordPress Q&A',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -448,7 +497,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'url'        => 'https://www.meetup.com/sanjosewp/events/245419844/',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup'     => 'The San Jose WordPress Meetup',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup_url' => 'https://www.meetup.com/sanjosewp/',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Thursday 5:30pm' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'start_unix_timestamp' => strtotime( 'next Thursday 5:30pm' ),
+                                                       'end_unix_timestamp'   => strtotime( 'next Thursday 6:30pm' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'location'   => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'location'  => 'Milpitas, CA, USA',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'country'   => 'us',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -456,6 +507,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'longitude' => -121.889313,
</span><span class="cx" style="display: block; padding: 0 10px">                                                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'type'       => 'wordcamp',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'title'      => 'WordCamp Los Angeles',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -462,7 +514,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'url'        => 'https://2018.la.wordcamp.org',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup'     => null,
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'meetup_url' => null,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'date'       => gmdate( 'Y-m-d H:i:s', strtotime( 'next Friday 9am' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'start_unix_timestamp' => strtotime( 'next Friday 9am' ),
+                                                       'end_unix_timestamp'   => strtotime( 'next Friday 10am' ),
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'location'   => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'location'  => 'Los Angeles, CA',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'country'   => 'US',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -470,9 +524,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'longitude' => -118.285426,
</span><span class="cx" style="display: block; padding: 0 10px">                                                        ),
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        ),
-                               )
-                       ),
</del><span class="cx" style="display: block; padding: 0 10px">                 );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre>
</div>
</div>

</body>
</html>