PluginProbe ʕ •ᴥ•ʔ
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF / trunk
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF vtrunk
2.0.5 trunk 1.3.7 1.4.0 1.4.1 1.4.2 1.4.6 1.5.0 1.5.3 1.5.6 1.5.8 1.6.5 1.6.6 1.6.9 1.7.0 1.7.4 1.8.1 1.8.2 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4
robin-image-optimizer / libs / factory / freemius / includes / class-freemius-api.php
robin-image-optimizer / libs / factory / freemius / includes Last commit date
entities 5 months ago licensing 5 months ago sdk 5 months ago updates 5 months ago class-freemius-api.php 5 months ago index.php 6 months ago
class-freemius-api.php
414 lines
1 <?php
2
3 namespace WBCR\Factory_Freemius_Rio_600;
4
5 use WBCR\Factory_Freemius_Rio_600\Sdk\Freemius_Api_WordPress;
6 use WBCR\Factory_Freemius_Rio_600\Sdk\Freemius_Exception;
7 use Wbcr_Factory600_Plugin;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 if ( ! defined( 'FREEMIUS__DIR_SDK' ) ) {
14 define( 'FREEMIUS__DIR_SDK', __DIR__ . '/sdk' );
15 }
16
17 /**
18 * Class FS_Api
19 *
20 * Wraps Freemius API SDK to handle:
21 * 1. Clock sync.
22 * 2. Fallback to HTTP when HTTPS fails.
23 * 3. Adds caching layer to GET requests.
24 * 4. Adds consistency for failed requests by using last cached version.
25 *
26 * @package core
27 * @since 1.0.0
28 */
29 final class Api {
30
31 /**
32 * @var Freemius_Api_WordPress
33 */
34 private $api;
35
36 /**
37 * @var Wbcr_Factory600_Plugin
38 */
39 private $plugin;
40
41 /**
42 * @var Api[]
43 */
44 private static $instances = [];
45
46 /**
47 * @var int Clock diff in seconds between current server to API server.
48 */
49 private static $clock_diff;
50
51 /**
52 * @param Wbcr_Factory600_Plugin $slug
53 * @param string $scope 'app', 'developer', 'user' or 'install'.
54 * @param number $id Element's id.
55 * @param string $public_key Public key.
56 * @param bool|string $secret_key Element's secret key.
57 * @param bool $is_sandbox
58 */
59 private function __construct( Wbcr_Factory600_Plugin $plugin, $scope, $id, $public_key, $secret_key, $is_sandbox ) {
60 if ( ! class_exists( 'WBCR\Factory_Freemius_Rio_600\Sdk\Freemius_Api_WordPress' ) ) {
61 require_once FREEMIUS__DIR_SDK . '/FreemiusWordPress.php';
62 }
63
64 $this->api = new Freemius_Api_WordPress( $scope, $id, $public_key, $secret_key, $is_sandbox );
65
66 $this->plugin = $plugin;
67
68 self::$clock_diff = $plugin->getPopulateOption( 'freemius_api_clock_diff', 0 );
69 Freemius_Api_WordPress::SetClockDiff( self::$clock_diff );
70
71 if ( $plugin->getPopulateOption( 'api_force_http', false ) ) {
72 Freemius_Api_WordPress::SetHttp();
73 }
74 }
75
76 /**
77 * @param Wbcr_Factory600_Plugin $plugin
78 * @param string $scope 'app', 'developer', 'user' or 'install'.
79 * @param number $id Element's id.
80 * @param string $public_key Public key.
81 * @param bool $is_sandbox
82 * @param bool|string $secret_key Element's secret key.
83 *
84 * @return Api
85 */
86 public static function instance( Wbcr_Factory600_Plugin $plugin, $scope, $id, $public_key, $is_sandbox, $secret_key = false ) {
87 $identifier = md5( $plugin->getPluginName() . $scope . $id . $public_key . ( is_string( $secret_key ) ? $secret_key : '' ) . json_encode( $is_sandbox ) );
88
89 if ( ! isset( self::$instances[ $identifier ] ) ) {
90 self::$instances[ $identifier ] = new self( $plugin, $scope, $id, $public_key, $secret_key, $is_sandbox );
91 }
92
93 return self::$instances[ $identifier ];
94 }
95
96 /**
97 * Check if valid ping request result.
98 *
99 * @since 1.1.1
100 *
101 * @param mixed $pong
102 *
103 * @return bool
104 */
105 public function is_valid_ping( $pong ) {
106 return Freemius_Api_WordPress::Test( $pong );
107 }
108
109 /**
110 * Override API call to wrap it in servers' clock sync method.
111 *
112 * @param string $path
113 * @param string $method
114 * @param array $params
115 *
116 * @return array|mixed|string
117 * @throws Freemius_Exception
118 */
119 public function call( $path, $method = 'GET', $params = [] ) {
120 return $this->_call( $path, $method, $params );
121 }
122
123 /**
124 * @param string $path
125 *
126 * @return string
127 */
128 public function get_url( $path = '' ) {
129 return Freemius_Api_WordPress::GetUrl( $path, $this->api->IsSandbox() );
130 }
131
132 /**
133 * Get API request URL signed via query string.
134 *
135 * @param string $path
136 *
137 * @return string
138 * @throws Freemius_Exception
139 */
140 public function get_signed_url( $path ) {
141 return $this->api->GetSignedUrl( $path );
142 }
143
144 // ----------------------------------------------------------------------------------
145 // region Error Handling
146 // ----------------------------------------------------------------------------------
147
148 /**
149 * @since 1.2.1.5
150 *
151 * @param mixed $result
152 *
153 * @return bool Is API result contains an error.
154 */
155 public static function is_api_error( $result ) {
156 return ( is_object( $result ) && isset( $result->error ) ) || is_string( $result );
157 }
158
159 /**
160 * @since 2.0.0
161 *
162 * @param mixed $result
163 *
164 * @return bool Is API result contains an error.
165 */
166 public static function is_api_error_object( $result ) {
167 return ( is_object( $result ) && isset( $result->error ) && isset( $result->error->message ) );
168 }
169
170 /**
171 * Checks if given API result is a non-empty and not an error object.
172 *
173 * @since 1.2.1.5
174 *
175 * @param mixed $result
176 * @param string|null $required_property Optional property we want to verify that is set.
177 *
178 * @return bool
179 */
180 public static function is_api_result_object( $result, $required_property = null ) {
181 return ( is_object( $result ) && ! isset( $result->error ) && ( empty( $required_property ) || isset( $result->{$required_property} ) ) );
182 }
183
184 /**
185 * Checks if given API result is a non-empty entity object with non-empty ID.
186 *
187 * @since 1.2.1.5
188 *
189 * @param mixed $result
190 *
191 * @return bool
192 */
193 /*
194 static function is_api_result_entity( $result ) {
195 return self::is_api_result_object( $result, 'id' ) && FS_Entity::is_valid_id( $result->id );
196 }*/
197
198 /**
199 * Get API result error code. If failed to get code, returns an empty string.
200 *
201 * @since 2.0.0
202 *
203 * @param mixed $result
204 *
205 * @return string
206 */
207 public static function get_error_code( $result ) {
208 if ( is_object( $result ) && isset( $result->error ) && is_object( $result->error ) && ! empty( $result->error->code ) ) {
209 return $result->error->code;
210 }
211
212 return '';
213 }
214 // endregion
215
216 /**
217 * Find clock diff between server and API server, and store the diff locally.
218 *
219 * @param bool|int $diff
220 *
221 * @return bool|int False if clock diff didn't change, otherwise returns the clock diff in seconds.
222 */
223 private function sync_clock_diff( $diff = false ) {
224
225 // Sync clock and store.
226 $new_clock_diff = ( false === $diff ) ? Freemius_Api_WordPress::FindClockDiff() : $diff;
227
228 if ( $new_clock_diff === self::$clock_diff ) {
229 return false;
230 }
231
232 self::$clock_diff = $new_clock_diff;
233
234 // Update API clock's diff.
235 Freemius_Api_WordPress::SetClockDiff( self::$clock_diff );
236
237 // Store new clock diff in storage.
238 $this->plugin->updatePopulateOption( 'freemius_api_clock_diff', self::$clock_diff );
239
240 return $new_clock_diff;
241 }
242
243 /**
244 * Override API call to enable retry with servers' clock auto sync method.
245 *
246 * @param string $path
247 * @param string $method
248 * @param array $params
249 * @param bool $retry Is in retry or first call attempt.
250 *
251 * @return array|mixed|string
252 */
253 private function _call( $path, $method = 'GET', $params = [], $retry = false ) {
254
255 $result = $this->api->Api( $path, $method, $params );
256
257 if ( null !== $result && isset( $result->error ) && isset( $result->error->code ) && 'request_expired' === $result->error->code ) {
258 if ( ! $retry ) {
259 $diff = isset( $result->error->timestamp ) ? ( time() - strtotime( $result->error->timestamp ) ) : false;
260
261 // Try to sync clock diff.
262 if ( false !== $this->sync_clock_diff( $diff ) ) {
263 // Retry call with new synced clock.
264 return $this->_call( $path, $method, $params, true );
265 }
266 }
267 }
268
269 return $result;
270 }
271
272 /**
273 * Test API connectivity.
274 *
275 * @since 1.0.9 If fails, try to fallback to HTTP.
276 * @since 1.1.6 Added a 5-min caching mechanism, to prevent from overloading the server if the API if
277 * temporary down.
278 *
279 * @return bool True if successful connectivity to the API.
280 */
281 /*
282 public static function test( $plugin ) {
283 self::init( $plugin );
284
285 $cache_key = 'ping_test';
286
287 $test = self::$_cache->get_valid( $cache_key, null );
288
289 if ( is_null( $test ) ) {
290 $test = Freemius_Api_WordPress::Test();
291
292 if ( false === $test && Freemius_Api_WordPress::IsHttps() ) {
293 // Fallback to HTTP, since HTTPS fails.
294 Freemius_Api_WordPress::SetHttp();
295
296 self::$_options->set_option( 'api_force_http', true, true );
297
298 $test = Freemius_Api_WordPress::Test();
299
300 if ( false === $test ) {
301 /**
302 * API connectivity test fail also in HTTP request, therefore,
303 * fallback to HTTPS to keep connection secure.
304 *
305 * @since 1.1.6
306 */
307 /*
308 self::$_options->set_option( 'api_force_http', false, true );
309 }
310 }
311
312 self::$_cache->set( $cache_key, $test, WP_FS__TIME_5_MIN_IN_SEC );
313 }
314
315 return $test;
316 }*/
317
318 /**
319 * Check if API is temporary down.
320 *
321 * @since 1.1.6
322 *
323 * @return bool
324 */
325 /*
326 public static function is_temporary_down() {
327 self::init();
328
329 $test = self::$_cache->get_valid( 'ping_test', null );
330
331 return ( false === $test );
332 }*/
333
334 /**
335 * @since 1.1.6
336 *
337 * @return object
338 */
339 /*
340 private function get_temporary_unavailable_error() {
341 return (object) array(
342 'error' => (object) array(
343 'type' => 'TemporaryUnavailable',
344 'message' => 'API is temporary unavailable, please retry in ' . ( self::$_cache->get_record_expiration( 'ping_test' ) - WP_FS__SCRIPT_START_TIME ) . ' sec.',
345 'code' => 'temporary_unavailable',
346 'http' => 503
347 )
348 );
349 }*/
350
351 /**
352 * Ping API for connectivity test, and return result object.
353 *
354 * @since 1.0.9
355 *
356 * @param null|string $unique_anonymous_id
357 * @param array $params
358 *
359 * @return object
360 */
361 /*
362 public function ping( $unique_anonymous_id = null, $params = array() ) {
363 if ( self::is_temporary_down() ) {
364 return $this->get_temporary_unavailable_error();
365 }
366
367 $pong = is_null( $unique_anonymous_id ) ? Freemius_Api_WordPress::Ping() : $this->_call( 'ping.json?' . http_build_query( array_merge( array( 'uid' => $unique_anonymous_id ), $params ) ) );
368
369 if ( $this->is_valid_ping( $pong ) ) {
370 return $pong;
371 }
372
373 if ( self::should_try_with_http( $pong ) ) {
374 // Fallback to HTTP, since HTTPS fails.
375 Freemius_Api_WordPress::SetHttp();
376
377 $this->plugin->updatePopulateOption( 'api_force_http', true );
378
379 $pong = is_null( $unique_anonymous_id ) ? Freemius_Api_WordPress::Ping() : $this->_call( 'ping.json?' . http_build_query( array_merge( array( 'uid' => $unique_anonymous_id ), $params ) ) );
380
381 if ( ! $this->is_valid_ping( $pong ) ) {
382 $this->plugin->updatePopulateOption( 'api_force_http', false );
383 }
384 }
385
386 return $pong;
387 }*/
388
389 /**
390 * Check if based on the API result we should try
391 * to re-run the same request with HTTP instead of HTTPS.
392 *
393 * @since 1.1.6
394 *
395 * @param $result
396 *
397 * @return bool
398 */
399 /*
400 private static function should_try_with_http( $result ) {
401 if ( ! Freemius_Api_WordPress::IsHttps() ) {
402 return false;
403 }
404
405 return ( ! is_object( $result ) || ! isset( $result->error ) || ! isset( $result->error->code ) || ! in_array( $result->error->code, array(
406 'curl_missing',
407 'cloudflare_ddos_protection',
408 'maintenance_mode',
409 'squid_cache_block',
410 'too_many_requests',
411 ) ) );
412 }*/
413 }
414