Skip to content

Commit 202bfea

Browse files
authored
Merge pull request #159 from mailchimp/fix/104
Fixed phone number and required field validations.
2 parents 8c3119b + 9d204bb commit 202bfea

File tree

13 files changed

+219
-251
lines changed

13 files changed

+219
-251
lines changed

assets/js/mailchimp.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,19 @@
9393
});
9494
});
9595
}
96+
97+
// Phone validation custom error message.
98+
if ($('.mailchimp-sf-phone').length > 0) {
99+
$('.mailchimp-sf-phone').each(function () {
100+
$(this)
101+
.on('input', function () {
102+
this.setCustomValidity('');
103+
})
104+
.on('invalid', function () {
105+
if (!this.validity.valid) {
106+
this.setCustomValidity(window.mailchimpSF.phone_validation_error);
107+
}
108+
});
109+
});
110+
}
96111
})(window.jQuery);

includes/blocks/mailchimp-form-field/edit.js

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -232,37 +232,20 @@ export const MailchimpFormField = (props) => {
232232
);
233233

234234
case 'phone':
235-
if (field?.options?.phone_format === 'US') {
236-
return (
237-
<>
238-
<input
239-
type="text"
240-
size="2"
241-
maxLength="3"
242-
name={`${tag}[area]`}
243-
id={`${tag}-area`}
244-
className="mc_input mc_phone"
245-
/>
246-
<input
247-
type="text"
248-
size="2"
249-
maxLength="3"
250-
name={`${tag}[detail1]`}
251-
id={`${tag}-detail1`}
252-
className="mc_input mc_phone"
253-
/>
254-
<input
255-
type="text"
256-
size="5"
257-
maxLength="4"
258-
name={`${tag}[detail2]`}
259-
id={`${tag}-detail2`}
260-
className="mc_input mc_phone"
261-
/>
262-
</>
263-
);
264-
}
265-
return <input type="text" size="18" name={tag} id={tag} className="mc_input" />;
235+
// eslint-disable-next-line no-case-declarations
236+
const isUSPhone = field?.options?.phone_format === 'US';
237+
// eslint-disable-next-line no-case-declarations
238+
const placeholder = isUSPhone ? '(###) ### - ####' : '';
239+
return (
240+
<input
241+
type="tel"
242+
size="18"
243+
name={tag}
244+
id={tag}
245+
className="mc_input"
246+
placeholder={placeholder}
247+
/>
248+
);
266249

267250
case 'email':
268251
case 'url':

includes/class-mailchimp-form-submission.php

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,64 @@ public function handle_form_submission() {
178178
return $message;
179179
}
180180

