Completed
Push — master ( b82535...2e701e )
by Stephanie
02:17
created

FrmAddonsController::license_settings()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
class FrmAddonsController {
4
5
	public static function menu() {
6
		if ( ! current_user_can( 'activate_plugins' ) ) {
7
			return;
8
		}
9
10
		$label = __( 'Add-Ons', 'formidable' );
11
		if ( FrmAppHelper::pro_is_installed() ) {
12
			$label = '<span style="color:#fe5a1d">' . $label . '</span>';
13
		}
14
		add_submenu_page( 'formidable', 'Formidable | ' . __( 'Add-Ons', 'formidable' ), $label, 'frm_view_forms', 'formidable-addons', 'FrmAddonsController::list_addons' );
15
16
		if ( ! FrmAppHelper::pro_is_installed() ) {
17
			add_submenu_page(
18
				'formidable',
19
				'Formidable | ' . __( 'Upgrade to Pro', 'formidable' ),
20
				'<span style="color:#fe5a1d">' . __( 'Upgrade to Pro', 'formidable' ) . '</span>',
21
				'frm_view_forms',
22
				'formidable-pro-upgrade',
23
				'FrmAddonsController::upgrade_to_pro'
24
			);
25
		}
26
	}
27
28
	public static function list_addons() {
29
		FrmAppHelper::include_svg();
30
		$installed_addons = apply_filters( 'frm_installed_addons', array() );
31
		$license_type     = '';
32
33
		$addons = self::get_api_addons();
34
		$errors = array();
35
36
		if ( isset( $addons['error'] ) ) {
37
			$api    = new FrmFormApi();
38
			$errors = $api->get_error_from_response( $addons );
39
			$license_type = isset( $addons['error']['type'] ) ? $addons['error']['type'] : '';
40
			unset( $addons['error'] );
41
		}
42
		self::prepare_addons( $addons );
43
44
		$pricing = FrmAppHelper::admin_upgrade_link( 'addons' );
45
46
		include( FrmAppHelper::plugin_path() . '/classes/views/addons/list.php' );
47
	}
48
49
	public static function license_settings() {
50
		$plugins = apply_filters( 'frm_installed_addons', array() );
51
		if ( empty( $plugins ) ) {
52
			esc_html_e( 'There are no plugins on your site that require a license', 'formidable' );
53
54
			return;
55
		}
56
57
		ksort( $plugins );
58
59
		include( FrmAppHelper::plugin_path() . '/classes/views/addons/settings.php' );
60
	}
61
62
	private static function get_api_addons() {
63
		$api    = new FrmFormApi();
64
		$addons = $api->get_api_info();
65
66
		if ( empty( $addons ) ) {
67
			$addons = self::fallback_plugin_list();
68
		} else {
69
			foreach ( $addons as $k => $addon ) {
70
				if ( empty( $addon['excerpt'] ) && $k !== 'error' ) {
71
					unset( $addons[ $k ] );
72
				}
73
			}
74
		}
75
76
		return $addons;
77
	}
78
79
	/**
80
	 * If the API is unable to connect, show something on the addons page
81
	 *
82
	 * @since 3.04.03
83
	 * @return array
84
	 */
85
	private static function fallback_plugin_list() {
86
		return array(
87
			'formidable-pro' => array(
88
				'title'   => 'Formidable Pro',
89
				'link'    => 'pricing/',
90
				'docs'    => '',
91
				'excerpt' => 'Enhance your basic Formidable forms with a plethora of Pro field types and features. Create advanced forms and data-driven applications in minutes.',
92
			),
93
			'mailchimp'      => array(
94
				'title'   => 'MailChimp Forms',
95
				'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.',
96
			),
97
			'registration'   => array(
98
				'title'   => 'User Registration Forms',
99
				'link'    => 'downloads/user-registration/',
100
				'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.',
101
			),
102
			'paypal'         => array(
103
				'title'   => 'PayPal Standard Forms',
104
				'link'    => 'downloads/paypal-standard/',
105
				'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.',
106
			),
107
			'stripe'         => array(
108
				'title'   => 'Stripe Forms',
109
				'docs'    => 'knowledgebase/stripe/',
110
				'excerpt' => 'Any Formidable forms on your site can accept credit card payments without users ever leaving your site.',
111
			),
112
			'authorize-net'  => array(
113
				'title'   => 'Authorize.net AIM Forms',
114
				'link'    => 'downloads/authorize-net-aim/',
115
				'docs'    => 'knowledgebase/authorize-net-aim/',
116
				'excerpt' => 'Accept one-time payments directly on your site, using Authorize.net AIM.',
117
			),
118
			'woocommerce'    => array(
119
				'title'   => 'WooCommerce Forms',
120
				'excerpt' => 'Use a Formidable form on your WooCommerce product pages.',
121
			),
122
			'autoresponder'  => array(
123
				'title'   => 'Form Action Automation',
124
				'docs'    => 'knowledgebase/schedule-autoresponder/',
125
				'excerpt' => 'Schedule email notifications, SMS messages, and API actions.',
126
			),
127
			'modal'          => array(
128
				'title'   => 'Bootstrap Modal Forms',
129
				'link'    => 'downloads/bootstrap-modal/',
130
				'docs'    => 'knowledgebase/bootstrap-modal/',
131
				'excerpt' => 'Open a view or form in a Bootstrap popup.',
132
			),
133
			'bootstrap'      => array(
134
				'title'   => 'Bootstrap Style Forms',
135
				'excerpt' => 'Instantly add Bootstrap styling to all your Formidable forms.',
136
			),
137
			'zapier'         => array(
138
				'title'   => 'Zapier Forms',
139
				'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.',
140
			),
141
			'signature'      => array(
142
				'title'   => 'Digital Signature Forms',
143
				'excerpt' => 'Add a signature field to your form. The user may write their signature with a trackpad/mouse or just type it.',
144
			),
145
			'api'            => array(
146
				'title'   => 'Formidable Forms API',
147
				'link'    => 'downloads/formidable-api/',
148
				'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.',
149
			),
150
			'twilio'         => array(
151
				'title'   => 'Twilio SMS Forms',
152
				'docs'    => 'knowledgebase/twilio-add-on/',
153
				'excerpt' => 'Allow users to text their votes for polls created by Formidable Forms, or send SMS notifications when entries are submitted or updated.',
154
			),
155
		);
156
	}
157
158
	/**
159
	 * If Pro is missing but has been authenticated, include a download URL
160
	 *
161
	 * @since 3.04.03
162
	 * @return string
163
	 */
164
	public static function get_pro_download_url() {
165
		$pro_cred_store = 'frmpro-credentials';
166
		$pro_wpmu_store = 'frmpro-wpmu-sitewide';
167
		if ( is_multisite() && get_site_option( $pro_wpmu_store ) ) {
168
			$creds = get_site_option( $pro_cred_store );
169
		} else {
170
			$creds = get_option( $pro_cred_store );
171
		}
172
173
		if ( empty( $creds ) || ! is_array( $creds ) || ! isset( $creds['license'] ) ) {
174
			return '';
175
		}
176
177
		$license = $creds['license'];
178
		if ( empty( $license ) ) {
179
			return '';
180
		}
181
182
		if ( strpos( $license, '-' ) ) {
183
			// this is a fix for licenses saved in the past
184
			$license = strtoupper( $license );
185
		}
186
187
		$api       = new FrmFormApi( $license );
188
		$downloads = $api->get_api_info();
189
		$pro       = isset( $downloads['93790'] ) ? $downloads['93790'] : array();
190
191
		return isset( $pro['url'] ) ? $pro['url'] : '';
192
	}
193
194
	/**
195
	 * @since 4.0.01
196
	 */
197
	public static function is_license_expired() {
198
		$installed_addons = apply_filters( 'frm_installed_addons', array() );
199
		if ( empty( $installed_addons ) || ! isset( $installed_addons['formidable_pro'] ) ) {
200
			return false;
201
		}
202
		$installed_addons = array(
203
			'formidable_pro' => $installed_addons['formidable_pro'],
204
		);
205
206
		$version_info = self::fill_update_addon_info( $installed_addons );
207
		if ( ! isset( $version_info['error'] ) ) {
208
			return false;
209
		}
210
211
		return $version_info['error'];
212
	}
213
214
	/**
215
	 * @since 3.04.03
216
	 */
217
	public static function check_update( $transient ) {
218
		if ( ! is_object( $transient ) ) {
219
			$transient = new stdClass();
220
		}
221
222
		$installed_addons = apply_filters( 'frm_installed_addons', array() );
223
		if ( empty( $installed_addons ) ) {
224
			return $transient;
225
		}
226
227
		$version_info = self::fill_update_addon_info( $installed_addons );
228
229
		$transient->last_checked = time();
230
231
		$wp_plugins = get_plugins();
232
233
		foreach ( $version_info as $id => $plugin ) {
234
			$plugin = (object) $plugin;
235
236
			if ( ! isset( $plugin->new_version ) || ! isset( $plugin->package ) ) {
237
				continue;
238
			}
239
240
			$folder = $plugin->plugin;
241
			if ( empty( $folder ) ) {
242
				continue;
243
			}
244
245
			if ( ! self::is_installed( $folder ) ) {
246
				// don't show an update if the plugin isn't installed
247
				continue;
248
			}
249
250
			$wp_plugin  = isset( $wp_plugins[ $folder ] ) ? $wp_plugins[ $folder ] : array();
251
			$wp_version = isset( $wp_plugin['Version'] ) ? $wp_plugin['Version'] : '1.0';
252
253
			if ( version_compare( $wp_version, $plugin->new_version, '<' ) ) {
254
				$slug                           = explode( '/', $folder );
255
				$plugin->slug                   = $slug[0];
256
				$transient->response[ $folder ] = $plugin;
257
			}
258
259
			$transient->checked[ $folder ] = $wp_version;
260
261
		}
262
263
		return $transient;
264
	}
265
266
	/**
267
	 * Check if a plugin is installed before showing an update for it
268
	 *
269
	 * @since 3.05
270
	 *
271
	 * @param string $plugin - the folder/filename.php for a plugin
272
	 *
273
	 * @return bool - True if installed
274
	 */
275
	private static function is_installed( $plugin ) {
276
		if ( ! function_exists( 'get_plugins' ) ) {
277
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
278
		}
279
280
		$all_plugins = get_plugins();
281
282
		return isset( $all_plugins[ $plugin ] );
283
	}
284
285
	/**
286
	 * @since 3.04.03
287
	 *
288
	 * @param array $installed_addons
289
	 *
290
	 * @return array
291
	 */
292
	private static function fill_update_addon_info( $installed_addons ) {
293
		$checked_licenses = array();
294
		$version_info     = array();
295
296
		foreach ( $installed_addons as $addon ) {
297
			if ( $addon->store_url !== 'https://formidableforms.com' ) {
298
				// check if this is a third-party addon
299
				continue;
300
			}
301
302
			$new_license = $addon->license;
303
			if ( empty( $new_license ) || in_array( $new_license, $checked_licenses ) ) {
304
				continue;
305
			}
306
307
			$checked_licenses[] = $new_license;
308
309
			$api = new FrmFormApi( $new_license );
310
			if ( empty( $version_info ) ) {
311
				$version_info = $api->get_api_info();
312
				continue;
313
			}
314
315
			$plugin = $api->get_addon_for_license( $addon, $version_info );
316
			if ( empty( $plugin ) ) {
317
				continue;
318
			}
319
320
			$download_id = isset( $plugin['id'] ) ? $plugin['id'] : 0;
321
			if ( ! empty( $download_id ) && ! isset( $version_info[ $download_id ]['package'] ) ) {
322
				// if this addon is using its own license, get the update url
323
				$addon_info = $api->get_api_info();
324
325
				$version_info[ $download_id ] = $addon_info[ $download_id ];
326
				if ( isset( $addon_info['error'] ) ) {
327
					$version_info[ $download_id ]['error'] = array(
328
						'message' => $addon_info['error']['message'],
329
						'code'    => $addon_info['error']['code'],
330
					);
331
				}
332
			}
333
		}
334
335
		return $version_info;
336
	}
337
338
	/**
339
	 * Get the action link for an addon that isn't active.
340
	 *
341
	 * @since 3.06.03
342
	 * @param string $addon The plugin slug
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...
343
	 * @return array
344
	 */
345
	public static function install_link( $plugin ) {
346
		$link    = array();
347
		$addons = self::get_api_addons();
348
		self::prepare_addons( $addons );
349
350
		foreach ( $addons as $addon ) {
351
			$slug = explode( '/', $addon['plugin'] );
352
			if ( $slug[0] !== 'formidable-' . $plugin ) {
353
				continue;
354
			}
355
356
			if ( $addon['status']['type'] === 'installed' && ! empty( $addon['activate_url'] ) ) {
357
				$link = array(
358
					'url'   => $addon['plugin'],
359
					'class' => 'frm-activate-addon',
360
				);
361
			} elseif ( isset( $addon['url'] ) && ! empty( $addon['url'] ) ) {
362
				$link = array(
363
					'url'   => $addon['url'],
364
					'class' => 'frm-install-addon',
365
				);
366
			} elseif ( isset( $addon['categories'] ) && ! empty( $addon['categories'] ) ) {
367
				$link = array(
368
					'categories' => $addon['categories'],
369
				);
370
			}
371
372
			return $link;
373
		}
374
	}
375
376
	/**
377
	 * @since 3.04.03
378
	 *
379
	 * @param array $addons
380
	 * @param object $license The FrmAddon object
381
	 *
382
	 * @return array
383
	 */
384
	public static function get_addon_for_license( $addons, $license ) {
385
		$download_id = $license->download_id;
386
		$plugin      = array();
387 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...
388
			foreach ( $addons as $addon ) {
389
				if ( strtolower( $license->plugin_name ) == strtolower( $addon['title'] ) ) {
390
					return $addon;
391
				}
392
			}
393
		} elseif ( isset( $addons[ $download_id ] ) ) {
394
			$plugin = $addons[ $download_id ];
395
		}
396
397
		return $plugin;
398
	}
