PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.13.1
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.13.1
3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 2.8.17 2.8.18 All 259 releases
wpfunnels / includes / core / gateways / API / class-wpfnl-api-base.php

class-wpfnl-api-base.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.13.1, at includes/core/gateways/API/class-wpfnl-api-base.php

623 lines 17.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WooCommerce Plugin Framework
4 *
5 * This source file is subject to the GNU General Public License v3.0
6 * that is bundled with this package in the file license.txt.
7 * It is also available through the world-wide-web at this URL:
8 * http://www.gnu.org/licenses/gpl-3.0.html
9 * If you did not receive a copy of the license and are unable to
10 * obtain it through the world-wide-web, please send an email
11 * to license@skyverge.com so we can send you a copy immediately.
12 *
13 * DISCLAIMER
14 *
15 * Do not edit or add to this file if you wish to upgrade the plugin to newer
16 * versions in the future. If you wish to customize the plugin for your
17 * needs please refer to http://www.skyverge.com
18 *
19 * @package SkyVerge/WooCommerce/API
20 * @author SkyVerge
21 * @copyright Copyright (c) 2013-2020, SkyVerge, Inc.
22 * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0
23 */
24
25 namespace WPFunnels\Gateway\API;
26
27 defined( 'ABSPATH' ) or exit;
28
29 class Wpfnl_API_Base {
30
31
32 public $parameters;
33 /** @var string request method, defaults to POST */
34 protected $request_method = 'POST';
35 /** @var string URI used for the request */
36 protected $request_uri;
37 /** @var array request headers */
38 protected $request_headers = array();
39 /** @var string request user-agent */
40 protected $request_user_agent;
41 /** @var string request HTTP version, defaults to 1.0 */
42 protected $request_http_version = '1.0';
43 /** @var string request duration */
44 protected $request_duration;
45 /** @var object request */
46 protected $request;
47 /** @var string response code */
48 protected $response_code;
49 /** @var string response message */
50 protected $response_message;
51 /** @var array response headers */
52 protected $response_headers;
53 /** @var string raw response body */
54 protected $raw_response_body;
55 /** @var string response handler class name */
56 protected $response_handler;
57 /** @var object response */
58 protected $response;
59
60 /**
61 * Add multiple parameters
62 *
63 * @param array $params
64 *
65 * @since 2.0
66 */
67 public function add_parameters( array $params ) {
68 foreach ( $params as $key => $value ) {
69 $this->add_parameter( $key, $value );
70 }
71 }
72
73 /**
74 * Add a parameter
75 *
76 * @param string $key
77 * @param string|int $value
78 *
79 * @since 2.0
80 */
81 public function add_parameter( $key, $value ) {
82 $this->parameters[ $key ] = $value;
83 }
84
85 public function clean_params() {
86 $this->parameters = array();
87 }
88
89 public function get_parameters() {
90
91 $this->parameters = apply_filters( 'wpfnl_api_args', $this->parameters, $this );
92
93 // validate parameters
94 foreach ( $this->parameters as $key => $value ) {
95
96 // remove unused params
97 if ( '' === $value || is_null( $value ) ) {
98 unset( $this->parameters[ $key ] );
99 }
100 }
101
102 return $this->parameters;
103 }
104
105 /**
106 * Perform the request and return the parsed response
107 *
108 * @param object $request class instance which implements \SV_WC_API_Request
109 *
110 * @return object class instance which implements \SV_WC_API_Response
111 * @throws Exception
112 * @since 2.2.0
113 *
114 */
115 protected function perform_request( $request ) {
116
117 // ensure API is in its default state
118 $this->reset_response();
119
120 // save the request object
121 $this->request = $request;
122
123 $start_time = microtime( true );
124 // perform the request
125 $response = $this->do_remote_request( $this->get_request_uri(), $this->get_request_args() );
126 // calculate request duration
127 $this->request_duration = round( microtime( true ) - $start_time, 5 );
128
129 try {
130
131 // parse & validate response
132 $response = $this->handle_response( $response );
133
134
135 } catch ( \Exception $e ) {
136
137 // alert other actors that a request has been made
138 $this->broadcast_request();
139 throw $e;
140 }
141
142 return $response;
143 }
144
145 /**
146 * Reset the API response members to their
147 *
148 * @since 1.0.0
149 */
150 protected function reset_response() {
151
152 $this->response_code = null;
153 $this->response_message = null;
154 $this->response_headers = null;
155 $this->raw_response_body = null;
156 $this->response = null;
157 $this->request_duration = null;
158 }
159
160 /**
161 * Simple wrapper for wp_remote_request() so child classes can override this
162 * and provide their own transport mechanism if needed, e.g. a custom
163 * cURL implementation
164 *
165 * @param string $request_uri
166 * @param string $request_args
167 *
168 * @return array|WP_Error
169 * @since 2.2.0
170 *
171 */
172 protected function do_remote_request( $request_uri, $request_args ) {
173 return wp_safe_remote_request( $request_uri, $request_args );
174 }
175
176 /**
177 * Get the request URI
178 *
179 * @return string
180 * @since 2.2.0
181 */
182 protected function get_request_uri() {
183
184 // API base request URI + any request-specific path
185 $uri = $this->request_uri . ( $this->get_request() ? $this->get_request()->path : '' );
186
187 /**
188 * Request URI Filter.
189 *
190 * Allow actors to filter the request URI. Note that child classes can override
191 * this method, which means this filter may be invoked prior to the overridden
192 * method.
193 *
194 * @param string $uri current request URI
195 * @param \Wpfnl_API_Base class instance
196 *
197 * @since 4.1.0
198 *
199 */
200 return apply_filters( 'wc_' . $this->get_api_id() . '_api_request_uri', $uri, $this );
201 }
202
203 /**
204 * Returns the most recent request object
205 *
206 * @return object the most recent request object
207 * @see \SV_WC_API_Request
208 * @since 2.2.0
209 */
210 public function get_request() {
211 return $this->request;
212 }
213
214 /**
215 * Get the ID for the API, used primarily to namespace the action name
216 * for broadcasting requests
217 *
218 * @return string
219 * @since 2.2.0
220 */
221 protected function get_api_id() {
222
223 return 'wpfunnels';
224 }
225
226 /**
227 * Get the request arguments in the format required by wp_remote_request()
228 *
229 * @return mixed|void
230 * @since 2.2.0
231 */
232 protected function get_request_args() {
233
234 $args = array(
235 'method' => $this->get_request_method(),
236 'timeout' => MINUTE_IN_SECONDS,
237 'redirection' => 0,
238 'httpversion' => $this->get_request_http_version(),
239 'sslverify' => true,
240 'blocking' => true,
241 'user-agent' => $this->get_request_user_agent(),
242 'headers' => $this->get_request_headers(),
243 'body' => $this->request->body,
244 'cookies' => array(),
245 );
246
247
248
249 /**
250 * Request arguments.
251 *
252 * Allow other actors to filter the request arguments. Note that
253 * child classes can override this method, which means this filter may
254 * not be invoked, or may be invoked prior to the overridden method
255 *
256 * @param array $args request arguments
257 * @param \Wpfnl_API_Base class instance
258 *
259 * @since 2.2.0
260 *
261 */
262 return apply_filters( 'wc_' . $this->get_api_id() . '_http_request_args', $args, $this );
263 }
264
265 /**
266 * Get the request method, POST by default
267 *
268 * @return string
269 * @since 2.2.0
270 */
271 protected function get_request_method() {
272 // if the request object specifies the method to use, use that, otherwise use the API default
273 return $this->get_request() && $this->get_request()->method ? $this->get_request()->method : $this->request_method;
274 }
275
276 /** Request Getters *******************************************************/
277
278 /**
279 * Get the request HTTP version, 1.1 by default
280 *
281 * @return string
282 * @since 2.2.0
283 */
284 protected function get_request_http_version() {
285
286 return $this->request_http_version;
287 }
288
289 /**
290 * Get the request user agent, defaults to:
291 *
292 * Dasherized-Plugin-Name/Plugin-Version (WooCommerce/WC-Version; WordPress/WP-Version)
293 *
294 * @return string
295 * @since 2.2.0
296 */
297 protected function get_request_user_agent() {
298 return '';
299
300 return sprintf( '%s/%s (WooCommerce/%s; WordPress/%s)', str_replace( ' ', '-', $this->get_plugin()->get_plugin_name() ), $this->get_plugin()->get_version(), WC_VERSION, $GLOBALS['wp_version'] );
301 }
302
303 /**
304 * Get the request headers
305 *
306 * @return array
307 * @since 2.2.0
308 */
309 protected function get_request_headers() {
310 return $this->request_headers;
311 }
312
313 /**
314 * Handle and parse the response
315 *
316 * @param array|WP_Error $response response data
317 *
318 * @return object request class instance that implements SV_WC_API_Request
319 * @throws Exception network issues, timeouts, API errors, etc
320 * @since 2.2.0
321 *
322 */
323 protected function handle_response( $response ) {
324
325 // check for WP HTTP API specific errors (network timeout, etc)
326 if ( is_wp_error( $response ) ) {
327 throw new \Exception( $response->get_error_message(), (int) $response->get_error_code() );
328 }
329
330 // set response data
331 $this->response_code = wp_remote_retrieve_response_code( $response );
332 $this->response_message = wp_remote_retrieve_response_message( $response );
333 $this->response_headers = wp_remote_retrieve_headers( $response );
334 $this->raw_response_body = wp_remote_retrieve_body( $response );
335
336
337
338 // allow child classes to validate response prior to parsing -- this is useful
339 // for checking HTTP status codes, etc.
340 $this->do_pre_parse_response_validation();
341
342 // parse the response body and tie it to the request
343 $this->response = $this->get_parsed_response( $this->raw_response_body );
344
345 // allow child classes to validate response after parsing -- this is useful
346 // for checking error codes/messages included in a parsed response
347 $this->do_post_parse_response_validation();
348
349 // fire do_action() so other actors can act on request/response data,
350 // primarily used for logging
351 $this->broadcast_request();
352
353 return $this->response;
354 }
355
356 /**
357 * Allow child classes to validate a response prior to instantiating the
358 * response object. Useful for checking response codes or messages, e.g.
359 * throw an exception if the response code is not 200.
360 *
361 * A child class implementing this method should simply return true if the response
362 * processing should continue, or throw a \SV_WC_API_Exception with a
363 * relevant error message & code to stop processing.
364 *
365 * Note: Child classes *must* sanitize the raw response body before throwing
366 * an exception, as it will be included in the broadcast_request() method
367 * which is typically used to log requests.
368 *
369 * @since 2.2.0
370 */
371 protected function do_pre_parse_response_validation() {
372 // stub method
373 }
374
375 /**
376 * Return the parsed response object for the request
377 *
378 * @param string $raw_response_body
379 *
380 * @return object response class instance which implements SV_WC_API_Request
381 * @since 2.2.0
382 *
383 */
384 protected function get_parsed_response( $raw_response_body ) {
385
386 /**
387 * do parsing if necessary
388 */
389
390 return $raw_response_body;
391 }
392
393 /**
394 * Allow child classes to validate a response after it has been parsed
395 * and instantiated. This is useful for check error codes or messages that
396 * exist in the parsed response.
397 *
398 * A child class implementing this method should simply return true if the response
399 * processing should continue, or throw an Exception with a
400 * relevant error message & code to stop processing.
401 *
402 * Note: Response body sanitization is handled automatically
403 *
404 * @since 2.2.0
405 */
406 protected function do_post_parse_response_validation() {
407 // stub method
408 }
409
410 /**
411 * Alert other actors that a request has been performed. This is primarily used
412 * for request logging.
413 *
414 * @since 2.2.0
415 */
416 protected function broadcast_request() {
417
418 $request_data = array(
419 'method' => $this->get_request_method(),
420 'uri' => $this->get_request_uri(),
421 'user-agent' => $this->get_request_user_agent(),
422 'headers' => $this->get_sanitized_request_headers(),
423 'body' => $this->request->body,
424 'duration' => $this->get_request_duration() . 's', // seconds
425 );
426
427 $response_data = array(
428 'code' => $this->get_response_code(),
429 'message' => $this->get_response_message(),
430 'headers' => $this->get_response_headers(),
431 'body' => $this->get_sanitized_response_body() ? $this->get_sanitized_response_body() : $this->get_raw_response_body(),
432 );
433
434 do_action( 'wc_' . $this->get_api_id() . '_api_request_performed', $request_data, $response_data, $this );
435 }
436
437
438 /** Response Getters ******************************************************/
439
440 /**
441 * Get sanitized request headers suitable for logging, stripped of any
442 * confidential information
443 *
444 * The `Authorization` header is sanitized automatically.
445 *
446 * Child classes that implement any custom authorization headers should
447 * override this method to perform sanitization.
448 *
449 * @return array
450 * @since 2.2.0
451 */
452 protected function get_sanitized_request_headers() {
453
454 $headers = $this->get_request_headers();
455
456 if ( ! empty( $headers['Authorization'] ) ) {
457 $headers['Authorization'] = str_repeat( '*', strlen( $headers['Authorization'] ) );
458 }
459
460 return $headers;
461 }
462
463 /**
464 * Get the request duration in seconds, rounded to the 5th decimal place
465 *
466 * @return string
467 * @since 2.2.0
468 */
469 protected function get_request_duration() {
470 return $this->request_duration;
471 }
472
473 /**
474 * Get the response code
475 *
476 * @return string
477 * @since 2.2.0
478 */
479 protected function get_response_code() {
480 return $this->response_code;
481 }
482
483 /**
484 * Get the response message
485 *
486 * @return string
487 * @since 2.2.0
488 */
489 protected function get_response_message() {
490 return $this->response_message;
491 }
492
493 /**
494 * Get the response headers
495 *
496 * @return array
497 * @since 2.2.0
498 */
499 protected function get_response_headers() {
500 return $this->response_headers;
501 }
502
503 /**
504 * Get the sanitized response body, provided by the response class
505 * to_string_safe() method
506 *
507 * @return string|null
508 * @since 2.2.0
509 */
510 protected function get_sanitized_response_body() {
511 return is_callable( array( $this->get_response(), 'to_string_safe' ) ) ? $this->get_response()->to_string_safe() : null;
512 }
513
514
515 /** Misc Getters ******************************************************/
516
517 /**
518 * Returns the most recent response object
519 *
520 * @return object the most recent response object
521 * @see \SV_WC_API_Response
522 * @since 2.2.0
523 */
524 public function get_response() {
525 return $this->response;
526 }
527
528 /**
529 * Get the raw response body, prior to any parsing or sanitization
530 *
531 * @return string
532 * @since 2.2.0
533 */
534 protected function get_raw_response_body() {
535 return $this->raw_response_body;
536 }
537
538 /**
539 * Get the response handler class name
540 *
541 * @return string
542 * @since 2.2.0
543 */
544 protected function get_response_handler() {
545 return $this->response_handler;
546 }
547
548
549
550
551
552
553 /** Setters ***************************************************************/
554
555 /**
556 * Set the response handler class name. This class will be instantiated
557 * to parse the response for the request.
558 *
559 * Note the class should implement SV_WC_API
560 *
561 * @param string $handler handle class name
562 *
563 * @return array
564 * @since 2.2.0
565 *
566 */
567 protected function set_response_handler( $handler ) {
568 $this->response_handler = $handler;
569 }
570
571 /**
572 * Set a header request
573 *
574 * @param string $name header name
575 * @param string $value header value
576 *
577 * @return string
578 * @since 2.2.0
579 *
580 */
581 protected function set_request_header( $name, $value ) {
582
583 $this->request_headers[ $name ] = $value;
584 }
585
586 /**
587 * Set HTTP basic auth for the request
588 *
589 * Since 2.2.0
590 *
591 * @param string $username
592 * @param string $password
593 */
594 protected function set_http_basic_auth( $username, $password ) {
595
596 $this->request_headers['Authorization'] = sprintf( 'Basic %s', base64_encode( "{$username}:{$password}" ) );
597 }
598
599 /**
600 * Set the Content-Type request header
601 *
602 * @param string $content_type
603 *
604 * @since 2.2.0
605 *
606 */
607 protected function set_request_content_type_header( $content_type ) {
608 $this->request_headers['content-type'] = $content_type;
609 }
610
611 /**
612 * Set the Accept request header
613 *
614 * @param string $type the request accept type
615 *
616 * @since 2.2.0
617 *
618 */
619 protected function set_request_accept_header( $type ) {
620 $this->request_headers['accept'] = $type;
621 }
622 }
623