PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.21
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.21
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
formidable / classes / models / FrmFormApi.php

FrmFormApi.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.21, at classes/models/FrmFormApi.php

421 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmFormApi {
7
8 /**
9 * @var string
10 */
11 protected $license = '';
12
13 /**
14 * @var string
15 */
16 protected $cache_key = '';
17
18 /**
19 * @var string
20 */
21 protected $cache_timeout = '+6 hours';
22
23 /**
24 * The number of days an add-on is new.
25 *
26 * @var int
27 */
28 protected $new_days = 90;
29
30 /**
31 * @since 3.06
32 */
33 public function __construct( $license = null ) {
34 $this->set_license( $license );
35 $this->set_cache_key();
36 }
37
38 /**
39 * @since 3.06
40 *
41 * @return void
42 */
43 private function set_license( $license ) {
44 if ( $license === null ) {
45 $edd_update = $this->get_pro_updater();
46 if ( ! empty( $edd_update ) ) {
47 $license = $edd_update->license;
48 }
49 }
50 $this->license = $license;
51 }
52
53 /**
54 * @since 3.06
55 * @return string
56 */
57 public function get_license() {
58 return $this->license;
59 }
60
61 /**
62 * @since 3.06
63 *
64 * @return void
65 */
66 protected function set_cache_key() {
67 $this->cache_key = 'frm_addons_l' . ( empty( $this->license ) ? '' : md5( $this->license ) );
68 }
69
70 /**
71 * @since 3.06
72 * @return string
73 */
74 public function get_cache_key() {
75 return $this->cache_key;
76 }
77
78 /**
79 * @since 3.06
80 * @return array
81 */
82 public function get_api_info() {
83 $url = $this->api_url();
84 if ( ! empty( $this->license ) ) {
85 $url .= '?l=' . urlencode( base64_encode( $this->license ) );
86 }
87
88 $addons = $this->get_cached();
89 if ( is_array( $addons ) ) {
90 return $addons;
91 }
92
93 if ( $this->is_running() ) {
94 // If there's no saved cache, we'll need to wait for the current request to finish.
95 return array();
96 }
97
98 $this->set_running();
99
100 // We need to know the version number to allow different downloads.
101 $agent = 'formidable/' . FrmAppHelper::plugin_version();
102 if ( class_exists( 'FrmProDb' ) ) {
103 $agent = 'formidable-pro/' . FrmProDb::$plug_version;
104 }
105
106 $response = wp_remote_get(
107 $url,
108 array(
109 'timeout' => 25,
110 'user-agent' => $agent . '; ' . get_bloginfo( 'url' ),
111 )
112 );
113
114 if ( is_array( $response ) && ! is_wp_error( $response ) ) {
115 $addons = $response['body'] ? json_decode( $response['body'], true ) : array();
116 }
117
118 if ( ! is_array( $addons ) ) {
119 $addons = array();
120 }
121
122 $addons['response_code'] = wp_remote_retrieve_response_code( $response );
123
124 foreach ( $addons as $k => $addon ) {
125 if ( ! is_array( $addon ) ) {
126 continue;
127 }
128
129 if ( isset( $addon['categories'] ) ) {
130 $cats = array_intersect( $this->skip_categories(), $addon['categories'] );
131 if ( ! empty( $cats ) ) {
132 unset( $addons[ $k ] );
133 continue;
134 }
135 }
136
137 if ( ! array_key_exists( 'is_new', $addon ) && array_key_exists( 'released', $addon ) ) {
138 $addons[ $k ]['is_new'] = $this->is_new( $addon );
139 }
140 }
141
142 $this->set_cached( $addons );
143 $this->done_running();
144
145 return $addons;
146 }
147
148 /**
149 * Prevent multiple requests from running at the same time.
150 *
151 * @since 6.8.3
152 *
153 * @return bool
154 */
155 protected function is_running() {
156 if ( $this->run_as_multisite() ) {
157 return get_site_transient( $this->transient_key() );
158 }
159 return get_transient( $this->transient_key() );
160 }
161
162 /**
163 * @since 6.8.3
164 *
165 * @return void
166 */
167 protected function set_running() {
168 $expires = 2 * MINUTE_IN_SECONDS;
169 if ( $this->run_as_multisite() ) {
170 set_site_transient( $this->transient_key(), true, $expires );
171 return;
172 }
173
174 set_transient( $this->transient_key(), true, $expires );
175 }
176
177 /**
178 * @since 6.8.3
179 *
180 * @return void
181 */
182 protected function done_running() {
183 if ( $this->run_as_multisite() ) {
184 delete_site_transient( $this->transient_key() );
185 }
186 delete_transient( $this->transient_key() );
187 }
188
189 /**
190 * Only allow one site in the network to make the api request at a time.
191 * If there is a license for the request, run individually.
192 *
193 * @since 6.8.3
194 *
195 * @return bool
196 */
197 protected function run_as_multisite() {
198 return is_multisite() && empty( $this->license );
199 }
200
201 /**
202 * @since 6.8.3
203 *
204 * @return string
205 */
206 protected function transient_key() {
207 return strtolower( __CLASS__ ) . '_request_lock';
208 }
209
210 /**
211 * @since 3.06
212 *
213 * @return string
214 */
215 protected function api_url() {
216 if ( empty( $this->license ) ) {
217 // Direct traffic to Cloudflare worker when there is no license.
218 return 'https://plapi.formidableforms.com/list/';
219 }
220 return 'https://formidableforms.com/wp-json/s11edd/v1/updates/';
221 }
222
223 /**
224 * @since 3.06
225 *
226 * @return string[]
227 */
228 protected function skip_categories() {
229 return array( 'WordPress Form Templates', 'WordPress Form Style Templates' );
230 }
231
232 /**
233 * @since 3.06
234 *
235 * @param object $license_plugin The FrmAddon object.
236 * @param array $addons
237 *
238 * @return array
239 */
240 public function get_addon_for_license( $license_plugin, $addons = array() ) {
241 if ( empty( $addons ) ) {
242 $addons = $this->get_api_info();
243 }
244 $download_id = $license_plugin->download_id;
245 $plugin = array();
246 if ( empty( $download_id ) && ! empty( $addons ) ) {
247 foreach ( $addons as $addon ) {
248 if ( is_array( $addon ) && ! empty( $addon['title'] ) && strtolower( $license_plugin->plugin_name ) === strtolower( $addon['title'] ) ) {
249 return $addon;
250 }
251 }
252 } elseif ( isset( $addons[ $download_id ] ) ) {
253 $plugin = $addons[ $download_id ];
254 }
255
256 return $plugin;
257 }
258
259 /**
260 * @since 3.06
261 */
262 public function get_pro_updater() {
263 if ( FrmAppHelper::pro_is_installed() && is_callable( 'FrmProAppHelper::get_updater' ) ) {
264 $updater = FrmProAppHelper::get_updater();
265 $this->set_license( $updater->license );
266
267 return $updater;
268 }
269
270 return false;
271 }
272
273 /**
274 * @since 3.06
275 *
276 * @return array|bool
277 */
278 protected function get_cached() {
279 $cache = $this->get_cached_option();
280 if ( empty( $cache ) ) {
281 return false;
282 }
283
284 // If the api call is running, we can use the expired cache.
285 if ( ! $this->is_running() ) {
286 if ( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
287 // Cache is expired.
288 return false;
289 }
290
291 $version = FrmAppHelper::plugin_version();
292 $for_current = isset( $cache['version'] ) && $cache['version'] == $version;
293 if ( ! $for_current ) {
294 // Force a new check.
295 return false;
296 }
297 }
298
299 $values = json_decode( $cache['value'], true );
300
301 return $values;
302 }
303
304 /**
305 * Get the cache for the network if multisite.
306 *
307 * @since 6.8.3
308 *
309 * @return mixed
310 */
311 protected function get_cached_option() {
312 if ( is_multisite() ) {
313 $cached = get_site_option( $this->cache_key );
314 if ( $cached ) {
315 return $cached;
316 }
317 }
318
319 return get_option( $this->cache_key );
320 }
321
322 /**
323 * @since 3.06
324 *
325 * @param array $addons
326 *
327 * @return void
328 */
329 protected function set_cached( $addons ) {
330 $data = array(
331 'timeout' => strtotime( $this->get_cache_timeout( $addons ), time() ),
332 'value' => wp_json_encode( $addons ),
333 'version' => FrmAppHelper::plugin_version(),
334 );
335
336 if ( is_multisite() ) {
337 update_site_option( $this->cache_key, $data );
338 } else {
339 update_option( $this->cache_key, $data, 'no' );
340 }
341 }
342
343 /**
344 * If the last check was a a rate limit, we'll need to check again sooner.
345 *
346 * @since 6.8.3
347 *
348 * @param array $addons
349 *
350 * @return string
351 */
352 protected function get_cache_timeout( $addons ) {
353 $timeout = $this->cache_timeout;
354 if ( isset( $addons['response_code'] ) && 429 === $addons['response_code'] ) {
355 $timeout = '+5 minutes';
356 }
357 return $timeout;
358 }
359
360 /**
361 * @since 3.06
362 *
363 * @return void
364 */
365 public function reset_cached() {
366 if ( is_multisite() ) {
367 delete_site_option( $this->cache_key );
368 } else {
369 delete_option( $this->cache_key );
370 }
371 $this->done_running();
372 }
373
374 /**
375 * @since 3.06
376 * @return array
377 */
378 public function error_for_license() {
379 $errors = array();
380 if ( ! empty( $this->license ) ) {
381 $errors = $this->get_error_from_response();
382 }
383
384 return $errors;
385 }
386
387 /**
388 * @since 3.06
389 * @return array
390 */
391 public function get_error_from_response( $addons = array() ) {
392 if ( empty( $addons ) ) {
393 $addons = $this->get_api_info();
394 }
395 $errors = array();
396 if ( isset( $addons['error'] ) ) {
397 if ( is_string( $addons['error'] ) ) {
398 $errors[] = $addons['error'];
399 } elseif ( ! empty( $addons['error']['message'] ) ) {
400 $errors[] = $addons['error']['message'];
401 }
402
403 do_action( 'frm_license_error', $addons['error'] );
404 }
405
406 return $errors;
407 }
408
409 /**
410 * Check if a template is new.
411 *
412 * @since 6.0
413 *
414 * @param array $addon
415 * @return bool
416 */
417 protected function is_new( $addon ) {
418 return strtotime( $addon['released'] ) > strtotime( '-' . $this->new_days . ' days' );
419 }
420 }
421