399
400
	private static function prepare_addons( &$addons ) {
401
		$activate_url = '';
402
		if ( current_user_can( 'activate_plugins' ) ) {
403
			$activate_url = add_query_arg( array( 'action' => 'activate' ), admin_url( 'plugins.php' ) );
404
		}
405
406
		$loop_addons = $addons;
407
		foreach ( $loop_addons as $id => $addon ) {
408
			if ( is_numeric( $id ) ) {
409
				$slug      = str_replace( array( '-wordpress-plugin', '-wordpress' ), '', $addon['slug'] );
410
				$file_name = $addon['plugin'];
411
			} else {
412
				$slug = $id;
413
				if ( isset( $addon['file'] ) ) {
414
					$base_file = $addon['file'];
415
				} else {
416
					$base_file = 'formidable-' . $slug;
417
				}
418
				$file_name = $base_file . '/' . $base_file . '.php';
419
			}
420
421
			$addon['installed']    = self::is_installed( $file_name );
422
			$addon['activate_url'] = '';
423
424
			if ( $addon['installed'] && ! empty( $activate_url ) && ! is_plugin_active( $file_name ) ) {
425
				$addon['activate_url'] = add_query_arg(
426
					array(
427
						'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $file_name ),
428
						'plugin'   => $file_name,
429
					),
430
					$activate_url
431
				);
432
			}
433
434
			if ( ! isset( $addon['docs'] ) ) {
435
				$addon['docs'] = 'knowledgebase/formidable-' . $slug . '/';
436
			}
437
			self::prepare_addon_link( $addon['docs'] );
438
439
			if ( ! isset( $addon['link'] ) ) {
440
				$addon['link'] = 'downloads/' . $slug . '/';
441
			}
442
			self::prepare_addon_link( $addon['link'] );
443
444
			self::set_addon_status( $addon );
445
			$addons[ $id ] = $addon;
446
		}
447
	}
