Last active
May 31, 2023 08:00
-
-
Save RadGH/7580023f71e8d4fbf356 to your computer and use it in GitHub Desktop.
Convert user-inputted phone number to consistently formatted HTML link, with extension support
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// improved version: https://gist.github.com/RadGH/31f16cd4705a2d8076021a9ad528f34f | |
// ---------- | |
// Example #1: HTML | |
$phone_number = '555.123.4567'; | |
echo format_phone( $phone_number ); | |
// Output: | |
// <span class="tel"><a href="tel:+15551234567" class="tel-link">(555) 123-4567</a></span> | |
// Example #2: Plain text | |
$phone_number = '555.123.4567'; | |
echo format_phone( $phone_number, false ); | |
// Output: | |
// (555) 123-4567 | |
// Structure as HTML. Ignore the line breaks. "tel-ext" is only included when an extension is provided. | |
// <span class="tel"> | |
// <a href="tel:+15411234567" class="tel-link"> | |
// 541-123-4567 | |
// </a> | |
// <span class="tel-ext"> | |
// <span class="tel-ext-prefix">ext.</span> 999 | |
// <span>ext.</span> 999 | |
// </span> | |
// </span> | |
// Output as text: | |
// 541-123-4567 ext. 999 | |
/** | |
* Format a phone number as a string or html link. | |
* Supports most extensions. If provided, the extension will be displayed after the link. | |
* Supports most 10+ digit phone numbers. Unsupported phone numbers return the original $phone (with no link). | |
* You can customize the $display_format. The default format is: "1 (555) 123-4567" | |
* | |
* @param string $phone US/Canada phone number: 5551234567 or 555-123-4567 or (555) 123-4567 or +15551234567 etc. | |
* @param bool $html Default true. Returns an HTML "tel:" link. | |
* @param string $extension_prefix If an extension is provided, the text before the extension. | |
* @param string $display_format The format used to display the phone number. Does not affect the link's href property. | |
* @param bool $hide_us_code If true, the country code for US phone numbers (1) will not be displayed. (The display format must contain "%1$d") | |
* | |
* @return string | |
*/ | |
function format_phone( $phone, $html = true, $extension_prefix = 'ext. ', $display_format = '%1$d (%2$d) %3$d-%4$d', $hide_us_code = true ) { | |
// Regex pattern to split parts of a phone number, and optional extension. | |
// Supports some country codes, but not all international phone number formats. | |
// https://regex101.com/r/4coVfU/1 | |
$pattern = '/^\+?([0-9]{0,3})?[^0-9]*([0-9]{3,3})[^0-9]*([0-9]{3,3})[^0-9]*([0-9]{4,4})[^0-9]*([^0-9]*(-|e?xt?\.?)[^0-9\-]*([0-9\-]{1,}))?[^0-9]*$/i'; | |
$found = preg_match($pattern, $phone, $matches); | |
// If the phone number could not be parsed, keep the original format | |
if ( ! $found ) return $phone; | |
// Result from regex match with input: "+1 (541) 123-4567 x999" | |
// [1] => 1 | |
// [2] => 541 | |
// [3] => 123 | |
// [4] => 4567 | |
// [5] => (ignore) | |
// [6] => (ignore) | |
// [7] => 999 | |
$country_code = $matches[1] ?: 1; | |
$extension = $matches[7] ?? ''; | |
// Should US country code be hidden? | |
if ( $hide_us_code && $country_code == '1' ) { | |
$display_format = str_replace( '%1$d', '', $display_format ); | |
$display_format = trim( $display_format ); | |
} | |
$output = ''; | |
if ( $html ) { | |
$output .= '<span class="tel">'; | |
} | |
// Start html link | |
if ( $html ) { | |
$tel_href = sprintf('tel:+%d%d%d%d', $country_code, $matches[2], $matches[3], $matches[4]); | |
$output .= '<a href="'. esc_attr($tel_href) .'" class="tel-link">'; | |
} | |
// The actual phone number to display | |
$output .= sprintf('%d (%d) %d-%d', $country_code, $matches[2], $matches[3], $matches[4]); | |
// End html link | |
if ( $html ) { | |
$output .= '</a>'; | |
} | |
// Add the extension | |
// Links do not (reliably) support an extension, so it appears after the link. | |
if ( $extension ) { | |
if ( $html ) { | |
$output .= '<span class="ext">'; | |
$output .= '<span class="ext-prefix">'. esc_html($extension_prefix) .'</span>'; | |
$output .= '<span class="ext-value">'. esc_html($extension) .'</span>'; | |
$output .= '</span>'; | |
}else{ | |
$output .= $extension_prefix . $extension; | |
} | |
} | |
if ( $html ) { | |
$output .= '</span>'; | |
} | |
return $output; | |
} |
In case anyone shows up here wanting this function for Javascript...
/***************************
PROCESS PHONE NUMBERS FOR TEL LINKS
***************************/
window.formatPhone = function formatPhone( string, html = true, classes = null ) {
// Pattern to collect digits from a phone number, and optional extension
// Extensions can be identified using: + - x ex ex. ext ext. extension extension.
// Now (should) function with country codes!
var matches = string.match(/\+?([0-9]{0,3})?[^0-9]*([0-9]{3,3})[^0-9]*([0-9]{3,3})[^0-9]*([0-9]{4,4})[^0-9]*([^0-9]*(-|e?xt?\.?)[^0-9]*([0-9]{1,}))?[^0-9]*$/i);
if (matches) {
// Input: "1 (541) 123-4567 x999"
// 1 => 1
// 2 => 541
// 3 => 123
// 4 => 4567
// 7 => 999
var result = [];
if (typeof matches[7] !== 'undefined') var ext = matches[7];
else var ext = '';
var countrycode = matches[1] ? matches[1] : 1;
// Output (HTML):
// <span class="tel"><a href="tel+15411234567" class="tel-link">541-123-4567</a><span class="tel-ext"><span> x</span>999</span></span>
// Output (Raw):
// 541-123-4567 x999
if ( html ) result.push('<span class="tel">');
if ( html ) result.push(`<a href="tel:+${countrycode}${matches[2]}${matches[3]}${matches[4]}" class="tel-link ${classes}">`);
result.push(`${countrycode} (${matches[2]}) ${matches[3]}-${matches[4]}`);
if ( html ) result.push('</a>');
// Note: tel: links cannot *reliably* include an extension, so it comes after the link.
if ( ext && html ) result.push(`<span class="tel-ext"><span> x</span>${ext}</span>`);
else if ( ext ) result.push(` x${ext}`);
if ( html ) result.push('</span>');
return result.join('');
}
// Pattern not found
return string; // The phone number isn't valid, but that's ok. Keep the original.
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for this, it's just what I needed. It should probably be noted that
esc_html()
is a WordPress-specific function and will return an error if you're using this code outside WordPress.