Summary
Telephone-number SMS-code validation is handled by mam_validate_phone_code (includes/user-roles/phone-code-validation.php), whose get_phone_validation_code() method issues a code and fires mam_notification_send_message (SMS channel). The same class powers phone-code login.
Naming caution:
mam_forms_manager_phone_manager(includes/forms-manager/phone-manager.php) is not a telephone-number utility — despite the name, itsget_phone_data()method appends form colors and social-platform help defaults to the mobile-app (“phone”) JSON pipeline. It has noissue_code()/verify_code()methods. Verify class ownership against source before wiring into either one.
Two distinct flows
| Flow | Use case | Notification type |
|---|---|---|
| One-shot validation | Validating a phone number during form submission (registration, “verify your number”) | gf-phone-number-validation |
| Phone-code login | Authenticating a returning user via SMS code instead of password | (Issued through mam_notification_send_message with the user-roles handler) |
Both share the same SMS dispatch path through the notification dispatcher.
How one-shot validation works
User enters phone in form field
│
▼
Field is configured with validation = phone_code (per-field special handling)
│
▼
Submission triggers mam_validate_phone_code::get_phone_validation_code()
│ ├─ Normalize the input (strip spaces, parens, etc.)
│ ├─ Generate a validation code
│ └─ Persist (code, phone, expiry) in a transient
▼
do_action('mam_notification_send_message', [
'message_type' => 'gf-phone-number-validation',
'phone' => $normalized_phone,
'message' => '[passwordcode]', ← gets replaced with the 6-digit code
])
▼
SMS sent via MAM_Sms_Sender → MAM_Sms_Client (Twilio)
▼
User enters the code in the next form step
▼
mam_validate_phone_code verifies the entered code against the transient
Normalization
The phone manager normalizes:
- Strips non-digits except a leading
+ - Defaults to E.164 (
+15551234567) where the country code can be inferred - Uses the per-site default country (configurable in Mobile App Manager → Forms → Phone settings) when the user enters a national number with no country prefix
⚠️ International apps with mixed-locale users should explicitly require the country code in the form’s UI — auto-inference only works reliably when most submissions come from one locale.
Phone-code login
mam_validate_phone_code (includes/user-roles/phone-code-validation.php) extends the same pattern:
- User enters phone number on the login screen
- Server issues a code, persists in transient, fires
mam_notification_send_message - User enters code;
mam_validate_phone_code::verify()compares - On success, the user is logged in (or, if the phone is unrecognized, the registration flow starts)
This is enabled by the Login content class’s phone_code_enabled setting.
Hooks involved
| Hook | Type | Role |
|---|---|---|
mam_notification_send_message |
Action | Fires the SMS code |
mam_form_manager_process_field_type_phone |
Filter | Standard phone-field processor (build-time) |
SMS dispatch dependencies
- Twilio credentials configured under Mobile App Mgr → Notifications Manager → SMS Setup tab (the in-house
MAM_Sms_Client, not an external plugin) - A populated
tsl_notification_text_status_*(ormam_notification_text_status_*) for the notification type to enable SMS routing - The recipient must have a phone number in
usermetabilling_phone(or supplied in the request)
ℹ️ In-house Twilio client. SMS is sent via MAM_Sms_Client::instance()->send(). When credentials are missing, is_configured() returns false and phone-code-validation.php bails early with an admin alert instead of silently failing — no global $sms dependency. Verification codes are transactional and bypass the opt-out list.
Gotchas
- Codes expire. The default expiry is short (a few minutes) — verify timing in the implementation if you need to extend.
- One code per phone at a time. Re-issuing a code overwrites the transient; the previous code becomes invalid.
- Don’t bypass normalization. Storing un-normalized phone numbers in
usermetacauses mismatches at lookup. - STOP-to-opt-out copy is appended automatically by the SMS sender. Don’t duplicate it in your message body.
Related articles
- Forms manager overview
- Notifications overview
- Notification channels: email, SMS, push
- Hook: mam_notification_send_message
Metadata
| Field | Value |
|---|---|
| Article type | Plugin Overview |
| Plugin slug | mam-main |
| Applies to plugin version | 2.1.11+ |
| Category | Plugin Reference |
| Audience | PHP developer |
| Last verified | 2026-05-02 |
