GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 563189...ded6c2 )
by Brad
02:25
created

FS_Api::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 6
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 22 and the first side effect is on line 10.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
	/**
3
	 * @package     Freemius
4
	 * @copyright   Copyright (c) 2015, Freemius, Inc.
5
	 * @license     https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6
	 * @since       1.0.4
7
	 */
8
9
	if ( ! defined( 'ABSPATH' ) ) {
10
		exit;
11
	}
12
13
	/**
14
	 * Class FS_Api
15
	 *
16
	 * Wraps Freemius API SDK to handle:
17
	 *      1. Clock sync.
18
	 *      2. Fallback to HTTP when HTTPS fails.
19
	 *      3. Adds caching layer to GET requests.
20
	 *      4. Adds consistency for failed requests by using last cached version.
21
	 */
22
	class FS_Api {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
23
		/**
24
		 * @var FS_Api[]
25
		 */
26
		private static $_instances = array();
27
28
		/**
29
		 * @var FS_Option_Manager Freemius options, options-manager.
30
		 */
31
		private static $_options;
32
33
		/**
34
		 * @var FS_Cache_Manager API Caching layer
35
		 */
36
		private static $_cache;
37
38
		/**
39
		 * @var int Clock diff in seconds between current server to API server.
40
		 */
41
		private static $_clock_diff;
42
43
		/**
44
		 * @var Freemius_Api_WordPress
45
		 */
46
		private $_api;
47
48
		/**
49
		 * @var string
50
		 */
51
		private $_slug;
52
53
		/**
54
		 * @var FS_Logger
55
		 * @since 1.0.4
56
		 */
57
		private $_logger;
58
59
		/**
60
		 * @param string      $slug
61
		 * @param string      $scope      'app', 'developer', 'user' or 'install'.
62
		 * @param number      $id         Element's id.
63
		 * @param string      $public_key Public key.
64
		 * @param bool        $is_sandbox
65
		 * @param bool|string $secret_key Element's secret key.
66
		 *
67
		 * @return FS_Api
68
		 */
69
		static function instance( $slug, $scope, $id, $public_key, $is_sandbox, $secret_key = false ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
70
			$identifier = md5( $slug . $scope . $id . $public_key . ( is_string( $secret_key ) ? $secret_key : '' ) . json_encode( $is_sandbox ) );
71
72
			if ( ! isset( self::$_instances[ $identifier ] ) ) {
73
				self::_init();
74
75
				self::$_instances[ $identifier ] = new FS_Api( $slug, $scope, $id, $public_key, $secret_key, $is_sandbox );
76
			}
77
78
			return self::$_instances[ $identifier ];
79
		}
80
81
		private static function _init() {
82
			if ( isset( self::$_options ) ) {
83
				return;
84
			}
85
86
			if ( ! class_exists( 'Freemius_Api_WordPress' ) ) {
87
				require_once WP_FS__DIR_SDK . '/FreemiusWordPress.php';
88
			}
89
90
			self::$_options = FS_Option_Manager::get_manager( WP_FS__OPTIONS_OPTION_NAME, true, true );
91
			self::$_cache   = FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME );
92
93
			self::$_clock_diff = self::$_options->get_option( 'api_clock_diff', 0 );
94
			Freemius_Api_WordPress::SetClockDiff( self::$_clock_diff );
95
96
			if ( self::$_options->get_option( 'api_force_http', false ) ) {
97
				Freemius_Api_WordPress::SetHttp();
98
			}
99
		}
100
101
		/**
102
		 * @param string      $slug
103
		 * @param string      $scope      'app', 'developer', 'user' or 'install'.
104
		 * @param number      $id         Element's id.
105
		 * @param string      $public_key Public key.
106
		 * @param bool|string $secret_key Element's secret key.
107
		 * @param bool        $is_sandbox
108
		 */
109
		private function __construct( $slug, $scope, $id, $public_key, $secret_key, $is_sandbox ) {
110
			$this->_api = new Freemius_Api_WordPress( $scope, $id, $public_key, $secret_key, $is_sandbox );
111
112
			$this->_slug   = $slug;
113
			$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_api', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
114
		}