448
449
	/**
450
	 * @since 3.04.02
451
	 */
452
	private static function prepare_addon_link( &$link ) {
453
		$site_url = 'https://formidableforms.com/';
454
		if ( strpos( $link, 'http' ) !== 0 ) {
455
			$link = $site_url . $link;
456
		}
457
		$link       = FrmAppHelper::make_affiliate_url( $link );
458
		$query_args = array(
459
			'utm_source'   => 'WordPress',
460
			'utm_medium'   => 'addons',
461
			'utm_campaign' => 'liteplugin',
462
		);
463
		$link       = add_query_arg( $query_args, $link );
464
	}
465
466
	/**
467
	 * Add the status to the addon array. Status options are:
468
	 * installed, active, not installed
469
	 *
470
	 * @since 3.04.02
471
	 */
472
	private static function set_addon_status( &$addon ) {
473
		if ( ! empty( $addon['activate_url'] ) ) {
474
			$addon['status'] = array(
475
				'type'  => 'installed',
476
				'label' => __( 'Installed', 'formidable' ),
477
			);
478
		} elseif ( $addon['installed'] ) {
479
			$addon['status'] = array(
480
				'type'  => 'active',
481
				'label' => __( 'Active', 'formidable' ),
482
			);
483
		} else {
484
			$addon['status'] = array(
485
				'type'  => 'not-installed',
486
				'label' => __( 'Not Installed', 'formidable' ),
487
			);
488
		}
489
	}
