Formidable Forms – Form Builder for WordPress - Version 4.06.02

Version Description

  • New: Added frm_field_value_object hook for making adjustments to the field before it's label and value is displayed.
  • New: Added frm_xml_response hook for altering the message/response when an XML file is imported.
  • Fix: Updated deprecated blacklist functions in WP 5.5.
  • Fix: Add more checks to the installation triggers to prevent them from being triggered at unintended times.
  • Show a more helpful error message in some cases when the XML import fails.
Download this release

Release Info

Developer sswells
Plugin Icon 128x128 Formidable Forms – Form Builder for WordPress
Version 4.06.02
Comparing to
See all releases

Code changes from version 4.06.01 to 4.06.02

classes/controllers/FrmAddonsController.php CHANGED
@@ -404,6 +404,10 @@ class FrmAddonsController {
404
  );
405
  }
406
 
 
 
 
 
407
  return $link;
408
  }
409
  }
@@ -850,6 +854,39 @@ class FrmAddonsController {
850
  wp_die();
851
  }
852
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
  /**
854
  * @since 3.04.02
855
  * @param string $installed The plugin folder name with file name
404
  );
405
  }
406
 
407
+ if ( ! empty( $link ) ) {
408
+ $link['status'] = $addon['status']['type'];
409
+ }
410
+
411
  return $link;
412
  }
413
  }
854
  wp_die();
855
  }
856
 
857
+ /**
858
+ * @since 4.06.02
859
+ */
860
+ public static function ajax_multiple_addons() {
861
+ self::install_addon_permissions();
862
+
863
+ // Set the current screen to avoid undefined notices.
864
+ global $hook_suffix;
865
+ set_current_screen();
866
+
867
+ $download_urls = FrmAppHelper::get_param( 'plugin', '', 'post' );
868
+ $download_urls = explode( ',', $download_urls );
869
+ FrmAppHelper::sanitize_value( 'esc_url_raw', $download_urls );
870
+
871
+ foreach ( $download_urls as $download_url ) {
872
+ $_POST['plugin'] = $download_url;
873
+ if ( strpos( $download_url, 'http' ) !== false ) {
874
+ // Installing.
875
+ self::maybe_show_cred_form();
876
+
877
+ $installed = self::install_addon();
878
+ self::maybe_activate_addon( $installed );
879
+ } else {
880
+ // Activating.
881
+ self::maybe_activate_addon( $download_url );
882
+ }
883
+ }
884
+
885
+ echo json_encode( __( 'Your plugins have been installed and activated.', 'formidable' ) );
886
+
887
+ wp_die();
888
+ }
889
+
890
  /**
891
  * @since 3.04.02
892
  * @param string $installed The plugin folder name with file name
classes/controllers/FrmAppController.php CHANGED
@@ -456,10 +456,22 @@ class FrmAppController {
456
  $args = array(
457
  'methods' => 'GET',
458
  'callback' => 'FrmAppController::api_install',
 
459
  );
 
460
  register_rest_route( 'frm-admin/v1', '/install', $args );
461
  }
462
 
 
 
 
 
 
 
 
 
 
 
463
  /**
464
  * Run silent upgrade on each site in the network during a network upgrade.
465
  * Update database settings for all sites in a network during network upgrade process.
@@ -469,7 +481,8 @@ class FrmAppController {
469
  * @param int $blog_id Blog ID.
470
  */
