PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 4.0.3
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v4.0.3
4.0.3 4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 341 releases
← All changes | admin/manage-fields.php +414 -107 3.9.84.0.3 View file →
@@ -106,8 +106,9 @@
106 106 // $manage_field_types['optgroups']['standard']['options'][] = 'Checkbox';
107 107 // $manage_field_types['optgroups']['standard']['options'][] = 'Radio';
108 108 $manage_field_types['optgroups']['standard']['options'][] = 'HTML';
109 109 $manage_field_types['optgroups']['standard']['options'][] = 'Upload';
110 + $manage_field_types['optgroups']['standard']['options'][] = 'International Telephone Input';
110 111 // $manage_field_types['optgroups']['standard']['options'][] = 'Avatar';
111 112
112 113 $manage_field_types['optgroups']['advanced']['options'][] = 'Phone';
113 114 $manage_field_types['optgroups']['advanced']['options'][] = 'Select (Country)';
@@ -113,8 +114,9 @@
113 114 $manage_field_types['optgroups']['advanced']['options'][] = 'Select (Country)';
114 115 $manage_field_types['optgroups']['advanced']['options'][] = 'Select (Timezone)';
115 116 $manage_field_types['optgroups']['advanced']['options'][] = 'Select (Currency)';
116 117 $manage_field_types['optgroups']['advanced']['options'][] = 'Select (CPT)';
118 + $manage_field_types['optgroups']['advanced']['options'][] = 'Select (Taxonomy)';
117 119 $manage_field_types['optgroups']['advanced']['options'][] = 'Checkbox (Terms and Conditions)';
118 120 $manage_field_types['optgroups']['advanced']['options'][] = 'Datepicker';
119 121 $manage_field_types['optgroups']['advanced']['options'][] = 'Timepicker';
120 122 $manage_field_types['optgroups']['advanced']['options'][] = 'Colorpicker';
@@ -119,8 +121,9 @@
119 121 $manage_field_types['optgroups']['advanced']['options'][] = 'Timepicker';
120 122 $manage_field_types['optgroups']['advanced']['options'][] = 'Colorpicker';
121 123 $manage_field_types['optgroups']['advanced']['options'][] = 'Validation';
122 124 $manage_field_types['optgroups']['advanced']['options'][] = 'Map';
125 + $manage_field_types['optgroups']['advanced']['options'][] = 'Additional Map';
123 126
124 127 $manage_field_types['optgroups']['other']['options'][] = 'Email';
125 128 $manage_field_types['optgroups']['other']['options'][] = 'URL';
126 129
@@ -132,10 +135,15 @@
132 135 }
133 136
134 137 $manage_field_types['optgroups']['other']['options'][] = 'Email Confirmation';
135 138
136 - /* added recaptcha and user role field since version 2.6.2 */
139 + /* added recaptcha field since version 2.6.2 */
137 140 $manage_field_types['optgroups']['advanced']['options'][] = 'reCAPTCHA';
141 +
142 + /* added turnstile field since version 3.15. */
143 + $manage_field_types['optgroups']['advanced']['options'][] = 'Turnstile';
144 +
145 + /* added user role field since version 2.6.2 */
138 146 $manage_field_types['optgroups']['advanced']['options'][] = 'Select (User Role)';
139 147
140 148
141 149 $manage_field_types['optgroups']['other']['options'] = apply_filters( 'wppb_manage_fields_types', $manage_field_types['optgroups']['other']['options'] );
@@ -150,8 +158,9 @@
150 158 $manage_field_types['optgroups']['standard']['options'][] = array( 'field_name' => 'WYSIWYG', 'disabled' => true );
151 159 $manage_field_types['optgroups']['standard']['options'][] = array( 'field_name' => 'Select (Multiple)', 'disabled' => true );
152 160 $manage_field_types['optgroups']['standard']['options'][] = array( 'field_name' => 'HTML', 'disabled' => true );
153 161 $manage_field_types['optgroups']['standard']['options'][] = array( 'field_name' => 'Upload', 'disabled' => true );
162 + $manage_field_types['optgroups']['standard']['options'][] = array( 'field_name' => 'International Telephone Input', 'disabled' => true );
154 163
155 164 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Phone', 'disabled' => true );
156 165 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Select (Country)', 'disabled' => true );
157 166 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Select (Timezone)', 'disabled' => true );
@@ -156,8 +165,9 @@
156 165 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Select (Country)', 'disabled' => true );
157 166 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Select (Timezone)', 'disabled' => true );
158 167 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Select (Currency)', 'disabled' => true );
159 168 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Select (CPT)', 'disabled' => true );
169 + $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Select (Taxonomy)', 'disabled' => true );
160 170 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Checkbox (Terms and Conditions)', 'disabled' => true );
161 171 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Datepicker', 'disabled' => true );
162 172 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Timepicker', 'disabled' => true );
163 173 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Colorpicker', 'disabled' => true );
@@ -162,8 +172,9 @@
162 172 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Timepicker', 'disabled' => true );
163 173 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Colorpicker', 'disabled' => true );
164 174 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Validation', 'disabled' => true );
165 175 $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Map', 'disabled' => true );
176 + $manage_field_types['optgroups']['advanced']['options'][] = array( 'field_name' => 'Additional Map', 'disabled' => true );
166 177
167 178 $manage_field_types['optgroups']['other']['options'][] = array( 'field_name' => 'WooCommerce Customer Billing Address', 'disabled' => true );
168 179 $manage_field_types['optgroups']['other']['options'][] = array( 'field_name' => 'WooCommerce Customer Shipping Address', 'disabled' => true );
169 180 $manage_field_types['optgroups']['other']['options'][] = array( 'field_name' => 'MailChimp Subscribe', 'disabled' => true );
@@ -179,9 +190,9 @@
179 190
180 191 // Free to Pro call to action on Manage Fields page
181 192 $field_description = __('Choose one of the supported field types','profile-builder');
182 193 if( PROFILE_BUILDER == 'Profile Builder Free' ) {
183 - $field_description .= sprintf( __('. Extra Field Types are available in <a href="%s">Basic or PRO versions</a>.' , 'profile-builder'), esc_url( 'https://www.cozmoslabs.com/wordpress-profile-builder/?utm_source=wpbackend&utm_medium=clientsite&utm_content=manage-fields-link&utm_campaign=PBFree' ) );
194 + $field_description .= sprintf( __('. Extra Field Types are available in <a href="%s">Basic or PRO versions</a>.' , 'profile-builder'), esc_url( 'https://www.cozmoslabs.com/wordpress-profile-builder/?utm_source=pb-form-fields&utm_medium=client-site&utm_campaign=pb-extra-fields#pricing' ) );
184 195 }
185 196
186 197 //user roles
187 198 global $wp_roles;
@@ -208,11 +219,31 @@
208 219 $default_currency_options[] = '%'. wppb_prepare_wck_labels( $currency_name ) .'%'.$iso_currency_code;
209 220 }
210 221
211 222 //cpt select
212 - $post_types = get_post_types( array( 'public' => true ), 'names' );
223 + $post_types_objects = get_post_types( array( 'public' => true ), 'objects' );
224 + $post_types = array();
213 225
226 + if ( !empty( $post_types_objects ) ) {
227 + // Loop through the post types objects and extract the labels
228 + foreach ( $post_types_objects as $types ) {
229 + if ( isset( $types->label ) )
230 + array_push( $post_types, '%' . wppb_prepare_wck_labels( $types->label ) . '%' . $types->name );
231 + }
232 + }
214 233
234 + //taxonomy select
235 + $taxonomies_objects = get_taxonomies( array( 'public' => true ), 'objects' );
236 + $taxonomies = array();
237 +
238 + if ( !empty( $taxonomies_objects ) ) {
239 + // Loop through the taxonomies objects and extract the labels
240 + foreach ( $taxonomies_objects as $taxonomy ) {
241 + if ( isset( $taxonomy->label ) )
242 + array_push( $taxonomies, '%' . wppb_prepare_wck_labels( $taxonomy->label ) . '%' . $taxonomy->name );
243 + }
244 + }
245 +
215 246 if( apply_filters( 'wppb_update_field_meta_key_in_db', false ) ) {
216 247 $meta_key_description = __( 'Use this in conjunction with WordPress functions to display the value in the page of your choosing<br/>Auto-completed but in some cases editable (in which case it must be unique)<br/>Changing this might take long in case of a very big user-count', 'profile-builder' );
217 248 }
218 249 else{
@@ -238,18 +269,25 @@
238 269 array( 'type' => 'text', 'slug' => 'row-count', 'title' => __( 'Row Count', 'profile-builder' ), 'default' => 5, 'description' => __( "Specify the number of rows for a 'Textarea' field<br/>If not specified, defaults to 5", 'profile-builder' ) ),
239 270 array( 'type' => 'text', 'slug' => 'allowed-image-extensions', 'title' => __( 'Allowed Image Extensions', 'profile-builder' ), 'default' => '.*', 'description' => __( 'Specify the extension(s) you want to limit to upload<br/>Example: .ext1,.ext2,.ext3<br/>If not specified, defaults to: .jpg,.jpeg,.gif,.png (.*)', 'profile-builder' ) ),
240 271 array( 'type' => 'checkbox', 'slug' => 'simple-upload', 'title' => __( 'Use Simple Upload', 'profile-builder' ), 'options' => array( '%'.__('Yes','profile-builder').'%'.'yes' ), 'description' => __( 'Use a simple upload field instead of the WordPress upload', 'profile-builder' ) ),
241 272 array( 'type' => 'text', 'slug' => 'allowed-upload-extensions', 'title' => __( 'Allowed Upload Extensions', 'profile-builder' ), 'default' => '.*', 'description' => __( 'Specify the extension(s) you want to limit to upload<br/>Example: .ext1,.ext2,.ext3<br/>If not specified, defaults to all WordPress allowed file extensions (.*)', 'profile-builder' ) ),
242 - array( 'type' => 'text', 'slug' => 'avatar-size', 'title' => __( 'Avatar Size', 'profile-builder' ), 'default' => 100, 'description' => __( "Enter a value (between 20 and 200) for the size of the 'Avatar'<br/>If not specified, defaults to 100", 'profile-builder' ) ),
273 + array( 'type' => 'text', 'slug' => 'avatar-size', 'title' => __( 'Avatar Size', 'profile-builder' ), 'default' => 100, 'description' => __( "Enter a value (between 20 and 800) for the size of the 'Avatar'<br/>If not specified, defaults to 100", 'profile-builder' ) ),
274 + array( 'type' => 'text', 'slug' => 'max-file-size', 'title' => __( 'Maximum File Size (MB)', 'profile-builder' ), 'description' => __( 'Specify the maximum file size allowed for upload (in MB)<br/>If not specified, defaults to the server maximum upload size', 'profile-builder' ) ),
243 275 array( 'type' => 'text', 'slug' => 'date-format', 'title' => __( 'Date-format', 'profile-builder' ), 'default' => 'mm/dd/yy', 'description' => __( 'Specify the format of the date when using Datepicker<br/>Valid options: mm/dd/yy, mm/yy/dd, dd/yy/mm, dd/mm/yy, yy/dd/mm, yy/mm/dd, mm-dd-yy, yy-mm-dd, D, dd M yy, D, d M y, DD, dd-M-y, D, d M yy, mm/yy, mm/dd, dd/mm, @<br/>If not specified, defaults to mm/dd/yy<br/>ATTENTION: if you plan to use this field for sorting, please make sure to use year first, then month, and day last.', 'profile-builder' ) ),
244 276 array( 'type' => 'textarea', 'slug' => 'terms-of-agreement', 'title' => __( 'Terms of Agreement', 'profile-builder' ), 'description' => __( 'Enter a detailed description of the terms of agreement for the user to read.<br/>Links can be inserted by using standard HTML syntax: &lt;a href="custom_url"&gt;custom_text&lt;/a&gt;', 'profile-builder' ) ),
245 277 array( 'type' => 'text', 'slug' => 'options', 'title' => __( 'Options', 'profile-builder' ), 'description' => __( "Enter a comma separated list of values<br/>This can be anything, as it is hidden from the user, but should not contain special characters or apostrophes", 'profile-builder' ) ),
246 278 array( 'type' => 'text', 'slug' => 'labels', 'title' => __( 'Labels', 'profile-builder' ), 'description' => __( "Enter a comma separated list of labels<br/>Visible for the user", 'profile-builder' ) ),
247 - array( 'type' => 'select', 'slug' => 'recaptcha-type', 'title' => __( 'reCAPTCHA Type', 'profile-builder' ), 'options' => array('%reCAPTCHA V2%v2', '%Invisible reCAPTCHA%invisible'), 'default' => 'v2', 'description' => __( 'Choose the <a href="https://developers.google.com/recaptcha/docs/versions" target="_blank">type of reCAPTCHA</a> you wish to add to this site.<br/>Please note that the Invisible reCAPTCHA is a type of reCAPTCHA v2.', 'profile-builder' ) ),
279 + array( 'type' => 'select', 'slug' => 'recaptcha-type', 'title' => __( 'reCAPTCHA Type', 'profile-builder' ), 'options' => array('%reCAPTCHA V2 Checkbox%v2', '%reCAPTCHA V2 Invisible%invisible', '%reCAPTCHA V3%v3'), 'default' => 'v2', 'description' => __( 'Choose the <a href="https://developers.google.com/recaptcha/docs/versions" target="_blank">type of reCAPTCHA</a> you wish to add to this site.<br/>Please note that the Invisible reCAPTCHA is a type of reCAPTCHA v2.', 'profile-builder' ) ),
248 280 array( 'type' => 'text', 'slug' => 'public-key', 'title' => __( 'Site Key', 'profile-builder' ), 'description' => __( 'The site key from Google, <a href="https://www.google.com/recaptcha/admin/create" target="_blank">https://www.google.com/recaptcha/admin/create</a>', 'profile-builder' ) ),
249 281 array( 'type' => 'text', 'slug' => 'private-key', 'title' => __( 'Secret Key', 'profile-builder' ), 'description' => __( 'The secret key from Google, <a href="https://www.google.com/recaptcha/admin/create" target="_blank">https://www.google.com/recaptcha/admin/create</a>', 'profile-builder' ) ),
282 + array( 'type' => 'text', 'slug' => 'score-threshold', 'title' => __( 'Score Threshold', 'profile-builder' ), 'default' => 0.5, 'description' => __( 'The required score threshold: 1.0 is very likely a good interaction, 0.0 is very likely a bot<br/>If not specified, defaults to 0.5', 'profile-builder' ) ),
250 283 array( 'type' => 'checkbox', 'slug' => 'captcha-pb-forms', 'title' => __( 'Display on PB forms', 'profile-builder' ), 'options' => array( '%'.__('PB Login','profile-builder').'%'.'pb_login', '%'.__('PB Register','profile-builder').'%'.'pb_register', '%'.__('PB Recover Password','profile-builder').'%'.'pb_recover_password' ), 'default' => 'pb_register', 'description' => __( "Select on which Profile Builder forms to display reCAPTCHA", 'profile-builder' ) ),
251 - array( 'type' => 'checkbox', 'slug' => 'captcha-wp-forms', 'title' => __( 'Display on default WP forms', 'profile-builder' ), 'options' => array( '%'.__('Default WP Login', 'profile-builder').'%'.'default_wp_login', '%'.__('Default WP Register', 'profile-builder').'%'.'default_wp_register', '%'.__('Default WP Recover Password', 'profile-builder').'%'.'default_wp_recover_password'), 'default' => 'default_wp_register', 'description' => __( "Select on which default WP forms to display reCAPTCHA", 'profile-builder' ) ),
284 + array( 'type' => 'checkbox', 'slug' => 'captcha-wp-forms', 'title' => __( 'Display on default WP forms', 'profile-builder' ), 'options' => array( '%'.__('Default WP Login', 'profile-builder').'%'.'default_wp_login', '%'.__('Default WP Register', 'profile-builder').'%'.'default_wp_register', '%'.__('Default WP Recover Password', 'profile-builder').'%'.'default_wp_recover_password', '%'.__('Default WP Comments', 'profile-builder').'%'.'default_wp_comments'), 'default' => 'default_wp_register', 'description' => __( "Select on which default WP forms to display reCAPTCHA", 'profile-builder' ) ),
285 + array( 'type' => 'select', 'slug' => 'theme', 'title' => __( 'Turnstile Theme', 'profile-builder' ), 'options' => array('%Auto%auto', '%Light%light', '%Dark%dark'), 'default' => 'auto', 'description' => __( 'Choose the theme for the Turnstile widget. The Auto option conforms to the user system preferences.', 'profile-builder' ) ),
286 + array( 'type' => 'text', 'slug' => 'turnstile-site-key', 'title' => __( 'Site Key', 'profile-builder' ), 'description' => __( 'The site key from <a href="https://dash.cloudflare.com/?to=/:account/turnstile" target="_blank">Cloudflare</a>', 'profile-builder' ) ),
287 + array( 'type' => 'text', 'slug' => 'turnstile-secret-key', 'title' => __( 'Secret Key', 'profile-builder' ), 'description' => __( 'The secret key from <a href="https://dash.cloudflare.com/?to=/:account/turnstile" target="_blank">Cloudflare</a>', 'profile-builder' ) ),
288 + array( 'type' => 'checkbox', 'slug' => 'turnstile-pb-forms', 'title' => __( 'Display on PB forms', 'profile-builder' ), 'options' => array( '%'.__('PB Login','profile-builder').'%'.'pb_login', '%'.__('PB Register','profile-builder').'%'.'pb_register', '%'.__('PB Recover Password','profile-builder').'%'.'pb_recover_password' ), 'default' => 'pb_register', 'description' => __( "Select on which Profile Builder forms to display Turnstile", 'profile-builder' ) ),
289 + array( 'type' => 'checkbox', 'slug' => 'turnstile-wp-forms', 'title' => __( 'Display on default WP forms', 'profile-builder' ), 'options' => array( '%'.__('Default WP Login', 'profile-builder').'%'.'default_wp_login', '%'.__('Default WP Register', 'profile-builder').'%'.'default_wp_register', '%'.__('Default WP Recover Password', 'profile-builder').'%'.'default_wp_recover_password', '%'.__('Default WP Comments', 'profile-builder').'%'.'default_wp_comments'), 'default' => 'default_wp_register', 'description' => __( "Select on which default WP forms to display Turnstile", 'profile-builder' ) ),
252 290 array( 'type' => 'checkbox', 'slug' => 'user-roles', 'title' => __( 'User Roles', 'profile-builder' ), 'options' => $user_roles, 'description' => __( "Select which user roles to show to the user ( drag and drop to re-order )", 'profile-builder' ) ),
253 291 array( 'type' => 'checkbox', 'slug' => 'user-roles-on-edit-profile', 'title' => __( 'Display on Edit Profile', 'profile-builder' ), 'options' => array('%Yes%yes'), 'description' => __( "Check if you want the select user role field to appear on Edit Profile forms", 'profile-builder' ) ),
254 292 array( 'type' => 'text', 'slug' => 'user-roles-sort-order', 'title' => __( 'User Roles Order', 'profile-builder' ), 'description' => __( "Save the user role order from the user roles checkboxes", 'profile-builder' ) ),
255 293 array( 'type' => 'text', 'slug' => 'default-value', 'title' => __( 'Default Value', 'profile-builder' ), 'description' => __( "Default value of the field", 'profile-builder' ) ),
@@ -259,8 +297,9 @@
259 297 array( 'type' => 'select', 'slug' => 'default-option-timezone', 'title' => __( 'Default Option', 'profile-builder' ), 'options' => wppb_timezone_select_options( 'back_end' ), 'description' => __( "Default option of the field", 'profile-builder' ) ),
260 298 array( 'type' => 'select', 'slug' => 'default-option-currency', 'title' => __( 'Default Option', 'profile-builder' ), 'options' => ( isset( $default_currency_options ) ) ? $default_currency_options : '', 'description' => __( "Default option of the field", 'profile-builder' ) ),
261 299 array( 'type' => 'select', 'slug' => 'show-currency-symbol', 'title' => __( 'Show Currency Symbol', 'profile-builder' ), 'options' => array( 'No', 'Yes' ), 'default' => 'No', 'description' => __( 'Whether the currency symbol should be displayed after the currency name in the select option.', 'profile-builder' ) ),
262 300 array( 'type' => 'select', 'slug' => 'cpt', 'title' => __( 'Show Post Type', 'profile-builder' ), 'options' => $post_types, 'default' => 'post', 'description' => __( 'Posts from what post type will be displayed in the select.', 'profile-builder' ) ),
301 + array( 'type' => 'select', 'slug' => 'taxonomy', 'title' => __( 'Show Taxonomy Term', 'profile-builder' ), 'options' => $taxonomies, 'default' => 'category', 'description' => __( 'Terms from taxonomies', 'profile-builder' ) ),
263 302 array( 'type' => 'text', 'slug' => 'validation-possible-values', 'title' => __( 'Allowable Values', 'profile-builder' ), 'description' => __( "Enter a comma separated list of possible values. Upon registration if the value provided by the user does not match one of these values, the user will not be registered.", 'profile-builder' ) ),
264 303 array( 'type' => 'text', 'slug' => 'custom-error-message', 'title' => __( 'Error Message', 'profile-builder' ), 'description' => __( "Set a custom error message that will be displayed to the user.", 'profile-builder' ) ),
265 304 array( 'type' => 'select', 'slug' => 'time-format', 'title' => __( 'Time Format', 'profile-builder' ), 'options' => array( '%12 Hours%12', '%24 Hours%24' ), 'description' => __( 'Specify the time format.', 'profile-builder' ) ),
266 305 array( 'type' => 'text', 'slug' => 'map-api-key', 'title' => __( 'Google Maps API Key', 'profile-builder' ), 'description' => __( 'Enter your Google Maps API key ( <a href="https://console.developers.google.com/flows/enableapi?apiid=maps_backend" target="_blank">Get your API key</a> ). If more than one map fields are added to a form the API key from the first map displayed will be used.', 'profile-builder' ) ),
@@ -293,13 +332,19 @@
293 332 array( 'type' => 'text', 'slug' => 'phone-format', 'title' => __( 'Phone Format', 'profile-builder' ), 'default' => '(###) ###-####', 'description' => __( "You can use: # for numbers, parentheses ( ), - sign, + sign, dot . and spaces.", 'profile-builder' ) .'<br>'. __( "Eg. (###) ###-####", 'profile-builder' ) .'<br>'. __( "Empty field won't check for correct phone number.", 'profile-builder' ) ),
294 333 array( 'type' => 'select', 'slug' => 'heading-tag', 'title' => __( 'Heading Tag', 'profile-builder' ), 'options' => array( '%h1 - biggest size%h1', 'h2', 'h3', 'h4', 'h5', '%h6 - smallest size%h6' ), 'default' => 'h4', 'description' => __( 'Change heading field size on front-end forms', 'profile-builder' ) ),
295 334 array( 'type' => 'text', 'slug' => 'min-number-value', 'title' => __( 'Min Number Value', 'profile-builder' ), 'description' => __( "Min allowed number value (0 to allow only positive numbers)", 'profile-builder' ) .'<br>'. __( "Leave it empty for no min value", 'profile-builder' ) ),
296 335 array( 'type' => 'text', 'slug' => 'max-number-value', 'title' => __( 'Max Number Value', 'profile-builder' ), 'description' => __( "Max allowed number value (0 to allow only negative numbers)", 'profile-builder' ) .'<br>'. __( "Leave it empty for no max value", 'profile-builder' ) ),
336 + array( 'type' => 'checkbox', 'slug' => 'ask-current-password', 'title' => __( 'Ask for Current Password', 'profile-builder' ), 'options' => array( '%' . __( 'Yes', 'profile-builder' ) . '%yes' ), 'description' => __( 'On Edit Profile forms, require users to enter their current password before changing it. This applies only when users change their own password.', 'profile-builder' ) ),
297 337 array( 'type' => 'text', 'slug' => 'number-step-value', 'title' => __( 'Number Step Value', 'profile-builder' ), 'description' => __( "Step value 1 to allow only integers, 0.1 to allow integers and numbers with 1 decimal", 'profile-builder' ) .'<br>'. __( "To allow multiple decimals use for eg. 0.01 (for 2 deciamls) and so on", 'profile-builder' ) .'<br>'. __( "You can also use step value to specify the legal number intervals (eg. step value 2 will allow only -4, -2, 0, 2 and so on)", 'profile-builder' ) .'<br>'. __( "Leave it empty for no restriction", 'profile-builder' ) ),
298 338 array( 'type' => 'select', 'slug' => 'required', 'title' => __( 'Required', 'profile-builder' ), 'options' => array( 'No', 'Yes' ), 'default' => 'No', 'description' => __( 'Whether the field is required or not', 'profile-builder' ) ),
299 339 array( 'type' => 'select', 'slug' => 'overwrite-existing', 'title' => __( 'Overwrite Existing', 'profile-builder' ), 'options' => array( 'No', 'Yes' ), 'default' => 'No', 'description' => __( "Selecting 'Yes' will add the field to the list, but will overwrite any other field in the database that has the same meta-name<br/>Use this at your own risk", 'profile-builder' ) ),
340 + array( 'type' => 'text', 'slug' => 'initial-country', 'title' => __( 'Initial Country', 'profile-builder' ), 'description' => __( "Set the initial country for the phone field. Use 'auto' to detect it automatically by IP, or enter one ISO 3166-1 alpha-2 country code (e.g. ro, jp, us).", 'profile-builder' ), 'default' => 'auto' ),
341 + array( 'type' => 'text', 'slug' => 'preferred-countries', 'title' => __( 'Preferred Countries', 'profile-builder' ), 'description' => __( "Set preferred countries using ISO 3166-1 alpha-2 codes (e.g. ro, jp, us), separated by commas.", 'profile-builder' ), 'default' => '' ),
342 + array( 'type' => 'text', 'slug' => 'excluded-countries', 'title' => __( 'Excluded Countries', 'profile-builder' ), 'description' => __( "Exclude countries using ISO 3166-1 alpha-2 codes (e.g. af, ru, us), separated by commas.", 'profile-builder' ), 'default' => '' ),
343 + array( 'type' => 'checkbox', 'slug' => 'national-mode', 'title' => __( 'National Mode', 'profile-builder' ), 'options' => array( '%'.__('Yes','profile-builder').'%'.'yes' ), 'description' => __( "Enable National Mode to enter numbers in local format (without country prefix). Disable it to use International Mode (with country prefix).", 'profile-builder' ) ),
344 + array( 'type' => 'checkbox', 'slug' => 'hide-flags', 'title' => __( 'Hide Flags', 'profile-builder' ), 'options' => array( '%'.__('Yes','profile-builder').'%'.'yes' ), 'description' => __( "Enable to hide country flags in the phone field.", 'profile-builder' ) ),
300 345
301 - // Added the new option for the map field type, that allows to customize the POIs load type.
346 + // Added the new option for the map field type, that allows to customize the POIs load type.
302 347 array(
303 348 'type' => 'select',
304 349 'slug' => 'map-pins-load-type',
305 350 'title' => __( 'POIs Load Type', 'profile-builder' ),
@@ -353,19 +398,25 @@
353 398
354 399 /* this is redundant but it should have a very low impact and for comfort we leave it here as well */
355 400 wppb_prepopulate_fields();
356 401
357 - // create the info side meta-box
358 - $args = array(
359 - 'metabox_id' => 'manage-fields-info',
360 - 'metabox_title' => __( 'Registration & Edit Profile Forms', 'profile-builder' ),
361 - 'post_type' => 'manage-fields',
362 - 'meta_name' => 'wppb_manage_fields_info',
363 - 'meta_array' => '',
364 - 'context' => 'option',
365 - 'mb_context' => 'side'
366 - );
367 - new Wordpress_Creation_Kit_PB( $args );
402 +
403 + // skip this meta-box for the Repeater Field -> Edit Field Group view
404 + if ( !isset( $_GET['wppb_rpf_repeater_meta_name'] ) ) {
405 +
406 + // create the info side meta-box
407 + $args = array(
408 + 'metabox_id' => 'manage-fields-info',
409 + 'metabox_title' => __( 'Form Shortcodes', 'profile-builder' ),
410 + 'post_type' => 'manage-fields',
411 + 'meta_name' => 'wppb_manage_fields_info',
412 + 'meta_array' => '',
413 + 'context' => 'option',
414 + 'mb_context' => 'side'
415 + );
416 + new Wordpress_Creation_Kit_PB( $args );
417 +
418 + }
368 419 }
369 420 add_action( 'admin_init', 'wppb_populate_manage_fields', 1 );
370 421
371 422 /**
@@ -710,12 +761,30 @@
710 761 'ZW' => __( 'Zimbabwe', 'profile-builder' ),
711 762 )
712 763 );
713 764
714 - return $country_array;
765 + return wppb_translate_countries( $country_array );
715 766 }
716 767
768 +/**
769 + * Helper function to translate country names with WPML
770 + * Registers strings in WPML String Translation and returns translated value
771 + */
772 +function wppb_translate_countries( $countries ) {
717 773
774 + if ( !function_exists( 'icl_register_string' ) || !function_exists( 'icl_t' ) ) {
775 + return $countries;
776 + }
777 +
778 + foreach( $countries as $index => $country ){
779 + $prefix = 'country_' . $country;
780 + icl_register_string( 'profile-builder', $prefix, $country );
781 + $countries[$index] = icl_t( 'profile-builder', $prefix, $country );
782 + }
783 +
784 + return $countries;
785 +}
786 +
718 787 /**
719 788 * Function that returns an array with timezone options
720 789 *
721 790 * @since v.2.0
@@ -1132,8 +1201,9 @@
1132 1201
1133 1202 if( !$only_default_fields ){
1134 1203 $unique_field_list[] = 'Avatar';
1135 1204 $unique_field_list[] = 'reCAPTCHA';
1205 + $unique_field_list[] = 'Turnstile';
1136 1206 $unique_field_list[] = 'Select (User Role)';
1137 1207 $unique_field_list[] = 'Map';
1138 1208 }
1139 1209
@@ -1173,8 +1243,13 @@
1173 1243 if ( ( in_array ( $posted_values['field'], $unique_field_list ) ) && ( $posted_values['field'] == $field['field'] ) && ( $posted_values['id'] != $field['id'] ) ){
1174 1244 $message .= __( "Please choose a different field type as this one already exists in your form (must be unique)\n", 'profile-builder' );
1175 1245 break;
1176 1246 }
1247 +
1248 + if ( ( $posted_values['field'] == 'reCAPTCHA' && $field['field'] == 'Turnstile' ) || ( $posted_values['field'] == 'Turnstile' && $field['field'] == 'reCAPTCHA' ) ){
1249 + $message .= __( "You cannot have both a reCAPTCHA and a Turnstile field! Please remove the other existing field first.\n", 'profile-builder' );
1250 + break;
1251 + }
1177 1252 }
1178 1253 }
1179 1254 // END check if the unique fields are only added once
1180 1255
@@ -1180,10 +1255,10 @@
1180 1255
1181 1256 // check for avatar size
1182 1257 if ( $posted_values['field'] == 'Avatar' ){
1183 1258 if ( is_numeric( $posted_values['avatar-size'] ) ){
1184 - if ( ( $posted_values['avatar-size'] < 20 ) || ( $posted_values['avatar-size'] > 200 ) )
1185 - $message .= __( "The entered avatar size is not between 20 and 200\n", 'profile-builder' );
1259 + if ( ( $posted_values['avatar-size'] < 20 ) || ( $posted_values['avatar-size'] > 800 ) )
1260 + $message .= __( "The entered avatar size is not between 20 and 800\n", 'profile-builder' );
1186 1261
1187 1262 }else
1188 1263 $message .= __( "The entered avatar size is not numerical\n", 'profile-builder' );
1189 1264
@@ -1189,8 +1264,17 @@
1189 1264
1190 1265 }
1191 1266 // END check for avatar size
1192 1267
1268 + // check for max file size
1269 + if ( in_array( $posted_values['field'], array( 'Avatar', 'Upload' ) ) ){
1270 + if ( isset( $posted_values['max-file-size'] ) && $posted_values['max-file-size'] !== '' ){
1271 + if ( !is_numeric( $posted_values['max-file-size'] ) || floatval( $posted_values['max-file-size'] ) <= 0 )
1272 + $message .= __( "The entered maximum file size is not a valid positive number\n", 'profile-builder' );
1273 + }
1274 + }
1275 + // END check for max file size
1276 +
1193 1277 // check for correct row value
1194 1278 if ( ( $posted_values['field'] == 'Default - Biographical Info' ) || ( $posted_values['field'] == 'Textarea' ) ){
1195 1279 if ( !is_numeric( $posted_values['row-count'] ) )
1196 1280 $message .= __( "The entered row number is not numerical\n", 'profile-builder' );
@@ -1201,14 +1285,20 @@
1201 1285 // END check for correct row value
1202 1286
1203 1287
1204 1288 // check for the public and private keys
1205 - if ( $posted_values['field'] == 'reCAPTCHA'){
1289 + if ( $posted_values['field'] == 'reCAPTCHA' ){
1206 1290 if ( trim( $posted_values['public-key'] ) == '' )
1207 - $message .= __( "You must enter the site key\n", 'profile-builder' );
1291 + $message .= __( "You must enter the site key!\n", 'profile-builder' );
1208 1292 if ( trim( $posted_values['private-key'] ) == '' )
1209 - $message .= __( "You must enter the secret key\n", 'profile-builder' );
1293 + $message .= __( "You must enter the secret key!\n", 'profile-builder' );
1210 1294 }
1295 + if ( $posted_values['field'] == 'Turnstile' ){
1296 + if ( trim( $posted_values['turnstile-site-key'] ) == '' )
1297 + $message .= __( "You must enter the site key!\n", 'profile-builder' );
1298 + if ( trim( $posted_values['turnstile-secret-key'] ) == '' )
1299 + $message .= __( "You must enter the secret key!\n", 'profile-builder' );
1300 + }
1211 1301 // END check for the public and private keys
1212 1302
1213 1303 // check for the correct the date-format
1214 1304 if ( $posted_values['field'] == 'Datepicker' ){
@@ -1234,85 +1324,99 @@
1234 1324
1235 1325 }
1236 1326 // END check for the correct the date-format
1237 1327
1238 - //check for empty meta-name and duplicate meta-name
1239 - if ( $posted_values['overwrite-existing'] == 'No' ){
1240 - $skip_check_for_fields = wppb_return_unique_field_list(true);
1241 - $skip_check_for_fields = apply_filters ( 'wppb_skip_check_for_fields', $skip_check_for_fields );
1242 1328
1243 - if ( !in_array( trim( $posted_values['field'] ), $skip_check_for_fields ) ){
1244 - $reserved_meta_name_list = wppb_get_reserved_meta_name_list( $all_fields, $posted_values );
1329 + $skip_check_for_fields = wppb_return_unique_field_list(true);
1330 + $skip_check_for_fields = apply_filters ( 'wppb_skip_check_for_fields', $skip_check_for_fields );
1245 1331
1246 - //check to see if meta-name is empty
1247 - $skip_empty_check_for_fields = array( 'Heading', 'Select (User Role)', 'reCAPTCHA', 'HTML', 'GDPR Delete Button' );
1332 + // check for empty, reserved and/or duplicate meta-name
1333 + if ( !in_array( trim( $posted_values['field'] ), $skip_check_for_fields ) ) {
1334 + $reserved_meta_name_list = wppb_get_reserved_meta_name_list( $all_fields, $posted_values );
1248 1335
1249 - if( !in_array( $posted_values['field'], $skip_empty_check_for_fields ) && empty( $posted_values['meta-name'] ) ) {
1250 - $message .= __( "The meta-name cannot be empty\n", 'profile-builder' );
1336 + //check to see if meta-name is empty
1337 + $skip_empty_check_for_fields = array( 'Heading', 'Select (User Role)', 'reCAPTCHA', 'Turnstile', 'HTML', 'GDPR Delete Button' );
1338 +
1339 + if( !in_array( $posted_values['field'], $skip_empty_check_for_fields ) && empty( $posted_values['meta-name'] ) ) {
1340 + $message .= __( "The meta-name cannot be empty\n", 'profile-builder' );
1341 + }
1342 +
1343 + //check if the meta-name starts or ends with a space
1344 + if ( strpos( $posted_values['meta-name'], " " ) === 0 ) {
1345 + $message .= __( "The meta-name cannot begin with a space\n", 'profile-builder' );
1346 + }
1347 + if ( strpos( $posted_values['meta-name'], " " ) === strlen( $posted_values['meta-name'] ) - 1 ) {
1348 + $message .= __( "The meta-name cannot end with a space\n", 'profile-builder' );
1349 + }
1350 +
1351 + // meta names that are reserved and cannot be used as part of other meta names
1352 + $reserved_meta_name_list_strict = apply_filters( 'wppb_unique_meta_name_list_strict', array( 'map' ) );
1353 + // skip meta name check for these fields
1354 + $skip_unique_meta_name_list_check = apply_filters( 'wppb_skip_unique_meta_name_list_check', array( 'Map', 'Honeypot' ) );
1355 +
1356 + // if the desired meta name is in the restricted list or if one of the meta names in the strictly
1357 + // restricted list is part of it display an error message
1358 + $is_reserved_meta_name = false;
1359 + $trimmed_meta_name = trim( $posted_values['meta-name'] );
1360 +
1361 + if ( !in_array( $posted_values['field'], $skip_unique_meta_name_list_check ) ) {
1362 + foreach ( $reserved_meta_name_list as $reserved_meta_name ) {
1363 +
1364 + if ( in_array( $trimmed_meta_name, $reserved_meta_name_list ) || ( strpos( $trimmed_meta_name, $reserved_meta_name ) !== false && in_array( $reserved_meta_name, $reserved_meta_name_list_strict ) ) ) {
1365 + $is_reserved_meta_name = true;
1366 + break;
1367 + }
1368 +
1251 1369 }
1370 + }
1252 1371
1253 - //check if the meta-name starts or ends with a space
1254 - if ( strpos( $posted_values['meta-name'], " " ) === 0 ) {
1255 - $message .= __( "The meta-name cannot begin with a space\n", 'profile-builder' );
1256 - }
1257 - if ( strpos( $posted_values['meta-name'], " " ) === strlen( $posted_values['meta-name'] ) - 1 ) {
1258 - $message .= __( "The meta-name cannot end with a space\n", 'profile-builder' );
1259 - }
1372 + if ( $is_reserved_meta_name ) {
1373 + $message .= __( "That meta-name can't be used, please choose another\n", 'profile-builder' );
1374 + }
1375 + elseif ( $posted_values['overwrite-existing'] == 'No' ) { // check for duplicate meta-name
1376 + $found_in_custom_fields = false;
1260 1377
1261 - // meta names that are reserved and cannot be used as part of other meta names
1262 - $reserved_meta_name_list_strict = apply_filters( 'wppb_unique_meta_name_list_strict', array( 'map' ) );
1263 - // skip meta name check for these fields
1264 - $skip_unique_meta_name_list_check = apply_filters( 'wppb_skip_unique_meta_name_list_check', array( 'Map', 'Honeypot' ) );
1378 + if( $all_fields != 'not_set' )
1379 + foreach( $all_fields as $field ){
1265 1380
1266 - // if the desired meta name is in the restricted list or if one of the meta names in the strictly
1267 - // restricted list is part of it display an error message
1268 - $is_reserved_meta_name = false;
1269 - $trimmed_meta_name = trim( $posted_values['meta-name'] );
1270 - if ( !in_array( $posted_values['field'], $skip_unique_meta_name_list_check ) ) {
1271 - foreach ($reserved_meta_name_list as $reserved_meta_name) {
1272 - if (in_array($trimmed_meta_name, $reserved_meta_name_list) ||
1273 - (strpos($trimmed_meta_name, $reserved_meta_name) !== false && in_array($reserved_meta_name, $reserved_meta_name_list_strict))) {
1274 - $is_reserved_meta_name = true;
1275 - break;
1381 + if ( $posted_values['meta-name'] != '' && ( $field['meta-name'] == $posted_values['meta-name'] ) && ( $field['id'] != $posted_values['id'] ) ) {
1382 + $message .= __( "That meta-name is already in use\n", 'profile-builder' );
1383 + $found_in_custom_fields = true;
1276 1384 }
1385 + elseif ( ( $field['meta-name'] == $posted_values['meta-name'] ) && ( $field['id'] == $posted_values['id'] ) )
1386 + $found_in_custom_fields = true;
1387 +
1277 1388 }
1278 - }
1279 - if ( $is_reserved_meta_name )
1280 - $message .= __( "That meta-name can't be used, please choose another\n", 'profile-builder' );
1281 1389
1282 - else{
1283 - $found_in_custom_fields = false;
1390 + if ( $found_in_custom_fields === false ) {
1284 1391
1285 - if( $all_fields != 'not_set' )
1286 - foreach( $all_fields as $field ){
1287 - if ( $posted_values['meta-name'] != '' && ( $field['meta-name'] == $posted_values['meta-name'] ) && ( $field['id'] != $posted_values['id'] ) ){
1288 - $message .= __( "That meta-name is already in use\n", 'profile-builder' );
1289 - $found_in_custom_fields = true;
1392 + if( $posted_values['meta-name'] != '' ) {
1393 + $found_meta_name = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->usermeta WHERE meta_key = %s", $posted_values['meta-name'] ) );
1290 1394
1291 - }elseif ( ( $field['meta-name'] == $posted_values['meta-name'] ) && ( $field['id'] == $posted_values['id'] ) )
1292 - $found_in_custom_fields = true;
1293 - }
1395 + if ( $found_meta_name != null )
1396 + $message .= __( "That meta-name is already in use\n", 'profile-builder' );
1294 1397
1295 - if ( $found_in_custom_fields === false ){
1296 - if( $posted_values['meta-name'] != '' ) {
1297 - $found_meta_name = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->usermeta WHERE meta_key = %s", $posted_values['meta-name']));
1298 - if ($found_meta_name != null)
1299 - $message .= __("That meta-name is already in use\n", 'profile-builder');
1300 - }
1301 - }
1302 - }
1303 - }
1304 - }
1305 - //END check duplicate meta-name
1398 + }
1306 1399
1307 - // check for correct meta name on upload field
1400 + }
1401 +
1402 + }
1403 +
1404 + }
1405 + //END check for empty, reserved and/or duplicate meta-name
1406 +
1407 + // check for correct meta name
1308 1408 if( $posted_values['field'] == 'Upload' ) {
1309 1409 if( ! empty( $posted_values['meta-name'] ) && preg_match( '/([^a-z\d_-])/', $posted_values['meta-name'] ) ) {
1310 1410 $message .= __( "The meta-name can only contain lowercase letters, numbers, _ , - and no spaces.\n", 'profile-builder' );
1311 1411 }
1312 1412 }
1313 - // END check for correct meta name on upload field
1413 + elseif ( ! empty( $posted_values['meta-name'] ) && preg_match( '/\s/', $posted_values['meta-name'] ) ) {
1414 + $message .= __( "The meta-name cannot contain spaces.\n", 'profile-builder' );
1415 + }
1314 1416
1417 + // END check for correct meta name
1418 +
1315 1419 // check for valid default option (checkbox, select, radio)
1316 1420 if ( ( $posted_values['field'] == 'Checkbox' ) || ( $posted_values['field'] == 'Select (Multiple)' ) ) {
1317 1421 $options = array_map( 'trim', explode( ',', $posted_values['options'] ) );
1318 1422 $default_options = ( ( trim( $posted_values['default-options'] ) == '' ) ? array() : array_map( 'trim', explode( ',', $posted_values['default-options'] ) ) );
@@ -1420,15 +1524,17 @@
1420 1524 * @return string
1421 1525 */
1422 1526 function wppb_add_content_before_manage_fields(){
1423 1527 ?>
1424 - <p><?php esc_html_e('Use these shortcodes on the pages you want the forms to be displayed:', 'profile-builder'); ?></p>
1425 - <ul>
1426 - <li><strong class="nowrap">[wppb-register]</strong></li>
1427 - <li><strong class="nowrap">[wppb-edit-profile]</strong></li>
1428 - <li><strong class="nowrap">[wppb-register role="author"]</strong></li>
1429 - </ul>
1430 - <p>
1528 + <p class="cozmoslabs-description"><?php esc_html_e('Use these shortcodes on the pages you want the forms to be displayed:', 'profile-builder'); ?></p>
1529 +
1530 + <ul class="cozmoslabs-shortcodes-list">
1531 + <li><strong class="nowrap">[wppb-register]</strong></li>
1532 + <li><strong class="nowrap">[wppb-edit-profile]</strong></li>
1533 + <li><strong class="nowrap">[wppb-register role="author"]</strong></li>
1534 + </ul>
1535 +
1536 + <p class="cozmoslabs-description">
1431 1537 <?php
1432 1538 $versions = array( 'Profile Builder Pro', 'Profile Builder Agency', 'Profile Builder Unlimited', 'Profile Builder Dev' );
1433 1539
1434 1540 if( in_array( PROFILE_BUILDER, $versions ) )
@@ -1578,9 +1684,9 @@
1578 1684 global $wpdb;
1579 1685
1580 1686 $meta_name_underlined = $meta_name . '_';
1581 1687
1582 - $results = $wpdb->get_results( "SELECT meta_value, meta_key FROM {$wpdb->usermeta} WHERE user_id={$user_id} AND meta_key LIKE '%{$meta_name_underlined}%'", ARRAY_N );
1688 + $results = $wpdb->get_results( $wpdb->prepare( "SELECT meta_value, meta_key FROM {$wpdb->usermeta} WHERE user_id = %d AND meta_key LIKE '%s'", $user_id, '%' . $meta_name_underlined . '%' ), ARRAY_N );
1583 1689
1584 1690 $markers = array();
1585 1691 $i = 0;
1586 1692
@@ -1717,27 +1823,13 @@
1717 1823 global $wpdb;
1718 1824 $wppb_manage_fields = get_option('wppb_manage_fields');
1719 1825 if (!empty($wppb_manage_fields)) {
1720 1826
1721 - /*
1722 - * We need to be sure this is not a repeater.
1723 - * The way we're doing this is by checking if the $values['meta-name'] is found inside $wppb_manage_fields
1724 - * If it's not, it's probably inside a repeater.
1725 - *
1726 - * The reason we're doing this is because when we're updating a repeater field the $meta is still 'wppb_manage_fields' for some reason, while $element_id comes from the position of the repeater.
1727 - *
1728 - * This means we're updating last_name (if it's the 9'th position in wppb_manage_fields) instead of 'something_repeater' that's also in the 9'th position but inside the repeater group.
1729 - *
1730 - * Also, this code didn't account for 'something_repeater_1' etc, meaning it would have changed just 1 field, causing data loss anyway.
1731 - *
1732 - */
1733 - $is_not_repeater = false;
1734 - foreach ($wppb_manage_fields as $field){
1735 - if ( $field['meta-name'] == $values['meta-name'] ){
1736 - $is_not_repeater = true;
1737 - }
1738 - }
1827 + $is_not_repeater = true;
1739 1828
1829 + if( !empty( $wppb_manage_fields[$element_id] ) && $wppb_manage_fields[$element_id]['field'] == 'Repeater' )
1830 + $is_not_repeater = false;
1831 +
1740 1832 if (!empty($values['meta-name']) && $wppb_manage_fields[$element_id]['meta-name'] != $values['meta-name'] && $is_not_repeater ) {
1741 1833 $wpdb->update(
1742 1834 $wpdb->usermeta,
1743 1835 array('meta_key' => sanitize_text_field($values['meta-name'])),
@@ -1794,4 +1886,219 @@
1794 1886 return $tags;
1795 1887 }
1796 1888 }
1797 1889 add_filter( 'wppb_map_bubble_fields', 'wppb_filter_map_bubble_fields' );
1890 +
1891 +
1892 +/**
1893 + * Get field property mapping for cleaning up stored field data
1894 + *
1895 + * Maps each field type to its required properties based on the JavaScript
1896 + * field definitions in assets/js/jquery-manage-fields-live-change.js
1897 + *
1898 + * @since 3.15.3
1899 + * @return array Field type to properties mapping
1900 + */
1901 +function wppb_get_field_property_mapping() {
1902 +
1903 + // Properties that can be dynamically added by various add-ons to many field types
1904 + $optional_addon_properties = array(
1905 + // Conditional Fields add-on
1906 + 'conditional-logic-enabled',
1907 + 'conditional-logic',
1908 + // WooCommerce Sync add-on
1909 + 'woocommerce-checkout-field',
1910 + // BuddyPress add-on
1911 + 'bdp-default-visibility',
1912 + 'bdp-allow-custom-visibility',
1913 + // Field Visibility add-on
1914 + 'visibility',
1915 + 'user-role-visibility',
1916 + 'location-visibility',
1917 + // Edit Profile Approved by Admin add-on
1918 + 'edit-profile-approved-by-admin',
1919 + // Maximum Character Length add-on
1920 + 'maximum-character-length',
1921 + // Custom CSS Classes add-on
1922 + 'class-field',
1923 + );
1924 +
1925 + /**
1926 + * Filter the optional addon properties that are applied to all field types.
1927 + *
1928 + * Add-ons can use this filter to register properties that should be preserved
1929 + * across all field types (e.g., properties that can be applied to any field).
1930 + *
1931 + * @since 3.15.3
1932 + *
1933 + * @param array $optional_addon_properties Array of property slugs to preserve for all fields
1934 + *
1935 + * @example
1936 + * add_filter( 'wppb_field_optional_properties', 'my_addon_register_optional_properties' );
1937 + * function my_addon_register_optional_properties( $properties ) {
1938 + * $properties[] = 'my-custom-property';
1939 + * $properties[] = 'another-property';
1940 + * return $properties;
1941 + * }
1942 + */
1943 + $optional_addon_properties = apply_filters( 'wppb_field_optional_properties', $optional_addon_properties );
1944 +
1945 + $mapping = array(
1946 + // Default WordPress Fields - Headings
1947 + 'Default - Name (Heading)' => array(),
1948 + 'Default - Contact Info (Heading)' => array(),
1949 + 'Default - About Yourself (Heading)' => array(),
1950 +
1951 + // Default WordPress Fields - User Data
1952 + 'Default - Username' => array('default-value'),
1953 + 'Default - First Name' => array('default-value'),
1954 + 'Default - Last Name' => array('default-value'),
1955 + 'Default - Nickname' => array('default-value'),
1956 + 'Default - E-mail' => array('default-value'),
1957 + 'Default - Website' => array('default-value'),
1958 + 'Default - AIM' => array('default-value'),
1959 + 'Default - Yahoo IM' => array('default-value'),
1960 + 'Default - Jabber / Google Talk' => array('default-value'),
1961 + 'Default - Password' => array('ask-current-password'),
1962 + 'Default - Repeat Password' => array(),
1963 + 'Default - Biographical Info' => array('row-count', 'default-content'),
1964 + 'Default - Display name publicly as' => array('default-value'),
1965 + 'Default - Blog Details' => array(),
1966 +
1967 + // GDPR Fields
1968 + 'GDPR Checkbox' => array(),
1969 + 'GDPR Delete Button' => array(),
1970 + 'GDPR Communication Preferences' => array('gdpr-communication-preferences', 'gdpr-communication-preferences-sort-order'),
1971 +
1972 + // Standard Fields
1973 + 'Heading' => array('heading-tag'),
1974 + 'Input' => array('default-value'),
1975 + 'Email' => array('default-value'),
1976 + 'Email Confirmation' => array(),
1977 + 'URL' => array('default-value'),
1978 + 'Number' => array('default-value', 'min-number-value', 'max-number-value', 'number-step-value'),
1979 + 'Input (Hidden)' => array('default-value'),
1980 + 'Language' => array('default-value'),
1981 + 'Textarea' => array('default-content', 'row-count'),
1982 + 'WYSIWYG' => array('default-content', 'row-count'),
1983 + 'Phone' => array('default-value', 'phone-format'),
1984 +
1985 + // Select Fields
1986 + 'Select' => array('default-option', 'options', 'labels'),
1987 + 'Select (Multiple)' => array('default-options', 'options', 'labels'),
1988 + 'Select (Country)' => array('default-option-country'),
1989 + 'Select (Currency)' => array('show-currency-symbol', 'default-option-currency'),
1990 + 'Select (Timezone)' => array('default-option-timezone'),
1991 + 'Select (CPT)' => array('default-option', 'cpt'),
1992 + 'Select (Taxonomy)' => array('default-option', 'taxonomy'),
1993 + 'Select2' => array('default-option', 'options', 'labels'),
1994 + 'Select2 (Multiple)' => array('default-options', 'options', 'labels', 'select2-multiple-limit', 'select2-multiple-tags'),
1995 +
1996 + // Checkbox and Radio Fields
1997 + 'Checkbox' => array('default-options', 'options', 'labels'),
1998 + 'Checkbox (Terms and Conditions)' => array('terms-of-agreement'),
1999 + 'Radio' => array('default-option', 'options', 'labels'),
2000 + 'Honeypot' => array(),
2001 +
2002 + // Upload Fields
2003 + 'Upload' => array('simple-upload', 'allowed-upload-extensions', 'max-file-size'),
2004 + 'Avatar' => array('simple-upload', 'allowed-image-extensions', 'avatar-size', 'max-file-size'),
2005 +
2006 + // Date/Time Fields
2007 + 'Datepicker' => array('default-value', 'date-format'),
2008 + 'Timepicker' => array('time-format'),
2009 + 'Colorpicker' => array('default-value'),
2010 +
2011 + // Advanced Fields
2012 + 'Validation' => array('validation-possible-values', 'custom-error-message'),
2013 + 'reCAPTCHA' => array('recaptcha-type', 'public-key', 'private-key', 'score-threshold', 'captcha-pb-forms', 'captcha-wp-forms'),
2014 + 'Turnstile' => array('theme', 'turnstile-site-key', 'turnstile-secret-key', 'turnstile-pb-forms', 'turnstile-wp-forms'),
2015 + 'Select (User Role)' => array('user-roles', 'user-roles-on-edit-profile', 'user-roles-sort-order'),
2016 + 'Map' => array('map-api-key', 'map-default-lat', 'map-default-lng', 'map-default-zoom', 'map-height', 'map-pins-load-type', 'map-pagination-number', 'map-bubble-fields'),
2017 + 'Additional Map' => array('map-default-lat', 'map-default-lng', 'map-default-zoom', 'map-height'),
2018 + 'HTML' => array('html-content'),
2019 +
2020 + // WooCommerce Fields (added via JS by add-on)
2021 + 'WooCommerce Customer Billing Address' => array('woo-billing-fields', 'woo-billing-fields-required', 'woo-billing-fields-sort-order', 'woo-billing-fields-name'),
2022 + 'WooCommerce Customer Shipping Address' => array('woo-shipping-fields', 'woo-shipping-fields-required', 'woo-shipping-fields-sort-order', 'woo-shipping-fields-name'),
2023 +
2024 + // Add-on Fields (MailChimp, MailPoet, Campaign Monitor, etc. may add their own)
2025 + 'MailChimp Subscribe' => array('mailchimp-lists', 'mailchimp-default-checked', 'mailchimp-hide-field'),
2026 + 'MailPoet Subscribe' => array('mailpoet-lists', 'mailpoet-default-checked', 'mailpoet-hide-field'),
2027 + 'Campaign Monitor Subscribe' => array('campaign-monitor-lists', 'campaign-monitor-hide-field'),
2028 + 'Subscription Plans' => array('subscription-plans', 'subscription-plans-sort-order', 'subscription-plan-selected'),
2029 + 'PMS Billing Fields' => array('pms-billing-fields'),
2030 + 'Repeater' => array('rpf-enable-limit', 'rpf-limit', 'rpf-limit-reached-message', 'rpf-role-limit', 'rpf-button'),
2031 + );
2032 +
2033 + // Add optional addon properties to all field types
2034 + foreach ( $mapping as $field_type => $properties ) {
2035 + $mapping[$field_type] = array_merge( $properties, $optional_addon_properties );
2036 + }
2037 +
2038 + // Allow add-ons to register their field type property mappings
2039 + $mapping = apply_filters( 'wppb_field_property_mapping', $mapping );
2040 +
2041 + return $mapping;
2042 +}
2043 +
2044 +/**
2045 + * Clean up field properties before saving to database
2046 + *
2047 + * Removes unused properties from each field based on its type, reducing database bloat.
2048 + * Common properties are kept for all fields, field-specific properties are kept only
2049 + * when relevant to the field type.
2050 + *
2051 + * @since 3.15.3
2052 + * @param array $value New field data being saved
2053 + * @param array $old_value Existing field data (not used)
2054 + * @return array Cleaned field data
2055 + */
2056 +function wppb_cleanup_manage_fields_before_save( $value, $old_value ) {
2057 + // Only process if we have an array
2058 + if ( ! is_array( $value ) ) {
2059 + return $value;
2060 + }
2061 +
2062 + // Get field type to property mapping
2063 + $mapping = wppb_get_field_property_mapping();
2064 +
2065 + // Common properties kept for all fields
2066 + // Note: meta-name is kept even when not shown in UI, as it's set programmatically
2067 + $common_properties = array(
2068 + 'id',
2069 + 'field',
2070 + 'field-title',
2071 + 'meta-name',
2072 + 'description',
2073 + 'required',
2074 + 'overwrite-existing',
2075 + );
2076 +
2077 + // Process each field
2078 + foreach ( $value as $key => $field ) {
2079 + if ( ! isset( $field['field'] ) ) {
2080 + continue;
2081 + }
2082 +
2083 + $field_type = $field['field'];
2084 + $allowed_properties = $common_properties;
2085 +
2086 + // Add field-specific properties if we have a mapping
2087 + if ( isset( $mapping[$field_type] ) ) {
2088 + $allowed_properties = array_merge( $allowed_properties, $mapping[$field_type] );
2089 + } else {
2090 + // Unknown field type: keep common properties + any non-empty properties
2091 + foreach ( $field as $prop_key => $prop_value ) {
2092 + if ( ! in_array( $prop_key, $common_properties ) && ! empty( $prop_value ) ) {
2093 + $allowed_properties[] = $prop_key;
2094 + }
2095 + }
2096 + }
2097 +
2098 + // Filter the field to only keep allowed properties
2099 + $value[$key] = array_intersect_key( $field, array_flip( $allowed_properties ) );
2100 + }
2101 +
2102 + return $value;
2103 +}
2104 +add_filter( 'pre_update_option_wppb_manage_fields', 'wppb_cleanup_manage_fields_before_save', 5, 2 );