Formidable Forms – Form Builder for WordPress - Version 3.0

Version Description

  • Move features into the free form builder: redirect and show page after save, javascript validation, field format options with HTML5 pattern validation, and phone number, number, user ID, hidden field, and HTML fields
  • Possibly breaking change: Remove code that has been deprecated since before v2.02
  • Save a combined js file to use on the front-end with a fallback if the file fails to generate. This file is updated when the plugin is activated or updated.
  • A UI pick-me-up in preparation of things to come in 4.0.
  • New: Use CSS grids for better layouts. If you would like your column layouts to show in Internet Explorer, you'll need to turn on the old styling in the Formidable -> Global settings. The grids use a 12-column layout with classes that range from frm1 (1 column of 12) to frm12 (span all 12 columns). (Thanks for the feedback from our feedback group!)
  • New: Search for fields by name, id, and key in the customization panel
  • Improved RTL styling in backend
  • Enhancement: Add frm_rtl class to forms with styles set to RTL for easier styling.
  • Enhancement: Customize the invalid message when a custom format is set on text fields
  • Better a11y/WCAG support: hidden labels where required, "for" tag on most labels, and link the field to its description for screenreaders.
  • Move form shortcodes from the sidebar to the form settings page
  • Change "field options" to "field settings" on the form builder page
  • Update the Print styling for the entries page
  • Remove frm_text_block class and do it by default. Radio buttons and checkboxes with wrapping text should look good by default.
  • Add a link in the footer to review Formidable
  • New: field object class to make it easy to make new field types. We don't have docs yet, but developers can take a look at the FrmFieldType class. But we've gone to great efforts to make sure fields done the old way will continue to function.
  • New hook: Add frm_output_single_style hook to add extra css into the generated stylesheet
  • New hook: Add frm_before_get_form hook for enqueueing form scripts
  • New hook: Add frm_enqueue_builder_scripts hook to load extra scripts on the form builder page
  • New hook: Add frm_show_entry_defaults hook to add extra atts to the frm_show_entry shortcode
  • Tweak: Include 'original_default' in the field array for new entries so we can compare and prevent double processing later
  • Fix: quotation marks were being escaped in frm_form_attributes and frm_form_div_attributes hooks
  • Removed: The preview page option in the global settings is no longer used. The form preview page is now generated.
  • Removed: The placeholder fallback javascript for old versions of IE is gone. No need to give everyone extra scripts to load.
  • Deprecated the accordion javascript checkbox in global settings since it isn't used by the plugin. If you had this box checked, you'll still see it. Once you uncheck it the option will no longer appear.
  • Pro Version Forms
  • New: Move Formidable Pro to its own plugin during update or install. Wahoo!
  • New: If the Pro version is installed without the lite forms, install it automatically. Prevent errors if pro is running alone or is also nested inside of lite.
  • Add range slider and toggle fields
  • Add visibility option to HTML and section fields
  • Move repeater field to its own field button
  • Combine image and URL fields
  • Add readonly option to time fields
  • Star rating fields: Separate from scale fields and remove the jquery rating js and replace with mostly html and css
  • Show frm-stats as stars with straight html/css (no more js)
  • New: Make it easier to show star values. Show the stars by default on the View entry page and show stars in a view with [25 html=1].
  • New: Added param checking to inline conditionals: [if 25 equals='param' param='set-name-here'] and [if get param="level" equals="gold"]
  • New: Add entry_position shortcode for incremental content in views. For example, this gives the option to show more or different information for the first entry in the view or insert ads after the third entry.
  • New: Automatically adjust fields to fit equally in an inline form
  • Separate Pro and Lite translations
  • Enhancement: If a form creates posts and is set to not save entries, save the created post.
  • Enhancement: Run form install on an API route instead of the admin ajax route and make sure there won't be multiple instances of the install running at once.
  • Enhancement: Use the options instead of transients for checking for updates. Some types of caching store transients indefinitely.
  • Enhancement: Get the shortcodes for a view more concisely. Check for any numeric shortcode instead of checking the database for the field ids
  • Tweak: Open files in the form upload field in a new tab
  • Tweak: Don't show the reports nav if the form has no entries
  • Tweak: Add .do-calculation class on a form to run calculations even if they are not on the current page of the form
  • Tweak: Add $atts with $atts['view'] to all pagination hooks
  • Fix: calculations in hidden fields inside of sections were not calculating
  • Fix: Add validation for the year range in date fields
  • Fix: Don't use conditional logic in form actions when the field isn't selected
  • Fix: Show address fields without
    in dynamic fields
  • Fix: Require the credit card field when editing a draft
  • Fix: Only show the user login for a user id field when the display name is empty. Don't show it as a fallback for other user values.
  • Fix: Return 403 instead of 401 when a file type isn't allowed to be uploaded.
  • Fix: Install the wp_frm_copies table during the first multisite installation, and prevent it from checking tables before they exist.
  • Fix: Do not process a shortcode that is inserted into a field.
  • Fix: Conditionals that check user meta were always returning true
  • Fix: Autocomplete for dynamic fields was too small
  • Fix: If a field includes regex, keep the slashes when the field is duplicated
  • Fix: Correctly check conditional logic when comparing 0 to blank.
  • Fix: Prevent double filtering shortcodes in a nested view
  • Fix: Allow a view to not be filtered on the same page as a filtered view
  • Fix: Searching dynamic fields were returning extra, incorrect results
  • Fix: Searching for a decimal value was dropping the value after the decimal
  • Fix: Searching for a number with post entries and frm-search wasn't correctly checking the posts
  • Fix: datepicker settings weren't loading correctly in an ajax form with date fields that aren't on the first form page
  • Fix: Correctly hide and show fields in embedded forms with the frm-show-entry shortcode
  • Fix: When a field immediately follows an embedded form, it was showing up when include_fields included the embedded form
  • Removed the option to bulk create templates from forms
  • Removed the list of users on the reports page for quicker report loading.
Download this release

Release Info

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

Code changes from version 2.05.09 to 3.0

Files changed (120) hide show
  1. classes/controllers/FrmAddonsController.php +16 -17
  2. classes/controllers/FrmAppController.php +97 -38
  3. classes/controllers/FrmEntriesController.php +53 -46
  4. classes/controllers/FrmFieldsController.php +169 -98
  5. classes/controllers/FrmFormsController.php +302 -73
  6. classes/controllers/FrmHooksController.php +4 -13
  7. classes/controllers/FrmStylesController.php +21 -1
  8. classes/controllers/FrmXMLController.php +6 -31
  9. classes/factories/FrmFieldFactory.php +88 -0
  10. classes/helpers/FrmAppHelper.php +110 -118
  11. classes/helpers/FrmEntriesHelper.php +59 -88
  12. classes/helpers/FrmEntriesListHelper.php +2 -2
  13. classes/helpers/FrmFieldsHelper.php +476 -629
  14. classes/helpers/FrmFormActionsHelper.php +0 -10
  15. classes/helpers/FrmFormsHelper.php +291 -47
  16. classes/helpers/FrmFormsListHelper.php +14 -33
  17. classes/helpers/FrmListHelper.php +89 -59
  18. classes/helpers/FrmShortcodeHelper.php +55 -0
  19. classes/helpers/FrmStylesHelper.php +5 -13
  20. classes/helpers/FrmTipsHelper.php +2 -2
  21. classes/helpers/FrmXMLHelper.php +3 -2
  22. classes/models/FrmAddon.php +32 -16
  23. classes/models/FrmCreateFile.php +100 -15
  24. classes/models/FrmDb.php +3 -2
  25. classes/models/FrmEDD_SL_Plugin_Updater.php +107 -34
  26. classes/models/FrmEntry.php +7 -45
  27. classes/models/FrmEntryFormatter.php +258 -25
  28. classes/models/FrmEntryMeta.php +38 -5
  29. classes/models/FrmEntryShortcodeFormatter.php +6 -0
  30. classes/models/FrmEntryValidate.php +35 -49
  31. classes/models/FrmEntryValues.php +11 -29
  32. classes/models/FrmField.php +215 -40
  33. classes/models/FrmFieldFormHtml.php +406 -0
  34. classes/models/FrmFieldValue.php +61 -55
  35. classes/models/FrmFieldValueSelector.php +2 -1
  36. classes/models/FrmForm.php +54 -26
  37. classes/models/FrmFormDeprecated.php +3 -3
  38. classes/models/FrmMigrate.php +9 -4
  39. classes/models/FrmSettings.php +3 -3
  40. classes/models/fields/FrmFieldCaptcha.php +198 -0
  41. classes/models/fields/FrmFieldCheckbox.php +63 -0
  42. classes/models/fields/FrmFieldDefault.php +53 -0
  43. classes/models/fields/FrmFieldEmail.php +43 -0
  44. classes/models/fields/FrmFieldHTML.php +46 -0
  45. classes/models/fields/FrmFieldHidden.php +45 -0
  46. classes/models/fields/FrmFieldNumber.php +91 -0
  47. classes/models/fields/FrmFieldPhone.php +34 -0
  48. classes/models/fields/FrmFieldRadio.php +59 -0
  49. classes/models/fields/FrmFieldSelect.php +53 -0
  50. classes/models/fields/FrmFieldText.php +28 -0
  51. classes/models/fields/FrmFieldTextarea.php +68 -0
  52. classes/models/fields/FrmFieldType.php +834 -0
  53. classes/models/fields/FrmFieldUrl.php +83 -0
  54. classes/models/fields/FrmFieldUserID.php +108 -0
  55. classes/views/addons/upgrade_to_pro.php +94 -21
  56. classes/views/frm-entries/_sidebar-shared-pub.php +7 -1
  57. classes/views/frm-entries/errors.php +1 -1
  58. classes/views/frm-entries/form.php +5 -10
  59. classes/views/frm-entries/list.php +21 -29
  60. classes/views/frm-entries/new.php +2 -2
  61. classes/views/frm-entries/show.php +74 -69
  62. classes/views/frm-entries/sidebar-shared.php +14 -5
  63. classes/views/frm-entries/sidebar-show.php +18 -34
  64. classes/views/frm-fields/back-end/ajax-field-placeholder.php +4 -0
  65. classes/views/frm-fields/back-end/dropdown-field.php +1 -1
  66. classes/views/frm-fields/back-end/field-captcha.php +7 -0
  67. classes/views/frm-fields/back-end/field-hidden.php +4 -0
  68. classes/views/frm-fields/back-end/field-html.php +6 -0
  69. classes/views/frm-fields/back-end/field-multiple.php +15 -0
  70. classes/views/frm-fields/back-end/field-user-id.php +3 -0
  71. classes/views/frm-fields/back-end/html-content.php +7 -0
  72. classes/views/frm-fields/back-end/number-range.php +15 -0
  73. classes/views/frm-fields/back-end/pixels-wide.php +7 -3
  74. classes/views/frm-fields/back-end/value-format.php +7 -0
  75. classes/views/frm-fields/front-end/checkbox-field.php +54 -0
  76. classes/views/frm-fields/front-end/dropdown-field.php +4 -7
  77. classes/views/frm-fields/front-end/radio-field.php +53 -0
  78. classes/views/frm-fields/input.php +3 -147
  79. classes/views/frm-fields/radio.php +2 -21
  80. classes/views/frm-fields/show-build.php +4 -35
  81. classes/views/frm-form-actions/form_action.php +1 -1
  82. classes/views/frm-forms/_publish_box.php +43 -88
  83. classes/views/frm-forms/actions-dropdown.php +19 -0
  84. classes/views/frm-forms/add_field.php +42 -72
  85. classes/views/frm-forms/add_field_links.php +113 -157
  86. classes/views/frm-forms/edit.php +13 -20
  87. classes/views/frm-forms/form.php +17 -21
  88. classes/views/frm-forms/insert_form_popup.php +45 -49
  89. classes/views/frm-forms/list.php +9 -10
  90. classes/views/frm-forms/mb_html_tab.php +4 -0
  91. classes/views/frm-forms/new.php +14 -15
  92. classes/views/frm-forms/settings.php +93 -57
  93. classes/views/frm-forms/sidebar-settings.php +11 -4
  94. classes/views/frm-settings/form.php +9 -6
  95. classes/views/frm-settings/license_box.php +1 -1
  96. classes/views/shared/admin-header.php +32 -0
  97. classes/views/shared/errors.php +15 -15
  98. classes/views/shared/form-nav.php +6 -7
  99. classes/views/shared/head.php +0 -2
  100. classes/views/shared/mb_adv_info.php +21 -9
  101. classes/views/styles/_sample_form.php +10 -8
  102. classes/views/styles/show.php +5 -5
  103. classes/views/xml/xml.php +2 -2
  104. css/_single_theme.css.php +62 -504
  105. css/custom_theme.css.php +107 -176
  106. css/font_icons.css +261 -6
  107. css/frm_admin.css +1240 -335
  108. css/frm_fonts.css +3 -2
  109. css/frm_grids.css +223 -108
  110. css/frm_old_grids.css +643 -0
  111. deprecated.php +0 -5
  112. fonts/s11-fp.eot +0 -0
  113. fonts/s11-fp.svg +151 -67
  114. fonts/s11-fp.ttf +0 -0
  115. fonts/s11-fp.woff +0 -0
  116. formidable.php +47 -40
  117. images/rte.png +0 -0
  118. js/formidable.js +196 -4073
  119. js/formidable.min.js +35 -105
  120. js/formidable_admin.js +248 -96