490
491
	public static function upgrade_to_pro() {
492
		FrmAppHelper::include_svg();
493
494
		$link_parts = array(
495
			'medium'  => 'upgrade',
496
			'content' => 'button',
497
		);
498
499
		$features = array(
500
			'Display Entries' => array(
501
				array(
502
					'label' => 'Display form data with virtually limitless views',
503
					'link'  => array(
504
						'content' => 'views',
505
						'param'   => 'views-display-form-data',
506
					),
507
					'lite'  => false,
508
				),
509
				array(
510
					'label' => 'Generate graphs and stats based on your submitted data',
511
					'link'  => array(
512
						'content' => 'graphs',
513
						'param'   => 'statistics-graphs-wordpress-forms',
514
					),
515
					'lite'  => false,
516
				),
517
			),
518
			'Entry Management' => array(
519
				array(
520
					'label' => 'Import entries from a CSV',
521
					'link'  => array(
522
						'content' => 'import-entries',
523
						'param'   => 'importing-exporting-wordpress-forms',
524
					),
525
					'lite'  => false,
526
				),
527
				array(
528
					'label' => 'Logged-in users can save drafts and return later',
529
					'link'  => array(
530
						'content' => 'save-drafts',
531
						'param'   => 'save-drafts-wordpress-form',
532
					),
533
					'lite'  => false,
534
				),
535
				array(
536
					'label' => 'Flexibly and powerfully view, edit, and delete entries from anywhere on your site',
537
					'link'  => array(
538
						'content' => 'front-edit',
539
						'param'   => 'wordpress-front-end-editing',
540
					),
541
					'lite'  => false,
542
				),
543
				array(
544
					'label' => 'View form submissions from the back-end',
545
					'lite'  => true,
546
				),
547
				array(
548
					'label' => 'Export your entries to a CSV',
549
					'lite'  => true,
550
				),
551
			),
552
			'Form Building' => array(
553
				array(
554
					'label' => 'Save a calculated value into a field',
555
					'link'  => array(
556
						'content' => 'calculations',
557
						'param'   => 'field-calculations-wordpress-form',
558
					),
559
					'lite'  => false,
560
				),
561
				array(
562
					'label' => 'Allow multiple file uploads',
563
					'link'  => array(
564
						'content' => 'file-uploads',
565
						'param'   => 'wordpress-multi-file-upload-fields',
566
					),
567
					'lite'  => false,
568
				),
569
				array(
570
					'label' => 'Repeat sections of fields',
571
					'link'  => array(
572
						'content' => 'repeaters',
573
						'param'   => 'repeatable-sections-forms',
574
					),
575
					'lite'  => false,
576
				),
577
				array(
578
					'label' => 'Hide and show fields conditionally based on other fields or the user\'s role',
579
					'link'  => array(
580
						'content' => 'conditional-logic',
581
						'param'   => 'conditional-logic-wordpress-forms',
582
					),
583
					'lite'  => false,
584
				),
585
				array(
586
					'label' => 'Confirmation fields',
587
					'link'  => array(
588
						'content' => 'confirmation-fields',
589
						'param'   => 'confirmation-fields-wordpress-forms',
590
					),
591
					'lite'  => false,
592
				),
593
				array(
594
					'label' => 'Multi-paged forms',
595
					'link'  => array(
596
						'content' => 'page-breaks',
597
						'param'   => 'wordpress-multi-page-forms',
598
					),
599
					'lite'  => false,
600
				),
601
				array(
602
					'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.',
603
					'lite'  => false,
604
				),
605
				array(
606
					'label' => 'Include text, email, url, paragraph text, radio, checkbox, dropdown fields, hidden fields, user ID fields, and HTML blocks in your form.',
607
					'lite'  => true,
608
				),
609
				array(
610
					'label' => 'Drag & Drop Form building',
611
					'link'  => array(
612
						'content' => 'drag-drop',
613
						'param'   => 'drag-drop-forms',
614
					),
615
					'lite'  => true,
616
				),
617
				array(
618
					'label' => 'Create forms from Templates',
619
					'link'  => array(
620
						'content' => 'form-templates',
621
						'param'   => 'wordpress-form-templates',
622
					),
623
					'lite'  => true,
624
				),
625
				array(
626
					'label' => 'Import and export forms with XML',
627
					'link'  => array(
628
						'content' => 'import',
629
						'param'   => 'importing-exporting-wordpress-forms',
630
					),
631
					'lite'  => true,
632
				),
633
				array(
634
					'label' => 'Use input placeholder text in your fields that clear when typing starts.',
635
					'lite'  => true,
636
				),
637
			),
638
			'Form Actions' => array(
639
				array(
640
					'label' => 'Conditionally send your email notifications based on values in your form',
641
					'link'  => array(
642
						'content' => 'conditional-emails',
643
					),
644
					'lite'  => false,
645
				),
646
				array(
647
					'label' => 'Create and edit WordPress posts or custom posts from the front-end',
648
					'link'  => array(
649
						'content' => 'create-posts',
650
						'param'   => 'create-posts-pages-wordpress-forms',
651
					),
652
					'lite'  => false,
653
				),
654
				array(
655
					'label' => 'Send multiple emails and autoresponders',
656
					'link'  => array(
657
						'content' => 'multiple-emails',
658
						'param'   => 'virtually-unlimited-emails',
659
					),
660
					'lite'  => true,
661
				),
662
			),
663
			'Form Appearance' => array(
664
				array(
665
					'label' => 'Create Multiple styles for different forms',
666
					'link'  => array(
667
						'content' => 'multiple-styles',
668
						'param'   => 'wordpress-visual-form-styler',
669
					),
670
					'lite'  => false,
671
				),
672
				array(
673
					'label' => 'Customizable layout with CSS classes',
674
					'link'  => array(
675
						'content' => 'form-layout',
676
						'param'   => 'wordpress-mobile-friendly-forms',
677
					),
678
					'lite'  => true,
679
				),
680
				array(
681
					'label' => 'Customize the HTML for your forms',
682
					'link'  => array(
683
						'content' => 'custom-html',
684
						'param'   => 'customizable-html-wordpress-form',
685
					),
686
					'lite'  => true,
687
				),
688
				array(
689
					'label' => 'Style your form with the Visual Form Styler',
690
					'lite'  => true,
691
				),
692
			),
693
		);
694
695
		include( FrmAppHelper::plugin_path() . '/classes/views/addons/upgrade_to_pro.php' );
696
	}
