Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 50 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
| HostingUapiClient | |
0.00% |
0 / 50 |
|
0.00% |
0 / 3 |
380 | |
0.00% |
0 / 1 |
| put_site_performance_redis | |
0.00% |
0 / 37 |
|
0.00% |
0 / 1 |
72 | |||
| extract_customer_error | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
72 | |||
| snippet | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace NewfoldLabs\WP\Module\Performance\Helpers; |
| 4 | |
| 5 | /** |
| 6 | * Minimal Hosting UAPI client for site-scoped endpoints. |
| 7 | */ |
| 8 | final class HostingUapiClient { |
| 9 | |
| 10 | /** |
| 11 | * PUT /v1/sites/{site_id}/performance/redis |
| 12 | * |
| 13 | * @param string $huapi_jwt HUAPI JWT (from Hiive customer payload). |
| 14 | * @param string $site_id HAL site id (digits). |
| 15 | * @param bool $enabled Desired redis enablement. |
| 16 | * @return true|\WP_Error |
| 17 | */ |
| 18 | public static function put_site_performance_redis( $huapi_jwt, $site_id, $enabled ) { |
| 19 | $huapi_jwt = (string) $huapi_jwt; |
| 20 | $site_id = (string) $site_id; |
| 21 | |
| 22 | if ( '' === $huapi_jwt || '' === $site_id ) { |
| 23 | return new \WP_Error( 'nfd_hosting_uapi_error', __( 'Could not enable object cache right now. Please try again later.', 'wp-module-performance' ) ); |
| 24 | } |
| 25 | |
| 26 | $base = SiteApisConfig::hosting_uapi_base_url(); |
| 27 | $url = $base . 'v1/sites/' . rawurlencode( $site_id ) . '/performance/redis'; |
| 28 | |
| 29 | $body = array( 'state' => (bool) $enabled ); |
| 30 | |
| 31 | /** |
| 32 | * Allow adjusting request body for environments that require 0/1 instead of JSON booleans. |
| 33 | * |
| 34 | * @param array $body |
| 35 | * @param string $site_id |
| 36 | */ |
| 37 | $body = apply_filters( 'newfold_performance_hosting_uapi_redis_toggle_body', $body, $site_id ); |
| 38 | |
| 39 | $args = array( |
| 40 | 'method' => 'PUT', |
| 41 | 'timeout' => SiteApisConfig::hosting_uapi_request_timeout_seconds(), |
| 42 | 'headers' => array( |
| 43 | 'Content-Type' => 'application/json', |
| 44 | 'Authorization' => 'Bearer ' . $huapi_jwt, |
| 45 | ), |
| 46 | 'body' => wp_json_encode( $body ), |
| 47 | ); |
| 48 | |
| 49 | $response = wp_remote_request( $url, $args ); |
| 50 | |
| 51 | if ( is_wp_error( $response ) ) { |
| 52 | return $response; |
| 53 | } |
| 54 | |
| 55 | $code = (int) wp_remote_retrieve_response_code( $response ); |
| 56 | $raw = (string) wp_remote_retrieve_body( $response ); |
| 57 | |
| 58 | if ( $code < 200 || $code >= 300 ) { |
| 59 | $data = json_decode( $raw, true ); |
| 60 | $customer_error = is_array( $data ) ? self::extract_customer_error( $data ) : null; |
| 61 | |
| 62 | $err = new \WP_Error( |
| 63 | 'nfd_hosting_uapi_error', |
| 64 | __( 'Could not enable object cache right now. Please try again later.', 'wp-module-performance' ), |
| 65 | array( |
| 66 | 'status' => $code, |
| 67 | 'body' => $raw, |
| 68 | 'customer_error' => $customer_error, |
| 69 | 'decoded' => is_array( $data ) ? $data : null, |
| 70 | ) |
| 71 | ); |
| 72 | |
| 73 | /** |
| 74 | * Filter WP_Error for Hosting UAPI failures (map/customize). |
| 75 | * |
| 76 | * @param \WP_Error $err |
| 77 | * @param int $code |
| 78 | * @param string $raw |
| 79 | */ |
| 80 | return apply_filters( 'newfold_performance_hosting_uapi_redis_toggle_error', $err, $code, $raw ); |
| 81 | } |
| 82 | |
| 83 | return true; |
| 84 | } |
| 85 | |
| 86 | /** |
| 87 | * Extract a stable customer-facing error string from a decoded JSON body when present. |
| 88 | * |
| 89 | * @param array $data Decoded JSON. |
| 90 | */ |
| 91 | private static function extract_customer_error( array $data ): ?string { |
| 92 | // Common shapes: { "customer_error": "..." } or nested under error/details. |
| 93 | if ( isset( $data['customer_error'] ) && is_string( $data['customer_error'] ) && '' !== $data['customer_error'] ) { |
| 94 | return $data['customer_error']; |
| 95 | } |
| 96 | |
| 97 | if ( isset( $data['error'] ) && is_array( $data['error'] ) ) { |
| 98 | $err = $data['error']; |
| 99 | if ( isset( $err['customer_error'] ) && is_string( $err['customer_error'] ) ) { |
| 100 | return $err['customer_error']; |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | return null; |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Truncate raw response text for error messages. |
| 109 | * |
| 110 | * @param string $raw Response body. |
| 111 | * @return string Trimmed substring, max 240 characters. |
| 112 | */ |
| 113 | private static function snippet( string $raw ): string { |
| 114 | $raw = trim( $raw ); |
| 115 | if ( '' === $raw ) { |
| 116 | return ''; |
| 117 | } |
| 118 | |
| 119 | return function_exists( 'mb_substr' ) |
| 120 | ? (string) mb_substr( $raw, 0, 240 ) |
| 121 | : (string) substr( $raw, 0, 240 ); |
| 122 | } |
| 123 | } |