classes/controllers/FrmAddonsController.php CHANGED
@@ -57,36 +57,35 @@ class FrmAddonsController {
57
  'title' => 'Formidable Pro',
58
  'link' => 'pricing/',
59
  'docs' => '',
60
- 'file' => 'formidable/pro',
61
  'excerpt' => 'Enhance your basic Formidable forms with a plethora of Pro field types and features. Create advanced forms and data-driven applications in minutes.',
62
  ),
63
  'mailchimp' => array(
64
- 'title' => 'MailChimp',
65
  '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.',
66
  ),
67
  'registration' => array(
68
- 'title' => 'User Registration',
69
  'link' => 'downloads/user-registration/',
70
  '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.',
71
  ),
72
  'paypal' => array(
73
- 'title' => 'PayPal Standard',
74
  'link' => 'downloads/paypal-standard/',
75
  '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.',
76
  ),
77
  'stripe' => array(
78
- 'title' => 'Stripe',
79
  'docs' => 'stripe/',
80
  'excerpt' => 'Any Formidable forms on your site can accept credit card payments without users ever leaving your site.',
81
  ),
82
  'authorize-net' => array(
83
- 'title' => 'Authorize.net AIM',
84
  'link' => 'downloads/authorize-net-aim/',
85
  'docs' => 'authorize-net-aim/',
86
  'excerpt' => 'Accept one-time payments directly on your site, using Authorize.net AIM.',
87
  ),
88
  'woocommerce' => array(
89
- 'title' => 'WooCommerce',
90
  'excerpt' => 'Use a Formidable form on your WooCommerce product pages.',
91
  ),