697
698
	/**
699
	 * Install Pro after connection with Formidable.
700
	 *
701
	 * @since 4.02.05
702
	 */
703
	public static function connect_pro() {
704
		FrmAppHelper::permission_check( 'install_plugins' );
705
		check_ajax_referer( 'frm_ajax', 'nonce' );
706
707
		$url = FrmAppHelper::get_post_param( 'plugin', '', 'sanitize_text_field' );
708
		if ( FrmAppHelper::pro_is_installed() || empty( $url ) ) {
709
			wp_die();
710
		}
711
712
		$response = array();
713
714
		// It's already installed and active.
715
		$active = activate_plugin( 'formidable-pro/formidable-pro.php', false, false, true );
716
		if ( is_wp_error( $active ) ) {
717
			// The plugin was installed, but not active. Download it now.
718
			self::ajax_install_addon();
719
		} else {
720
			$response['active'] = true;
721
		}
722
723
		echo json_encode( $response );
724
		wp_die();
725
	}
726
727
	/**
728
	 * @since 3.04.02
729
	 */
730
	public static function ajax_install_addon() {
731
732
		self::install_addon_permissions();
733
734
		// Set the current screen to avoid undefined notices.
735
		global $hook_suffix;
736
		set_current_screen();
737
738
		self::maybe_show_cred_form();
739
740
		$installed = self::install_addon();
741
		self::maybe_activate_addon( $installed );
742
743
		// Send back a response.
744
		echo json_encode( __( 'Your plugin has been installed. Please reload the page to see more options.', 'formidable' ) );
745
		wp_die();
746
	}
