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 / FrmAddon.php

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

893 lines 25.1 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 6.15 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 $api = new FrmSalesApi();
335 $api->reset_cached();
336 }
337
338 /**
339 * The Pro version includes the show_license_message function.
340 * We need an extra check before we allow it to show a message.
341 *
342 * @since 3.04.03
343 */
344 public function maybe_show_license_message( $file, $plugin ) {
345 if ( $this->is_expired_addon || isset( $plugin['package'] ) ) {
346 // let's not show a ton of duplicate messages
347 return;
348 }
349
350 $this->show_license_message( $file, $plugin );
351 }
352
353 public function show_license_message( $file, $plugin ) {
354 $message = '';
355 if ( empty( $this->license ) ) {
356 /* translators: %1$s: Plugin name, %2$s: Start link HTML, %3$s: end link HTML */
357 $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>' );
358 } else {
359 $api = new FrmFormApi( $this->license );
360 $errors = $api->error_for_license();
361 if ( ! empty( $errors ) ) {
362 $message = reset( $errors );
363 }
364 }
365
366 if ( empty( $message ) ) {
367 return;
368 }
369
370 $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
371 $id = sanitize_title( $plugin['Name'] ) . '-next';
372
373 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>';
374 FrmAppHelper::kses_echo( $message, 'a' );
375 echo '<script type="text/javascript">var d = document.getElementById("' . esc_attr( $id ) . '").previousSibling;if ( d !== null ){ d.className = d.className + " update"; }</script>';
376 echo '</p></div></td></tr>';
377 }
378
379 public function clear_expired_download( $transient ) {
380 if ( ! is_object( $transient ) ) {
381 return $transient;
382 }
383
384 if ( $this->is_current_version( $transient ) ) {
385 // Make sure it doesn't show there is an update if plugin is up-to-date.
386 if ( isset( $transient->response[ $this->plugin_folder ] ) ) {
387 unset( $transient->response[ $this->plugin_folder ] );
388 }
389 } elseif ( isset( $transient->response ) && isset( $transient->response[ $this->plugin_folder ] ) ) {
390 $this->prepare_update_details( $transient->response[ $this->plugin_folder ] );
391
392 // if the transient has expired, clear the update and trigger it again
393 if ( $transient->response[ $this->plugin_folder ] === false ) {
394 if ( ! $this->has_been_cleared() ) {
395 $this->cleared_plugins();
396 $this->manually_queue_update();
397 }
398 unset( $transient->response[ $this->plugin_folder ] );
399 }
400 }
401
402 return $transient;
403 }
404
405 /**
406 * Check if the plugin information is correct to allow an update
407 *
408 * @since 3.04.03
409 *
410 * @param object $transient The current plugin info saved for update.
411 */
412 private function prepare_update_details( &$transient ) {
413 $version_info = $transient;
414 $has_beta_url = ! empty( $version_info->beta );
415 if ( $this->get_beta && ! $has_beta_url ) {
416 $version_info = (object) $this->get_api_info( $this->license );
417 }
418
419 if ( ! empty( $version_info->new_version ) ) {
420 $this->clear_old_plugin_version( $version_info );
421 if ( $version_info === false ) {
422 // Was cleared with timeout.
423 $transient = false;
424 } else {
425 $this->maybe_use_beta_url( $version_info );
426
427 if ( version_compare( $version_info->new_version, $this->version, '>' ) ) {
428 $transient = $version_info;
429 }
430 }
431 }
432 }
433
434 /**
435 * Get the API info for this plugin
436 *
437 * @since 3.04.03
438 */
439 protected function get_api_info( $license ) {
440 $api = new FrmFormApi( $license );
441 $addon = $api->get_addon_for_license( $this );
442
443 // if there is no download url, this license does not apply to the addon
444 if ( isset( $addon['package'] ) ) {
445 $this->is_parent_licence = true;
446 } elseif ( isset( $addon['error'] ) ) {
447 // if the license is expired, we must assume all add-ons were packaged
448 $this->is_parent_licence = true;
449 $this->is_expired_addon = true;
450 }
451
452 return $addon;
453 }
454
455 /**
456 * Make sure transients don't stick around on sites that
457 * don't save the transient expiration
458 *
459 * @since 2.05.05
460 */
461 private function clear_old_plugin_version( &$version_info ) {
462 $timeout = ! empty( $version_info->timeout ) ? $version_info->timeout : 0;
463 if ( ! empty( $timeout ) && time() > $timeout ) {
464 // Cache is expired.
465 $version_info = false;
466 $api = new FrmFormApi( $this->license );
467 $api->reset_cached();
468 }
469 }
470
471 /**
472 * The beta url is always included if the download has a beta.
473 * Check if the beta should be downloaded.
474 *
475 * @since 3.04.03
476 */
477 private function maybe_use_beta_url( &$version_info ) {
478 if ( $this->get_beta && ! empty( $version_info->beta ) ) {
479 $version_info->new_version = $version_info->beta['version'];
480 $version_info->package = $version_info->beta['package'];
481 if ( ! empty( $version_info->plugin ) ) {
482 $version_info->plugin = $version_info->beta['plugin'];
483 }
484 }
485 }
486
487 private function is_current_version( $transient ) {
488 if ( empty( $transient->checked ) || ! isset( $transient->checked[ $this->plugin_folder ] ) ) {
489 return false;
490 }
491
492 $response = empty( $transient->response );
493 if ( $response ) {
494 return true;
495 }
496
497 return isset( $transient->response ) && isset( $transient->response[ $this->plugin_folder ] ) && $transient->checked[ $this->plugin_folder ] === $transient->response[ $this->plugin_folder ]->new_version;
498 }
499
500 /**
501 * @return bool
502 */
503 private function has_been_cleared() {
504 $last_cleared = get_option( 'frm_last_cleared' );
505 return $last_cleared && $last_cleared > gmdate( 'Y-m-d H:i:s', strtotime( '-5 minutes' ) );
506 }
507
508 private function cleared_plugins() {
509 update_option( 'frm_last_cleared', gmdate( 'Y-m-d H:i:s' ) );
510 }
511
512 private function is_license_revoked() {
513 if ( empty( $this->license ) || empty( $this->plugin_slug ) || isset( $_POST['license'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
514 return;
515 }
516
517 if ( $this->get_defined_license() ) {
518 // Don't check if the license is defined in wp-config.php since we can't remove it.
519 return;
520 }
521
522 // Only check weekly.
523 if ( $this->checked_recently( '7 days', 'valid' ) || $this->is_running() ) {
524 return;
525 }
526
527 $response = $this->get_license_status();
528 if ( 'revoked' === $response['status'] || 'blocked' === $response['status'] || 'disabled' === $response['status'] || 'missing' === $response['status'] ) {
529 $this->clear_license();
530 }
531 }
532
533 /**
534 * Has this been checked too recently?
535 *
536 * @param string $time ie. '1 day'.
537 * @param string $required_status Return false if the last check does not match. ie 'valid'.
538 *
539 * @return bool
540 */
541 private function checked_recently( $time, $required_status = '' ) {
542 $last_checked = $this->last_checked();
543 $is_429 = isset( $last_checked['response_code'] ) && 429 === $last_checked['response_code'];
544 if ( $is_429 ) {
545 // If the last check was a a rate limit, we'll need to check again sooner.
546 $time = '5 minutes';
547 $required_status = '';
548 }
549
550 if ( $required_status && ( ! isset( $last_checked['status'] ) || $last_checked['status'] !== $required_status ) ) {
551 // If the last check was invalid, we don't need to check again.
552 return true;
553 }
554
555 $checked_time = isset( $last_checked['time'] ) ? $last_checked['time'] : false;
556 $time_ago = gmdate( 'Y-m-d H:i:s', strtotime( '-' . $time ) );
557 return $checked_time && $checked_time > $time_ago;
558 }
559
560 /**
561 * @since 6.8.3 Switched to an array to store extra response info.
562 *
563 * @return array
564 */
565 private function last_checked() {
566 if ( is_multisite() ) {
567 $last_checked = get_site_option( $this->transient_key() );
568 } else {
569 $last_checked = get_option( $this->transient_key() );
570 }
571 if ( $last_checked && ! is_array( $last_checked ) ) {
572 // Get string into array for existing values.
573 $last_checked = array( 'time' => $last_checked );
574 }
575 return $last_checked ? (array) $last_checked : array();
576 }
577
578 /**
579 * @return void
580 */
581 private function update_last_checked() {
582 $this->save_response['time'] = gmdate( 'Y-m-d H:i:s' );
583 if ( is_multisite() ) {
584 update_site_option( $this->transient_key(), $this->save_response );
585 } else {
586 update_option( $this->transient_key(), $this->save_response );
587 }
588 }
589
590 /**
591 * Use a new cache after the license is changed, or Formidable is updated.
592 */
593 private function transient_key() {
594 return 'frm_' . md5( sanitize_key( $this->license . '_' . $this->plugin_slug ) );
595 }
596
597 public static function activate() {
598 FrmAppHelper::permission_check( 'frm_change_settings' );
599 check_ajax_referer( 'frm_ajax', 'nonce' );
600
601 $license = stripslashes( FrmAppHelper::get_param( 'license', '', 'post', 'sanitize_text_field' ) );
602 if ( empty( $license ) ) {
603 wp_send_json(
604 array(
605 'message' => __( 'Oops! You forgot to enter your license number.', 'formidable' ),
606 'success' => false,
607 )
608 );
609 }
610
611 $plugin_slug = FrmAppHelper::get_param( 'plugin', '', 'post', 'sanitize_text_field' );
612 $response = self::activate_license_for_plugin( $license, $plugin_slug );
613
614 FrmInbox::clear_cache();
615
616 wp_send_json( $response );
617 }
618
619 /**
620 * @since 4.08
621 */
622 public static function activate_license_for_plugin( $license, $plugin_slug ) {
623 $this_plugin = self::get_addon( $plugin_slug );
624 return $this_plugin->activate_license( $license );
625 }
626
627 private function activate_license( $license ) {
628 $this->set_license( $license );
629 $this->license = $license;
630
631 $this->die_if_not_allowed();
632
633 $response = $this->get_license_status();
634 $response['message'] = '';
635 $response['success'] = false;
636
637 if ( $response['error'] ) {
638 $response['message'] = $response['status'];
639 } else {
640 $messages = $this->get_messages();
641 if ( is_string( $response['status'] ) && isset( $messages[ $response['status'] ] ) ) {
642 $response['message'] = $messages[ $response['status'] ];
643 } else {
644 $response['message'] = FrmAppHelper::kses( $response['status'], array( 'a' ) );
645 }
646
647 $is_valid = false;
648 if ( 'valid' === $response['status'] ) {
649 $is_valid = 'valid';
650 $response['success'] = true;
651 }
652 $this->maybe_set_active( $is_valid );
653 }
654
655 $this->update_last_checked();
656
657 return $response;
658 }
659
660 /**
661 * Prevent this check from happening more than once per minute with the same license.
662 *
663 * @return void
664 */
665 private function die_if_not_allowed() {
666 if ( ! $this->checked_recently( '2 minutes' ) ) {
667 return;
668 }
669
670 // Don't check more than once per minute.
671 wp_send_json(
672 array(
673 'message' => __( 'Please wait two minutes before trying again.', 'formidable' ),
674 'success' => false,
675 )
676 );
677 }
678
679 private function get_license_status() {
680 $this->set_running();
681
682 $response = array(
683 'status' => 'missing',
684 'error' => true,
685 );
686 if ( empty( $this->license ) ) {
687 $response['error'] = false;
688
689 return $response;
690 }
691
692 try {
693 $response['error'] = false;
694 $license_data = $this->send_mothership_request( 'activate_license' );
695
696 // $license_data->license will be either "valid" or "invalid"
697 if ( is_array( $license_data ) ) {
698 if ( ! empty( $license_data['license'] ) && in_array( $license_data['license'], array( 'valid', 'invalid' ), true ) ) {
699 $response['status'] = $license_data['license'];
700 $this->save_status['status'] = $license_data['license'];
701 }
702 } else {
703 $response['status'] = $license_data;
704 }
705 } catch ( Exception $e ) {
706 $response['status'] = $e->getMessage();
707 }
708
709 $this->update_last_checked();
710 $this->done_running();
711 return $response;
712 }
713
714 private function get_messages() {
715 return array(
716 'valid' => __( 'Your license has been activated. Enjoy!', 'formidable' ),
717 'invalid' => __( 'That license key is invalid', 'formidable' ),
718 'expired' => __( 'That license is expired', 'formidable' ),
719 'revoked' => __( 'That license has been refunded', 'formidable' ),
720 'no_activations_left' => __( 'That license has been used on too many sites', 'formidable' ),
721 'invalid_item_id' => __( 'Oops! That is the wrong license key for this plugin.', 'formidable' ),
722 'missing' => __( 'That license key is invalid', 'formidable' ),
723 );
724 }
725
726 /**
727 * @since 4.03
728 */
729 public static function reset_cache() {
730 FrmAppHelper::permission_check( 'frm_change_settings' );
731 check_ajax_referer( 'frm_ajax', 'nonce' );
732
733 $this_plugin = self::set_license_from_post();
734 $this_plugin->delete_cache();
735
736 $response = array(
737 'success' => true,
738 'message' => __( 'Cache cleared', 'formidable' ),
739 );
740
741 wp_send_json( $response );
742 }
743
744 public static function deactivate() {
745 FrmAppHelper::permission_check( 'frm_change_settings' );
746 check_ajax_referer( 'frm_ajax', 'nonce' );
747
748 $this_plugin = self::set_license_from_post();
749
750 $response = array(
751 'success' => false,
752 'message' => '',
753 );
754 try {
755 // $license_data->license will be either "deactivated" or "failed"
756 $license_data = $this_plugin->send_mothership_request( 'deactivate_license' );
757 if ( is_array( $license_data ) && 'deactivated' === $license_data['license'] ) {
758 $response['success'] = true;
759 $response['message'] = __( 'That license was removed successfully', 'formidable' );
760 } else {
761 $response['message'] = __( 'There was an error deactivating your license.', 'formidable' );
762 }
763 } catch ( Exception $e ) {
764 $response['message'] = $e->getMessage();
765 }
766
767 $this_plugin->clear_license();
768 FrmInbox::clear_cache();
769
770 wp_send_json( $response );
771 }
772
773 /**
774 * @since 4.03
775 */
776 private static function set_license_from_post() {
777 $plugin_slug = FrmAppHelper::get_param( 'plugin', '', 'post', 'sanitize_text_field' );
778 $this_plugin = self::get_addon( $plugin_slug );
779 $license = $this_plugin->get_license();
780 $this_plugin->license = $license;
781 return $this_plugin;
782 }
783
784 /**
785 * @return string
786 */
787 public function send_mothership_request( $action ) {
788 $api_params = array(
789 'edd_action' => $action,
790 'license' => $this->license,
791 'url' => home_url(),
792 );
793 if ( is_numeric( $this->download_id ) ) {
794 $api_params['item_id'] = absint( $this->download_id );
795 } else {
796 $api_params['item_name'] = rawurlencode( $this->plugin_name );
797 }
798
799 $arg_array = array(
800 'body' => $api_params,
801 'timeout' => 25,
802 'user-agent' => $this->plugin_slug . '/' . $this->version . '; ' . get_bloginfo( 'url' ),
803 );
804
805 $resp = wp_remote_post(
806 $this->store_url . '?l=' . urlencode( base64_encode( $this->license ) ),
807 $arg_array
808 );
809 $body = wp_remote_retrieve_body( $resp );
810 $this->save_status = array( 'response_code' => wp_remote_retrieve_response_code( $resp ) );
811
812 $message = __( 'Your License Key was invalid', 'formidable' );
813 if ( is_wp_error( $resp ) ) {
814 $link = FrmAppHelper::admin_upgrade_link( 'api', 'knowledgebase/why-cant-i-activate-formidable-pro/' );
815 /* translators: %1$s: Start link HTML, %2$s: End link HTML */
816 $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>' );
817 $message .= ' ' . $resp->get_error_message();
818 } elseif ( 'error' === $body || is_wp_error( $body ) ) {
819 $message = __( 'You had an HTTP error connecting to the Formidable API', 'formidable' );
820 } else {
821 $json_res = json_decode( $body, true );
822 if ( null !== $json_res ) {
823 if ( is_array( $json_res ) && isset( $json_res['error'] ) ) {
824 $message = $json_res['error'];
825 } else {
826 $message = $json_res;
827 }
828 } elseif ( ! empty( $resp['response'] ) && ! empty( $resp['response']['code'] ) ) {
829 $resp['body'] = wp_strip_all_tags( $resp['body'] );
830
831 $message = sprintf(
832 /* translators: %1$s: Error code, %2$s: Error message */
833 esc_html__( 'There was a %1$s error: %2$s', 'formidable' ),
834 esc_html( $resp['response']['code'] ),
835 $resp['response']['message'] . ' ' . $resp['body']
836 );
837 }
838 }//end if
839
840 return $message;
841 }
842
843 public function manually_queue_update() {
844 $updates = new stdClass();
845 $updates->last_checked = 0;
846 $updates->response = array();
847 $updates->translations = array();
848 $updates->no_update = array();
849 $updates->checked = array();
850 set_site_transient( 'update_plugins', $updates );
851 }
852
853 /**
854 * Set the transient key for the lock. It should be unique to the license.
855 *
856 * @since 6.8.3
857 *
858 * @return bool
859 */
860 protected function lock_key() {
861 return $this->transient_lock_key . '_' . $this->license;
862 }
863
864 /**
865 * Prevent multiple requests from running at the same time.
866 *
867 * @since 6.8.3
868 *
869 * @return bool
870 */
871 protected function is_running() {
872 return get_transient( $this->lock_key() );
873 }
874
875 /**
876 * @since 6.8.3
877 *
878 * @return void
879 */
880 protected function set_running() {
881 set_transient( $this->lock_key(), true, 2 * MINUTE_IN_SECONDS );
882 }
883
884 /**
885 * @since 6.8.3
886 *
887 * @return void
888 */
889 protected function done_running() {
890 delete_transient( $this->lock_key() );
891 }
892 }
893