wp/wp-admin/includes/class-wp-community-events.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
    90 
    90 
    91 		if ( ! $location_search && $cached_events ) {
    91 		if ( ! $location_search && $cached_events ) {
    92 			return $cached_events;
    92 			return $cached_events;
    93 		}
    93 		}
    94 
    94 
    95 		// include an unmodified $wp_version
    95 		// Include an unmodified $wp_version.
    96 		include( ABSPATH . WPINC . '/version.php' );
    96 		require ABSPATH . WPINC . '/version.php';
    97 
    97 
    98 		$api_url                    = 'http://api.wordpress.org/events/1.0/';
    98 		$api_url                    = 'http://api.wordpress.org/events/1.0/';
    99 		$request_args               = $this->get_request_args( $location_search, $timezone );
    99 		$request_args               = $this->get_request_args( $location_search, $timezone );
   100 		$request_args['user-agent'] = 'WordPress/' . $wp_version . '; ' . home_url( '/' );
   100 		$request_args['user-agent'] = 'WordPress/' . $wp_version . '; ' . home_url( '/' );
   101 
   101 
   111 		if ( is_wp_error( $response ) ) {
   111 		if ( is_wp_error( $response ) ) {
   112 			$response_error = $response;
   112 			$response_error = $response;
   113 		} elseif ( 200 !== $response_code ) {
   113 		} elseif ( 200 !== $response_code ) {
   114 			$response_error = new WP_Error(
   114 			$response_error = new WP_Error(
   115 				'api-error',
   115 				'api-error',
   116 				/* translators: %d: numeric HTTP status code, e.g. 400, 403, 500, 504, etc. */
   116 				/* translators: %d: Numeric HTTP status code, e.g. 400, 403, 500, 504, etc. */
   117 				sprintf( __( 'Invalid API response code (%d)' ), $response_code )
   117 				sprintf( __( 'Invalid API response code (%d).' ), $response_code )
   118 			);
   118 			);
   119 		} elseif ( ! isset( $response_body['location'], $response_body['events'] ) ) {
   119 		} elseif ( ! isset( $response_body['location'], $response_body['events'] ) ) {
   120 			$response_error = new WP_Error(
   120 			$response_error = new WP_Error(
   121 				'api-invalid-response',
   121 				'api-invalid-response',
   122 				isset( $response_body['error'] ) ? $response_body['error'] : __( 'Unknown API error.' )
   122 				isset( $response_body['error'] ) ? $response_body['error'] : __( 'Unknown API error.' )
   227 	 * _NOT_ guarantee that the returned address is valid or accurate, and it can
   227 	 * _NOT_ guarantee that the returned address is valid or accurate, and it can
   228 	 * be easily spoofed.
   228 	 * be easily spoofed.
   229 	 *
   229 	 *
   230 	 * @since 4.8.0
   230 	 * @since 4.8.0
   231 	 *
   231 	 *
   232 	 * @return false|string The anonymized address on success; the given address
   232 	 * @return string|false The anonymized address on success; the given address
   233 	 *                      or false on failure.
   233 	 *                      or false on failure.
   234 	 */
   234 	 */
   235 	public static function get_unsafe_client_ip() {
   235 	public static function get_unsafe_client_ip() {
   236 		$client_ip = false;
   236 		$client_ip = false;
   237 
   237 
   298 	 * functions, and having it abstracted keeps the logic consistent and DRY,
   298 	 * functions, and having it abstracted keeps the logic consistent and DRY,
   299 	 * which is less prone to errors.
   299 	 * which is less prone to errors.
   300 	 *
   300 	 *
   301 	 * @since 4.8.0
   301 	 * @since 4.8.0
   302 	 *
   302 	 *
   303 	 * @param  array $location Should contain 'latitude' and 'longitude' indexes.
   303 	 * @param array $location Should contain 'latitude' and 'longitude' indexes.
   304 	 * @return bool|string false on failure, or a string on success.
   304 	 * @return bool|string false on failure, or a string on success.
   305 	 */
   305 	 */
   306 	protected function get_events_transient_key( $location ) {
   306 	protected function get_events_transient_key( $location ) {
   307 		$key = false;
   307 		$key = false;
   308 
   308 
   339 	/**
   339 	/**
   340 	 * Gets cached events.
   340 	 * Gets cached events.
   341 	 *
   341 	 *
   342 	 * @since 4.8.0
   342 	 * @since 4.8.0
   343 	 *
   343 	 *
   344 	 * @return false|array false on failure; an array containing `location`
   344 	 * @return array|false An array containing `location` and `events` items
   345 	 *                     and `events` items on success.
   345 	 *                     on success, false on failure.
   346 	 */
   346 	 */
   347 	public function get_cached_events() {
   347 	public function get_cached_events() {
   348 		$cached_response = get_site_transient( $this->get_events_transient_key( $this->user_location ) );
   348 		$cached_response = get_site_transient( $this->get_events_transient_key( $this->user_location ) );
   349 		$cached_response = $this->trim_events( $cached_response );
   349 		$cached_response = $this->trim_events( $cached_response );
   350 
   350 
   359 	 * the cache, then all users would see the events in the localized data/time
   359 	 * the cache, then all users would see the events in the localized data/time
   360 	 * of the user who triggered the cache refresh, rather than their own.
   360 	 * of the user who triggered the cache refresh, rather than their own.
   361 	 *
   361 	 *
   362 	 * @since 4.8.0
   362 	 * @since 4.8.0
   363 	 *
   363 	 *
   364 	 * @param  array $response_body The response which contains the events.
   364 	 * @param array $response_body The response which contains the events.
   365 	 * @return array The response with dates and times formatted.
   365 	 * @return array The response with dates and times formatted.
   366 	 */
   366 	 */
   367 	protected function format_event_data_time( $response_body ) {
   367 	protected function format_event_data_time( $response_body ) {
   368 		if ( isset( $response_body['events'] ) ) {
   368 		if ( isset( $response_body['events'] ) ) {
   369 			foreach ( $response_body['events'] as $key => $event ) {
   369 			foreach ( $response_body['events'] as $key => $event ) {
   373 				 * The `date_format` option is not used because it's important
   373 				 * The `date_format` option is not used because it's important
   374 				 * in this context to keep the day of the week in the formatted date,
   374 				 * in this context to keep the day of the week in the formatted date,
   375 				 * so that users can tell at a glance if the event is on a day they
   375 				 * so that users can tell at a glance if the event is on a day they
   376 				 * are available, without having to open the link.
   376 				 * are available, without having to open the link.
   377 				 */
   377 				 */
   378 				/* translators: Date format for upcoming events on the dashboard. Include the day of the week. See https://secure.php.net/date. */
   378 				/* translators: Date format for upcoming events on the dashboard. Include the day of the week. See https://www.php.net/date */
   379 				$response_body['events'][ $key ]['formatted_date'] = date_i18n( __( 'l, M j, Y' ), $timestamp );
   379 				$formatted_date = date_i18n( __( 'l, M j, Y' ), $timestamp );
   380 				$response_body['events'][ $key ]['formatted_time'] = date_i18n( get_option( 'time_format' ), $timestamp );
   380 				$formatted_time = date_i18n( get_option( 'time_format' ), $timestamp );
       
   381 
       
   382 				if ( isset( $event['end_date'] ) ) {
       
   383 					$end_timestamp      = strtotime( $event['end_date'] );
       
   384 					$formatted_end_date = date_i18n( __( 'l, M j, Y' ), $end_timestamp );
       
   385 
       
   386 					if ( 'meetup' !== $event['type'] && $formatted_end_date !== $formatted_date ) {
       
   387 						/* translators: Upcoming events month format. See https://www.php.net/date */
       
   388 						$start_month = date_i18n( _x( 'F', 'upcoming events month format' ), $timestamp );
       
   389 						$end_month   = date_i18n( _x( 'F', 'upcoming events month format' ), $end_timestamp );
       
   390 
       
   391 						if ( $start_month === $end_month ) {
       
   392 							$formatted_date = sprintf(
       
   393 								/* translators: Date string for upcoming events. 1: Month, 2: Starting day, 3: Ending day, 4: Year. */
       
   394 								__( '%1$s %2$d–%3$d, %4$d' ),
       
   395 								$start_month,
       
   396 								/* translators: Upcoming events day format. See https://www.php.net/date */
       
   397 								date_i18n( _x( 'j', 'upcoming events day format' ), $timestamp ),
       
   398 								date_i18n( _x( 'j', 'upcoming events day format' ), $end_timestamp ),
       
   399 								/* translators: Upcoming events year format. See https://www.php.net/date */
       
   400 								date_i18n( _x( 'Y', 'upcoming events year format' ), $timestamp )
       
   401 							);
       
   402 						} else {
       
   403 							$formatted_date = sprintf(
       
   404 								/* translators: Date string for upcoming events. 1: Starting month, 2: Starting day, 3: Ending month, 4: Ending day, 5: Year. */
       
   405 								__( '%1$s %2$d – %3$s %4$d, %5$d' ),
       
   406 								$start_month,
       
   407 								date_i18n( _x( 'j', 'upcoming events day format' ), $timestamp ),
       
   408 								$end_month,
       
   409 								date_i18n( _x( 'j', 'upcoming events day format' ), $end_timestamp ),
       
   410 								date_i18n( _x( 'Y', 'upcoming events year format' ), $timestamp )
       
   411 							);
       
   412 						}
       
   413 
       
   414 						$formatted_date = wp_maybe_decline_date( $formatted_date, 'F j, Y' );
       
   415 					}
       
   416 				}
       
   417 
       
   418 				$response_body['events'][ $key ]['formatted_date'] = $formatted_date;
       
   419 				$response_body['events'][ $key ]['formatted_time'] = $formatted_time;
   381 			}
   420 			}
   382 		}
   421 		}
   383 
   422 
   384 		return $response_body;
   423 		return $response_body;
   385 	}
   424 	}
   395 	 * higher position, so that it doesn't get trimmed off.
   434 	 * higher position, so that it doesn't get trimmed off.
   396 	 *
   435 	 *
   397 	 * @since 4.8.0
   436 	 * @since 4.8.0
   398 	 * @since 4.9.7 Stick a WordCamp to the final list.
   437 	 * @since 4.9.7 Stick a WordCamp to the final list.
   399 	 *
   438 	 *
   400 	 * @param  array $response_body The response body which contains the events.
   439 	 * @param array $response_body The response body which contains the events.
   401 	 * @return array The response body with events trimmed.
   440 	 * @return array The response body with events trimmed.
   402 	 */
   441 	 */
   403 	protected function trim_events( $response_body ) {
   442 	protected function trim_events( $response_body ) {
   404 		if ( isset( $response_body['events'] ) ) {
   443 		if ( isset( $response_body['events'] ) ) {
   405 			$wordcamps         = array();
   444 			$wordcamps = array();
   406 			$current_timestamp = current_time( 'timestamp' );
   445 			$today     = current_time( 'Y-m-d' );
   407 
   446 
   408 			foreach ( $response_body['events'] as $key => $event ) {
   447 			foreach ( $response_body['events'] as $key => $event ) {
   409 				/*
   448 				/*
   410 				 * Skip WordCamps, because they might be multi-day events.
   449 				 * Skip WordCamps, because they might be multi-day events.
   411 				 * Save a copy so they can be pinned later.
   450 				 * Save a copy so they can be pinned later.
   413 				if ( 'wordcamp' === $event['type'] ) {
   452 				if ( 'wordcamp' === $event['type'] ) {
   414 					$wordcamps[] = $event;
   453 					$wordcamps[] = $event;
   415 					continue;
   454 					continue;
   416 				}
   455 				}
   417 
   456 
   418 				$event_timestamp = strtotime( $event['date'] );
   457 				// We don't get accurate time with timezone from API, so we only take the date part (Y-m-d).
   419 
   458 				$event_date = substr( $event['date'], 0, 10 );
   420 				if ( $current_timestamp > $event_timestamp && ( $current_timestamp - $event_timestamp ) > DAY_IN_SECONDS ) {
   459 
       
   460 				if ( $today > $event_date ) {
   421 					unset( $response_body['events'][ $key ] );
   461 					unset( $response_body['events'][ $key ] );
   422 				}
   462 				}
   423 			}
   463 			}
   424 
   464 
   425 			$response_body['events'] = array_slice( $response_body['events'], 0, 3 );
   465 			$response_body['events'] = array_slice( $response_body['events'], 0, 3 );
   426 			$trimmed_event_types     = wp_list_pluck( $response_body['events'], 'type' );
   466 			$trimmed_event_types     = wp_list_pluck( $response_body['events'], 'type' );
   427 
   467 
   428 			// Make sure the soonest upcoming WordCamp is pinned in the list.
   468 			// Make sure the soonest upcoming WordCamp is pinned in the list.
   429 			if ( ! in_array( 'wordcamp', $trimmed_event_types ) && $wordcamps ) {
   469 			if ( ! in_array( 'wordcamp', $trimmed_event_types, true ) && $wordcamps ) {
   430 				array_pop( $response_body['events'] );
   470 				array_pop( $response_body['events'] );
   431 				array_push( $response_body['events'], $wordcamps[0] );
   471 				array_push( $response_body['events'], $wordcamps[0] );
   432 			}
   472 			}
   433 		}
   473 		}
   434 
   474