PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.12
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.12
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 / FrmAddon.php

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

887 lines 25.0 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 /** @phpstan-consistent-constructor */
7 class FrmAddon {
8 public $store_url = 'https://formidableforms.com';
9 public $download_id;
10 public $plugin_file;
11 public $plugin_folder;
12 public $plugin_name;
13 public $plugin_slug;
14 public $option_name;
15 public $version;
16 public $author = 'Strategy11';
17 public $is_parent_licence = false;
18 public $needs_license = true;
19 private $is_expired_addon = false;
20 public $license;
21 protected $get_beta = false;
22 protected $save_status;
23
24 /**
25 * This is used to decide whether the license checks should continue.
26 * The point is to avoid license issues when a site url changes.
27 *
28 * @since 6.8.3
29 *
30 * @var array
31 */
32 private $save_response = array();
33
34 /**
35 * This is used to flag other add ons not to send a request.
36 * We only want to send a single API request per page load.
37 *
38 * @since 6.8.3
39 *
40 * @var string
41 */
42 private $transient_lock_key = 'frm_activate_request_lock';
43
44 /**
45 * @since 6.8.3
46 *
47 * @var bool
48 */
49 protected $should_clear_cache = true;
50
51 public function __construct() {
52
53 if ( empty( $this->plugin_slug ) ) {
54 $this->plugin_slug = preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $this->plugin_name ) ) );
55 }
56 if ( empty( $this->option_name ) ) {
57 $this->option_name = 'edd_' . $this->plugin_slug . '_license_';
58 }
59
60 $this->plugin_folder = plugin_basename( $this->plugin_file );
61 $this->license = $this->get_license();
62
63 add_filter( 'frm_installed_addons', array( &$this, 'insert_installed_addon' ) );
64 $this->edd_plugin_updater();
65 }
66
67 public static function load_hooks() {
68 add_filter( 'frm_include_addon_page', '__return_true' );
69 new static();
70 }
71
72 public function insert_installed_addon( $plugins ) {
73 $plugins[ $this->plugin_slug ] = $this;
74
75 return $plugins;
76 }
77
78 public static function get_addon( $plugin_slug ) {
79 $plugins = apply_filters( 'frm_installed_addons', array() );
80 $plugin = false;
81 if ( isset( $plugins[ $plugin_slug ] ) ) {
82 $plugin = $plugins[ $plugin_slug ];
83 }
84
85 return $plugin;
86 }
87
88 public function edd_plugin_updater() {
89
90 $this->is_license_revoked();
91 $license = $this->license;
92
93 add_action( 'after_plugin_row_' . plugin_basename( $this->plugin_file ), array( $this, 'maybe_show_license_message' ), 10, 2 );
94
95 if ( ! empty( $license ) ) {
96
97 if ( 'formidable/formidable.php' !== $this->plugin_folder ) {
98 add_filter( 'plugins_api', array( &$this, 'plugins_api_filter' ), 10, 3 );
99 }
100
101 add_filter( 'site_transient_update_plugins', array( &$this, 'clear_expired_download' ) );
102 }
103 }
104
105 /**
106 * Updates information on the "View version x.x details" page with custom data.
107 *
108 * @uses api_request()
109 *
110 * @param mixed $_data
111 * @param string $_action
112 * @param object $_args
113 *
114 * @return object $_data
115 */
116 public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
117
118 if ( $_action != 'plugin_information' ) {
119 return $_data;
120 }
121
122 $slug = basename( $this->plugin_file, '.php' );
123 $slug2 = str_replace( '/' . $slug . '.php', '', $this->plugin_folder );
124 if ( empty( $_args->slug ) || ( $_args->slug != $slug && $_args->slug !== $slug2 ) ) {
125 return $_data;
126 }
127
128 $item_id = $this->download_id;
129 if ( empty( $item_id ) ) {
130 $_data = array(
131 'name' => $this->plugin_name,
132 'excerpt' => '',
133 'changelog' => 'See the full changelog at <a href="' . esc_url( $this->store_url . '/changelog/' ) . '"></a>',
134 'banners' => array(
135 'high' => '',
136 'low' => 'https://ps.w.org/formidable/assets/banner-1544x500.png',
137 ),
138 );
139 } else {
140 $api = new FrmFormApi( $this->license );
141 $plugins = $api->get_api_info();
142 $_data = $plugins[ $item_id ];
143 }
144
145 $_data['sections'] = array(
146 'description' => $_data['excerpt'],
147 'changelog' => $_data['changelog'],
148 );
149 $_data['author'] = '<a href="' . esc_url( $this->store_url ) . '">' . esc_html( $this->author ) . '</a>';
150 $_data['homepage'] = $this->store_url;
151
152 return (object) $_data;
153 }
154
155 public function get_license() {
156 $license = $this->maybe_get_pro_license();
157 if ( ! empty( $license ) ) {
158 return $license;
159 }
160
161 $license = trim( get_option( $this->option_name . 'key' ) );
162 if ( empty( $license ) ) {
163 $license = $this->activate_defined_license();
164 }
165
166 return $license;
167 }
168
169 /**
170 * @since 3.04.03
171 */
172 protected function maybe_get_pro_license() {
173 // prevent a loop if $this is the pro plugin
174 $get_license = FrmAppHelper::pro_is_installed() && is_callable( 'FrmProAppHelper::get_updater' ) && $this->plugin_name != 'Formidable Pro';
175
176 if ( ! $get_license ) {
177 return false;
178 }
179
180 $api = new FrmFormApi();
181 $api->get_pro_updater();
182 $license = $api->get_license();
183 if ( empty( $license ) ) {
184 return false;
185 }
186
187 $this->get_api_info( $license );
188 if ( ! $this->is_parent_licence ) {
189 $license = false;
190 }
191
192 return $license;
193 }
194
195 /**
196 * Activate the license in wp-config.php
197 *
198 * @since 2.04
199 */
200 public function activate_defined_license() {
201 $license = $this->get_defined_license();
202 if ( ! empty( $license ) && ! $this->is_active() && ! $this->checked_recently( '1 day' ) ) {
203 $response = $this->activate_license( $license );
204 if ( ! $response['success'] ) {
205 $license = '';
206 }
207 }
208
209 return $license;
210 }
211
212 /**
213 * Check the wp-config.php for the license key
214 *
215 * @since 2.04
216 */
217 public function get_defined_license() {
218 $consant_name = 'FRM_' . strtoupper( $this->plugin_slug ) . '_LICENSE';
219
220 return defined( $consant_name ) ? constant( $consant_name ) : false;
221 }
222
223 public function set_license( $license ) {
224 update_option( $this->option_name . 'key', $license );
225 }
226
227 public function is_active() {
228 return get_option( $this->option_name . 'active' );
229 }
230
231 /**
232 * @since 3.04.03
233 *
234 * @param array|string $error
235 */
236 public function maybe_clear_license( $error ) {
237 if ( is_array( $error ) && $error['code'] === 'disabled' && $error['license'] === $this->license ) {
238 $this->clear_license();
239 }
240 }
241
242 public function clear_license() {
243 delete_option( $this->option_name . 'active' );
244 delete_option( $this->option_name . 'key' );
245
246 if ( $this->should_clear_cache ) {
247 delete_site_option( $this->transient_key() );
248 delete_option( $this->transient_key() );
249 $this->delete_cache();
250 $this->should_clear_cache = true;
251 }
252 }
253
254 /**
255 * Don't save an invalid license.
256 *
257 * @since 6.8.3
258 *
259 * @param bool $is_valid If license activation was successful.
260 *
261 * @return void
262 */
263 protected function maybe_set_active( $is_valid ) {
264 update_option( $this->option_name . 'active', $is_valid );
265 if ( $is_valid ) {
266 $this->set_active( $is_valid );
267 return;
268 }
269
270 // Don't save the license if it's invalid.
271 $this->should_clear_cache = false;
272 $this->clear_license();
273 delete_option( $this->option_name . 'key' );
274 $this->license = '';
275 }
276
277 public function set_active( $is_active ) {
278 $this->delete_cache();
279 FrmAppHelper::save_combined_js();
280 $this->update_pro_capabilities();
281 }
282
283 /**
284 * Updates roles capabilities after pro license is active.
285 *
286 * @since 5.0
287 */
288 protected function update_pro_capabilities() {
289 global $wp_roles;
290
291 if ( ! function_exists( 'get_editable_roles' ) ) {
292 require_once ABSPATH . 'wp-admin/includes/user.php';
293 }
294
295 $caps = FrmAppHelper::frm_capabilities( 'pro_only' );
296 $roles = get_editable_roles();
297 $settings = new FrmSettings();
298 foreach ( $caps as $cap => $cap_desc ) {
299 $cap_roles = (array) ( isset( $settings->$cap ) ? $settings->$cap : 'administrator' );
300
301 // Make sure administrators always have permissions.
302 if ( ! in_array( 'administrator', $cap_roles, true ) ) {
303 array_push( $cap_roles, 'administrator' );
304 }
305
306 foreach ( $roles as $role => $details ) {
307 if ( in_array( $role, $cap_roles ) ) {
308 $wp_roles->add_cap( $role, $cap );
309 } else {
310 $wp_roles->remove_cap( $role, $cap );
311 }
312 }
313 }
314 }
315
316 /**
317 * @since 3.04.03
318 */
319 protected function delete_cache() {
320 delete_transient( 'frm_api_licence' );
321
322 // Cleanup option that has been removed.
323 delete_option( $this->option_name . 'last_activate' );
324
325 $api = new FrmFormApi( $this->license );
326 $api->reset_cached();
327
328 $api = new FrmFormTemplateApi( $this->license );
329 $api->reset_cached();
330
331 $api = new FrmApplicationApi( $this->license );
332 $api->reset_cached();
333 }
334
335 /**
336 * The Pro version includes the show_license_message function.
337 * We need an extra check before we allow it to show a message.
338 *
339 * @since 3.04.03
340 */
341 public function maybe_show_license_message( $file, $plugin ) {
342 if ( $this->is_expired_addon || isset( $plugin['package'] ) ) {
343 // let's not show a ton of duplicate messages
344 return;
345 }
346
347 $this->show_license_message( $file, $plugin );
348 }
349
350 public function show_license_message( $file, $plugin ) {
351 $message = '';
352 if ( empty( $this->license ) ) {
353 /* translators: %1$s: Plugin name, %2$s: Start link HTML, %3$s: end link HTML */
354 $message = sprintf( esc_html__( 'Your %1$s license key is missing. Please add it on the %2$slicenses page%3$s.', 'formidable' ), esc_html( $this->plugin_name ), '<a href="' . esc_url( admin_url( 'admin.php?page=formidable-settings' ) ) . '">', '</a>' );
355 } else {
356 $api = new FrmFormApi( $this->license );
357 $errors = $api->error_for_license();
358 if ( ! empty( $errors ) ) {
359 $message = reset( $errors );
360 }
361 }
362
363 if ( empty( $message ) ) {
364 return;
365 }
366
367 $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
368 $id = sanitize_title( $plugin['Name'] ) . '-next';
369
370 echo '<tr class="plugin-update-tr active" id="' . esc_attr( $id ) . '"><td colspan="' . esc_attr( $wp_list_table->get_column_count() ) . '" class="plugin-update colspanchange"><div class="update-message notice error inline notice-error notice-alt"><p>';
371 echo FrmAppHelper::kses( $message, 'a' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
372 echo '<script type="text/javascript">var d = document.getElementById("' . esc_attr( $id ) . '").previousSibling;if ( d !== null ){ d.className = d.className + " update"; }</script>';
373 echo '</p></div></td></tr>';
374 }
375
376 public function clear_expired_download( $transient ) {
377 if ( ! is_object( $transient ) ) {
378 return $transient;
379 }
380
381 if ( $this->is_current_version( $transient ) ) {
382 // Make sure it doesn't show there is an update if plugin is up-to-date.
383 if ( isset( $transient->response[ $this->plugin_folder ] ) ) {
384 unset( $transient->response[ $this->plugin_folder ] );
385 }
386 } elseif ( isset( $transient->response ) && isset( $transient->response[ $this->plugin_folder ] ) ) {
387 $this->prepare_update_details( $transient->response[ $this->plugin_folder ] );
388
389 // if the transient has expired, clear the update and trigger it again
390 if ( $transient->response[ $this->plugin_folder ] === false ) {
391 if ( ! $this->has_been_cleared() ) {
392 $this->cleared_plugins();
393 $this->manually_queue_update();
394 }
395 unset( $transient->response[ $this->plugin_folder ] );
396 }
397 }
398
399 return $transient;
400 }
401
402 /**
403 * Check if the plugin information is correct to allow an update
404 *
405 * @since 3.04.03
406 *
407 * @param object $transient The current plugin info saved for update.
408 */
409 private function prepare_update_details( &$transient ) {
410 $version_info = $transient;
411 $has_beta_url = ! empty( $version_info->beta );
412 if ( $this->get_beta && ! $has_beta_url ) {
413 $version_info = (object) $this->get_api_info( $this->license );
414 }
415
416 if ( ! empty( $version_info->new_version ) ) {
417 $this->clear_old_plugin_version( $version_info );
418 if ( $version_info === false ) {
419 // Was cleared with timeout.
420 $transient = false;
421 } else {
422 $this->maybe_use_beta_url( $version_info );
423
424 if ( version_compare( $version_info->new_version, $this->version, '>' ) ) {
425 $transient = $version_info;
426 }
427 }
428 }
429 }
430
431 /**
432 * Get the API info for this plugin
433 *
434 * @since 3.04.03
435 */
436 protected function get_api_info( $license ) {
437 $api = new FrmFormApi( $license );
438 $addon = $api->get_addon_for_license( $this );
439
440 // if there is no download url, this license does not apply to the addon
441 if ( isset( $addon['package'] ) ) {
442 $this->is_parent_licence = true;
443 } elseif ( isset( $addon['error'] ) ) {
444 // if the license is expired, we must assume all add-ons were packaged
445 $this->is_parent_licence = true;
446 $this->is_expired_addon = true;
447 }
448
449 return $addon;
450 }
451
452 /**
453 * Make sure transients don't stick around on sites that
454 * don't save the transient expiration
455 *
456 * @since 2.05.05
457 */
458 private function clear_old_plugin_version( &$version_info ) {
459 $timeout = ! empty( $version_info->timeout ) ? $version_info->timeout : 0;
460 if ( ! empty( $timeout ) && time() > $timeout ) {
461 // Cache is expired.
462 $version_info = false;
463 $api = new FrmFormApi( $this->license );
464 $api->reset_cached();
465 }
466 }
467
468 /**
469 * The beta url is always included if the download has a beta.
470 * Check if the beta should be downloaded.
471 *
472 * @since 3.04.03
473 */
474 private function maybe_use_beta_url( &$version_info ) {
475 if ( $this->get_beta && ! empty( $version_info->beta ) ) {
476 $version_info->new_version = $version_info->beta['version'];
477 $version_info->package = $version_info->beta['package'];
478 if ( ! empty( $version_info->plugin ) ) {
479 $version_info->plugin = $version_info->beta['plugin'];
480 }
481 }
482 }
483
484 private function is_current_version( $transient ) {
485 if ( empty( $transient->checked ) || ! isset( $transient->checked[ $this->plugin_folder ] ) ) {
486 return false;
487 }
488
489 $response = empty( $transient->response );
490 if ( $response ) {
491 return true;
492 }
493
494 return isset( $transient->response ) && isset( $transient->response[ $this->plugin_folder ] ) && $transient->checked[ $this->plugin_folder ] === $transient->response[ $this->plugin_folder ]->new_version;
495 }
496
497 /**
498 * @return bool
499 */
500 private function has_been_cleared() {
501 $last_cleared = get_option( 'frm_last_cleared' );
502 return $last_cleared && $last_cleared > gmdate( 'Y-m-d H:i:s', strtotime( '-5 minutes' ) );
503 }
504
505 private function cleared_plugins() {
506 update_option( 'frm_last_cleared', gmdate( 'Y-m-d H:i:s' ) );
507 }
508
509 private function is_license_revoked() {
510 if ( empty( $this->license ) || empty( $this->plugin_slug ) || isset( $_POST['license'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
511 return;
512 }
513
514 if ( $this->get_defined_license() ) {
515 // Don't check if the license is defined in wp-config.php since we can't remove it.
516 return;
517 }
518
519 // Only check weekly.
520 if ( $this->checked_recently( '7 days', 'valid' ) || $this->is_running() ) {
521 return;
522 }
523
524 $response = $this->get_license_status();
525 if ( 'revoked' === $response['status'] || 'blocked' === $response['status'] || 'disabled' === $response['status'] || 'missing' === $response['status'] ) {
526 $this->clear_license();
527 }
528 }
529
530 /**
531 * Has this been checked too recently?
532 *
533 * @param string $time ie. '1 day'.
534 * @param string $required_status Return false if the last check does not match. ie 'valid'.
535 *
536 * @return bool
537 */
538 private function checked_recently( $time, $required_status = '' ) {
539 $last_checked = $this->last_checked();
540 $is_429 = isset( $last_checked['response_code'] ) && 429 === $last_checked['response_code'];
541 if ( $is_429 ) {
542 // If the last check was a a rate limit, we'll need to check again sooner.
543 $time = '5 minutes';
544 $required_status = '';
545 }
546
547 if ( $required_status && ( ! isset( $last_checked['status'] ) || $last_checked['status'] !== $required_status ) ) {
548 // If the last check was invalid, we don't need to check again.
549 return true;
550 }
551
552 $checked_time = isset( $last_checked['time'] ) ? $last_checked['time'] : false;
553 $time_ago = gmdate( 'Y-m-d H:i:s', strtotime( '-' . $time ) );
554 return $checked_time && $checked_time > $time_ago;
555 }
556
557 /**
558 * @since 6.8.3 Switched to an array to store extra response info.
559 *
560 * @return array
561 */
562 private function last_checked() {
563 if ( is_multisite() ) {
564 $last_checked = get_site_option( $this->transient_key() );
565 } else {
566 $last_checked = get_option( $this->transient_key() );
567 }
568 if ( $last_checked && ! is_array( $last_checked ) ) {
569 // Get string into array for existing values.
570 $last_checked = array( 'time' => $last_checked );
571 }
572 return $last_checked ? (array) $last_checked : array();
573 }
574
575 /**
576 * @return void
577 */
578 private function update_last_checked() {
579 $this->save_response['time'] = gmdate( 'Y-m-d H:i:s' );
580 if ( is_multisite() ) {
581 update_site_option( $this->transient_key(), $this->save_response );
582 } else {
583 update_option( $this->transient_key(), $this->save_response );
584 }
585 }
586
587 /**
588 * Use a new cache after the license is changed, or Formidable is updated.
589 */
590 private function transient_key() {
591 return 'frm_' . md5( sanitize_key( $this->license . '_' . $this->plugin_slug ) );
592 }
593
594 public static function activate() {
595 FrmAppHelper::permission_check( 'frm_change_settings' );
596 check_ajax_referer( 'frm_ajax', 'nonce' );
597
598 $license = stripslashes( FrmAppHelper::get_param( 'license', '', 'post', 'sanitize_text_field' ) );
599 if ( empty( $license ) ) {
600 wp_send_json(
601 array(
602 'message' => __( 'Oops! You forgot to enter your license number.', 'formidable' ),
603 'success' => false,
604 )
605 );
606 }
607
608 $plugin_slug = FrmAppHelper::get_param( 'plugin', '', 'post', 'sanitize_text_field' );
609 $response = self::activate_license_for_plugin( $license, $plugin_slug );
610
611 wp_send_json( $response );
612 }
613
614 /**
615 * @since 4.08
616 */
617 public static function activate_license_for_plugin( $license, $plugin_slug ) {
618 $this_plugin = self::get_addon( $plugin_slug );
619 return $this_plugin->activate_license( $license );
620 }
621
622 private function activate_license( $license ) {
623 $this->set_license( $license );
624 $this->license = $license;
625
626 $this->die_if_not_allowed();
627
628 $response = $this->get_license_status();
629 $response['message'] = '';
630 $response['success'] = false;
631
632 if ( $response['error'] ) {
633 $response['message'] = $response['status'];
634 } else {
635 $messages = $this->get_messages();
636 if ( is_string( $response['status'] ) && isset( $messages[ $response['status'] ] ) ) {
637 $response['message'] = $messages[ $response['status'] ];
638 } else {
639 $response['message'] = FrmAppHelper::kses( $response['status'], array( 'a' ) );
640 }
641
642 $is_valid = false;
643 if ( 'valid' === $response['status'] ) {
644 $is_valid = 'valid';
645 $response['success'] = true;
646 }
647 $this->maybe_set_active( $is_valid );
648 }
649
650 $this->update_last_checked();
651
652 return $response;
653 }
654
655 /**
656 * Prevent this check from happening more than once per minute with the same license.
657 *
658 * @return void
659 */
660 private function die_if_not_allowed() {
661 if ( ! $this->checked_recently( '2 minutes' ) ) {
662 return;
663 }
664
665 // Don't check more than once per minute.
666 wp_send_json(
667 array(
668 'message' => __( 'Please wait two minutes before trying again.', 'formidable' ),
669 'success' => false,
670 )
671 );
672 }
673
674 private function get_license_status() {
675 $this->set_running();
676
677 $response = array(
678 'status' => 'missing',
679 'error' => true,
680 );
681 if ( empty( $this->license ) ) {
682 $response['error'] = false;
683
684 return $response;
685 }
686
687 try {
688 $response['error'] = false;
689 $license_data = $this->send_mothership_request( 'activate_license' );
690
691 // $license_data->license will be either "valid" or "invalid"
692 if ( is_array( $license_data ) ) {
693 if ( ! empty( $license_data['license'] ) && in_array( $license_data['license'], array( 'valid', 'invalid' ), true ) ) {
694 $response['status'] = $license_data['license'];
695 $this->save_status['status'] = $license_data['license'];
696 }
697 } else {
698 $response['status'] = $license_data;
699 }
700 } catch ( Exception $e ) {
701 $response['status'] = $e->getMessage();
702 }
703
704 $this->update_last_checked();
705 $this->done_running();
706 return $response;
707 }
708
709 private function get_messages() {
710 return array(
711 'valid' => __( 'Your license has been activated. Enjoy!', 'formidable' ),
712 'invalid' => __( 'That license key is invalid', 'formidable' ),
713 'expired' => __( 'That license is expired', 'formidable' ),
714 'revoked' => __( 'That license has been refunded', 'formidable' ),
715 'no_activations_left' => __( 'That license has been used on too many sites', 'formidable' ),
716 'invalid_item_id' => __( 'Oops! That is the wrong license key for this plugin.', 'formidable' ),
717 'missing' => __( 'That license key is invalid', 'formidable' ),
718 );
719 }
720
721 /**
722 * @since 4.03
723 */
724 public static function reset_cache() {
725 FrmAppHelper::permission_check( 'frm_change_settings' );
726 check_ajax_referer( 'frm_ajax', 'nonce' );
727
728 $this_plugin = self::set_license_from_post();
729 $this_plugin->delete_cache();
730
731 $response = array(
732 'success' => true,
733 'message' => __( 'Cache cleared', 'formidable' ),
734 );
735
736 wp_send_json( $response );
737 }
738
739 public static function deactivate() {
740 FrmAppHelper::permission_check( 'frm_change_settings' );
741 check_ajax_referer( 'frm_ajax', 'nonce' );
742
743 $this_plugin = self::set_license_from_post();
744
745 $response = array(
746 'success' => false,
747 'message' => '',
748 );
749 try {
750 // $license_data->license will be either "deactivated" or "failed"
751 $license_data = $this_plugin->send_mothership_request( 'deactivate_license' );
752 if ( is_array( $license_data ) && 'deactivated' === $license_data['license'] ) {
753 $response['success'] = true;
754 $response['message'] = __( 'That license was removed successfully', 'formidable' );
755 } else {
756 $response['message'] = __( 'There was an error deactivating your license.', 'formidable' );
757 }
758 } catch ( Exception $e ) {
759 $response['message'] = $e->getMessage();
760 }
761
762 $this_plugin->clear_license();
763
764 wp_send_json( $response );
765 }
766
767 /**
768 * @since 4.03
769 */
770 private static function set_license_from_post() {
771 $plugin_slug = FrmAppHelper::get_param( 'plugin', '', 'post', 'sanitize_text_field' );
772 $this_plugin = self::get_addon( $plugin_slug );
773 $license = $this_plugin->get_license();
774 $this_plugin->license = $license;
775 return $this_plugin;
776 }
777
778 /**
779 * @return string
780 */
781 public function send_mothership_request( $action ) {
782 $api_params = array(
783 'edd_action' => $action,
784 'license' => $this->license,
785 'url' => home_url(),
786 );
787 if ( is_numeric( $this->download_id ) ) {
788 $api_params['item_id'] = absint( $this->download_id );
789 } else {
790 $api_params['item_name'] = rawurlencode( $this->plugin_name );
791 }
792
793 $arg_array = array(
794 'body' => $api_params,
795 'timeout' => 25,
796 'user-agent' => $this->plugin_slug . '/' . $this->version . '; ' . get_bloginfo( 'url' ),
797 );
798
799 $resp = wp_remote_post(
800 $this->store_url . '?l=' . urlencode( base64_encode( $this->license ) ),
801 $arg_array
802 );
803 $body = wp_remote_retrieve_body( $resp );
804 $this->save_status = array( 'response_code' => wp_remote_retrieve_response_code( $resp ) );
805
806 $message = __( 'Your License Key was invalid', 'formidable' );
807 if ( is_wp_error( $resp ) ) {
808 $link = FrmAppHelper::admin_upgrade_link( 'api', 'knowledgebase/why-cant-i-activate-formidable-pro/' );
809 /* translators: %1$s: Start link HTML, %2$s: End link HTML */
810 $message = sprintf( __( 'You had an error communicating with the Formidable API. %1$sClick here%2$s for more information.', 'formidable' ), '<a href="' . esc_url( $link ) . '" target="_blank">', '</a>' );
811 $message .= ' ' . $resp->get_error_message();
812 } elseif ( 'error' === $body || is_wp_error( $body ) ) {
813 $message = __( 'You had an HTTP error connecting to the Formidable API', 'formidable' );
814 } else {
815 $json_res = json_decode( $body, true );
816 if ( null !== $json_res ) {
817 if ( is_array( $json_res ) && isset( $json_res['error'] ) ) {
818 $message = $json_res['error'];
819 } else {
820 $message = $json_res;
821 }
822 } elseif ( ! empty( $resp['response'] ) && ! empty( $resp['response']['code'] ) ) {
823 $resp['body'] = wp_strip_all_tags( $resp['body'] );
824
825 $message = sprintf(
826 /* translators: %1$s: Error code, %2$s: Error message */
827 esc_html__( 'There was a %1$s error: %2$s', 'formidable' ),
828 esc_html( $resp['response']['code'] ),
829 $resp['response']['message'] . ' ' . $resp['body']
830 );
831 }
832 }//end if
833
834 return $message;
835 }
836
837 public function manually_queue_update() {
838 $updates = new stdClass();
839 $updates->last_checked = 0;
840 $updates->response = array();
841 $updates->translations = array();
842 $updates->no_update = array();
843 $updates->checked = array();
844 set_site_transient( 'update_plugins', $updates );
845 }
846
847 /**
848 * Set the transient key for the lock. It should be unique to the license.
849 *
850 * @since 6.8.3
851 *
852 * @return bool
853 */
854 protected function lock_key() {
855 return $this->transient_lock_key . '_' . $this->license;
856 }
857
858 /**
859 * Prevent multiple requests from running at the same time.
860 *
861 * @since 6.8.3
862 *
863 * @return bool
864 */
865 protected function is_running() {
866 return get_transient( $this->lock_key() );
867 }
868
869 /**
870 * @since 6.8.3
871 *
872 * @return void
873 */
874 protected function set_running() {
875 set_transient( $this->lock_key(), true, 2 * MINUTE_IN_SECONDS );
876 }
877
878 /**
879 * @since 6.8.3
880 *
881 * @return void
882 */
883 protected function done_running() {
884 delete_transient( $this->lock_key() );
885 }
886 }
887