115
116
		/**
117
		 * Find clock diff between server and API server, and store the diff locally.
118
		 *
119
		 * @param bool|int $diff
120
		 *
121
		 * @return bool|int False if clock diff didn't change, otherwise returns the clock diff in seconds.
122
		 */
123
		private function _sync_clock_diff( $diff = false ) {
124
			$this->_logger->entrance();
125
126
			// Sync clock and store.
127
			$new_clock_diff = ( false === $diff ) ?
128
				Freemius_Api_WordPress::FindClockDiff() :
129
				$diff;
130
131
			if ( $new_clock_diff === self::$_clock_diff ) {
132
				return false;
133
			}
134
135
			self::$_clock_diff = $new_clock_diff;
0 ignored issues
show
Documentation Bug introduced by
It seems like $new_clock_diff can also be of type boolean. However, the property $_clock_diff is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
136
137
			// Update API clock's diff.
138
			Freemius_Api_WordPress::SetClockDiff( self::$_clock_diff );
139
140
			// Store new clock diff in storage.
141
			self::$_options->set_option( 'api_clock_diff', self::$_clock_diff, true );
142
143
			return $new_clock_diff;
144
		}
145
146
		/**
147
		 * Override API call to enable retry with servers' clock auto sync method.
148
		 *
149
		 * @param string $path
150
		 * @param string $method
151
		 * @param array  $params
152
		 * @param bool   $retry Is in retry or first call attempt.
153
		 *
154
		 * @return array|mixed|string|void
155
		 */
156
		private function _call( $path, $method = 'GET', $params = array(), $retry = false ) {
157
			$this->_logger->entrance( $method . ':' . $path );
158
159
			if ( self::is_temporary_down() ) {
160
				$result = $this->get_temporary_unavailable_error();
161
			} else {
162
				$result = $this->_api->Api( $path, $method, $params );
163
164
				if ( null !== $result &&
165
				     isset( $result->error ) &&
166
				     isset( $result->error->code ) &&
167
				     'request_expired' === $result->error->code
168
				) {
169
					if ( ! $retry ) {
170
						$diff = isset( $result->error->timestamp ) ?
171
							( time() - strtotime( $result->error->timestamp ) ) :
172
							false;
173
174
						// Try to sync clock diff.
175
						if ( false !== $this->_sync_clock_diff( $diff ) ) {
176
							// Retry call with new synced clock.
177
							return $this->_call( $path, $method, $params, true );
178
						}
179
					}
180
				}
181
			}
182
183
			if ( $this->_logger->is_on() && self::is_api_error( $result ) ) {
184
				// Log API errors.
185
				$this->_logger->api_error( $result );
186
			}
187
188
			return $result;
189
		}
190
191
		/**
192
		 * Override API call to wrap it in servers' clock sync method.
193
		 *
194
		 * @param string $path
195
		 * @param string $method
196
		 * @param array  $params
197
		 *
198
		 * @return array|mixed|string|void
199
		 * @throws Freemius_Exception
200
		 */
201
		function call( $path, $method = 'GET', $params = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
202
			return $this->_call( $path, $method, $params );
203
		}
204
205
		/**
206
		 * Get API request URL signed via query string.
207
		 *
208
		 * @param string $path
209
		 *
210
		 * @return string
211
		 */
212
		function get_signed_url( $path ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
213
			return $this->_api->GetSignedUrl( $path );
214
		}
215
216
		/**
217
		 * @param string $path
218
		 * @param bool   $flush
219
		 * @param int    $expiration (optional) Time until expiration in seconds from now, defaults to 24 hours
220
		 *
221
		 * @return stdClass|mixed
222
		 */
