Open Source Training Seminar FreePBX Paid Support

Issue:

  • Both dialplan extension numbers and module destinations are completely decentralized. For extensions this creates issues that the same extension can be created in two different modules with un-deterministic results. For destinations, it results in a module being able to delete an entity with no reasonable way for it to determine if some other module is using it as a destination. The latter issue results in broken dialplans that drop calls, for example, an IVR option that goes to a ringgroup which just got deleted.

Proposal:

  • There needs to be some sort of extension registry as well as a destination registry so that the creation process for an extension can check if that extension is being used elsewhere before creating it. Similarly, a destination registry would allow the module delete routines to check if the given element is being used prior to deleting it and not allowing it to be deleted, or edited where editing can change the number used. In all cases, it requires cooperative behavior of modules to function properly. It is not clear if this could easily be enforced centrally. However, it is probably possible to do integrity checks in retrieve_conf.

Implementation:

  • We originally considered doing these registries as central tables that would be managed. Modules would submit and check information against them. This can end up in database integrity issues being out of sync. Greg suggested using callbacks to manage this information. That may be an excellent way and relatively easy to retrofit into the system.

Callback Proposal:

  • Step one is to suggest a callback that can be used to obtain either a global view of extension or destination usage, or to check against specific extension or destinations. Here is some psuedo code for this idea:

modulename_check_extensions():

/** Get extension specific or all extension information
 * @param mixed    The extension to check against or boolean true if all extensions should be listed
 * @return array   if exten passed, return array with exten info or empty array if not being used. If exten
 *                 passed true return array of all extens
 *
 * The idea behind this is that a module that is going to create a new "extension" or rename an existing one
 * will call an api that engages these callbacks to determine if that is being used in another module first. Or
 * the callback can be used to in an api to list all extensions used in the system (which could handle integrity
 * checking elsewhere such as retrieve_conf
 */
function <module_name>_check_extensions($exten=true) {
  if ($exten === true) {
    return list_extensions();
  } else {
    return list_extensions($exten);
  }
}

Return information:

extension passed and not being used returns boolean false
extension passed and being used, or listing all extensions:

array with specific extension or each extension being used:

  $exten_arr[$exten]['description'] = 'Description of extension';
                    ['edit_url']    = 'URL that could be engaged to directly edit this extension'
                    ['status']      = 'Status code: INUSE, RESERVED, RESTRICTED'

modulename_check_destinations():

/** Get destination specific or all destination information
 * @param mixed    The destination to check against or boolean true if all destination should be listed
 * @return array   If destination(s) are passed and not being used, return empty array, else return array
 *
 * The idea behind this is a module that is going to delete it's object listed as use for destinations
 * first passes the destination or destinations that are published for that object to an api which will use these
 * callback routines to see if any module is currently using that object's destination. The callbacks could also
 * be used elsewhere to create a view of all places in the dialplan that are using the various destinations.
 */
function <module_name>_check_destinations($dest=true) {
  if ($dest=== true) {
    return list_destinations();
  } else {
    return list_destinations($dest);
  }
}

Return information:

destination passed and not being used returns boolean false
destination(s) passed and being used, or listing all destinations:

array with specific destinations or each destination being used:

  $dest_arr[]['dest']        = 'requested dest or all dests if true'
             ['description'] = 'Description of the entity that is using this destination';
             ['edit_url']    = 'URL that could be engaged to directly edit the entity using this'

For example, an IVR my return "IVR Support is using this as a destination for option 3" followed by a 
URL to edit that IVR.

Callback Usage:

  • With these callbacks, some central APIs can then be developed inside framework that are required to be called by any routine to check if extensions exist before creating new ones or to check if they are being used as a destination before allowing them to be deleted. Other APIs can also be created in framework or other modules that use these callbacks to create lists of all extensions and where they are being used, to create do integrity checking, etc.