471
  public static function network_upgrade_site( $blog_id = 0 ) {
472
-
 
473
  $request = new WP_REST_Request( 'GET', '/frm-admin/v1/install' );
474
 
475
  if ( $blog_id ) {
@@ -490,6 +503,7 @@ class FrmAppController {
490
  * @since 3.0
491
  */
492
  public static function api_install() {
 
493
  if ( self::needs_update() ) {
494
  $running = get_option( 'frm_install_running' );
495
  if ( false === $running || $running < strtotime( '-5 minutes' ) ) {
456
  $args = array(
457
  'methods' => 'GET',
458
  'callback' => 'FrmAppController::api_install',
459
+ 'permission_callback' => __CLASS__ . '::can_update_db',
460
  );
461
+
462
  register_rest_route( 'frm-admin/v1', '/install', $args );
463
  }
464
 
465
+ /**
466
+ * Make sure the install is only being run when we tell it to.
467
+ * We don't want to run manually by people calling the API.
468
+ *
469
+ * @since 4.06.02
470
+ */
471
+ public static function can_update_db() {
472
+ return get_transient( 'frm_updating_api' );
473
+ }
474
+
475
  /**
476
  * Run silent upgrade on each site in the network during a network upgrade.
477
  * Update database settings for all sites in a network during network upgrade process.
481
  * @param int $blog_id Blog ID.
482
  */
483
  public static function network_upgrade_site( $blog_id = 0 ) {
484
+ // Flag to check if install is happening as intended.
485
+ set_transient( 'frm_updating_api', true, MINUTE_IN_SECONDS );
486
  $request = new WP_REST_Request( 'GET', '/frm-admin/v1/install' );
487
 
488
  if ( $blog_id ) {
503
  * @since 3.0
504
  */
505
  public static function api_install() {
506
+ delete_transient( 'frm_updating_api' );
507
  if ( self::needs_update() ) {
508
  $running = get_option( 'frm_install_running' );
509
  if ( false === $running || $running < strtotime( '-5 minutes' ) ) {
classes/controllers/FrmHooksController.php CHANGED
@@ -157,6 +157,7 @@ class FrmHooksController {
157
  add_action( 'wp_ajax_frm_addon_deactivate', 'FrmAddon::deactivate' );
158
  add_action( 'wp_ajax_frm_install_addon', 'FrmAddonsController::ajax_install_addon' );
159
  add_action( 'wp_ajax_frm_activate_addon', 'FrmAddonsController::ajax_activate_addon' );
 
160
  add_action( 'wp_ajax_frm_connect', 'FrmAddonsController::connect_pro' );
161
 
162
  // Fields Controller.
157
  add_action( 'wp_ajax_frm_addon_deactivate', 'FrmAddon::deactivate' );
158
  add_action( 'wp_ajax_frm_install_addon', 'FrmAddonsController::ajax_install_addon' );
159
  add_action( 'wp_ajax_frm_activate_addon', 'FrmAddonsController::ajax_activate_addon' );
160
+ add_action( 'wp_ajax_frm_multiple_addons', 'FrmAddonsController::ajax_multiple_addons' );
161
  add_action( 'wp_ajax_frm_connect', 'FrmAddonsController::connect_pro' );
162
 
163
  // Fields Controller.
classes/controllers/FrmSettingsController.php CHANGED
@@ -79,7 +79,7 @@ class FrmSettingsController {
79
  $show_licenses = false;
80
  $installed_addons = apply_filters( 'frm_installed_addons', array() );
81
  foreach ( $installed_addons as $installed_addon ) {
82
- if ( ! $installed_addon->is_parent_licence && $installed_addon->plugin_name != 'Formidable Pro' ) {
83
  $show_licenses = true;
84
  break;
85
  }
79
  $show_licenses = false;
80
  $installed_addons = apply_filters( 'frm_installed_addons', array() );
81
  foreach ( $installed_addons as $installed_addon ) {
82
+ if ( ! $installed_addon->is_parent_licence && $installed_addon->plugin_name != 'Formidable Pro' && $installed_addon->needs_license ) {
83
  $show_licenses = true;
84
  break;
85
  }
classes/controllers/FrmXMLController.php CHANGED
@@ -39,6 +39,9 @@ class FrmXMLController {
39
 
40
  $url = FrmAppHelper::get_param( 'xml', '', 'post', 'esc_url_raw' );
41
 
 
 
 
42
  $response = wp_remote_get( $url );
43
  $body = wp_remote_retrieve_body( $response );
44
  $xml = simplexml_load_string( $body );
@@ -63,16 +66,130 @@ class FrmXMLController {
63
  'redirect' => FrmForm::get_edit_link( $form_id ),
64
  'success' => 1,
65
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  } else {
 
 
 
 
 
67
  $response = array(
68
- 'message' => __( 'There was an error importing form', 'formidable' ),
69
  );
 
70
  }
71
 
 
 
72
  echo wp_json_encode( $response );
73
  wp_die();
74
  }
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  /**
77
  * Change the name of the last form that is not a child.
78
  * This will allow for lookup fields and embedded forms
@@ -87,6 +204,12 @@ class FrmXMLController {
87
  return;
88
  }
89
 
 
 
 
 
 
 
90
  // Get the main form ID.
91
  $set_name = 0;
92
  foreach ( $xml->form as $form ) {
@@ -98,8 +221,8 @@ class FrmXMLController {
98
  foreach ( $xml->form as $form ) {
99
  // Maybe set the form name if this isn't a child form.
100
  if ( $set_name == $form->id ) {
101
- $form->name = FrmAppHelper::get_param( 'name', '', 'post', 'sanitize_text_field' );
102
- $form->description = FrmAppHelper::get_param( 'desc', '', 'post', 'sanitize_textarea_field' );
103
  }
104
 
105
  // Use a unique key to prevent editing existing form.
39
 
40
  $url = FrmAppHelper::get_param( 'xml', '', 'post', 'esc_url_raw' );
41
 
42
+ $form = self::get_posted_form();
43
+ self::override_url( $form, $url );
44
+
45
  $response = wp_remote_get( $url );
46
  $body = wp_remote_retrieve_body( $response );
47
  $xml = simplexml_load_string( $body );
66
  'redirect' => FrmForm::get_edit_link( $form_id ),
67
  'success' => 1,
68
  );
69
+ if ( ! empty( $imported['imported']['posts'] ) ) {
70
+ // Return the link to the last page created.
71
+ $pages = $imported['posts'];
72
+ }
73
+
74
+ if ( ! empty( $form ) ) {
75
+ // Create selected pages with the correct shortcodes.
76
+ $pages = self::create_pages_for_import( $form );
77
+ }
78
+
79
+ if ( isset( $pages ) && ! empty( $pages ) ) {
80
+ $post_id = end( $pages );
81
+ $response['redirect'] = get_permalink( $post_id );
82
+ }
83
  } else {
84
+ if ( isset( $imported['error'] ) ) {
85
+ $message = $imported['error'];
86
+ } else {
87
+ $message = __( 'There was an error importing form', 'formidable' );
88
+ }
89
  $response = array(
90
+ 'message' => $message,
91
  );
92
+
93
  }
94
 
95
+ $response = apply_filters( 'frm_xml_response', $response, compact( 'form', 'imported' ) );
96
+
97
  echo wp_json_encode( $response );
98
  wp_die();
99
  }
100
 
101
+ /**
102
+ * @since 4.06.02
103
+ */
104
+ private static function get_posted_form() {
105
+ $form = FrmAppHelper::get_param( 'form', '', 'post', 'wp_unslash' );
106
+ if ( empty( $form ) ) {
107
+ return $form;
108
+ }
109
+ $form = json_decode( $form, true );
110
+ return $form;
111
+ }
112
+
113
+ /**
114
+ * Get a different URL depending on the selection in the form.
115
+ *
116
+ * @since 4.06.02
117
+ */
118
+ private static function override_url( $form, &$url ) {
119
+ $selected_form = self::get_selected_in_form( $form, 'form' );
120
+ if ( empty( $selected_form ) ) {
121
+ return;
122
+ }
123
+
124
+ $selected_xml = isset( $form['xml'] ) && isset( $form['xml'][ $selected_form ] ) ? $form['xml'][ $selected_form ] : '';
125
+ if ( empty( $selected_xml ) || strpos( $selected_xml, 'http' ) !== 0 ) {
126
+ return;
127
+ }
128
+
129
+ $url = $selected_xml;
130
+ }
131
+
132
+ /**
133
+ * @since 4.06.02
134
+ */
135
+ private static function get_selected_in_form( $form, $value = 'form' ) {
136
+ if ( ! empty( $form ) && isset( $form[ $value ] ) && ! empty( $form[ $value ] ) ) {
137
+ return $form[ $value ];
138
+ }
139
+
140
+ return '';
141
+ }
142
+
143
+ /**
144
+ * @since 4.06.02
145
+ *
146
+ * @param array $form The posted form values.
147
+ *
148
+ * @return array The array of created pages.
149
+ */
150
+ private static function create_pages_for_import( $form ) {
151
+ if ( ! isset( $form['pages'] ) || empty( $form['pages'] ) ) {
152
+ return;
153
+ }
154
+
155
+ $form_key = self::get_selected_in_form( $form, 'form' );
156
+ $view_keys = self::get_selected_in_form( $form, 'view' );
157
+
158
+ $page_ids = array();
159
+ foreach ( (array) $form['pages'] as $for => $name ) {
160
+ if ( empty( $name ) ) {
161
+ // Don't create a page if no title is given.
162
+ continue;
163
+ }
164
+
165
+ if ( $for === 'view' ) {
166
+ $item_key = is_array( $view_keys ) ? $view_keys[ $form_key ] : $view_keys;
167
+ $shortcode = '[display-frm-data id=%1$s filter=limited]';
168
+ } elseif ( $for === 'form' ) {
169
+ $item_key = $form_key;
170
+ $shortcode = '[formidable id=%1$s]';
171
+ } else {
172
+ $item_key = self::get_selected_in_form( $form, 'form' );
173
+ $shortcode = '[' . esc_html( $for ) . ' id=%1$s]';
174
+ }
175
+
176
+ if ( empty( $item_key ) ) {
177
+ // Don't create it if the shortcode won't show anything.
178
+ continue;
179
+ }
180
+
181
+ $page_ids[ $for ] = wp_insert_post(
182
+ array(
183
+ 'post_title' => $name,
184
+ 'post_type' => 'page',
185
+ 'post_content' => sprintf( $shortcode, $item_key ),
186
+ )
187
+ );
188
+ }
189
+
190
+ return $page_ids;
191
+ }
192
+
193
  /**
194
  * Change the name of the last form that is not a child.
195
  * This will allow for lookup fields and embedded forms
204
  return;
205
  }
206
 
207
+ $name = FrmAppHelper::get_param( 'name', '', 'post', 'sanitize_text_field' );
208
+ $description = FrmAppHelper::get_param( 'desc', '', 'post', 'sanitize_textarea_field' );
209
+ if ( empty( $name ) && empty( $description ) ) {
210
+ return;
211
+ }
212
+
213
  // Get the main form ID.
214
  $set_name = 0;
215
  foreach ( $xml->form as $form ) {
221
  foreach ( $xml->form as $form ) {
222
  // Maybe set the form name if this isn't a child form.
223
  if ( $set_name == $form->id ) {
224
+ $form->name = $name;
225
+ $form->description = $description;
226
  }
227
 
228
  // Use a unique key to prevent editing existing form.
classes/helpers/FrmAppHelper.php CHANGED
@@ -11,7 +11,7 @@ class FrmAppHelper {
11
  /**
12
  * @since 2.0
13
  */
14
- public static $plug_version = '4.06.01';
15
 
16
  /**
17
  * @since 1.07.02
@@ -82,6 +82,7 @@ class FrmAppHelper {
82
  if ( empty( $page ) ) {
83
  $page = 'https://formidableforms.com/lite-upgrade/';
84
  } else {
 
85
  $page = 'https://formidableforms.com/' . $page;
86
  }
87
 
@@ -201,6 +202,14 @@ class FrmAppHelper {
201
  return apply_filters( 'frm_pro_installed', false );
202
  }
203
 
 
 
 
 
 
 
 
 
204
  /**
205
  * @since 4.06
206
  */
@@ -732,6 +741,10 @@ class FrmAppHelper {
732
  'width' => true,
733
  'x' => true,
734
  'y' => true,
 
 
 
 
735
  ),
736
  'section' => $allow_class,
737
  'span' => array(
@@ -755,6 +768,7 @@ class FrmAppHelper {
755
  'width' => true,
756
  'height' => true,
757
  'style' => true,
 
758
  ),
759
  'use' => array(
760
  'href' => true,
11
  /**
12
  * @since 2.0
13
  */
14
+ public static $plug_version = '4.06.02';
15
 
16
  /**
17
  * @since 1.07.02
82
  if ( empty( $page ) ) {
83
  $page = 'https://formidableforms.com/lite-upgrade/';
84
  } else {
85
+ $page = str_replace( 'https://formidableforms.com/', '', $page );
86
  $page = 'https://formidableforms.com/' . $page;
87
  }
88
 
202
  return apply_filters( 'frm_pro_installed', false );
203
  }
204
 
205
+ /**
206
+ * @since 4.06.02
207
+ */
208
+ public static function pro_is_connected() {
209
+ global $frm_vars;
210
+ return self::pro_is_installed() && $frm_vars['pro_is_authorized'];
211
+ }
212
+
213
  /**
214
  * @since 4.06
215
  */
741
  'width' => true,
742
  'x' => true,
743
  'y' => true,
744
+ 'rx' => true,
745
+ 'stroke' => true,
746
+ 'stroke-opacity' => true,
747
+ 'stroke-width' => true,
748
  ),
749
  'section' => $allow_class,
750
  'span' => array(
768
  'width' => true,
769
  'height' => true,
770
  'style' => true,
771
+ 'fill' => true,
772
  ),
773
  'use' => array(
774
  'href' => true,
classes/helpers/FrmFormsHelper.php CHANGED
@@ -1357,11 +1357,15 @@ BEFORE_HTML;
1357
  return false;
1358
  }
1359
 
1360
- $plans = array( 'free', 'Personal', 'Business', 'Elite' );
1361
 
1362
  foreach ( $item['categories'] as $k => $category ) {
1363
  if ( in_array( $category, $plans ) ) {
1364
  unset( $item['categories'][ $k ] );
 
 
 
 
1365
  return $category;
1366
  }
1367
  }
1357
  return false;
1358
  }
1359
 
1360
+ $plans = array( 'free', 'Basic', 'Personal', 'Business', 'Elite' );
1361
 
1362
  foreach ( $item['categories'] as $k => $category ) {
1363
  if ( in_array( $category, $plans ) ) {
1364
  unset( $item['categories'][ $k ] );
1365
+ if ( $category === 'Personal' ) {
1366
+ // Show the current package name.
1367
+ $category = 'Basic';
1368
+ }
1369
  return $category;
1370
  }
1371
  }
classes/helpers/FrmXMLHelper.php CHANGED
@@ -59,6 +59,10 @@ class FrmXMLHelper {
59
  * @return array The number of items imported
60
  */
61
  public static function import_xml_now( $xml ) {
 
 
 
 
62
  $imported = self::pre_import_data();
63
 
64
  foreach ( array( 'term', 'form', 'view' ) as $item_type ) {
@@ -70,7 +74,16 @@ class FrmXMLHelper {
70
  }
71
  }
72
 
73
- return apply_filters( 'frm_importing_xml', $imported, $xml );
 
 
 
 
 
 
 
 
 
74
  }
75
 
76
  /**
59
  * @return array The number of items imported
60
  */
61
  public static function import_xml_now( $xml ) {
62
+ if ( ! defined( 'WP_IMPORTING' ) ) {
63
+ define( 'WP_IMPORTING', true );
64
+ }
65
+
66
  $imported = self::pre_import_data();
67
 
68
  foreach ( array( 'term', 'form', 'view' ) as $item_type ) {
74
  }
75
  }
76
 
77
+ $imported = apply_filters( 'frm_importing_xml', $imported, $xml );
78
+
79
+ if ( ! isset( $imported['form_status'] ) || empty( $imported['form_status'] ) ) {
80
+ // Check for an error message in the XML.
81
+ if ( isset( $xml->Code ) && isset( $xml->Message ) ) { // phpcs:ignore WordPress.NamingConventions
82
+ $imported['error'] = reset( $xml->Message ); // phpcs:ignore WordPress.NamingConventions
83
+ }
84
+ }
85
+
86
+ return $imported;
87
  }
88
 
89
  /**
classes/models/FrmAddon.php CHANGED
@@ -15,6 +15,7 @@ class FrmAddon {
15
  public $version;
16
  public $author = 'Strategy11';
17
  public $is_parent_licence = false;
 
18
  private $is_expired_addon = false;
19
  public $license;
20
  protected $get_beta = false;
15
  public $version;
16
  public $author = 'Strategy11';
17
  public $is_parent_licence = false;
18
+ public $needs_license = true;
19
  private $is_expired_addon = false;
20
  public $license;
21
  protected $get_beta = false;
classes/models/FrmEmail.php CHANGED
@@ -331,6 +331,7 @@ class FrmEmail {
331
  $args = array(
332
  'entry' => $this->entry,
333
  'email_key' => $this->email_key,
 
334
  );
335
 
336
  $this->attachments = apply_filters( 'frm_notification_attachment', array(), $this->form, $args );
331
  $args = array(
332
  'entry' => $this->entry,
333
  'email_key' => $this->email_key,
334
+ 'settings' => $this->settings,
335
  );
336
 
337
  $this->attachments = apply_filters( 'frm_notification_attachment', array(), $this->form, $args );
classes/models/FrmEntryValidate.php CHANGED
@@ -233,7 +233,7 @@ class FrmEntryValidate {
233
  }
234
 
235
  if ( self::blacklist_check( $values ) ) {
236
- $errors['spam'] = __( 'Your entry appears to be blacklist spam!', 'formidable' );
237
  }
238
 
239
  if ( self::is_akismet_spam( $values ) ) {
@@ -272,7 +272,7 @@ class FrmEntryValidate {
272
  return false;
273
  }
274
 
275
- $mod_keys = trim( get_option( 'blacklist_keys' ) );
276
  if ( empty( $mod_keys ) ) {
277
  return false;
278
  }
@@ -286,7 +286,34 @@ class FrmEntryValidate {
286
  $user_agent = FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' );
287
  $user_info = self::get_spam_check_user_info( $values );
288
 
289
- return wp_blacklist_check( $user_info['comment_author'], $user_info['comment_author_email'], $user_info['comment_author_url'], $content, $ip, $user_agent );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  }
291
 
292
  /**
233
  }
234
 
235
  if ( self::blacklist_check( $values ) ) {
236
+ $errors['spam'] = __( 'Your entry appears to be blocked spam!', 'formidable' );
237
  }
238
 
239
  if ( self::is_akismet_spam( $values ) ) {
272
  return false;
273
  }
274
 
275
+ $mod_keys = trim( self::get_disallowed_words() );
276
  if ( empty( $mod_keys ) ) {
277
  return false;
278
  }
286
  $user_agent = FrmAppHelper::get_server_value( 'HTTP_USER_AGENT' );
287
  $user_info = self::get_spam_check_user_info( $values );
288
 
289
+ return self::check_disallowed_words( $user_info['comment_author'], $user_info['comment_author_email'], $user_info['comment_author_url'], $content, $ip, $user_agent );
290
+ }
291
+
292
+ /**
293
+ * For WP 5.5 compatibility.
294
+ *
295
+ * @since 4.06.02
296
+ */
297
+ private static function check_disallowed_words( $author, $email, $url, $content, $ip, $user_agent ) {
298
+ if ( function_exists( 'wp_check_comment_disallowed_list' ) ) {
299
+ return wp_check_comment_disallowed_list( $author, $email, $url, $content, $ip, $user_agent );
300
+ } else {
301
+ return wp_blacklist_check( $author, $email, $url, $content, $ip, $user_agent );
302
+ }
303
+ }
304
+
305
+ /**
306
+ * For WP 5.5 compatibility.
307
+ *
308
+ * @since 4.06.02
309
+ */
310
+ private static function get_disallowed_words() {
311
+ $keys = get_option( 'disallowed_keys' );
312
+ if ( false === $keys ) {
313
+ // Fallback for WP < 5.5.
314
+ $keys = get_option( 'blacklist_keys' );
315
+ }
316
+ return $keys;
317
  }
318
 
319
  /**
classes/models/FrmField.php CHANGED
@@ -51,7 +51,7 @@ class FrmField {
51
  'icon' => 'frm_icon_font frm_code_icon',
52
  ),
53
  'hidden' => array(
54
- 'name' => __( 'Hidden Field', 'formidable' ),
55
  'icon' => 'frm_icon_font frm_eye_slash_icon',
56
  ),
57
  'user_id' => array(
51
  'icon' => 'frm_icon_font frm_code_icon',
52
  ),
53
  'hidden' => array(
54
+ 'name' => __( 'Hidden', 'formidable' ),
55
  'icon' => 'frm_icon_font frm_eye_slash_icon',
56
  ),
57
  'user_id' => array(
classes/models/FrmFieldValue.php CHANGED
@@ -53,6 +53,7 @@ class FrmFieldValue {
53
 
54
  $this->entry = $entry;
55
  $this->entry_id = $entry->id;
 
56
  $this->field = $field;
57
  $this->init_saved_value( $entry );
58
  }
53
 
54
  $this->entry = $entry;
55
  $this->entry_id = $entry->id;
56
+ $field = apply_filters( 'frm_field_value_object', $field );
57
  $this->field = $field;
58
  $this->init_saved_value( $entry );
59
  }
classes/models/FrmFormAction.php CHANGED
@@ -712,6 +712,11 @@ class FrmFormAction {
712
  }
713
 
714
  public static function action_conditions_met( $action, $entry ) {
 
 
 
 
 
715
  $notification = $action->post_content;
716
  $stop = false;
717
  $met = array();
@@ -755,6 +760,7 @@ class FrmFormAction {
755
  * Prepare the logic value for comparison against the entered value
756
  *
757
  * @since 2.01.02
 
758
  *
759
  * @param array|string $logic_value
760
  */
@@ -779,6 +785,7 @@ class FrmFormAction {
779
  * Get the value from a specific field and entry
780
  *
781
  * @since 2.01.02
 
782
  *
783
  * @param object $entry
784
  * @param int $field_id
712
  }
713
 
714
  public static function action_conditions_met( $action, $entry ) {
715
+ if ( is_callable( 'FrmProFormActionsController::action_conditions_met' ) ) {
716
+ return FrmProFormActionsController::action_conditions_met( $action, $entry );
717
+ }
718
+
719
+ // This is here for reverse compatibility.
720
  $notification = $action->post_content;
721
  $stop = false;
722
  $met = array();
760
  * Prepare the logic value for comparison against the entered value
761
  *
762
  * @since 2.01.02
763
+ * @deprecated 4.06.02
764
  *
765
  * @param array|string $logic_value
766
  */
785
  * Get the value from a specific field and entry
786
  *
787
  * @since 2.01.02
788
+ * @deprecated 4.06.02
789
  *
790
  * @param object $entry
791
  * @param int $field_id
classes/models/FrmSolution.php ADDED
@@ -0,0 +1,804 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Handles the installation of a solution and any dependencies.
4
+ * This page is shown when a Formidable plugin is activated.
5
+ *
6
+ * @since 4.06.02
7
+ */
8
+
9
+ if ( ! defined( 'ABSPATH' ) ) {
10
+ die( 'You are not allowed to call this page directly.' );
11
+ }
12
+
13
+ class FrmSolution {
14
+
15
+ protected $plugin_slug = '';
16
+
17
+ protected $plugin_file = '';
18
+
19
+ /**
20
+ * Hidden welcome page slug.
21
+ *
22
+ * @since 4.06.02
23
+ */
24
+ protected $page = '';
25
+
26
+ protected $icon = 'frm_icon_font frm_settings_icon';
27
+
28
+ public function __construct( $atts = array() ) {
29
+ if ( empty( $this->plugin_slug ) ) {
30
+ return;
31
+ }
32
+
33
+ add_action( 'plugins_loaded', array( $this, 'load_hooks' ), 50 );
34
+ add_action( 'admin_init', array( $this, 'redirect' ), 9999 );
35
+
36
+ if ( empty( $this->plugin_file ) ) {
37
+ $this->plugin_file = $this->plugin_slug . '.php';
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Register all WP hooks.
43
+ *
44
+ * @since 4.06.02
45
+ */
46
+ public function load_hooks() {
47
+ // If user is in admin ajax or doing cron, return.
48
+ if ( wp_doing_cron() ) {
49
+ return;
50
+ }
51
+
52
+ add_filter( 'frm_add_settings_section', array( $this, 'add_settings' ) );
53
+
54
+ if ( wp_doing_ajax() ) {
55
+ return;
56
+ }
57
+
58
+ // If user cannot manage_options, return.
59
+ if ( ! current_user_can( 'frm_change_settings' ) && ! FrmAppHelper::is_formidable_admin() ) {
60
+ return;
61
+ }
62
+
63
+ add_filter( 'plugin_action_links_' . $this->plugin_slug . '/' . $this->plugin_file, array( $this, 'plugin_links' ) );
64
+ add_action( 'admin_menu', array( $this, 'register' ) );
65
+ add_action( 'admin_head', array( $this, 'hide_menu' ) );
66
+ }
67
+
68
+ public function plugin_links( $links ) {
69
+ if ( ! $this->is_complete() ) {
70
+ $settings = '<a href="' . esc_url( $this->settings_link() ) . '">' . __( 'Setup', 'formidable' ) . '</a>';
71
+ array_unshift( $links, $settings );
72
+ }
73
+
74
+ return $links;
75
+ }
76
+
77
+ /**
78
+ * Register the pages to be used for the Welcome screen (and tabs).
79
+ *
80
+ * These pages will be removed from the Dashboard menu, so they will
81
+ * not actually show. Sneaky, sneaky.
82
+ *
83
+ * @since 4.06.02
84
+ */
85
+ public function register() {
86
+
87
+ // Getting started - shows after installation.
88
+ add_dashboard_page(
89
+ esc_html( $this->page_title() ),
90
+ esc_html( $this->page_title() ),
91
+ 'frm_change_settings',
92
+ $this->page,
93
+ array( $this, 'output' )
94
+ );
95
+ }
96
+
97
+ /**
98
+ * Removed the dashboard pages from the admin menu.
99
+ *
100
+ * This means the pages are still available to us, but hidden.
101
+ *
102
+ * @since 4.06.02
103
+ */
104
+ public function hide_menu() {
105
+ remove_submenu_page( 'index.php', $this->page );
106
+ }
107
+
108
+ protected function plugin_name() {
109
+ return '';
110
+ }
111
+
112
+ protected function page_title() {
113
+ return __( 'Welcome to Formidable Forms', 'formidable' );
114
+ }
115
+
116
+ protected function page_description() {
117
+ return __( 'Follow the steps below to get started.', 'formidable' );
118
+ }
119
+
120
+ /**
121
+ * Welcome screen redirect.
122
+ *
123
+ * This function checks if a new install or update has just occurred. If so,
124
+ * then we redirect the user to the appropriate page.
125
+ *
126
+ * @since 4.06.02
127
+ */
128
+ public function redirect() {
129
+
130
+ $current_page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
131
+ if ( $current_page === $this->page ) {
132
+ // Prevent endless loop.
133
+ return;
134
+ }
135
+
136
+ // Only do this for single site installs.
137
+ if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) { // WPCS: CSRF ok.
138
+ return;
139
+ }
140
+
141
+ // Check if we should consider redirection.
142
+ if ( ! $this->is_current_plugin() ) {
143
+ return;
144
+ }
145
+
146
+ delete_transient( 'frm_activation_redirect' );
147
+
148
+ // Initial install.
149
+ wp_safe_redirect( $this->settings_link() );
150
+ exit;
151
+ }
152
+
153
+ protected function settings_link() {
154
+ return admin_url( 'index.php?page=' . $this->page );
155
+ }
156
+
157
+ /*
158
+ * Add page to global settings.
159
+ */
160
+ public static function add_settings( $sections ) {
161
+ wp_enqueue_style( 'formidable-pro-fields' );
162
+ $sections[ $this->plugin_slug ] = array(
163
+ 'class' => $this,
164
+ 'function' => 'settings_page',
165
+ 'name' => $this->plugin_name(),
166
+ 'icon' => $this->icon,
167
+ 'ajax' => true,
168
+ );
169
+ return $sections;
170
+ }
171
+
172
+ /*
173
+ * Output for global settings.
174
+ */
175
+ public static function settings_page() {
176
+ $steps = $this->get_steps_data();
177
+ if ( ! $steps['license']['complete'] ) {
178
+ $this->license_box( $steps['license'] );
179
+ }
180
+
181
+ if ( isset( $steps['plugin'] ) && ! $steps['license']['complete'] ) {
182
+ $this->show_plugin_install( $steps['plugin'] );
183
+ }
184
+
185
+ $all_imported = $this->is_complete( 'all' );
186
+
187
+ $step = $steps['import'];
188
+ $step['label'] = '';
189
+ $step['nested'] = true;
190
+ if ( $steps['complete']['current'] ) {
191
+ // Always show this step in settings.
192
+ $step['current'] = true;
193
+
194
+ $new_class = $all_imported ? ' button frm_hidden' : '';
195
+ $step['button_class'] = str_replace( 'frm_grey disabled', $new_class, $step['button_class'] );
196
+ }
197
+ if ( $all_imported ) {
198
+ $step['description'] = __( 'The following form(s) have been created.', 'formidable' );
199
+ }
200
+ $this->show_app_install( $step );
201
+
202
+ if ( ! $all_imported ) {
203
+ $step = $steps['complete'];
204
+ $step['current'] = false;
205
+ $step['button_class'] .= ' frm_grey disabled';
206
+ $this->show_page_links( $step );
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Getting Started screen. Shows after first install.
212
+ */
213
+ public function output() {
214
+ FrmAppHelper::include_svg();
215
+ $this->css();
216
+ $class = FrmAppHelper::pro_is_installed() ? 'pro' : 'lite';
217
+
218
+ echo '<div id="frm-welcome" class="wrap frm-wrap frm-admin-plugin-landing upgrade_to_pro ' . sanitize_html_class( $class ) . '">';
219
+
220
+ $this->header();
221
+ $this->main_content();
222
+
223
+ echo '</div>';
224
+ }
225
+
226
+ /**
227
+ * Heading section.
228
+ */
229
+ protected function header() {
230
+ $size = array(
231
+ 'height' => 90,
232
+ 'width' => 90,
233
+ );
234
+
235
+ ?>
236
+ <section class="top">
237
+ <div class="frm-smtp-logos">
238
+ <?php FrmAppHelper::show_logo( $size ); ?>
239
+ <?php
240
+ FrmAppHelper::icon_by_class(
241
+ 'frmfont frm_arrow_right_icon',
242
+ array(
243
+ 'aria-label' => 'Install',
244
+ 'style' => 'width:30px;height:30px;margin:0 35px;',
245
+ )
246
+ );
247
+ FrmAppHelper::icon_by_class(
248
+ 'frmfont frm_wordpress_icon',
249
+ array(
250
+ 'aria-label' => 'WordPress',
251
+ 'style' => 'width:90px;height:90px;',
252
+ )
253
+ );
254
+ ?>
255
+ </div>
256
+ <h1><?php echo esc_html( $this->page_title() ); ?></h1>
257
+ <p><?php echo esc_html( $this->page_description() ); ?></p>
258
+ </section>
259
+ <?php
260
+ }
261
+
262
+ /**
263
+ * This is the welcome page content.
264
+ * Override me to insert different content.
265
+ */
266
+ protected function main_content() {
267
+ $steps = $this->get_steps_data();
268
+ $this->license_box( $steps['license'] );
269
+ if ( isset( $steps['plugin'] ) ) {
270
+ $this->show_plugin_install( $steps['plugin'] );
271
+ }
272
+ $this->show_app_install( $steps['import'] );
273
+ $this->show_page_links( $steps['complete'] );
274
+ }
275
+
276
+ protected function get_steps_data() {
277
+ $pro_installed = FrmAppHelper::pro_is_connected();
278
+
279
+ $steps = array(
280
+ 'license' => array(
281
+ 'label' => __( 'Connect to FormidableForms.com', 'formidable' ),
282
+ 'description' => __( 'Create a connection to get plugin downloads.', 'formidable' ),
283
+ 'button_label' => __( 'Connect an Account', 'formidable' ),
284
+ 'current' => empty( $pro_installed ),
285
+ 'complete' => $pro_installed,
286
+ 'num' => 1,
287
+ ),
288
+ 'plugin' => array(
289
+ 'label' => __( 'Install and Activate Add-Ons', 'formidable' ),
290
+ 'description' => __( 'Install any required add-ons from FormidableForms.com.', 'formidable' ),
291
+ 'button_label' => __( 'Install & Activate', 'formidable' ),
292
+ 'current' => false,
293
+ 'complete' => false,
294
+ 'num' => 2,
295
+ ),
296
+ 'import' => array(
297
+ 'label' => __( 'Setup Forms, Views, and Pages', 'formidable' ),
298
+ 'description' => __( 'Build the forms, views, and pages automatically.', 'formidable' ),
299
+ 'button_label' => __( 'Create Now', 'formidable' ),
300
+ 'complete' => $this->is_complete(),
301
+ 'num' => 3,
302
+ ),
303
+ 'complete' => array(
304
+ 'label' => __( 'Customize Your New Pages', 'formidable' ),
305
+ 'description' => __( 'Make any required changes and publish the page.', 'formidable' ),
306
+ 'button_label' => __( 'View Page', 'formidable' ),
307
+ 'complete' => false,
308
+ 'num' => 4,
309
+ ),
310
+ );
311
+
312
+ $this->adjust_plugin_install_step( $steps );
313
+
314
+ $has_current = false;
315
+ foreach ( $steps as $k => $step ) {
316
+ // Set the current step.
317
+ if ( ! isset( $step['current'] ) ) {
318
+ if ( $step['complete'] ) {
319
+ $steps[ $k ]['current'] = false;
320
+ } else {
321
+ $steps[ $k ]['current'] = ! $has_current;
322
+ $has_current = true;
323
+ }
324
+ } elseif ( $step['current'] ) {
325
+ $has_current = true;
326
+ }
327
+
328
+ // Set disabled buttons.
329
+ $class = isset( $step['button_class'] ) ? $step['button_class'] : '';
330
+ $class .= ' button-primary frm-button-primary';
331
+ if ( ! $steps[ $k ]['current'] ) {
332
+ $class .= ' frm_grey disabled';
333
+ }
334
+ $steps[ $k ]['button_class'] = $class;
335
+ }
336
+
337
+ return $steps;
338
+ }
339
+
340
+ protected function adjust_plugin_install_step( &$steps ) {
341
+ $plugins = $this->required_plugins();
342
+ if ( empty( $plugins ) ) {
343
+ unset( $steps['plugin'] );
344
+ $steps['import']['num'] = 2;
345
+ $steps['complete']['num'] = 3;
346
+ return;
347
+ }
348
+
349
+ $missing = array();
350
+ $rel = array();
351
+ foreach ( $plugins as $plugin_key ) {
352
+ $plugin = FrmAddonsController::install_link( $plugin_key );
353
+ if ( $plugin['status'] === 'active' ) {
354
+ continue;
355
+ }
356
+ $links[ $plugin_key ] = $plugin;
357
+ if ( isset( $plugin['url'] ) ) {
358
+ $rel[] = $plugin['url'];
359
+ } else {
360
+ // Add-on is required but not allowed.
361
+ $missing[] = $plugin_key;
362
+ }
363
+ }
364
+ if ( empty( $rel ) && empty( $missing ) ) {
365
+ $steps['plugin']['complete'] = true;
366
+ } elseif ( ! empty( $missing ) ) {
367
+ $steps['plugin']['error'] = sprintf(
368
+ /* translators: %1$s: Plugin name */
369
+ esc_html__( 'You need permission to download the Formidable %1$s plugin', 'formidable' ),
370
+ implode( ', ', $missing )
371
+ );
372
+ } else {
373
+ $steps['plugin']['links'] = $rel;
374
+ $steps['plugin']['button_class'] = 'frm-solution-multiple ';
375
+ }
376
+
377
+ if ( $steps['license']['complete'] && ! $steps['plugin']['complete'] ) {
378
+ $steps['plugin']['current'] = true;
379
+ }
380
+ }
381
+
382
+ protected function step_top( $step ) {
383
+ $section_class = ( ! isset( $step['current'] ) || ! $step['current'] ) ? 'frm_grey' : '';
384
+
385
+ ?>
386
+ <section class="step step-install <?php echo esc_attr( $section_class ); ?>">
387
+ <aside class="num">
388
+ <?php
389
+ if ( isset( $step['complete'] ) && $step['complete'] ) {
390
+ FrmAppHelper::icon_by_class(
391
+ 'frmfont frm_step_complete_icon',
392
+ array(
393
+ /* translators: %1$s: Step number */
394
+ 'aria-label' => sprintf( __( 'Step %1$d', 'formidable' ), $step['num'] ),
395
+ 'style' => 'width:50px;height:50px;',
396
+ )
397
+ );
398
+ } else {
399
+ ?>
400
+ <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 100 100"><circle cx="50" cy="50" r="50" fill="#ccc"/><text x="50%" y="50%" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="2px" dy=".3em" font-size="3.7em"><?php echo esc_html( $step['num'] ); ?></text></svg>
401
+ <?php
402
+ }
403
+ ?>
404
+ <i class="loader hidden"></i>
405
+ </aside>
406
+ <div>
407
+ <?php if ( $step['label'] ) { ?>
408
+ <h3 class="frm-step-heading"><?php echo esc_html( $step['label'] ); ?></h3>
409
+ <?php } ?>
410
+ <p><?php echo esc_html( $step['description'] ); ?></p>
411
+ <?php if ( isset( $step['error'] ) ) { ?>
412
+ <p class="frm_error"><?php echo esc_html( $step['error'] ); ?></p>
413
+ <?php } ?>
414
+ <?php
415
+ }
416
+
417
+ protected function step_bottom( $step ) {
418
+ ?>
419
+ </div>
420
+ </section>
421
+ <?php
422
+ }
423
+
424
+ /**
425
+ * Generate and output Connect step section HTML.
426
+ */
427
+ protected function license_box( $step ) {
428
+ $this->step_top( $step );
429
+
430
+ if ( $step['complete'] ) {
431
+ ?>
432
+ <a href="#" class="<?php echo esc_attr( $step['button_class'] ); ?>">
433
+ <?php echo esc_html( $step['button_label'] ); ?>
434
+ </a>
435
+ <?php
436
+ } else {
437
+ FrmSettingsController::license_box();
438
+ }
439
+
440
+ $this->step_bottom( $step );
441
+ }
442
+
443
+ protected function show_plugin_install( $step ) {
444
+ $this->step_top( $step );
445
+
446
+ if ( ! isset( $step['error'] ) ) {
447
+ $rel = isset( $step['links'] ) ? $step['links'] : array();
448
+
449
+ ?>
450
+ <a rel="<?php echo esc_attr( implode( ',', $rel ) ); ?>" class="<?php echo esc_attr( $step['button_class'] ); ?>">
451
+ <?php echo esc_html( $step['button_label'] ); ?>
452
+ </a>
453
+ <?php
454
+ }
455
+
456
+ $this->step_bottom( $step );
457
+ }
458
+
459
+ protected function show_app_install( $step ) {
460
+ $is_complete = $step['complete'];
461
+ if ( ! empty( $this->form_options() ) && ! $is_complete ) {
462
+ $step['description'] = __( 'Select the form or view you would like to create.', 'formidable' );
463
+ }
464
+
465
+ $this->step_top( $step );
466
+
467
+ $api = new FrmFormApi();
468
+ $addons = $api->get_api_info();
469
+
470
+ $id = $this->download_id();
471
+ $has_file = isset( $addons[ $id ] ) && isset( $addons[ $id ]['beta'] );
472
+
473
+ if ( ! $step['current'] ) {
474
+ ?>
475
+ <a href="#" class="<?php echo esc_attr( $step['button_class'] ); ?>">
476
+ <?php echo esc_html( $step['button_label'] ); ?>
477
+ </a>
478
+ <?php
479
+
480
+ $this->step_bottom( $step );
481
+ return;
482
+ }
483
+
484
+ if ( ! $has_file ) {
485
+ echo '<p class="frm_error_style">' . esc_html__( 'We didn\'t find anything to import. Please contact our team.', 'formidable' ) . '</p>';
486
+ } elseif ( ! isset( $addons[ $id ]['beta']['package'] ) ) {
487
+ echo '<p class="frm_error_style">' . esc_html__( 'Looks like you may not have a current subscription for this solution. Please check your account.', 'formidable' ) . '</p>';
488
+ } else {
489
+ $xml = $addons[ $id ]['beta']['package'];
490
+ if ( is_array( $xml ) ) {
491
+ $xml = reset( $xml );
492
+ }
493
+
494
+ if ( isset( $step['nested'] ) ) {
495
+ echo '<fieldset id="frm-new-template" class="field-group">';
496
+ } else {
497
+ echo '<form name="frm-new-template" id="frm-new-template" method="post" class="field-group">';
498
+ }
499
+
500
+ ?>
501
+ <input type="hidden" name="link" id="frm_link" value="<?php echo esc_attr( $xml ); ?>" />
502
+ <input type="hidden" name="type" id="frm_action_type" value="frm_install_template" />
503
+ <input type="hidden" name="template_name" id="frm_template_name" value="" />
504
+ <input type="hidden" name="template_desc" id="frm_template_desc" value="" />
505
+ <input type="hidden" name="redirect" value="0" />
506
+ <input type="hidden" name="show_response" value="frm_install_error" />
507
+ <?php
508
+ $this->show_form_options( $xml );
509
+ $this->show_view_options();
510
+
511
+ if ( ! $this->is_complete( 'all' ) ) {
512
+ // Don't show on the settings page when complete.
513
+ $this->show_page_options();
514
+ }
515
+ ?>
516
+ <p>
517
+ <button <?php echo esc_html( isset( $step['nested'] ) ? '' : 'type="submit" ' ); ?>class="<?php echo esc_attr( $step['button_class'] ); ?>">
518
+ <?php echo esc_html( $step['button_label'] ); ?>
519
+ </button>
520
+ </p>
521
+ <p id="frm_install_error" class="frm_error_style frm_hidden"></p>
522
+ <?php
523
+ if ( isset( $step['nested'] ) ) {
524
+ echo '</fieldset>';
525
+ } else {
526
+ echo '</form>';
527
+ }
528
+ }
529
+
530
+ $this->step_bottom( $step );
531
+ }
532
+
533
+ protected function show_form_options( $xml ) {
534
+ $this->show_import_options( $this->form_options(), 'form', $xml );
535
+ }
536
+
537
+ protected function show_view_options() {
538
+ $this->show_import_options( $this->view_options(), 'view' );
539
+ }
540
+
541
+ protected function show_import_options( $options, $importing, $xml = '' ) {
542
+ if ( empty( $options ) ) {
543
+ return;
544
+ }
545
+
546
+ $imported = $this->previously_imported_forms();
547
+ $count = count( $options );
548
+ foreach ( $options as $info ) {
549
+ // Count the number of options displayed for css.
550
+ if ( $count > 1 && ! isset( $info['img'] ) ) {
551
+ $count --;
552
+ }
553
+ }
554
+ $width = floor( ( 533 - ( ( $count - 1 ) * 20 ) ) / $count );
555
+ unset( $count );
556
+
557
+ $selected = false;
558
+
559
+ include( FrmAppHelper::plugin_path() . '/classes/views/solutions/_import.php' );
560
+ }
561
+
562
+ protected function show_page_options() {
563
+ $pages = $this->needed_pages();
564
+ if ( empty( $pages ) ) {
565
+ return;
566
+ }
567
+
568
+ echo '<h3>Choose New Page Title</h3>';
569
+ foreach ( $pages as $page ) {
570
+ ?>
571
+ <p>
572
+ <label for="pages_<?php echo esc_html( $page['type'] ); ?>">
573
+ <?php echo esc_html( $page['label'] ); ?>
574
+ </label>
575
+ <input type="text" name="pages[<?php echo esc_html( $page['type'] ); ?>]" value="<?php echo esc_attr( $page['name'] ); ?>" id="pages_<?php echo esc_html( $page['type'] ); ?>" required />
576
+ </p>
577
+ <?php
578
+ }
579
+ }
580
+
581
+ protected function show_page_links( $step ) {
582
+ if ( $step['current'] ) {
583
+ return;
584
+ }
585
+
586
+ $this->step_top( $step );
587
+
588
+ ?>
589
+ <a href="#" target="_blank" rel="noopener" id="frm-redirect-link" class="<?php echo esc_attr( $step['button_class'] ); ?>">
590
+ <?php echo esc_html( $step['button_label'] ); ?>
591
+ </a>
592
+ <?php
593
+
594
+ $this->step_bottom( $step );
595
+ }
596
+
597
+ /**
598
+ * Only show the content for the correct plugin.
599
+ */
600
+ protected function is_current_plugin() {
601
+ $to_redirect = get_transient( 'frm_activation_redirect' );
602
+ return $to_redirect === $this->plugin_slug && empty( $this->is_complete() );
603
+ }
604
+
605
+ /**
606
+ * Override this function to indicate when install is complete.
607
+ */
608
+ protected function is_complete( $count = 1 ) {
609
+ $imported = $this->previously_imported_forms();
610
+ if ( $count === 'all' ) {
611
+ return count( $imported ) >= count( $this->form_options() );
612
+ }
613
+ return ! empty( $imported );
614
+ }
615
+
616
+ /**
617
+ * Get an array of all of the forms that have been imported.
618
+ *
619
+ * @return array
620
+ */
621
+ protected function previously_imported_forms() {
622
+ $imported = array();
623
+ $forms = $this->form_options();
624
+ foreach ( $forms as $form ) {
625
+ $was_imported = isset( $form['form'] ) ? FrmForm::get_id_by_key( $form['form'] ) : false;
626
+ if ( $was_imported ) {
627
+ $imported[ $form['form'] ] = $was_imported;
628
+ }
629
+ }
630
+
631
+ return $imported;
632
+ }
633
+
634
+ /**
635
+ * In the new plugin has any dependencies, include them here.
636
+ */
637
+ protected function required_plugins() {
638
+ return array();
639
+ }
640
+
641
+ /**
642
+ * This needs to be overridden.
643
+ */
644
+ protected function download_id() {
645
+ return 0;
646
+ }
647
+
648
+ /**
649
+ * Give options for which forms to import.
650
+ */
651
+ protected function form_options() {
652
+ /**
653
+ * Example:
654
+ * array(
655
+ * 'unique-key' => array(
656
+ * 'keys' => 'forms keys here',
657
+ * 'name' => 'displayed label here',
658
+ * 'img' => 'svg code',
659
+ * ),
660
+ * )
661
+ */
662
+ return array();
663
+ }
664
+
665
+ /**
666
+ * Give options for which view to use.
667
+ */
668
+ protected function view_options() {
669
+ return array();
670
+ }
671
+
672
+ /**
673
+ * If the pages aren't imported automatically, set the page names.
674
+ */
675
+ protected function needed_pages() {
676
+ /**
677
+ * Example:
678
+ * array(
679
+ * array(
680
+ * 'label' => 'Page Name',
681
+ * 'name' => 'Default name',
682
+ * 'type' => 'form' or 'view',
683
+ * ),
684
+ * )
685
+ */
686
+
687
+ return array();
688
+ }
689
+
690
+ private function css() {
691
+ wp_enqueue_style( 'formidable-pro-fields' );
692
+ ?>
693
+ <style>
694
+ #frm-welcome *, #frm-welcome *::before, #frm-welcome *::after {
695
+ -webkit-box-sizing: border-box;
696
+ -moz-box-sizing: border-box;
697
+ box-sizing: border-box;
698
+ }
699
+ #frm-welcome{
700
+ width: 700px;
701
+ margin: 0 auto;
702
+ }
703
+ #frm-welcome p {
704
+ font-size: 15px;
705
+ }
706
+ #frm-welcome section{
707
+ margin: 50px 0;
708
+ text-align: left;
709
+ clear: both;
710
+ }
711
+ #frm-welcome .top{
712
+ text-align: center;
713
+ }
714
+ .frm-smtp-logos {
715
+ margin-bottom: 38px;
716
+ }
717
+ .frm-smtp-logos svg {
718
+ vertical-align: middle;
719
+ }
720
+ #frm-welcome .top h1 {
721
+ font-size: 26px;
722
+ font-weight: 600;
723
+ margin-bottom: 0;
724
+ padding: 0;
725
+ }
726
+ #frm-welcome .top p {
727
+ font-size: 17px;
728
+ color: #777;
729
+ margin-top: .5em;
730
+ }
731
+ #frm-welcome .screenshot ul {
732
+ display: inline-block;
733
+ margin: 0 0 0 30px;
734
+ list-style-type: none;
735
+ max-width: calc(100% - 350px);
736
+ }
737
+ #frm-welcome .screenshot li {
738
+ margin: 16px 0;
739
+ padding: 0;
740
+ font-size: 15px;
741
+ color: #777;
742
+ }
743
+ #frm-welcome .screenshot .cont img {
744
+ max-width: 100%;
745
+ display: block;
746
+ }
747
+ #frm-welcome .screenshot .cont {
748
+ display: inline-block;
749
+ position: relative;
750
+ width: 315px;
751
+ padding: 5px;
752
+ background-color: #fff;
753
+ border-radius: 3px;
754
+ }
755
+ #frm-welcome .step,
756
+ #frm-welcome .screenshot .cont {
757
+ -webkit-box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
758
+ -moz-box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
759
+ box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
760
+ }
761
+ #frm-welcome .step {
762
+ background-color: #F9F9F9;
763
+ border: 1px solid #E5E5E5;
764
+ margin: 0 0 25px;
765
+ }
766
+ #frm-welcome .screenshot > *,
767
+ #frm-welcome .step > * {
768
+ vertical-align: middle;
769
+ }
770
+ #frm-welcome .step p {
771
+ font-size: 16px;
772
+ color: #777777;
773
+ }
774
+ #frm-welcome .step .num {
775
+ display: inline-block;
776
+ position: relative;
777
+ width: 100px;
778
+ height: 50px;
779
+ text-align: center;
780
+ }
781
+ #frm-welcome .step > div {
782
+ display: inline-block;
783
+ width: calc(100% - 104px);
784
+ background-color: #fff;
785
+ padding: 30px;
786
+ border-left: 1px solid #eee;
787
+ }
788
+ #frm-welcome .step h3.frm-step-heading {
789
+ font-size: 24px;
790
+ line-height: 22px;
791
+ margin-top: 0;
792
+ margin-bottom: 15px;
793
+ }
794
+ #frm-welcome .button.disabled {
795
+ cursor: default;
796
+ }
797
+ #frm-welcome #frm-using-lite {
798
+ display: none;
799
+ }
800
+ </style>
801
+ <?php
802
+ }
803
+
804
+ }
classes/views/addons/list.php CHANGED
@@ -8,16 +8,9 @@
8
  ?>
