PluginProbe
Parse.ly / 3.16.2
Parse.ly v3.16.2
3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 3.20.2 3.20.3 All 105 releases
wp-parsely / src / RemoteAPI / class-base-endpoint-remote.php

class-base-endpoint-remote.php in Parse.ly 3.16.2, at src/RemoteAPI/class-base-endpoint-remote.php

151 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Remote API: Base class for remote API endpoints
4 *
5 * @package Parsely
6 * @since 3.2.0
7 */
8
9 declare(strict_types=1);
10
11 namespace Parsely\RemoteAPI;
12
13 use Parsely\Endpoints\Base_Endpoint;
14 use Parsely\Parsely;
15 use UnexpectedValueException;
16 use WP_Error;
17
18 use function Parsely\Utils\convert_to_associative_array;
19
20 /**
21 * Base class for remote API endpoints.
22 *
23 * Child classes must add protected ENDPOINT, API_BASE_URL and QUERY_FILTER
24 * constants.
25 *
26 * @since 3.2.0 Introduced as Remote_API_Base.
27 * @since 3.11.0 Renamed to Base_Endpoint_Remote and moved some members into Base_Endpoint.
28 *
29 * @phpstan-type Remote_API_Error array{
30 * code: int,
31 * message: string,
32 * htmlMessage: string,
33 * }
34 *
35 * @phpstan-import-type WP_HTTP_Request_Args from Parsely
36 */
37 abstract class Base_Endpoint_Remote extends Base_Endpoint implements Remote_API_Interface {
38 protected const API_BASE_URL = '';
39 protected const QUERY_FILTER = '';
40
41 /**
42 * Gets Parse.ly API endpoint.
43 *
44 * @since 3.6.2
45 *
46 * @return string
47 */
48 public function get_endpoint(): string {
49 return static::ENDPOINT;
50 }
51
52 /**
53 * Gets the URL for a particular Parse.ly API endpoint.
54 *
55 * @since 3.2.0
56 *
57 * @param array<string, mixed> $query The query arguments to send to the remote API.
58 * @throws UnexpectedValueException If the endpoint constant is not defined.
59 * @throws UnexpectedValueException If the query filter constant is not defined.
60 * @return string
61 */
62 public function get_api_url( array $query ): string {
63 $this->validate_required_constraints();
64
65 $query['apikey'] = $this->parsely->get_site_id();
66 if ( $this->parsely->api_secret_is_set() ) {
67 $query['secret'] = $this->parsely->get_api_secret();
68 }
69 $query = array_filter( $query );
70
71 // Sort by key so the query args are in alphabetical order.
72 ksort( $query );
73
74 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- Hook names are defined in child classes.
75 $query = apply_filters( static::QUERY_FILTER, $query );
76 return add_query_arg( $query, static::API_BASE_URL . static::ENDPOINT );
77 }
78
79 /**
80 * Gets items from the specified endpoint.
81 *
82 * @since 3.2.0
83 * @since 3.7.0 Added $associative param.
84 *
85 * @param array<string, mixed> $query The query arguments to send to the remote API.
86 * @param bool $associative When TRUE, returned objects will be converted into associative arrays.
87 * @return array<string, mixed>|object|WP_Error
88 */
89 public function get_items( array $query, bool $associative = false ) {
90 $full_api_url = $this->get_api_url( $query );
91
92 /**
93 * GET request options.
94 *
95 * @var WP_HTTP_Request_Args $options
96 */
97 $options = $this->get_request_options();
98 $response = wp_safe_remote_get( $full_api_url, $options );
99
100 if ( is_wp_error( $response ) ) {
101 return $response;
102 }
103
104 $body = wp_remote_retrieve_body( $response );
105 $decoded = json_decode( $body );
106
107 if ( ! is_object( $decoded ) ) {
108 return new WP_Error( 400, __( 'Unable to decode upstream API response', 'wp-parsely' ) );
109 }
110
111 if ( ! property_exists( $decoded, 'data' ) ) {
112 return new WP_Error( $decoded->code ?? 400, $decoded->message ?? __( 'Unable to read data from upstream API', 'wp-parsely' ) );
113 }
114
115 if ( ! is_array( $decoded->data ) ) {
116 return new WP_Error( 400, __( 'Unable to parse data from upstream API', 'wp-parsely' ) );
117 }
118
119 $data = $decoded->data;
120
121 return $associative ? convert_to_associative_array( $data ) : $data;
122 }
123
124 /**
125 * Returns the request's options for the remote API call.
126 *
127 * @since 3.9.0
128 *
129 * @return array<string, mixed> The array of options.
130 */
131 public function get_request_options(): array {
132 return array();
133 }
134
135 /**
136 * Validates that required constants are defined.
137 *
138 * @since 3.14.0
139 *
140 * @throws UnexpectedValueException If any required constant is not defined.
141 */
142 protected function validate_required_constraints(): void {
143 if ( static::ENDPOINT === '' ) {
144 throw new UnexpectedValueException( 'ENDPOINT constant must be defined in child class.' );
145 }
146 if ( static::QUERY_FILTER === '' ) {
147 throw new UnexpectedValueException( 'QUERY_FILTER constant must be defined in child class.' );
148 }
149 }
150 }
151