HEX
Server: Apache/2.4.65 (Debian)
System: Linux 88f31f35b0b8 6.1.0-38-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.147-1 (2025-08-02) x86_64
User: www-data (33)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/html/wp-content/plugins/uptime-monitor-plus/includes/class-api-client.php
<?php
defined('ABSPATH') || exit;

/**
 * API Client for UptimeMonitor+ backend communication.
 */
class UptimeMonitorPlus_API_Client {

    /** @var string */
    private $base_url;

    /**
     * @param string|null $base_url Optional base URL override.
     */
    public function __construct( $base_url = null ) {
        $this->base_url = rtrim( $base_url ?? get_option( 'uptimemonitorplus_api_base_url', 'https://uptimemonitorplus.oimmei.com' ), '/' );
    }

    // ── JWT-authenticated methods ──

    /**
     * Login with email and password.
     *
     * @param string $email
     * @param string $password
     * @return array|WP_Error
     */
    public function login( $email, $password ) {
        return $this->post( '/api/auth/login', array(
            'email'    => $email,
            'password' => $password,
        ) );
    }

    /**
     * Get user's domains.
     *
     * @param string $token JWT token.
     * @return array|WP_Error
     */
    public function get_domains( $token ) {
        return $this->get( '/api/domains', array(), array(
            'Authorization' => 'Bearer ' . $token,
        ) );
    }

    /**
     * Create a new domain.
     *
     * @param string $token JWT token.
     * @param string $url   Domain URL.
     * @return array|WP_Error
     */
    public function create_domain( $token, $url ) {
        return $this->post( '/api/domains', array( 'url' => $url ), array(
            'Authorization' => 'Bearer ' . $token,
        ) );
    }

    /**
     * Generate or retrieve API token for a domain.
     *
     * @param string $token     JWT token.
     * @param string $domain_id Domain UUID.
     * @return array|WP_Error
     */
    public function generate_api_token( $token, $domain_id ) {
        return $this->post( '/api/domains/' . $domain_id . '/api-token', array(), array(
            'Authorization' => 'Bearer ' . $token,
        ) );
    }

    /**
     * Revoke API token for a domain.
     *
     * @param string $token     JWT token.
     * @param string $domain_id Domain UUID.
     * @return array|WP_Error
     */
    public function revoke_api_token( $token, $domain_id ) {
        return $this->delete( '/api/domains/' . $domain_id . '/api-token', array(
            'Authorization' => 'Bearer ' . $token,
        ) );
    }

    // ── Domain-token-authenticated methods ──

    /**
     * Get domain info.
     *
     * @return array|WP_Error
     */
    public function get_domain() {
        return $this->get( '/api/plugin/domain', array(), $this->domain_token_headers() );
    }

    /**
     * Get SSL certificate data.
     *
     * @return array|WP_Error
     */
    public function get_ssl() {
        return $this->get( '/api/plugin/domain/ssl', array(), $this->domain_token_headers() );
    }

    /**
     * Get 24h sparkline data.
     *
     * @return array|WP_Error
     */
    public function get_sparklines() {
        return $this->get( '/api/plugin/domain/sparklines', array(), $this->domain_token_headers() );
    }

    /**
     * Get check results with pagination.
     *
     * @param array $params Query params (cursor, limit, date, tz).
     * @return array|WP_Error
     */
    public function get_checks( $params = array() ) {
        return $this->get( '/api/plugin/domain/checks', $params, $this->domain_token_headers() );
    }

    /**
     * Get analytics data.
     *
     * @param string $range Time range (1h/24h/7d/30d).
     * @return array|WP_Error
     */
    public function get_analytics( $range = '24h' ) {
        return $this->get( '/api/plugin/domain/analytics', array( 'range' => $range ), $this->domain_token_headers() );
    }

    /**
     * Get error log.
     *
     * @param string $range Time range (1h/24h/7d/30d).
     * @return array|WP_Error
     */
    public function get_errors( $range = '24h' ) {
        return $this->get( '/api/plugin/domain/errors', array( 'range' => $range ), $this->domain_token_headers() );
    }

    /**
     * Get incidents.
     *
     * @param int $page     Page number.
     * @param int $pageSize Items per page.
     * @return array|WP_Error
     */
    public function get_incidents( $page = 1, $pageSize = 10 ) {
        return $this->get( '/api/plugin/domain/incidents', array(
            'page'     => $page,
            'pageSize' => $pageSize,
        ), $this->domain_token_headers() );
    }