9
  <div class="wrap">
10
 
11
- <?php include( FrmAppHelper::plugin_path() . '/classes/views/shared/errors.php' ); ?>
12
-
13
- <p class="alignleft">
14
- <?php esc_html_e( 'Missing add-ons?', 'formidable' ); ?>
15
- <a href="#" id="frm_reconnect_link" class="frm-show-authorized" data-refresh="1">
16
- <?php esc_html_e( 'Check now for a recent upgrade or renewal', 'formidable' ); ?>
17
- </a>
18
- </p>
19
-
20
  <?php
 
 
21
  FrmAppHelper::show_search_box(
22
  array(
23
  'input_id' => 'addon',
@@ -25,6 +18,19 @@
25
  'tosearch' => 'frm-card',
26
  )
27
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  ?>
29
  <div class="clear"></div>
30
 
@@ -79,7 +85,13 @@
79
  <?php esc_html_e( 'Renew Now', 'formidable' ); ?>
80
  </a>
81
  <?php } else { ?>
82
- <a class="install-now button button-secondary frm-button-secondary" href="<?php echo esc_url( $pricing . '&utm_content=' . $addon['slug'] ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Upgrade Now', 'formidable' ); ?>">
 
 
 
 
 
 
83
  <?php esc_html_e( 'Upgrade Now', 'formidable' ); ?>
84
  </a>
85
  <?php } ?>