223
		function get( $path = '/', $flush = false, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
224
			$this->_logger->entrance( $path );
225
226
			$cache_key = $this->get_cache_key( $path );
227
228
			// Always flush during development.
229
			if ( WP_FS__DEV_MODE || $this->_api->IsSandbox() ) {
230
				$flush = true;
231
			}
232
233
			$cached_result = self::$_cache->get( $cache_key );
234
235
			if ( $flush || ! self::$_cache->has_valid( $cache_key, $expiration ) ) {
236
				$result = $this->call( $path );
237
238
				if ( ! is_object( $result ) || isset( $result->error ) ) {
239
					// Api returned an error.
240
					if ( is_object( $cached_result ) &&
241
					     ! isset( $cached_result->error )
242
					) {
243
						// If there was an error during a newer data fetch,
244
						// fallback to older data version.
245
						$result = $cached_result;
246
247
						if ( $this->_logger->is_on() ) {
248
							$this->_logger->warn( 'Fallback to cached API result: ' . var_export( $cached_result, true ) );
249
						}
250
					} else {
251
					    if ( is_object( $result ) && 404 == $result->error->http ) {
252
                            /**
253
                             * If the response code is 404, cache the result for half of the `$expiration`.
254
                             *
255
                             * @author Leo Fajardo (@leorw)
256
                             * @since 2.2.3.1
257
                             */
258
					        $expiration /= 2;
259
                        } else {
260
                            // If no older data version and the response code is not 404, return result without
261
                            // caching the error.
262
                            return $result;
263
                        }
264
					}
265
				}
266
267
				self::$_cache->set( $cache_key, $result, $expiration );
268
269
				$cached_result = $result;
270
			} else {
271
				$this->_logger->log( 'Using cached API result.' );
272
			}
273
274
			return $cached_result;
275
		}
276
277
		/**
278
		 * Check if there's a cached version of the API request.
279
		 *
280
		 * @author Vova Feldman (@svovaf)
281
		 * @since  1.2.1
282
		 *
283
		 * @param string $path
284
		 * @param string $method
285
		 * @param array  $params
286
		 *
287
		 * @return bool
288
		 */
289
		function is_cached( $path, $method = 'GET', $params = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
290
			$cache_key = $this->get_cache_key( $path, $method, $params );
291
292
			return self::$_cache->has_valid( $cache_key );
293
		}
294
295
		/**
296
		 * Invalidate a cached version of the API request.
297
		 *
298
		 * @author Vova Feldman (@svovaf)
299
		 * @since  1.2.1.5
300
		 *
301
		 * @param string $path
302
		 * @param string $method
303
		 * @param array  $params
304
		 */
305
		function purge_cache( $path, $method = 'GET', $params = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
306
			$this->_logger->entrance( "{$method}:{$path}" );
307
308
			$cache_key = $this->get_cache_key( $path, $method, $params );
309
310
			self::$_cache->purge( $cache_key );
311
		}
312
313
        /**
314
         * Invalidate a cached version of the API request.
315
         *
316
         * @author Vova Feldman (@svovaf)
317
         * @since  2.0.0
318
         *
319
         * @param string $path
320
         * @param int    $expiration
321
         * @param string $method
322
         * @param array  $params
323
         */
324
        function update_cache_expiration( $path, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $method = 'GET', $params = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
325
            $this->_logger->entrance( "{$method}:{$path}:{$expiration}" );
326
327
            $cache_key = $this->get_cache_key( $path, $method, $params );
328
329
            self::$_cache->update_expiration( $cache_key, $expiration );
330
        }
331
332
        /**
333
		 * @param string $path
334
		 * @param string $method
335
		 * @param array  $params
336
		 *
337
		 * @return string
338
		 * @throws \Freemius_Exception
339
		 */
340
		private function get_cache_key( $path, $method = 'GET', $params = array() ) {
341
			$canonized = $this->_api->CanonizePath( $path );
342
//			$exploded = explode('/', $canonized);
0 ignored issues
show
Unused Code Comprehensibility introduced by
44% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
343
//			return $method . '_' . array_pop($exploded) . '_' . md5($canonized . json_encode($params));
344
			return strtolower( $method . ':' . $canonized ) . ( ! empty( $params ) ? '#' . md5( json_encode( $params ) ) : '' );
345
		}
346
347
		/**
348
		 * Test API connectivity.
349
		 *
350
		 * @author Vova Feldman (@svovaf)
351
		 * @since  1.0.9 If fails, try to fallback to HTTP.
352
		 * @since  1.1.6 Added a 5-min caching mechanism, to prevent from overloading the server if the API if
353
		 *         temporary down.
354
		 *
355
		 * @return bool True if successful connectivity to the API.
356
		 */
357
		static function test() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
