message = $message; } else { // translators: %element% is the field label. $this->message = __( "Please enter a valid phone number in %element%", 'contact-forms' ); } } /** * Validate phone number following ITU-T E.164 standard * * E.164 specifies maximum 15 digits (not counting the + sign). * We require a minimum of 7 digits for actual phone numbers. * We allow flexible formatting for user convenience: * - Minimum 7 digits (most countries have 7+ digit numbers) * - Maximum 15 digits (E.164 compliant) * - Allows: digits, spaces, dashes, dots, slashes, parentheses, plus sign * - Plus sign only allowed at the beginning * - Prefix-only values (≤4 digits with +) are treated as empty for optional fields * * @param string $value The phone number to validate * @return bool True if valid or empty (empty handled by Required validation), false otherwise */ public function isValid($value) { // Skip validation for empty/null values (handled by Required validation if needed) if ($this->isNotApplicable($value)) { return true; } // Trim whitespace $value = trim($value); // Empty after trim is valid (Required validation handles mandatory fields) if ($value === '') { return true; } // FIRST: Check for invalid characters (only digits, spaces, dashes, dots, slashes, parentheses, plus) if (!preg_match('/^[\d\s\-\.\/\(\)\+]+$/', $value)) { return false; } // Plus sign only allowed at the start if (strpos($value, '+') !== false && strpos($value, '+') !== 0) { return false; } // Multiple plus signs not allowed if (substr_count($value, '+') > 1) { return false; } // Count digits only $digitCount = strlen(preg_replace('/\D/', '', $value)); // Treat prefix-only values (1-4 digits starting with +) as empty for optional fields // This allows optional phone fields with placeholder prefixes like "+39" to pass validation if (strpos($value, '+') === 0 && $digitCount <= 4) { return true; } // Require minimum 5 digits for actual phone numbers // NOTE: Client-side uses libphonenumber which may accept 5-6 digit numbers for some countries // Server must be equal or more lenient to avoid rejecting client-accepted values if ($digitCount < 5) { return false; } // E.164 standard: maximum 15 digits if ($digitCount > 15) { return false; } return true; } }