root/modules/branches/2.10/directory/agi-bin/directory.lib.php

Revision 13160, 9.9 kB (checked in by mbrevda, 1 year ago)

upstream changes (bug fixes/formating)

Line 
1 <?php
2 //will be enabled when I (or someone) gose through this to ensure that we dont break anything
3 //require_once(getenv('FREEPBX_CONF') ? getenv('FREEPBX_CONF') : '/etc/freepbx.php');
4
5 class Dir{
6     //agi class handler
7     var $agi;
8     //inital agi pased variables
9     var $agivar;   
10     //asterisk manager class handler
11     var $ami;
12     //pear::db database object handel
13     var $db;
14     //options of the directory that we are currently working with
15     var $dir;
16     //the current directory that we are working with
17     var $directory;
18     //string we are searching for
19     var $searchstring;
20     //TODO: what is this var for?
21     var $vmbasedir='';
22     
23   //PHP4 comaptibility constructor
24   function Dir(){
25     $this->__construct();
26   }
27
28     //this function is run by php automaticly when the class is initalized
29     function __construct(){
30         $this->agi=$this->__construct_agi();
31         //$this->ami=$this->__construct_ami();
32         $this->db=$this->__construct_db();
33         //$this->agivars=$this->__construct_inital_vars();
34         $this->directory=$this->agivar['dir'];
35         $this->dir=$this->__construct_dir_opts();
36     }
37     
38     //get agi handel/inital agi vars, called by __construct()
39     function __construct_agi(){
40         require_once('phpagi.php');
41         $agi=new AGI();
42         foreach($agi->request as $key => $value){//strip agi_ prefix from keys
43             if(substr($key,0,4)=='agi_'){
44                 $opts[substr($key,4)]=$value;
45             }
46         }
47
48         foreach($opts as $key => $value){//get passed in vars
49             if(substr($key,0,4)=='arg_'){
50                 $expld=explode('=',$value);
51                 $opts[$expld[0]]=$expld[1];
52                 unset($opts[$key]);
53             }
54         }
55         
56         array_shift($_SERVER['argv']);
57         foreach($_SERVER['argv'] as $arg){
58             $arg=explode('=',$arg);
59             //remove leading '--'
60             if(substr($arg['0'],0,2) == '--'){$arg['0']=substr($arg['0'],2);}
61             $opts[$arg['0']]=isset($arg['1'])?$arg['1']:null;
62         }
63         $this->agivar=$opts;
64         return $agi;
65     }
66     
67     //get ami handel, called by __construct()
68     function __construct_ami(){
69         require_once('phpagi-asmanager.php');
70         $ami=new AGI_AsteriskManager();
71         return $ami;
72     }   
73     
74     //get database handle, called by __construct()
75   // TODO: hardcoded mysql, deal with sqlite...
76   //
77     function __construct_db(){
78         require_once("DB.php");
79         $dsn=array(
80             'phptype'  => $this->agi_get_var('AMPDBENGINE'),
81             'hostspec' => $this->agi_get_var('AMPDBHOST'),
82             'database' => $this->agi_get_var('AMPDBNAME'),
83             'username' => $this->agi_get_var('AMPDBUSER'),
84             'password' => $this->agi_get_var('AMPDBPASS'),
85         );
86         $db=DB::connect($dsn);
87         return $db;
88     }
89     
90     //get options associated with the current dir
91      // TODO: handle getRow failures
92     function __construct_dir_opts(){
93         $sql='SELECT * FROM directory_details WHERE ID = ?';
94         $row=$this->db->getRow($sql,array($this->directory),DB_FETCHMODE_ASSOC);
95         //TODO: Error Checking
96
97         //If any non-defaults (non-zero id) then lookup files
98          //
99         if ($row['announcement'] || $row['repeat_recording'] || $row['invalid_recording']) {
100             $sql='SELECT id, filename from recordings where id in ('.$row['announcement'].','.$row['repeat_recording'].','.$row['invalid_recording'].')';
101             $res=$this->db->getAll($sql,DB_FETCHMODE_ASSOC);
102             if(DB::IsError($res)) {
103                 dbug("FATAL: got error from getAll query",1);
104                 dbug($res->getDebugInfo());
105             }
106             $rec_file = array();
107             foreach ($res as $entry) {
108                 //TODO: check if file exists, which means splitting on & and checkking all
109                 $rec_file[$entry['id']] = $entry['filename'];
110             }
111             unset($res);
112         }
113         $row['announcement'] = $row['announcement']&&isset($rec_file[$row['announcement']])?$rec_file[$row['announcement']]:'cdir-please-enter-first-three';
114         $row['repeat_recording'] = $row['repeat_recording']&&isset($rec_file[$row['repeat_recording']])?$rec_file[$row['repeat_recording']]:'cdir-sorry-no-entries';
115         $row['invalid_recording'] = $row['invalid_recording']&&isset($rec_file[$row['invalid_recording']])?$rec_file[$row['invalid_recording']]:'cdir-transferring-further-assistance';
116         return $row;
117     }
118
119     //get a channel varibale   
120     function agi_get_var($var){
121         global $agi_cache;
122         if (isset($agi_cache[$var])) {
123             return $agi_cache[$var];
124         }
125         $ret=$this->agi->get_variable($var);
126         if($ret['result']==1){
127             $result=$ret['data'];
128             $agi_cache[$var] = $result;
129             return $result;
130         }else{
131             return '';
132         }
133     }
134
135     // Return null on nothing pressed, false on error, otherwise the key
136     // TODO: make it so you can pass in an array:
137     //
138     function getKeypress($filename, $pressables='', $timeout=2000){
139         if (!is_array($filename)) {
140             $filename = array($filename);
141         }
142         foreach ($filename as $chunk) {
143             $ret=is_int($chunk)?$this->agi->say_number($chunk,$pressables):$this->agi->stream_file($chunk,$pressables);
144             if(!empty($ret['result'])) {break;}
145         }
146         if(empty($ret['result'])){
147             $ret=$this->agi->wait_for_digit($timeout);
148         }
149         switch ($ret['result']) {
150             case 0:
151                 return null;
152             case -1:
153                 return false;
154             default:
155                 return chr($ret['result']);
156         }
157     }
158     
159     function readContact($con, $keys='#'){
160         switch($con['audio']){
161             case 'vm':
162                 $vm_dir = $this->agi->database_get('AMPUSER',$con['dial'].'/voicemail');
163                 $vm_dir = $vm_dir['data'];
164                 dbug('got directory ' . $vm_dir . ' for user ' . $con['dial']);
165                 //check to see if we have a greet.* and play it. otherwise, fallback to spelling the name
166
167                 if ($vm_dir && $vm_dir != 'novm') {
168                     if (!$this->vmbasedir) {
169                         $this->vmbasedir = $this->agi_get_var('ASTSPOOLDIR').'/voicemail/';
170                     }
171                     
172                     $dir=scandir($this->vmbasedir.$vm_dir.'/'.$con['dial']);
173                     foreach($dir as $file){
174                         dbug("looking for vm file $file using: ".basename($file),6);
175                         if(substr($file,0,5) == 'greet' && is_file($this->vmbasedir.$vm_dir.'/'.$con['dial'].'/'.$file)){
176                             $ret=$this->agi->stream_file($this->vmbasedir.$vm_dir.'/'.$con['dial'].'/greet',$keys);
177                             if ($ret['result']) {
178                                 $ret['result']=chr($ret['result']);
179                             }
180                             break 2;   
181                         }   
182                     }
183                 }
184                 //fallthough if not successfull
185             case 'spell':
186                 foreach(str_split(strtolower($con['name']),1) as $char){
187                     dbug('saying '.$char.' from string '.strtolower($con['name']));
188                     switch(true){
189                         case ctype_alpha($char):
190                             $ret = $this->agi->evaluate('SAY ALPHA '.$char.' '.$keys);
191                             dbug("returned from SAY ALPHA with code/result {$ret['code']}/{$ret['result']}",6);
192                             break;
193                         case ctype_digit($char):
194                             $ret = $this->agi->say_digits($char, $keys);
195                             break;
196                         case ctype_space($char)://pause
197                             $ret = $this->agi->wait_for_digit(750);
198                             break;                   
199                     }
200                     if(trim($ret['result'])) {
201                         $ret['result'] = chr($ret['result']);
202                         break;
203                     }
204                 }
205                 break;
206                 //TODO: BUG: hardcoded to Flite, needs to either check what is there or be configurable
207                 //we dont call the flite app cirectly as it still uses | as a parameter separator
208             case 'tts':
209                 $tmp = $this->agi_get_var('ASTSPOOLDIR') . '/tmp/directory-tts-' . time() . rand(100, 999);
210                 system('flite -t "' . $con['name'] .'" -o ' . $tmp . '.wav', $exit_code);
211                 if ($exit_code === 0) {
212                         $ret = $this->agi->stream_file($tmp, $keys);
213                         if ($ret['result']) {
214                             $ret['result'] = chr($ret['result']);
215                         }
216                         unlink($tmp . '.wav');
217                 } else {
218                     $ret = array('result' => '');
219                 }
220     
221                 break;
222             default:
223                 if(is_numeric($con['audio'])){
224                     $sql='SELECT filename from recordings where id = ?';
225                     $rec=$this->db->getOne($sql, array($con['audio']));
226                     dbug("got record id: {$con['audio']} file(s): $rec");
227                     if($rec){
228                         $rec=explode('&',$rec);
229                         foreach($rec as $r){
230                             $ret=$this->agi->stream_file($r,$keys);
231                             if(trim($ret['result'])){$ret['result']=chr($ret['result']);break;}
232                         }
233                     } else {
234                         //TODO: handle error
235                         dbug("ERROR: unknown/undefined sound file");
236                     }
237                 }
238                 break;
239             }
240             return $ret;
241         }
242     
243     function search($key,$count=0){
244         if($key == ''){return false;}//requre search term
245
246         if(strstr($key,'0') !== false) {
247             dbug("user pressed 0 - bailing out");
248             $this->bail();
249         }
250
251         //the regex in the query will match the searchstring at the beging of the string or after a space
252         $num= array('1','2','3','4','5','6','7','8','9','0','#');
253         $alph=array("[ \s@,-\!/+=\.']",'[abcABC]','[defDEF]','[ghiGHI]','[jklJKL]','[mnoMNO]','[pqrsPQRS]','[tuvTUV]','[wxyzWXYZ]','','');
254         $this->searchstring=$this->db->escapeSimple(str_replace($num,$alph,$key));
255         dbug("search string for regex: {$this->searchstring}");
256
257         //TODO: check db results for errors and fail gracefully
258
259         $vtable = '(SELECT DISTINCT a.audio, IF(a.name != "",a.name,b.name) name, IF(a.dial != "",a.dial,b.extension) dial FROM directory_entries a LEFT JOIN users b ON a.foreign_id = b.extension WHERE id = "'.$this->directory.'") v';
260         if($count==1){
261             $sql="SELECT COUNT(*) FROM $vtable WHERE name REGEXP \"(^| ){$this->searchstring}\"";
262             $res=$this->db->getOne($sql);
263             if(DB::IsError($res)) {
264                 dbug("FATAL: got error from COUNT(*) query");
265                 dbug($res->getDebugInfo());
266             }
267             dbug("Found $res possible matches from $key");
268         }else{
269             $sql="SELECT * FROM $vtable WHERE name REGEXP \"(^| ){$this->searchstring}\"";
270             $res=$this->db->getAll($sql,DB_FETCHMODE_ASSOC);
271             if(DB::IsError($res)) {
272                 dbug("FATAL: got error from getAll query");
273                 dbug($res->getDebugInfo());
274             } else {
275                 dbug("Found the following matches:");
276                 foreach ($res as $ent) {
277                     dbug("name: {$ent['name']}, audio: {$ent['audio']}, dial: {$ent['dial']}");
278                 }
279             }
280         }
281         return $res;
282     }
283
284     function bail() {
285         //do something if we are exiting due to to many tries
286         //
287         dbug("User pressed zero, passing back recording of {$this->dir['invalid_recording']}");
288         $this->agi->set_variable('DIR_INVALID_RECORDING',$this->dir['invalid_recording']);
289         if($this->agi_get_var('IVR_CONTEXT')){
290             $this->agi->set_extension('retivr');
291         }else{
292              $dest = explode(',',$this->dir['invalid_destination']);
293             $this->agi->set_variable('DIR_INVALID_CONTEXT',$dest['0']);
294             $this->agi->set_variable('DIR_INVALID_EXTEN',$dest['1']);
295             $this->agi->set_variable('DIR_INVALID_PRI',$dest['2']);
296             $this->agi->set_extension('invalid');
297         }
298         $this->agi->set_priority('1');
299         exit;
300     }
301 }
302
303 ?>
304
Note: See TracBrowser for help on using the browser.