APIClient.php
7.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
<?php
namespace WP_Rocket\Engine\CriticalPath;
use stdClass;
use WP_Error;
class APIClient {
/**
* Constant url for Critical Path API job.
*/
const API_URL = 'https://cpcss.wp-rocket.me/api/job/';
/**
* Sends a generation request to the Critical Path API.
*
* @since 3.6
*
* @param string $url The URL to send a CPCSS generation request for.
* @param array $params Optional. Parameters needed to be sent in the body. Default: [].
* @param string $item_type Optional. Type for this item if it's custom or specific type. Default: custom.
* @return array
*/
public function send_generation_request( $url, $params = [], $item_type = 'custom' ) {
$params['url'] = $url;
$is_mobile = isset( $params['mobile'] ) && $params['mobile'];
$response = wp_remote_post(
self::API_URL,
[
/**
* Filters the parameters sent to the Critical CSS generator API.
*
* @since 2.11
*
* @param array $params An array of parameters to send to the API.
*/
'body' => apply_filters( 'rocket_cpcss_job_request', $params ),
]
);
return $this->prepare_response( $response, $url, $is_mobile, $item_type );
}
/**
* Prepare the response to be returned.
*
* @since 3.6
*
* @param array|WP_Error $response The response or WP_Error on failure.
* @param string $url Url to be checked.
* @param bool $is_mobile Optional. Flag for if this is cpcss for mobile or not. Default: false.
* @param string $item_type Optional. Type for this item if it's custom or specific type. Default: custom.
*
* @return array|WP_Error
*/
private function prepare_response( $response, $url, $is_mobile = false, $item_type = 'custom' ) {
if ( is_wp_error( $response ) ) {
return new WP_Error(
$this->get_response_code( $response ),
sprintf(
// translators: %1$s = type of content, %2$s = error message.
__( 'Critical CSS for %1$s not generated. Error: %2$s', 'rocket' ),
( 'custom' === $item_type ) ? $url : $item_type,
$response->get_error_message()
),
[
'status' => 400,
]
);
}
$response_data = $this->get_response_data( $response );
$response_status_code = $this->get_response_status( $response, ( isset( $response_data->status ) ) ? $response_data->status : null );
$succeeded = $this->get_response_success( $response_status_code, $response_data );
if ( $succeeded ) {
return $response_data;
}
$response_message = $this->get_response_message( $response_status_code, $response_data, $url, $is_mobile, $item_type );
if ( 200 === $response_status_code ) {
$response_status_code = 400;
}
return new WP_Error(
$this->get_response_code( $response ),
$response_message,
[
'status' => $response_status_code,
]
);
}
/**
* Get the status of response.
*
* @since 3.6
*
* @param int $response_code Response code to check success or failure.
* @param stdClass $response_data Object of data returned from request.
*
* @return bool success or failed.
*/
private function get_response_success( $response_code, $response_data ) {
return (
200 === $response_code
&&
! empty( $response_data )
&&
(
(
isset( $response_data->status )
&&
200 === $response_data->status
)
||
(
isset( $response_data->data )
&&
isset( $response_data->data->id )
)
)
);
}
/**
* Get response status code/number.
*
* @since 3.6
*
* @param array|WP_Error $response The response or WP_Error on failure.
* @param null|int $status Optional. Status code to overwrite the response status. Default: null.
*
* @return int status code|number of response.
*/
private function get_response_status( $response, $status = null ) {
if ( ! is_null( $status ) ) {
return (int) $status;
}
return (int) wp_remote_retrieve_response_code( $response );
}
/**
* Get response message.
*
* @since 3.6
*
* @param int $response_status_code Response status code.
* @param stdClass $response_data Object of data returned from request.
* @param string $url Url for the web page to be checked.
* @param bool $is_mobile Optional. Flag for if this is cpcss for mobile or not. Default: false.
* @param string $item_type Optional. Type for this item if it's custom or specific type. Default: custom.
*
* @return string
*/
private function get_response_message( $response_status_code, $response_data, $url, $is_mobile = false, $item_type = 'custom' ) {
$message = '';
switch ( $response_status_code ) {
case 200:
if ( ! isset( $response_data->data->id ) ) {
$message .= sprintf(
$is_mobile
?
// translators: %s = item URL.
__( 'Critical CSS for %1$s on mobile not generated. Error: The API returned an empty response.', 'rocket' )
:
// translators: %s = item URL.
__( 'Critical CSS for %1$s not generated. Error: The API returned an empty response.', 'rocket' ),
( 'custom' === $item_type ) ? $url : $item_type
);
}
break;
case 400:
case 440:
case 404:
// translators: %s = item URL.
$message .= sprintf(
$is_mobile
// translators: %s = item URL.
? __( 'Critical CSS for %1$s on mobile not generated.', 'rocket' )
// translators: %s = item URL.
: __( 'Critical CSS for %1$s not generated.', 'rocket' ),
( 'custom' === $item_type ) ? $url : $item_type
);
break;
default:
$message .= sprintf(
$is_mobile
// translators: %s = URL.
? __( 'Critical CSS for %1$s on mobile not generated. Error: The API returned an invalid response code.', 'rocket' )
// translators: %s = URL.
: __( 'Critical CSS for %1$s not generated. Error: The API returned an invalid response code.', 'rocket' ),
( 'custom' === $item_type ) ? $url : $item_type
);
break;
}
if ( isset( $response_data->message ) ) {
// translators: %1$s = error message.
$message .= ' ' . sprintf( __( 'Error: %1$s', 'rocket' ), $response_data->message );
}
return $message;
}
/**
* Get response data from the API.
*
* @since 3.6
*
* @param array|WP_Error $response The response or WP_Error on failure.
*
* @return mixed response of API.
*/
private function get_response_data( $response ) {
return json_decode( wp_remote_retrieve_body( $response ) );
}
/**
* Get our internal response code [Not the standard HTTP codes].
*
* @since 3.6
*
* @param array|WP_Error $response The response or WP_Error on failure.
*
* @return string response code.
*/
private function get_response_code( $response ) {
// Todo: we can return code based on the response status number, for example 404 not_found.
return 'cpcss_generation_failed';
}
/**
* Get job details by calling API with job ID.
*
* @since 3.6
*
* @param string $job_id ID for the job to get details.
* @param string $url URL to be used in error messages.
* @param bool $is_mobile Optional. Flag for if this is cpcss for mobile or not. Default: false.
* @param string $item_type Optional. Type for this item if it's custom or specific type. Default: custom.
*
* @return mixed|WP_Error Details for job.
*/
public function get_job_details( $job_id, $url, $is_mobile = false, $item_type = 'custom' ) {
$response = wp_remote_get(
self::API_URL . "{$job_id}/"
);
return $this->prepare_response( $response, $url, $is_mobile, $item_type );
}
}