Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
wp-content
/
plugins
/
the-events-calendar
/
src
/
Events
/
Admin
/
Notice
:
Rest_Api.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /** * Shows an admin notice when our REST API endpoints are not available. * * @since * * @package TEC\Events\Admin\Notice */ namespace TEC\Events\Admin\Notice; use TEC\Events\Traits\Development_Mode; use Tribe\Events\Views\V2\Rest_Endpoint as V2; use Tribe__Events__REST__V1__Main as V1; use WP_Error; /** * Class Rest_Api * * Shows an admin notice when our REST API endpoints are not available. * * @since 6.5.0 */ class Rest_Api { use Development_Mode; /** * Notice Slug on the user options * * @since 6.5.0 * * @var string */ private $slug = 'events-rest-api-notice'; /** * Blocked endpoint. * * @since 6.5.0 * * @var string */ private $blocked_endpoint = ''; /** * Constructor. * * @since 6.5.0 * * @return void */ public function hook(): void { tribe_notice( $this->slug, [ $this, 'notice' ], [ 'type' => 'warning', 'dismiss' => 1, 'wrap' => 'p', 'recurring' => true, 'recurring_interval' => 'P7D', ], [ $this, 'should_display' ] ); add_action( 'tribe_events_views_v2_before_make_view_for_rest', [ $this, 'mark_as_unblocked' ] ); } /** * Checks if we are in a TEC page or in the main Dashboard. * * @since 6.5.0 * * @return bool */ public function should_display(): bool { if ( ! tribe( 'admin.helpers' )->is_screen() ) { return false; } if ( ! current_user_can( 'activate_plugins' ) ) { return false; } return $this->is_rest_api_blocked(); } /** * Marks the REST API as unblocked. * * @since 6.11.1 * * @return void */ public function mark_as_unblocked(): void { tec_timed_option()->set( 'events_is_rest_api_blocked', false, 48 * HOUR_IN_SECONDS ); } /** * Checks if our endpoints are accessible. * * @since 6.5.0 * @sicne 6.5.0.1 Introduce a force param. * * @param bool $force Force the check, skipping timed option cache. * * @return bool */ public function is_rest_api_blocked( bool $force = false ): bool { $cache_key = 'events_is_rest_api_blocked'; $cache_timeout = 48 * HOUR_IN_SECONDS; if ( ! $force && tec_timed_option()->exists( $cache_key, $force ) ) { $this->blocked_endpoint = tec_timed_option()->get( $cache_key, null, $force ); return ! empty( $this->blocked_endpoint ); } // Check multiple endpoints to determine if the REST API is blocked. $endpoints = $this->get_routes_to_check(); foreach ( $endpoints as $endpoint ) { $response = wp_safe_remote_get( $endpoint, [ 'timeout' => 3 ] ); if ( $this->is_response_blocked( $response ) ) { $this->blocked_endpoint = $endpoint; tec_timed_option()->set( $cache_key, $endpoint, $cache_timeout ); return true; } } tec_timed_option()->set( $cache_key, false, $cache_timeout ); return false; } /** * HTML for the notice when we have blocked REST API endpoints. * * @since 6.5.0 * * @return false|string */ public function notice() { $output = sprintf( /* translators: %1$s and %2$s - opening and closing strong tags, respectively. */ __( '%1$sWarning%2$s: The Events Calendar REST API endpoints are not accessible! This may be due to a server configuration or another plugin blocking access to the REST API.', 'the-events-calendar' ), '<strong>', '</strong>' ); $output .= '<br />'; $output .= __( 'Please check with your hosting provider or system administrator to ensure that the below is accessible:', 'the-events-calendar' ); $output .= '<br />'; $output .= '<a href="' . $this->blocked_endpoint . '" target="_blank">' . $this->blocked_endpoint . '</a>'; return $output; } /** * Checks if the response is blocked. * * @since 6.6.3 * * @param array|WP_Error $response The response from the REST API. * * @return bool */ private function is_response_blocked( $response ): bool { // First handle a WP_Error object. if ( is_wp_error( $response ) ) { $blocked = $this->is_wp_error_response_blocking( $response ); } else { $response_code = wp_remote_retrieve_response_code( $response ); $blocked = ( 200 !== $response_code ); } /** * Filters whether the REST API response is considered to be blocked. * * @since 6.6.3 * * @param bool $blocked Whether the REST API response is blocked. * @param array|WP_Error $response The response from the REST API. */ return apply_filters( 'tec_events_rest_api_response_blocked', $blocked, $response ); } /** * Checks if the WP_Error response is blocking. * * @since 6.6.3 * * @param WP_Error $response The response from the REST API. * * @return bool */ private function is_wp_error_response_blocking( WP_Error $response ): bool { switch ( $response->get_error_code() ) { case 'http_request_failed': $message = $response->get_error_message(); // If the site is in development mode, we allow cURL error 60. if ( str_starts_with( $message, 'cURL error 60' ) && $this->is_site_development_mode() ) { $blocked = false; } elseif ( str_starts_with( $message, 'cURL error 28: Operation timed out' ) ) { /** * Filters whether the REST API response is considered to be blocked due to a timeout. * * @since 6.6.3 * * @param bool $blocked Whether the REST API response is blocked. * @param WP_Error $response The response from the REST API. */ $blocked = (bool) apply_filters( 'tec_events_rest_api_response_blocked_due_to_timeout', false, $response ); } else { $blocked = true; } break; default: $blocked = true; break; } return $blocked; } /** * Get the routes to check for possible REST API blocking. * * @since 6.6.3 * * @return array */ private function get_routes_to_check(): array { $routes = []; $v1_main = tribe( 'tec.rest-v1.main' ); // Ensure that what we got from tribe() is the instance we expect. if ( $v1_main instanceof V1 ) { $routes[] = rest_url( $v1_main->get_events_route_namespace() ); } $routes[] = rest_url( V2::ROOT_NAMESPACE ); return $routes; } }