Beispiel #1
0
function paging_get_config($engine)
{
    global $db;
    global $ext;
    global $chan_dahdi;
    global $version;
    switch ($engine) {
        case "asterisk":
            $ast_ge_16 = version_compare($version, "1.6", "ge");
            // setup for intercom
            $fcc = new featurecode('paging', 'intercom-prefix');
            $intercom_code = $fcc->getCodeActive();
            unset($fcc);
            // Since these are going down channel local, set ALERT_INFO and SIPADDHEADER which will be set in dialparties.agi
            // no point in even setting the headers here they will get lost in channel local
            //
            /* Set these up once here and in intercom so that autoanswer macro does not have
             * to go through this for every single extension which causes a lot of extra overhead
             * with big page groups
             */
            $has_answermacro = false;
            $alertinfo = 'Alert-Info: Ring Answer';
            $callinfo = 'Call-Info: <uri>\\;answer-after=0';
            $sipuri = 'intercom=true';
            $doptions = 'A(beep)';
            $dtime = '5';
            $custom_vars = array();
            $autoanswer_arr = paging_get_autoanswer_defaults();
            foreach ($autoanswer_arr as $autosetting) {
                switch (trim($autosetting['var'])) {
                    case 'ALERTINFO':
                        $alertinfo = trim($autosetting['setting']);
                        break;
                    case 'CALLINFO':
                        $callinfo = trim($autosetting['setting']);
                        break;
                    case 'SIPURI':
                        $sipuri = trim($autosetting['setting']);
                        break;
                    case 'VXML_URL':
                        $vxml_url = trim($autosetting['setting']);
                        break;
                    case 'DOPTIONS':
                        $doptions = trim($autosetting['setting']);
                        break;
                    case 'DTIME':
                        $dtime = trim($autosetting['setting']);
                        break;
                    default:
                        $key = trim($autosetting['var']);
                        $custom_vars[$key] = trim($autosetting['setting']);
                        if (ltrim($custom_vars[$key], '_') == "ANSWERMACRO") {
                            $has_answermacro = true;
                        }
                        break;
                }
            }
            $extpaging = 'ext-paging';
            if (!empty($intercom_code)) {
                $code = '_' . $intercom_code . '.';
                $context = 'ext-intercom';
                $ext->add($context, $code, '', new ext_macro('user-callerid'));
                $ext->add($context, $code, '', new ext_setvar('dialnumber', '${EXTEN:' . strlen($intercom_code) . '}'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/block)}" = "blocked"]', 'end'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(DND/${dialnumber})}" = "YES"]', 'end'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom/${AMPUSER})}" = "allow" ]', 'allow'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom/${AMPUSER})}" = "deny" ]', 'nointercom'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom)}" = "disabled" ]', 'nointercom'));
                $ext->add($context, $code, 'allow', new ext_dbget('DEVICES', 'AMPUSER/${dialnumber}/device'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DEVICES}" = "" ]', 'end'));
                $ext->add($context, $code, '', new ext_setvar('LOOPCNT', '${FIELDQTY(DEVICES,&)}'));
                /* Set these up so that macro-autoanswer doesn't have to
                 */
                $ext->add($context, $code, '', new ext_setvar('_SIPURI', ''));
                if (trim($alertinfo) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_ALERTINFO', $alertinfo));
                }
                if (trim($callinfo) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_CALLINFO', $callinfo));
                }
                if (trim($sipuri) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_SIPURI', $sipuri));
                }
                if (trim($vxml_url) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_VXML_URL', $vxml_url));
                }
                if (trim($doptions) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_DOPTIONS', $doptions));
                }
                foreach ($custom_vars as $key => $value) {
                    $ext->add($context, $code, '', new ext_setvar('_' . ltrim($key, '_'), $value));
                }
                $ext->add($context, $code, '', new ext_setvar('_DTIME', $dtime));
                $ext->add($context, $code, '', new ext_setvar('_ANSWERMACRO', ''));
                $ext->add($context, $code, '', new ext_gotoif('$[${LOOPCNT} > 1 ]', 'pagemode'));
                $ext->add($context, $code, '', new ext_macro('autoanswer', '${DEVICES}'));
                if ($ast_ge_16) {
                    $ext->add($context, $code, 'check', new ext_chanisavail('${DIAL}', 's'));
                    $ext->add($context, $code, '', new ext_gotoif('$["${AVAILORIGCHAN}" == ""]', 'end'));
                } else {
                    $ext->add($context, $code, 'check', new ext_chanisavail('${DIAL}', 'sj'));
                }
                $ext->add($context, $code, '', new ext_dial('${DIAL}', '${DTIME},${DOPTIONS}'));
                $ext->add($context, $code, 'end', new ext_busy());
                $ext->add($context, $code, '', new ext_macro('hangupcall'));
                if (!$ast_ge_16) {
                    $ext->add($context, $code, '', new ext_busy(), 'check', 101);
                    $ext->add($context, $code, '', new ext_macro('hangupcall'));
                }
                $ext->add($context, $code, 'pagemode', new ext_setvar('ITER', '1'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', ''));
                $ext->add($context, $code, 'begin', new ext_setvar('DIALSTR', '${DIALSTR}&LOCAL/PAGE${CUT(DEVICES,&,${ITER})}@' . $extpaging));
                $ext->add($context, $code, '', new ext_setvar('ITER', '$[${ITER} + 1]'));
                $ext->add($context, $code, '', new ext_gotoif('$[${ITER} <= ${LOOPCNT}]', 'begin'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', '${DIALSTR:1}'));
                $ext->add($context, $code, '', new ext_setvar('_AMPUSER', '${AMPUSER}'));
                $ext->add($context, $code, '', new ext_page('${DIALSTR},d'));
                $ext->add($context, $code, '', new ext_busy());
                $ext->add($context, $code, '', new ext_macro('hangupcall'));
                $ext->add($context, $code, 'nointercom', new ext_noop('Intercom disallowed by ${dialnumber}'));
                $ext->add($context, $code, '', new ext_playback('intercom&for&extension'));
                $ext->add($context, $code, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $code, '', new ext_playback('is&disabled'));
                $ext->add($context, $code, '', new ext_congestion());
                $extintercomusers = 'ext-intercom-users';
                $userlist = core_users_list();
                if (is_array($userlist)) {
                    foreach ($userlist as $item) {
                        $ext_intercom_code = $intercom_code . $item[0];
                        $ext->add($extintercomusers, $ext_intercom_code, '', new ext_goto($context . ',${EXTEN},1'));
                    }
                }
                $context = $extintercomusers;
                $ext->addInclude('from-internal-additional', $context);
            }
            $fcc = new featurecode('paging', 'intercom-on');
            $oncode = $fcc->getCodeActive();
            unset($fcc);
            if ($oncode) {
                $ext->add($context, $oncode, '', new ext_answer(''));
                $ext->add($context, $oncode, '', new ext_wait('1'));
                $ext->add($context, $oncode, '', new ext_macro('user-callerid'));
                $ext->add($context, $oncode, '', new ext_setvar('DB(AMPUSER/${AMPUSER}/intercom)', 'enabled'));
                $ext->add($context, $oncode, '', new ext_playback('intercom&enabled'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $target = '${EXTEN:' . strlen($oncode) . '}';
                $oncode = "_" . $oncode . ".";
                $ext->add($context, $oncode, '', new ext_answer(''));
                $ext->add($context, $oncode, '', new ext_wait('1'));
                $ext->add($context, $oncode, '', new ext_macro('user-callerid'));
                $ext->add($context, $oncode, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/' . $target . ')}" = "allow" ]}', 'unset'));
                $ext->add($context, $oncode, '', new ext_gotoif('$[${DB_EXISTS(AMPUSER/${EXTEN:3}/device)} != 1]', 'invaliduser'));
                $ext->add($context, $oncode, '', new ext_dbput('AMPUSER/${AMPUSER}/intercom/' . $target, 'allow'));
                $ext->add($context, $oncode, '', new ext_playback('intercom&enabled&for&extension&number'));
                $ext->add($context, $oncode, '', new ext_saydigits($target));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $ext->add($context, $oncode, 'unset', new ext_dbdeltree('AMPUSER/${AMPUSER}/intercom/' . $target));
                $ext->add($context, $oncode, '', new ext_playback('intercom&enabled&cancelled&for&extension&number'));
                $ext->add($context, $oncode, '', new ext_saydigits($target));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $ext->add($context, $oncode, 'invaliduser', new ext_playback('extension&number'));
                $ext->add($context, $oncode, '', new ext_saydigits($target));
                $ext->add($context, $oncode, '', new ext_playback('is&invalid'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
            }
            $fcc = new featurecode('paging', 'intercom-off');
            $offcode = $fcc->getCodeActive();
            unset($fcc);
            if ($offcode) {
                $ext->add($context, $offcode, '', new ext_answer(''));
                $ext->add($context, $offcode, '', new ext_wait('1'));
                $ext->add($context, $offcode, '', new ext_macro('user-callerid'));
                $ext->add($context, $offcode, '', new ext_setvar('DB(AMPUSER/${AMPUSER}/intercom)', 'disabled'));
                $ext->add($context, $offcode, '', new ext_playback('intercom&disabled'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $target = '${EXTEN:' . strlen($offcode) . '}';
                $offcode = "_" . $offcode . ".";
                $ext->add($context, $offcode, '', new ext_answer(''));
                $ext->add($context, $offcode, '', new ext_wait('1'));
                $ext->add($context, $offcode, '', new ext_macro('user-callerid'));
                $ext->add($context, $offcode, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/' . $target . ')}" = "deny" ]}', 'unset2'));
                $ext->add($context, $offcode, '', new ext_gotoif('$[${DB_EXISTS(AMPUSER/${EXTEN:3}/device)} != 1]', 'invaliduser2'));
                $ext->add($context, $offcode, '', new ext_dbput('AMPUSER/${AMPUSER}/intercom/' . $target, 'deny'));
                $ext->add($context, $offcode, '', new ext_playback('intercom&disabled&for&extension&number'));
                $ext->add($context, $offcode, '', new ext_saydigits($target));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $ext->add($context, $offcode, 'unset2', new ext_dbdeltree('AMPUSER/${AMPUSER}/intercom/' . $target));
                $ext->add($context, $offcode, '', new ext_playback('intercom&disabled&cancelled&for&extension&number'));
                $ext->add($context, $offcode, '', new ext_saydigits($target));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $ext->add($context, $offcode, 'invaliduser2', new ext_playback('extension&number'));
                $ext->add($context, $offcode, '', new ext_saydigits($target));
                $ext->add($context, $offcode, '', new ext_playback('is&invalid'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
            }
            /* Create macro-autoanswer that will try to intelligently set the
            		   	required parameters to handle paging. Eventually it will use
            			 	known device information.
            
            				This macro does the following:
            
            				Input:  FreePBX Device number to be called requiring autoanswer
            				Output: ${DIAL} Channel Variable with the dial string to be called
            				        Appropriate SIP headers added
            								Other special requirements that may be custom for this device
            
            				1. Set ${DIAL} to the device's dial string
            				2. If there is a device specific macro defined in the DEVICE's object
            				   (DEVICE/<devicenum>/autoanswer/macro) then execute that macro and end
            				3. Try to identify endpoints by their useragents that may need known
            				   changes and make those changes. These are generated from the
            					 paging_autoanswer table so users can extend them, if any are present
            				5. Set the variables and end unless a useragent specific ANSWERMACRO is
            				   defined in which case call it and end.
            
            				This macro is called for intercoming and paging to try and enable the
            				target device to auto-answer. Devices with special needs can be handled
            				with the device specific macro. For example, if you have a device that
            				can not auto-answer except by specifically configuring a line key on
            				the device that always answers, you could use a device specific macro
            				to change the dialstring. If you had a set of such devices, you could
            				standardize on the device numbers (e.g. nnnn for normal calls and 2nnnn
            				for auto-answer calls). You could then create a general purpose macro
            				to modify the dial string accordingly. Provisioning tools will be able
            				to take advantage of setting and creating such an ability.
            				If you have a set of devices that can be identified with a SIP useragent
            				then you can use a general macro without setting info in each device.
            		 	*/
            $autoanswer_arr = paging_get_autoanswer_useragents();
            $macro = 'macro-autoanswer';
            $ext->add($macro, "s", '', new ext_setvar('DIAL', '${DB(DEVICE/${ARG1}/dial)}'));
            // If we are in DAHDI compat mode, then we need to substitute DAHDI for ZAP
            if ($chan_dahdi) {
                $ext->add($macro, "s", '', new ext_execif('$["${DIAL:0:3}" = "ZAP"]', 'Set', 'DIAL=DAHDI${DIAL:3}'));
            }
            $ext->add($macro, "s", '', new ext_gotoif('$["${DB(DEVICE/${ARG1}/autoanswer/macro)}" != "" ]', 'macro'));
            // If there are no phone specific auto-answer vars, then we don't care what the phone is below
            //
            if (!empty($autoanswer_arr)) {
                $ext->add($macro, "s", '', new ext_setvar('phone', '${SIPPEER(${CUT(DIAL,/,2)}:useragent)}'));
            }
            // We used to set all the variables here (ALERTINFO, CALLINFO, etc. That has been moved to each
            // paging group and the intercom main macro, since it was redundant for every phone causing a lot
            // of overhead with large page groups.
            //
            // Defaults are setup, now make specific adjustments for detected phones
            // These come from the SQL table as well where installations can make customizations
            //
            foreach ($autoanswer_arr as $autosetting) {
                $useragent = trim($autosetting['useragent']);
                $autovar = trim($autosetting['var']);
                $data = trim($autosetting['setting']);
                switch (ltrim($autovar, '_')) {
                    case 'ANSWERMACRO':
                        $has_answermacro = true;
                        // fall through - no break on purpose
                    // fall through - no break on purpose
                    case 'ALERTINFO':
                    case 'CALLINFO':
                    case 'SIPURI':
                    case 'VXML_URL':
                    case 'DOPTIONS':
                    case 'DTIME':
                    default:
                        if (trim($data) != "") {
                            $ext->add($macro, "s", '', new ext_execif('$["${phone:0:' . strlen($useragent) . '}" = "' . $useragent . '"]', 'Set', $autovar . '=' . $data));
                        }
                        break;
                }
            }
            // Now any adjustments have been made, set the headers and done
            //
            if ($has_answermacro) {
                $ext->add($macro, "s", '', new ext_gotoif('$["${ANSWERMACRO}" != ""]', 'macro2'));
            }
            $ext->add($macro, "s", '', new ext_execif('$["${ALERTINFO}" != ""]', 'SipAddHeader', '${ALERTINFO}'));
            $ext->add($macro, "s", '', new ext_execif('$["${CALLINFO}" != ""]', 'SipAddHeader', '${CALLINFO}'));
            $ext->add($macro, "s", '', new ext_execif('$["${SIPURI}" != ""]', 'Set', '__SIP_URI_OPTIONS=${SIPURI}'));
            $ext->add($macro, "s", 'macro', new ext_macro('${DB(DEVICE/${ARG1}/autoanswer/macro)}', '${ARG1}'), 'n', 2);
            if ($has_answermacro) {
                $ext->add($macro, "s", 'macro2', new ext_macro('${ANSWERMACRO}', '${ARG1}'), 'n', 2);
            }
            // Create the paging context that is used in the paging application for each phone to auto-answer
            //
            $ext->addInclude('from-internal-additional', $extpaging);
            // Normal page version
            $ext->add($extpaging, "_PAGE.", '', new ext_gotoif('$[ ${AMPUSER} = ${EXTEN:4} ]', 'skipself'));
            if ($ast_ge_16) {
                $ext->add($extpaging, "_PAGE.", 'AVAIL', new ext_chanisavail('${DB(DEVICE/${EXTEN:4}/dial)}', 's'));
                $ext->add($extpaging, "_PAGE.", '', new ext_gotoif('$["${AVAILORIGCHAN}" == ""]', 'skipself'));
            } else {
                $ext->add($extpaging, "_PAGE.", 'AVAIL', new ext_chanisavail('${DB(DEVICE/${EXTEN:4}/dial)}', 'js'));
            }
            $ext->add($extpaging, "_PAGE.", '', new ext_gotoif('$["${DB(DND/${DB(DEVICE/${EXTEN:4}/user)})}" = "YES"]', 'skipself'));
            $ext->add($extpaging, "_PAGE.", 'SKIPCHECK', new ext_macro('autoanswer', '${EXTEN:4}'));
            $ext->add($extpaging, "_PAGE.", '', new ext_dial('${DIAL}', '${DTIME},${DOPTIONS}'));
            $ext->add($extpaging, "_PAGE.", 'skipself', new ext_hangup());
            if (!$ast_ge_16) {
                $ext->add($extpaging, "_PAGE.", '', new ext_hangup(''), 'AVAIL', 101);
            }
            // Force page version
            $ext->add($extpaging, "_FPAGE.", '', new ext_gotoif('$[ ${AMPUSER} = ${EXTEN:5} ]', 'skipself'));
            $ext->add($extpaging, "_FPAGE.", 'SKIPCHECK', new ext_macro('autoanswer', '${EXTEN:5}'));
            $ext->add($extpaging, "_FPAGE.", '', new ext_dial('${DIAL}', '${DTIME},${DOPTIONS}'));
            $ext->add($extpaging, "_FPAGE.", 'skipself', new ext_hangup());
            //
            // Now get a list of all the paging groups...
            $sql = "SELECT page_group, force_page, duplex FROM paging_config";
            $paging_groups = $db->getAll($sql, DB_FETCHMODE_ASSOC);
            foreach ($paging_groups as $thisgroup) {
                $grp = trim($thisgroup['page_group']);
                $pagemode = $thisgroup['force_page'] ? 'FPAGE' : 'PAGE';
                $sql = "SELECT ext FROM paging_groups WHERE page_number='{$grp}'";
                $all_exts = $db->getAll($sql);
                $dialstr = '';
                foreach ($all_exts as $local_dial) {
                    if (strtoupper(substr($local_dial[0], -1)) == "X") {
                        $local_dial[0] = rtrim($local_dial[0], "xX");
                    }
                    $dialstr .= "LOCAL/{$pagemode}" . trim($local_dial[0]) . "@" . $extpaging . "&";
                }
                // It will always end with an &, so lets take that off.
                $dialstr = rtrim($dialstr, "&");
                if ($thisgroup['duplex']) {
                    $dialstr .= ",d";
                }
                $ext->add($extpaging, $grp, '', new ext_answer(''));
                $ext->add($extpaging, $grp, '', new ext_macro('user-callerid'));
                // make AMPUSER inherited here, so we can skip the proper 'self' if using cidnum masquerading
                $ext->add($extpaging, $grp, '', new ext_setvar('_AMPUSER', '${AMPUSER}'));
                $ext->add($extpaging, $grp, '', new ext_setvar('_SIPURI', ''));
                if (trim($alertinfo) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_ALERTINFO', $alertinfo));
                }
                if (trim($callinfo) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_CALLINFO', $callinfo));
                }
                if (trim($sipuri) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_SIPURI', $sipuri));
                }
                if (trim($vxml_url) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_VXML_URL', $vxml_url));
                }
                if (trim($doptions) != "") {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_DOPTIONS', $doptions));
                }
                $ext->add($extpaging, $grp, '', new ext_setvar('_DTIME', $dtime));
                $ext->add($extpaging, $grp, '', new ext_setvar('_ANSWERMACRO', ''));
                foreach ($custom_vars as $key => $value) {
                    $ext->add($extpaging, $grp, '', new ext_setvar('_' . ltrim($key, '_'), $value));
                }
                $ext->add($extpaging, $grp, '', new ext_setvar('__FORWARD_CONTEXT', 'block-cf'));
                $ext->add($extpaging, $grp, '', new ext_page($dialstr));
            }
            break;
    }
}
function paging_get_config($engine)
{
    global $db, $ext, $chan_dahdi, $version, $amp_conf, $conferences_conf;
    switch ($engine) {
        case "asterisk":
            // setup for intercom
            $fcc = new featurecode('paging', 'intercom-prefix');
            $intercom_code = $fcc->getCodeActive();
            unset($fcc);
            // Since these are going down channel local, set ALERT_INFO and SIPADDHEADER which will be set in dialparties.agi
            // no point in even setting the headers here they will get lost in channel local
            //
            /* Set these up once here and in intercom so that autoanswer macro does not have
             * to go through this for every single extension which causes a lot of extra overhead
             * with big page groups
             */
            $has_answermacro = false;
            $alertinfo = 'Ring Answer';
            $callinfo = '<uri>\\;answer-after=0';
            $sipuri = 'intercom=true';
            $doptions = 'A(beep)b(autoanswer^s^1(${ALERTINFO},${CALLINFO}))';
            $vxml_url = '';
            $dtime = '5';
            $custom_vars = array();
            $autoanswer_arr = paging_get_autoanswer_defaults();
            foreach ($autoanswer_arr as $autosetting) {
                switch (trim($autosetting['var'])) {
                    case 'ALERTINFO':
                        $alertinfo = trim($autosetting['setting']);
                        break;
                    case 'CALLINFO':
                        $callinfo = trim($autosetting['setting']);
                        break;
                    case 'SIPURI':
                        $sipuri = trim($autosetting['setting']);
                        break;
                    case 'VXML_URL':
                        $vxml_url = trim($autosetting['setting']);
                        break;
                    case 'DOPTIONS':
                        $doptions = trim($autosetting['setting']);
                        break;
                    case 'DTIME':
                        $dtime = trim($autosetting['setting']);
                        break;
                    default:
                        $key = trim($autosetting['var']);
                        $custom_vars[$key] = trim($autosetting['setting']);
                        if (ltrim($custom_vars[$key], '_') == "ANSWERMACRO") {
                            $has_answermacro = true;
                        }
                        break;
                }
            }
            $apppaging = 'app-paging';
            if (!empty($intercom_code)) {
                $code = '_' . $intercom_code . '.';
                $context = 'ext-intercom';
                // Add for languages
                $ext->add($context, 'lang-playback', '', new ext_gosubif('$[${DIALPLAN_EXISTS(' . $context . ',${CHANNEL(language)})}]', $context . ',${CHANNEL(language)},${ARG1}', $context . ',en,${ARG1}'));
                $ext->add($context, 'lang-playback', '', new ext_return());
                $ext->add($context, $code, '', new ext_macro('user-callerid'));
                $ext->add($context, $code, '', new ext_setvar('dialnumber', '${EXTEN:' . strlen($intercom_code) . '}'));
                $ext->add($context, $code, '', new ext_setvar('INTERCOM_CALL', 'TRUE'));
                $ext->add($context, $code, '', new ext_gosub('1', 's', 'sub-record-check', 'exten,${dialnumber}'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/block)}" = "blocked"]', 'end'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(DND/${dialnumber})}" = "YES"]', 'end'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom/${AMPUSER})}" = "allow" ]', 'allow'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom/${AMPUSER})}" = "deny" ]', 'nointercom'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${dialnumber}/intercom)}" = "disabled" ]', 'nointercom'));
                $ext->add($context, $code, 'allow', new ext_dbget('DEVICES', 'AMPUSER/${dialnumber}/device'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DEVICES}" = "" ]', 'end'));
                $ext->add($context, $code, '', new ext_dbget('OVERRIDE', 'AMPUSER/${dialnumber}/intercom/override'));
                $ext->add($context, $code, '', new ext_setvar('LOOPCNT', '${FIELDQTY(DEVICES,&)}'));
                /* Set these up so that macro-autoanswer doesn't have to
                 */
                $ext->add($context, $code, '', new ext_setvar('_SIPURI', ''));
                if (trim($alertinfo) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_ALERTINFO', $alertinfo));
                }
                if (trim($callinfo) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_CALLINFO', $callinfo));
                }
                if (trim($sipuri) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_SIPURI', $sipuri));
                }
                if (trim($vxml_url) != "") {
                    $ext->add($context, $code, '', new ext_setvar('_VXML_URL', $vxml_url));
                }
                foreach ($custom_vars as $key => $value) {
                    $ext->add($context, $code, '', new ext_setvar('_' . ltrim($key, '_'), $value));
                }
                $ext->add($context, $code, '', new ext_setvar('_DTIME', $dtime));
                $ext->add($context, $code, '', new ext_setvar('_ANSWERMACRO', ''));
                $ext->add($context, $code, '', new ext_gotoif('$[${LOOPCNT} > 1 ]', 'pagemode'));
                $ext->add($context, $code, '', new ext_macro('autoanswer', '${DEVICES}'));
                $ext->add($context, $code, '', new ext_setvar('_DOPTIONS', $doptions));
                $ext->add($context, $code, 'check', new ext_chanisavail('${DEVICE}', 's'));
                // If it's ringing for an inbound call, we should page.
                $ext->add($context, $code, '', new ext_execif('$["${AVAILSTATUS}" = "6"]', 'Set', 'AVAILORIGCHAN=${DEVICE}'));
                // Did we have a device we can page? If so, go to continue. If not, check for
                // paging override functions.
                $ext->add($context, $code, '', new ext_gotoif('$["${AVAILORIGCHAN}" != ""]', 'continue'));
                // Check the intercom override.
                $ext->add($context, $code, '', new ext_execif('$["${OVERRIDE}" = ""]', 'Set', 'OVERRIDE=reject'));
                $ext->add($context, $code, '', new ext_gotoif('$["${OVERRIDE}" = "reject"]', 'end'));
                // We don't know what the phones are going to do. Let's be generous.
                $ext->add($context, $code, '', new ext_set('DTIME', '30'));
                // If it's ring, treat it as a normal call.
                $ext->add($context, $code, '', new ext_execif('$["${OVERRIDE}" = "ring"]', 'Set', 'DOPTIONS=A(beep)'));
                // It's something else. Assume it's force, and just smash the device.
                $ext->add($context, $code, 'continue', new ext_noop('Continuing with page', 5));
                $len = strlen($code) - 2;
                $dopt = 'I';
                // Don't sent connectedline updates.
                $ext->add($context, $code, '', new ext_gotoif('$["${DB(AMPUSER/${EXTEN:' . $len . '}/cidname)}" = ""]', 'godial'));
                $ext->add($context, $code, '', new ext_set('CONNECTEDLINE(name,i)', '${DB(AMPUSER/${EXTEN:' . $len . '}/cidname)}'));
                $ext->add($context, $code, '', new ext_set('CONNECTEDLINE(num)', '${EXTEN:' . $len . '}'));
                $ext->add($context, $code, 'godial', new ext_dial('${DIAL}', '${DTIME},' . $dopt . '${DOPTIONS}${INTERCOM_EXT_DOPTIONS}'));
                $ext->add($context, $code, 'end', new ext_execif('$[${INTERCOM_RETURN}]', 'Return'));
                $ext->add($context, $code, '', new ext_busy());
                $ext->add($context, $code, '', new ext_macro('hangupcall'));
                $ext->add($context, $code, 'pagemode', new ext_setvar('ITER', '1'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', ''));
                $ds = $amp_conf['ASTCONFAPP'] == 'app_confbridge' ? '${DIALSTR}-${CUT(DEVICES,&,${ITER})}' : '${DIALSTR}&LOCAL/PAGE${CUT(DEVICES,&,${ITER})}@' . $apppaging;
                $ext->add($context, $code, 'begin', new ext_chanisavail('${DB(DEVICE/${CUT(DEVICES,&,${ITER})}/dial)}', 's'));
                $ext->add($context, $code, '', new ext_gotoif('$["${AVAILORIGCHAN}" = ""]', 'skip'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', $ds));
                $ext->add($context, $code, 'skip', new ext_setvar('ITER', '$[${ITER} + 1]'));
                $ext->add($context, $code, '', new ext_gotoif('$[${ITER} <= ${LOOPCNT}]', 'begin'));
                $ext->add($context, $code, '', new ext_setvar('DIALSTR', '${DIALSTR:1}'));
                $ext->add($context, $code, '', new ext_gotoif('$["${DIALSTR}" = ""]', 'end2'));
                $ext->add($context, $code, '', new ext_setvar('_AMPUSER', '${AMPUSER}'));
                if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                    $ext->add($context, $code, '', new ext_gosub('1', 'page', false, '${DIALSTR}'));
                } else {
                    $ext->add($context, $code, '', new ext_page('${DIALSTR},d'));
                }
                $ext->add($context, $code, 'end2', new ext_execif('$[${INTERCOM_RETURN}]', 'Return'));
                $ext->add($context, $code, '', new ext_busy());
                $ext->add($context, $code, '', new ext_macro('hangupcall'));
                $ext->add($context, $code, 'nointercom', new ext_noop('Intercom disallowed by ${dialnumber}'));
                $ext->add($context, $code, '', new ext_execif('$[${INTERCOM_RETURN}]', 'Return'));
                $ext->add($context, $code, '', new ext_gosub('1', 'lang-playback', $context, 'hook_0'));
                $ext->add($context, $code, '', new ext_congestion());
                if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                    $sub = 'page';
                    $ext->add($context, $sub, '', new ext_set('PAGE_CONF', '${EPOCH}${RAND(100,999)}'));
                    $ext->add($context, $sub, '', new ext_set('PAGEMODE', 'PAGE'));
                    $ext->add($context, $sub, '', new ext_set('PAGE_MEMBERS', '${ARG1}'));
                    $ext->add($context, $sub, '', new ext_set('PAGE_CONF_OPTS', 'duplex'));
                    $ext->add($context, $sub, '', new ext_agi('page.agi'));
                    $ext->add($context, $sub, '', new ext_set('CONFBRIDGE(user,template)', 'page_user_duplex'));
                    $ext->add($context, $sub, '', new ext_set('CONFBRIDGE(user,admin)', 'yes'));
                    $ext->add($context, $sub, '', new ext_set('CONFBRIDGE(user,marked)', 'yes'));
                    $ext->add($context, $sub, '', new ext_meetme('${PAGE_CONF}', ',', 'admin_menu'));
                    $ext->add($context, $sub, '', new ext_hangup());
                }
                $lang = 'en';
                // English
                $ext->add($context, $lang, 'hook_0', new ext_playback('intercom&for&extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('is&disabled'));
                $ext->add($context, $lang, '', new ext_return());
                $lang = 'ja';
                // Japanese
                $ext->add($context, $lang, 'hook_0', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-no&intercom&jp-wa&disabled-2'));
                $ext->add($context, $lang, '', new ext_return());
                $extintercomusers = 'ext-intercom-users';
                $sql = "SELECT LENGTH(id) as len FROM devices GROUP BY len";
                $sth = FreePBX::Database()->prepare($sql);
                $sth->execute();
                $rows = $sth->fetchAll(\PDO::FETCH_ASSOC);
                foreach ($rows as $row) {
                    $ext->add($extintercomusers, '_' . $intercom_code . str_repeat('X', $row['len']), '', new ext_goto($context . ',${EXTEN},1'));
                }
                $context = $extintercomusers;
                // for language handling which is done on a per context basis
                $ext->add($context, 'lang-playback', '', new ext_gosubif('$[${DIALPLAN_EXISTS(' . $context . ',${CHANNEL(language)})}]', $context . ',${CHANNEL(language)},${ARG1}', $context . ',en,${ARG1}'));
                $ext->add($context, 'lang-playback', '', new ext_return());
                $ext->addInclude('from-internal-additional', $context);
            }
            $fcc = new featurecode('paging', 'intercom-on');
            $oncode = $fcc->getCodeActive();
            unset($fcc);
            if ($oncode) {
                $ext->add($context, $oncode, '', new ext_macro('user-callerid'));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(name-charset,i)', 'utf8'));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(name,i)', _("Intercom: Enabled")));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(num,i)', '${AMPUSER}'));
                $ext->add($context, $oncode, '', new ext_answer(''));
                $ext->add($context, $oncode, '', new ext_wait('1'));
                $ext->add($context, $oncode, '', new ext_setvar('DB(AMPUSER/${AMPUSER}/intercom)', 'enabled'));
                $ext->add($context, $oncode, '', new ext_playback('intercom&enabled'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $target = '${EXTEN:' . strlen($oncode) . '}';
                $oncode = "_" . $oncode . ".";
                $ext->add($context, $oncode, '', new ext_macro('user-callerid'));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(name-charset,i)', 'utf8'));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(name,i)', sprintf(_("Intercom from %s: Enabled"), $target)));
                $ext->add($context, $oncode, '', new ext_set('CONNECTEDLINE(num,i)', '${AMPUSER}'));
                $ext->add($context, $oncode, '', new ext_setvar('dialnumber', '${EVAL(${EXTEN:' . strlen(substr($oncode, 1, -1)) . '})}'));
                // Asterisk variable for saydigits languages
                $ext->add($context, $oncode, '', new ext_answer(''));
                $ext->add($context, $oncode, '', new ext_wait('1'));
                $ext->add($context, $oncode, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/' . $target . ')}" = "allow" ]}', 'unset'));
                $ext->add($context, $oncode, '', new ext_gotoif('$[${DB_EXISTS(AMPUSER/' . $target . '/device)} != 1]', 'invaliduser'));
                $ext->add($context, $oncode, '', new ext_dbput('AMPUSER/${AMPUSER}/intercom/' . $target, 'allow'));
                $ext->add($context, $oncode, '', new ext_gosub('1', 'lang-playback', $context, 'hook_1'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $ext->add($context, $oncode, 'unset', new ext_dbdeltree('AMPUSER/${AMPUSER}/intercom/' . $target));
                $ext->add($context, $oncode, '', new ext_gosub('1', 'lang-playback', $context, 'hook_2'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $ext->add($context, $oncode, 'invaliduser', new ext_gosub('1', 'lang-playback', $context, 'hook_3'));
                $ext->add($context, $oncode, '', new ext_macro('hangupcall'));
                $lang = 'en';
                // English
                $ext->add($context, $lang, 'hook_1', new ext_playback('intercom&from&extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('enabled'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_2', new ext_playback('intercom&enabled&cancelled&for&extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_3', new ext_playback('extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('invalid'));
                $ext->add($context, $lang, '', new ext_return());
                $lang = 'ja';
                // Japanese
                $ext->add($context, $lang, 'hook_1', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-kara&jp-no&intercom&jp-wo&allow'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_2', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-kara&jp-no&intercom&setting&jp-wo&cancelled'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_3', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('invalid'));
                $ext->add($context, $lang, '', new ext_return());
            }
            $fcc = new featurecode('paging', 'intercom-off');
            $offcode = $fcc->getCodeActive();
            unset($fcc);
            if ($offcode) {
                $ext->add($context, $offcode, '', new ext_macro('user-callerid'));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(name-charset,i)', 'utf8'));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(name,i)', _("Intercom: Disabled")));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(num,i)', '${AMPUSER}'));
                $ext->add($context, $offcode, '', new ext_answer(''));
                $ext->add($context, $offcode, '', new ext_wait('1'));
                $ext->add($context, $offcode, '', new ext_setvar('DB(AMPUSER/${AMPUSER}/intercom)', 'disabled'));
                $ext->add($context, $offcode, '', new ext_playback('intercom&disabled'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $target = '${EXTEN:' . strlen($offcode) . '}';
                $offcode = "_" . $offcode . ".";
                $ext->add($context, $offcode, '', new ext_macro('user-callerid'));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(name-charset,i)', 'utf8'));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(name,i)', sprintf(_("Intercom from %s: Disabled"), $target)));
                $ext->add($context, $offcode, '', new ext_set('CONNECTEDLINE(num,i)', '${AMPUSER}'));
                $ext->add($context, $offcode, '', new ext_setvar('dialnumber', '${EVAL(${EXTEN:' . strlen(substr($offcode, 1, -1)) . '})}'));
                // Asterisk variable for saydigits languages
                $ext->add($context, $offcode, '', new ext_answer(''));
                $ext->add($context, $offcode, '', new ext_wait('1'));
                $ext->add($context, $offcode, '', new ext_gotoif('$["${DB(AMPUSER/${AMPUSER}/intercom/' . $target . ')}" = "deny" ]}', 'unset2'));
                $ext->add($context, $offcode, '', new ext_gotoif('$[${DB_EXISTS(AMPUSER/' . $target . '/device)} != 1]', 'invaliduser2'));
                $ext->add($context, $offcode, '', new ext_dbput('AMPUSER/${AMPUSER}/intercom/' . $target, 'deny'));
                $ext->add($context, $offcode, '', new ext_gosub('1', 'lang-playback', $context, 'hook_4'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $ext->add($context, $offcode, 'unset2', new ext_dbdeltree('AMPUSER/${AMPUSER}/intercom/' . $target));
                $ext->add($context, $offcode, '', new ext_gosub('1', 'lang-playback', $context, 'hook_5'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $ext->add($context, $offcode, 'invaliduser2', new ext_gosub('1', 'lang-playback', $context, 'hook_6'));
                $ext->add($context, $offcode, '', new ext_macro('hangupcall'));
                $lang = 'en';
                $ext->add($context, $lang, 'hook_4', new ext_playback('intercom&from&extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('disabled'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_5', new ext_playback('intercom&disabled&cancelled&for&extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_6', new ext_playback('extension&number'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('invalid'));
                $ext->add($context, $lang, '', new ext_return());
                $lang = 'ja';
                $ext->add($context, $lang, 'hook_4', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-kara&jp-no&intercom&jp-wo&deny'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_5', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('jp-kara&jp-no&intercom&setting&jp-wo&cancelled'));
                $ext->add($context, $lang, '', new ext_return());
                $ext->add($context, $lang, 'hook_6', new ext_playback('extension'));
                $ext->add($context, $lang, '', new ext_saydigits('${dialnumber}'));
                $ext->add($context, $lang, '', new ext_playback('invalid'));
                $ext->add($context, $lang, '', new ext_return());
            }
            /* Create macro-autoanswer that will try to intelligently set the
            			required parameters to handle paging. Eventually it will use
            				known device information.
            
            				This macro does the following:
            
            				Input:  FreePBX Device number to be called requiring autoanswer
            				Output: ${DIAL} Channel Variable with the dial string to be called
            						Appropriate SIP headers added
            								Other special requirements that may be custom for this device
            
            				1. Set ${DIAL} to the device's dial string
            				2. If there is a device specific macro defined in the DEVICE's object
            				   (DEVICE/<devicenum>/autoanswer/macro) then execute that macro and end
            				3. Try to identify endpoints by their useragents that may need known
            				   changes and make those changes. These are generated from the
            					 paging_autoanswer table so users can extend them, if any are present
            				5. Set the variables and end unless a useragent specific ANSWERMACRO is
            				   defined in which case call it and end.
            
            				This macro is called for intercoming and paging to try and enable the
            				target device to auto-answer. Devices with special needs can be handled
            				with the device specific macro. For example, if you have a device that
            				can not auto-answer except by specifically configuring a line key on
            				the device that always answers, you could use a device specific macro
            				to change the dialstring. If you had a set of such devices, you could
            				standardize on the device numbers (e.g. nnnn for normal calls and 2nnnn
            				for auto-answer calls). You could then create a general purpose macro
            				to modify the dial string accordingly. Provisioning tools will be able
            				to take advantage of setting and creating such an ability.
            				If you have a set of devices that can be identified with a SIP useragent
            				then you can use a general macro without setting info in each device.
            			 */
            $autoanswer_arr = paging_get_autoanswer_useragents();
            $macro = 'macro-autoanswer';
            // Do we already know what the correct string is? This may have been handed to us
            // by page.agi.
            $ext->add($macro, "s", '', new ext_gotoif('$["${KNOWNDIAL}" != ""]', 'knowndial'));
            // Do we have a PJSIP Endpoint?
            $ext->add($macro, "s", '', new ext_setvar('DEVICE', '${DB(DEVICE/${ARG1}/dial)}'));
            $ext->add($macro, "s", '', new ext_gotoif('$["${DEVICE:0:5}" == "PJSIP" ]', 'dopjsip'));
            // We're not pjsip, so our dial is going to be our device
            $ext->add($macro, "s", '', new ext_setvar('KNOWNDIAL', '${DEVICE}'));
            $ext->add($macro, "s", '', new ext_goto('knowndial'));
            // Handle PJSIP stuff.
            $ext->add($macro, "s", 'dopjsip', new ext_setvar('KNOWNDIAL', '${PJSIP_DIAL_CONTACTS(${ARG1})}'));
            // If there's an ampersand, there's more than one device registered to this endpoint, and we
            // need to page, rather than intercom.
            $ext->add($macro, "s", '', new ext_gotoif('$[${REGEX("&" ${KNOWNDIAL})} == 0]', 'knowndial'));
            // Bugger. However, we can hard-code some settings here that'll make our life a bit easier.
            $ext->add($macro, "s", '', new ext_gosub('1', 'ssetup', 'app-paging'));
            $ext->add($macro, "s", '', new ext_setvar('PAGEMODE', 'PAGE'));
            $ext->add($macro, "s", '', new ext_setvar('PAGE_CONF_OPTS', 'duplex'));
            $ext->add($macro, "s", '', new ext_setvar('STREAM', 'NONE'));
            $ext->add($macro, "s", '', new ext_setvar('PAGE_MEMBERS', '${ARG1}'));
            // Start the AGI to get the clients into the conf
            $ext->add($macro, "s", '', new ext_agi('page.agi'));
            // Now I need to join the conf as admin.
            $ext->add($macro, "s", '', new ext_set('CONFBRIDGE(user,template)', 'page_user_duplex'));
            $ext->add($macro, "s", '', new ext_set('CONFBRIDGE(user,admin)', 'yes'));
            $ext->add($macro, "s", '', new ext_set('CONFBRIDGE(user,marked)', 'yes'));
            $ext->add($macro, "s", '', new ext_meetme('${PAGE_CONF}', ',', 'admin_menu'));
            // ext_confbridge, actually.
            $ext->add($macro, "s", '', new ext_hangup());
            // Don't even try to continue after this.
            // Right. Bypassing all that, it's a single device, and, we know what our dial string is.
            $ext->add($macro, "s", 'knowndial', new ext_setvar('DIAL', '${KNOWNDIAL}'));
            // If we are in DAHDI compat mode, then we need to substitute DAHDI for ZAP
            if ($chan_dahdi) {
                $ext->add($macro, "s", '', new ext_execif('$["${DIAL:0:3}" = "ZAP"]', 'Set', 'DIAL=DAHDI${DIAL:3}'));
            }
            $ext->add($macro, "s", '', new ext_gotoif('$["${DB(DEVICE/${ARG1}/autoanswer/macro)}" != "" ]', 'macro'));
            // If there are no phone specific auto-answer vars, then we don't care what the phone is below
            //
            if (!empty($autoanswer_arr)) {
                global $version;
                $ext->add($macro, "s", '', new ext_gotoif('$["${DIAL:0:5}" = "PJSIP"]', 'pjsipua'));
                //http://issues.freepbx.org/browse/FREEPBX-7715
                if (version_compare($version, "12", "<")) {
                    $ext->add($macro, "s", '', new ext_setvar('USERAGENT', '${SIPPEER(${CUT(DIAL,/,2)}:useragent)}'));
                } else {
                    $ext->add($macro, "s", '', new ext_setvar('USERAGENT', '${SIPPEER(${CUT(DIAL,/,2)},useragent)}'));
                }
                $ext->add($macro, "s", '', new ext_goto('uafin'));
                $ext->add($macro, "s", 'pjsipua', new ext_setvar('AOR', '${CUT(DIAL,/,2)}'));
                $ext->add($macro, "s", '', new ext_setvar('CONTACT', '${PJSIP_AOR(${AOR},contact)}'));
                $ext->add($macro, "s", '', new ext_setvar('USERAGENT', '${PJSIP_CONTACT(${CONTACT},user_agent)}'));
                $ext->add($macro, "s", 'uafin', new ext_execif('$["${KNOWNAGENT}" != ""]', 'Set', 'USERAGENT=${KNOWNAGENT}'));
            }
            // We used to set all the variables here (ALERTINFO, CALLINFO, etc. That has been moved to each
            // paging group and the intercom main macro, since it was redundant for every phone causing a lot
            // of overhead with large page groups.
            //
            // Defaults are setup, now make specific adjustments for detected phones
            // These come from the SQL table as well where installations can make customizations
            //
            foreach ($autoanswer_arr as $autosetting) {
                $useragent = trim($autosetting['useragent']);
                $autovar = trim($autosetting['var']);
                $data = trim($autosetting['setting']);
                switch (ltrim($autovar, '_')) {
                    case 'ANSWERMACRO':
                        $has_answermacro = true;
                        // fall through - no break on purpose
                    // fall through - no break on purpose
                    case 'ALERTINFO':
                    case 'CALLINFO':
                    case 'SIPURI':
                    case 'VXML_URL':
                    case 'DOPTIONS':
                    case 'DTIME':
                    default:
                        if (trim($data) != "") {
                            $ext->add($macro, "s", '', new ext_execif('$["${USERAGENT:0:' . strlen($useragent) . '}" = "' . $useragent . '"]', 'Set', $autovar . '=' . $data));
                        }
                        break;
                }
            }
            // Now any adjustments have been made, set the headers and done
            //
            if ($has_answermacro) {
                $ext->add($macro, "s", '', new ext_gotoif('$["${ANSWERMACRO}" != ""]', 'macro2'));
            }
            $ext->add($macro, "s", '', new ext_execif('$["${SIPURI}" != ""]', 'Set', '__SIP_URI_OPTIONS=${SIPURI}'));
            $ext->add($macro, "s", 'macro', new ext_macro('${DB(DEVICE/${ARG1}/autoanswer/macro)}', '${ARG1}'), 'n', 2);
            if ($has_answermacro) {
                $ext->add($macro, "s", 'macro2', new ext_macro('${ANSWERMACRO}', '${ARG1}'), 'n', 2);
            }
            //auto answer stuff
            //set autoanswer variables
            if (!empty($custom_vars)) {
                foreach ($custom_vars as $key => $value) {
                    $ext->add($apppaging, '_AUTOASWER.', '', new ext_setvar('_' . ltrim($key, '_'), $value));
                }
                $ext->add($apppaging, '_AUTOASWER.', '', new ext_macro('autoanswer', '${EXTEN:9}'));
                $ext->add($apppaging, '_AUTOASWER.', '', new ext_return());
            }
            // Macro to apply SIP Headers to channel.
            //   function ext_gosubif($condition, $true_priority, $false_priority = false, $true_args = '', $false_args = '') {
            //
            $ext->add("autoanswer", "s", '', new ext_gosubif('$["${ARG1}" != ""]', 'func-set-sipheader,s,1', false, 'Alert-Info,${ARG1}'));
            $ext->add("autoanswer", "s", '', new ext_gosubif('$["${ARG2}" != ""]', 'func-set-sipheader,s,1', false, 'Call-Info,${ARG2}'));
            $ext->add("autoanswer", "s", '', new ext_gosub('func-apply-sipheaders,s,1'));
            $ext->add("autoanswer", "s", '', new ext_return());
            // Setup Variables before AGI script
            //
            $ext->add($apppaging, 'ssetup', '', new ext_set('_SIPURI', ''));
            if (isset($alertinfo) && trim($alertinfo) != "") {
                $ext->add($apppaging, 'ssetup', '', new ext_set('_ALERTINFO', $alertinfo));
            }
            if (isset($callinfo) && trim($callinfo) != "") {
                $ext->add($apppaging, 'ssetup', '', new ext_set('_CALLINFO', $callinfo));
            }
            if (isset($sipuri) && trim($sipuri) != "") {
                $ext->add($apppaging, 'ssetup', '', new ext_set('_SIPURI', $sipuri));
            }
            if (isset($vxml_url) && trim($vxml_url) != "") {
                $ext->add($apppaging, 'ssetup', '', new ext_set('_VXML_URL', $vxml_url));
            }
            $ext->add($apppaging, 'ssetup', '', new ext_set('_DTIME', $dtime));
            $ext->add($apppaging, 'ssetup', '', new ext_set('_ANSWERMACRO', ''));
            $page_opts = $amp_conf['ASTCONFAPP'] == 'app_confbridge' ? '1qs' : '1dqsx';
            $ext->add($apppaging, 'ssetup', '', new ext_set('PAGE_CONF', '${EPOCH}${RAND(100,999)}'));
            $ext->add($apppaging, 'ssetup', '', new ext_return());
            // Normal page version (now used for Force also)
            // If we had any custom_vars then call the AUTOASWER subroutine first, otherwise go
            // straight to macro-autoanswer
            if (!empty($custom_vars)) {
                $ext->add($apppaging, "_PAGE.", 'SKIPCHECK', new ext_gosub('AUTOASWER${EXTEN:4},1'));
            } else {
                $ext->add($apppaging, "_PAGE.", 'SKIPCHECK', new ext_macro('autoanswer', '${EXTEN:4}'));
            }
            $ext->add($apppaging, "_PAGE.", '', new ext_noop('${EXTRINGTIME}'));
            $ext->add($apppaging, "_PAGE.", '', new ext_gotoif('$["${EXTRINGTIME}" != "true"]', 'doptions'));
            $ext->add($apppaging, "_PAGE.", '', new ext_set('_DTIME', '${RINGTIMER_DEFAULT}'));
            $ext->add($apppaging, "_PAGE.", '', new ext_execif('$["${DB(AMPUSER/${EXTEN:4}/ringtimer)}" != "" & ${DB(AMPUSER/${EXTEN:4}/ringtimer)} > 0]', 'Set', '_DTIME=${DB(AMPUSER/${EXTEN:4}/ringtimer)}'));
            //strip the global Announcement out of doptions (We use our announcement variable lower --V)
            $doptions2 = preg_replace("/A\\([^\\)]*\\)/", "", $doptions);
            $ext->add($apppaging, "_PAGE.", 'doptions', new ext_execif('$["${DOPTIONS}" = ""]', 'Set', '_DOPTIONS=' . $doptions2));
            $ext->add($apppaging, "_PAGE.", '', new ext_dial('${DIAL}', '${DTIME},A(${ANNOUNCEMENT})${DOPTIONS}'));
            $ext->add($apppaging, "_PAGE.", 'skipself', new ext_hangup());
            // Try ChanSpy Version
            $ext->add($apppaging, "_SPAGE.", 'chanspy', new ext_chanspy('${SP_DEVICE}-', 'qW'));
            $ext->add($apppaging, "_SPAGE.", '', new ext_hangup());
            // If Asterisk 10 and app_confbridge:
            //
            // Common to admin:
            //  d: dynamically addd conf
            //  o: talker optimization (don't mix non-talkers)
            //  q: quiet mode no enter/leave sounds
            //  x: close conf when last marked user exits
            //
            // Not in Admin:
            //  1: ???
            //  s: present menu
            //See http://issues.freepbx.org/browse/FREEPBX-8796
            //before you even think about removing this to after checking for a page group!
            if ($amp_conf['ASTCONFAPP'] == 'app_confbridge' && isset($conferences_conf) && is_a($conferences_conf, "conferences_conf")) {
                $pu = 'page_user';
                $pud = 'page_user_duplex';
                foreach (array($pu, $pud) as $u) {
                    $conferences_conf->addConfUser($u, 'quiet', 'yes');
                    $conferences_conf->addConfUser($u, 'announce_user_count', 'no');
                    $conferences_conf->addConfUser($u, 'wait_marked', 'yes');
                    $conferences_conf->addConfUser($u, 'end_marked', 'yes');
                    $dds = \FreePBX::Paging()->getDropSilence() ? 'yes' : 'no';
                    $conferences_conf->addConfUser($u, 'dsp_drop_silence', $dds);
                    $conferences_conf->addConfUser($u, 'announce_join_leave', 'no');
                    $conferences_conf->addConfUser($u, 'admin', 'no');
                    $conferences_conf->addConfUser($u, 'marked', 'no');
                }
                $conferences_conf->addConfUser($pu, 'startmuted', 'yes');
            }
            //page playback
            $c = 'app-page-stream';
            $ext->add($c, 's', '', new ext_wait(1));
            $ext->add($c, 's', '', new ext_answer());
            // TODO: PAGE_CONF_OPTS reset in agi script so just use proper context if 10+confbridge no mute
            // x: close conf when last marked user exits
            // q: quiet mode no enter/leave sounds
            //
            // TODO: Ideally what we want is to mark the stream and wait for that, if no stream then no wait for makred user. However
            //       it seems like to end a conference you have to have the kick after last marked user since there doesn't have to be
            //       an admin as far as I can tell.
            //
            //
            if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                $ext->add($c, 's', '', new ext_set('CONFBRIDGE(user,template)', $pud));
                $ext->add($c, 's', '', new ext_set('CONFBRIDGE(user,marked)', 'yes'));
                $ext->add($c, 's', '', new ext_meetme('${PAGE_CONF}', '', ''));
            } else {
                $ext->add($c, 's', '', new ext_meetme('${PAGE_CONF}', '${PAGE_CONF_OPTS}'));
            }
            $ext->add($c, 's', '', new ext_hangup());
            $apppagegroups = 'app-pagegroups';
            // Now get a list of all the paging groups...
            $sql = "SELECT page_group, force_page, duplex, announcement FROM paging_config";
            $paging_groups = $db->getAll($sql, DB_FETCHMODE_ASSOC);
            if (!$paging_groups) {
                break;
                //no need to continue if we dont have any pagegroups
            }
            $extpaging = 'ext-paging';
            if (!empty($paging_groups)) {
                $ext->addInclude('from-internal-noxfer-additional', $extpaging);
            }
            foreach ($paging_groups as $thisgroup) {
                $grp = trim($thisgroup['page_group']);
                switch ($thisgroup['force_page']) {
                    case 1:
                        $pagemode = 'FPAGE';
                        break;
                    case 2:
                        $pagemode = 'SPAGE';
                        break;
                    case 0:
                    default:
                        $pagemode = 'PAGE';
                        break;
                }
                $sql = "SELECT ext FROM paging_groups WHERE page_number='{$grp}'";
                $all_exts = $db->getCol($sql);
                // Create the paging context that is used in the paging application for each phone to auto-answer
                //add ext-paging with goto's to our app-paging context and a hint for the page
                $ext->add($extpaging, $grp, '', new ext_goto($apppagegroups . ',' . $grp . ',1'));
                $ext->addHint($extpaging, $grp, 'Custom:PAGE' . $grp);
                //app-page dialplan
                $ext->add($apppagegroups, $grp, '', new ext_macro('user-callerid'));
                $ext->add($apppagegroups, $grp, '', new ext_set('_PAGEGROUP', $grp));
                //if page group it in use, goto to busy
                $ext->add($apppagegroups, $grp, 'busy-check', new ext_gotoif('$[${TRYLOCK(apppagegroups' . $grp . ')}]', '', 'busy'));
                //set blf to in use
                $ext->add($apppagegroups, $grp, 'devstate', new ext_setvar('DEVICE_STATE(Custom:PAGE' . $grp . ')', 'INUSE'));
                $ext->add($apppagegroups, $grp, '', new ext_gosub('1', 'ssetup', $apppaging));
                $ext->add($apppagegroups, $grp, '', new ext_set('PAGEMODE', $pagemode));
                $ext->add($apppagegroups, $grp, '', new ext_set('PAGE_MEMBERS', implode('-', $all_exts)));
                if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                    $ext->add($apppagegroups, $grp, '', new ext_set('PAGE_CONF_OPTS', $thisgroup['duplex'] ? 'duplex' : ''));
                } else {
                    $ext->add($apppagegroups, $grp, '', new ext_set('PAGE_CONF_OPTS', $page_opts . (!$thisgroup['duplex'] ? 'm' : '')));
                }
                //Default announcement is a beep
                $announcement = "beep";
                //extract our "global default announcement" from the doptions and set it to announcement
                if (preg_match("/A\\(([^\\)]*)\\)/", $doptions, $matches)) {
                    $announcement = isset($matches[1]) ? $matches[1] : "";
                }
                //get our individual page group announcement if set
                if (!empty($thisgroup['announcement'])) {
                    switch ($thisgroup['announcement']) {
                        case "beep":
                            $announcement = "beep";
                            break;
                        case "none":
                            $announcement = "";
                            break;
                        case "default":
                            //do nothing
                            break;
                        default:
                            if (function_exists('recordings_get_file')) {
                                $announcement = recordings_get_file($thisgroup['announcement']);
                            } else {
                                $announcement = "";
                            }
                            break;
                    }
                }
                $ext->add($apppagegroups, $grp, '', new ext_set('ANNOUNCEMENT', $announcement));
                $ext->add($apppagegroups, $grp, 'agi', new ext_agi('page.agi'));
                //we cant use originate from the dialplan as the dialplan command is not asynchronous
                //we would like to though...
                //this code here as a sign of hope -MB
                /*foreach ($page_members as $member) {
                				$ext->add($apppagegroups, $grp, 'page', new ext_originate($member,'app','meetme', '${PAGE_CONF}\,${PAGE_CONF_OPTS}'));
                		}*/
                // TODO this is the master so set appropriate
                //      This is what everyone else has: 1doqsx
                //      Common:
                //        d: dynamically addd conf
                //        o: talker optimization (don't mix non-talkers)
                //        q: quiet mode no enter/leave sounds
                //        x: close conf when last marked user exits
                //      Added:
                //      	w: W() wait until marked user enters conf
                //      	A: Set marked mode
                //      	G: G() Play an intro announcemend in conference
                //      Removed:
                //        1: ???
                //        s: present menu
                //
                //
                if ($amp_conf['ASTCONFAPP'] == 'app_confbridge') {
                    $ext->add($apppagegroups, $grp, '', new ext_set('CONFBRIDGE(user,template)', $pud));
                    $ext->add($apppagegroups, $grp, '', new ext_set('CONFBRIDGE(user,admin)', 'yes'));
                    $ext->add($apppagegroups, $grp, '', new ext_set('CONFBRIDGE(user,marked)', 'yes'));
                    // TODO: should I have no menu?
                    $ext->add($apppagegroups, $grp, '', new ext_answer(''));
                    $ext->add($apppagegroups, $grp, 'page', new ext_meetme('${PAGE_CONF}', ',', 'admin_menu'));
                } else {
                    $ext->add($apppagegroups, $grp, '', new ext_answer(''));
                    $ext->add($apppagegroups, $grp, 'page', new ext_meetme('${PAGE_CONF}', 'dqwxAG'));
                }
                $ext->add($apppagegroups, $grp, '', new ext_hangup());
                $ext->add($apppagegroups, $grp, 'busy', new ext_set('PAGE${PAGEGROUP}BUSY', 'TRUE'));
                $ext->add($apppagegroups, $grp, 'play-busy', new ext_busy(3));
                $ext->add($apppagegroups, $grp, 'busy-hang', new ext_goto('app-pagegroups,h,1'));
            }
            //h
            $ext->add($apppagegroups, 'h', '', new ext_execif('$[${ISNULL(${PAGE${PAGEGROUP}BUSY})}]', 'Set', 'DEVICE_STATE(Custom:PAGE${PAGEGROUP})=NOT_INUSE'));
            break;
    }
}