Completed
Push — master ( a1f0e2...210fe1 )
by Stephanie
27s queued 10s
created

FrmAddonsController::get_pro_updater()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	die( 'You are not allowed to call this page directly.' );
4
}
5
6
class FrmAddonsController {
7
8
	public static function menu() {
9
		if ( ! current_user_can( 'activate_plugins' ) ) {
10
			return;
11
		}
12
13
		$label = __( 'Add-Ons', 'formidable' );
14
		if ( FrmAppHelper::pro_is_installed() ) {
15
			$label = '<span style="color:#fe5a1d">' . $label . '</span>';
16
		}
17
		add_submenu_page( 'formidable', 'Formidable | ' . __( 'Add-Ons', 'formidable' ), $label, 'frm_view_forms', 'formidable-addons', 'FrmAddonsController::list_addons' );
18
19
		if ( ! FrmAppHelper::pro_is_installed() ) {
20
			add_submenu_page(
21
				'formidable',
22
				'Formidable | ' . __( 'Upgrade', 'formidable' ),
23
				'<span style="color:#fe5a1d">' . __( 'Upgrade', 'formidable' ) . '</span>',
24
				'frm_view_forms',
25
				'formidable-pro-upgrade',
26
				'FrmAddonsController::upgrade_to_pro'
27
			);
28
		} elseif ( 'formidable-pro-upgrade' === FrmAppHelper::get_param( 'page' ) ) {
29
			wp_safe_redirect( admin_url( 'admin.php?page=formidable' ) );
30
			exit;
31
		}
32
	}
33
34
	public static function list_addons() {
35
		FrmAppHelper::include_svg();
36
		$installed_addons = apply_filters( 'frm_installed_addons', array() );
37
		$license_type     = '';
38
39
		$addons = self::get_api_addons();
40
		$errors = array();
41
42
		if ( isset( $addons['error'] ) ) {
43
			$api    = new FrmFormApi();
44
			$errors = $api->get_error_from_response( $addons );
45
			$license_type = isset( $addons['error']['type'] ) ? $addons['error']['type'] : '';
46
			unset( $addons['error'] );
47
		}
48
		self::prepare_addons( $addons );
49
50
		$pricing = FrmAppHelper::admin_upgrade_link( 'addons' );
51
52
		include( FrmAppHelper::plugin_path() . '/classes/views/addons/list.php' );
53
	}
54
55
	public static function license_settings() {
56
		$plugins = apply_filters( 'frm_installed_addons', array() );
57
		if ( empty( $plugins ) ) {
58
			esc_html_e( 'There are no plugins on your site that require a license', 'formidable' );
59
60
			return;
61
		}
62
63
		ksort( $plugins );
64
65
		include( FrmAppHelper::plugin_path() . '/classes/views/addons/settings.php' );
66
	}
67
68
	protected static function get_api_addons() {
69
		$api    = new FrmFormApi();
70
		$addons = $api->get_api_info();
71
72
		if ( empty( $addons ) ) {
73
			$addons = self::fallback_plugin_list();
74
		} else {
75
			foreach ( $addons as $k => $addon ) {
76
				if ( empty( $addon['excerpt'] ) && $k !== 'error' ) {
77
					unset( $addons[ $k ] );
78
				}
79
			}
80
		}
81
82
		return $addons;
83
	}
84
85
	/**
86
	 * If the API is unable to connect, show something on the addons page
87
	 *
88
	 * @since 3.04.03
89
	 * @return array
90
	 */
91
	protected static function fallback_plugin_list() {
92
		$list = array(
93
			'formidable-pro' => array(
94
				'title'   => 'Formidable Forms',
95
				'link'    => 'pricing/',
96
				'docs'    => '',
97
				'excerpt' => 'Enhance your basic Formidable forms with a plethora of Pro field types and features. Create advanced forms and data-driven applications in minutes.',
98
			),
99
			'mailchimp'      => array(
100
				'title'   => 'MailChimp Forms',
101
				'excerpt' => 'Get on the path to more sales and leads in a matter of minutes. Add leads to a MailChimp mailing list when they submit forms and update their information along with the entry.',
102
			),
103
			'registration'   => array(
104
				'title'   => 'User Registration Forms',
105
				'link'    => 'downloads/user-registration/',
106
				'excerpt' => 'Give new users access to your site as quickly and painlessly as possible. Allow users to register, edit and be able to login to their profiles on your site from the front end in a clean, customized registration form.',
107
			),
108
			'paypal'         => array(
109
				'title'   => 'PayPal Standard Forms',
110
				'link'    => 'downloads/paypal-standard/',
111
				'excerpt' => 'Automate your business by collecting instant payments from your clients. Collect information, calculate a total, and send them on to PayPal. Require a payment before publishing content on your site.',
112
			),
113
			'stripe'         => array(
114
				'title'   => 'Stripe Forms',
115
				'docs'    => 'knowledgebase/stripe/',
116
				'excerpt' => 'Any Formidable forms on your site can accept credit card payments without users ever leaving your site.',
117
			),
118
			'authorize-net'  => array(
119
				'title'   => 'Authorize.net AIM Forms',
120
				'link'    => 'downloads/authorize-net-aim/',
121
				'docs'    => 'knowledgebase/authorize-net-aim/',
122
				'excerpt' => 'Accept one-time payments directly on your site, using Authorize.net AIM.',
123
			),
124
			'woocommerce'    => array(
125
				'title'   => 'WooCommerce Forms',
126
				'excerpt' => 'Use a Formidable form on your WooCommerce product pages.',
127
			),
128
			'autoresponder'  => array(
129
				'title'   => 'Form Action Automation',
130
				'docs'    => 'knowledgebase/schedule-autoresponder/',
131
				'excerpt' => 'Schedule email notifications, SMS messages, and API actions.',
132
			),
133
			'modal'          => array(
134
				'title'   => 'Bootstrap Modal Forms',
135
				'link'    => 'downloads/bootstrap-modal/',
136
				'docs'    => 'knowledgebase/bootstrap-modal/',
137
				'excerpt' => 'Open a view or form in a Bootstrap popup.',
138
			),
139
			'bootstrap'      => array(
140
				'title'   => 'Bootstrap Style Forms',
141
				'excerpt' => 'Instantly add Bootstrap styling to all your Formidable forms.',
142
			),
143
			'zapier'         => array(
144
				'title'   => 'Zapier Forms',
145
				'excerpt' => 'Connect with hundreds of different applications through Zapier. Insert a new row in a Google docs spreadsheet, post on Twitter, or add a new Dropbox file with your form.',
146
			),
147
			'signature'      => array(
148
				'title'   => 'Digital Signature Forms',
149
				'excerpt' => 'Add a signature field to your form. The user may write their signature with a trackpad/mouse or just type it.',
150
			),
151
			'api'            => array(
152
				'title'   => 'Formidable Forms API',
153
				'link'    => 'downloads/formidable-api/',
154
				'excerpt' => 'Send entry results to any other site that has a Rest API. This includes the option of sending entries from one Formidable site to another.',
155
			),
156
			'twilio'         => array(
157
				'title'   => 'Twilio SMS Forms',
158
				'docs'    => 'knowledgebase/twilio-add-on/',
159
				'excerpt' => 'Allow users to text their votes for polls created by Formidable Forms, or send SMS notifications when entries are submitted or updated.',
160
			),
161
			'views'          => array(
162
				'title'   => 'Formidable Views',
163
				'excerpt' => 'Add the power of views to your Formidable Forms to display your form submissions in listings, tables, calendars, and more.',
164
			),
165
		);
166
167
		$defaults = array(
168
			'released' => '',
169
		);
170
171
		foreach ( $list as $k => $info ) {
172
			$info['slug'] = $k;
173
			$list[ $k ]   = array_merge( $defaults, $info );
174
		}
175
		return $list;
176
	}
177
178
	/**
179
	 * If Pro is missing but has been authenticated, include a download URL
180
	 *
181
	 * @since 3.04.03
182
	 * @return string
183
	 */
184
	public static function get_pro_download_url() {
185
		$license   = self::get_pro_license();
186
		$api       = new FrmFormApi( $license );
187
		$downloads = $api->get_api_info();
188
		$pro       = self::get_pro_from_addons( $downloads );
189
190
		return isset( $pro['url'] ) ? $pro['url'] : '';
191
	}
192
193
	/**
194
	 * @since 4.08
195
	 */
196
	public static function get_pro_license() {
197
		$pro_cred_store = 'frmpro-credentials';
198
		$pro_wpmu_store = 'frmpro-wpmu-sitewide';
199
		if ( is_multisite() && get_site_option( $pro_wpmu_store ) ) {
200
			$creds = get_site_option( $pro_cred_store );
201
		} else {
202
			$creds = get_option( $pro_cred_store );
203
		}
204
205
		if ( empty( $creds ) || ! is_array( $creds ) || ! isset( $creds['license'] ) ) {
206
			return '';
207
		}
208
209
		$license = $creds['license'];
210
		if ( empty( $license ) ) {
211
			return '';
212
		}
213
214
		if ( strpos( $license, '-' ) ) {
215
			// this is a fix for licenses saved in the past
216
			$license = strtoupper( $license );
217
		}
218
		return $license;
219
	}
220
221
	/**
222
	 * @since 4.08
223
	 */
224
	protected static function get_pro_from_addons( $addons ) {
225
		return isset( $addons['93790'] ) ? $addons['93790'] : array();
226
	}
227
228
	/**
229
	 * @since 4.06
230
	 */
231
	public static function license_type() {
232
		if ( is_callable( 'FrmProAddonsController::license_type' ) ) {
233
			return FrmProAddonsController::license_type();
234
		}
235
236
		return 'free';
237
	}
238
239
	/**
240
	 * @since 4.0.01
241
	 */
242
	public static function is_license_expired() {
243
		if ( is_callable( 'FrmProAddonsController::is_license_expired' ) ) {
244
			return FrmProAddonsController::is_license_expired();
245
		}
246
247
		$version_info = self::get_primary_license_info();
248
		if ( ! isset( $version_info['error'] ) ) {
249
			return false;
250
		}
251
252
		return $version_info['error'];
253
	}
254
255
	/**
256
	 * @since 4.08
257
	 *
258
	 * @return boolean|int false or the number of days until expiration.
259
	 */
260
	public static function is_license_expiring() {
261
		if ( is_callable( 'FrmProAddonsController::is_license_expiring' ) ) {
262
			return FrmProAddonsController::is_license_expiring();
263
		}
264
265
		return false;
266
	}
267
268
	/**
269
	 * @since 4.08
270
	 */
271
	protected static function get_primary_license_info() {
272
		if ( is_callable( 'FrmProAddonsController::get_primary_license_info' ) ) {
273
			return FrmProAddonsController::get_primary_license_info();
274
		}
275
276
		$installed_addons = apply_filters( 'frm_installed_addons', array() );
277
		if ( empty( $installed_addons ) || ! isset( $installed_addons['formidable_pro'] ) ) {
278
			return false;
279
		}
280
		$installed_addons = array(
281
			'formidable_pro' => $installed_addons['formidable_pro'],
282
		);
283
284
		return self::fill_update_addon_info( $installed_addons );
285
	}
286
287
	/**
288
	 * @since 3.04.03
289
	 */
290
	public static function check_update( $transient ) {
291
		if ( ! FrmAppHelper::pro_is_installed() ) {
292
			// Don't make any changes if only Lite is installed.
293
			return $transient;
294
		}
295
296
		if ( is_callable( 'FrmProAddonsController::check_update' ) ) {
297
			return FrmProAddonsController::check_update( $transient );
298
		}
299
300
		if ( ! is_object( $transient ) ) {
301
			$transient = new stdClass();
302
		}
303
304
		$installed_addons = apply_filters( 'frm_installed_addons', array() );
305
		if ( empty( $installed_addons ) ) {
306
			return $transient;
307
		}
308
309
		$version_info = self::fill_update_addon_info( $installed_addons );
310
311
		$transient->last_checked = time();
312
313
		if ( ! function_exists( 'get_plugins' ) ) {
314
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
315
		}
316
		$wp_plugins = get_plugins();
317
318
		foreach ( $version_info as $id => $plugin ) {
319
			$plugin = (object) $plugin;
320
321
			if ( ! isset( $plugin->new_version ) || ! isset( $plugin->package ) ) {
322
				continue;
323
			}
324
325
			$folder = $plugin->plugin;
326
			if ( empty( $folder ) ) {
327
				continue;
328
			}
329
330
			if ( ! self::is_installed( $folder ) ) {
331
				// don't show an update if the plugin isn't installed
332
				continue;
333
			}
334
335
			$wp_plugin  = isset( $wp_plugins[ $folder ] ) ? $wp_plugins[ $folder ] : array();
336
			$wp_version = isset( $wp_plugin['Version'] ) ? $wp_plugin['Version'] : '1.0';
337
338
			if ( version_compare( $wp_version, $plugin->new_version, '<' ) ) {
339
				$slug                           = explode( '/', $folder );
340
				$plugin->slug                   = $slug[0];
341
				$transient->response[ $folder ] = $plugin;
342
			}
343
344
			$transient->checked[ $folder ] = $wp_version;
345
346
		}
347
348
		return $transient;
349
	}
350
351
	/**
352
	 * Check if a plugin is installed before showing an update for it
353
	 *
354
	 * @since 3.05
355
	 *
356
	 * @param string $plugin - the folder/filename.php for a plugin
357
	 *
358
	 * @return bool - True if installed
359
	 */
360
	protected static function is_installed( $plugin ) {
361
		if ( ! function_exists( 'get_plugins' ) ) {
362
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
363
		}
364
365
		$all_plugins = get_plugins();
366
367
		return isset( $all_plugins[ $plugin ] );
368
	}
369
370
	/**
371
	 * @since 3.04.03
372
	 *
373
	 * @param array $installed_addons
374
	 *
375
	 * @return array
376
	 */
377
	protected static function fill_update_addon_info( $installed_addons ) {
378
		$checked_licenses = array();
379
		$version_info     = array();
380
381
		foreach ( $installed_addons as $addon ) {
382
			if ( $addon->store_url !== 'https://formidableforms.com' ) {
383
				// check if this is a third-party addon
384
				continue;
385
			}
386
387
			$new_license = $addon->license;
388
			if ( empty( $new_license ) || in_array( $new_license, $checked_licenses ) ) {
389
				continue;
390
			}
391
392
			$checked_licenses[] = $new_license;
393
394
			$api = new FrmFormApi( $new_license );
395
			if ( empty( $version_info ) ) {
396
				$version_info = $api->get_api_info();
397
				continue;
398
			}
399
400
			$plugin = $api->get_addon_for_license( $addon, $version_info );
401
			if ( empty( $plugin ) ) {
402
				continue;
403
			}
404
405
			$download_id = isset( $plugin['id'] ) ? $plugin['id'] : 0;
406
			if ( ! empty( $download_id ) && ! isset( $version_info[ $download_id ]['package'] ) ) {
407
				// if this addon is using its own license, get the update url
408
				$addon_info = $api->get_api_info();
409
410
				$version_info[ $download_id ] = $addon_info[ $download_id ];
411
				if ( isset( $addon_info['error'] ) ) {
412
					$version_info[ $download_id ]['error'] = array(
413
						'message' => $addon_info['error']['message'],
414
						'code'    => $addon_info['error']['code'],
415
					);
416
				}
417
			}
418
		}
419
420
		return $version_info;
421
	}
422
423
	/**
424
	 * Get the action link for an addon that isn't active.
425
	 *
426
	 * @since 3.06.03
427
	 * @param string $plugin The plugin slug
428
	 * @return array
429
	 */
430
	public static function install_link( $plugin ) {
431
		$link  = array();
432
		$addon = self::get_addon( $plugin );
433
434
		if ( $addon ) {
435
			if ( $addon['status']['type'] === 'installed' && ! empty( $addon['activate_url'] ) ) {
436
				$link = array(
437
					'url'   => $addon['plugin'],
438
					'class' => 'frm-activate-addon',
439
				);
440
			} elseif ( isset( $addon['url'] ) && ! empty( $addon['url'] ) ) {
441
				$link = array(
442
					'url'   => $addon['url'],
443
					'class' => 'frm-install-addon',
444
				);
445
			} elseif ( isset( $addon['categories'] ) && ! empty( $addon['categories'] ) ) {
446
				$link = array(
447
					'categories' => $addon['categories'],
448
				);
449
			}
450
451
			if ( ! empty( $link ) ) {
452
				$link['status'] = $addon['status']['type'];
453
			}
454
		}
455
456
		return $link;
457
	}
458
459
	/**
460
	 * @since 4.09
461
	 * @param string $plugin The plugin slug
462
	 * @return array|false
463
	 */
464
	protected static function get_addon( $plugin ) {
465
		$addons = self::get_api_addons();
466
		self::prepare_addons( $addons );
467
		foreach ( $addons as $addon ) {
468
			$slug = explode( '/', $addon['plugin'] );
469
			if ( $slug[0] === 'formidable-' . $plugin ) {
470
				return $addon;
471
			}
472
		}
473
		return false;
474
	}
475
476
	/**
477
	 * @since 4.09
478
	 * @return string
479
	 */
480
	protected static function get_license_type() {
481
		$license_type = '';
482
		$addons       = self::get_api_addons();
483
		if ( isset( $addons['error'] ) && isset( $addons['error']['type'] ) ) {
484
			$license_type = $addons['error']['type'];
485
		}
486
		return $license_type;
487
	}
488
489
	/**
490
	 * @since 3.04.03
491
	 *
492
	 * @param array $addons
493
	 * @param object $license The FrmAddon object
494
	 *
495
	 * @return array
496
	 */
497
	public static function get_addon_for_license( $addons, $license ) {
498
		$download_id = $license->download_id;
499
		$plugin      = array();
500 View Code Duplication
		if ( empty( $download_id ) && ! empty( $addons ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
501
			foreach ( $addons as $addon ) {
502
				if ( strtolower( $license->plugin_name ) == strtolower( $addon['title'] ) ) {
503
					return $addon;
504
				}
505
			}
506
		} elseif ( isset( $addons[ $download_id ] ) ) {
507
			$plugin = $addons[ $download_id ];
508
		}
509
510
		return $plugin;
511
	}
512
513
	protected static function prepare_addons( &$addons ) {
514
		$activate_url = '';
515
		if ( current_user_can( 'activate_plugins' ) ) {
516
			$activate_url = add_query_arg( array( 'action' => 'activate' ), admin_url( 'plugins.php' ) );
517
		}
518
519
		$loop_addons = $addons;
520
		foreach ( $loop_addons as $id => $addon ) {
521
			if ( is_numeric( $id ) ) {
522
				$slug      = str_replace( array( '-wordpress-plugin', '-wordpress' ), '', $addon['slug'] );
523
				$file_name = $addon['plugin'];
524
			} else {
525
				$slug = $id;
526
				if ( isset( $addon['file'] ) ) {
527
					$base_file = $addon['file'];
528
				} else {
529
					$base_file = 'formidable-' . $slug;
530
				}
531
				$file_name = $base_file . '/' . $base_file . '.php';
532
				if ( ! isset( $addon['plugin'] ) ) {
533
					$addon['plugin'] = $file_name;
534
				}
535
			}
536
537
			$addon['installed']    = self::is_installed( $file_name );
538
			$addon['activate_url'] = '';
539
540
			if ( $addon['installed'] && ! empty( $activate_url ) && ! is_plugin_active( $file_name ) ) {
541
				$addon['activate_url'] = add_query_arg(
542
					array(
543
						'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $file_name ),
544
						'plugin'   => $file_name,
545
					),
546
					$activate_url
547
				);
548
			}
549
550
			if ( ! isset( $addon['docs'] ) ) {
551
				$addon['docs'] = 'knowledgebase/formidable-' . $slug . '/';
552
			}
553
			self::prepare_addon_link( $addon['docs'] );
554
555
			if ( ! isset( $addon['link'] ) ) {
556
				$addon['link'] = 'downloads/' . $slug . '/';
557
			}
558
			self::prepare_addon_link( $addon['link'] );
559
560
			self::set_addon_status( $addon );
561
			$addons[ $id ] = $addon;
562
		}
563
	}
564
565
	/**
566
	 * @since 3.04.02
567
	 */
568
	protected static function prepare_addon_link( &$link ) {
569
		$site_url = 'https://formidableforms.com/';
570
		if ( strpos( $link, 'http' ) !== 0 ) {
571
			$link = $site_url . $link;
572
		}
573
		$link       = FrmAppHelper::make_affiliate_url( $link );
574
		$query_args = array(
575
			'utm_source'   => 'WordPress',
576
			'utm_medium'   => 'addons',
577
			'utm_campaign' => 'liteplugin',
578
		);
579
		$link       = add_query_arg( $query_args, $link );
580
	}
581
582
	/**
583
	 * Add the status to the addon array. Status options are:
584
	 * installed, active, not installed
585
	 *
586
	 * @since 3.04.02
587
	 */
588
	protected static function set_addon_status( &$addon ) {
589
		if ( ! empty( $addon['activate_url'] ) ) {
590
			$addon['status'] = array(
591
				'type'  => 'installed',
592
				'label' => __( 'Installed', 'formidable' ),
593
			);
594
		} elseif ( $addon['installed'] ) {
595
			$addon['status'] = array(
596
				'type'  => 'active',
597
				'label' => __( 'Active', 'formidable' ),
598
			);
599
		} else {
600
			$addon['status'] = array(
601
				'type'  => 'not-installed',
602
				'label' => __( 'Not Installed', 'formidable' ),
603
			);
604
		}
605
	}
606
607
	public static function upgrade_to_pro() {
608
		FrmAppHelper::include_svg();
609
610
		$link_parts = array(
611
			'medium'  => 'upgrade',
612
			'content' => 'button',
613
		);
614
615
		$features = array(
616
			'Display Entries' => array(
617
				array(
618
					'label' => 'Display form data with virtually limitless views',
619
					'link'  => array(
620
						'content' => 'views',
621
						'param'   => 'views-display-form-data',
622
					),
623
					'lite'  => false,
624
				),
625
				array(
626
					'label' => 'Generate graphs and stats based on your submitted data',
627
					'link'  => array(
628
						'content' => 'graphs',
629
						'param'   => 'statistics-graphs-wordpress-forms',
630
					),
631
					'lite'  => false,
632
				),
633
			),
634
			'Entry Management' => array(
635
				array(
636
					'label' => 'Import entries from a CSV',
637
					'link'  => array(
638
						'content' => 'import-entries',
639
						'param'   => 'importing-exporting-wordpress-forms',
640
					),
641
					'lite'  => false,
642
				),
643
				array(
644
					'label' => 'Logged-in users can save drafts and return later',
645
					'link'  => array(
646
						'content' => 'save-drafts',
647
						'param'   => 'save-drafts-wordpress-form',
648
					),
649
					'lite'  => false,
650
				),
651
				array(
652
					'label' => 'Flexibly and powerfully view, edit, and delete entries from anywhere on your site',
653
					'link'  => array(
654
						'content' => 'front-edit',
655
						'param'   => 'wordpress-front-end-editing',
656
					),
657
					'lite'  => false,
658
				),
659
				array(
660
					'label' => 'View form submissions from the back-end',
661
					'lite'  => true,
662
				),
663
				array(
664
					'label' => 'Export your entries to a CSV',
665
					'lite'  => true,
666
				),
667
			),
668
			'Form Building' => array(
669
				array(
670
					'label' => 'Save a calculated value into a field',
671
					'link'  => array(
672
						'content' => 'calculations',
673
						'param'   => 'field-calculations-wordpress-form',
674
					),
675
					'lite'  => false,
676
				),
677
				array(
678
					'label' => 'Allow multiple file uploads',
679
					'link'  => array(
680
						'content' => 'file-uploads',
681
						'param'   => 'wordpress-multi-file-upload-fields',
682
					),
683
					'lite'  => false,
684
				),
685
				array(
686
					'label' => 'Repeat sections of fields',
687
					'link'  => array(
688
						'content' => 'repeaters',
689
						'param'   => 'repeatable-sections-forms',
690
					),
691
					'lite'  => false,
692
				),
693
				array(
694
					'label' => 'Hide and show fields conditionally based on other fields or the user\'s role',
695
					'link'  => array(
696
						'content' => 'conditional-logic',
697
						'param'   => 'conditional-logic-wordpress-forms',
698
					),
699
					'lite'  => false,
700
				),
701
				array(
702
					'label' => 'Confirmation fields',
703
					'link'  => array(
704
						'content' => 'confirmation-fields',
705
						'param'   => 'confirmation-fields-wordpress-forms',
706
					),
707
					'lite'  => false,
708
				),
709
				array(
710
					'label' => 'Multi-paged forms',
711
					'link'  => array(
712
						'content' => 'page-breaks',
713
						'param'   => 'wordpress-multi-page-forms',
714
					),
715
					'lite'  => false,
716
				),
717
				array(
718
					'label' => 'Include section headings, page breaks, rich text, dates, times, scales, star ratings, sliders, toggles, dynamic fields populated from other forms, passwords, and tags in advanced forms.',
719
					'lite'  => false,
720
				),
721
				array(
722
					'label' => 'Include text, email, url, paragraph text, radio, checkbox, dropdown fields, hidden fields, user ID fields, and HTML blocks in your form.',
723
					'lite'  => true,
724
				),
725
				array(
726
					'label' => 'Drag & Drop Form building',
727
					'link'  => array(
728
						'content' => 'drag-drop',
729
						'param'   => 'drag-drop-forms',
730
					),
731
					'lite'  => true,
732
				),
733
				array(
734
					'label' => 'Create forms from Templates',
735
					'link'  => array(
736
						'content' => 'form-templates',
737
						'param'   => 'wordpress-form-templates',
738
					),
739
					'lite'  => true,
740
				),
741
				array(
742
					'label' => 'Import and export forms with XML',
743
					'link'  => array(
744
						'content' => 'import',
745
						'param'   => 'importing-exporting-wordpress-forms',
746
					),
747
					'lite'  => true,
748
				),
749
				array(
750
					'label' => 'Use input placeholder text in your fields that clear when typing starts.',
751
					'lite'  => true,
752
				),
753
			),
754
			'Form Actions' => array(
755
				array(
756
					'label' => 'Conditionally send your email notifications based on values in your form',
757
					'link'  => array(
758
						'content' => 'conditional-emails',
759
					),
760
					'lite'  => false,
761
				),
762
				array(
763
					'label' => 'Create and edit WordPress posts or custom posts from the front-end',
764
					'link'  => array(
765
						'content' => 'create-posts',
766
						'param'   => 'create-posts-pages-wordpress-forms',
767
					),
768
					'lite'  => false,
769
				),
770
				array(
771
					'label' => 'Send multiple emails and autoresponders',
772
					'link'  => array(
773
						'content' => 'multiple-emails',
774
						'param'   => 'virtually-unlimited-emails',
775
					),
776
					'lite'  => true,
777
				),
778
			),
779
			'Form Appearance' => array(
780
				array(
781
					'label' => 'Create Multiple styles for different forms',
782
					'link'  => array(
783
						'content' => 'multiple-styles',
784
						'param'   => 'wordpress-visual-form-styler',
785
					),
786
					'lite'  => false,
787
				),
788
				array(
789
					'label' => 'Customizable layout with CSS classes',
790
					'link'  => array(
791
						'content' => 'form-layout',
792
						'param'   => 'wordpress-mobile-friendly-forms',
793
					),
794
					'lite'  => true,
795
				),
796
				array(
797
					'label' => 'Customize the HTML for your forms',
798
					'link'  => array(
799
						'content' => 'custom-html',
800
						'param'   => 'customizable-html-wordpress-form',
801
					),
802
					'lite'  => true,
803
				),
804
				array(
805
					'label' => 'Style your form with the Visual Form Styler',
806
					'lite'  => true,
807
				),
808
			),
809
		);
810
811
		include( FrmAppHelper::plugin_path() . '/classes/views/addons/upgrade_to_pro.php' );
812
	}
813
814
	/**
815
	 * Install Pro after connection with Formidable.
816
	 *
817
	 * @since 4.02.05
818
	 */
819
	public static function connect_pro() {
820
		FrmAppHelper::permission_check( 'install_plugins' );
821
		check_ajax_referer( 'frm_ajax', 'nonce' );
822
823
		$url = FrmAppHelper::get_post_param( 'plugin', '', 'sanitize_text_field' );
824
		if ( FrmAppHelper::pro_is_installed() || empty( $url ) ) {
825
			wp_die();
826
		}
827
828
		$response = array();
829
830
		// It's already installed and active.
831
		$active = activate_plugin( 'formidable-pro/formidable-pro.php', false, false, true );
832
		if ( is_wp_error( $active ) ) {
833
			// The plugin was installed, but not active. Download it now.
834
			self::ajax_install_addon();
0 ignored issues
show
Deprecated Code introduced by
The method FrmAddonsController::ajax_install_addon() has been deprecated with message: 4.09.01

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
835
		} else {
836
			$response['active']  = true;
837
			$response['success'] = true;
838
		}
839
840
		echo json_encode( $response );
841
		wp_die();
842
	}
843
844
	/**
845
	 * @since 4.08
846
	 */
847
	protected static function download_and_activate() {
848
		// Set the current screen to avoid undefined notices.
849
		if ( is_admin() ) {
850
			global $hook_suffix;
851
			set_current_screen();
852
		}
853
854
		self::maybe_show_cred_form();
855
856
		$installed = self::install_addon();
857
		if ( is_array( $installed ) && isset( $installed['message'] ) ) {
858
			return $installed;
859
		}
860
		self::maybe_activate_addon( $installed );
861
	}
862
863
	/**
864
	 * @since 3.04.02
865
	 */
866
	protected static function maybe_show_cred_form() {
867
		if ( ! function_exists( 'request_filesystem_credentials' ) ) {
868
			include_once( ABSPATH . 'wp-admin/includes/file.php' );
869
		}
870
871
		// Start output bufferring to catch the filesystem form if credentials are needed.
872
		ob_start();
873
874
		$show_form = false;
875
		$method    = '';
876
		$url       = add_query_arg( array( 'page' => 'formidable-settings' ), admin_url( 'admin.php' ) );
877
		$url       = esc_url_raw( $url );
878
		$creds     = request_filesystem_credentials( $url, $method, false, false, null );
879
880
		if ( false === $creds ) {
881
			$show_form = true;
882
		} elseif ( ! WP_Filesystem( $creds ) ) {
883
			request_filesystem_credentials( $url, $method, true, false, null );
884
			$show_form = true;
885
		}
886
887
		if ( $show_form ) {
888
			$form     = ob_get_clean();
889
			$message  = __( 'Sorry, your site requires FTP authentication. Please download plugins from FormidableForms.com and install them manually.', 'formidable' );
890
			$data     = $form;
0 ignored issues
show
Unused Code introduced by
$data is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
891
			$response = array(
892
				'success' => false,
893
				'message' => $message,
894
				'form'    => $form,
895
			);
896
			wp_send_json( $response );
897
		}
898
899
		ob_end_clean();
900
	}
901
902
	/**
903
	 * We do not need any extra credentials if we have gotten this far,
904
	 * so let's install the plugin.
905
	 *
906
	 * @since 3.04.02
907
	 */
908
	protected static function install_addon() {
909
		require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
910
911
		$download_url = FrmAppHelper::get_param( 'plugin', '', 'post', 'esc_url_raw' );
912
913
		// Create the plugin upgrader with our custom skin.
914
		$installer = new Plugin_Upgrader( new FrmInstallerSkin() );
915
		$installer->install( $download_url );
916
917
		// Flush the cache and return the newly installed plugin basename.
918
		wp_cache_flush();
919
920
		$plugin = $installer->plugin_info();
921
		if ( empty( $plugin ) ) {
922
			return array(
923
				'message' => 'Plugin was not installed. ' . $installer->result,
924
				'success' => false,
925
			);
926
		}
927
		return $plugin;
928
	}
929
930
	/**
931
	 * @since 3.06.03
932
	 */
933
	public static function ajax_activate_addon() {
934
935
		self::install_addon_permissions();
936
937
		// Set the current screen to avoid undefined notices.
938
		global $hook_suffix;
939
		set_current_screen();
940
941
		$plugin = FrmAppHelper::get_param( 'plugin', '', 'post', 'sanitize_text_field' );
942
		self::maybe_activate_addon( $plugin );
943
944
		// Send back a response.
945
		echo json_encode( __( 'Your plugin has been activated. Please reload the page to see more options.', 'formidable' ) );
946
		wp_die();
947
	}
948
949
	/**
950
	 * @since 3.04.02
951
	 * @param string $installed The plugin folder name with file name
952
	 */
953
	protected static function maybe_activate_addon( $installed ) {
954
		if ( ! $installed ) {
955
			return;
956
		}
957
958
		$activate = activate_plugin( $installed );
959
		if ( is_wp_error( $activate ) ) {
960
			// Ignore the invalid header message that shows with nested plugins.
961
			if ( $activate->get_error_code() !== 'no_plugin_header' ) {
962
				if ( wp_doing_ajax() ) {
963
					echo json_encode( array( 'error' => $activate->get_error_message() ) );
964
					wp_die();
965
				}
966
				return array(
967
					'message' => $activate->get_error_message(),
968
					'success' => false,
969
				);
970
			}
971
		}
972
	}
973
974
	/**
975
	 * Run security checks before installing
976
	 *
977
	 * @since 3.04.02
978
	 */
979
	protected static function install_addon_permissions() {
980
		check_ajax_referer( 'frm_ajax', 'nonce' );
981
982
		if ( ! current_user_can( 'activate_plugins' ) || ! isset( $_POST['plugin'] ) ) {
983
			echo json_encode( true );
984
			wp_die();
985
		}
986
	}
987
988
	/**
989
	 * @since 4.08
990
	 */
991
	public static function connect_link() {
992
		$auth = get_option( 'frm_connect_token' );
993
		if ( empty( $auth ) ) {
994
			$auth = hash( 'sha512', wp_rand() );
995
			update_option( 'frm_connect_token', $auth );
996
		}
997
		$link = FrmAppHelper::admin_upgrade_link( 'connect', 'api-connect' );
998
		$args = array(
999
			'v'       => 2,
1000
			'siteurl' => FrmAppHelper::site_url(),
1001
			'url'     => get_rest_url(),
1002
			'token'   => $auth,
1003
			'l'       => self::get_pro_license(),
1004
		);
1005
1006
		return add_query_arg( $args, $link );
1007
	}
1008
1009
	/**
1010
	 * Check the auth value for install permission.
1011
	 *
1012
	 * @since 4.08
1013
	 *
1014
	 * @return bool
1015
	 */
1016
	public static function can_install_addon_api() {
1017
		// Verify params present (auth & download link).
1018
		$post_auth = FrmAppHelper::get_param( 'token', '', 'request', 'sanitize_text_field' );
1019
		$post_url  = FrmAppHelper::get_param( 'file_url', '', 'request', 'sanitize_text_field' );
1020
1021
		if ( empty( $post_auth ) || empty( $post_url ) ) {
1022
			return false;
1023
		}
1024
1025
		// Verify auth.
1026
		$auth = get_option( 'frm_connect_token' );
1027
		if ( empty( $auth ) || ! hash_equals( $auth, $post_auth ) ) {
1028
			return false;
1029
		}
1030
1031
		return true;
1032
	}
1033
1034
	/**
1035
	 * Install and/or activate the add-on file.
1036
	 *
1037
	 * @since 4.08
1038
	 */
1039
	public static function install_addon_api() {
1040
		// Sanitize when it's used to prevent double sanitizing.
1041
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput
1042
		$_POST['plugin'] = isset( $_REQUEST['file_url'] ) ? $_REQUEST['file_url'] : ''; // Set for later use
1043
1044
		$error = esc_html__( 'Could not install an upgrade. Please download from formidableforms.com and install manually.', 'formidable' );
0 ignored issues
show
Unused Code introduced by
$error is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1045
1046
		// Delete so cannot replay.
1047
		delete_option( 'frm_connect_token' );
1048
1049
		// It's already installed and active.
1050
		$active = activate_plugin( 'formidable-pro/formidable-pro.php', false, false, true );
1051
		if ( is_wp_error( $active ) ) {
1052
			// Download plugin now.
1053
			$response = self::download_and_activate();
1054
			if ( is_array( $response ) && isset( $response['success'] ) ) {
1055
				return $response;
1056
			}
1057
		}
1058
1059
		// If empty license, save it now.
1060
		if ( empty( self::get_pro_license() ) && function_exists( 'load_formidable_pro' ) ) {
1061
			load_formidable_pro();
1062
			$license = stripslashes( FrmAppHelper::get_param( 'key', '', 'request', 'sanitize_text_field' ) );
1063
			if ( empty( $license ) ) {
1064
				return array(
1065
					'success' => false,
1066
					'error'   => 'That site does not have a valid license key.',
1067
				);
1068
			}
1069
1070
			$response = FrmAddon::activate_license_for_plugin( $license, 'formidable_pro' );
1071
			if ( ! $response['success'] ) {
1072
				// Could not activate license.
1073
				return $response;
1074
			}
1075
		}
1076
1077
		return array(
1078
			'success' => true,
1079
		);
1080
	}
1081
1082
	/**
1083
	 * Render a conditional action button for a specified plugin
1084
	 *
1085
	 * @param string $plugin
1086
	 * @param array|string $upgrade_link_args
1087
	 * @since 4.09
1088
	 */
1089
	public static function conditional_action_button( $plugin, $upgrade_link_args ) {
1090
		if ( is_callable( 'FrmProAddonsController::conditional_action_button' ) ) {
1091
			return FrmProAddonsController::conditional_action_button( $plugin, $upgrade_link_args );
1092
		}
1093
1094
		$addon        = self::get_addon( $plugin );
1095
		$upgrade_link = FrmAppHelper::admin_upgrade_link( $upgrade_link_args );
1096
		self::addon_upgrade_link( $addon, $upgrade_link );
1097
	}
1098
1099
	/**
1100
	 * Render a conditional action button for an add on
1101
	 *
1102
	 * @since 4.09.01
1103
	 * @param array $addon
0 ignored issues
show
Bug introduced by
There is no parameter named $addon. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1104
	 * @param string|false $license_type
0 ignored issues
show
Bug introduced by
There is no parameter named $license_type. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1105
	 * @param string $plan_required
0 ignored issues
show
Bug introduced by
There is no parameter named $plan_required. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1106
	 * @param string $upgrade_link
0 ignored issues
show
Bug introduced by
There is no parameter named $upgrade_link. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1107
	 */
1108
	public static function show_conditional_action_button( $atts ) {
1109
		if ( is_callable( 'FrmProAddonsController::show_conditional_action_button' ) ) {
1110
			return FrmProAddonsController::show_conditional_action_button( $atts );
1111
		}
1112
1113
		self::addon_upgrade_link( $atts['addon'], $atts['upgrade_link'] );
1114
	}
1115
1116
	/**
1117
	 * @since 4.09.01
1118
	 */
1119
	protected static function addon_upgrade_link( $addon, $upgrade_link ) {
1120
		if ( $addon ) {
1121
			$upgrade_link .= '&utm_content=' . $addon['slug'];
1122
		}
1123
1124
		if ( $addon && isset( $addon['categories'] ) && in_array( 'Solution', $addon['categories'], true ) ) {
1125
			// Solutions will go to a separate page.
1126
			$upgrade_link = FrmAppHelper::admin_upgrade_link( 'addons', $addon['link'] );
1127
		}
1128
		?>
1129
		<a class="install-now button button-secondary frm-button-secondary" href="<?php echo esc_url( $upgrade_link ); ?>" target="_blank" rel="noopener" aria-label="<?php esc_attr_e( 'Upgrade Now', 'formidable' ); ?>">
1130
			<?php esc_html_e( 'Upgrade Now', 'formidable' ); ?>
1131
		</a>
1132
		<?php
1133
	}
1134
1135
	/**
1136
	 * @since 3.04.02
1137
	 * @deprecated 4.09.01
1138
	 */
1139
	public static function ajax_install_addon() {
1140
		FrmDeprecated::ajax_install_addon();
1141
	}
1142
1143
	/**
1144
	 * @since 4.06.02
1145
	 * @deprecated 4.09.01
1146
	 */
1147
	public static function ajax_multiple_addons() {
1148
		FrmDeprecated::ajax_multiple_addons();
1149
	}
1150
1151
	/**
1152
	 * @since 3.04.03
1153
	 * @deprecated 3.06
1154
	 * @codeCoverageIgnore
1155
	 * @return array
1156
	 */
1157
	public static function error_for_license( $license ) {
1158
		return FrmDeprecated::error_for_license( $license );
1159
	}
1160
1161
	/**
1162
	 * @since 3.04.03
1163
	 * @deprecated 3.06
1164
	 * @codeCoverageIgnore
1165
	 */
1166
	public static function get_pro_updater() {
1167
		return FrmDeprecated::get_pro_updater();
1168
	}
1169
1170
	/**
1171
	 * @since 3.04.03
1172
	 * @deprecated 3.06
1173
	 * @codeCoverageIgnore
1174
	 *
1175
	 * @return array
1176
	 */
1177
	public static function get_addon_info( $license = '' ) {
1178
		return FrmDeprecated::get_addon_info( $license );
1179
	}
1180
1181
	/**
1182
	 * @since 3.04.03
1183
	 * @deprecated 3.06
1184
	 * @codeCoverageIgnore
1185
	 *
1186
	 * @return string
1187
	 */
1188
	public static function get_cache_key( $license ) {
1189
		return FrmDeprecated::get_cache_key( $license );
1190
	}
1191
1192
	/**
1193
	 * @since 3.04.03
1194
	 * @deprecated 3.06
1195
	 * @codeCoverageIgnore
1196
	 */
1197
	public static function reset_cached_addons( $license = '' ) {
1198
		FrmDeprecated::reset_cached_addons( $license );
1199
	}
1200
1201
	/**
1202
	 * @since 2.03.08
1203
	 * @deprecated 3.04.03
1204
	 * @codeCoverageIgnore
1205
	 *
1206
	 * @param boolean $return
1207
	 * @param string $package
1208
	 *
1209
	 * @return boolean
1210
	 */
1211
	public static function add_shorten_edd_filename_filter( $return, $package ) {
1212
		return FrmDeprecated::add_shorten_edd_filename_filter( $return, $package );
1213
	}
1214
1215
	/**
1216
	 * @since 2.03.08
1217
	 * @deprecated 3.04.03
1218
	 * @codeCoverageIgnore
1219
	 *
1220
	 * @param string $filename
1221
	 * @param string $ext
1222
	 *
1223
	 * @return string
1224
	 */
1225
	public static function shorten_edd_filename( $filename, $ext ) {
1226
		return FrmDeprecated::shorten_edd_filename( $filename, $ext );
1227
	}
1228
1229
	/**
1230
	 * @deprecated 3.04.03
1231
	 * @codeCoverageIgnore
1232
	 */
1233
	public static function get_licenses() {
1234
		FrmDeprecated::get_licenses();
1235
	}
1236
}
1237