181+
/**
182+
* Validate phone
183+
*
184+
* @param string $opt_val Option value.
185+
* @param array $data Data.
186+
* @return string|WP_Error Option value or error.
187+
*/
188+
public function validate_phone( $opt_val, $data ) {
189+
if ( empty( $opt_val ) ) {
190+
return '';
191+
}
192+
193+
// Backwards compatibility for old phone format.
194+
if ( is_array( $opt_val ) ) {
195+
$opt_val = implode( '-', $opt_val );
196+
}
197+
198+
$opt_val = trim( $opt_val );
199+
200+
// Validate phone number.
201+
if ( preg_match( '/^\+?[\d\s\-\(\)\.]*$/', $opt_val ) ) {
202+
return $opt_val;
203+
} else {
204+
/* translators: %s: field name */
205+
$message = sprintf( esc_html__( 'Please enter a valid %s.', 'mailchimp' ), esc_html( $data['name'] ) );
206+
return new WP_Error( 'mc_phone_validation', $message );
207+
}
208+
}
209+
210+
/**
211+
* Validate address
212+
*
213+
* @param array $opt_val Option value
214+
* @param array $data Data
215+
* @return mixed
216+
*/
217+
public function validate_address( $opt_val, $data ) {
218+
if ( true === (bool) $data['required'] ) {
219+
if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) {
220+
/* translators: %s: field name */
221+
$message = sprintf( esc_html__( '%s: Please enter a complete address.', 'mailchimp' ), esc_html( $data['name'] ) );
222+
$error = new WP_Error( 'invalid_address_merge', $message );
223+
return $error;
224+
}
225+
} elseif ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) {
226+
return false;
227+
}
228+
229+
$merge = new stdClass();
230+
$merge->addr1 = $opt_val['addr1'];
231+
$merge->addr2 = $opt_val['addr2'];
232+
$merge->city = $opt_val['city'];
233+
$merge->state = $opt_val['state'];
234+
$merge->zip = $opt_val['zip'];
235+
$merge->country = $opt_val['country'];
236+
return $merge;
237+
}
238+
181239
/**
182240
* Prepare the merge fields body for the API request.
183241
*
@@ -193,29 +251,20 @@ public function prepare_merge_fields_body( $merge_fields, $skip_merge_validation
193251
$opt = 'mc_mv_' . $tag;
194252

195253
// Skip if the field is not required and not submitted.
196-
if ( ( 'Y' !== $merge_field['required'] && ! isset( $_POST[ $opt ] ) ) || $skip_merge_validation ) {
254+
if ( ( true !== (bool) $merge_field['required'] && ! isset( $_POST[ $opt ] ) ) || $skip_merge_validation ) {
197255
continue;
198256
}
199257

200258
$opt_val = isset( $_POST[ $opt ] ) ? map_deep( stripslashes_deep( $_POST[ $opt ] ), 'sanitize_text_field' ) : '';
201259

202260
switch ( $merge_field['type'] ) {
203261
/**
204-
* US Phone validation
205-
*
206-
* - Merge field is phone
207-
* - Phone format is set in Mailchimp account
208-
* - Phone format is US in Mailchimp account
262+
* US/International Phone validation
209263
*/
210264
case 'phone':
211-
if (
212-
isset( $merge_field['options']['phone_format'] )
213-
&& 'US' === $merge_field['options']['phone_format']
214-
) {
215-
$opt_val = mailchimp_sf_merge_validate_phone( $opt_val, $merge_field );
216-
if ( is_wp_error( $opt_val ) ) {
217-
return $opt_val;
218-
}
265+
$opt_val = $this->validate_phone( $opt_val, $merge_field );
266+
if ( is_wp_error( $opt_val ) ) {
267+
return $opt_val;
219268
}
220269
break;
221270

@@ -227,7 +276,7 @@ public function prepare_merge_fields_body( $merge_fields, $skip_merge_validation
227276
*/
228277
case 'address':
229278
if ( is_array( $opt_val ) ) {
230-
$validate = mailchimp_sf_merge_validate_address( $opt_val, $merge_field );
279+
$validate = $this->validate_address( $opt_val, $merge_field );
231280
if ( is_wp_error( $validate ) ) {
232281
return $validate;
233282
}
@@ -260,9 +309,9 @@ public function prepare_merge_fields_body( $merge_fields, $skip_merge_validation
260309
/**
261310
* Required fields
262311
*
263-
* If the field is required and empty, return an error
312+
* If the field is required and empty, +return an error
264313
*/
265-
if ( 'Y' === $merge_field['required'] && trim( $opt_val ) === '' ) {
314+
if ( true === (bool) $merge_field['required'] && empty( $opt_val ) ) {
266315
/* translators: %s: field name */
267316
$message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $merge_field['name'] ) );
268317
$error = new WP_Error( 'missing_required_field', $message );
@@ -512,6 +561,16 @@ protected function validate_form_submission() {
512561
return new WP_Error( 'spam', $spam_message );
513562
}
514563

564+
// Early return if the email is not set
565+
if ( empty( $_POST['mc_mv_EMAIL'] ) ) {
566+
return new WP_Error( 'email_required', esc_html__( 'Please enter your email address.', 'mailchimp' ) );
567+
}
568+
569+
// Check if the email is valid
570+
if ( ! is_email( sanitize_email( wp_unslash( $_POST['mc_mv_EMAIL'] ) ) ) ) {
571+
return new WP_Error( 'invalid_email', esc_html__( 'Please enter a valid email address.', 'mailchimp' ) );
572+
}
573+
515574
/**
516575
* Filter to allow for custom validation of the form submission.
517576
*

includes/mailchimp-deprecated-functions.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,39 @@ function mailchimp_sf_merge_remove_empty( $merge ) {
113113
$form_submission = new Mailchimp_Form_Submission();
114114
return $form_submission->remove_empty_merge_fields( $merge );
115115
}
116+
117+
118+
/**
119+
* Validate phone
120+
*
121+
* @deprecated x.x.x
122+
*
123+
* @param array $opt_val Option value.
124+
* @param array $data Data.
125+
* @return string|WP_Error Option value or error.
126+
*/
127+
function mailchimp_sf_merge_validate_phone( $opt_val, $data ): string|WP_Error {
128+
_deprecated_function( __FUNCTION__, 'x.x.x', 'Mailchimp_Form_Submission::validate_phone()' );
129+
130+
if ( is_array( $opt_val ) ) {
131+
$opt_val = implode( '-', $opt_val );
132+
}
133+
$form_submission = new Mailchimp_Form_Submission();
134+
return $form_submission->validate_phone( $opt_val, $data );
135+
}
136+
137+
/**
138+
* Validate address
139+
*
140+
* @deprecated x.x.x
141+
*
142+
* @param array $opt_val Option value.
143+
* @param array $data Data.
144+
* @return mixed
145+
*/
146+
function mailchimp_sf_merge_validate_address( $opt_val, $data ) {
147+
_deprecated_function( __FUNCTION__, 'x.x.x', 'Mailchimp_Form_Submission::validate_address()' );
148+
149+
$form_submission = new Mailchimp_Form_Submission();
150+
return $form_submission->validate_address( $opt_val, $data );
151+
}

mailchimp.php

Lines changed: 3 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ function mailchimp_sf_load_resources() {
164164
'mailchimp_sf_main_js',
165165
'mailchimpSF',
166166
array(
167-
'ajax_url' => trailingslashit( home_url() ),
167+
'ajax_url' => trailingslashit( home_url() ),
168+
'phone_validation_error' => esc_html__( 'Please enter a valid phone number.', 'mailchimp' ),
168169
)
169170
);
170171

@@ -510,7 +511,7 @@ function mailchimp_sf_save_general_form_settings() {
510511
if ( is_array( $mv ) ) {
511512
foreach ( $mv as $mv_var ) {
512513
$opt = 'mc_mv_' . $mv_var['tag'];
513-
if ( isset( $_POST[ $opt ] ) || 'Y' === $mv_var['required'] ) {
514+
if ( isset( $_POST[ $opt ] ) || true === (bool) $mv_var['required'] ) {
514515
update_option( $opt, 'on' );
515516
} else {
516517
update_option( $opt, 'off' );
@@ -787,65 +788,6 @@ function mailchimp_sf_check_status( $endpoint ) {
787788
return $subscriber['status'];
788789
}
789790

790-
/**
791-
* Validate phone
792-
*
793-
* @param array $opt_val Option value
794-
* @param array $data Data
795-
* @return void
796-
*/
797-
function mailchimp_sf_merge_validate_phone( $opt_val, $data ) {
798-
// This filters out all 'falsey' elements
799-
$opt_val = array_filter( $opt_val );
800-
// If they weren't all empty
801-
if ( ! $opt_val ) {
802-
return;
803-
}
804-
805-
$opt_val = implode( '-', $opt_val );
806-
if ( strlen( $opt_val ) < 12 ) {
807-
$opt_val = '';
808-
}
809-
810-
if ( ! preg_match( '/[0-9]{0,3}-[0-9]{0,3}-[0-9]{0,4}/A', $opt_val ) ) {
811-
/* translators: %s: field name */
812-
$message = sprintf( esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) );
813-
$error = new WP_Error( 'mc_phone_validation', $message );
814-
return $error;
815-
}
816-
817-
return $opt_val;
818-
}
819-
820-
/**
821-
* Validate address
822-
*
823-
* @param array $opt_val Option value
824-
* @param array $data Data
825-
* @return mixed
826-
*/
827-
function mailchimp_sf_merge_validate_address( $opt_val, $data ) {
828-
if ( 'Y' === $data['required'] ) {
829-
if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) {
830-
/* translators: %s: field name */
831-
$message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) );
832-
$error = new WP_Error( 'invalid_address_merge', $message );
833-
return $error;
834-
}
835-
} elseif ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) {
836-
return false;
837-
}
838-
839-
$merge = new stdClass();
840-
$merge->addr1 = $opt_val['addr1'];
841-
$merge->addr2 = $opt_val['addr2'];
842-
$merge->city = $opt_val['city'];
843-
$merge->state = $opt_val['state'];
844-
$merge->zip = $opt_val['zip'];
845-
$merge->country = $opt_val['country'];
846-
return $merge;
847-
}
848-
849791
/**
850792
* Verify key
851793
*

mailchimp_widget.php

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -452,17 +452,9 @@ function mailchimp_form_field( $data, $num_fields, $should_display = null, $labe
452452
<input type="text" size="18" maxlength="5" value="" name="' . esc_attr( $opt ) . '" id="' . esc_attr( $opt ) . '" class="mc_input" />';
453453
break;
454454
case 'phone':
455-
if ( isset( $data['options']['phone_format'] ) && 'US' === $data['options']['phone_format'] ) {
456-
$html .= '
457-
<input type="text" size="2" maxlength="3" value="" name="' . esc_attr( $opt . '[area]' ) . '" id="' . esc_attr( $opt . '-area' ) . '" class="mc_input mc_phone" />
458-
<input type="text" size="2" maxlength="3" value="" name="' . esc_attr( $opt . '[detail1]' ) . '" id="' . esc_attr( $opt . '-detail1' ) . '" class="mc_input mc_phone" />
459-
<input type="text" size="5" maxlength="4" value="" name="' . esc_attr( $opt . '[detail2]' ) . '" id="' . esc_attr( $opt . '-detail2' ) . '" class="mc_input mc_phone" />
460-
';
461-
} else {
462-
$html .= '
463-
<input type="text" size="18" value="" name="' . esc_attr( $opt ) . '" id="' . esc_attr( $opt ) . '" class="mc_input" />
464-
';
465-
}
455+
$is_us_phone = isset( $data['options']['phone_format'] ) && 'US' === $data['options']['phone_format'];
456+
$html .= '
457+
<input type="tel" size="20" minlength="6" maxlength="20" pattern="^\+?[\d\s\-\(\)\.]*$" value="" name="' . esc_attr( $opt ) . '" id="' . esc_attr( $opt ) . '" class="mc_input mailchimp-sf-phone" placeholder="' . esc_attr( $is_us_phone ? '(###) ### - ####' : '' ) . '" />';
466458
break;
467459
case 'email':
468460
case 'url':

0 commit comments

Comments
 (0)