747
748
	/**
749
	 * @since 3.04.02
750
	 */
751
	private static function maybe_show_cred_form() {
752
		// Start output bufferring to catch the filesystem form if credentials are needed.
753
		ob_start();
754
755
		$show_form = false;
756
		$method    = '';
757
		$url       = add_query_arg( array( 'page' => 'formidable-settings' ), admin_url( 'admin.php' ) );
758
		$url       = esc_url_raw( $url );
759
		$creds     = request_filesystem_credentials( $url, $method, false, false, null );
760
761
		if ( false === $creds ) {
762
			$show_form = true;
763
		} elseif ( ! WP_Filesystem( $creds ) ) {
764
			request_filesystem_credentials( $url, $method, true, false, null );
765
			$show_form = true;
766
		}
767
768
		if ( $show_form ) {
769
			//$form = ob_get_clean();
770
			//TODO: test this: echo json_encode( array( 'form' => $form ) );
771
			echo json_encode( array( 'form' => __( 'Sorry, you\'re site requires FTP authentication. Please install plugins manaully.', 'formidable' ) ) );
772
			wp_die();
773
		}
774
775
		ob_end_clean();
776
	}
777
778
	/**
779
	 * We do not need any extra credentials if we have gotten this far,
780
	 * so let's install the plugin.
781
	 *
782
	 * @since 3.04.02
783
	 */