Questions/Issues/Discussions:

  • What do you do with Feature Codes?
    • some are wild cards which today can end up in strange behavior
    • some are fixed plus wild card versions
    • SUGGESTION:
      • Due to the uniqueness and complications with featurecodes, I suggest they be handled differently as described.
        • Entering a feature code that conflicts with another featurecode will be handled as it is today.
        • Entering a featurecode that conflicts with another module will be allowed, but will result in a table at the top of featurecodes warning about conflicts. This will make it evident and is easy to correct and the table will have links to the conflicting modules. Conflicts with other featurecodes will not be listed int that table.
        • The feature code module itself should be modified to highlight it's own conflicts if they are entered. The javascript validation does the initial warning but it should remain highlighted if left. It should ignore highlighting on disabled featurecodes.
        • The featurcode module should publish all its codes and other modules will block assigning numbers that conflict as is always the case.
  • What are implications of a module being disabled?
    • it will no longer participate in the callback, or do you address that?
    • it's destinations will go away - do you not allow it to be disabled if it has destinations in use?
  • What are implications of a module being removed?
    • do you require uninstall scripts to check for usage first and abort?
    • is module_admin able to handle 'failed' uninstalls and not uninstall the module?
  • The call back routine should know which module is making the request. I believe this can be obtained form the global framework variable.
    • the purpose of this is to allow modules that may respond with an 'in-use' type message as a from of proxy.
      • on behalf of reservations
      • to enforce restrictions (e.g. ringgroups must be in the range of nnn-mmm so return an in-use if a ringgroup tries to make a reservation out of that range)
      • on behalf of remote branches to facilitate a potential poor-man's branch office setup
  • Should this be a callback per display vs module?
    • A module know's all its displays so a module is probably better

Reservation/Restriction Module:

  • Such a module could be used for the following purposes
    • create reservation ranges that can only be used by a specific module (or set of modules). It would return in-use to any other module requesting that range'
    • create a restriction range for a specific module or set of modules. So that a module trying to create an extension out of that range would be sent an in-use return (really a you aren't allowed to use that number return but the concept is the same, it is blocked from using it.)

Example of working prototype conferences_check_extensions:

function conferences_check_extensions($exten=true) {
  $extenlist = array();
  $sql = "SELECT exten,description FROM meetme ";
  if ($exten !== true) {
    $sql .= "WHERE exten = $exten ";
  }
  $sql .= " ORDER BY exten";
  $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);

  foreach ($results as $result) {
    $extenlist[$result['exten']]['description'] = $result['description'];
    $extenlist[$result['exten']]['status'] = 'INUSE';
    $extenlist[$result['exten']]['edit_url'] = 'config.php?display=conferences&extdisplay='.urlencode($result['exten']);
  }
  return $extenlist;
}

Example of working prototype framework_check_extension_usage()

/** check if a specific extension is being used, or get a list of all extensions that are being used
 * @param mixed     the extension number to check against, or if boolean true then return list of all extensions
 * @return array    returns an empty array if exten not in use, or any array with usage info, or of all usage 
 *                  if exten is boolean true
 * @description     Upon passing in an extension number, this api will query all modules to determine if any
 *                  are using that extension number. If so, it will return an array with the usage information
 *                  as described below, otherwise an empty array. If passed boolean true, it will return an array
 *                  of the same format with all extensions on the system that are being used.
 *
 *                  $exten_usage[$module][$exten]['description'] // description of the extension
 *                                               ['edit_url']    // a url that could be invoked to edit extension
 *                                               ['status']      // Status: INUSE, RESERVED, RESTRICTED
 */
function framework_check_extension_usage($exten=true) {
  global $active_modules;

  $exten_usage = array();
  foreach($active_modules as $key => $module) {
    $function = $key."_check_extensions";
    if (function_exists($function)) {
      $module_usage = $function($exten);
      if (count($module_usage)) {
        $exten_usage[$key] = $module_usage;
      }
    }
  }
  return $exten_usage;
}

Example of working prototype framework_extension_usage_alert()

  • Displays a crude table of status if there is a conflict
  • It will make sense to come up with a standardized call that modules can use to display conflicts
function framework_display_extension_usage_alert($usage_arr=array()) {
  global $active_modules;
  if (count($usage_arr)) {
    $str = "<h4>Extension Not Available</h4><table>";
    foreach($usage_arr as $rawmodule => $properties) {
      $str .=  "<tr><td>Module:</td><td colspan='2'>".$active_modules[$rawmodule]['name']."</td></tr>";
      foreach($properties as $exten => $details) {                                                                                                                            
        $str .=  "<tr><td></td><td>Description:</td><td>".htmlspecialchars($details['description'])."</td></tr>";                                                             
        $str .=  "<tr><td></td><td>Edit URL:</td><td>".htmlspecialchars($details['edit_url'])."</td></tr>";                                                                   
        $str .=  "<tr><td></td><td>Edit URL:</td><td><a href='".$details['edit_url']."'>Edit this extension</a></td></tr>";
        $str .=  "<tr><td></td><td>Status:</td><td>".htmlspecialchars($details['status'])."</td></tr>";                                                                        
      }                                                                                                                                                                        
    }                                                                                                                                                                          
  }                                                                                                                                                                            
  echo "$str"."</table>";                                                                                                                                                      
}                                                                                                                                                                              
Donate



Support
Download
Develop
Forums
News
Documentation
Paid Support
About

Paid Ads