358
			self::_init();
359
360
			$cache_key = 'ping_test';
361
362
			$test = self::$_cache->get_valid( $cache_key, null );
363
364
			if ( is_null( $test ) ) {
365
				$test = Freemius_Api_WordPress::Test();
366
367
				if ( false === $test && Freemius_Api_WordPress::IsHttps() ) {
368
					// Fallback to HTTP, since HTTPS fails.
369
					Freemius_Api_WordPress::SetHttp();
370
371
					self::$_options->set_option( 'api_force_http', true, true );
372
373
					$test = Freemius_Api_WordPress::Test();
374
375
					if ( false === $test ) {
376
						/**
377
						 * API connectivity test fail also in HTTP request, therefore,
378
						 * fallback to HTTPS to keep connection secure.
379
						 *
380
						 * @since 1.1.6
381
						 */
382
						self::$_options->set_option( 'api_force_http', false, true );
383
					}
384
				}
385
386
				self::$_cache->set( $cache_key, $test, WP_FS__TIME_5_MIN_IN_SEC );
387
			}
388
389
			return $test;
390
		}
391
392
		/**
393
		 * Check if API is temporary down.
394
		 *
395
		 * @author Vova Feldman (@svovaf)
396
		 * @since  1.1.6
397
		 *
398
		 * @return bool
399
		 */
400
		static function is_temporary_down() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
401
			self::_init();
402
403
			$test = self::$_cache->get_valid( 'ping_test', null );
404
405
			return ( false === $test );
406
		}
407
408
		/**
409
		 * @author Vova Feldman (@svovaf)
410
		 * @since  1.1.6
411
		 *
412
		 * @return object
413
		 */
414
		private function get_temporary_unavailable_error() {
415
			return (object) array(
416
				'error' => (object) array(
417
					'type'    => 'TemporaryUnavailable',
418
					'message' => 'API is temporary unavailable, please retry in ' . ( self::$_cache->get_record_expiration( 'ping_test' ) - WP_FS__SCRIPT_START_TIME ) . ' sec.',
419
					'code'    => 'temporary_unavailable',
420
					'http'    => 503
421
				)
422
			);
423
		}
424
425
		/**
426
		 * Ping API for connectivity test, and return result object.
427
		 *
428
		 * @author   Vova Feldman (@svovaf)
429
		 * @since    1.0.9
430
		 *
431
		 * @param null|string $unique_anonymous_id
432
		 * @param array       $params
433
		 *
434
		 * @return object
435
		 */
436
		function ping( $unique_anonymous_id = null, $params = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
437
			$this->_logger->entrance();
438
439
			if ( self::is_temporary_down() ) {
440
				return $this->get_temporary_unavailable_error();
441
			}
442
443
			$pong = is_null( $unique_anonymous_id ) ?
444
				Freemius_Api_WordPress::Ping() :
445
				$this->_call( 'ping.json?' . http_build_query( array_merge(
446
						array( 'uid' => $unique_anonymous_id ),
447
						$params
448
					) ) );
449
450
			if ( $this->is_valid_ping( $pong ) ) {
451
				return $pong;
452
			}
453
454
			if ( self::should_try_with_http( $pong ) ) {
455
				// Fallback to HTTP, since HTTPS fails.
456
				Freemius_Api_WordPress::SetHttp();
457
458
				self::$_options->set_option( 'api_force_http', true, true );
459
460
				$pong = is_null( $unique_anonymous_id ) ?
461
					Freemius_Api_WordPress::Ping() :
462
					$this->_call( 'ping.json?' . http_build_query( array_merge(
463
							array( 'uid' => $unique_anonymous_id ),
464
							$params
465
						) ) );
466
467
				if ( ! $this->is_valid_ping( $pong ) ) {
468
					self::$_options->set_option( 'api_force_http', false, true );
469
				}
470
			}
471
472
			return $pong;
473
		}
474
475
		/**
476
		 * Check if based on the API result we should try
477
		 * to re-run the same request with HTTP instead of HTTPS.
478
		 *
479
		 * @author Vova Feldman (@svovaf)
480
		 * @since  1.1.6
481
		 *
482
		 * @param $result
483
		 *
484
		 * @return bool
485
		 */