784
	private static function install_addon() {
785
		require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
786
787
		$download_url = FrmAppHelper::get_param( 'plugin', '', 'post', 'esc_url_raw' );
788
789
		// Create the plugin upgrader with our custom skin.
790
		$installer = new Plugin_Upgrader( new FrmInstallerSkin() );
791
		$installer->install( $download_url );
792
793
		// Flush the cache and return the newly installed plugin basename.
794
		wp_cache_flush();
795
796
		return $installer->plugin_info();
797
	}
798
799
	/**
800
	 * @since 3.06.03
801
	 */
802
	public static function ajax_activate_addon() {
803
804
		self::install_addon_permissions();
805
806
		// Set the current screen to avoid undefined notices.
807
		global $hook_suffix;
808
		set_current_screen();
809
810
		$plugin = FrmAppHelper::get_param( 'plugin', '', 'post', 'sanitize_text_field' );
811
		self::maybe_activate_addon( $plugin );
812
813
		// Send back a response.
814
		echo json_encode( __( 'Your plugin has been activated. Please reload the page to see more options.', 'formidable' ) );
815
		wp_die();
816
	}
817
818
	/**
819
	 * @since 3.04.02
820
	 * @param string $installed The plugin folder name with file name
821
	 */
822
	private static function maybe_activate_addon( $installed ) {
823
		if ( ! $installed ) {
824
			return;
825
		}
826
827
		$activate = activate_plugin( $installed );
828
		if ( is_wp_error( $activate ) ) {
829
			// Ignore the invalid header message that shows with nested plugins.
830
			if ( $activate->get_error_code() !== 'no_plugin_header' ) {
831
				echo json_encode( array( 'error' => $activate->get_error_message() ) );
832
				wp_die();
833
			}
834
		}
835
	}
