<?php declare(strict_types=1);  
    namespace AutoTel; # add suffix 'new' for development version
    if (!defined('PmWiki')) exit();
/* AutoTel recipe  
+
  Copyright 2022-present Simon Davis, Petko Yotov
  This software is written for PmWiki; you can redistribute it and/or modify it under the terms
  of the GNU General Public License as published by the Free Software Foundation; 
  either version 3 of the License, or (at your option) any later version. 
  See pmwiki.php for full details and lack of warranty.
  
  The recipe implements PmWiki markup that detects telephone numbers.
  The telephone number are wrapped in an anchor element using the "tel:" URI scheme.
  This enables calling by clicking on the link where a device supports it to dial the number.
  The tel: number is formatted with the hyphen visual separator before area code and subscriber number
  The user supplied text is displayed unchanged, but spaces are converted to non-breaking spaces to avoid the number wrapping
  See
  * RFC 5341    https://www.rfc-editor.org/rfc/rfc5341.html The Internet Assigned Number Authority (IANA) tel Uniform Resource Identifier (URI) Parameter Registry
  * RFC 3966    https://www.rfc-editor.org/rfc/rfc3966.html The tel URI for Telephone Numbers
  * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a
  * https://www.pmwiki.org/wiki/Cookbook/AutoTel
  * http://regexstorm.net/tester
  Regex notes
  * Free spacing (/x) mode is used
  * Case insensitive (/i) mode is used in case text is supplied
+
Revision History <reverse chronological order please>
# 2022-12-22 Initial version based on Petko Yotov's code snippet at https://www.pmwiki.org/wiki/Cookbook/LinkTel-Talk
*/
    DEFINE ('AUTOTELNAME', 'AutoTel');
    if (substr(__NAMESPACE__, -3) === 'new') {
        $AutoTelNew = 'new'; # empty string for production version, 'new' for development version
    }
#
    if (boolval($DisableRecipe[AUTOTELNAME]) === true) return;
  # set debug flag
    \SDV($AutoTelDebug, false); # set default debug setting if not defined in an configuration file
    $AutoTel_debugon = boolval ($AutoTelDebug); # if on writes input and output to web page
# Version date
    $RecipeInfo[AUTOTELNAME]['Version'] = '2022-12-22' . $AutoTelNew; # PmWiki version numbering is done by date
# recipe version page variable
    $FmtPV['$AutoTelVersion'] = "'" . __NAMESPACE__ . " version {$RecipeInfo[AUTOTELNAME]['Version']}'"; // return version as a custom page variable
# declare $AutoTel for (:if enabled AutoTel:) recipe installation check
    $AutoTel = true; # enabled
##
## get configuration defaults
    \SDV($AutoTelConfig, array(
      'CountryCodeDefault' => '+64',
      'AreaCodeDefault' => '4',
    ));
  #
  # the following characters cannot be immediately before a telephone number
  # telephone number cannot start in the middle of a number
  DEFINE ('IGNOREPREFIX', 
      '# not preceded by [, :, =, #, apos, quote, 0-9, or 0-9 followed by a space
      (?<![:\\["\'=#0-9]|[0-9][ ])');
  # the following characters cannot be immediately after a telephone number
  DEFINE ('IGNORESUFFIX', 
      '# not followed by 0-9 or space 0-9
      (?![ ]?[0-9])');
  # visual separator is space or hyphen, or for legacy reasons '&nbsp;'
  DEFINE ('VISUALSEPARATOR_VAL', 
      '[ -]|&nbsp;');
  # visual separator, non capturing group
  DEFINE ('VISUALSEPARATOR', 
      '(?:' . VISUALSEPARATOR_VAL . ')');
  # country code is recognised by the leading "+"
  DEFINE ('COUNTRYCODE', 
      '# optional country code capture group
      (\\+\\d{1,3})?');
  # capture group
  DEFINE ('AREACODE_MOBILE', 
      '# area code mobile, optional leading zero, (1 2); capture group
      ([0]?\\d{1,2})');  
  # capture group
  DEFINE ('AREACODE_LAND', 
      '# area code land, optional leading zero, (1); capture group
      ([0]?\\d{1,1})');
  #
  DEFINE ('SUBSCRIBERNUMBER_MOBILE', 
      '# subscriber number mobile, may be split in the middle. (3 3, 3 4, 4 3, or 3 5); capture group
      (\\d{3}(?:[ -]|&nbsp;)?\\d{5}|\\d{3,4}(?:[ -]|&nbsp;)?\\d{3,4})');
  #
  DEFINE ('SUBSCRIBERNUMBER_LAND', 
      '# subscriber number land line, may be split in the middle. (3 4 or 4 3); capture group
      (\\d{3}(?:[ -]|&nbsp;)?\\d{4}|\\d{4}(?:[ -]|&nbsp;)?\\d{3})');
## 
  $MarkupPatternLand = '/' . IGNOREPREFIX 
    # optional country code and area code, non-capturing group
    . '(?:'
    # optional country code followed by optional visual separator
    . COUNTRYCODE . VISUALSEPARATOR . '?'
    # area code land, optionally in (parenthesis), followed by mandatory visual separator
    . '[\\(]?' . AREACODE_LAND . '(?:[\\)]?|[\\)]?' . VISUALSEPARATOR . ')'
    . ')?'
    . SUBSCRIBERNUMBER_LAND
    . IGNORESUFFIX
    . '/xi';
  ## for land line, requires subscriber number (must be first call to MarkUp)
  Markup('autotel_landline', '>links', $MarkupPatternLand, __NAMESPACE__ . '\AutoTelFmt');
  ##
##
  $MarkupPatternMobile = '/' . IGNOREPREFIX 
    # optional country code followed by optional visual separator
    . COUNTRYCODE . VISUALSEPARATOR . '?'
    # area code mobile, optionally in (parenthesis), followed by mandatory visual separator
    . '[\\(]?' . AREACODE_MOBILE . '(?:[\\)]?|[\\)]?' . VISUALSEPARATOR . ')'
    . SUBSCRIBERNUMBER_MOBILE
    . IGNORESUFFIX
    . '/xi';
  ## for mobile, requires area code and subscriber number (must be second call)
  Markup('autotel_mobile', '>links', $MarkupPatternMobile, __NAMESPACE__ . '\AutoTelFmt');
#
  return; # finished recipe setup
#
  function AutoTelFmt($m) {
    # process telephone number when detected      
    global $AutoTelConfig;

    $ccode = @$m[1]? $m[1] : $AutoTelConfig['CountryCodeDefault']; # add country code if unset

    $acode = @$m[2]? $m[2] : $AutoTelConfig['AreaCodeDefault']; # area code if unset
    if(!@$m[1]) $acode = preg_replace('/^0/','',$acode); # trim area code leading zero
     
    $remspace = array (' ', '&nbsp;', '-', '&#8209;');
    # remove embedded separators
    $subnr = str_replace ($remspace, '', $m[3]);
    # add visual separator
    $subnr = substr_replace ($subnr, '-', intdiv (strlen ($subnr), 2), 0);
    # build dialable number with visual separators
    $telval = "$ccode($acode)$subnr";
    
    $remsep = array (' ', '-'); # separators to be replaced
    $replsep = array ('&nbsp;', '&#8209;'); # non-breaking space and hyphen
    $displaynr = str_replace ($remsep, $replsep, $m[0]);
    $disptitle = \XL('Dial') . ' ' . $telval;

    return Keep("<a class='tel' title='$disptitle' href='tel:$telval'>$displaynr</a>");
  }