$title_setting = $this->getSetting('title');
foreach ($items as $delta => $item) {
+ // If the telephone number is 5 or less digits, parse_url() will think
+ // it's a port number rather than a phone number which causes the link
+ // formatter to throw an InvalidArgumentException. Avoid this by inserting
+ // a dash (-) after the first digit - RFC 3966 defines the dash as a
+ // visual separator character and so will be removed before the phone
+ // number is used. See https://bugs.php.net/bug.php?id=70588 for more.
+ // While the bug states this only applies to numbers <= 65535, a 5 digit
+ // number greater than 65535 will cause parse_url() to return FALSE so
+ // we need the work around on any 5 digit (or less) number.
+ // First we strip whitespace so we're counting actual digits.
+ $phone_number = preg_replace('/\s+/', '', $item->value);
+ if (strlen($phone_number) <= 5) {
+ $phone_number = substr_replace($phone_number, '-', 1, 0);
+ }
+
// Render each element as link.
$element[$delta] = [
'#type' => 'link',
// itself as title.
'#title' => $title_setting ?: $item->value,
// Prepend 'tel:' to the telephone number.
- '#url' => Url::fromUri('tel:' . rawurlencode(preg_replace('/\s+/', '', $item->value))),
+ '#url' => Url::fromUri('tel:' . rawurlencode($phone_number)),
'#options' => ['external' => TRUE],
];