File "Rest_Api.php"
Full Path: /home/romayxjt/public_html/wp-content/plugins/the-events-calendar/src/Events/Admin/Notice/Rest_Api.php
File size: 6 KB
MIME-type: text/x-php
Charset: utf-8
<?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;
}
}