| 1 |
<?php |
<?php |
| 2 |
// $Id: asterisk.module,v 1.98 2007/11/09 23:08:21 thehunmonkgroup Exp $ |
// $Id: asterisk.module,v 1.99 2007/11/09 23:39:34 thehunmonkgroup Exp $ |
| 3 |
|
|
| 4 |
/** |
/** |
| 5 |
* @file |
* @file |
| 18 |
function asterisk_block($op = 'list', $delta = 0, $edit = array()) { |
function asterisk_block($op = 'list', $delta = 0, $edit = array()) { |
| 19 |
if ($op == 'list') { |
if ($op == 'list') { |
| 20 |
$blocks[0]['info'] = t('Displays a listing of recent audio files. Users can click to hear the file via phone'); |
$blocks[0]['info'] = t('Displays a listing of recent audio files. Users can click to hear the file via phone'); |
| 21 |
|
$blocks[0]['cache'] = BLOCK_CACHE_PER_USER; |
| 22 |
$blocks[1]['info'] = t('Display a simple text entry to originate calls'); |
$blocks[1]['info'] = t('Display a simple text entry to originate calls'); |
| 23 |
|
$blocks[1]['cache'] = BLOCK_CACHE_PER_USER; |
| 24 |
return $blocks; |
return $blocks; |
| 25 |
} |
} |
| 26 |
else if ($op == 'configure') { |
else if ($op == 'configure') { |
| 92 |
/** |
/** |
| 93 |
* Implementation of hook_help(). |
* Implementation of hook_help(). |
| 94 |
*/ |
*/ |
| 95 |
function asterisk_help($section) { |
function asterisk_help($path, $arg) { |
| 96 |
switch ($section) { |
switch ($path) { |
| 97 |
case 'admin/help#asterisk': |
case 'admin/help#asterisk': |
| 98 |
global $user; |
global $user; |
|
$url = parse_url($GLOBALS['base_url']); |
|
| 99 |
|
|
| 100 |
return t("<p>The Asterisk integration project seeks to add a rich telephony feature set to Drupal. This module maintains a call queue in your local drupal database.</p> |
return t("<p>The Asterisk integration project seeks to add a rich telephony feature set to Drupal. This module maintains a call queue in your local drupal database.</p> |
| 101 |
|
|
| 317 |
/** |
/** |
| 318 |
* Implementation of hook_user() |
* Implementation of hook_user() |
| 319 |
*/ |
*/ |
| 320 |
function asterisk_user($op, &$edit, &$user) { |
function asterisk_user($op, &$edit, &$account) { |
| 321 |
|
|
| 322 |
switch($op) { |
switch($op) { |
| 323 |
case 'load': |
case 'load': |
| 324 |
asterisk_user_load($user); |
asterisk_user_load($account); |
| 325 |
break; |
break; |
| 326 |
case 'insert': |
case 'insert': |
| 327 |
asterisk_user_insert($edit, $user); |
asterisk_user_insert($edit, $account); |
| 328 |
break; |
break; |
| 329 |
case 'update': |
case 'update': |
| 330 |
asterisk_user_update($edit, $user); |
asterisk_user_update($edit, $account); |
| 331 |
break; |
break; |
| 332 |
case 'delete': |
case 'delete': |
| 333 |
asterisk_user_delete($edit, $user); |
asterisk_user_delete($edit, $account); |
| 334 |
break; |
break; |
| 335 |
case 'form': |
case 'form': |
| 336 |
return asterisk_user_form($edit, $user); |
return asterisk_user_form($edit, $account); |
| 337 |
case 'view': |
case 'view': |
| 338 |
|
|
| 339 |
/* |
/* |
| 340 |
* Adds a telephone number to the users profile. |
* Adds a telephone number to the users profile. |
| 341 |
* Users with telephone numbers can click to call other users |
* Users with telephone numbers can click to call other users |
| 342 |
*/ |
*/ |
| 343 |
if (user_access('make calls') && $user->number != '') { |
if (user_access('make calls') && $account->number != '') { |
| 344 |
if (_asterisk_is_same_user($user)) { |
if (_asterisk_is_same_user($account)) { |
| 345 |
$output = l(t('Call me'), 'asterisk/callme', array('query' => drupal_get_destination())); |
$output = l(t('Call me'), 'asterisk/callme', array('query' => drupal_get_destination())); |
| 346 |
} |
} |
| 347 |
else { |
else { |
| 348 |
$output = l(t('Call user'), "asterisk/calluser/$user->uid", array('query' => drupal_get_destination())); |
$output = l(t('Call user'), "asterisk/calluser/$account->uid", array('query' => drupal_get_destination())); |
| 349 |
} |
} |
| 350 |
return array(t('Telephone') => array( array('value' => $output, 'class' => 'user'))); |
|
| 351 |
|
if (!isset($account->content['summary'])) { |
| 352 |
|
$account->content['telephone'] = array(); |
| 353 |
|
} |
| 354 |
|
$account->content['telephone'] += array( |
| 355 |
|
'#type' => 'user_profile_category', |
| 356 |
|
'#attributes' => array('class' => 'user-member'), |
| 357 |
|
'#weight' => 10, |
| 358 |
|
'#title' => t('Telephone'), |
| 359 |
|
); |
| 360 |
|
$account->content['telephone']['call_link'] = array( |
| 361 |
|
'#type' => 'user_profile_item', |
| 362 |
|
'#title' => t('Place calls'), |
| 363 |
|
'#value' => $output, |
| 364 |
|
); |
| 365 |
} |
} |
| 366 |
break; |
break; |
| 367 |
} |
} |
| 378 |
array('boolean', 'array'), |
array('boolean', 'array'), |
| 379 |
t('receives a list of new messages from the Asterisk server') |
t('receives a list of new messages from the Asterisk server') |
| 380 |
), |
), |
|
|
|
|
// expose some functionality for directleap integration |
|
|
/* array( |
|
|
'asterisk.civiCRMGetGroups', |
|
|
'asterisk_get_civicrm_groups', |
|
|
array('struct', 'string'), |
|
|
t('returns a list of CiviCRM groups') |
|
|
), |
|
|
array( |
|
|
'asterisk.civiCRMGroupGetNumbers', |
|
|
'asterisk_civicrm_group_get_numbers', |
|
|
array('struct', 'string', 'integer'), |
|
|
t('returns an array of phone numbers from a CiviCRM group') |
|
|
), |
|
|
array( |
|
|
'asterisk.civiCRMGetGroups', |
|
|
'asterisk_get_civicrm_groups', |
|
|
array('struct', 'string'), |
|
|
t('returns a list of CiviCRM groups') |
|
|
), |
|
|
array( |
|
|
'asterisk.civiCRMGroupGetNumbers', |
|
|
'asterisk_civicrm_group_get_numbers', |
|
|
array('struct', 'string', 'integer'), |
|
|
t('returns an array of phone numbers from a CiviCRM group') |
|
|
)*/ |
|
| 381 |
); |
); |
| 382 |
} |
} |
| 383 |
|
|
| 613 |
* Boolean which determines if the file will be listed in the node as soon as it's created. Default is FALSE. |
* Boolean which determines if the file will be listed in the node as soon as it's created. Default is FALSE. |
| 614 |
*/ |
*/ |
| 615 |
function asterisk_record_message($filename, $callee_number, $nid = 0, $module = '', $uid = 0, $dispatch_time = NULL, $list = 0) { |
function asterisk_record_message($filename, $callee_number, $nid = 0, $module = '', $uid = 0, $dispatch_time = NULL, $list = 0) { |
| 616 |
|
|
| 617 |
|
// Get a file ID. |
| 618 |
|
$fid = asterisk_get_file_id($uid); |
| 619 |
|
|
| 620 |
$call = array(); |
$call = array(); |
| 621 |
$calls = array(); |
$calls = array(); |
| 622 |
$call['caller_number'] = $callee_number; |
$call['caller_number'] = $callee_number; |
| 624 |
$call['module'] = $module; |
$call['module'] = $module; |
| 625 |
$call['uid'] = $uid; |
$call['uid'] = $uid; |
| 626 |
$call['dispatch_time'] = $dispatch_time; |
$call['dispatch_time'] = $dispatch_time; |
| 627 |
$call['vars'] = array('drupal_fid' => db_next_id('fid'), 'drupal_nid' => $nid, 'drupal_filename' => $filename, 'drupal_list_file' => $list); |
$call['vars'] = array('drupal_fid' => $fid, 'drupal_nid' => $nid, 'drupal_filename' => $filename, 'drupal_list_file' => $list); |
| 628 |
|
|
| 629 |
$calls[1] = asterisk_call($call); |
$calls[1] = asterisk_call($call); |
| 630 |
asterisk_send_calls($calls); |
asterisk_send_calls($calls); |
| 634 |
} |
} |
| 635 |
|
|
| 636 |
/** |
/** |
| 637 |
|
* Gets a file ID for a file recording. |
| 638 |
|
* |
| 639 |
|
* @param $uid |
| 640 |
|
* The user submitting the record request. |
| 641 |
|
* @return |
| 642 |
|
* The file ID. |
| 643 |
|
*/ |
| 644 |
|
function asterisk_get_file_id($uid) { |
| 645 |
|
// Enter a temporary file into the files table -- placeholder. |
| 646 |
|
$query = "INSERT INTO {files} |
| 647 |
|
(uid, filename, filepath, filemime, filesize, status, timestamp) |
| 648 |
|
VALUES |
| 649 |
|
(%d, '%s', '%s', '%s', %d, %d, %d)"; |
| 650 |
|
|
| 651 |
|
$args = array( |
| 652 |
|
$uid, |
| 653 |
|
'', |
| 654 |
|
'', |
| 655 |
|
'', |
| 656 |
|
0, |
| 657 |
|
FILE_STATUS_TEMPORARY, |
| 658 |
|
time(), |
| 659 |
|
); |
| 660 |
|
|
| 661 |
|
db_query($query, $args); |
| 662 |
|
$fid = db_last_insert_id('files', 'fid'); |
| 663 |
|
|
| 664 |
|
return $fid; |
| 665 |
|
} |
| 666 |
|
|
| 667 |
|
/** |
| 668 |
* Use the generic call function to call given a user (the callee). The caller is made |
* Use the generic call function to call given a user (the callee). The caller is made |
| 669 |
* the callee so that the user can hear anything that the IVR might play |
* the callee so that the user can hear anything that the IVR might play |
| 670 |
* @param $callee |
* @param $callee |
| 759 |
|
|
| 760 |
// This call is a bridged call with optional recording |
// This call is a bridged call with optional recording |
| 761 |
if ($callee_number = format_number($form_state['values']['callee_number'])) { |
if ($callee_number = format_number($form_state['values']['callee_number'])) { |
| 762 |
|
// Get a file ID. |
| 763 |
|
$fid = asterisk_get_file_id($uid); |
| 764 |
$call['vars'] = array( |
$call['vars'] = array( |
| 765 |
'drupal_fid' => db_next_id('fid'), |
'drupal_fid' => $fid, |
| 766 |
'drupal_nid' => $form_state['values']['asterisk_record_nid'], |
'drupal_nid' => $form_state['values']['asterisk_record_nid'], |
| 767 |
'drupal_filename' => $form_state['values']['asterisk_record_file'], |
'drupal_filename' => $form_state['values']['asterisk_record_file'], |
| 768 |
'drupal_list_file' => $form_state['values']['asterisk_record_list_file'], |
'drupal_list_file' => $form_state['values']['asterisk_record_list_file'], |
| 806 |
|
|
| 807 |
$node = node_load($file['nid']); |
$node = node_load($file['nid']); |
| 808 |
$file['vid'] = $node->vid ? $node->vid : 0; |
$file['vid'] = $node->vid ? $node->vid : 0; |
|
$file['fid'] = $file['fid'] ? $file['fid']: db_next_id('files_fid'); |
|
| 809 |
$data = $file['bits']; |
$data = $file['bits']; |
| 810 |
|
|
| 811 |
$name = $file['filename'] ? $file['filename'] : t('unknown'); |
$name = $file['filename'] ? $file['filename'] : t('unknown'); |
| 822 |
return; |
return; |
| 823 |
} |
} |
| 824 |
|
|
| 825 |
$query = "INSERT INTO {files} |
$query = "UPDATE {files} SET filename = '%s', filepath = '%s', filemime = '%s', filesize = %d, status = %d, timestamp = %d WHERE fid = %d"; |
|
(fid, nid, filename, filepath, filemime, filesize) |
|
|
VALUES |
|
|
(%d, %d, '%s', '%s', '%s', %d)"; |
|
| 826 |
|
|
| 827 |
$args = array($file['fid'], |
$args = array( |
| 828 |
$file['nid'], |
$name, |
| 829 |
$name, |
$filepath, |
| 830 |
$filepath, |
$file['filemime'], |
| 831 |
$file['filemime'], |
$file['filesize'], |
| 832 |
$file['filesize'], |
FILE_STATUS_PERMANENT, |
| 833 |
); |
time(), |
| 834 |
|
$file['fid'], |
| 835 |
|
); |
| 836 |
|
|
| 837 |
db_query($query, $args); |
db_query($query, $args); |
| 838 |
|
|
| 839 |
$query = "INSERT INTO {file_revisions} |
$query = "INSERT INTO {upload} |
| 840 |
(fid, vid, description, list) |
(fid, nid, vid, description, list) |
| 841 |
VALUES |
VALUES |
| 842 |
(%d, %d, '%s', %d)"; |
(%d, %d, %d, '%s', %d)"; |
| 843 |
|
|
| 844 |
$args = array($file['fid'], |
$args = array($file['fid'], |
| 845 |
|
$file['nid'], |
| 846 |
$file['vid'], |
$file['vid'], |
| 847 |
$name, |
$name, |
| 848 |
(integer) $file['list'] |
(integer) $file['list'] |
| 861 |
function asterisk_get_file_info($fid) { |
function asterisk_get_file_info($fid) { |
| 862 |
global $base_url; |
global $base_url; |
| 863 |
|
|
| 864 |
$query = 'SELECT f.*, n.changed, n.title FROM {files} f INNER JOIN {node} n ON n.nid = f.nid WHERE fid = %d'; |
$nid = db_result(db_query('SELECT n.nid FROM {upload} u INNER JOIN {node} n ON n.nid = u.nid WHERE n.status = 1 AND n.vid = u.vid AND fid = %d', $fid)); |
| 865 |
$result = db_query($query, $fid); |
$node = node_load($nid); |
| 866 |
|
|
| 867 |
if (db_num_rows($result)) { |
// Make sure the file is still active on the node. |
| 868 |
$file = db_fetch_array($result); |
if ($node) { |
| 869 |
|
$file = (array) $node->files[$fid]; |
| 870 |
|
|
| 871 |
// more unique name for the file on the asterisk server |
// more unique name for the file on the asterisk server |
| 872 |
$file['server_file_name'] = $file['fid'] .'_'. $file['nid'] .'_'. $file['filename']; |
$file['server_file_name'] = $file['fid'] .'_'. $file['nid'] .'_'. $file['filename']; |
| 890 |
} |
} |
| 891 |
|
|
| 892 |
/** |
/** |
|
* get the oldest(according to the callid, not the timestamp) call placed into the queue |
|
|
*/ |
|
|
function asterisk_getnextinqueue() { |
|
|
|
|
|
$max_count = variable_get('asterisk_queuelength', 10); |
|
|
if ($calls = _asterisk_getnextinqueue_helper($max_count)) { |
|
|
return $calls; |
|
|
} |
|
|
else { |
|
|
return array(); |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
/** |
|
|
* helper function for fetching calls from queue |
|
|
*/ |
|
|
function _asterisk_getnextinqueue_helper($max_count) { |
|
|
|
|
|
$uniqueid = microtime() . mt_rand(1000, 9999); |
|
|
|
|
|
$query = "SELECT call_id FROM {asterisk_call_queue} WHERE call_status = 'uncalled' AND dispatch_time < %d ORDER BY call_id ASC LIMIT %d"; |
|
|
|
|
|
if ($result = db_query($query, time(), $max_count)) { |
|
|
while ($call = db_fetch_object($result)) { |
|
|
$call_ids[] = $call->call_id; |
|
|
} |
|
|
if (is_array($call_ids)) { |
|
|
|
|
|
// attempt to "lock" these rows so that its not sent off the queue more than once |
|
|
$query = ("UPDATE {asterisk_call_queue} SET call_status = '%s' WHERE call_id IN (%s)"); |
|
|
$call_ids = implode(', ', $call_ids); |
|
|
$result = db_query($query, $uniqueid, $call_ids); |
|
|
$number_locked = db_affected_rows(); |
|
|
|
|
|
if ($number_locked > 0) { |
|
|
|
|
|
// get the 'locked' rows |
|
|
$result = db_query("SELECT * FROM {asterisk_call_queue} WHERE call_status = '%s'", $uniqueid); |
|
|
|
|
|
while ($call = db_fetch_array($result)) { |
|
|
$call['vars'] = unserialize($call['vars']); |
|
|
$calls[] = $call; |
|
|
} |
|
|
$call_ids = implode(', ', array_keys($calls)); |
|
|
|
|
|
// update the status of the locked rows |
|
|
$query = "UPDATE {asterisk_call_queue} SET call_status = 'dispatched' WHERE call_status = '%s'"; |
|
|
if (db_query($query, $uniqueid)) { |
|
|
$number_updated = db_affected_rows(); |
|
|
if ($number_updated < $number_locked) { |
|
|
watchdog('asterisk', "Lost track of one or more calls: '%call_ids'", array('$call_ids' => $call_ids), WATCHDOG_WARNING); |
|
|
} |
|
|
return $calls; |
|
|
} |
|
|
else { |
|
|
watchdog('asterisk', "unable to send calls: '%call_ids' off the queue", array('$call_ids' => $call_ids), WATCHDOG_WARNING); |
|
|
return FALSE; |
|
|
} |
|
|
} |
|
|
else { |
|
|
// unable to lock any rows from the queue |
|
|
watchdog('asterisk', 'Unable to lock any rows', array(), WATCHDOG_WARNING); |
|
|
return FALSE; |
|
|
} |
|
|
} |
|
|
else { |
|
|
return FALSE; |
|
|
} |
|
|
} |
|
|
else { |
|
|
return FALSE; |
|
|
} |
|
|
} |
|
|
|
|
|
/** |
|
| 893 |
* Load the user's information |
* Load the user's information |
| 894 |
*/ |
*/ |
| 895 |
function asterisk_user_load(&$user) { |
function asterisk_user_load(&$user) { |
| 906 |
*/ |
*/ |
| 907 |
function asterisk_user_insert(&$edit, &$user) { |
function asterisk_user_insert(&$edit, &$user) { |
| 908 |
// save the main details to the database |
// save the main details to the database |
| 909 |
$query = "INSERT INTO {asterisk_users} (pin, number, uid, direct_leap_account_number) VALUES ('%s', '%s', %d, '%s')"; |
$query = "INSERT INTO {asterisk_users} (pin, number, uid) VALUES ('%s', '%s', %d)"; |
| 910 |
db_query($query, $edit['asterisk_pin'], $edit['asterisk_number'], $user->uid, $edit['direct_leap_account_number']); |
db_query($query, $edit['asterisk_pin'], $edit['asterisk_number'], $user->uid); |
| 911 |
|
|
| 912 |
|
|
| 913 |
/* Disabled for now... |
/* Disabled for now... |
| 916 |
$vars = array('op' => 'create-user', 'user' => $user); |
$vars = array('op' => 'create-user', 'user' => $user); |
| 917 |
asterisk_call('system', 'system', 'asterisk', $user->uid, FALSE, $vars); |
asterisk_call('system', 'system', 'asterisk', $user->uid, FALSE, $vars); |
| 918 |
|
|
|
$edit['direct_leap_account_number'] = NULL; |
|
| 919 |
*/ |
*/ |
| 920 |
|
|
| 921 |
$edit['asterisk_number'] = NULL; |
$edit['asterisk_number'] = NULL; |
| 929 |
function asterisk_user_update(&$edit, &$user) { |
function asterisk_user_update(&$edit, &$user) { |
| 930 |
|
|
| 931 |
// update the PIN and telephone number information |
// update the PIN and telephone number information |
| 932 |
$query = "UPDATE {asterisk_users} SET pin = '%s', number = '%s', direct_leap_account_number = '%s' WHERE uid = %d"; |
$query = "UPDATE {asterisk_users} SET pin = '%s', number = '%s' WHERE uid = %d"; |
| 933 |
db_query($query, $edit['asterisk_pin'], $edit['asterisk_number'], $edit['direct_leap_account_number'], $user->uid); |
db_query($query, $edit['asterisk_pin'], $edit['asterisk_number'], $user->uid); |
| 934 |
if (db_affected_rows() == 0) { |
if (db_affected_rows() == 0) { |
| 935 |
$row = db_fetch_object(db_query("SELECT COUNT(*) FROM {asterisk_users} WHERE uid = %d", $user->uid)); |
$query = "INSERT INTO {asterisk_users} (pin, number, uid) VALUES ('%s', '%s', %d)"; |
| 936 |
if ($row->count == 0) { |
db_query($query, $edit['asterisk_pin'], $edit['asterisk_number'], $user->uid); |
|
$query = "INSERT INTO {asterisk_users} (pin, number, uid, direct_leap_account_number) VALUES ('%s', '%s', %d, '%s')"; |
|
|
db_query($query, $edit['asterisk_pin'], $edit['asterisk_number'], $user->uid, $edit['direct_leap_account_number']); |
|
|
} |
|
| 937 |
} |
} |
| 938 |
|
|
| 939 |
/* Disabled for now... |
/* Disabled for now... |
| 1022 |
} |
} |
| 1023 |
|
|
| 1024 |
function asterisk_audio_file_block() { |
function asterisk_audio_file_block() { |
| 1025 |
$query = "SELECT DISTINCT f.fid, filename FROM {files} f INNER JOIN {node} n ON n.nid = f.nid INNER JOIN {file_revisions} r ON f.fid = r.fid WHERE (filemime LIKE '%audio%wav%' OR filemime LIKE '%audio%mpeg%') AND list = 1 ORDER BY changed DESC, fid DESC"; |
$query = "SELECT DISTINCT f.fid, f.filename FROM {files} f INNER JOIN {upload} u ON f.fid = u.fid INNER JOIN {node} n ON n.nid = u.nid WHERE n.status = 1 AND n.vid = u.vid AND (f.filemime LIKE '%audio%wav%' OR f.filemime LIKE '%audio%mpeg%') AND u.list = 1 ORDER BY f.fid DESC"; |
| 1026 |
$result = db_query_range($query, 0, variable_get('asterisk_audio_block_items', 5)); |
$result = db_query_range($query, 0, variable_get('asterisk_audio_block_items', 5)); |
|
if (db_num_rows($result) < 1) { |
|
|
return; |
|
|
} |
|
| 1027 |
|
|
| 1028 |
|
$links = array(); |
| 1029 |
while ($file = db_fetch_object($result)) { |
while ($file = db_fetch_object($result)) { |
| 1030 |
$links[] = l(check_plain($file->filename), 'asterisk/play/'.$file->fid.'?'.drupal_get_destination(), |
$links[] = l($file->filename, 'asterisk/play/'. $file->fid, |
| 1031 |
array('title' => t('listen to this file by phone'))); |
array('title' => t('listen to this file by phone'), 'query' => drupal_get_destination())); |
| 1032 |
|
} |
| 1033 |
|
|
| 1034 |
|
$output = ''; |
| 1035 |
|
if (!empty($links)) { |
| 1036 |
|
$output .= '<strong>'. t('Click to listen by phone:') .'</strong>'; |
| 1037 |
|
$output .= theme('item_list', $links); |
| 1038 |
} |
} |
| 1039 |
$output = '<strong>'. t('Click to listen by phone:') .'</strong>'; |
|
|
$output .= "<ul>\n <li>".implode("</li>\n <li>", $links)."</li>\n</ul>"; |
|
| 1040 |
return $output; |
return $output; |
| 1041 |
} |
} |
| 1042 |
|
|
| 1075 |
$fid = explode('?', arg(2)); |
$fid = explode('?', arg(2)); |
| 1076 |
$fid = $fid[0]; |
$fid = $fid[0]; |
| 1077 |
// Validate that the user can listen to this file. |
// Validate that the user can listen to this file. |
| 1078 |
$nid = db_result(db_query('SELECT nid FROM {files} WHERE fid = %d', $fid)); |
$nid = db_result(db_query('SELECT nid FROM {upload} WHERE fid = %d', $fid)); |
| 1079 |
if (!node_access('view', node_load($nid), $user->uid)) { |
if (!node_access('view', node_load($nid), $user->uid)) { |
| 1080 |
return drupal_access_denied();; |
return drupal_access_denied();; |
| 1081 |
} |
} |