    /**
     * Get calendar data.
     *
     * @param int    $months Number of months.
     * @param int    $offset Month offset.
     * @param string $tz     Timezone.
     * @return array|WP_Error
     */
    public function get_calendar( $months = 3, $offset = 0, $tz = 'UTC' ) {
        return $this->get( '/api/plugin/domain/calendar', array(
            'months' => $months,
            'offset' => $offset,
            'tz'     => $tz,
        ), $this->domain_token_headers() );
    }

    /**
     * Update notification preferences.
     *
     * @param array $data Notification data.
     * @return array|WP_Error
     */
    public function update_notifications( $data ) {
        return $this->patch( '/api/plugin/domain/notifications', $data, $this->domain_token_headers() );
    }

    // ── HTTP helpers ──

    /**
     * Get domain token headers.
     *
     * @return array
     */
    private function domain_token_headers() {
        return array(
            'X-Domain-Token' => get_option( 'uptimemonitorplus_api_token', '' ),
        );
    }

    /**
     * Perform a GET request.
     *
     * @param string $path    API path.
     * @param array  $params  Query parameters.
     * @param array  $headers HTTP headers.
     * @return array|WP_Error
     */
    private function get( $path, $params = array(), $headers = array() ) {
        $url = $this->base_url . $path;
        if ( ! empty( $params ) ) {
            $url .= '?' . http_build_query( $params );
        }

        $response = wp_remote_get( $url, array(
            'timeout' => 15,
            'headers' => array_merge( array(
                'Content-Type' => 'application/json',
                'Accept'       => 'application/json',
            ), $headers ),
        ) );

        return $this->handle_response( $response );
    }

    /**
     * Perform a POST request.
     *
     * @param string $path    API path.
     * @param array  $data    Request body data.
     * @param array  $headers HTTP headers.
     * @return array|WP_Error
     */
    private function post( $path, $data = array(), $headers = array() ) {
        $response = wp_remote_post( $this->base_url . $path, array(
            'timeout' => 15,
            'headers' => array_merge( array(
                'Content-Type' => 'application/json',
                'Accept'       => 'application/json',
            ), $headers ),
            'body'    => wp_json_encode( $data ),
        ) );

        return $this->handle_response( $response );
    }

    /**
     * Perform a PATCH request.
     *
     * @param string $path    API path.
     * @param array  $data    Request body data.
     * @param array  $headers HTTP headers.
     * @return array|WP_Error
     */
    private function patch( $path, $data = array(), $headers = array() ) {
        $response = wp_remote_request( $this->base_url . $path, array(
            'method'  => 'PATCH',
            'timeout' => 15,
            'headers' => array_merge( array(
                'Content-Type' => 'application/json',
                'Accept'       => 'application/json',
            ), $headers ),
            'body'    => wp_json_encode( $data ),
        ) );

        return $this->handle_response( $response );
    }

    /**
     * Perform a DELETE request.
     *
     * @param string $path    API path.
     * @param array  $headers HTTP headers.
     * @return array|WP_Error
     */
    private function delete( $path, $headers = array() ) {
        $response = wp_remote_request( $this->base_url . $path, array(
            'method'  => 'DELETE',
            'timeout' => 15,
            'headers' => array_merge( array(
                'Content-Type' => 'application/json',
                'Accept'       => 'application/json',
            ), $headers ),
        ) );

        return $this->handle_response( $response );
    }

    /**
     * Handle HTTP response.
     *
     * @param array|WP_Error $response HTTP response.
     * @return array|WP_Error Decoded body or WP_Error.
     */
    private function handle_response( $response ) {
        if ( is_wp_error( $response ) ) {
            return $response;
        }

        $code = wp_remote_retrieve_response_code( $response );
        $body = wp_remote_retrieve_body( $response );
        $data = json_decode( $body, true );

        if ( $code >= 400 ) {
            $error_message = isset( $data['error'] ) ? $data['error'] : 'API request failed';
            $error_code    = isset( $data['code'] ) ? $data['code'] : 'API_ERROR';
            return new WP_Error( $error_code, $error_message, array(
                'status'   => $code,
                'response' => $data,
            ) );
        }

        return $data;
    }
}