AIL' . PHP_EOL; $message .= 'WP_Error: ' . $response->get_error_message() . PHP_EOL; } elseif ( 200 !== wp_remote_retrieve_response_code( $response ) ) { $message .= 'FAIL' . PHP_EOL; } elseif ( isset( $formatted_response['error_description'] ) ) { $message .= 'FAIL' . PHP_EOL; $message .= 'Bad Request' === $formatted_response['error_description'] ? esc_html__( 'Bad request. Please check the code.', 'rank-math' ) : $formatted_response['error_description']; } else { $message .= 'PASS' . PHP_EOL; } $message .= 'REQUEST: ' . $http_verb . ' > ' . $url . PHP_EOL; $message .= 'REQUEST_PARAMETERS: ' . wp_json_encode( $params ) . PHP_EOL; $message .= 'REQUEST_API_ARGUMENTS: ' . wp_json_encode( $args ) . PHP_EOL; $message .= 'RESPONSE_CODE: ' . wp_remote_retrieve_response_code( $response ) . PHP_EOL; $message .= 'RESPONSE_CODE_MESSAGE: ' . wp_remote_retrieve_body( $response ) . PHP_EOL; $message .= 'RESPONSE_FORMATTED: ' . wp_json_encode( $formatted_response ) . PHP_EOL; $message .= 'ORIGINAL_RESPONSE: ' . wp_json_encode( $response ) . PHP_EOL; $message .= '================================' . PHP_EOL; $message .= $wp_filesystem->get_contents( $file ); $wp_filesystem->put_contents( $file, $message ); } /** * Decode the response and format any error messages for debugging * * @param array|WP_Error $response The response from the curl request. * * @return array|false The JSON decoded into an array */ private function format_response( $response ) { $this->last_response = $response; if ( is_wp_error( $response ) ) { return false; } if ( ! empty( $response['body'] ) ) { return json_decode( $response['body'], true ); } return false; } /** * Check if the response was successful or a failure. If it failed, store the error. * * @param object $response The response from the curl request. * @param array|false $formatted_response The response body payload from the curl request. */ private function determine_success( $response, $formatted_response ) { if ( is_wp_error( $response ) ) { $this->last_error = 'WP_Error: ' . $response->get_error_message(); return; } $this->last_code = wp_remote_retrieve_response_code( $response ); if ( in_array( $this->last_code, [ 200, 204 ], true ) ) { $this->is_success = true; return; } if ( isset( $formatted_response['error_description'] ) ) { $this->last_error = 'Bad Request' === $formatted_response['error_description'] ? esc_html__( 'Bad request. Please check the code.', 'rank-math' ) : $formatted_response['error_description']; return; } $message = esc_html__( 'Unknown error, call get_response() to find out what happened.', 'rank-math' ); $body = wp_remote_retrieve_body( $response ); if ( ! empty( $body ) ) { $body = json_decode( $body, true ); if ( ! empty( $body['error'] ) && ! empty( $body['error']['message'] ) ) { $message = $body['error']['message']; } elseif ( ! empty( $body['errors'] ) && is_array( $body['errors'] ) && ! empty( $body['errors'][0]['message'] ) ) { $message = $body['errors'][0]['message']; } } $this->last_error = $message; } /** * Reset request. */ private function reset() { $this->last_code = 0; $this->last_error = ''; $this->is_success = false; $this->last_response = [ 'body' => null, 'headers' => null, ]; } /** * Refresh access token when user login. */ public function refresh_token() { // Bail if the user is not authenticated at all yet. if ( ! Authentication::is_authorized() || ! Authentication::is_token_expired() ) { return true; } $response = $this->get_refresh_token(); if ( ! $response ) { return false; } if ( false === $response['success'] ) { return false; } $tokens = Authentication::tokens(); // Save new token. $this->token = $response['access_token']; $tokens['expire'] = $response['expire']; $tokens['access_token'] = $response['access_token']; Authentication::tokens( $tokens ); return true; } /** * Get the new refresh token. * * @return mixed */ protected function get_refresh_token() { $tokens = Authentication::tokens(); if ( empty( $tokens['refresh_token'] ) ) { return false; } $response = wp_remote_get( add_query_arg( [ 'code' => $tokens['refresh_token'], 'format' => 'json', ], Authentication::get_auth_app_url() . '/refresh.php' ) ); if ( 200 !== wp_remote_retrieve_response_code( $response ) ) { return false; } $response = json_decode( wp_remote_retrieve_body( $response ), true ); if ( empty( $response ) ) { return false; } return $response; } /** * Revoke an OAuth2 token. * * @return boolean Whether the token was revoked successfully. */ public function revoke_token() { Authentication::tokens( false ); delete_option( 'rank_math_google_analytic_profile' ); delete_option( 'rank_math_google_analytic_options' ); delete_option( 'rankmath_google_api_failed_attempts_data' ); delete_option( 'rankmath_google_api_reconnect' ); return $this->is_success(); } /** * Log every failed API call. * And kill all next scheduled event if failed count is more then three. * * @param array $response Response from api. * @param string $action Action performing. * @param string $start_date Start date fetching for (or page URI for inspections). * @param array $args Array of arguments. */ public function log_failed_request( $response, $action, $start_date, $args ) { if ( $this->is_success() ) { return; } $option_key = 'rankmath_google_api_failed_attempts_data'; $reconnect_google_option_key = 'rankmath_google_api_reconnect'; if ( empty( $response['error'] ) || ! is_array( $response['error'] ) ) { delete_option( $option_key ); delete_option( $reconnect_google_option_key ); return; } // Limit maximum 10 failed attempt data to log. $failed_attempts = get_option( $option_key, [] ); $failed_attempts = ( ! empty( $failed_attempts ) && is_array( $failed_attempts ) ) ? array_slice( $failed_attempts, -9, 9 ) : []; $failed_attempts[] = [ 'action' => $action, 'args' => $args, 'error' => $response['error'], ]; update_option( $option_key, $failed_attempts, false ); // Number of allowed attempt. if ( 3 < count( $failed_attempts ) ) { update_option( $reconnect_google_option_key, 'search_analytics_query' ); return; } Schedule::single_action( time() + 60, "rank_math/analytics/get_{$action}_data", [ $start_date ], 'rank-math' ); } }