PluginProbe ʕ •ᴥ•ʔ
JetFormBuilder — Dynamic Blocks Form Builder / 3.3.4
JetFormBuilder — Dynamic Blocks Form Builder v3.3.4
3.6.3.1 3.6.3 3.6.2.2 3.6.2.1 3.6.2 3.6.1.1 3.6.1 3.6.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.10 2.1.11 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 3.0.0 3.0.0.1 3.0.0.2 3.0.0.3 3.0.1 3.0.1.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.0.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.3.2 3.3.3 3.3.3.1 3.3.4 3.3.4.1 3.3.4.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.5.1 3.4.5.2 3.4.6 3.4.7 3.4.7.1 3.5.0 3.5.1 3.5.1.1 3.5.1.2 3.5.2 3.5.2.1 3.5.3 3.5.4 3.5.5 3.5.6 3.5.6.1 3.5.6.2 3.5.6.3 3.6.0
jetformbuilder / includes / addons / manager.php
jetformbuilder / includes / addons Last commit date
manager.php 2 years ago
manager.php
700 lines
1 <?php
2 /**
3 * This class required to get actual JetFormBuilder addons list and changelog for these addons from account.jetformbuilder.com.
4 * The data retrieved from the account.jetformbuilder.com contains only information about addons and required to show Addons admin page.
5 * This class don't send any sensetive data from client website to account.jetformbuilder.com, just technical information required webservers to communicate between each other
6 * like IP or server URI, there is no user personal data send with this requests
7 */
8
9 namespace Jet_Form_Builder\Addons;
10
11 use Jet_Form_Builder\Classes\Tools;
12
13 // If this file is called directly, abort.
14 if ( ! defined( 'WPINC' ) ) {
15 die;
16 }
17
18 class Manager {
19
20 const NOT_ACTIVE = 'license-not-activated';
21 const NONCE_ACTION = 'jfb-addons-admin-page';
22
23 /**
24 * [$api_url description]
25 *
26 * @var string
27 */
28 public $api_url = 'https://account.jetformbuilder.com';
29
30 /**
31 * [$jet_changelog_url description]
32 *
33 * @var string
34 */
35 public $jet_changelog_url = 'https://account.jetformbuilder.com/wp-content/uploads/jet-changelog/%s.json';
36
37 /**
38 * [$user_plugins description]
39 *
40 * @var boolean
41 */
42 public $user_installed_plugins = false;
43
44 /**
45 * [$update_plugins description]
46 *
47 * @var boolean
48 */
49 public $update_plugins = false;
50
51 private $addons_info;
52
53 /**
54 * @param false $addon_filename
55 *
56 * @return string
57 */
58 public function get_addon_slug_by_filename( $addon_filename = false ) {
59 return explode( '/', $addon_filename )[0];
60 }
61
62 /**
63 * @return array
64 */
65 public function get_plugin_data_list() {
66
67 $jet_plugin_list = $this->get_jfb_remote_plugin_list();
68 $user_plugin_list = $this->get_user_plugins();
69
70 $plugins_list = array();
71
72 if ( ! empty( $jet_plugin_list ) ) {
73 foreach ( $jet_plugin_list as $key => $plugin_data ) {
74
75 $plugin_slug = $plugin_data['slug'];
76
77 if ( array_key_exists( $plugin_slug, $user_plugin_list ) ) {
78 $plugin_data = wp_parse_args( $plugin_data, $user_plugin_list[ $plugin_slug ] );
79 } else {
80 $plugin_data = wp_parse_args(
81 $plugin_data,
82 array(
83 'version' => $plugin_data['version'],
84 'currentVersion' => $plugin_data['version'],
85 'updateAvaliable' => false,
86 'isActivated' => false,
87 'isInstalled' => false,
88 )
89 );
90 }
91
92 $plugins_list[ $plugin_data['slug'] ] = $plugin_data;
93 }
94 }
95
96 return $plugins_list;
97 }
98
99 /**
100 * Remote request to updater API.
101 *
102 * @return array|bool
103 * @since 1.0.0
104 */
105 public function get_jfb_remote_plugin_list() {
106
107 if ( ! is_null( $this->addons_info ) ) {
108 return $this->addons_info;
109 }
110
111 $remote_jfb_addons_info = get_site_transient( 'jfb_remote_addons_list' );
112
113 if ( $remote_jfb_addons_info ) {
114 $this->addons_info = $remote_jfb_addons_info;
115
116 return $remote_jfb_addons_info;
117 }
118
119 $response = wp_remote_get(
120 $this->api_url . '/wp-json/croco/v1/plugins/',
121 array(
122 'timeout' => 30,
123 )
124 );
125
126 if ( is_wp_error( $response ) || 200 !== ( (int) wp_remote_retrieve_response_code( $response ) ) ) {
127 return array();
128 }
129
130 $response = json_decode( $response['body'], true );
131
132 if ( ! $response['success'] ) {
133 return array();
134 }
135
136 if ( ! isset( $response['plugins'] ) ) {
137 return array();
138 }
139
140 $jfb_remote_addons_list = $response['plugins'];
141
142 set_site_transient( 'jfb_remote_addons_list', $jfb_remote_addons_list, HOUR_IN_SECONDS * 24 );
143
144 return $jfb_remote_addons_list;
145 }
146
147 /**
148 * @param false $plugin_file
149 *
150 * @return false|mixed
151 */
152 public function get_jfb_remote_plugin_data( $plugin_file = false ) {
153
154 if ( ! $plugin_file ) {
155 return false;
156 }
157
158 $remote_plugin_list = $this->get_jfb_remote_plugin_list();
159
160 if ( $remote_plugin_list ) {
161 foreach ( $remote_plugin_list as $key => $plugin_data ) {
162 if ( $plugin_file === $plugin_data['slug'] ) {
163 return $plugin_data;
164 }
165 }
166 }
167
168 return false;
169 }
170
171 /**
172 * @return array[]|bool
173 */
174 public function get_user_installed_plugins() {
175
176 if ( ! $this->user_installed_plugins ) {
177
178 if ( ! function_exists( 'get_plugins' ) ) {
179 require_once ABSPATH . 'wp-admin/includes/plugin.php';
180 }
181
182 $this->user_installed_plugins = get_plugins();
183 }
184
185 return $this->user_installed_plugins;
186 }
187
188 /**
189 * [get_addon_data description]
190 *
191 * @return [type] [description]
192 */
193 public function get_user_plugins() {
194
195 $user_installed_plugins = $this->get_user_installed_plugins();
196
197 $plugin_list = array();
198
199 if ( $user_installed_plugins ) {
200
201 foreach ( $user_installed_plugins as $plugin_file => $plugin_data ) {
202
203 $current_version = $plugin_data['Version'];
204 $latest_version = $this->get_latest_version( $plugin_file );
205
206 $plugin_list[ $plugin_file ] = array(
207 'version' => $latest_version,
208 'currentVersion' => $current_version,
209 'updateAvaliable' => version_compare( $latest_version, $current_version, '>' ),
210 'isActivated' => is_plugin_active( $plugin_file ),
211 'isInstalled' => true,
212 );
213
214 }
215 }
216
217 return $plugin_list;
218 }
219
220 /**
221 * Get latest version for passed plugin
222 *
223 * @param [type] $remote_plugin_data [description]
224 *
225 * @return [type] [description]
226 */
227 public function get_latest_version( $plugin_file ) {
228
229 if ( ! $this->update_plugins ) {
230 $this->update_plugins = get_site_transient( 'update_plugins' );
231 }
232
233 $available_addons_data = $this->get_jfb_remote_plugin_list();
234
235 if ( ! empty( $available_addons_data ) && array_key_exists( $plugin_file, $this->user_installed_plugins ) ) {
236
237 foreach ( $available_addons_data as $key => $addon_info ) {
238
239 if ( $plugin_file === $addon_info['slug'] && version_compare( $this->user_installed_plugins[ $plugin_file ]['Version'], $addon_info['version'], '<' ) ) {
240 return $addon_info['version'];
241 }
242 }
243 }
244
245 $no_update = $this->update_plugins->no_update ?? false;
246 $to_update = $this->update_plugins->response ?? false;
247
248 if ( $to_update && array_key_exists( $plugin_file, $to_update ) ) {
249 return $to_update[ $plugin_file ]->new_version;
250 } elseif ( ! empty( $no_update ) && array_key_exists( $plugin_file, $no_update ) ) {
251 return $no_update[ $plugin_file ]->new_version;
252 } elseif ( array_key_exists( $plugin_file, $this->user_installed_plugins ) ) {
253 return $this->user_installed_plugins[ $plugin_file ]['Version'];
254 } else {
255 return '1.0.0';
256 }
257
258 return false;
259 }
260
261 /**
262 * @param $plugin_file
263 *
264 * @return array
265 */
266 public function get_addon_data( $plugin_file ) {
267
268 $user_installed_plugins = $this->get_user_installed_plugins();
269
270 if ( empty( $user_installed_plugins[ $plugin_file ] ) ) {
271 return false;
272 }
273
274 $plugin_data = $user_installed_plugins[ $plugin_file ];
275 $current_version = $plugin_data['Version'];
276 $latest_version = $this->get_latest_version( $plugin_file );
277
278 return array(
279 'version' => $latest_version,
280 'currentVersion' => $current_version,
281 'updateAvaliable' => version_compare( $latest_version, $current_version, '>' ),
282 'isActivated' => is_plugin_active( $plugin_file ),
283 'isInstalled' => true,
284 );
285 }
286
287 /**
288 * Plugin Action Handler
289 */
290 public function addon_activate_action() {
291
292 if ( ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ?? '' ), self::NONCE_ACTION ) ) {
293 wp_send_json(
294 array(
295 'success' => false,
296 'message' => __( 'The addon has been deactivated', 'jet-form-builder' ),
297 )
298 );
299 }
300
301 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
302 $data = ( ! empty( $_POST['data'] ) ) ? Tools::sanitize_recursive( $_POST['data'] ) : false;
303
304 if ( ! $data ) {
305 wp_send_json(
306 array(
307 'success' => false,
308 'message' => __( 'Server error. Please, try again later', 'jet-form-builder' ),
309 'data' => array(),
310 )
311 );
312 }
313
314 $plugin = $data['plugin'];
315
316 $this->activate_plugin( $plugin );
317
318 wp_send_json(
319 array(
320 'success' => true,
321 'message' => __( 'Success', 'jet-form-builder' ),
322 'data' => array(),
323 )
324 );
325 }
326
327 /**
328 * Plugin Action Handler
329 */
330 public function addon_deactivate_action() {
331
332 if ( ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ?? '' ), self::NONCE_ACTION ) ) {
333 wp_send_json(
334 array(
335 'success' => false,
336 'message' => __( 'The addon has been deactivated', 'jet-form-builder' ),
337 )
338 );
339 }
340
341 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
342 $data = ( ! empty( $_POST['data'] ) ) ? Tools::sanitize_recursive( $_POST['data'] ) : false;
343
344 if ( ! $data ) {
345 wp_send_json(
346 array(
347 'success' => false,
348 'message' => __( 'Server error. Please, try again later', 'jet-form-builder' ),
349 'data' => array(),
350 )
351 );
352 }
353
354 $plugin = $data['plugin'];
355
356 $this->deactivate_plugin( $plugin );
357
358 wp_send_json(
359 array(
360 'success' => true,
361 'message' => __( 'Success', 'jet-form-builder' ),
362 'data' => array(),
363 )
364 );
365 }
366
367 /**
368 * @param $plugin_file
369 */
370 public function activate_plugin( $plugin_file ) {
371
372 $status = array();
373
374 if ( ! current_user_can( 'activate_plugins' ) ) {
375 wp_send_json(
376 array(
377 'success' => false,
378 'message' => __( 'Sorry, you are not allowed to install plugins on this site.', 'jet-form-builder' ),
379 'data' => array(),
380 )
381 );
382 }
383
384 $activate = null;
385
386 if ( ! is_plugin_active( $plugin_file ) ) {
387 $activate = activate_plugin( $plugin_file );
388 }
389
390 if ( is_wp_error( $activate ) ) {
391 wp_send_json(
392 array(
393 'success' => false,
394 'message' => $activate->get_error_message(),
395 'data' => array(),
396 )
397 );
398 }
399
400 wp_send_json(
401 array(
402 'success' => true,
403 'message' => __( 'The addon has been activated', 'jet-form-builder' ),
404 'data' => $this->get_addon_data( $plugin_file ),
405 )
406 );
407 }
408
409 /**
410 * @param $plugin_file
411 */
412 public function deactivate_plugin( $plugin_file ) {
413
414 $status = array();
415
416 if ( ! current_user_can( 'activate_plugins' ) ) {
417 wp_send_json(
418 array(
419 'success' => false,
420 'message' => __( 'Sorry, you are not allowed to install plugins on this site.', 'jet-form-builder' ),
421 'data' => array(),
422 )
423 );
424 }
425
426 if ( is_plugin_active( $plugin_file ) ) {
427 deactivate_plugins( $plugin_file );
428 }
429
430 wp_send_json(
431 array(
432 'success' => true,
433 'message' => __( 'The addon has been deactivated', 'jet-form-builder' ),
434 'data' => $this->get_addon_data( $plugin_file ),
435 )
436 );
437 }
438
439 /**
440 * License service action
441 */
442 public function service_action() {
443
444 if ( ! wp_verify_nonce( sanitize_key( $_POST['nonce'] ?? '' ), self::NONCE_ACTION ) ) {
445 wp_send_json(
446 array(
447 'success' => false,
448 'message' => __( 'The addon has been deactivated', 'jet-form-builder' ),
449 )
450 );
451 }
452
453 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
454 $data = ( ! empty( $_POST['data'] ) ) ? Tools::sanitize_recursive( $_POST['data'] ) : false;
455
456 if ( ! $data || ! isset( $data['action'] ) ) {
457 wp_send_json(
458 array(
459 'success' => false,
460 'message' => __( 'Server error. Please, try again later', 'jet-form-builder' ),
461 'data' => array(),
462 )
463 );
464 }
465
466 $action = $data['action'];
467
468 switch ( $action ) {
469
470 case 'check-plugin-update':
471 wp_clean_update_cache();
472
473 wp_send_json(
474 array(
475 'success' => true,
476 'message' => __( 'Addons Update Checked', 'jet-form-builder' ),
477 'data' => array(),
478 )
479 );
480
481 break;
482
483 default:
484 wp_send_json(
485 array(
486 'success' => false,
487 'message' => __( 'Service action Not Found', 'jet-form-builder' ),
488 'data' => array(),
489 )
490 );
491 break;
492 }
493
494 exit;
495 }
496
497 /**
498 * @param $plugin_meta
499 * @param $plugin_file
500 * @param $plugin_data
501 *
502 * @return mixed
503 */
504 public function plugin_row_meta( $plugin_meta, $plugin_file, $plugin_data ) {
505
506 $available_addons_data = $this->get_jfb_remote_plugin_list();
507
508 $is_jfb_addon = false;
509 $plugin_data = false;
510
511 foreach ( $available_addons_data as $key => $addon_data ) {
512
513 if ( $plugin_file === $addon_data['slug'] ) {
514 $is_jfb_addon = true;
515 $plugin_data = $addon_data;
516 }
517 }
518
519 if ( $is_jfb_addon && empty( $plugin_data['update'] ) ) {
520
521 $plugin_slug = $this->get_addon_slug_by_filename( $plugin_data['slug'] );
522
523 $plugin_meta['view-details'] = sprintf(
524 '<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>',
525 esc_url_raw( network_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $plugin_slug . '&TB_iframe=true&width=600&height=550' ) ),
526 esc_attr(
527 /* translators: %s - plugin name */
528 sprintf( __( 'More information about %s', 'jet-form-builder' ), $plugin_data['name'] )
529 ),
530 esc_attr( $plugin_data['name'] ),
531 __( 'View details', 'jet-form-builder' )
532 );
533 }
534
535 return $plugin_meta;
536 }
537
538 /**
539 * @param $_data
540 * @param string $_action
541 * @param null $_args
542 *
543 * @return mixed
544 */
545 public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
546
547 if ( 'plugin_information' !== $_action ) {
548 return $_data;
549 }
550
551 if ( ! isset( $_args->slug ) ) {
552 return $_data;
553 }
554
555 $available_addons_data = $this->get_jfb_remote_plugin_list();
556 $user_installed_plugins = $this->get_user_installed_plugins();
557
558 $registered_plugin_data = false;
559
560 foreach ( $available_addons_data as $key => $addon_data ) {
561
562 $addon_slug = $this->get_addon_slug_by_filename( $addon_data['slug'] );
563
564 if ( $addon_slug === $_args->slug ) {
565 $registered_plugin_data = $addon_data;
566 $registered_plugin_data['plugin_slug'] = $addon_slug;
567 $registered_plugin_data['transient_key'] = $addon_slug . '_addon_info_data';
568 $registered_plugin_data['banners'] = array();
569
570 if ( ! empty( $user_installed_plugins[ $addon_data['slug'] ] ) ) {
571 $installed_plugin_data = $user_installed_plugins[ $addon_data['slug'] ];
572
573 $registered_plugin_data['author'] = $installed_plugin_data['Author'];
574 $registered_plugin_data['plugin_url'] = $installed_plugin_data['PluginURI'];
575 $registered_plugin_data['requires'] = $installed_plugin_data['RequiresWP'];
576 $registered_plugin_data['tested'] = $installed_plugin_data['RequiresPHP'];
577 }
578
579 break;
580 }
581 }
582
583 if ( ! $registered_plugin_data ) {
584 return $_data;
585 }
586
587 $addon_api_data = get_site_transient( $registered_plugin_data['transient_key'] );
588
589 if ( empty( $addon_api_data ) ) {
590 $changelog_remote_response = $this->changelog_remote_query( $registered_plugin_data['plugin_slug'] );
591
592 if ( ! $changelog_remote_response ) {
593 return $_data;
594 }
595
596 $plugin_api_data = new \stdClass();
597
598 $plugin_api_data->name = $registered_plugin_data['name'];
599 $plugin_api_data->slug = $registered_plugin_data['slug'];
600 $plugin_api_data->author = $registered_plugin_data['author'];
601 $plugin_api_data->homepage = $registered_plugin_data['plugin_url'];
602 $plugin_api_data->requires = $registered_plugin_data['requires'];
603 $plugin_api_data->tested = $registered_plugin_data['tested'];
604 $plugin_api_data->banners = $registered_plugin_data['banners'];
605 $plugin_api_data->version = $changelog_remote_response->current_version;
606 $plugin_api_data->sections = array(
607 'changelog' => $changelog_remote_response->changelog,
608 );
609
610 // Expires in 1 day
611 set_site_transient( $registered_plugin_data['transient_key'], $plugin_api_data, DAY_IN_SECONDS );
612 }
613
614 $_data = $addon_api_data;
615
616 return $_data;
617 }
618
619 /**
620 * @param $slug
621 *
622 * @return false|mixed
623 */
624 public function changelog_remote_query( $slug ) {
625
626 $response = wp_remote_get( sprintf( $this->jet_changelog_url, $slug ) );
627
628 if ( is_wp_error( $response ) || 200 !== ( (int) wp_remote_retrieve_response_code( $response ) ) ) {
629 return false;
630 }
631
632 return json_decode( $response['body'] );
633 }
634
635 /**
636 * [get_theme_info description]
637 *
638 * @return [type] [description]
639 */
640 public function get_theme_info() {
641 $style_parent_theme = wp_get_theme( get_template() );
642
643 return apply_filters(
644 'jfb-addons-page/theme-info',
645 array(
646 'name' => $style_parent_theme->get( 'Name' ),
647 'theme' => strtolower( preg_replace( '/\s+/', '', $style_parent_theme->get( 'Name' ) ) ),
648 'version' => $style_parent_theme->get( 'Version' ),
649 'author' => $style_parent_theme->get( 'Author' ),
650 'authorSlug' => strtolower( preg_replace( '/\s+/', '', $style_parent_theme->get( 'Author' ) ) ),
651 )
652 );
653 }
654
655 /**
656 * [allow_unsafe_urls description]
657 *
658 * @param [type] $args [description]
659 *
660 * @return [type] [description]
661 */
662 public function allow_unsafe_urls( $args ) {
663
664 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
665 if ( 'jfb_addon_action' === sanitize_key( $_REQUEST['action'] ?? '' ) ) {
666 $args['reject_unsafe_urls'] = false;
667 }
668
669 return $args;
670 }
671
672 public function is_active() {
673 return ! empty( get_option( 'jfb-license-data', false ) );
674 }
675
676 public function get_slug(): string {
677 return $this->is_active() ? 'jetformbuilder-license' : self::NOT_ACTIVE;
678 }
679
680 /**
681 * Manager constructor.
682 */
683 public function __construct() {
684
685 add_action( 'wp_ajax_jfb_license_service_action', array( $this, 'service_action' ) );
686
687 add_action( 'wp_ajax_jfb_addon_action', array( $this, 'plugin_action' ) );
688
689 add_action( 'wp_ajax_jfb_addon_activate_action', array( $this, 'addon_activate_action' ) );
690
691 add_action( 'wp_ajax_jfb_addon_deactivate_action', array( $this, 'addon_deactivate_action' ) );
692
693 add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 3 );
694
695 add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
696
697 add_filter( 'http_request_args', array( $this, 'allow_unsafe_urls' ) );
698 }
699 }
700