836
837
	/**
838
	 * Run security checks before installing
839
	 *
840
	 * @since 3.04.02
841
	 */
842
	private static function install_addon_permissions() {
843
		check_ajax_referer( 'frm_ajax', 'nonce' );
844
845
		if ( ! current_user_can( 'activate_plugins' ) || ! isset( $_POST['plugin'] ) ) {
846
			echo json_encode( true );
847
			wp_die();
848
		}
849
	}
850
851
	/**
852
	 * @since 3.04.03
853
	 * @deprecated 3.06
854
	 * @codeCoverageIgnore
855
	 * @return array
856
	 */
857
	public static function error_for_license( $license ) {
858
		return FrmDeprecated::error_for_license( $license );
859
	}
860
861
	/**
862
	 * @since 3.04.03
863
	 * @deprecated 3.06
864
	 * @codeCoverageIgnore
865
	 */
866
	public static function get_pro_updater() {
867
		return FrmDeprecated::get_pro_updater();
868
	}
869
870
	/**
871
	 * @since 3.04.03
872
	 * @deprecated 3.06
873
	 * @codeCoverageIgnore
874
	 *
875
	 * @return array
876
	 */
877
	public static function get_addon_info( $license = '' ) {
878
		return FrmDeprecated::get_addon_info( $license );
879
	}
880
881
	/**
882
	 * @since 3.04.03
883
	 * @deprecated 3.06
884
	 * @codeCoverageIgnore
885
	 *
886
	 * @return string
887
	 */
888
	public static function get_cache_key( $license ) {
889
		return FrmDeprecated::get_cache_key( $license );
890
	}
891
892
	/**
893
	 * @since 3.04.03
894
	 * @deprecated 3.06
895
	 * @codeCoverageIgnore
896
	 */
897
	public static function reset_cached_addons( $license = '' ) {
898
		FrmDeprecated::reset_cached_addons( $license );
899
	}
900
901
	/**
902
	 * @since 2.03.08
903
	 * @deprecated 3.04.03
904
	 * @codeCoverageIgnore
905
	 *
906
	 * @param boolean $return
907
	 * @param string $package
908
	 *
909
	 * @return boolean
910
	 */
911
	public static function add_shorten_edd_filename_filter( $return, $package ) {
912
		return FrmDeprecated::add_shorten_edd_filename_filter( $return, $package );
913
	}
914
915
	/**
916
	 * @since 2.03.08
917
	 * @deprecated 3.04.03
918
	 * @codeCoverageIgnore
919
	 *
920
	 * @param string $filename
921
	 * @param string $ext
922
	 *
923
	 * @return string
924
	 */
925
	public static function shorten_edd_filename( $filename, $ext ) {
926
		return FrmDeprecated::shorten_edd_filename( $filename, $ext );
927
	}
928
929
	/**
930
	 * @deprecated 3.04.03
931
	 * @codeCoverageIgnore
932
	 */
933
	public static function get_licenses() {
934
		FrmDeprecated::get_licenses();
935
	}
936
}
937