8
  ?>
9
  <div class="wrap">
10
 
 
 
 
 
 
 
 
 
 
11
  <?php
12
+ include( FrmAppHelper::plugin_path() . '/classes/views/shared/errors.php' );
13
+
14
  FrmAppHelper::show_search_box(
15
  array(
16
  'input_id' => 'addon',
18
  'tosearch' => 'frm-card',
19
  )
20
  );
21
+
22
+ if ( FrmAppHelper::pro_is_connected() ) {
23
+ ?>
24
+ <p class="alignleft">
25
+ <?php esc_html_e( 'Missing add-ons?', 'formidable' ); ?>
26
+ <a href="#" id="frm_reconnect_link" class="frm-show-authorized" data-refresh="1">
27
+ <?php esc_html_e( 'Check now for a recent upgrade or renewal', 'formidable' ); ?>
28
+ </a>
29
+ </p>
30
+ <?php
31
+ } else {
32
+ FrmSettingsController::license_box();
33
+ }
34
  ?>
35
  <div class="clear"></div>
36
 
85
  <?php esc_html_e( 'Renew Now', 'formidable' ); ?>
86
  </a>
87
  <?php } else { ?>
88
+ <?php
89
+ if ( isset( $addon['categories'] ) && in_array( 'Solution', $addon['categories'] ) ) {
90
+ // Solutions will go to a separate page.
91
+ $pricing = FrmAppHelper::admin_upgrade_link( 'addons', $addon['link'] );
92
+ }
93
+ ?>
94
+ <a class="install-now button button-secondary frm-button-secondary" href="<?php echo esc_url( $pricing . '&utm_content=' . $addon['slug'] ); ?>" target="_blank" rel="noopener" aria-label="<?php esc_attr_e( 'Upgrade Now', 'formidable' ); ?>">
95
  <?php esc_html_e( 'Upgrade Now', 'formidable' ); ?>
96
  </a>
97
  <?php } ?>
