PluginProbe
Stream – Activity Log & Audit Trail / 2.0.5
Stream – Activity Log & Audit Trail v2.0.5
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
stream / classes / class-wp-stream-api.php

class-wp-stream-api.php in Stream – Activity Log & Audit Trail 2.0.5, at classes/class-wp-stream-api.php

469 lines 11.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class WP_Stream_API {
4
5 /**
6 * API Key key/identifier
7 */
8 const API_KEY_OPTION_KEY = 'wp_stream_site_api_key';
9
10 /**
11 * Site UUID key/identifier
12 */
13 const SITE_UUID_OPTION_KEY = 'wp_stream_site_uuid';
14
15 /**
16 * Site Retricted key/identifier
17 */
18 const RESTRICTED_OPTION_KEY = 'wp_stream_site_restricted';
19
20 /**
21 * The site's API Key
22 *
23 * @var string
24 */
25 public $api_key = false;
26
27 /**
28 * The site's unique identifier
29 *
30 * @var string
31 */
32 public $site_uuid = false;
33
34 /**
35 * The site's restriction status
36 *
37 * @var bool
38 */
39 public static $restricted = true;
40
41 /**
42 * The API URL
43 *
44 * @var string
45 */
46 public $api_url = 'https://api.wp-stream.com';
47
48 /**
49 * Error messages
50 *
51 * @var array
52 */
53 public $errors = array();
54
55 /**
56 * Total API calls made per page load
57 * Used for debugging and optimization
58 *
59 * @var array
60 */
61 public $count = 0;
62
63 /**
64 * Public constructor
65 *
66 * @return void
67 */
68 public function __construct() {
69 $this->api_key = get_option( self::API_KEY_OPTION_KEY, 0 );
70 $this->site_uuid = get_option( self::SITE_UUID_OPTION_KEY, 0 );
71 self::$restricted = get_option( self::RESTRICTED_OPTION_KEY, 1 );
72 }
73
74 /**
75 * Check if the current site is restricted
76 *
77 * @param bool Force the API to send a request to check the site's plan type
78 *
79 * @return bool
80 */
81 public static function is_restricted( $force_check = false ) {
82 if ( $force_check ) {
83 $site = WP_Stream::$api->get_site();
84
85 self::$restricted = ( ! isset( $site->plan->type ) || 'free' === $site->plan->type );
86 }
87
88 return self::$restricted;
89 }
90
91 /**
92 * Used to prioritise the streams transport which support non-blocking
93 *
94 * @filter http_api_transports
95 *
96 * @return bool
97 */
98 public static function http_api_transport_priority( $request_order, $args, $url ) {
99 if ( isset( $args['blocking'] ) && false === $args['blocking'] ) {
100 $request_order = array( 'streams', 'curl' );
101 }
102
103 return $request_order;
104 }
105
106 /**
107 * Get the details for a specific site.
108 *
109 * @param array Returns specified fields only.
110 * @param bool Allow API calls to be cached.
111 * @param int Set transient expiration in seconds.
112 *
113 * @return mixed
114 */
115 public function get_site( $fields = array(), $allow_cache = true, $expiration = 30 ) {
116 if ( ! $this->site_uuid ) {
117 return false;
118 }
119
120 $params = array();
121
122 if ( ! empty( $fields ) ) {
123 $params['fields'] = implode( ',', $fields );
124 }
125
126 $url = $this->request_url( sprintf( '/sites/%s', urlencode( $this->site_uuid ) ), $params );
127 $args = array( 'method' => 'GET' );
128 $site = $this->remote_request( $url, $args, $allow_cache, $expiration );
129
130 if ( $site && ! is_wp_error( $site ) ) {
131 $is_restricted = ( ! isset( $site->plan->type ) || 'free' === $site->plan->type ) ? 1 : 0;
132
133 if ( self::$restricted !== (bool) $is_restricted ) {
134 self::$restricted = $is_restricted;
135
136 update_option( self::RESTRICTED_OPTION_KEY, $is_restricted );
137 }
138 }
139
140 return $site;
141 }
142
143 /**
144 * Return this site's plan type
145 *
146 * @return string
147 */
148 public function get_plan_type() {
149 $site = WP_Stream::$api->get_site();
150
151 return isset( $site->plan->type ) ? esc_html( $site->plan->type ) : 'free';
152 }
153
154 /**
155 * Return this site's plan type label
156 *
157 * @return string
158 */
159 public function get_plan_type_label() {
160 $type = WP_Stream::$api->get_plan_type();
161
162 // Only check the beginning of these type strings
163 if ( 0 === strpos( $type, 'pro' ) ) {
164 $label = __( 'Pro', 'stream' );
165 } else {
166 $label = __( 'Free', 'stream' );
167 }
168
169 return $label;
170 }
171
172 /**
173 * Return this site's plan retention length
174 *
175 * @return int
176 */
177 public function get_plan_retention() {
178 $site = WP_Stream::$api->get_site();
179
180 return isset( $site->plan->retention ) ? absint( $site->plan->retention ) : 30;
181 }
182
183 /**
184 * Return this site's plan retention label
185 *
186 * @return string
187 */
188 public function get_plan_retention_label() {
189 $retention = WP_Stream::$api->get_plan_retention();
190
191 if ( 0 === $retention ) {
192 $label = __( '1 Year', 'stream' );
193 } else {
194 $label = sprintf(
195 _n( '1 Day', '%s Days', $retention, 'stream' ),
196 $retention
197 );
198 }
199
200 return $label;
201 }
202
203 /**
204 * Return the oldest record date (GMT) allowed for this site's plan
205 *
206 * @return string
207 */
208 public function get_plan_retention_max_date( $format = 'Y-m-d H:i:s' ) {
209 $retention = WP_Stream::$api->get_plan_retention();
210
211 return empty( $retention ) ? gmdate( $format, strtotime( '1 year ago' ) ) : gmdate( $format, strtotime( sprintf( '%d days ago', $retention ) ) );
212 }
213
214 /**
215 * Return this site's plan amount
216 *
217 * @return string
218 */
219 public function get_plan_amount() {
220 $site = WP_Stream::$api->get_site();
221
222 return isset( $site->plan->amount ) ? esc_html( $site->plan->amount ) : 0;
223 }
224
225 /**
226 * Return the account creation date for this site
227 *
228 * @return string
229 */
230 public function get_created_date() {
231 $site = WP_Stream::$api->get_site();
232 $date_format = get_option( 'date_format' );
233
234 return isset( $site->created ) ? date_i18n( $date_format, strtotime( $site->created ) ) : __( 'N/A', 'stream' );
235 }
236
237 /**
238 * Return the expiration date for this site's plan
239 *
240 * @return string
241 */
242 public function get_expiry_date() {
243 $site = WP_Stream::$api->get_site();
244 $date_format = get_option( 'date_format' );
245
246 return isset( $site->expiry->date ) ? date_i18n( $date_format, strtotime( $site->expiry->date ) ) : __( 'N/A', 'stream' );
247 }
248
249 /**
250 * Get a specific record.
251 *
252 * @param string A record ID.
253 * @param array Returns specified fields only.
254 * @param bool Allow API calls to be cached.
255 * @param int Set transient expiration in seconds.
256 *
257 * @return mixed
258 */
259 public function get_record( $record_id = false, $fields = array(), $allow_cache = true, $expiration = 30 ) {
260 if ( false === $record_id ) {
261 return false;
262 }
263
264 if ( ! $this->site_uuid ) {
265 return false;
266 }
267
268 $params = array();
269
270 if ( ! empty( $fields ) ) {
271 $params['fields'] = implode( ',', $fields );
272 }
273
274 $url = $this->request_url( sprintf( '/sites/%s/records/%s', urlencode( $this->site_uuid ), urlencode( $record_id ) ), $params );
275 $args = array( 'method' => 'GET' );
276
277 return $this->remote_request( $url, $args, $allow_cache, $expiration );
278 }
279
280 /**
281 * Get all records.
282 *
283 * @param array Returns specified fields only.
284 * @param bool Allow API calls to be cached.
285 * @param int Set transient expiration in seconds.
286 *
287 * @return mixed
288 */
289 public function get_records( $fields = array(), $allow_cache = true, $expiration = 30 ) {
290 if ( ! $this->site_uuid ) {
291 return false;
292 }
293
294 $params = array();
295
296 if ( ! empty( $fields ) ) {
297 $params['fields'] = implode( ',', $fields );
298 }
299
300 $url = $this->request_url( sprintf( '/sites/%s/records', urlencode( $this->site_uuid ) ), $params );
301 $args = array( 'method' => 'GET' );
302
303 return $this->remote_request( $url, $args, $allow_cache, $expiration );
304 }
305
306 /**
307 * Create new records.
308 *
309 * @param array $records
310 * @param bool $blocking
311 *
312 * @return mixed
313 */
314 public function new_records( $records, $blocking = false ) {
315 if ( ! $this->site_uuid ) {
316 return false;
317 }
318
319 $url = $this->request_url( sprintf( '/sites/%s/records', urlencode( $this->site_uuid ) ) );
320 $args = array( 'method' => 'POST', 'body' => json_encode( array( 'records' => $records ) ), 'blocking' => (bool) $blocking );
321
322 return $this->remote_request( $url, $args );
323 }
324
325 /**
326 * Search all records.
327 *
328 * @param array Elasticsearch's Query DSL query object.
329 * @param array Returns specified fields only.
330 * @param bool Allow API calls to be cached.
331 * @param int Set transient expiration in seconds.
332 *
333 * @return mixed
334 */
335 public function search( $query = array(), $fields = array(), $sites = array(), $search_type = '', $allow_cache = false, $expiration = 120 ) {
336 if ( ! $this->site_uuid ) {
337 return false;
338 }
339
340 $body = array();
341
342 $body['query'] = ! empty( $query ) ? $query : array();
343 $body['fields'] = ! empty( $fields ) ? $fields : array();
344 $body['sites'] = ! empty( $sites ) ? $sites : array( $this->site_uuid );
345 $body['search_type'] = ! empty( $search_type ) ? $search_type : '';
346
347 $url = $this->request_url( '/search' );
348 $args = array( 'method' => 'POST', 'body' => json_encode( (object) $body ) );
349
350 return $this->remote_request( $url, $args, $allow_cache, $expiration );
351 }
352
353 /**
354 * Helper function to create and escape a URL for an API request.
355 *
356 * @param string The endpoint path, with a starting slash.
357 * @param array The $_GET parameters.
358 *
359 * @return string A properly escaped URL.
360 */
361 public function request_url( $path, $params = array() ) {
362 return esc_url_raw(
363 add_query_arg(
364 $params,
365 untrailingslashit( $this->api_url ) . $path
366 )
367 );
368 }
369
370 /**
371 * Helper function to query the marketplace API via wp_remote_request.
372 *
373 * @param string The url to access.
374 * @param string The method of the request.
375 * @param array The headers sent during the request.
376 * @param bool Allow API calls to be cached.
377 * @param int Set transient expiration in seconds.
378 *
379 * @return object The results of the wp_remote_request request.
380 */
381 protected function remote_request( $url = '', $args = array(), $allow_cache = true, $expiration = 300 ) {
382 if ( empty( $url ) || empty( $this->api_key ) ) {
383 return false;
384 }
385
386 $defaults = array(
387 'headers' => array(),
388 'method' => 'GET',
389 'body' => '',
390 'sslverify' => true,
391 );
392
393 $this->count++;
394
395 $args = wp_parse_args( $args, $defaults );
396
397 $args['headers']['Stream-Site-API-Key'] = $this->api_key;
398 $args['headers']['Content-Type'] = 'application/json';
399
400 if ( WP_Stream::is_development_mode() ) {
401 $args['blocking'] = true;
402 }
403
404 add_filter( 'http_api_transports', array( __CLASS__, 'http_api_transport_priority' ), 10, 3 );
405
406 $transient = 'wp_stream_' . md5( $url );
407
408 if ( 'GET' === $args['method'] && $allow_cache ) {
409 if ( false === ( $request = get_transient( $transient ) ) ) {
410 $request = wp_remote_request( $url, $args );
411
412 set_transient( $transient, $request, $expiration );
413 }
414 } else {
415 $request = wp_remote_request( $url, $args );
416 }
417
418 remove_filter( 'http_api_transports', array( __CLASS__, 'http_api_transport_priority' ), 10 );
419
420 // Return early if the request is non blocking
421 if ( isset( $args['blocking'] ) && false === $args['blocking'] ) {
422 return true;
423 }
424
425 if ( ! is_wp_error( $request ) ) {
426 /**
427 * Filter the request data of the API response.
428 *
429 * Does not fire on non-blocking requests.
430 *
431 * @since 2.0.0
432 *
433 * @param string $url
434 * @param array $args
435 *
436 * @return array
437 */
438 $data = apply_filters( 'wp_stream_api_request_data', json_decode( $request['body'] ), $url, $args );
439
440 // Loose comparison needed
441 if ( 200 == $request['response']['code'] || 201 == $request['response']['code'] ) {
442 return $data;
443 } else {
444 // Disconnect if unauthorized or no longer exists, loose comparison needed
445 if ( 403 == $request['response']['code'] || 410 == $request['response']['code'] ) {
446 WP_Stream_Admin::remove_api_authentication();
447 }
448
449 $this->errors['errors']['http_code'] = $request['response']['code'];
450 }
451
452 if ( isset( $data->error ) ) {
453 $this->errors['errors']['api_error'] = $data->error;
454 }
455 } else {
456 $this->errors['errors']['remote_request_error'] = $request->get_error_message();
457
458 WP_Stream::notice( sprintf( '<strong>%s</strong> %s.', __( 'Stream API Error.', 'stream' ), $this->errors['errors']['remote_request_error'] ) );
459 }
460
461 if ( ! empty( $this->errors ) ) {
462 delete_transient( $transient );
463 }
464
465 return false;
466 }
467
468 }
469