root/modules/branches/2.10/queues/functions.inc.php

Revision 12263, 53.5 kB (checked in by mbrevda, 2 years ago)

re #5170 - update to work with queues

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php /* $id:$ */
2
3 class queues_conf {
4
5     var $_queues_general    = array();
6
7     // return an array of filenames to write
8     // files named like pinset_N
9     function get_filename() {
10         $files = array(
11             'queues_additional.conf',
12             'queues_general_additional.conf',
13             );
14         return $files;
15     }
16     
17     // return the output that goes in each of the files
18     function generateConf($file) {
19         global $version;
20
21         switch ($file) {
22             case 'queues_additional.conf':
23                 return $this->generate_queues_additional($version);
24                 break;
25             case 'queues_general_additional.conf':
26                 return $this->generate_queues_general_additional($version);
27                 break;
28         }
29     }
30
31     function addQueuesGeneral($key, $value) {
32         $this->_queues_general[] = array('key' => $key, 'value' => $value);
33     }
34
35     function generate_queues_additional($ast_version) {
36
37         global $db;
38         global $amp_conf;
39
40         $additional = "";
41         $output = "";
42         // Asterisk 1.4 does not like blank assignments so just don't put them there
43         //
44         $ver12 = version_compare($ast_version, '1.4', 'lt');
45         $ver16 = version_compare($ast_version, '1.6', 'ge');
46     $ast_ge_14_25 = version_compare($ast_version,'1.4.25','ge');
47     $ast_ge_18 = version_compare($ast_version,'1.8','ge');
48         
49         // legacy but in case someone was using this we will leave it
50         //
51         $sql = "SELECT keyword,data FROM queues_details WHERE id='-1' AND keyword <> 'account'";
52         $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
53         if(DB::IsError($results)) {
54            die($results->getMessage());
55         }
56         foreach ($results as $result) {
57             if (!$ver12 && trim($result['data']) == '') {
58                 continue;
59             }
60             $additional .= $result['keyword']."=".$result['data']."\n";
61         }
62
63     if ($ast_ge_14_25) {
64           $devices = array();
65           $device_results = core_devices_list('all','full',true);
66           if (is_array($device_results)) {
67               foreach ($device_results as $device) {
68           if (!isset($devices[$device['user']]) && $device['devicetype'] == 'fixed') {
69                     $devices[$device['user']] = $device['dial'];
70           }
71               }
72               unset($device_results);
73           }
74     }
75     if ($amp_conf['USEQUEUESTATE'] || $ast_ge_14_25) {
76           $users = array();
77           $user_results = core_users_list();
78           if (is_array($user_results)) {
79               foreach ($user_results as $user) {
80                   $users[$user[0]] = $user[1];
81               }
82               unset($user_results);
83           }
84     }
85         $results = queues_list(true);
86         foreach ($results as $result) {
87             $output .= "[".$result[0]."]\n";
88
89             // passing 2nd param 'true' tells queues_get to send back only queue_conf required params
90             // and nothing else
91             //
92             $results2 = queues_get($result[0], true);
93
94             // memebers is an array of members so we set it asside and remove it
95             // and then generate each later
96             //
97             $members = $results2['member'];
98             unset($results2['member']);
99
100             foreach ($results2 as $keyword => $data) {
101                 if ($ver12){
102                     switch($keyword){
103                         case 'ringinuse':
104                         case 'autofill':
105                             break;
106                         case 'retry':
107                             if ($data == 'none') {
108                                 $data = 0;
109                             }
110                             // no break, fallthrough to default
111                         default:
112                             $output .= $keyword."=".$data."\n";
113                             break;
114                     }
115                 }else{
116                     switch($keyword){
117                         case (trim($data) == ''):
118                         case 'monitor-join':
119                             break;
120                         case 'monitor-format':
121                             if (strtolower($data) != 'no'){
122                                 $output .= "monitor-type=mixmonitor\n";
123                                 $output .= $keyword."=".$data."\n";
124                             }
125                             break;
126                         case 'announce-position':
127                             if ($ver16) {
128                                 $output .= $keyword."=".$data."\n";
129                             }
130                             break;
131                         case 'retry':
132                             if ($data == 'none') {
133                                 $data = 0;
134                             }
135                             // no break, fallthrough to default
136                         default:
137                             $output .= $keyword."=".$data."\n";
138                             break;
139                     }
140                 }
141             }
142
143             // Now pull out all the memebers, one line for each
144             //
145       if ($ast_ge_18 || $amp_conf['USEQUEUESTATE']) {
146               foreach ($members as $member) {
147                   preg_match("/^Local\/([\d]+)\@*/",$member,$matches);
148                   if (isset($matches[1]) && isset($users[$matches[1]])) {
149                       $name = $users[$matches[1]];
150                       str_replace(',','\,',$name);
151             
152             $qnostate = queues_get_qnostate($matches[1]);
153             if ($qnostate == 'ignorestate') {
154               freepbx_log(FPBX_LOG_NOTICE,"Ignoring State information for Queue Member: ".$matches[1]);
155                         $output .= "member=$member,$name\n";
156             } else {
157                         $output .= "member=$member,$name,hint:".$matches[1]."@ext-local\n";
158             }
159                   } else {
160                       $output .= "member=".$member."\n";
161                   }
162               }
163       } else if ($ast_ge_14_25) {
164               foreach ($members as $member) {
165                   preg_match("/^Local\/([\d]+)\@*/",$member,$matches);
166                   if (isset($matches[1]) && isset($devices[$matches[1]])) {
167                       $name = $users[$matches[1]];
168                       str_replace(',','\,',$name);
169             $qnostate = queues_get_qnostate($matches[1]);
170             if ($qnostate == 'ignorestate') {
171               freepbx_log(FPBX_LOG_NOTICE,"Ignoring State information for Queue Member: ".$matches[1]);
172                         $output .= "member=$member,$name\n";
173             } else {
174                         $output .= "member=$member,$name,".$devices[$matches[1]]."\n";
175             }
176                   } else {
177                       $output .= "member=".$member."\n";
178                   }
179               }
180       } else {
181         foreach ($members as $member) {
182           $output .= "member=".$member."\n";
183         }
184       }
185             $output .= $additional."\n";
186         }
187
188         // Before returning the results, do an integrity check to see
189         // if there are any truncated compound recrodings and if so
190         // crate a noticication.
191         //
192         $nt = notifications::create($db);
193
194         $compound_recordings = queues_check_compoundrecordings();
195         if (empty($compound_recordings)) {
196             $nt->delete('queues', 'COMPOUNDREC');
197         } else {
198             $str = _("Warning, there are compound recordings configured in one or more Queue configurations. Queues can not play these so they have been truncated to the first sound file. You should correct this problem.<br />Details:<br /><br />");
199             foreach ($compound_recordings as $item) {
200                 $str .= sprintf(_("Queue - %s (%s): %s<br />"), $item['extension'], $item['descr'], $item['error']);
201             }
202             $nt->add_error('queues', 'COMPOUNDREC', _("Compound Recordings in Queues Detected"), $str);
203         }
204         return $output;
205     }
206
207     function generate_queues_general_additional($ast_version) {
208         $output = '';
209
210         if (isset($this->_queues_general) && is_array($this->_queues_general)) {
211             foreach ($this->_queues_general as $values) {
212                 $output .= $values['key']."=".$values['value']."\n";
213             }
214         }
215         return $output;
216     }
217 }
218
219 // The destinations this module provides
220 // returns a associative arrays with keys 'destination' and 'description'
221 function queues_destinations() {
222     //get the list of all exisiting
223     $results = queues_list(true);
224     
225     //return an associative array with destination and description
226     if (isset($results)) {
227         foreach($results as $result){
228                 $extens[] = array('destination' => 'ext-queues,'.$result['0'].',1', 'description' => $result['1'].' <'.$result['0'].'>');
229         }
230     }
231     
232     if (isset($extens))
233         return $extens;
234     else
235         return null;
236 }
237
238 function queues_getdest($exten) {
239     return array('ext-queues,'.$exten.',1');
240 }
241
242 function queues_getdestinfo($dest) {
243     global $active_modules;
244
245     if (substr(trim($dest),0,11) == 'ext-queues,') {
246         $exten = explode(',',$dest);
247         $exten = $exten[1];
248         $thisexten = queues_get($exten);
249         if (empty($thisexten)) {
250             return array();
251         } else {
252             //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup';
253             return array('description' => sprintf(_("Queue %s : %s"),$exten,$thisexten['name']),
254                          'edit_url' => 'config.php?display=queues&extdisplay='.urlencode($exten),
255                                   );
256         }
257     } else {
258         return false;
259     }
260 }
261
262 function queues_recordings_usage($recording_id) {
263     global $active_modules;
264
265     $results = sql("SELECT `extension`, `descr` FROM `queues_config` WHERE `agentannounce_id` = '$recording_id' OR `joinannounce_id` = '$recording_id'","getAll",DB_FETCHMODE_ASSOC);
266     if (empty($results)) {
267         return array();
268     } else {
269         //$type = isset($active_modules['queues']['type'])?$active_modules['queues']['type']:'setup';
270         foreach ($results as $result) {
271             $usage_arr[] = array(
272               'url_query' => 'config.php?display=queues&extdisplay='.urlencode($result['extension']),
273                 'description' => sprintf(_("Queue: %s"),$result['descr']),
274             );
275         }
276         return $usage_arr;
277     }
278 }
279
280 function queues_ivr_usage($ivr_id) {
281     global $active_modules;
282
283     $results = sql("SELECT `extension`, `descr` FROM `queues_config` WHERE `ivr_id` = '$ivr_id'","getAll",DB_FETCHMODE_ASSOC);
284     if (empty($results)) {
285         return array();
286     } else {
287         foreach ($results as $result) {
288             $usage_arr[] = array(
289               'url_query' => 'config.php?display=queues&extdisplay='.urlencode($result['extension']),
290                 'description' => sprintf(_("Queue: %s"),$result['descr']),
291             );
292         }
293         return $usage_arr;
294     }
295 }
296
297 /*     Generates dialplan for "queues" components (extensions & inbound routing)
298     We call this with retrieve_conf
299 */
300 function queues_get_config($engine) {
301     global $ext// is this the best way to pass this?
302     global $queues_conf;
303     global $amp_conf;
304     global $version;
305
306     switch($engine) {
307         case "asterisk":
308             global $astman;
309
310       $ast_ge_14 = version_compare($version,'1.4','ge');
311       $ast_ge_16 = version_compare($version,'1.6','ge');
312       $ast_ge_14_25 = version_compare($version,'1.4.25','ge');
313       $ast_ge_18 = version_compare($version,'1.8','ge');
314
315       $has_extension_state = $ast_ge_16;
316             if ($ast_ge_14 && !$ast_ge_16) {
317                 $response = $astman->send_request('Command', array('Command' => 'module show like func_extstate'));
318                 if (preg_match('/1 modules loaded/', $response['data'])) {
319           $has_extension_state = true;
320         }
321             }
322
323             if (isset($queues_conf) && is_a($queues_conf, "queues_conf")) {
324                 $queues_conf->addQueuesGeneral('persistentmembers',$amp_conf['QUEUES_PESISTENTMEMBERS'] ? 'yes' : 'no');
325         if ($ast_ge_16) {
326                   $queues_conf->addQueuesGeneral('shared_lastcall',$amp_conf['QUEUES_SHARED_LASTCALL'] ? 'yes' : 'no');
327                   $queues_conf->addQueuesGeneral('updatecdr',$amp_conf['QUEUES_UPDATECDR'] ? 'yes' : 'no');
328         }
329         if ($amp_conf['QUEUES_MIX_MONITOR']) {
330                   $queues_conf->addQueuesGeneral('monitor-type', 'MixMonitor');
331         }
332             }
333
334             /* queue extensions */
335             $ext->addInclude('from-internal-additional','ext-queues');
336             /* Trial DEVSTATE */
337             if ($amp_conf['USEDEVSTATE']) {
338                 $ext->addGlobal('QUEDEVSTATE','TRUE');
339             }
340             // $que_code = '*45';
341             $fcc = new featurecode('queues', 'que_toggle');
342             $que_code = $fcc->getCodeActive();
343             unset($fcc);
344             if ($que_code != '') {
345                 queue_app_toggle($que_code);
346                 queue_agent_del_toggle();
347                 queue_agent_add_toggle();
348             }
349             $qlist = queues_list(true);
350
351             $from_queue_exten_only = 'from-queue-exten-only';
352             $from_queue_exten_internal = 'from-queue-exten-internal';
353
354             if (is_array($qlist)) {
355                 foreach($qlist as $item) {
356                     
357                     $exten = $item[0];
358                     $q = queues_get($exten);
359
360                     $grppre = (isset($q['prefix'])?$q['prefix']:'');
361                     $alertinfo = (isset($q['alertinfo'])?$q['alertinfo']:'');
362
363                     // Not sure why someone would ever have a ; in the regex, but since Asterisk has problems with them
364                     // it would need to be escaped
365                     //
366                     $qregex = (isset($q['qregex'])?$q['qregex']:'');
367                     str_replace(';','\;',$qregex);
368                     
369                     $ext->add('ext-queues', $exten, '', new ext_macro('user-callerid'));
370                     
371                     if (isset($q['qnoanswer']) && $q['qnoanswer'] == FALSE) {
372                         $ext->add('ext-queues', $exten, '', new ext_answer(''));
373                     } else {
374             // TODO: should this only be set if noanswer + (!ringtones || joinannounce)???
375                       $ext->add('ext-queues', $exten, '', new ext_progress());
376           }
377
378                     // block voicemail until phone is answered at which point a macro should be called on the answering
379                     // line to clear this flag so that subsequent transfers can occur.
380                     //
381                     if ($q['queuewait']) {
382                         $ext->add('ext-queues', $exten, '', new ext_execif('$["${QUEUEWAIT}" = ""]', 'Set', '__QUEUEWAIT=${EPOCH}'));
383                     }
384           // If extension_only don't do this and CFIGNORE
385           if($q['use_queue_context'] != '2') {
386                       $ext->add('ext-queues', $exten, '', new ext_macro('blkvm-set', 'reset'));
387                       $ext->add('ext-queues', $exten, '', new ext_execif('$["${REGEX("(M[(]auto-blkvm[)])" ${DIAL_OPTIONS})}" != "1"]', 'Set', '_DIAL_OPTIONS=${DIAL_OPTIONS}M(auto-blkvm)'));
388           }
389
390                     // Inform all the children NOT to send calls to destinations or voicemail
391                     //
392                     $ext->add('ext-queues', $exten, '', new ext_setvar('__NODEST', '${EXTEN}'));
393
394                     // deal with group CID prefix
395                     if ($grppre != '') {
396                         $ext->add('ext-queues', $exten, '', new ext_macro('prepend-cid', $grppre));
397                     }
398
399                     // Set Alert_Info
400                     if ($alertinfo != '') {
401                         $ext->add('ext-queues', $exten, '', new ext_setvar('__ALERT_INFO', str_replace(';', '\;', $alertinfo)));
402                     }
403
404                     $ext->add('ext-queues', $exten, '', new ext_setvar('MONITOR_FILENAME','/var/spool/asterisk/monitor/q${EXTEN}-${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}-${UNIQUEID}'));
405                     if ($amp_conf['QUEUES_MIX_MONITOR']) {
406                         $monitor_options = '';
407                         if (isset($q['monitor_type']) && $q['monitor_type'] != '') {
408                             $monitor_options .= 'b';
409                         }
410                         if (isset($q['monitor_spoken']) && $q['monitor_spoken'] != 0) {
411                                                         $monitor_options .= 'V('.$q['monitor_spoken'].')';
412                                                 }
413                         if (isset($q['monitor_heard']) && $q['monitor_heard'] != 0) {
414                                                         $monitor_options .= 'v('.$q['monitor_heard'].')';
415                                                 }
416                         if ($monitor_options != '') {
417                             $ext->add('ext-queues', $exten, '', new ext_setvar('MONITOR_OPTIONS', $monitor_options ));
418                         }
419                     }
420                     $joinannounce_id = (isset($q['joinannounce_id'])?$q['joinannounce_id']:'');
421                     if($joinannounce_id) {
422                         $joinannounce = recordings_get_file($joinannounce_id);
423                     
424                         if (isset($q['qnoanswer']) && $q['qnoanswer'] == TRUE) {
425                             $joinannounce = $joinannounce.', noanswer';
426                         }
427
428                         $ext->add('ext-queues', $exten, '', new ext_playback($joinannounce));
429                     }
430                     $options = 't';
431                     if ($q['rtone'] == 1) {
432                         $options .= 'r';
433                     }
434                     if ($q['retry'] == 'none'){
435                         $options .= 'n';
436                     }
437                     if (isset($q['music'])) {
438                          $ext->add('ext-queues', $exten, '', new ext_setvar('__MOHCLASS', $q['music']));
439                     }
440                     // Set CWIGNORE  if enabled so that busy agents don't have another line key ringing and
441                     // stalling the ACD.
442                     if ($q['cwignore'] == 1 || $q['cwignore'] == 2 ) {
443                          $ext->add('ext-queues', $exten, '', new ext_setvar('__CWIGNORE', 'TRUE'));
444                     }
445                     if ($q['use_queue_context']) {
446                          $ext->add('ext-queues', $exten, '', new ext_setvar('__CFIGNORE', 'TRUE'));
447                          $ext->add('ext-queues', $exten, '', new ext_setvar('__FORWARD_CONTEXT', 'block-cf'));
448                     }
449                     $agentannounce_id = (isset($q['agentannounce_id'])?$q['agentannounce_id']:'');
450                     if ($agentannounce_id) {
451                         $agentannounce = recordings_get_file($agentannounce_id);
452                     } else {
453                         $agentannounce = '';
454                     }
455                     
456                     if ($q['callconfirm'] == 1) {
457                         $ext->add('ext-queues', $exten, '', new ext_setvar('__FORCE_CONFIRM', '${CHANNEL}'));
458                         if ($amp_conf['AST_FUNC_SHARED']) {
459                                 $ext->add('ext-queues', $exten, '', new ext_setvar('SHARED(ANSWER_STATUS)','NOANSWER'));
460                               }
461                         $ext->add('ext-queues', $exten, '', new ext_setvar('__CALLCONFIRMCID', '${CALLERID(number)}'));
462                         $callconfirm_id = (isset($q['callconfirm_id']))?$q['callconfirm_id']:'';
463                         if ($callconfirm_id) {   
464                             $callconfirm = recordings_get_file($callconfirm_id);
465                         } else {
466                             $callconfirm = '';
467                         }
468                         $ext->add('ext-queues', $exten, '', new ext_setvar('__ALT_CONFIRM_MSG', $callconfirm));                   
469                     }
470
471                     $ext->add('ext-queues', $exten, '', new ext_queue($exten,$options,'',$agentannounce,$q['maxwait']));
472  
473           if($q['use_queue_context'] != '2') {
474                       $ext->add('ext-queues', $exten, '', new ext_macro('blkvm-clr'));
475           }
476                      // If we are here, disable the NODEST as we want things to resume as normal
477                      //
478                      $ext->add('ext-queues', $exten, '', new ext_setvar('__NODEST', ''));
479                     
480                     if ($q['callconfirm'] == 1) {
481                         if ($amp_conf['AST_FUNC_SHARED']) {
482                             $ext->add('ext-queues', $exten, '', new ext_setvar('SHARED(ANSWER_STATUS)', ''));
483                         }
484                         $ext->add('ext-queues', $exten, '', new ext_setvar('__FORCE_CONFIRM', ''));
485                         $ext->add('ext-queues', $exten, '', new ext_setvar('__ALT_CONFIRM_MSG', ''));               
486                     }
487
488                     if($monitor_options != '') {
489                         $ext->add('ext-queues', $exten, '', new ext_setvar('MONITOR_OPTIONS', ''));
490                     }
491                     if ($q['cwignore'] == 1 || $q['cwignore'] == 2 ) {
492                         $ext->add('ext-queues', $exten, '', new ext_setvar('__CWIGNORE', ''));
493                     }
494                     if ($q['use_queue_context']) {
495                          $ext->add('ext-queues', $exten, '', new ext_setvar('__CFIGNORE', ''));
496                          $ext->add('ext-queues', $exten, '', new ext_setvar('__FORWARD_CONTEXT', 'from-internal'));
497                     }
498     
499                     // destination field in 'incoming' database is backwards from what ext_goto expects
500                     $goto_context = strtok($q['goto'],',');
501                     $goto_exten = strtok(',');
502                     $goto_pri = strtok(',');
503                     
504                     $ext->add('ext-queues', $exten, '', new ext_goto($goto_pri,$goto_exten,$goto_context));
505                     
506                     //dynamic agent login/logout
507                     if (trim($qregex) != '') {
508                          $ext->add('ext-queues', $exten."*", '', new ext_setvar('QREGEX', $qregex));
509                     }
510           if($q['use_queue_context'] == '2') {
511                       $ext->add('ext-queues', $exten."*", '', new ext_macro('agent-add',$exten.",".$q['password'].",EXTEN"));
512           } else {
513                       $ext->add('ext-queues', $exten."*", '', new ext_macro('agent-add',$exten.",".$q['password']));
514           }
515                     $ext->add('ext-queues', $exten."**", '', new ext_macro('agent-del',"$exten"));
516                     if ($que_code != '') {
517             $ext->add('ext-queues', $que_code.$exten, '', new ext_setvar('QUEUENO',$exten));
518             $ext->add('ext-queues', $que_code.$exten, '', new ext_goto('start','s','app-queue-toggle'));
519           }
520                     /* Trial Devstate */
521                     // Create Hints for Devices and Add Astentries for Users
522                     // Clean up the Members array
523                     if ($q['togglehint'] && $amp_conf['USEDEVSTATE'] && $que_code != '') {
524             if (!isset($device_list)) {
525                           $device_list = core_devices_list("all", 'full', true);
526             }
527             if ($astman) {
528               if (($dynmemberonly = strtolower($astman->database_get('QPENALTY/'.$exten,'dynmemberonly')) == 'yes') == true) {
529                 $get=$astman->database_show('QPENALTY/'.$exten.'/agents');
530                 if($get){
531                   $mem = array();
532                   foreach($get as $key => $value){
533                     $key=explode('/',$key);
534                     $mem[$key[4]]=$value;
535                   }
536                 }
537               }
538             } else {
539               fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
540             }
541                         foreach ($device_list as $device) {
542               if ((!$dynmemberonly||$device['devicetype']=='adhoc'||isset($mem[$device['user']]))&&($device['tech']=='sip'||$device['tech']=='iax2')) {
543                               $ext->add('ext-queues', $que_code.$device['id'].'*'.$exten, '', new ext_setvar('QUEUENO',$exten));
544                               $ext->add('ext-queues', $que_code.$device['id'].'*'.$exten, '', new ext_goto('start','s','app-queue-toggle'));
545                               $ext->addHint('ext-queues', $que_code.$device['id'].'*'.$exten, "Custom:QUEUE".$device['id'].'*'.$exten);
546               }
547                         }
548                     }
549
550                     // Add routing vector to direct which context call should go
551                     //
552                     $agent_context = $q['use_queue_context'] ? $queue_context : 'from-internal';
553                     switch ($q['use_queue_context']) {
554                         case 1:
555                             $agent_context = $from_queue_exten_internal;
556                             break;
557                         case 2:
558                             $agent_context = $from_queue_exten_only;
559                             break;
560                         case 0:
561                         default:
562                             $agent_context = 'from-internal';
563                             break;
564                     }
565                     $ext->add('from-queue', $exten, '', new ext_goto('1','${QAGENT}',$agent_context));
566                 }
567             }
568             // We need to have a hangup here, if call is ended by the caller during Playback it will end in the
569             // h context and do a proper hangup and clean the blkvm if set, see #4671
570             $ext->add('ext-queues', 'h', '', new ext_macro('hangupcall'));           
571             // NODEST will be the queue that this came from, so we will vector though an entry to determine the context the
572             // agent should be delivered to. All queue calls come here, this decides if the should go direct to from-internal
573             // or indirectly through from-queue-exten-only to trap extension calls and avoid their follow-me, etc.
574             //
575             $ext->add('from-queue', '_.', '', new ext_setvar('QAGENT','${EXTEN}'));
576             $ext->add('from-queue', '_.', '', new ext_goto('1','${NODEST}'));
577
578             $ext->addInclude($from_queue_exten_internal,$from_queue_exten_only);
579             $ext->addInclude($from_queue_exten_internal,'from-internal');
580             $ext->add($from_queue_exten_internal, 'foo', '', new ext_noop('bar'));
581
582             /* create a context, from-queue-exten-only, that can be used for queues that want behavir similar to
583              * ringgroup where only the agent's phone will be rung, no follow-me will be pursued.
584              */
585             $userlist = core_users_list();
586             if (is_array($userlist)) {
587                 foreach($userlist as $item) {
588                      $ext->add($from_queue_exten_only, $item[0], '', new ext_setvar('RingGroupMethod', 'none'));
589                     $ext->add($from_queue_exten_only, $item[0], '', new ext_macro('record-enable',$item[0].",IN"));
590           if ($has_extension_state) {
591                       $ext->add($from_queue_exten_only, $item[0], '', new ext_macro('dial-one',',${DIAL_OPTIONS},'.$item[0]));
592           } else {
593                       $ext->add($from_queue_exten_only, $item[0], '', new ext_macro('dial',',${DIAL_OPTIONS},'.$item[0]));
594           }
595                      $ext->add($from_queue_exten_only, $item[0], '', new ext_hangup());
596                 }
597                  $ext->add($from_queue_exten_only, 'h', '', new ext_macro('hangupcall'));
598             }
599
600             /*
601              * Adds a dynamic agent/member to a Queue
602              * Prompts for call-back number - in not entered, uses CIDNum
603              */
604
605             $context = 'macro-agent-add';
606             $exten = 's';
607             
608             $ext->add($context, $exten, '', new ext_wait(1));
609             $ext->add($context, $exten, '', new ext_macro('user-callerid', 'SKIPTTL'));
610             $ext->add($context, $exten, 'a3', new ext_read('CALLBACKNUM', 'agent-login'));  // get callback number from user
611             $ext->add($context, $exten, '', new ext_gotoif('$[${LEN(${CALLBACKNUM})}=0]','a5','a7'));  // if user just pressed # or timed out, use cidnum
612             $ext->add($context, $exten, 'a5', new ext_set('CALLBACKNUM', '${IF($[${LEN(${AMPUSER})}=0]?${CALLERID(number)}:${AMPUSER})}'));
613
614       if ($ast_ge_14_25) {
615               $ext->add($context, $exten, '', new ext_set('THISDEVICE', '${DB(DEVICE/${REALCALLERIDNUM}/dial)}'));
616       }
617             $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a3'));  // if still no number, start over
618             $ext->add($context, $exten, 'a7', new ext_gotoif('$["${CALLBACKNUM}" = "${ARG1}"]', 'invalid'));  // Error, they put in the queue number
619
620       // If this is an extension only queue then EXTEN is passed as ARG3 and we make sure this is a valid extension being entered
621       //
622             $ext->add($context, $exten, '', new ext_gotoif('$["${ARG3}" = "EXTEN" & ${DB_EXISTS(AMPUSER/${CALLBACKNUM}/cidname)} = 0]', 'invalid'));
623
624       // If this is a restricted dynamic agent queue then check to make sure they are allowed
625       //
626       $ext->add($context, $exten, '', new ext_gotoif('$["${DB(QPENALTY/${ARG1}/dynmemberonly)}" = "yes" & ${DB_EXISTS(QPENALTY/${ARG1}/agents/${CALLBACKNUM})} != 1]', 'invalid'));
627
628             $ext->add($context, $exten, '', new ext_execif('$["${QREGEX}" != ""]', 'GotoIf', '$["${REGEX("${QREGEX}" ${CALLBACKNUM})}" = "0"]?invalid'));
629             $ext->add($context, $exten, '', new ext_execif('$["${ARG2}" != ""]', 'Authenticate', '${ARG2}'));
630
631
632       if ($ast_ge_18 || $amp_conf['USEQUEUESTATE']) {
633               $ext->add($context, $exten, '', new ext_execif('$[${DB_EXISTS(AMPUSER/${CALLBACKNUM}/cidname)} = 1 & "${DB(AMPUSER/${CALLBACKNUM}/queues/qnostate)}" != "ignorestate"]', 'AddQueueMember', '${ARG1},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${ARG1}/agents/${CALLBACKNUM})},,${DB(AMPUSER/${CALLBACKNUM}/cidname)},hint:${CALLBACKNUM}@ext-local'));
634               $ext->add($context, $exten, '', new ext_execif('$[${DB_EXISTS(AMPUSER/${CALLBACKNUM}/cidname)} = 1 & "${DB(AMPUSER/${CALLBACKNUM}/queues/qnostate)}" = "ignorestate"]', 'AddQueueMember', '${ARG1},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${ARG1}/agents/${CALLBACKNUM})},,${DB(AMPUSER/${CALLBACKNUM}/cidname)}'));
635               $ext->add($context, $exten, '', new ext_execif('$[${DB_EXISTS(AMPUSER/${CALLBACKNUM}/cidname)} = 0]', 'AddQueueMember', '${ARG1},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${ARG1}/agents/${CALLBACKNUM})}'));
636       } else if ($ast_ge_14_25) {
637               $ext->add($context, $exten, '', new ext_set('THISDEVICE', '${IF($[${LEN(${THISDEVICE})}=0]?${DB(DEVICE/${CUT(DB(AMPUSER/${CALLBACKNUM}/device),&,1)}/dial)}:${THISDEVICE})}'));
638               $ext->add($context, $exten, '', new ext_execif('$[${LEN(${THISDEVICE})}!=0 & "${DB(AMPUSER/${CALLBACKNUM}/queues/qnostate)}" != "ignorestate"]', 'AddQueueMember', '${ARG1},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${ARG1}/agents/${CALLBACKNUM})},,${DB(AMPUSER/${CALLBACKNUM}/cidname)},${THISDEVICE}'));
639               $ext->add($context, $exten, '', new ext_execif('$[${LEN(${THISDEVICE})}!=0 & "${DB(AMPUSER/${CALLBACKNUM}/queues/qnostate)}" = "ignorestate"]', 'AddQueueMember', '${ARG1},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${ARG1}/agents/${CALLBACKNUM})},,${DB(AMPUSER/${CALLBACKNUM}/cidname)}'));
640               $ext->add($context, $exten, '', new ext_execif('$[${LEN(${THISDEVICE})}=0]', 'AddQueueMember', '${ARG1},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${ARG1}/agents/${CALLBACKNUM})}'));
641       } else {
642         $ext->add($context, $exten, 'a9', new ext_addqueuemember('${ARG1}', 'Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${ARG1}/agents/${CALLBACKNUM})}'));
643       }
644           $ext->add($context, $exten, '', new ext_userevent('Agentlogin', 'Agent: ${CALLBACKNUM}'));
645           $ext->add($context, $exten, '', new ext_wait(1));
646           $ext->add($context, $exten, '', new ext_playback('agent-loginok&with&extension'));
647           $ext->add($context, $exten, '', new ext_saydigits('${CALLBACKNUM}'));
648           $ext->add($context, $exten, '', new ext_hangup());
649           $ext->add($context, $exten, '', new ext_macroexit());
650           $ext->add($context, $exten, 'invalid', new ext_playback('pbx-invalid'));
651           $ext->add($context, $exten, '', new ext_goto('a3'));
652
653             /*
654              * Removes a dynamic agent/member from a Queue
655              * Prompts for call-back number - in not entered, uses CIDNum
656              */
657
658             $context = 'macro-agent-del';
659             
660             $ext->add($context, $exten, '', new ext_wait(1));
661             $ext->add($context, $exten, '', new ext_macro('user-callerid', 'SKIPTTL'));
662             $ext->add($context, $exten, 'a3', new ext_read('CALLBACKNUM', 'agent-logoff'));  // get callback number from user
663             $ext->add($context, $exten, '', new ext_gotoif('$[${LEN(${CALLBACKNUM})}=0]','a5','a7'));  // if user just pressed # or timed out, use cidnum
664             $ext->add($context, $exten, 'a5', new ext_set('CALLBACKNUM', '${IF($[${LEN(${AMPUSER})}=0]?${CALLERID(number)}:${AMPUSER})}'));
665             $ext->add($context, $exten, '', new ext_gotoif('$["${CALLBACKNUM}" = ""]', 'a3'));  // if still no number, start over
666
667             // remove from both contexts in case left over dynamic agents after an upgrade
668             $ext->add($context, $exten, 'a7', new ext_removequeuemember('${ARG1}', 'Local/${CALLBACKNUM}@from-queue/n'));
669             $ext->add($context, $exten, '', new ext_removequeuemember('${ARG1}', 'Local/${CALLBACKNUM}@from-internal/n'));
670             $ext->add($context, $exten, '', new ext_userevent('RefreshQueue'));
671             $ext->add($context, $exten, '', new ext_wait(1));
672             $ext->add($context, $exten, '', new ext_playback('agent-loggedoff'));
673             $ext->add($context, $exten, '', new ext_hangup());
674         break;
675     }
676 }
677
678 function queues_timeString($seconds, $full = false) {
679     if ($seconds == 0) {
680         return "0 ".($full ? _("seconds") : "s");
681     }
682
683     $minutes = floor($seconds / 60);
684     $seconds = $seconds % 60;
685
686     $hours = floor($minutes / 60);
687     $minutes = $minutes % 60;
688
689     $days = floor($hours / 24);
690     $hours = $hours % 24;
691
692     if ($full) {
693          return substr(
694                       ($days ? $days." "._("day").(($days == 1) ? "" : "s").", " : "").
695                       ($hours ? $hours." ".(($hours == 1) ? _("hour") : _("hours")).", " : "").
696                       ($minutes ? $minutes." ".(($minutes == 1) ? _("minute") : _("minutes")).", " : "").
697                       ($seconds ? $seconds." ".(($seconds == 1) ? _("second") : _("seconds")).", " : ""),
698                       0, -2);
699     } else {
700         return substr(($days ? $days."d, " : "").($hours ? $hours."h, " : "").($minutes ? $minutes."m, " : "").($seconds ? $seconds."s, " : ""), 0, -2);
701     }
702 }
703
704 function queues_add($account,$name,$password,$prefix,$goto,$agentannounce_id,$members,$joinannounce_id,$maxwait,$alertinfo='',$cwignore='0',$qregex='',$queuewait='0', $use_queue_context='0', $dynmembers = '', $dynmemberonly = 'no', $togglehint = '0', $qnoanswer = '0', $callconfirm = '0', $callconfirm_id, $monitor_type = '', $monitor_heard = '0', $monitor_spoken = '0') {
705   global $db,$astman,$amp_conf;
706
707     $ast_ge_16 = version_compare($amp_conf['ASTVERSION'] , '1.6', 'ge');
708     
709     if (trim($account) == '') {
710         echo "<script>javascript:alert('"._("Bad Queue Number, can not be blank")."');</script>";
711         return false;
712     }
713
714     //add to extensions table
715     if (empty($agentannounce_id)) {
716         $agentannounce_id="";
717     }
718
719 $fields = array(
720     array($account,'maxlen',($_REQUEST['maxlen'])?$_REQUEST['maxlen']:'0',0),
721     array($account,'joinempty',($_REQUEST['joinempty'])?$_REQUEST['joinempty']:'yes',0),
722     array($account,'leavewhenempty',($_REQUEST['leavewhenempty'])?$_REQUEST['leavewhenempty']:'no',0),
723     array($account,'strategy',($_REQUEST['strategy'])?$_REQUEST['strategy']:'ringall',0),
724     array($account,'timeout',(isset($_REQUEST['timeout']))?$_REQUEST['timeout']:'15',0),
725     array($account,'retry',(isset($_REQUEST['retry']) && $_REQUEST['retry'] != '')?$_REQUEST['retry']:'5',0),
726     array($account,'wrapuptime',($_REQUEST['wrapuptime'])?$_REQUEST['wrapuptime']:'0',0),
727     array($account,'announce-frequency',($_REQUEST['announcefreq'])?$_REQUEST['announcefreq']:'0',0),
728     array($account,'announce-holdtime',($_REQUEST['announceholdtime'])?$_REQUEST['announceholdtime']:'no',0),
729     array($account,'announce-position',($_REQUEST['announceposition'])?$_REQUEST['announceposition']:'no',0),
730     array($account,'queue-youarenext',($_REQUEST['announceposition']=='no')?'silence/1':'queue-youarenext',0),  //if no, play no sound
731     array($account,'queue-thereare',($_REQUEST['announceposition']=='no')?'silence/1':'queue-thereare',0),  //if no, play no sound
732     array($account,'queue-callswaiting',($_REQUEST['announceposition']=='no')?'silence/1':'queue-callswaiting',0),  //if no, play no sound
733     array($account,'queue-thankyou',($_REQUEST['announceposition']=='no')?'':'queue-thankyou',0),  //if no, play no sound
734     array($account,'periodic-announce-frequency',($_REQUEST['pannouncefreq'])?$_REQUEST['pannouncefreq']:'0',0),
735     array($account,'monitor-format',($_REQUEST['monitor-format'])?$_REQUEST['monitor-format']:'',0),
736     array($account,'monitor-join','yes',0),
737     array($account,'eventwhencalled',($_REQUEST['eventwhencalled'])?$_REQUEST['eventwhencalled']:'no',0),
738     array($account,'eventmemberstatus',($_REQUEST['eventmemberstatus'])?$_REQUEST['eventmemberstatus']:'no',0),
739     array($account,'weight',(isset($_REQUEST['weight']))?$_REQUEST['weight']:'0',0),
740     array($account,'autofill',(isset($_REQUEST['autofill']))?'yes':'no',0),
741     array($account,'ringinuse',($cwignore == 2 || $cwignore == 3)?'no':'yes',0),
742     array($account,'reportholdtime',(isset($_REQUEST['reportholdtime']))?$_REQUEST['reportholdtime']:'no',0),
743     array($account,'servicelevel',(isset($_REQUEST['servicelevel']))?$_REQUEST['servicelevel']:60,0),
744     array($account,'memberdelay',(isset($_REQUEST['memberdelay']))?$_REQUEST['memberdelay']:'0',0),
745     array($account,'timeoutrestart',(isset($_REQUEST['timeoutrestart']))?$_REQUEST['timeoutrestart']:'no',0),
746 );
747
748     if($ast_ge_16) {
749         $fields[] = array($account, 'timeoutpriority',(isset($_REQUEST['timeoutpriority']))?$_REQUEST['timeoutpriority']:'app',0);
750         $fields[] = array($account, 'penaltymemberslimit',(isset($_REQUEST['penaltymemberslimit']))?$_REQUEST['penaltymemberslimit']:'0',0);
751     }
752
753     if ($_REQUEST['music'] != 'inherit') {
754         $fields[] = array($account,'music',($_REQUEST['music'])?$_REQUEST['music']:'default',0);
755     }
756
757     //there can be multiple members
758     if (isset($members)) {
759         $count = 0;
760         $members = array_unique($members);
761         foreach ($members as $member) {
762             $fields[] = array($account,'member',$member,$count);
763             $count++;
764         }
765     }
766
767     $compiled = $db->prepare('INSERT INTO queues_details (id, keyword, data, flags) values (?,?,?,?)');
768     $result = $db->executeMultiple($compiled,$fields);
769     if(DB::IsError($result)) {
770         die_freepbx($result->getMessage()."<br><br>error adding to queues_details table");   
771     }
772     $extension        = $account;
773     $descr         = isset($name) ? $db->escapeSimple($name):'';
774     $grppre        = isset($prefix) ? $db->escapeSimple($prefix):'';
775     $alertinfo     = isset($alertinfo) ? $db->escapeSimple($alertinfo):'';
776     //$joinannounce_id  = $joinannounce_id;
777     $ringing       = isset($_REQUEST['rtone']) ? $_REQUEST['rtone']:'';
778     //$agentannounce_id = $agentannounce_id;
779     $maxwait       = isset($maxwait) ? $maxwait:'';
780     $password      = isset($password) ? $password:'';
781     $ivr_id        = isset($_REQUEST['announcemenu']) ? $_REQUEST['announcemenu']:'none';
782     $dest          = isset($goto) ? $goto:'';
783     $cwignore      = isset($cwignore) ? $cwignore:'0';
784     $queuewait     = isset($queuewait) ? $queuewait:'0';
785     $qregex        = isset($qregex) ? $db->escapeSimple($qregex):'';
786     $use_queue_context = isset($use_queue_context) ? $use_queue_context:'0';
787     $togglehint    = isset($togglehint) ? $togglehint:'0';
788     $qnoanswer     = isset($qnoanswer) ? $qnoanswer:'0';
789     $callconfirm   = isset($callconfirm) ? $callconfirm:'0';
790     $monitor_type  = isset($monitor_type) ? $monitor_type:'';
791     $monitor_heard = isset($monitor_heard) ? $monitor_heard:'0';
792     $monitor_spoken = isset($monitor_spoken) ? $monitor_spoken:'0';
793
794     // Assumes it has just been deleted
795     $sql = "INSERT INTO queues_config (extension, descr, grppre, alertinfo, joinannounce_id, ringing, agentannounce_id, maxwait, password, ivr_id, dest, cwignore, qregex, queuewait, use_queue_context, togglehint, qnoanswer, callconfirm, callconfirm_id, monitor_type, monitor_heard, monitor_spoken)
796              VALUES ('$extension', '$descr', '$grppre', '$alertinfo', '$joinannounce_id', '$ringing', '$agentannounce_id', '$maxwait', '$password', '$ivr_id', '$dest', '$cwignore', '$qregex', '$queuewait', '$use_queue_context', '$togglehint', '$qnoanswer', '$callconfirm', '$callconfirm_id', '$monitor_type', '$monitor_heard', '$monitor_spoken')    ";
797     $results = sql($sql);
798
799   // store dynamic member data in astDB
800     if ($astman) {
801     $dynmembers = array_unique($dynmembers);
802       foreach($dynmembers as $member){
803         $mem=explode(',',$member);
804       if (isset($mem[0]) && trim($mem[0]) != '') {
805         $penalty = isset($mem[1]) && ctype_digit(trim($mem[1])) ? $mem[1] : 0;
806           $astman->database_put('QPENALTY/'.$account.'/agents',trim($mem[0]),trim($penalty));
807       }
808     }
809        $astman->database_put('QPENALTY/'.$account,'dynmemberonly',$dynmemberonly);
810     } else {
811         fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
812     }
813
814     return true;
815 }
816
817 function queues_del($account) {
818     global $db,$astman,$amp_conf;
819     
820     $sql = "DELETE FROM queues_details WHERE id = '$account'";
821     $result = $db->query($sql);
822     if(DB::IsError($result)) {
823         die_freepbx($result->getMessage().$sql);
824     }
825     $sql = "DELETE FROM queues_config WHERE extension = '$account'";
826     $result = $db->query($sql);
827     if(DB::IsError($result)) {
828         die_freepbx($result->getMessage().$sql);
829     }
830     
831     //remove dynamic memebers from astDB
832     if ($astman) {
833       $astman->database_deltree('QPENALTY/'.$account);
834     } else {
835         fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
836     }
837 }
838
839 //get the existing queue extensions
840 //
841 function queues_list($listall=false) {
842     global $db;
843     $sql = "SELECT extension, descr FROM queues_config ORDER BY extension";
844     $results = $db->getAll($sql);
845     if(DB::IsError($results)) {
846         $results = array();
847     }
848
849     foreach($results as $result){
850         if ($listall || checkRange($result[0])){
851             $extens[] = array($result[0],$result[1]);
852         }
853     }
854     if (isset($extens)) {
855         return $extens;
856     } else {
857         return array();
858     }
859 }
860
861 function queues_check_extensions($exten=true) {
862     global $active_modules;
863
864     $extenlist = array();
865     if (is_array($exten) && empty($exten)) {
866         return $extenlist;
867     }
868     $sql = "SELECT extension, descr FROM queues_config ";
869     if (is_array($exten)) {
870         $sql .= "WHERE extension in ('".implode("','",$exten)."')";
871     }
872     $sql .= " ORDER BY extension";
873     $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
874
875     //$type = isset($active_modules['queues']['type'])?$active_modules['queues']['type']:'setup';
876     foreach ($results as $result) {
877         $thisexten = $result['extension'];
878         $extenlist[$thisexten]['description'] = sprintf(_("Queue: %s"),$result['descr']);
879         $extenlist[$thisexten]['status'] = _('INUSE');
880         $extenlist[$thisexten]['edit_url'] = 'config.php?display=queues&extdisplay='.urlencode($thisexten);
881     }
882     return $extenlist;
883 }
884
885 function queues_check_destinations($dest=true) {
886     global $active_modules;
887
888     $destlist = array();
889     if (is_array($dest) && empty($dest)) {
890         return $destlist;
891     }
892     $sql = "SELECT extension, descr, dest FROM queues_config";
893     if ($dest !== true) {
894         $sql .= " WHERE dest in ('".implode("','",$dest)."')";
895     }
896     $sql .= " ORDER BY extension";
897
898     $results = sql($sql,"getAll",DB_FETCHMODE_ASSOC);
899
900     //$type = isset($active_modules['announcement']['type'])?$active_modules['announcement']['type']:'setup';
901
902     foreach ($results as $result) {
903         $thisdest = $result['dest'];
904         $thisid   = $result['extension'];
905         $destlist[] = array(
906             'dest' => $thisdest,
907             'description' => sprintf(_("Queue: %s (%s)"),$result['descr'],$thisid),
908             'edit_url' => 'config.php?display=queues&extdisplay='.urlencode($thisid),
909         );
910     }
911     return $destlist;
912 }
913
914 function queue_change_destination($old_dest, $new_dest) {
915     $sql = 'UPDATE queues_config SET dest = "' . $new_dest . '" WHERE dest = "' . $old_dest . '"';
916     sql($sql, "query");
917 }
918
919 function queues_check_compoundrecordings() {
920     global $db;
921
922     $compound_recordings = array();
923     $sql = "SELECT extension, descr, agentannounce_id, ivr_id FROM queues_config WHERE (ivr_id != 'none' AND ivr_id != '') OR agentannounce_id != ''";
924     $results = sql($sql, "getAll",DB_FETCHMODE_ASSOC);
925
926     if (function_exists('ivr_get_details')) {
927         $ivr_details = ivr_get_details();
928         foreach ($ivr_details as $item) {
929             $ivr_hash[$item['id']] = $item;
930         }
931         $check_ivr = true;
932     } else {
933         $check_ivr = false;
934     }
935
936     foreach ($results as $result) {
937         $agentannounce = $result['agentannounce_id'] ? recordings_get_file($result['agentannounce_id']):'';
938         if (strpos($agentannounce,"&") !== false) {
939             $compound_recordings[] = array(
940                                            'extension' => $result['extension'],
941                                                                  'descr' => $result['descr'],
942                                                                  'error' => _("Agent Announce Msg"),
943                                                              );
944         }
945         if ($result['ivr_id'] != 'none' && $result['ivr_id'] != '' && $check_ivr) {
946             $id = $ivr_hash[$result['ivr_id']]['announcement_id'];
947             $announce = $id ? recordings_get_file($id) : '';
948             if (strpos($announce,"&") !== false) {
949                 $compound_recordings[] = array(
950                                                'extension' => $result['extension'],
951                                                                      'descr' => $result['descr'],
952                                                                      'error' => sprintf(_("IVR Announce: %s"),$ivr_hash[$result['ivr_id']]['displayname']),
953                                                                  );
954             }
955         }
956     }
957     return $compound_recordings;
958 }
959
960
961 function queues_get($account, $queues_conf_only=false) {
962     global $db,$astman,$amp_conf;
963     
964     if ($account == "")
965     {
966         return array();
967     }
968
969     $account = q($account);
970     //get all the variables for the queue
971     $sql = "SELECT keyword,data FROM queues_details WHERE id = $account";
972     $results = $db->getAssoc($sql);
973     if (empty($results)) {
974         return array();
975     }
976
977     //okay, but there can be multiple member variables ... do another select for them
978     $sql = "SELECT data FROM queues_details WHERE id = $account AND keyword = 'member' order by flags";
979     $results['member'] = $db->getCol($sql);
980     
981     //if 'queue-youarenext=queue-youarenext', then assume we want to announce position
982     if (!$queues_conf_only) {
983         if(isset($results['queue-youarenext']) && $results['queue-youarenext'] == 'queue-youarenext') {
984             $results['announce-position'] = 'yes';
985         } else {
986             $results['announce-position'] = 'no';
987         }
988     }
989     
990     //if 'eventmemberstatusoff=Yes', then assume we want to 'eventmemberstatus=no'
991     if(isset($results['eventmemberstatusoff'])) {
992         if (strtolower($results['eventmemberstatusoff']) == 'yes') {
993             $results['eventmemberstatus'] = 'no';
994         } else {
995             $results['eventmemberstatus'] = 'yes';
996         }
997     } elseif (!isset($results['eventmemberstatus'])){
998         $results['eventmemberstatus'] = 'no';
999     }
1000
1001     if ($queues_conf_only) {
1002         $sql = "SELECT ivr_id FROM queues_config WHERE extension = $account";
1003         $config = sql($sql, "getRow",DB_FETCHMODE_ASSOC);
1004     } else {
1005         $sql = "SELECT * FROM queues_config WHERE extension = $account";
1006         $config = sql($sql, "getRow",DB_FETCHMODE_ASSOC);
1007
1008         $results['prefix']        = $config['grppre'];
1009         $results['alertinfo']     = $config['alertinfo'];
1010         $results['agentannounce_id'] = $config['agentannounce_id'];
1011         $results['maxwait']       = $config['maxwait'];
1012         $results['name']          = $config['descr'];
1013         $results['joinannounce_id']  = $config['joinannounce_id'];
1014         $results['password']      = $config['password'];
1015         $results['goto']          = $config['dest'];
1016         $results['announcemenu']  = $config['ivr_id'];
1017         $results['rtone']         = $config['ringing'];
1018         $results['cwignore']      = $config['cwignore'];
1019         $results['qregex']        = $config['qregex'];
1020         $results['queuewait']     = $config['queuewait'];
1021         $results['use_queue_context'] = $config['use_queue_context'];
1022         $results['togglehint']    = $config['togglehint'];
1023         $results['qnoanswer']     = $config['qnoanswer'];
1024         $results['callconfirm']    = $config['callconfirm'];
1025         $results['callconfirm_id'] = $config['callconfirm_id'];
1026         $results['monitor_type']   = $config['monitor_type'];
1027         $results['monitor_heard']   = $config['monitor_heard'];
1028         $results['monitor_spoken']   = $config['monitor_spoken'];
1029
1030     // TODO: why the str_replace?
1031     //
1032       if ($astman) {
1033         $account=str_replace("'",'',$account);
1034         //get dynamic members priority from astDB
1035         $get=$astman->database_show('QPENALTY/'.$account.'/agents');
1036         if($get){
1037             foreach($get as $key => $value){
1038                 $key=explode('/',$key);
1039                 $mem[$key[4]]=$value;
1040             }
1041             foreach($mem as $mem => $pnlty){
1042                 $dynmem[]=$mem.','.$pnlty;
1043             }
1044           $results['dynmembers']=implode("\n",$dynmem);
1045         } else {
1046           $results['dynmembers']='';
1047       }
1048         $results['dynmemberonly'] = $astman->database_get('QPENALTY/'.$account,'dynmemberonly');
1049       } else {
1050           fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1051       }
1052     }
1053
1054     $results['context'] = '';
1055     $results['periodic-announce'] = '';
1056
1057     if ($config['ivr_id'] != 'none' && $config['ivr_id'] != '') {
1058         if (function_exists('ivr_get_details')) {
1059             $results['context'] = "ivr-".$config['ivr_id'];
1060             $arr = ivr_get_details($config['ivr_id']);
1061             if( isset($arr['announcement_id']) && $arr['announcement_id'] != '') {
1062                 $periodic = recordings_get_file($arr['announcement_id']);
1063                 // We need to strip off all but the first sound file of any compound sound files
1064                 //
1065                 $periodic_arr = explode("&", $periodic);
1066                 $results['periodic-announce'] = $periodic_arr[0];
1067             }
1068         }
1069     }
1070     return $results;
1071 }
1072 /* Trial DEVSTATE */
1073 function queue_app_toggle($c) {
1074     global $ext;
1075     global $amp_conf;
1076     global $version;
1077
1078     $id = "app-queue-toggle"; // The context to be included
1079     $ext->addInclude('from-internal-additional', $id); // Add the include from from-internal
1080
1081     $c = 's';
1082
1083     $ext->add($id, $c, 'start', new ext_answer(''));
1084     $ext->add($id, $c, '', new ext_wait('1'));
1085     $ext->add($id, $c, '', new ext_macro('user-callerid'));
1086     $ext->add($id, $c, '', new ext_setvar('QUEUESTAT', 'LOGGEDOUT'));
1087     $ext->add($id, $c, '', new ext_agi('queue_devstate.agi,getqueues,${AMPUSER}'));
1088
1089     $ext->add($id, $c, '', new ext_gotoif('$["${QUEUESTAT}" = "LOGGEDOUT"]', 'activate'));
1090     $ext->add($id, $c, '', new ext_gotoif('$["${QUEUESTAT}" = "LOGGEDIN"]', 'deactivate'));
1091     $ext->add($id, $c, '', new ext_gotoif('$["${QUEUESTAT}" = "STATIC"]', 'static','end'));
1092     $ext->add($id, $c, 'deactivate', new ext_noop('Agent Logged out'));
1093     $ext->add($id, $c, '', new ext_macro('toggle-del-agent'));
1094     if ($amp_conf['USEDEVSTATE']) {
1095         $ext->add($id, $c, '', new ext_setvar('STATE', 'NOT_INUSE'));
1096         $ext->add($id, $c, '', new ext_gosub('1', 'sstate'));
1097         }
1098     $ext->add($id, $c, '', new ext_playback('agent-loggedoff'));
1099     $ext->add($id, $c, '', new ext_macro('hangupcall'));
1100
1101     $ext->add($id, $c, 'activate', new ext_noop('Agent Logged In'));
1102     $ext->add($id, $c, '', new ext_macro('toggle-add-agent'));
1103     if ($amp_conf['USEDEVSTATE']) {
1104         $ext->add($id, $c, '', new ext_setvar('STATE', 'INUSE'));
1105         $ext->add($id, $c, '', new ext_gosub('1', 'sstate'));
1106     }
1107     $ext->add($id, $c, '', new ext_playback('agent-loginok'));
1108     $ext->add($id, $c, '', new ext_saydigits('${CALLBACKNUM}'));
1109     $ext->add($id, $c, '', new ext_macro('hangupcall'));
1110
1111     $ext->add($id, $c, 'static', new ext_noop('User is a Static Agent'));
1112     if ($amp_conf['USEDEVSTATE']) {
1113         $ext->add($id, $c, '', new ext_setvar('STATE', 'INUSE'));
1114         $ext->add($id, $c, '', new ext_gosub('1', 'sstate'));
1115     }
1116     $ext->add($id, $c, '', new ext_playback('agent-loginok'));
1117     $ext->add($id, $c, '', new ext_macro('hangupcall'));
1118
1119     if ($amp_conf['USEDEVSTATE']) {
1120         $c = 'sstate';
1121         $ext->add($id, $c, '', new ext_dbget('DEVICES','AMPUSER/${AMPUSER}/device'));
1122         $ext->add($id, $c, '', new ext_gotoif('$["${DEVICES}" = "" ]', 'return'));
1123         $ext->add($id, $c, '', new ext_setvar('LOOPCNT', '${FIELDQTY(DEVICES,&)}'));
1124         $ext->add($id, $c, '', new ext_setvar('ITER', '1'));
1125         $ext->add($id, $c, 'begin', new ext_setvar($amp_conf['AST_FUNC_DEVICE_STATE'].'(Custom:QUEUE${CUT(DEVICES,&,${ITER})}*${QUEUENO})','${STATE}'));
1126         $ext->add($id, $c, '', new ext_setvar('ITER', '$[${ITER} + 1]'));
1127         $ext->add($id, $c, '', new ext_gotoif('$[${ITER} <= ${LOOPCNT}]', 'begin'));
1128         $ext->add($id, $c, 'return', new ext_return());
1129         }
1130 }
1131 function queue_agent_add_toggle() {
1132     global $ext;
1133     global $amp_conf;
1134     global $version;
1135
1136   $ast_ge_14_25 = version_compare($version,'1.4.25','ge');
1137   $ast_ge_18 = version_compare($version,'1.8','ge');
1138     $id = "macro-toggle-add-agent"; // The context to be included
1139
1140     $c = 's';
1141
1142     $ext->add($id, $c, '', new ext_wait('1'));
1143     $ext->add($id, $c, '', new ext_macro('user-callerid,SKIPTTL'));
1144     $ext->add($id, $c, '', new ext_setvar('CALLBACKNUM','${AMPUSER}'));
1145   //TODO: check if it's not a user for some reason and abort?
1146   $ext->add($id, $c, '', new ext_gotoif('$["${DB(QPENALTY/${QUEUENO}/dynmemberonly)}" = "yes" & ${DB_EXISTS(QPENALTY/${QUEUENO}/agents/${CALLBACKNUM})} != 1]', 'invalid'));
1147   if ($ast_ge_18 || $amp_conf['USEQUEUESTATE']) {
1148       $ext->add($id, $c, '', new ext_execif('$["${DB(AMPUSER/${CALLBACKNUM}/queues/qnostate)}" != "ignorestate"]', 'AddQueueMember', '${QUEUENO},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${QUEUENO}/agents/${CALLBACKNUM})},,${DB(AMPUSER/${CALLBACKNUM}/cidname)},hint:${CALLBACKNUM}@ext-local'));
1149       $ext->add($id, $c, '', new ext_execif('$["${DB(AMPUSER/${CALLBACKNUM}/queues/qnostate)}" = "ignorestate"]', 'AddQueueMember', '${QUEUENO},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${QUEUENO}/agents/${CALLBACKNUM})},,${DB(AMPUSER/${CALLBACKNUM}/cidname)}'));
1150
1151   } else if ($ast_ge_14_25) {
1152       $ext->add($id, $c, '', new ext_execif('$["${DB(AMPUSER/${CALLBACKNUM}/queues/qnostate)}" != "ignorestate"]', 'AddQueueMember', '${QUEUENO},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${QUEUENO}/agents/${CALLBACKNUM})},,${DB(AMPUSER/${CALLBACKNUM}/cidname)},${DB(DEVICE/${REALCALLERIDNUM}/dial)}'));
1153       $ext->add($id, $c, '', new ext_execif('$["${DB(AMPUSER/${CALLBACKNUM}/queues/qnostate)}" = "ignorestate"]', 'AddQueueMember', '${QUEUENO},Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${QUEUENO}/agents/${CALLBACKNUM})},,${DB(AMPUSER/${CALLBACKNUM}/cidname)}'));
1154   } else {
1155       $ext->add($id, $c, '', new ext_addqueuemember('${QUEUENO}','Local/${CALLBACKNUM}@from-queue/n,${DB(QPENALTY/${QUEUENO}/agents/${CALLBACKNUM})}'));
1156   }
1157
1158     $ext->add($id, $c, '', new ext_userevent('AgentLogin','Agent: ${CALLBACKNUM}'));
1159     $ext->add($id, $c, '', new ext_macroexit());
1160   $ext->add($id, $c, 'invalid', new ext_playback('pbx-invalid'));
1161     $ext->add($id, $c, '', new ext_macroexit());
1162 }
1163
1164 function queue_agent_del_toggle() {
1165     global $ext;
1166     global $amp_conf;
1167
1168     $id = "macro-toggle-del-agent"; // The context to be included
1169
1170     $c = 's';
1171
1172     $ext->add($id, $c, '', new ext_wait('1'));
1173     $ext->add($id, $c, '', new ext_macro('user-callerid,SKIPTTL'));
1174     $ext->add($id, $c, '', new ext_setvar('CALLBACKNUM','${AMPUSER}'));
1175     $ext->add($id, $c, '', new ext_removequeuemember('${QUEUENO}','Local/${CALLBACKNUM}@from-queue/n'));
1176     $ext->add($id, $c, '', new ext_removequeuemember('${QUEUENO}','Local/${CALLBACKNUM}@from-internal/n'));
1177     $ext->add($id, $c, '', new ext_userevent('RefreshQueue'));
1178     $ext->add($id, $c, '', new ext_macroexit());
1179 }
1180
1181 /************************************************************************************************************
1182  * Hook Exentions/Users to allow an extension to indicate if the Queue should ignore it's state information
1183  * when it is acting as a Queue Member (Agent).
1184  */
1185 function queues_get_qnostate($exten) {
1186     global $astman;
1187
1188     // Retrieve the qnostate configuraiton from this user from ASTDB
1189     if ($astman) {
1190     $qnostate = $astman->database_get("AMPUSER",$exten."/queues/qnostate");
1191     } else {
1192         fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1193     }
1194     // If it's blank, set it to 'usestate'
1195   //
1196     return ($qnostate == 'ignorestate' ? $qnostate : 'usestate');
1197 }
1198
1199 function queues_set_qnostate($exten,$qnostate) {
1200     global $astman;
1201     
1202     // Update the settings in ASTDB
1203   if ($astman) {
1204       $astman->database_put("AMPUSER",$exten."/queues/qnostate",$qnostate);
1205   } else {
1206       fatal("Cannot connect to Asterisk Manager with ".$amp_conf["AMPMGRUSER"]."/".$amp_conf["AMPMGRPASS"]);
1207   }
1208 }
1209
1210 function queues_applyhooks() {
1211     global $currentcomponent;
1212
1213     $currentcomponent->addoptlistitem('qnostate', 'usestate', _('Use State'));
1214     $currentcomponent->addoptlistitem('qnostate', 'ignorestate',_('Ignore State'));
1215     $currentcomponent->setoptlistopts('qnostate', 'sort', false);
1216
1217     // Add the 'process' function - this gets called when the page is loaded, to hook into
1218     // displaying stuff on the page.
1219     $currentcomponent->addguifunc('queues_configpageload',9);
1220
1221 }
1222
1223 function queues_configpageinit($pagename) {
1224     global $currentcomponent;
1225
1226     $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
1227     $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
1228     $extension = isset($_REQUEST['extension'])?$_REQUEST['extension']:null;
1229     $tech_hardware = isset($_REQUEST['tech_hardware'])?$_REQUEST['tech_hardware']:null;
1230
1231     // We only want to hook 'users' or 'extensions' pages.
1232     if ($pagename != 'users' && $pagename != 'extensions')
1233         return true;
1234     // On a 'new' user, 'tech_hardware' is set, and there's no extension. Hook into the page.
1235     if ($tech_hardware != null || $pagename == 'users') {
1236         queues_applyhooks();
1237         $currentcomponent->addprocessfunc('queues_configprocess', 8);
1238     } elseif ($action=="add") {
1239         // We don't need to display anything on an 'add', but we do need to handle returned data.
1240         $currentcomponent->addprocessfunc('queues_configprocess', 8);
1241     } elseif ($extdisplay != '') {
1242         // We're now viewing an extension, so we need to display _and_ process.
1243         queues_applyhooks();
1244         $currentcomponent->addprocessfunc('queues_configprocess', 8);
1245     }
1246 }
1247
1248 // This is called before the page is actually displayed, so we can use addguielem().
1249 function queues_configpageload() {
1250     global $currentcomponent;
1251
1252     // Init vars from $_REQUEST[]
1253     $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
1254     $extdisplay = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
1255     
1256     // Don't display this stuff it it's on a 'This xtn has been deleted' page.
1257     if ($action != 'del') {
1258
1259         $qnostate = queues_get_qnostate($extdisplay);
1260
1261         $section = _('Extension Options');
1262         $currentcomponent->addguielem($section, new gui_selectbox('qnostate', $currentcomponent->getoptlist('qnostate'), $qnostate, _('Queue State Detection'), _("If this extension is part of a Queue then the Queue will attempt to use the user's extension state or device state information when determining if this queue member should be called. In some uncommon situations such as a Follow-Me with no physical device, or some virtual extension scenarios, the state information will indicate that this member is not available when they are. Setting this to 'Ignore State' will make the Queue ignore all state information thus always trying to contact this member. Certain side affects can occur when this route is taken due to the nature of how Queues handle Local channels, such as subsequent transfers will continue to show the member as busy until the original call is terminated. In most cases, this SHOULD BE set to 'Use State'."), false));
1263     }
1264 }
1265
1266 function queues_configprocess() {
1267     //create vars from the request
1268     $action = isset($_REQUEST['action'])?$_REQUEST['action']:null;
1269     $ext = isset($_REQUEST['extdisplay'])?$_REQUEST['extdisplay']:null;
1270     $extn = isset($_REQUEST['extension'])?$_REQUEST['extension']:null;
1271     $qnostate = isset($_REQUEST['qnostate'])?$_REQUEST['qnostate']:null;
1272
1273     if ($ext==='') {
1274         $extdisplay = $extn;
1275     } else {
1276         $extdisplay = $ext;
1277     }
1278     if ($action == "add" || $action == "edit") {
1279         if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true) {
1280       queues_set_qnostate($extdisplay, $qnostate);
1281         }
1282     } // if 'del' then core will remove the entire tree
1283 }
1284 ?>
1285
Note: See TracBrowser for help on using the browser.