classes/views/addons/settings.php CHANGED
@@ -1,10 +1,8 @@
1
  <div class="wrap">
2
- <h2 class="frm-h2"><?php esc_html_e( 'Plugin Licenses', 'formidable' ); ?></h2>
3
-
4
  <?php
5
 
6
  foreach ( $plugins as $slug => $plugin ) {
7
- if ( $slug == 'formidable_pro' || $plugin->is_parent_licence ) {
8
  continue;
9
  }
10
 
1
  <div class="wrap">
 
 
2
  <?php
3
 
4
  foreach ( $plugins as $slug => $plugin ) {
5
+ if ( $slug == 'formidable_pro' || $plugin->is_parent_licence || ! $plugin->needs_license ) {
6
  continue;
7
  }
8
 
classes/views/frm-settings/license_box.php CHANGED
@@ -4,7 +4,7 @@
4
  <?php esc_html_e( 'Connect an Account', 'formidable' ); ?>
5
  </a>
6
  or
7
- <a href="<?php echo esc_url( FrmAppHelper::admin_upgrade_link( 'settings-license' ) ); ?>" target="_blank" class="button-secondary frm-secondary-button">
8
  <?php esc_html_e( 'Get Formidable Now', 'formidable' ); ?>
9
  </a>
10
  </p>
4
  <?php esc_html_e( 'Connect an Account', 'formidable' ); ?>
5
  </a>
6
  or
7
+ <a href="<?php echo esc_url( FrmAppHelper::admin_upgrade_link( 'settings-license' ) ); ?>" target="_blank" class="button-secondary frm-button-secondary">
8
  <?php esc_html_e( 'Get Formidable Now', 'formidable' ); ?>
9
  </a>
10
  </p>
classes/views/solutions/_import.php ADDED
@@ -0,0 +1,63 @@