486
		private static function should_try_with_http( $result ) {
487
			if ( ! Freemius_Api_WordPress::IsHttps() ) {
488
				return false;
489
			}
490
491
			return ( ! is_object( $result ) ||
492
			         ! isset( $result->error ) ||
493
			         ! isset( $result->error->code ) ||
494
			         ! in_array( $result->error->code, array(
495
				         'curl_missing',
496
				         'cloudflare_ddos_protection',
497
				         'maintenance_mode',
498
				         'squid_cache_block',
499
				         'too_many_requests',
500
			         ) ) );
501
502
		}
503
504
		/**
505
		 * Check if valid ping request result.
506
		 *
507
		 * @author Vova Feldman (@svovaf)
508
		 * @since  1.1.1
509
		 *
510
		 * @param mixed $pong
511
		 *
512
		 * @return bool
513
		 */
514
		function is_valid_ping( $pong ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
515
			return Freemius_Api_WordPress::Test( $pong );
516
		}
517
518
		function get_url( $path = '' ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
519
			return Freemius_Api_WordPress::GetUrl( $path, $this->_api->IsSandbox() );
520
		}
521
522
		/**
523
		 * Clear API cache.
524
		 *
525
		 * @author Vova Feldman (@svovaf)
526
		 * @since  1.0.9
527
		 */
528
		static function clear_cache() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
529
			self::_init();
530
531
			self::$_cache = FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME );
532
			self::$_cache->clear();
533
		}
534
535
		#----------------------------------------------------------------------------------
536
		#region Error Handling
537
		#----------------------------------------------------------------------------------
538
539
		/**
540
		 * @author Vova Feldman (@svovaf)
541
		 * @since  1.2.1.5
542
		 *
543
		 * @param mixed $result
544
		 *
545
		 * @return bool Is API result contains an error.
546
		 */
547
		static function is_api_error( $result ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
548
			return ( is_object( $result ) && isset( $result->error ) ) ||
549
			       is_string( $result );
550
		}
551
552
        /**
553
         * @author Vova Feldman (@svovaf)
554
         * @since  2.0.0
555
         *
556
         * @param mixed $result
557
         *
558
         * @return bool Is API result contains an error.
559
         */
560
        static function is_api_error_object( $result ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
561
            return (
562
                is_object( $result ) &&
563
                isset( $result->error ) &&
564
                isset( $result->error->message )
565
            );
566
        }
567
568
		/**
569
		 * Checks if given API result is a non-empty and not an error object.
570
		 *
571
		 * @author Vova Feldman (@svovaf)
572
		 * @since  1.2.1.5
573
		 *
574
		 * @param mixed       $result
575
		 * @param string|null $required_property Optional property we want to verify that is set.
576
		 *
577
		 * @return bool
578
		 */
579
		static function is_api_result_object( $result, $required_property = null ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
580
			return (
581
				is_object( $result ) &&
582
				! isset( $result->error ) &&
583
				( empty( $required_property ) || isset( $result->{$required_property} ) )
584
			);
585
		}
586
587
		/**
588
		 * Checks if given API result is a non-empty entity object with non-empty ID.
589
		 *
590
		 * @author Vova Feldman (@svovaf)
591
		 * @since  1.2.1.5
592
		 *
593
		 * @param mixed $result
594
		 *
595
		 * @return bool
596
		 */
597
		static function is_api_result_entity( $result ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
598
			return self::is_api_result_object( $result, 'id' ) &&
599
			       FS_Entity::is_valid_id( $result->id );
600
		}
601
602
        /**
603
         * Get API result error code. If failed to get code, returns an empty string.
604
         *
605
         * @author Vova Feldman (@svovaf)
606
         * @since  2.0.0
607
         *
608
         * @param mixed $result
609
         *
610
         * @return string
611
         */
612
        static function get_error_code( $result ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
613
            if ( is_object( $result ) &&
614
                 isset( $result->error ) &&
615
                 is_object( $result->error ) &&
616
                 ! empty( $result->error->code )
617
            ) {
618
                return $result->error->code;
619
            }
620
621
            return '';
622
        }
623
624
		#endregion
625
	}