PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.0
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.0
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/models/FrmFormApi.php +45 -348 6.32.15.0 View file →
@@ -4,44 +4,14 @@
4 4 }
5 5
6 6 class FrmFormApi {
7 7
8 - /**
9 - * @var string
10 - */
11 8 protected $license = '';
12 -
13 - /**
14 - * @var string
15 - */
16 9 protected $cache_key = '';
17 -
18 - /**
19 - * @var string
20 - */
21 10 protected $cache_timeout = '+6 hours';
22 11
23 12 /**
24 - * The number of days an add-on is new.
25 - *
26 - * @var int
27 - */
28 - protected $new_days = 90;
29 -
30 - /**
31 - * If true, calls to get_api_info will bypass cache.
32 - * This is set true by calling force_api_request.
33 - *
34 - * @var bool
35 - */
36 - protected $force = false;
37 -
38 - /**
39 13 * @since 3.06
40 - *
41 - * @param string|null $license The license key.
42 - *
43 - * @return void
44 14 */
45 15 public function __construct( $license = null ) {
46 16 $this->set_license( $license );
47 17 $this->set_cache_key();
@@ -48,18 +18,13 @@
48 18 }
49 19
50 20 /**
51 21 * @since 3.06
52 - *
53 - * @param string|null $license The license key.
54 - *
55 - * @return void
56 22 */
57 23 private function set_license( $license ) {
58 24 if ( $license === null ) {
59 25 $edd_update = $this->get_pro_updater();
60 -
61 - if ( $edd_update ) {
26 + if ( ! empty( $edd_update ) ) {
62 27 $license = $edd_update->license;
63 28 }
64 29 }
65 30 $this->license = $license;
@@ -66,9 +31,8 @@
66 31 }
67 32
68 33 /**
69 34 * @since 3.06
70 - *
71 35 * @return string
72 36 */
73 37 public function get_license() {
74 38 return $this->license;
@@ -75,18 +39,15 @@
75 39 }
76 40
77 41 /**
78 42 * @since 3.06
79 - *
80 - * @return void
81 43 */
82 44 protected function set_cache_key() {
83 - $this->cache_key = 'frm_addons_l' . ( $this->license ? md5( $this->license ) : '' );
45 + $this->cache_key = 'frm_addons_l' . ( empty( $this->license ) ? '' : md5( $this->license ) );
84 46 }
85 47
86 48 /**
87 49 * @since 3.06
88 - *
89 50 * @return string
90 51 */
91 52 public function get_cache_key() {
92 53 return $this->cache_key;
@@ -92,52 +53,24 @@
92 53 return $this->cache_key;
93 54 }
94 55
95 56 /**
96 - * Flag the force property as true, so the next API request bypasses cache.
97 - * This is used to pull API data for change logs, which are excluded from the cached data.
98 - *
99 - * @since 6.28
100 - *
101 - * @return void
102 - */
103 - public function force_api_request() {
104 - $this->force = true;
105 - }
106 -
107 - /**
108 57 * @since 3.06
109 - *
110 58 * @return array
111 59 */
112 60 public function get_api_info() {
113 61 $url = $this->api_url();
114 -
115 - if ( $this->license ) {
62 + if ( ! empty( $this->license ) ) {
116 63 $url .= '?l=' . urlencode( base64_encode( $this->license ) );
117 64 }
118 65
119 - if ( $this->force ) {
120 - $addons = false;
121 - $this->force = false;
122 - } else {
123 - $addons = $this->get_cached();
124 - }
125 -
126 - if ( is_array( $addons ) ) {
66 + $addons = $this->get_cached();
67 + if ( ! empty( $addons ) ) {
127 68 return $addons;
128 69 }
129 70
130 - if ( $this->is_running() ) {
131 - // If there's no saved cache, we'll need to wait for the current request to finish.
132 - return array();
133 - }
134 -
135 - $this->set_running();
136 -
137 71 // We need to know the version number to allow different downloads.
138 72 $agent = 'formidable/' . FrmAppHelper::plugin_version();
139 -
140 73 if ( class_exists( 'FrmProDb' ) ) {
141 74 $agent = 'formidable-pro/' . FrmProDb::$plug_version;
142 75 }
143 76
@@ -147,124 +80,43 @@
147 80 'timeout' => 25,
148 81 'user-agent' => $agent . '; ' . get_bloginfo( 'url' ),
149 82 )
150 83 );
151 -
152 84 if ( is_array( $response ) && ! is_wp_error( $response ) ) {
153 - $addons = $response['body'] ? json_decode( $response['body'], true ) : array();
154 - }
85 + $addons = $response['body'];
86 + if ( ! empty( $addons ) ) {
87 + $addons = json_decode( $addons, true );
155 88
156 - if ( ! is_array( $addons ) ) {
157 - $addons = array();
158 - }
159 -
160 - $addons['response_code'] = wp_remote_retrieve_response_code( $response );
161 -
162 - foreach ( $addons as $k => $addon ) {
163 - if ( ! is_array( $addon ) ) {
164 - continue;
165 - }
166 -
167 - if ( isset( $addon['categories'] ) ) {
168 - $cats = array_intersect( $this->skip_categories(), $addon['categories'] );
169 -
170 - if ( $cats ) {
171 - unset( $addons[ $k ] );
172 - continue;
89 + foreach ( $addons as $k => $addon ) {
90 + if ( ! isset( $addon['categories'] ) ) {
91 + continue;
92 + }
93 + $cats = array_intersect( $this->skip_categories(), $addon['categories'] );
94 + if ( ! empty( $cats ) ) {
95 + unset( $addons[ $k ] );
96 + }
173 97 }
174 - }
175 98
176 - if ( ! array_key_exists( 'is_new', $addon ) && array_key_exists( 'released', $addon ) ) {
177 - $addons[ $k ]['is_new'] = $this->is_new( $addon );
99 + $this->set_cached( $addons );
178 100 }
179 101 }
180 102
181 - $this->set_cached( $addons );
182 - $this->done_running();
103 + if ( empty( $addons ) ) {
104 + return array();
105 + }
183 106
184 107 return $addons;
185 108 }
186 109
187 110 /**
188 - * Prevent multiple requests from running at the same time.
189 - *
190 - * @since 6.8.3
191 - *
192 - * @return bool
193 - */
194 - protected function is_running() {
195 - if ( $this->run_as_multisite() ) {
196 - return get_site_transient( $this->transient_key() );
197 - }
198 - return get_transient( $this->transient_key() );
199 - }
200 -
201 - /**
202 - * @since 6.8.3
203 - *
204 - * @return void
205 - */
206 - protected function set_running() {
207 - $expires = 2 * MINUTE_IN_SECONDS;
208 -
209 - if ( $this->run_as_multisite() ) {
210 - set_site_transient( $this->transient_key(), true, $expires );
211 - return;
212 - }
213 -
214 - set_transient( $this->transient_key(), true, $expires );
215 - }
216 -
217 - /**
218 - * @since 6.8.3
219 - *
220 - * @return void
221 - */
222 - protected function done_running() {
223 - if ( $this->run_as_multisite() ) {
224 - delete_site_transient( $this->transient_key() );
225 - }
226 - delete_transient( $this->transient_key() );
227 - }
228 -
229 - /**
230 - * Only allow one site in the network to make the api request at a time.
231 - * If there is a license for the request, run individually.
232 - *
233 - * @since 6.8.3
234 - *
235 - * @return bool
236 - */
237 - protected function run_as_multisite() {
238 - return is_multisite() && ! $this->license;
239 - }
240 -
241 - /**
242 - * @since 6.8.3
243 - *
244 - * @return string
245 - */
246 - protected function transient_key() {
247 - return strtolower( self::class ) . '_request_lock';
248 - }
249 -
250 - /**
251 111 * @since 3.06
252 - *
253 - * @return string
254 112 */
255 113 protected function api_url() {
256 - if ( ! $this->license ) {
257 - // Direct traffic to Cloudflare worker when there is no license.
258 - return 'https://plapi.formidableforms.com/list/';
259 - }
260 114 return 'https://formidableforms.com/wp-json/s11edd/v1/updates/';
261 115 }
262 116
263 117 /**
264 118 * @since 3.06
265 - *
266 - * @return string[]
267 119 */
268 120 protected function skip_categories() {
269 121 return array( 'WordPress Form Templates', 'WordPress Form Style Templates' );
270 122 }
@@ -271,24 +123,21 @@
271 123
272 124 /**
273 125 * @since 3.06
274 126 *
275 - * @param object $license_plugin The FrmAddon object.
276 - * @param array $addons
127 + * @param object $license_plugin The FrmAddon object
277 128 *
278 129 * @return array
279 130 */
280 131 public function get_addon_for_license( $license_plugin, $addons = array() ) {
281 - if ( ! $addons ) {
132 + if ( empty( $addons ) ) {
282 133 $addons = $this->get_api_info();
283 134 }
284 -
285 135 $download_id = $license_plugin->download_id;
286 136 $plugin = array();
287 -
288 - if ( ! $download_id && $addons ) {
137 + if ( empty( $download_id ) && ! empty( $addons ) ) {
289 138 foreach ( $addons as $addon ) {
290 - if ( is_array( $addon ) && ! empty( $addon['title'] ) && 0 === strcasecmp( $license_plugin->plugin_name, $addon['title'] ) ) {
139 + if ( strtolower( $license_plugin->plugin_name ) == strtolower( $addon['title'] ) ) {
291 140 return $addon;
292 141 }
293 142 }
294 143 } elseif ( isset( $addons[ $download_id ] ) ) {
@@ -299,10 +148,8 @@
299 148 }
300 149
301 150 /**
302 151 * @since 3.06
303 - *
304 - * @return false|object
305 152 */
306 153 public function get_pro_updater() {
307 154 if ( FrmAppHelper::pro_is_installed() && is_callable( 'FrmProAppHelper::get_updater' ) ) {
308 155 $updater = FrmProAppHelper::get_updater();
@@ -315,28 +162,21 @@
315 162 }
316 163
317 164 /**
318 165 * @since 3.06
319 - *
320 - * @return array|bool
166 + * @return array
321 167 */
322 168 protected function get_cached() {
323 - $cache = $this->get_cached_option();
169 + $cache = get_option( $this->cache_key );
324 170
325 - if ( ! $cache ) {
326 - return false;
171 + if ( empty( $cache ) || empty( $cache['timeout'] ) || current_time( 'timestamp' ) > $cache['timeout'] ) {
172 + return false; // Cache is expired
327 173 }
328 174
329 - $is_expired = empty( $cache['timeout'] ) || time() > $cache['timeout'];
330 -
331 - if ( ! $is_expired && isset( $cache['version'] ) && $cache['version'] !== FrmAppHelper::plugin_version() ) {
332 - $is_expired = true;
333 - }
334 -
335 - // Avoid old cached data, unless we're currently trying to query for new data.
336 - // The call to $this->is_running likely triggers a database query, so only call if if we're expired.
337 - // (Rather than the other way around, which is less efficient).
338 - if ( $is_expired && ! $this->is_running() ) {
175 + $version = FrmAppHelper::plugin_version();
176 + $for_current = isset( $cache['version'] ) && $cache['version'] == $version;
177 + if ( ! $for_current ) {
178 + // Force a new check.
339 179 return false;
340 180 }
341 181
342 182 return json_decode( $cache['value'], true );
@@ -342,196 +182,53 @@
342 182 return json_decode( $cache['value'], true );
343 183 }
344 184
345 185 /**
346 - * Get the cache for the network if multisite.
347 - *
348 - * @since 6.8.3
349 - *
350 - * @return mixed
351 - */
352 - protected function get_cached_option() {
353 - if ( is_multisite() ) {
354 - $cached = get_site_option( $this->cache_key );
355 -
356 - if ( $cached ) {
357 - return $cached;
358 - }
359 - }
360 -
361 - return get_option( $this->cache_key );
362 - }
363 -
364 - /**
365 186 * @since 3.06
366 - *
367 - * @param array $addons
368 - *
369 - * @return void
370 187 */
371 188 protected function set_cached( $addons ) {
372 - $addons = $this->reduce_addon_data_before_caching( $addons );
373 -
374 189 $data = array(
375 - 'timeout' => strtotime( $this->get_cache_timeout( $addons ), time() ),
376 - 'value' => wp_json_encode( $addons ),
190 + 'timeout' => strtotime( $this->cache_timeout, current_time( 'timestamp' ) ),
191 + 'value' => json_encode( $addons ),
377 192 'version' => FrmAppHelper::plugin_version(),
378 193 );
379 194
380 - if ( is_multisite() ) {
381 - update_site_option( $this->cache_key, $data );
382 - } else {
383 - // Autoload the license cache because it gets called everywhere.
384 - $autoload = str_starts_with( $this->cache_key, 'frm_addons_l' );
385 - update_option( $this->cache_key, $data, $autoload );
386 - }
195 + update_option( $this->cache_key, $data, 'no' );
387 196 }
388 197
389 198 /**
390 - * Remove certain add-on API data that we don't need to cache.
391 - * This is to help keep the option data (which is auto-loaded) small.
392 - *
393 - * @since 6.28
394 - *
395 - * @param array $addons
396 - *
397 - * @return array
398 - */
399 - private function reduce_addon_data_before_caching( $addons ) {
400 - if ( is_subclass_of( $this, 'FrmFormApi' ) ) {
401 - // We only want to modify FrmFormApi. Leave the other APIs alone for now.
402 - return $addons;
403 - }
404 -
405 - $reduced_addons = array();
406 -
407 - foreach ( $addons as $key => $addon ) {
408 - if ( ! is_array( $addon ) ) {
409 - $reduced_addons[ $key ] = $addon;
410 - continue;
411 - }
412 -
413 - if ( ! $this->should_include_addon_in_cached_data( $addon ) ) {
414 - continue;
415 - }
416 -
417 - if ( isset( $addon['changelog'] ) ) {
418 - unset( $addon['changelog'], $addon['banners'] );
419 - }
420 -
421 - $reduced_addons[ $key ] = $addon;
422 - }
423 -
424 - return $reduced_addons;
425 - }
426 -
427 - /**
428 - * @since 6.28
429 - *
430 - * @param array $addon
431 - *
432 - * @return bool True if the add-on should be included in cached data.
433 - */
434 - private function should_include_addon_in_cached_data( $addon ) {
435 - if ( isset( $addon['version'] ) && '' === $addon['version'] ) {
436 - // If version is set but blank, the plugin is not actually live.
437 - return false;
438 - }
439 -
440 - if ( isset( $addon['categories'] ) ) {
441 - if ( isset( $addon['slug'] ) && 'views' === $addon['slug'] ) {
442 - // Legacy views has no categories set, but we should still
443 - // Include it in cache since it is a valid add-on.
444 - return true;
445 - }
446 -
447 - $categories_are_empty = ! $addon['categories'] || $addon['categories'] === array( 'Strategy11' );
448 -
449 - if ( $categories_are_empty ) {
450 - return false;
451 - }
452 - }
453 -
454 - return true;
455 - }
456 -
457 - /**
458 - * If the last check was a a rate limit, we'll need to check again sooner.
459 - *
460 - * @since 6.8.3
461 - *
462 - * @param array $addons
463 - *
464 - * @return string
465 - */
466 - protected function get_cache_timeout( $addons ) {
467 - if ( isset( $addons['response_code'] ) && 429 === $addons['response_code'] ) {
468 - return '+5 minutes';
469 - }
470 - return $this->cache_timeout;
471 - }
472 -
473 - /**
474 199 * @since 3.06
475 - *
476 - * @return void
477 200 */
478 201 public function reset_cached() {
479 - if ( is_multisite() ) {
480 - delete_site_option( $this->cache_key );
481 - } else {
482 - delete_option( $this->cache_key );
483 - }
484 - $this->done_running();
202 + delete_option( $this->cache_key );
485 203 }
486 204
487 205 /**
488 206 * @since 3.06
489 - *
490 207 * @return array
491 208 */
492 209 public function error_for_license() {
493 - return $this->license ? $this->get_error_from_response() : array();
210 + $errors = array();
211 + if ( ! empty( $this->license ) ) {
212 + $errors = $this->get_error_from_response();
213 + }
214 +
215 + return $errors;
494 216 }
495 217
496 218 /**
497 219 * @since 3.06
498 - *
499 - * @param array $addons
500 - *
501 220 * @return array
502 221 */
503 222 public function get_error_from_response( $addons = array() ) {
504 - if ( ! $addons ) {
223 + if ( empty( $addons ) ) {
505 224 $addons = $this->get_api_info();
506 225 }
507 -
508 226 $errors = array();
509 -
510 - if ( ! isset( $addons['error'] ) ) {
511 - return $errors;
512 - }
513 -
514 - if ( is_string( $addons['error'] ) ) {
515 - $errors[] = $addons['error'];
516 - } elseif ( ! empty( $addons['error']['message'] ) ) {
227 + if ( isset( $addons['error'] ) ) {
517 228 $errors[] = $addons['error']['message'];
229 + do_action( 'frm_license_error', $addons['error'] );
518 230 }
519 231
520 - do_action( 'frm_license_error', $addons['error'] );
521 -
522 232 return $errors;
523 - }
524 -
525 - /**
526 - * Check if a template is new.
527 - *
528 - * @since 6.0
529 - *
530 - * @param array $addon
531 - *
532 - * @return bool
533 - */
534 - protected function is_new( $addon ) {
535 - return strtotime( $addon['released'] ) > strtotime( '-' . $this->new_days . ' days' );
536 233 }
537 234 }