92
  'autoresponder' => array(
@@ -95,49 +94,49 @@ class FrmAddonsController {
95
  'excerpt' => 'Schedule email notifications, SMS messages, and API actions.',
96
  ),
97
  'modal' => array(
98
- 'title' => 'Bootstrap Modal',
99
  'link' => 'downloads/bootstrap-modal/',
100
  'docs' => 'bootstrap-modal/',
101
  'excerpt' => 'Open a view or form in a Bootstrap popup.',
102
  ),
103
  'bootstrap' => array(
104
- 'title' => 'Bootstrap',
105
  'excerpt' => 'Instantly add Bootstrap styling to all your Formidable forms.',
106
  ),
107
  'zapier' => array(
108
- 'title' => 'Zapier',
109
  '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.',
110
  ),
111
  'signature' => array(
112
- 'title' => 'Signature',
113
  'excerpt' => 'Add a signature field to your form. The user may write their signature with a trackpad/mouse or just type it.',
114
  ),
115
  'api' => array(
116
- 'title' => 'Formidable API',
117
  'link' => 'downloads/formidable-api/',
118
  '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.',
119
  ),
120
  'twilio' => array(
121
- 'title' => 'Twilio',
122
  'docs' => 'twilio-add-on/',
123
  'excerpt' => 'Allow users to text their votes for polls created by Formidable Forms, or send SMS notifications when entries are submitted or updated.',
124
  ),
125
  'aweber' => array(
126
- 'title' => 'AWeber',
127
  'excerpt' => 'Subscribe users to an AWeber mailing list when they submit a form. AWeber is a powerful email marketing service.',
128
  ),
129
  'highrise' => array(
130
- 'title' => 'Highrise',
131
  'excerpt' => 'Add your leads to your Highrise CRM account any time a Formidable form is submitted.',
132
  ),
133
  'wpml' => array(
134
- 'title' => 'WP Multilingual',
135
  'link' => 'downloads/wp-multilingual/',
136
  'docs' => 'formidable-multi-language/',
137
  'excerpt' => 'Translate your forms into multiple languages using the Formidable-integrated WPML plugin.',
138
  ),
139
  'polylang' => array(
140
- 'title' => 'Polylang',
141
  'excerpt' => 'Create bilingual or multilingual forms with help from Polylang.',
142
  ),
143
  'locations' => array(
57
  'title' => 'Formidable Pro',
58
  'link' => 'pricing/',
59
  'docs' => '',
 
60
  'excerpt' => 'Enhance your basic Formidable forms with a plethora of Pro field types and features. Create advanced forms and data-driven applications in minutes.',
61
  ),
62
  'mailchimp' => array(
63
+ 'title' => 'MailChimp Forms',
64
  '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.',
65
  ),
66
  'registration' => array(
67
+ 'title' => 'User Registration Forms',
68
  'link' => 'downloads/user-registration/',
69
  '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.',
70
  ),
71
  'paypal' => array(
72
+ 'title' => 'PayPal Standard Forms',
73
  'link' => 'downloads/paypal-standard/',
74
  '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.',
75
  ),
76
  'stripe' => array(
77
+ 'title' => 'Stripe Forms',
78
  'docs' => 'stripe/',
79
  'excerpt' => 'Any Formidable forms on your site can accept credit card payments without users ever leaving your site.',
80
  ),
81
  'authorize-net' => array(
82
+ 'title' => 'Authorize.net AIM Forms',
83
  'link' => 'downloads/authorize-net-aim/',
84
  'docs' => 'authorize-net-aim/',
85
  'excerpt' => 'Accept one-time payments directly on your site, using Authorize.net AIM.',
86
  ),
87
  'woocommerce' => array(
88
+ 'title' => 'WooCommerce Forms',
89
  'excerpt' => 'Use a Formidable form on your WooCommerce product pages.',
90
  ),
91
  'autoresponder' => array(
94
  'excerpt' => 'Schedule email notifications, SMS messages, and API actions.',
95
  ),
96
  'modal' => array(
97
+ 'title' => 'Bootstrap Modal Forms',
98
  'link' => 'downloads/bootstrap-modal/',
99
  'docs' => 'bootstrap-modal/',
100
  'excerpt' => 'Open a view or form in a Bootstrap popup.',
101
  ),
102
  'bootstrap' => array(
103
+ 'title' => 'Bootstrap Style Forms',
104
  'excerpt' => 'Instantly add Bootstrap styling to all your Formidable forms.',
105
  ),
106
  'zapier' => array(
107
+ 'title' => 'Zapier Forms',
108
  '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.',
109
  ),
110
  'signature' => array(
111
+ 'title' => 'Digital Signature Forms',
112
  'excerpt' => 'Add a signature field to your form. The user may write their signature with a trackpad/mouse or just type it.',
113
  ),
114
  'api' => array(
115
+ 'title' => 'Formidable Forms API',
116
  'link' => 'downloads/formidable-api/',
117
  '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.',
118
  ),
119
  'twilio' => array(
120
+ 'title' => 'Twilio SMS Forms',
121
  'docs' => 'twilio-add-on/',
122
  'excerpt' => 'Allow users to text their votes for polls created by Formidable Forms, or send SMS notifications when entries are submitted or updated.',
123
  ),
124
  'aweber' => array(
125
+ 'title' => 'AWeber Forms',
126
  'excerpt' => 'Subscribe users to an AWeber mailing list when they submit a form. AWeber is a powerful email marketing service.',
127
  ),
128
  'highrise' => array(
129
+ 'title' => 'Highrise Forms',
130
  'excerpt' => 'Add your leads to your Highrise CRM account any time a Formidable form is submitted.',
131
  ),
132
  'wpml' => array(
133
+ 'title' => 'WP Multilingual Forms',
134
  'link' => 'downloads/wp-multilingual/',
135
  'docs' => 'formidable-multi-language/',
136
  'excerpt' => 'Translate your forms into multiple languages using the Formidable-integrated WPML plugin.',
137
  ),
138
  'polylang' => array(
139
+ 'title' => 'Polylang Forms',
140
  'excerpt' => 'Create bilingual or multilingual forms with help from Polylang.',
141
  ),
142
  'locations' => array(
classes/controllers/FrmAppController.php CHANGED
@@ -23,6 +23,29 @@ class FrmAppController {
23
  return $pos;
24
  }
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  public static function load_wp_admin_style() {
27
  FrmAppHelper::load_font_style();
28
  }
@@ -94,7 +117,7 @@ class FrmAppController {
94
 
95
  // Adds a settings link to the plugins page
96
  public static function settings_link( $links ) {
97
- $settings = '<a href="' . esc_url( admin_url( 'admin.php?page=formidable-settings' ) ) . '">' . __( 'Settings', 'formidable' ) . '</a>';
98
  array_unshift( $links, $settings );
99
 
100
  return $links;
@@ -108,21 +131,29 @@ class FrmAppController {
108
  return;
109
  }
110
 
111
- if ( get_site_option( 'frmpro-authorized' ) && ! file_exists( FrmAppHelper::plugin_path() . '/pro/formidable-pro.php' ) ) {
112
- FrmAppHelper::load_admin_wide_js();
 
 
 
 
113
 
114
- // user is authorized, but running free version
115
- $inst_install_url = 'https://formidableforms.com/knowledgebase/install-formidable-forms/';
 
 
 
 
116
  ?>
117
  <div class="error" class="frm_previous_install">
118
  <?php
119
- echo wp_kses_post( apply_filters( 'frm_pro_update_msg',
120
  sprintf(
121
- __( 'This site has been previously authorized to run Formidable Forms.<br/>%1$sInstall Formidable Pro%2$s or %3$sdeauthorize%4$s this site to continue running the free version and remove this message.', 'formidable' ),
122
- '<a href="' . esc_url( $inst_install_url ) . '" target="_blank">', '</a>',
123
  '<a href="#" class="frm_deauthorize_link">', '</a>'
124
  ), esc_url( $inst_install_url )
125
- ) );
126
  ?>
127
  </div>
128
  <?php
@@ -272,6 +303,7 @@ class FrmAppController {
272
 
273
  wp_register_script( 'formidable-editinplace', FrmAppHelper::plugin_url() . '/js/jquery/jquery.editinplace.packed.js', array( 'jquery' ), '2.3.0' );
274
 
 
275
  } else if ( $pagenow == 'post.php' || ( $pagenow == 'post-new.php' && $post_type == 'frm_display' ) ) {
276
  if ( isset( $_REQUEST['post_type'] ) ) {
277
  $post_type = sanitize_title( $_REQUEST['post_type'] );
@@ -319,19 +351,14 @@ class FrmAppController {
319
  }
320
  }
321
 
322
- public static function localize_script( $location ) {
323
- _deprecated_function( __FUNCTION__, '2.0.9', 'FrmAppHelper::localize_script' );
324
- return FrmAppHelper::localize_script( $location );
325
- }
326
-
327
- public static function custom_stylesheet() {
328
- _deprecated_function( __FUNCTION__, '2.0.9', 'FrmStylesController::custom_stylesheet' );
329
- return FrmStylesController::custom_stylesheet();
330
- }
331
-
332
- public static function load_css() {
333
- _deprecated_function( __FUNCTION__, '2.0.9', 'FrmStylesController::load_saved_css' );
334
- return FrmStylesController::load_saved_css();
335
  }
336
 
337
  /**
@@ -343,22 +370,38 @@ class FrmAppController {
343
  * @param int $blog_id Blog ID.
344
  */
345
  public static function network_upgrade_site( $blog_id = 0 ) {
 
 
 
346
  if ( $blog_id ) {
347
  switch_to_blog( $blog_id );
348
- $upgrade_url = admin_url( 'admin-ajax.php' );
349
  restore_current_blog();
350
  } else {
351
- $upgrade_url = admin_url( 'admin-ajax.php' );
352
  }
353
 
354
- $upgrade_url = add_query_arg( array( 'action' => 'frm_silent_upgrade' ), $upgrade_url );
355
- $r = wp_remote_get( esc_url_raw( $upgrade_url ) );
356
- if ( is_wp_error( $r ) || ! is_array( $r ) || ! empty( $r['body'] ) ) {
357
  // if the remove post fails, use javascript instead
358
  add_action( 'admin_notices', 'FrmAppController::install_js_fallback' );
359
  }
360
  }
361
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  /**
363
  * Silent database upgrade (no redirect).
364
  * Called via ajax request during network upgrade process.
@@ -366,15 +409,16 @@ class FrmAppController {
366
  * @since 2.0.1
367
  */
368
  public static function ajax_install() {
369
- if ( self::needs_update() ) {
370
- self::install();
371
- }
372
  wp_die();
373
  }
374
 
375
  public static function activation_install() {
376
  FrmDb::delete_cache_and_transient( 'frm_plugin_version' );
377
  FrmFormActionsController::actions_init();
 
 
 
378
  self::install();
379
  }
380
 
@@ -407,16 +451,16 @@ class FrmAppController {
407
  }
408
 
409
  // Routes for wordpress pages -- we're just replacing content here folks.
410
- public static function page_route( $content ) {
411
- global $post;
 
412
 
413
- $frm_settings = FrmAppHelper::get_settings();
414
- if ( $post && $post->ID == $frm_settings->preview_page_id && isset( $_GET['form'] ) ) {
415
- $content = FrmFormsController::page_preview();
416
- }
417
 
418
- return $content;
419
- }
420
 
421
  public static function deauthorize() {
422
  FrmAppHelper::permission_check('frm_change_settings');
@@ -429,6 +473,21 @@ class FrmAppController {
429
  wp_die();
430
  }
431
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
  public static function get_form_shortcode( $atts ) {
433
  _deprecated_function( __FUNCTION__, '1.07.05', 'FrmFormsController::get_form_shortcode()' );
434
  return FrmFormsController::get_form_shortcode( $atts );
23
  return $pos;
24
  }
25
 
26
+ /**
27
+ * @since 3.0
28
+ */
29
+ public static function add_admin_class( $classes ) {
30
+ if ( self::is_white_page() ) {
31
+ $classes .= ' frm-white-body ';
32
+ }
33
+ return $classes;
34
+ }
35
+
36
+ /**
37
+ * @since 3.0
38
+ */
39
+ private static function is_white_page() {
40
+ $is_white_page = ( FrmAppHelper::is_admin_page( 'formidable' ) || FrmAppHelper::is_admin_page( 'formidable-entries' ) || FrmAppHelper::is_admin_page( 'formidable-pro-upgrade' ) );
41
+ if ( ! $is_white_page ) {
42
+ $screen = get_current_screen();
43
+ $is_white_page = ( $screen && $screen->id === 'edit-frm_display' );
44
+ }
45
+
46
+ return $is_white_page;
47
+ }
48
+
49
  public static function load_wp_admin_style() {
50
  FrmAppHelper::load_font_style();
51
  }
117
 
118
  // Adds a settings link to the plugins page
119
  public static function settings_link( $links ) {
120
+ $settings = '<a href="' . esc_url( admin_url( 'admin.php?page=formidable' ) ) . '">' . __( 'Build a Form', 'formidable' ) . '</a>';
121
  array_unshift( $links, $settings );
122
 
123
  return $links;
131
  return;
132
  }
133
 
134
+ $pro_installed = is_dir( WP_PLUGIN_DIR . '/formidable-pro' );
135
+
136
+ if ( get_site_option( 'frmpro-authorized' ) && ! is_callable( 'load_formidable_pro' ) ) {
137
+ FrmAppHelper::load_admin_wide_js();
138
+
139
+ // user is authorized, but running free version
140
 
141
+ if ( $pro_installed ) {
142
+ // if pro version is installed, include link to activate it
143
+ $inst_install_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=formidable-pro/formidable-pro.php' ), 'activate-plugin_formidable-pro/formidable-pro.php' );
144
+ } else {
145
+ $inst_install_url = 'https://formidableforms.com/knowledgebase/install-formidable-forms/';
146
+ }
147
  ?>
148
  <div class="error" class="frm_previous_install">
149
  <?php
150
+ echo apply_filters( 'frm_pro_update_msg',
151
  sprintf(
152
+ esc_html__( 'This site has been previously authorized to run Formidable Forms. %1$sInstall Formidable Pro%2$s or %3$sdeauthorize%4$s this site to continue running the free version and remove this message.', 'formidable' ),
153
+ '<br/><a href="' . esc_url( $inst_install_url ) . '" target="_blank">', '</a>',
154
  '<a href="#" class="frm_deauthorize_link">', '</a>'
155
  ), esc_url( $inst_install_url )
156
+ );
157
  ?>
158
  </div>
159
  <?php
303
 
304
  wp_register_script( 'formidable-editinplace', FrmAppHelper::plugin_url() . '/js/jquery/jquery.editinplace.packed.js', array( 'jquery' ), '2.3.0' );
305
 
306
+ do_action( 'frm_enqueue_builder_scripts' );
307
  } else if ( $pagenow == 'post.php' || ( $pagenow == 'post-new.php' && $post_type == 'frm_display' ) ) {
308
  if ( isset( $_REQUEST['post_type'] ) ) {
309
  $post_type = sanitize_title( $_REQUEST['post_type'] );
351
  }
352
  }
353
 
354
+ /**
355
+ * @since 3.0
356
+ */
357
+ public static function create_rest_routes() {
358
+ register_rest_route( 'frm-admin/v1', '/install', array(
359
+ 'methods' => 'GET',
360
+ 'callback' => 'FrmAppController::api_install',
361
+ ) );
 
 
 
 
 
362
  }
363
 
364
  /**
370
  * @param int $blog_id Blog ID.
371
  */
372
  public static function network_upgrade_site( $blog_id = 0 ) {
373
+
374
+ $request = new WP_REST_Request( 'GET', '/frm-admin/v1/install' );
375
+
376
  if ( $blog_id ) {
377
  switch_to_blog( $blog_id );
378
+ $response = rest_do_request( $request );
379
  restore_current_blog();
380
  } else {
381
+ $response = rest_do_request( $request );
382
  }
383
 
384
+ if ( $response->is_error() ) {
 
 
385
  // if the remove post fails, use javascript instead
386
  add_action( 'admin_notices', 'FrmAppController::install_js_fallback' );
387
  }
388
  }
389
 
390
+ /**
391
+ * @since 3.0
392
+ */
393
+ public static function api_install() {
394
+ if ( self::needs_update() ) {
395
+ $running = get_option( 'frm_install_running' );
396
+ if ( false === $running ) {
397
+ update_option( 'frm_install_running', true );
398
+ self::install();
399
+ delete_option( 'frm_install_running' );
400
+ }
401
+ }
402
+ return true;
403
+ }
404
+
405
  /**
406
  * Silent database upgrade (no redirect).
407
  * Called via ajax request during network upgrade process.
409
  * @since 2.0.1
410
  */
411
  public static function ajax_install() {
412
+ self::api_install();
 
 
413
  wp_die();
414
  }
415
 
416
  public static function activation_install() {
417
  FrmDb::delete_cache_and_transient( 'frm_plugin_version' );
418
  FrmFormActionsController::actions_init();
419
+ if ( ! self::needs_update() ) {
420
+ FrmAppHelper::save_combined_js();
421
+ }
422
  self::install();
423
  }
424
 
451
  }
452
 
453
  // Routes for wordpress pages -- we're just replacing content here folks.
454
+ public static function page_route( $content ) {
455
+ _deprecated_function( __METHOD__, '3.0' );
456
+ global $post;
457
 
458
+ if ( $post && isset( $_GET['form'] ) ) {
459
+ $content = FrmFormsController::page_preview();
460
+ }
 
461
 
462
+ return $content;
463
+ }
464
 
465
  public static function deauthorize() {
466
  FrmAppHelper::permission_check('frm_change_settings');
473
  wp_die();
474
  }
475
 
476
+ public static function set_footer_text( $text ) {
477
+ if ( FrmAppHelper::is_formidable_admin() ) {
478
+ $text = sprintf(
479
+ __( 'Help us spread the %1$sFormidable Forms%2$s love with %3$s %5$s on WordPress.org%4$s. Thank you heaps!', 'formidable' ),
480
+ '<a href="' . esc_url( FrmAppHelper::make_affiliate_url( 'https://formidableforms.com' ) ) . '" target="_blank">',
481
+ '</a>',
482
+ '<a href="https://wordpress.org/support/plugin/formidable/reviews/?filter=5#new-post" target="_blank">',
483
+ '</a>',
484
+ '&#9733;&#9733;&#9733;&#9733;&#9733;'
485
+ );
486
+ $text = '<span id="footer-thankyou">' . $text . '</span>';
487
+ }
488
+ return $text;
489
+ }
490
+
491
  public static function get_form_shortcode( $atts ) {
492
  _deprecated_function( __FUNCTION__, '1.07.05', 'FrmFormsController::get_form_shortcode()' );
493
  return FrmFormsController::get_form_shortcode( $atts );
classes/controllers/FrmEntriesController.php CHANGED
@@ -14,13 +14,15 @@ class FrmEntriesController {
14
  * @since 2.05.07
15
  */
16
  private static function load_manage_entries_hooks() {
17
- if ( ! in_array( FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' ), array( 'edit', 'show' ) ) ) {
18
  $menu_name = FrmAppHelper::get_menu_name();
19
  $base = self::base_column_key( $menu_name );
20
 
21
  add_filter( 'manage_' . $base . '_columns', 'FrmEntriesController::manage_columns' );
22
  add_filter( 'get_user_option_' . self::hidden_column_key( $menu_name ), 'FrmEntriesController::hidden_columns' );
23
  add_filter( 'manage_' . $base . '_sortable_columns', 'FrmEntriesController::sortable_columns' );
 
 
24
  }
25
  }
26
 
@@ -52,7 +54,8 @@ class FrmEntriesController {
52
 
53
  $action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
54
  $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
55
- if ( $page != 'formidable-entries' || ( ! empty( $action ) && $action != 'list' ) ) {
 
56
  return $help;
57
  }
58
 
@@ -73,6 +76,21 @@ class FrmEntriesController {
73
  return $help;
74
  }
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  public static function manage_columns( $columns ) {
77
  global $frm_vars;
78
  $form_id = FrmForm::get_current_form_id();
@@ -411,6 +429,7 @@ class FrmEntriesController {
411
 
412
  $fields = FrmField::get_all_for_form( $entry->form_id, '', 'include' );
413
  $to_emails = array();
 
414
 
415
  include( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/show.php' );
416
  }
@@ -421,9 +440,7 @@ class FrmEntriesController {
421
  $params = FrmForm::get_admin_params();
422
 
423
  if ( isset( $params['keep_post'] ) && $params['keep_post'] ) {
424
- //unlink entry from post
425
- global $wpdb;
426
- $wpdb->update( $wpdb->prefix . 'frm_items', array( 'post_id' => '' ), array( 'id' => $params['id'] ) );
427
  }
428
 
429
  $message = '';
@@ -520,17 +537,35 @@ class FrmEntriesController {
520
 
521
  if ( empty( $errors ) ) {
522
  $_POST['frm_skip_cookie'] = 1;
 
523
  if ( $params['action'] == 'create' ) {
524
  if ( apply_filters( 'frm_continue_to_create', true, $form_id ) && ! isset( $frm_vars['created_entries'][ $form_id ]['entry_id'] ) ) {
525
  $frm_vars['created_entries'][ $form_id ]['entry_id'] = FrmEntry::create( $_POST );
 
 
526
  }
527
  }
528
 
529
  do_action( 'frm_process_entry', $params, $errors, $form, array( 'ajax' => $ajax ) );
 
 
 
530
  unset( $_POST['frm_skip_cookie'] );
531
  }
532
  }
533
 
 
 
 
 
 
 
 
 
 
 
 
 
534
  public static function delete_entry_before_redirect( $url, $form, $atts ) {
535
  self::_delete_entry( $atts['id'], $form );
536
  return $url;
@@ -548,17 +583,27 @@ class FrmEntriesController {
548
 
549
  $form->options = maybe_unserialize( $form->options );
550
  if ( isset( $form->options['no_save'] ) && $form->options['no_save'] ) {
 
551
  FrmEntry::destroy( $entry_id );
552
  }
553
  }
554
 
 
 
 
 
 
 
 
 
 
555
  /**
556
  * @param $atts
557
  *
558
  * @return array|string
559
  */
560
  public static function show_entry_shortcode( $atts ) {
561
- $defaults = array(
562
  'id' => false,
563
  'entry' => false,
564
  'fields' => false,
@@ -581,7 +626,8 @@ class FrmEntriesController {
581
  'include_fields' => '',
582
  'include_extras' => '',
583
  'inline_style' => 1,
584
- );
 
585
 
586
  $atts = shortcode_atts( $defaults, $atts );
587
 
@@ -603,11 +649,6 @@ class FrmEntriesController {
603
  return $formatted_entry;
604
  }
605
 
606
- public static function get_params( $form = null ) {
607
- _deprecated_function( __FUNCTION__, '2.0.9', 'FrmForm::get_params' );
608
- return FrmForm::get_params( $form );
609
- }
610
-
611
  public static function entry_sidebar( $entry ) {
612
  $data = maybe_unserialize( $entry->description );
613
  $date_format = get_option( 'date_format' );
@@ -618,38 +659,4 @@ class FrmEntriesController {
618
 
619
  include( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/sidebar-shared.php' );
620
  }
621
-
622
- /***********************************************************************
623
- * Deprecated Functions
624
- ************************************************************************/
625
-
626
- /**
627
- * @deprecated 2.02.14
628
- *
629
- * @return mixed
630
- */
631
- public static function filter_email_value( $value ) {
632
- _deprecated_function( __FUNCTION__, '2.02.14', 'FrmProEntriesController::filter_value_in_single_entry_table' );
633
- return $value;
634
- }
635
-
636
- /**
637
- * @deprecated 2.02.14
638
- *
639
- * @return mixed
640
- */
641
- public static function filter_display_value( $value ) {
642
- _deprecated_function( __FUNCTION__, '2.02.14', 'FrmProEntriesController::filter_display_value' );
643
- return $value;
644
- }
645
-
646
- /**
647
- * @deprecated 2.03.04
648
- *
649
- * @return mixed
650
- */
651
- public static function filter_shortcode_value( $value ) {
652
- _deprecated_function( __FUNCTION__, '2.03.04', 'custom code' );
653
- return $value;
654
- }
655
  }
14
  * @since 2.05.07
15
  */
16
  private static function load_manage_entries_hooks() {
17
+ if ( ! in_array( FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' ), array( 'edit', 'show', 'new' ) ) ) {
18
  $menu_name = FrmAppHelper::get_menu_name();
19
  $base = self::base_column_key( $menu_name );
20
 
21
  add_filter( 'manage_' . $base . '_columns', 'FrmEntriesController::manage_columns' );
22
  add_filter( 'get_user_option_' . self::hidden_column_key( $menu_name ), 'FrmEntriesController::hidden_columns' );
23
  add_filter( 'manage_' . $base . '_sortable_columns', 'FrmEntriesController::sortable_columns' );
24
+ } else {
25
+ add_filter( 'screen_options_show_screen', __CLASS__ . '::remove_screen_options', 10, 2 );
26
  }
27
  }
28
 
54
 
55
  $action = FrmAppHelper::simple_get( 'frm_action', 'sanitize_title' );
56
  $page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
57
+ $show_help = ( $page == 'formidable-entries' && ( empty( $action ) || $action == 'list' ) );
58
+ if ( ! $show_help ) {
59
  return $help;
60
  }
61
 
76
  return $help;
77
  }
78
 
79
+ /**
80
+ * Prevent the "screen options" tab from showing when
81
+ * editing or creating an entry
82
+ *
83
+ * @since 3.0
84
+ */
85
+ public static function remove_screen_options( $show_screen, $screen ) {
86
+ $menu_name = sanitize_title( FrmAppHelper::get_menu_name() );
87
+ if ( $screen->id == $menu_name . '_page_formidable-entries' ) {
88
+ $show_screen = false;
89
+ }
90
+
91
+ return $show_screen;
92
+ }
93
+
94
  public static function manage_columns( $columns ) {
95
  global $frm_vars;
96
  $form_id = FrmForm::get_current_form_id();
429
 
430
  $fields = FrmField::get_all_for_form( $entry->form_id, '', 'include' );
431
  $to_emails = array();
432
+ $form = FrmForm::getOne( $entry->form_id );
433
 
434
  include( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/show.php' );
435
  }
440
  $params = FrmForm::get_admin_params();
441
 
442
  if ( isset( $params['keep_post'] ) && $params['keep_post'] ) {
443
+ self::unlink_post( $params['id'] );
 
 
444
  }
445
 
446
  $message = '';
537
 
538
  if ( empty( $errors ) ) {
539
  $_POST['frm_skip_cookie'] = 1;
540
+ $do_success = false;
541
  if ( $params['action'] == 'create' ) {
542
  if ( apply_filters( 'frm_continue_to_create', true, $form_id ) && ! isset( $frm_vars['created_entries'][ $form_id ]['entry_id'] ) ) {
543
  $frm_vars['created_entries'][ $form_id ]['entry_id'] = FrmEntry::create( $_POST );
544
+ $params['id'] = $frm_vars['created_entries'][ $form_id ]['entry_id'];
545
+ $do_success = true;
546
  }
547
  }
548
 
549
  do_action( 'frm_process_entry', $params, $errors, $form, array( 'ajax' => $ajax ) );
550
+ if ( $do_success ) {
551
+ FrmFormsController::maybe_trigger_redirect( $form, $params, array( 'ajax' => $ajax ) );
552
+ }
553
  unset( $_POST['frm_skip_cookie'] );
554
  }
555
  }
556
 
557
+ /**
558
+ * Escape url entities before redirect
559
+ *
560
+ * @since 3.0
561
+ *
562
+ * @param string $url
563
+ * @return string
564
+ */
565
+ public static function prepare_redirect_url( $url ) {
566
+ return str_replace( array( ' ', '[', ']', '|', '@' ), array( '%20', '%5B', '%5D', '%7C', '%40' ), $url );
567
+ }
568
+
569
  public static function delete_entry_before_redirect( $url, $form, $atts ) {
570
  self::_delete_entry( $atts['id'], $form );
571
  return $url;
583
 
584
  $form->options = maybe_unserialize( $form->options );
585
  if ( isset( $form->options['no_save'] ) && $form->options['no_save'] ) {
586
+ self::unlink_post( $entry_id );
587
  FrmEntry::destroy( $entry_id );
588
  }
589
  }
590
 
591
+ /**
592
+ * unlink entry from post
593
+ */
594
+ private static function unlink_post( $entry_id ) {
595
+ global $wpdb;
596
+ $wpdb->update( $wpdb->prefix . 'frm_items', array( 'post_id' => '' ), array( 'id' => $entry_id ) );
597
+ FrmEntry::clear_cache();
598
+ }
599
+
600
  /**
601
  * @param $atts
602
  *
603
  * @return array|string
604
  */
605
  public static function show_entry_shortcode( $atts ) {
606
+ $defaults = apply_filters( 'frm_show_entry_defaults', array(
607
  'id' => false,
608
  'entry' => false,
609
  'fields' => false,
626
  'include_fields' => '',
627
  'include_extras' => '',
628
  'inline_style' => 1,
629
+ 'child_array' => false, // return embedded fields as nested array
630
+ ) );
631
 
632
  $atts = shortcode_atts( $defaults, $atts );
633
 
649
  return $formatted_entry;
650
  }
651
 
 
 
 
 
 
652
  public static function entry_sidebar( $entry ) {
653
  $data = maybe_unserialize( $entry->description );
654
  $date_format = get_option( 'date_format' );
659
 
660
  include( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/sidebar-shared.php' );
661
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
  }
classes/controllers/FrmFieldsController.php CHANGED
@@ -14,36 +14,32 @@ class FrmFieldsController {
14
  $_GET['page'] = 'formidable';
15
  $fields = stripslashes_deep( $fields );
16
 
17
- $ajax = true;
18
- $values = array( 'id' => FrmAppHelper::get_post_param( 'form_id', '', 'absint' ) );
19
- $path = FrmAppHelper::plugin_path();
 
20
  $field_html = array();
21
 
22
  foreach ( $fields as $field ) {
23
- $field = htmlspecialchars_decode( nl2br( $field ) );
24
- $field = json_decode( $field, true );
25
- if ( ! isset( $field['id'] ) ) {
26
- // this field may have already been loaded
27
- continue;
28
- }
29
-
30
- $field_id = absint( $field['id'] );
31
-
32
- if ( ! isset( $field['value'] ) ) {
33
- $field['value'] = '';
34
- }
35
 
36
- $field_name = 'item_meta[' . $field_id . ']';
37
- $html_id = FrmFieldsHelper::get_html_id( $field );
 
 
 
38
 
39
- ob_start();
40
- include( $path . '/classes/views/frm-forms/add_field.php' );
41
- $field_html[ $field_id ] = ob_get_contents();
42
- ob_end_clean();
43
  }
44
 
45
- unset( $path );
46
-
47
  echo json_encode( $field_html );
48
 
49
  wp_die();
@@ -89,12 +85,15 @@ class FrmFieldsController {
89
  return false;
90
  }
91
 
92
- $field = self::include_single_field( $field_id, $values, $form_id );
 
93
 
94
  return $field;
95
  }
96
 
97
  public static function edit_name( $field = 'name', $id = '' ) {
 
 
98
  FrmAppHelper::permission_check( 'frm_edit_forms' );
99
  check_ajax_referer( 'frm_ajax', 'nonce' );
100
 
@@ -150,8 +149,6 @@ class FrmFieldsController {
150
  FrmAppHelper::permission_check( 'frm_edit_forms' );
151
  check_ajax_referer( 'frm_ajax', 'nonce' );
152
 
153
- global $wpdb;
154
-
155
  $field_id = FrmAppHelper::get_post_param( 'field_id', 0, 'absint' );
156
  $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
157
 
@@ -168,31 +165,95 @@ class FrmFieldsController {
168
  $values = apply_filters( 'frm_prepare_single_field_for_duplication', $values );
169
 
170
  $field_id = FrmField::create( $values );
171
- if ( ! $field_id ) {
172
- wp_die();
173
  }
174
 
175
- self::include_single_field( $field_id, $values );
176
-
177
  wp_die();
178
  }
179
 
180
- /**
181
- * Load a single field in the form builder along with all needed variables
182
- */
183
- public static function include_single_field( $field_id, $values, $form_id = 0 ) {
 
 
 
 
 
 
 
 
184
  $field = FrmFieldsHelper::setup_edit_vars( FrmField::getOne( $field_id ) );
185
- $field_name = 'item_meta[' . $field_id . ']';
186
- $html_id = FrmFieldsHelper::get_html_id( $field );
187
- $id = $form_id ? $form_id : $field['form_id'];
188
- if ( $field['type'] == 'html' ) {
189
- $field['stop_filter'] = true;
190
- }
191
 
192
- require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/add_field.php' );
 
193
 
194
- return $field;
195
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
  public static function destroy() {
198
  FrmAppHelper::permission_check( 'frm_edit_forms' );
@@ -216,30 +277,23 @@ class FrmFieldsController {
216
 
217
  $field = FrmField::getOne( $id );
218
 
219
- if ( 'other' == $opt_type ) {
220
  $opt = __( 'Other', 'formidable' );
221
- $other_val = '';
222
- $opt_key = 'other_' . $opt_key;
223
- } else {
224
  $opt = __( 'New Option', 'formidable' );
225
- }
226
- $field_val = $opt;
227
 
228
- $field_data = $field;
229
  $field = (array) $field;
230
  $field['separate_value'] = isset( $field_data->field_options['separate_value'] ) ? $field_data->field_options['separate_value'] : 0;
231
  unset( $field_data );
 
232
 
233
- $field_name = 'item_meta[' . $id . ']';
234
- $html_id = FrmFieldsHelper::get_html_id( $field );
235
- $checked = '';
236
 
237
- if ( 'other' == $opt_type ) {
238
- include( FrmAppHelper::plugin_path() . '/pro/classes/views/frmpro-fields/other-option.php' );
239
- } else {
240
- require( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/single-option.php' );
241
- }
242
- wp_die();
243
  }
244
 
245
  public static function edit_option() {
@@ -348,16 +402,7 @@ class FrmFieldsController {
348
 
349
  $field['options'] = $opts;
350
 
351
- if ( $field['type'] == 'radio' || $field['type'] == 'checkbox' ) {
352
- $field_name = 'item_meta[' . $field['id'] . ']';
353
-
354
- // Get html_id which will be used in single-option.php
355
- $html_id = FrmFieldsHelper::get_html_id( $field );
356
-
357
- require( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/radio.php' );
358
- } else {
359
- FrmFieldsHelper::show_single_option( $field );
360
- }
361
 
362
  wp_die();
363
  }
@@ -376,9 +421,11 @@ class FrmFieldsController {
376
  public static function change_type( $type ) {
377
  $type_switch = array(
378
  'scale' => 'radio',
 
379
  '10radio' => 'radio',
380
  'rte' => 'textarea',
381
  'website' => 'url',
 
382
  );
383
  if ( isset( $type_switch[ $type ] ) ) {
384
  $type = $type_switch[ $type ];
@@ -393,36 +440,31 @@ class FrmFieldsController {
393
  return $type;
394
  }
395
 
396
- public static function display_field_options( $display ) {
397
- switch ( $display['type'] ) {
398
- case 'captcha':
399
- $display['required'] = false;
400
- $display['invalid'] = true;
401
- $display['default_blank'] = false;
402
- $display['captcha_size'] = true;
403
- break;
404
- case 'radio':
405
- $display['default_blank'] = false;
406
- break;
407
- case 'text':
408
- case 'textarea':
409
- $display['size'] = true;
410
- $display['clear_on_focus'] = true;
411
- break;
412
- case 'select':
413
- $display['size'] = true;
414
- break;
415
- case 'url':
416
- case 'website':
417
- case 'email':
418
- $display['size'] = true;
419
- $display['clear_on_focus'] = true;
420
- $display['invalid'] = true;
421
- }
422
 
423
- return $display;
424
  }
425
 
 
 
 
 
 
 
 
 
 
 
426
  public static function input_html( $field, $echo = true ) {
427
  $class = array(); //$field['type'];
428
  self::add_input_classes( $field, $class );
@@ -437,7 +479,8 @@ class FrmFieldsController {
437
 
438
  FrmFormsHelper::add_html_attr( $class, 'class', $add_html );
439
 
440
- self::add_shortcodes_to_html( $field, $add_html );
 
441
 
442
  $add_html = apply_filters( 'frm_field_extra_html', $add_html, $field );
443
  $add_html = ' ' . implode( ' ', $add_html ) . ' ';
@@ -577,6 +620,10 @@ class FrmFieldsController {
577
  * get the label to use as the placeholder
578
  *
579
  * @since 2.05
 
 
 
 
580
  */
581
  public static function get_default_value_from_name( $field ) {
582
  $position = FrmField::get_option( $field, 'label' );
@@ -590,11 +637,13 @@ class FrmFieldsController {
590
 
591
  /**
592
  * use HMTL5 placeholder with js fallback
 
 
 
593
  */
594
  private static function add_placeholder_to_input( $field, &$add_html ) {
595
  if ( FrmFieldsHelper::is_placeholder_field_type( $field['type'] ) ) {
596
  $add_html['placeholder'] = 'placeholder="' . esc_attr( $field['default_value'] ) . '"';
597
- wp_enqueue_script( 'jquery-placeholder' );
598
  }
599
  }
600
 
@@ -638,6 +687,28 @@ class FrmFieldsController {
638
  }
639
  }
640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
641
  public static function check_value( $opt, $opt_key, $field ) {
642
  if ( is_array( $opt ) ) {
643
  if ( FrmField::is_option_true( $field, 'separate_value' ) ) {
14
  $_GET['page'] = 'formidable';
15
  $fields = stripslashes_deep( $fields );
16
 
17
+ $values = array(
18
+ 'id' => FrmAppHelper::get_post_param( 'form_id', '', 'absint' ),
19
+ 'doing_ajax' => true,
20
+ );
21
  $field_html = array();
22
 
23
  foreach ( $fields as $field ) {
24
+ $field = htmlspecialchars_decode( nl2br( $field ) );
25
+ $field = json_decode( $field );
26
+ if ( ! isset( $field->id ) || ! is_numeric( $field->id ) ) {
27
+ // this field may have already been loaded
28
+ continue;
29
+ }
 
 
 
 
 
 
30
 
31
+ if ( ! isset( $field->value ) ) {
32
+ $field->value = '';
33
+ }
34
+ $field->field_options = json_decode( json_encode( $field->field_options ), true );
35
+ $field->options = json_decode( json_encode( $field->options ), true );
36
 
37
+ ob_start();
38
+ self::load_single_field( $field, $values );
39
+ $field_html[ absint( $field->id ) ] = ob_get_contents();
40
+ ob_end_clean();
41
  }
42
 
 
 
43
  echo json_encode( $field_html );
44
 
45
  wp_die();
85
  return false;
86
  }
87
 
88
+ $field = self::get_field_array_from_id( $field_id );
89
+ self::load_single_field( $field, $values, $form_id );
90
 
91
  return $field;
92
  }
93
 
94
  public static function edit_name( $field = 'name', $id = '' ) {
95
+ _deprecated_function( __FUNCTION__, '3.0' );
96
+
97
  FrmAppHelper::permission_check( 'frm_edit_forms' );
98
  check_ajax_referer( 'frm_ajax', 'nonce' );
99
 
149
  FrmAppHelper::permission_check( 'frm_edit_forms' );
150
  check_ajax_referer( 'frm_ajax', 'nonce' );
151
 
 
 
152
  $field_id = FrmAppHelper::get_post_param( 'field_id', 0, 'absint' );
153
  $form_id = FrmAppHelper::get_post_param( 'form_id', 0, 'absint' );
154
 
165
  $values = apply_filters( 'frm_prepare_single_field_for_duplication', $values );
166
 
167
  $field_id = FrmField::create( $values );
168
+ if ( $field_id ) {
169
+ self::load_single_field( $field_id, $values );
170
  }
171
 
 
 
172
  wp_die();
173
  }
174
 
175
+ /**
176
+ * Load a single field in the form builder along with all needed variables
177
+ *
178
+ * @param int $field_id
179
+ * @param array $values
180
+ * @param int $form_id
181
+ *
182
+ * @return array
183
+ */
184
+ public static function include_single_field( $field_id, $values, $form_id = 0 ) {
185
+ _deprecated_function( __FUNCTION__, '3.0', 'FrmFieldsController::load_single_field' );
186
+
187
  $field = FrmFieldsHelper::setup_edit_vars( FrmField::getOne( $field_id ) );
188
+ self::load_single_field( $field, $values, $form_id );
 
 
 
 
 
189
 
190
+ return $field;
191
+ }
192
 
193
+ /**
194
+ * @since 3.0
195
+ *
196
+ * @param int $field_id
197
+ *
198
+ * @return array
199
+ */
200
+ public static function get_field_array_from_id( $field_id ) {
201
+ $field = FrmField::getOne( $field_id );
202
+ return FrmFieldsHelper::setup_edit_vars( $field );
203
+ }
204
+
205
+ /**
206
+ * @since 3.0
207
+ *
208
+ * @param int|array|object $field_object
209
+ * @param array $values
210
+ * @param int $form_id
211
+ */
212
+ public static function load_single_field( $field_object, $values, $form_id = 0 ) {
213
+ if ( is_numeric( $field_object ) ) {
214
+ $field_object = FrmField::getOne( $field_object );
215
+ } elseif ( is_array( $field_object ) ) {
216
+ $field = $field_object;
217
+ $field_object = FrmField::getOne( $field['id'] );
218
+ }
219
+
220
+ $field_obj = FrmFieldFactory::get_field_factory( $field_object );
221
+ $display = self::display_field_options( array(), $field_obj );
222
+
223
+ $ajax_loading = isset( $values['ajax_load'] ) && $values['ajax_load'];
224
+ $ajax_this_field = isset( $values['count'] ) && $values['count'] > 10 && ! in_array( $field_object->type, array( 'divider', 'end_divider' ) );
225
+
226
+ if ( $ajax_loading && $ajax_this_field ) {
227
+ $li_classes = self::get_classes_for_builder_field( array(), $display, $field_obj );
228
+ include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/ajax-field-placeholder.php' );
229
+ } else {
230
+ $frm_settings = FrmAppHelper::get_settings();
231
+
232
+ $pro_field_selection = FrmField::pro_field_selection();
233
+ $frm_all_field_selection = array_merge( FrmField::field_selection(), $pro_field_selection );
234
+ $disabled_fields = FrmAppHelper::pro_is_installed() ? array() : $pro_field_selection;
235
+
236
+ if ( ! isset( $field ) && is_object( $field_object ) ) {
237
+ $field = FrmFieldsHelper::setup_edit_vars( $field_object );
238
+ }
239
+
240
+ $li_classes = self::get_classes_for_builder_field( $field, $display, $field_obj );
241
+ $li_classes .= ' ui-state-default widgets-holder-wrap';
242
+
243
+ require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/add_field.php' );
244
+ }
245
+ }
246
+
247
+ /**
248
+ * @since 3.0
249
+ */
250
+ private static function get_classes_for_builder_field( $field, $display, $field_info ) {
251
+ $li_classes = $field_info->form_builder_classes( $display['type'] );
252
+ if ( ! empty( $field ) ) {
253
+ $li_classes = apply_filters( 'frm_build_field_class', $li_classes, $field );
254
+ }
255
+ return $li_classes;
256
+ }
257
 
258
  public static function destroy() {
259
  FrmAppHelper::permission_check( 'frm_edit_forms' );
277
 
278
  $field = FrmField::getOne( $id );
279
 
280
+ if ( 'other' == $opt_type ) {
281
  $opt = __( 'Other', 'formidable' );
282
+ $opt_key = 'other_' . $opt_key;
283
+ } else {
 
284
  $opt = __( 'New Option', 'formidable' );
285
+ }
 
286
 
287
+ $field_data = $field;
288
  $field = (array) $field;
289
  $field['separate_value'] = isset( $field_data->field_options['separate_value'] ) ? $field_data->field_options['separate_value'] : 0;
290
  unset( $field_data );
291
+ $field['html_name'] = 'item_meta[' . $field['id'] . ']';
292
 
293
+ $field['options'] = array( $opt_key => $opt );
294
+ FrmFieldsHelper::show_single_option( $field );
 
295
 
296
+ wp_die();
 
 
 
 
 
297
  }
298
 
299
  public static function edit_option() {
402
 
403
  $field['options'] = $opts;
404
 
405
+ FrmFieldsHelper::show_single_option( $field );
 
 
 
 
 
 
 
 
 
406
 
407
  wp_die();
408
  }
421
  public static function change_type( $type ) {
422
  $type_switch = array(
423
  'scale' => 'radio',
424
+ 'star' => 'radio',
425
  '10radio' => 'radio',
426
  'rte' => 'textarea',
427
  'website' => 'url',
428
+ 'image' => 'url',
429
  );
430
  if ( isset( $type_switch[ $type ] ) ) {
431
  $type = $type_switch[ $type ];
440
  return $type;
441
  }
442
 
443
+ /**
444
+ * @param array $settings
445
+ * @param object $field_info
446
+ *
447
+ * @return array
448
+ */
449
+ public static function display_field_options( $settings, $field_info = null ) {
450
+ if ( $field_info ) {
451
+ $settings = $field_info->display_field_settings();
452
+ $settings['field_data'] = $field_info->field;
453
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
454
 
455
+ return apply_filters( 'frm_display_field_options', $settings );
456
  }
457
 
458
+ /**
459
+ * Display the format option
460
+ *
461
+ * @since 3.0
462
+ * @param array $field
463
+ */
464
+ public static function show_format_option( $field ) {
465
+ include( FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/value-format.php' );
466
+ }
467
+
468
  public static function input_html( $field, $echo = true ) {
469
  $class = array(); //$field['type'];
470
  self::add_input_classes( $field, $class );
479
 
480
  FrmFormsHelper::add_html_attr( $class, 'class', $add_html );
481
 
482
+ self::add_shortcodes_to_html( $field, $add_html );
483
+ self::add_pattern_attribute( $field, $add_html );
484
 
485
  $add_html = apply_filters( 'frm_field_extra_html', $add_html, $field );
486
  $add_html = ' ' . implode( ' ', $add_html ) . ' ';
620
  * get the label to use as the placeholder
621
  *
622
  * @since 2.05
623
+ *
624
+ * @param array $field
625
+ *
626
+ * @return string
627
  */
628
  public static function get_default_value_from_name( $field ) {
629
  $position = FrmField::get_option( $field, 'label' );
637
 
638
  /**
639
  * use HMTL5 placeholder with js fallback
640
+ *
641
+ * @param array $field
642
+ * @param array $add_html
643
  */
644
  private static function add_placeholder_to_input( $field, &$add_html ) {
645
  if ( FrmFieldsHelper::is_placeholder_field_type( $field['type'] ) ) {
646
  $add_html['placeholder'] = 'placeholder="' . esc_attr( $field['default_value'] ) . '"';
 
647
  }
648
  }
649
 
687
  }
688
  }
689
 
690
+ /**
691
+ * Add pattern attribute
692
+ *
693
+ * @since 3.0
694
+ * @param array $field
695
+ * @param array $add_html
696
+ */
697
+ private static function add_pattern_attribute( $field, array &$add_html ) {
698
+ $has_format = FrmField::is_option_true_in_array( $field, 'format' );
699
+ $format_field = FrmField::is_field_type( $field, 'text' );
700
+
701
+ if ( $field['type'] == 'phone' || ( $has_format && $format_field ) ) {
702
+ $frm_settings = FrmAppHelper::get_settings();
703
+
704
+ if ( $frm_settings->use_html ) {
705
+ $format = FrmEntryValidate::phone_format( $field );
706
+ $format = substr( $format, 2, -1 );
707
+ $add_html['pattern'] = 'pattern="' . esc_attr( $format ) . '"';
708
+ }
709
+ }
710
+ }
711
+
712
  public static function check_value( $opt, $opt_key, $field ) {
713
  if ( is_array( $opt ) ) {
714
  if ( FrmField::is_option_true( $field, 'separate_value' ) ) {
classes/controllers/FrmFormsController.php CHANGED
@@ -18,10 +18,10 @@ class FrmFormsController {
18
  return;
19
  }
20
 
21
- add_filter('get_user_option_managetoplevel_page_formidablecolumnshidden', 'FrmFormsController::hidden_columns' );
22
 
23
- add_filter('manage_toplevel_page_formidable_columns', 'FrmFormsController::get_columns', 0 );
24
- add_filter('manage_toplevel_page_formidable_sortable_columns', 'FrmFormsController::get_sortable_columns' );
25
  }
26
 
27
  public static function head() {
@@ -117,7 +117,8 @@ class FrmFormsController {
117
  $form = FrmForm::getOne( $id );
118
  $fields = FrmField::get_all_for_form($id);
119
 
120
- $values = FrmAppHelper::setup_edit_vars($form, 'forms', $fields, true);
 
121
  $all_templates = FrmForm::getAll( array( 'is_template' => 1 ), 'name' );
122
 
123
  require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/new.php' );
@@ -163,18 +164,21 @@ class FrmFormsController {
163
  }
164
 
165
  public static function edit_key() {
 
166
  $values = self::edit_in_place_value( 'form_key' );
167
- echo wp_kses( stripslashes( FrmForm::getKeyById( $values['form_id'] ) ), array() );
168
  wp_die();
169
  }
170
 
171
  public static function edit_description() {
 
172
  $values = self::edit_in_place_value( 'description' );
173
  echo wp_kses_post( FrmAppHelper::use_wpautop( stripslashes( $values['description'] ) ) );
174
  wp_die();
175
  }
176
 
177
  private static function edit_in_place_value( $field ) {
 
178
  check_ajax_referer( 'frm_ajax', 'nonce' );
179
  FrmAppHelper::permission_check('frm_edit_forms', 'hide');
180
 
@@ -218,16 +222,6 @@ class FrmFormsController {
218
  }
219
  }
220
 
221
- public static function bulk_create_template( $ids ) {
222
- FrmAppHelper::permission_check( 'frm_edit_forms' );
223
-
224
- foreach ( $ids as $id ) {
225
- FrmForm::duplicate( $id, true, true );
226
- }
227
-
228
- return __( 'Form template was Successfully Created', 'formidable' );
229
- }
230
-
231
  /**
232
  * Redirect to the url for creating from a template
233
  * Also delete the current form
@@ -244,7 +238,7 @@ class FrmFormsController {
244
  FrmForm::destroy( $current_form );
245
  }
246
 
247
- echo esc_url_raw( admin_url( 'admin.php?page=formidable&action=duplicate&id=' . $template_id ) );
248
  wp_die();
249
  }
250
 
@@ -268,26 +262,117 @@ class FrmFormsController {
268
  }
269
 
270
  $form = FrmForm::getOne( $params['form'] );
271
- if ( ! $form ) {
272
- return;
273
- }
274
- return self::show_form( $form->id, '', true, true );
275
  }
276
 
 
 
 
 
 
 
 
277
  public static function preview() {
278
  do_action( 'frm_wp' );
279
 
280
  global $frm_vars;
281
  $frm_vars['preview'] = true;
282
 
283
- if ( ! defined( 'ABSPATH' ) && ! defined( 'XMLRPC_REQUEST' ) ) {
284
- global $wp;
285
- $root = dirname( dirname( dirname( dirname( __FILE__ ) ) ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  include_once( $root . '/wp-config.php' );
287
- $wp->init();
288
- $wp->register_globals();
289
- }
 
290
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
292
 
293
  $key = FrmAppHelper::simple_get( 'form', 'sanitize_title' );
@@ -298,11 +383,10 @@ class FrmFormsController {
298
  $form = FrmForm::getAll( array( 'form_key' => $key ), '', 1 );
299
  if ( empty( $form ) ) {
300
  $form = FrmForm::getAll( array(), '', 1 );
301
- }
302
 
303
  require( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/direct.php' );
304
- wp_die();
305
- }
306
 
307
  public static function register_pro_scripts() {
308
  _deprecated_function( __FUNCTION__, '2.03', 'FrmProEntriesController::register_scripts' );
@@ -441,11 +525,6 @@ class FrmFormsController {
441
  self::display_forms_list( array(), $message );
442
  }
443
 
444
- public static function scheduled_delete( $delete_timestamp = '' ) {
445
- _deprecated_function( __FUNCTION__, '2.0.9', 'FrmForm::scheduled_delete' );
446
- return FrmForm::scheduled_delete( $delete_timestamp );
447
- }
448
-
449
  /**
450
  * Inserts Formidable button
451
  * Hook exists since 2.5.0
@@ -530,12 +609,8 @@ class FrmFormsController {
530
  wp_die();
531
  }
532
 
533
- public static function display_forms_list( $params = array(), $message = '', $errors = array(), $deprecated_errors = array() ) {
534
  FrmAppHelper::permission_check( 'frm_view_forms' );
535
- if ( ! empty( $deprecated_errors ) ) {
536
- $errors = $deprecated_errors;
537
- _deprecated_argument( 'errors', '2.0.8' );
538
- }
539
 
540
  global $wpdb, $frm_vars;
541
 
@@ -647,7 +722,8 @@ class FrmFormsController {
647
  unset($end_section_values, $last_order, $open, $reset_fields);
648
 
649
  $args = array( 'parent_form_id' => $form->id );
650
- $values = FrmAppHelper::setup_edit_vars( $form, 'forms', $fields, true, array(), $args );
 
651
 
652
  $edit_message = __( 'Form was Successfully Updated', 'formidable' );
653
  if ( $form->is_template && $message == $edit_message ) {
@@ -690,6 +766,8 @@ class FrmFormsController {
690
 
691
  $styles = apply_filters('frm_get_style_opts', array());
692
 
 
 
693
  require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/settings.php' );
694
  }
695
 
@@ -769,12 +847,6 @@ class FrmFormsController {
769
  $entry_shortcodes['default-message'] = __( 'Default Msg', 'formidable' );
770
  $entry_shortcodes['default-html'] = __( 'Default HTML', 'formidable' );
771
  $entry_shortcodes['default-plain'] = __( 'Default Plain', 'formidable' );
772
- } else {
773
- $entry_shortcodes['detaillink'] = __( 'Detail Link', 'formidable' );
774
- $entry_shortcodes['editlink location="front" label="Edit" page_id=x'] = __( 'Edit Entry Link', 'formidable' );
775
- $entry_shortcodes['evenodd'] = __( 'Even/Odd', 'formidable' );
776
- $entry_shortcodes['entry_count'] = __( 'Entry Count', 'formidable' );
777
- $entry_shortcodes['event_date format="Y-m-d"'] = __( 'Calendar Date', 'formidable' );
778
  }
779
 
780
  /**
@@ -787,22 +859,29 @@ class FrmFormsController {
787
  return $entry_shortcodes;
788
  }
789
 
790
- // Insert the form class setting into the form
 
 
791
  public static function form_classes( $form ) {
792
- if ( isset($form->options['form_class']) ) {
793
  echo esc_attr( sanitize_text_field( $form->options['form_class'] ) );
794
- }
795
- }
 
 
 
 
 
 
 
 
796
 
797
- public static function get_email_html() {
798
- FrmAppHelper::permission_check('frm_view_forms');
799
- check_ajax_referer( 'frm_ajax', 'nonce' );
800
  echo FrmEntriesController::show_entry_shortcode( array(
801
  'form_id' => FrmAppHelper::get_post_param( 'form_id', '', 'absint' ),
802
- 'default_email' => true,
803
  'plain_text' => FrmAppHelper::get_post_param( 'plain_text', '', 'absint' ),
804
- ) );
805
- wp_die();
806
  }
807
 
808
  public static function filter_content( $content, $form, $entry = false ) {
@@ -876,13 +955,10 @@ class FrmFormsController {
876
  break;
877
  case 'untrash':
878
  $message = self::bulk_untrash( $ids );
879
- break;
880
- case 'create_template':
881
- $message = self::bulk_create_template( $ids );
882
  }
883
 
884
  if ( isset( $message ) && ! empty( $message ) ) {
885
- echo '<div id="message" class="updated frm_msg_padding">' . FrmAppHelper::kses( $message, array( 'a' ) ) . '</div>';
886
  }
887
 
888
  return $errors;
@@ -1171,6 +1247,8 @@ class FrmFormsController {
1171
  public static function get_form( $form, $title, $description, $atts = array() ) {
1172
  ob_start();
1173
 
 
 
1174
  self::get_form_contents( $form, $title, $description, $atts );
1175
  self::enqueue_scripts( FrmForm::get_params( $form ) );
1176
 
@@ -1209,18 +1287,15 @@ class FrmFormsController {
1209
 
1210
  if ( apply_filters( 'frm_continue_to_create', true, $form->id ) ) {
1211
  $entry_id = self::just_created_entry( $form->id );
 
 
 
 
 
1212
 
1213
- $conf_method = apply_filters( 'frm_success_filter', 'message', $form, 'create' );
1214
- if ( $entry_id && is_numeric( $entry_id ) && $conf_method != 'message' ) {
1215
- self::run_success_action( compact( 'entry_id', 'form', 'conf_method' ) );
1216
- } else {
1217
- $pass_args['reset'] = true;
1218
- $pass_args['entry_id'] = $entry_id;
1219
- self::show_message_after_save( $pass_args );
1220
- }
1221
  do_action( 'frm_after_entry_processed', array(
1222
  'entry_id' => $entry_id,
1223
- 'form' => $form,
1224
  ) );
1225
  }
1226
  }
@@ -1249,12 +1324,143 @@ class FrmFormsController {
1249
  return ( isset( $frm_vars['created_entries'] ) && isset( $frm_vars['created_entries'][ $form_id ] ) && isset( $frm_vars['created_entries'][ $form_id ]['entry_id'] ) ) ? $frm_vars['created_entries'][ $form_id ]['entry_id'] : 0;
1250
  }
1251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1252
  /**
1253
  * Used when the success action is not 'message'
1254
  * @since 2.05
1255
  */
1256
  public static function run_success_action( $args ) {
1257
- do_action( 'frm_success_action', $args['conf_method'], $args['form'], $args['form']->options, $args['entry_id'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1258
  }
1259
 
1260
  /**
@@ -1354,9 +1560,14 @@ class FrmFormsController {
1354
 
1355
  public static function front_head() {
1356
  $version = FrmAppHelper::plugin_version();
1357
- $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
1358
- wp_register_script( 'formidable', FrmAppHelper::plugin_url() . "/js/formidable{$suffix}.js", array( 'jquery' ), $version, true );
1359
- wp_register_script( 'jquery-placeholder', FrmAppHelper::plugin_url() . '/js/jquery/jquery.placeholder.min.js', array( 'jquery' ), '2.3.1', true );
 
 
 
 
 
1360
  add_filter( 'script_loader_tag', 'FrmFormsController::defer_script_loading', 10, 2 );
1361
 
1362
  if ( FrmAppHelper::is_admin() ) {
@@ -1368,6 +1579,13 @@ class FrmFormsController {
1368
  FrmStylesController::enqueue_css( 'register' );
1369
  }
1370
 
 
 
 
 
 
 
 
1371
  public static function maybe_load_css( $form, $this_load, $global_load ) {
1372
  $load_css = FrmForm::is_form_loaded( $form, $this_load, $global_load );
1373
 
@@ -1413,4 +1631,15 @@ class FrmFormsController {
1413
  private static function is_minification_on( $atts ) {
1414
  return isset( $atts['minimize'] ) && ! empty( $atts['minimize'] );
1415
  }
 
 
 
 
 
 
 
 
 
 
 
1416
  }
18
  return;
19
  }
20
 
21
+ add_filter( 'get_user_option_managetoplevel_page_formidablecolumnshidden', 'FrmFormsController::hidden_columns' );
22
 
23
+ add_filter( 'manage_toplevel_page_formidable_columns', 'FrmFormsController::get_columns', 0 );
24
+ add_filter( 'manage_toplevel_page_formidable_sortable_columns', 'FrmFormsController::get_sortable_columns' );
25
  }
26
 
27
  public static function head() {
117
  $form = FrmForm::getOne( $id );
118
  $fields = FrmField::get_all_for_form($id);
119
 
120
+ $values = FrmAppHelper::setup_edit_vars($form, 'forms', '', true);
121
+ $values['fields'] = $fields;
122
  $all_templates = FrmForm::getAll( array( 'is_template' => 1 ), 'name' );
123
 
124
  require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/new.php' );
164
  }
165
 
166
  public static function edit_key() {
167
+ _deprecated_function( __METHOD__, '3.0' );
168
  $values = self::edit_in_place_value( 'form_key' );
169
+ echo wp_kses( stripslashes( FrmForm::get_key_by_id( $values['form_id'] ) ), array() );
170
  wp_die();
171
  }
172
 
173
  public static function edit_description() {
174
+ _deprecated_function( __METHOD__, '3.0' );
175
  $values = self::edit_in_place_value( 'description' );
176
  echo wp_kses_post( FrmAppHelper::use_wpautop( stripslashes( $values['description'] ) ) );
177
  wp_die();
178
  }
179
 
180
  private static function edit_in_place_value( $field ) {
181
+ _deprecated_function( __METHOD__, '3.0' );
182
  check_ajax_referer( 'frm_ajax', 'nonce' );
183
  FrmAppHelper::permission_check('frm_edit_forms', 'hide');
184
 
222
  }
223
  }
224
 
 
 
 
 
 
 
 
 
 
 
225
  /**
226
  * Redirect to the url for creating from a template
227
  * Also delete the current form
238
  FrmForm::destroy( $current_form );
239
  }
240
 
241
+ echo esc_url_raw( admin_url( 'admin.php?page=formidable&frm_action=duplicate&id=' . absint( $template_id ) ) );
242
  wp_die();
243
  }
244
 
262
  }
263
 
264
  $form = FrmForm::getOne( $params['form'] );
265
+ if ( $form ) {
266
+ return self::show_form( $form->id, '', true, true );
267
+ }
 
268
  }
269
 
270
+ /**
271
+ * @since 3.0
272
+ */
273
+ public static function show_page_preview() {
274
+ echo self::page_preview();
275
+ }
276
+
277
  public static function preview() {
278
  do_action( 'frm_wp' );
279
 
280
  global $frm_vars;
281
  $frm_vars['preview'] = true;
282
 
283
+ self::load_wp();
284
+
285
+ $include_theme = FrmAppHelper::get_param( 'theme', '', 'get', 'absint' );
286
+ if ( $include_theme ) {
287
+ self::set_preview_query();
288
+ self::load_theme_preview();
289
+ } else {
290
+ self::load_direct_preview();
291
+ }
292
+
293
+ wp_die();
294
+ }
295
+
296
+ /**
297
+ * @since 3.0
298
+ */
299
+ private static function load_wp() {
300
+ if ( ! defined( 'ABSPATH' ) && ! defined( 'XMLRPC_REQUEST' ) ) {
301
+ global $wp;
302
+ $root = dirname( dirname( dirname( dirname( __FILE__ ) ) ) );
303
  include_once( $root . '/wp-config.php' );
304
+ $wp->init();
305
+ $wp->register_globals();
306
+ }
307
+ }
308
 
309
+ private static function set_preview_query() {
310
+ $random_page = get_posts( array(
311
+ 'numberposts' => 1,
312
+ 'orderby' => 'date',
313
+ 'order' => 'ASC',
314
+ 'post_type' => 'page',
315
+ ) );
316
+
317
+ if ( ! empty( $random_page ) ) {
318
+ $random_page = reset( $random_page );
319
+ query_posts( array(
320
+ 'post_type' => 'page',
321
+ 'page_id' => $random_page->ID,
322
+ ) );
323
+ }
324
+ }
325
+
326
+ /**
327
+ * @since 3.0
328
+ */
329
+ private static function load_theme_preview() {
330
+ add_filter( 'wp_title', 'FrmFormsController::preview_title', 9999 );
331
+ add_filter( 'the_title', 'FrmFormsController::preview_page_title', 9999 );
332
+ add_filter( 'the_content', 'FrmFormsController::preview_content', 9999 );
333
+ add_action( 'loop_no_results', 'FrmFormsController::show_page_preview' );
334
+ add_filter( 'is_active_sidebar', '__return_false' );
335
+ get_template_part( 'page' );
336
+ }
337
+
338
+
339
+ /**
340
+ * Set the page title for the theme preview page
341
+ *
342
+ * @since 3.0
343
+ */
344
+ public static function preview_page_title( $title ) {
345
+ if ( in_the_loop() ) {
346
+ $title = self::preview_title( $title );
347
+ }
348
+ return $title;
349
+ }
350
+
351
+ /**
352
+ * Set the page title for the theme preview page
353
+ *
354
+ * @since 3.0
355
+ */
356
+ public static function preview_title( $title ) {
357
+ return __( 'Form Preview', 'formidable' );
358
+ }
359
+
360
+ /**
361
+ * Set the page content for the theme preview page
362
+ *
363
+ * @since 3.0
364
+ */
365
+ public static function preview_content( $content ) {
366
+ if ( in_the_loop() ) {
367
+ $content = FrmFormsController::show_page_preview();
368
+ }
369
+ return $content;
370
+ }
371
+
372
+ /**
373
+ * @since 3.0
374
+ */
375
+ private static function load_direct_preview() {
376
  header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
377
 
378
  $key = FrmAppHelper::simple_get( 'form', 'sanitize_title' );
383
  $form = FrmForm::getAll( array( 'form_key' => $key ), '', 1 );
384
  if ( empty( $form ) ) {
385
  $form = FrmForm::getAll( array(), '', 1 );
386
+ }
387
 
388
  require( FrmAppHelper::plugin_path() . '/classes/views/frm-entries/direct.php' );
389
+ }
 
390
 
391
  public static function register_pro_scripts() {
392
  _deprecated_function( __FUNCTION__, '2.03', 'FrmProEntriesController::register_scripts' );
525
  self::display_forms_list( array(), $message );
526
  }
527
 
 
 
 
 
 
528
  /**
529
  * Inserts Formidable button
530
  * Hook exists since 2.5.0
609
  wp_die();
610
  }
611
 
612
+ public static function display_forms_list( $params = array(), $message = '', $errors = array() ) {
613
  FrmAppHelper::permission_check( 'frm_view_forms' );
 
 
 
 
614
 
615
  global $wpdb, $frm_vars;
616
 
722
  unset($end_section_values, $last_order, $open, $reset_fields);
723
 
724
  $args = array( 'parent_form_id' => $form->id );
725
+ $values = FrmAppHelper::setup_edit_vars( $form, 'forms', '', true, array(), $args );
726
+ $values['fields'] = $fields;
727
 
728
  $edit_message = __( 'Form was Successfully Updated', 'formidable' );
729
  if ( $form->is_template && $message == $edit_message ) {
766
 
767
  $styles = apply_filters('frm_get_style_opts', array());
768
 
769
+ $first_h3 = 'frm_first_h3';
770
+
771
  require( FrmAppHelper::plugin_path() . '/classes/views/frm-forms/settings.php' );
772
  }
773
 
847
  $entry_shortcodes['default-message'] = __( 'Default Msg', 'formidable' );
848
  $entry_shortcodes['default-html'] = __( 'Default HTML', 'formidable' );
849
  $entry_shortcodes['default-plain'] = __( 'Default Plain', 'formidable' );
 
 
 
 
 
 
850
  }
851
 
852
  /**
859
  return $entry_shortcodes;
860
  }
861
 
862
+ /**
863
+ * Insert the form class setting into the form
864
+ */
865
  public static function form_classes( $form ) {
866
+ if ( isset($form->options['form_class']) ) {
867
  echo esc_attr( sanitize_text_field( $form->options['form_class'] ) );
868
+ }
869
+
870
+ if ( isset( $form->options['js_validate'] ) && $form->options['js_validate'] ) {
871
+ echo ' frm_js_validate ';
872
+ }
873
+ }
874
+
875
+ public static function get_email_html() {
876
+ FrmAppHelper::permission_check( 'frm_view_forms' );
877
+ check_ajax_referer( 'frm_ajax', 'nonce' );
878
 
 
 
 
879
  echo FrmEntriesController::show_entry_shortcode( array(
880
  'form_id' => FrmAppHelper::get_post_param( 'form_id', '', 'absint' ),
881
+ 'default_email' => true,
882
  'plain_text' => FrmAppHelper::get_post_param( 'plain_text', '', 'absint' ),
883
+ ) );
884
+ wp_die();
885
  }
886
 
887
  public static function filter_content( $content, $form, $entry = false ) {
955
  break;
956
  case 'untrash':
957
  $message = self::bulk_untrash( $ids );
 
 
 
958
  }
959
 
960
  if ( isset( $message ) && ! empty( $message ) ) {
961
+ echo '<div id="message" class="updated frm_updated_message">' . FrmAppHelper::kses( $message, array( 'a' ) ) . '</div>';
962
  }
963
 
964
  return $errors;
1247
  public static function get_form( $form, $title, $description, $atts = array() ) {
1248
  ob_start();
1249
 
1250
+ do_action( 'frm_before_get_form', $atts );
1251
+
1252
  self::get_form_contents( $form, $title, $description, $atts );
1253
  self::enqueue_scripts( FrmForm::get_params( $form ) );
1254
 
1287
 
1288
  if ( apply_filters( 'frm_continue_to_create', true, $form->id ) ) {
1289
  $entry_id = self::just_created_entry( $form->id );
1290
+ $pass_args['entry_id'] = $entry_id;
1291
+ $pass_args['reset'] = true;
1292
+ $pass_args['conf_method'] = self::get_confirmation_method( compact( 'form', 'entry_id' ) );
1293
+
1294
+ self::run_success_action( $pass_args );
1295
 
 
 
 
 
 
 
 
 
1296
  do_action( 'frm_after_entry_processed', array(
1297
  'entry_id' => $entry_id,
1298
+ 'form' => $form,
1299
  ) );
1300
  }
1301
  }
1324
  return ( isset( $frm_vars['created_entries'] ) && isset( $frm_vars['created_entries'][ $form_id ] ) && isset( $frm_vars['created_entries'][ $form_id ]['entry_id'] ) ) ? $frm_vars['created_entries'][ $form_id ]['entry_id'] : 0;
1325
  }
1326
 
1327
+ /**
1328
+ * @since 3.0
1329
+ */
1330
+ private static function get_confirmation_method( $atts ) {
1331
+ $opt = 'success_action';
1332
+ $method = ( isset( $atts['form']->options[ $opt ] ) && ! empty( $atts['form']->options[ $opt ] ) ) ? $atts['form']->options[ $opt ] : 'message';
1333
+ $method = apply_filters( 'frm_success_filter', $method, $atts['form'], 'create' );
1334
+
1335
+ if ( $method != 'message' && ( ! $atts['entry_id'] || ! is_numeric( $atts['entry_id'] ) ) ) {
1336
+ $method = 'message';
1337
+ }
1338
+
1339
+ return $method;
1340
+ }
1341
+
1342
+ public static function maybe_trigger_redirect( $form, $params, $args ) {
1343
+ if ( ! isset( $params['id'] ) ) {
1344
+ global $frm_vars;
1345
+ $params['id'] = $frm_vars['created_entries'][ $form->id ]['entry_id'];
1346
+ }
1347
+
1348
+ $conf_method = self::get_confirmation_method( array(
1349
+ 'form' => $form,
1350
+ 'entry_id' => $params['id'],
1351
+ ) );
1352
+
1353
+ if ( 'redirect' === $conf_method ) {
1354
+ self::trigger_redirect( $form, $params, $args );
1355
+ }
1356
+ }
1357
+
1358
+ public static function trigger_redirect( $form, $params, $args ) {
1359
+ $success_args = array(
1360
+ 'action' => $params['action'],
1361
+ 'conf_method' => 'redirect',
1362
+ 'form' => $form,
1363
+ 'entry_id' => $params['id'],
1364
+ );
1365
+
1366
+ if ( isset( $args['ajax'] ) ) {
1367
+ $success_args['ajax'] = $args['ajax'];
1368
+ }
1369
+
1370
+ self::run_success_action( $success_args );
1371
+ }
1372
+
1373
  /**
1374
  * Used when the success action is not 'message'
1375
  * @since 2.05
1376
  */
1377
  public static function run_success_action( $args ) {
1378
+ $extra_args = $args;
1379
+ unset( $extra_args['form'] );
1380
+
1381
+ do_action( 'frm_success_action', $args['conf_method'], $args['form'], $args['form']->options, $args['entry_id'], $extra_args );
1382
+
1383
+ $opt = ( ! isset( $args['action'] ) || $args['action'] == 'create' ) ? 'success' : 'edit';
1384
+ $args['success_opt'] = $opt;
1385
+ if ( $args['conf_method'] == 'page' && is_numeric( $args['form']->options[ $opt . '_page_id' ] ) ) {
1386
+ self::load_page_after_submit( $args );
1387
+ } elseif ( $args['conf_method'] == 'redirect' ) {
1388
+ self::redirect_after_submit( $args );
1389
+ } else {
1390
+ self::show_message_after_save( $args );
1391
+ }
1392
+ }
1393
+
1394
+ /**
1395
+ * @since 3.0
1396
+ */
1397
+ private static function load_page_after_submit( $args ) {
1398
+ global $post;
1399
+ $opt = $args['success_opt'];
1400
+ if ( ! $post || $args['form']->options[ $opt . '_page_id' ] != $post->ID ) {
1401
+ $page = get_post( $args['form']->options[ $opt . '_page_id' ] );
1402
+ $old_post = $post;
1403
+ $post = $page;
1404
+ $content = apply_filters( 'frm_content', $page->post_content, $args['form'], $args['entry_id'] );
1405
+ echo apply_filters( 'the_content', $content );
1406
+ $post = $old_post;
1407
+ }
1408
+ }
1409
+
1410
+ /**
1411
+ * @since 3.0
1412
+ */
1413
+ private static function redirect_after_submit( $args ) {
1414
+ global $frm_vars;
1415
+
1416
+ add_filter( 'frm_use_wpautop', '__return_false' );
1417
+
1418
+ $opt = $args['success_opt'];
1419
+ $success_url = trim( $args['form']->options[ $opt . '_url' ] );
1420
+ $success_url = apply_filters( 'frm_content', $success_url, $args['form'], $args['entry_id'] );
1421
+
1422
+ $success_msg = isset( $args['form']->options[ $opt . '_msg' ] ) ? $args['form']->options[ $opt . '_msg' ] : __( 'Please wait while you are redirected.', 'formidable' );
1423
+
1424
+ $redirect_msg = self::get_redirect_message( $success_url, $success_msg, $args );
1425
+
1426
+ $args['id'] = $args['entry_id'];
1427
+ FrmEntriesController::delete_entry_before_redirect( $success_url, $args['form'], $args );
1428
+
1429
+ add_filter( 'frm_redirect_url', 'FrmEntriesController::prepare_redirect_url' );
1430
+ $success_url = apply_filters( 'frm_redirect_url', $success_url, $args['form'], $args);
1431
+
1432
+ $doing_ajax = FrmAppHelper::doing_ajax();
1433
+
1434
+ if ( isset( $args['ajax'] ) && $args['ajax'] && $doing_ajax ) {
1435
+ echo json_encode( array( 'redirect' => $success_url ) );
1436
+ wp_die();
1437
+ } elseif ( ! headers_sent() ) {
1438
+ wp_redirect( esc_url_raw( $success_url ) );
1439
+ die(); // do not use wp_die or redirect fails
1440
+ } else {
1441
+ add_filter( 'frm_use_wpautop', '__return_true' );
1442
+
1443
+ echo $redirect_msg;
1444
+ echo "<script type='text/javascript'>window.onload = function(){setTimeout(window.location='" . esc_url_raw( $success_url ) . "', 8000);}</script>";
1445
+ }
1446
+ }
1447
+
1448
+ /**
1449
+ * @since 3.0
1450
+ * @param string $success_url
1451
+ * @param string $success_msg
1452
+ * @param array $args
1453
+ */
1454
+ private static function get_redirect_message( $success_url, $success_msg, $args ) {
1455
+ $redirect_msg = '<div class="' . esc_attr( FrmFormsHelper::get_form_style_class( $args['form'] ) ) . '"><div class="frm-redirect-msg frm_message">' . $success_msg . '<br/>' .
1456
+ sprintf( __( '%1$sClick here%2$s if you are not automatically redirected.', 'formidable' ), '<a href="' . esc_url( $success_url ) . '">', '</a>') .
1457
+ '</div></div>';
1458
+
1459
+ return apply_filters( 'frm_redirect_msg', $redirect_msg, array(
1460
+ 'entry_id' => $args['entry_id'],
1461
+ 'form_id' => $args['form']->id,
1462
+ 'form' => $args['form'],
1463
+ ) );
1464
  }
1465
 
1466
  /**
1560
 
1561
  public static function front_head() {
1562
  $version = FrmAppHelper::plugin_version();
1563
+ $suffix = FrmAppHelper::js_suffix();
1564
+
1565
+ if ( ! empty( $suffix ) && self::has_combo_js_file() ) {
1566
+ wp_register_script( 'formidable', FrmAppHelper::plugin_url() . '/js/frm.min.js', array( 'jquery' ), $version, true );
1567
+ } else {
1568
+ wp_register_script( 'formidable', FrmAppHelper::plugin_url() . "/js/formidable{$suffix}.js", array( 'jquery' ), $version, true );
1569
+ }
1570
+
1571
  add_filter( 'script_loader_tag', 'FrmFormsController::defer_script_loading', 10, 2 );
1572
 
1573
  if ( FrmAppHelper::is_admin() ) {
1579
  FrmStylesController::enqueue_css( 'regi