source: trunk/prototype/services/ImapServiceAdapter.php @ 5604

Revision 5604, 18.5 KB checked in by cristiano, 12 years ago (diff)

Ticket #2497 - Nova estrategia para o salvamento automatico de rascunhos

Line 
1<?php
2
3include_once ROOTPATH."/../expressoMail1_2/inc/class.imap_functions.inc.php";
4
5class ImapServiceAdapter extends imap_functions/* implements Service*/
6{
7    public function open( $config )
8    {
9                $this->init();
10    }
11
12//     public function connect( $config )
13//     {
14//                      $this->init();
15//     }
16       
17    public function find( $URI, $justthese = false, $criteria = false )
18        {
19                $context = $justthese['context'];
20                $URI = $URI['concept'];
21
22                switch( $URI )
23                {
24                        case 'folder':
25                        {
26                                $result = $this->to_utf8($this->get_folders_list());
27
28                                foreach ($result as $res) {
29
30                                        $response[] = array(
31                                                        'id' => $res['folder_id'],
32                                                        'commonName' => $res['folder_name'],
33                                                        'parentFolder' => $res['folder_parent'],
34                                                        'messageCount' => array('unseen' => isset($res['folder_unseen']) ? $res['folder_unseen'] : null, 'total' => null)
35                                                );
36                                }
37
38                                return $response;
39                        }
40                        case 'message':
41                        {
42                                //begin: for grid       
43                                $page  = $criteria['page']; //{1}    get the requested page
44                                $limit = $criteria['rows']; //{10}   get how many rows we want to have into the grid
45                                $sidx  = $criteria['sidx']; //{id}   get index row - i.e. user click to sort
46                                $sord  = $criteria['sord']; //{desc} get the direction
47
48                                $filter = $criteria['filter'];
49
50                                if( !$sidx ) $sidx = 1;
51
52                                $folder_name = str_replace( '.', $this->imap_delimiter, $context['folder'] );
53                               
54                                $count = imap_num_msg( $this->open_mbox( $folder_name ) );
55
56                                $total_pages = $count > 0 ? ceil( $count/$limit ) : 0;
57
58                                if( $page > $total_pages )
59                                        $page = $total_pages;
60
61                                $start = $limit * $page - $limit;
62
63                                // do not put $limit*($page - 1)
64                                //end: for grid
65
66                                if( $filter )
67                                {
68                                        if( $filter[0] !== 'msgNumber' )
69                                        {
70                                        for( $i = 0; $i < count($filter); $i++ )
71                                        {
72                                                if( count( $filter[$i] ) === 4 )
73                                                $criteria['isExact'] = ( array_shift( $filter[$i] ) === 'AND' );
74
75                                                $criteria[ $filter[$i][0] ] = array( 'criteria' => $filter[$i][2], 'filter' => $filter[$i][1] );
76                                        }
77
78                                        return $this->searchSieveRule($criteria);
79                                        }
80
81                                        $msgNumber = array();
82
83                                        for( $i = $start; $i < $start + $limit && isset( $filter[2][$i] ); $i++ )
84                                          $msgNumber[] = $filter[2][$i];
85
86                                        if( empty( $msgNumber ) )
87                                        return( false );
88
89                                        $result = $this->get_info_msgs( array( 'folder' => $folder_name,
90                                                                           'msgs_number' => implode( ',', $msgNumber ) ) );
91
92                                        foreach( $result as $i => $val )
93                                        $result[$i] = unserialize( $val );
94
95                                }
96                                else
97                                {
98                                        $result = $this->get_range_msgs2(
99                                                array(
100                                                        'folder' => $folder_name, //INBOX
101                                                        'msg_range_begin' => $start + 1, //??
102                                                        'msg_range_end' => $start + $limit, //$limit = $_GET['rows']; // get how many rows we want to have into the grid
103                                                        'sort_box_type' => 'SORTARRIVAL',
104                                                        'search_box_type' => 'ALL',
105                                                        'sort_box_reverse' => 1
106                                                )
107                                        );
108                                }
109                                //return var_export($result);
110
111                                $response = array( "page" => $page, "total" => $total_pages, "records" => $count );
112                               
113                                for ($i=0; $i<count($result); $i++)
114                                {
115                                        $flags_enum = array('Recent', 'Unseen',  'Answered',  'Draft',  'Deleted', 'Flagged');
116
117                                        foreach ($flags_enum as $key => $flag)
118                                        {
119                                                if ( !isset($result[$i][$flag]) || !trim($result[$i][$flag]) || trim($result[$i][$flag]) == '')
120                                                        unset($flags_enum[$key]);
121
122                                                unset($result[$i][$flag]);
123                                        }
124
125                                        if (array_key_exists($i, $result))
126                                        {
127                                                $response["rows"][$i] = $result[$i];
128                                                $response["rows"][$i]['timestamp'] = ( ( $result[$i]['udate'] + $this->functions->CalculateDateOffset() ) * 1000 );
129                                                $response["rows"][$i]['flags'] = implode(',', $flags_enum);
130                                                $response["rows"][$i]['size'] = $response["rows"][$i]['Size'];
131                                                //$response["rows"][$i]['udate'] = ( $result[$i]['udate'] + $this->functions->CalculateDateOffset()  * 1000 );
132                                                unset($response["rows"][$i]['Size']);
133                                        }
134                                 }
135
136                                return $this->to_utf8($response);
137                        }
138                       
139                        /**
140                         * Filtros suportados:
141                         * - ['=', 'folderName', $X]
142                         * - [
143                         *              'AND',
144                         *              [
145                         *                      'AND',
146                         *                      ['=', 'folderName', $X],
147                         *                      ['IN', 'messageNumber', $Ys]
148                         *              ],
149                         *              ['IN', 'labelId', $Zs]
150                         * ]
151                         * - ['=', 'labelId', $X]
152                         * - [
153                         *              'AND',
154                         *              ['=', 'folderName', $X],
155                         *              ['=', 'labelId', $Y]
156                         * ]
157                         * - ['IN', 'labelId', $Ys]
158                         * - [
159                         *              'AND',
160                         *              ['=', 'folderName', $X],
161                         *              ['IN', 'labelId', $Ys]
162                         * ]                   
163                         */
164                        case 'labeled':
165                        {
166                                $result = array ( );
167                                if (isset($criteria["filter"]) && is_array($criteria['filter'])) {
168                                        //TODO - melhorar o tratamento do filter com a lista de todos os labelIds dado pelo interceptor
169                                        $map = array(
170                                                'id' => array(),
171                                                'folderName' => array(),
172                                                'messageNumber' => array(),
173                                                'labelId' => array()
174                                        );
175                                       
176                                        self::parseFilter($criteria["filter"], &$map);
177                                       
178                                        if (count($map['folderName']) == 0) {
179                                                $folders = $this->get_folders_list();
180                                                foreach ($folders as $folder)
181                                                        if (isset($folder['folder_id']))
182                                                                $map['folderName'][] = $folder['folder_id'];
183                                        }
184
185                                        foreach ($map['folderName'] as $folder) {
186                                                $this->mbox = $this->open_mbox($folder);
187                                               
188                                                foreach ($map['labelId'] as $label) {
189                                                        $messagesLabeleds = imap_search($this->mbox, 'UNDELETED KEYWORD "$Label'.$label.'"', SE_UID);
190                                                       
191                                                        foreach ($messagesLabeleds as $messageLabeled) {
192                                                                if (count($map['messageNumber']) > 0 && !in_array($messageLabeled, $map['messageNumber']))
193                                                                        continue;
194                                                                       
195                                                                $result[] = array (
196                                                                        'id' => $folder . '/' . $messageLabeled . '#' . $label,
197                                                                        'folderName' => $folder,
198                                                                        'messageNumber' => $messageLabeled,
199                                                                        'labelId' => $label
200                                                                );
201                                                        }
202                                                }
203                                               
204                                                imap_close($this->mbox);
205                                                $this->mbox = false;
206                                        }
207                                }
208                               
209                                return $result;
210                        }
211                       
212                        case 'followupflagged':
213                        {
214                       
215                                $result = array ( );
216                                if (isset($criteria["filter"]) && is_array($criteria['filter'])) {
217                                        //TODO - melhorar o tratamento do filter com a lista de todos os labelIds dado pelo interceptor
218                                        $map = array(
219                                                'id' => array(),
220                                                'folderName' => array(),
221                                                'messageNumber' => array()
222                                        );
223                                       
224                                        self::parseFilter($criteria["filter"], &$map);
225                                       
226                                        if (empty($map['folderName'])) {
227                                                $folders = $this->get_folders_list();
228                                                foreach ($folders as $folder)
229                                                        if (isset($folder['folder_id']))
230                                                                $map['folderName'][] = $folder['folder_id'];
231                                        }
232
233                                        foreach ($map['folderName'] as $folder) {
234                                                $this->mbox = $this->open_mbox($folder);
235                                               
236                                                foreach ($map['id'] as $followupflagged) {
237                                                        $messagesFlaggeds = imap_search($this->mbox, 'UNDELETED KEYWORD "$Followupflag'.$followupflagged.'"', SE_UID);
238                                                       
239                                                        foreach ($messagesFlaggeds as $messageFlagged) {
240                                                                if (count($map['messageNumber']) > 0 && !in_array($messageFlagged, $map['messageNumber']))
241                                                                        continue;
242                                                                       
243                                                                $result[] = array (
244                                                                        'id' => $folder . '/' . $messageFlagged . '#' . $followupflagged,
245                                                                        'folderName' => $folder,
246                                                                        'messageNumber' => $messageFlagged
247                                                                );
248                                                        }
249                                                }
250                                               
251                                                imap_close($this->mbox);
252                                                $this->mbox = false;
253                                        }
254                                }
255                                               
256                                return $result;                         
257                        }
258                }
259    }
260
261    public function read( $URI, $justthese = false )
262    {
263
264                switch( $URI['concept'] )
265                {
266                        case 'message':
267                        {
268                                return $this->to_utf8(
269                                        $this->get_info_msg( array('msg_number'=>$URI['id'],
270                                        'msg_folder'=>str_replace( '.', $this->imap_delimiter, $justthese['context']['folder'] )) )
271                                );
272                        }
273                        case 'labeled':
274                        {
275                                /**
276                                 * id looks like 'folder/subfolder/subsubfolder/65#13', meaning messageId#labelId
277                                 */
278                                list($messageId, $labelId) = explode('#', $URI['id']);
279                                $folderName = basename($messageId);
280                                $messageNumber = dirname($messageId);
281                               
282                                $result = array();
283
284                                if ($folderName && $messageNumber && $labelId) {
285                                        $this->mbox = $this->open_mbox($folderName);
286                                        $messagesLabeleds = imap_search($this->mbox, 'UNDELETED KEYWORD "$Label'.$labelId.'"', SE_UID);
287                                       
288                                        if (in_array($messageNumber, $messagesLabeleds)) {
289                                                $result = array (
290                                                        'id' => $URI['id'],
291                                                        'folderName' => $folderName,
292                                                        'messageNumber' => $messageNumber,
293                                                        'labelId' => $labelId
294                                                );
295                                        }
296                                        imap_close($this->mbox);
297                                        $this->mbox = false;
298                                }
299                               
300                                return $result;
301                        }
302                       
303                        case 'followupflagged':
304                        {
305                                /**
306                                 * id looks like 'folder/subfolder/subsubfolder/65#13', meaning messageId#followupflaggedId
307                                 */
308                                list($messageId, $followupflaggedId) = explode('#', $URI['id']);
309                                $folderName = basename($messageId);
310                                $messageNumber = dirname($messageId);
311                               
312                                $result = array();
313
314                                if ($folderName && $messageNumber && $followupflaggedId) {
315                                        $this->mbox = $this->open_mbox($folderName);
316                                        $messagesFlaggeds = imap_search($this->mbox, 'UNDELETED KEYWORD "$Followupflag'.$followupflaggedId.'"', SE_UID);
317                                       
318                                        if (in_array($messageNumber, $messagesFlaggeds)) {
319                                                $result = array (
320                                                        'id' => $URI['id'],
321                                                        'folderName' => $folderName,
322                                                        'messageNumber' => $messageNumber
323                                                );
324                                        }
325                                        imap_close($this->mbox);
326                                        $this->mbox = false;
327                                }
328                               
329                                return $result;
330                        }
331                }
332    }
333
334    public function create( $URI, $data)
335    {               
336                switch( $URI['concept'] )
337                {
338                        case 'labeled':
339                        {
340                                if (isset($data['folderName']) && isset($data['messageNumber']) && isset($data['labelId'])) {
341                                        $this->mbox = $this->open_mbox($data['folderName']);
342                                        imap_setflag_full($this->mbox, $data['messageNumber'], '$Label' . $data['labelId'], ST_UID);
343
344                                        imap_close($this->mbox);
345                                        $this->mbox = false;
346
347                                        return array ('id' => $data['folderName'].'/'.$data['messageNumber'].'#'.$data['labelId']);
348                                }
349                                return array ();
350                        }
351                        case 'followupflagged':
352                        {
353                                //deve ser gravado no banco primeiro, obtido o id e, depois, gravado no imap passando o id no parametro $data
354                                if (isset($data['folderName']) && isset($data['messageNumber']) && isset($data['id'])) {
355                                        list($messageId, $followupflaggedId) = explode('#', $data['id']);
356                                       
357                                        $this->mbox = $this->open_mbox($data['folderName']);
358                                        imap_setflag_full($this->mbox, $data['messageNumber'], '$Followupflag' . $followupflaggedId, ST_UID);
359
360                                        imap_close($this->mbox);
361                                        $this->mbox = false;
362
363                                        return array ('id' => $data['id']);
364                                }
365                                return array ();
366                        }
367                        case 'message':
368                        {
369                                $GLOBALS['phpgw_info']['flags'] = array( 'noheader' => true, 'nonavbar' => true,'currentapp' => 'expressoMail1_2','enable_nextmatchs_class' => True );
370                                $return = array();
371
372                                require_once dirname(__FILE__) . '/../../services/class.servicelocator.php';
373                                $mailService = ServiceLocator::getService('mail');
374
375                                $msg_uid = $data['msg_id'];
376                                $body = $data['body'];
377                                $body = str_replace("%nbsp;","&nbsp;",$body);
378                                $body = preg_replace("/\n/"," ",$body);
379                                $body = preg_replace("/\r/","" ,$body);
380                                $body = html_entity_decode ( $body, ENT_QUOTES , 'ISO-8859-1' );                                       
381
382                                $folder = mb_convert_encoding($data['folder'], "UTF7-IMAP","ISO-8859-1, UTF-8");
383                                $folder = @eregi_replace("INBOX[/.]", "INBOX".$this->imap_delimiter, $folder);
384
385                                $mailService->addTo($data['input_to']);
386                                $mailService->addCc( $data['input_cc']);
387                                $mailService->addBcc($data['input_cco']);
388                                $mailService->setSubject($data['input_subject']);
389
390                                if(isset($data['input_important_message']))
391                                        $mailService->addHeaderField('Importance','High');
392
393                                if(isset($data['input_return_receipt']))
394                                        $mailService->addHeaderField('Disposition-Notification-To', Config::me('mail'));
395
396                                $isHTML = ( ( array_key_exists( 'type', $data ) && in_array( strtolower( $data[ 'type' ] ), array( 'html', 'plain' ) ) ) ? strtolower( $data[ 'type' ] ) != 'plain' : true );
397
398                                if (!$body) $body = ' ';
399                               
400
401                                $mbox_stream = $this->open_mbox($folder);
402
403                                $attachment = json_decode($data['attachments'],TRUE);
404                               
405
406                                foreach ($attachment as &$value)
407                                {
408
409                                    if((int)$value > 0) //BD attachment
410                                    {
411                                         $att = Controller::read(array('id'=> $value , 'concept' => 'mailAttachment'));
412                                         
413                                         if($att['disposition'] == 'embedded')
414                                         {
415                                             $body = str_replace('"../prototype/getArchive.php?mailAttachment='.$att['id'].'"', $att['name'], $body);
416                                             $mailService->addStringImage(base64_decode($att['source']), $att['type'], $att['name']);
417                                         }
418                                         else
419                                             $mailService->addStringAttachment(base64_decode($att['source']), $att['name'], $att['type'], 'base64', isset($att['disposition']) ? $att['disposition'] :'attachment' );
420                                         
421                                         unset($att);
422                                    }
423                                    else //message attachment
424                                    {
425                                        $value = json_decode($value, true);
426                                        $sub =  $value['name'] ? $value['name'].'.eml' :'no title.eml';
427                                        $mbox_stream = $this->open_mbox($value['folder']);
428                                        $rawmsg = $this->getRawHeader($value['uid']) . "\r\n\r\n" . $this->getRawBody($value['uid']);
429                                        $mailService->addStringAttachment($rawmsg, $sub, 'message/rfc822', '7bit', 'attachment' );
430                                        unset($rawmsg);
431                                    }
432
433                                }
434                               
435                                if($isHTML) $mailService->setBodyHtml($body); else $mailService->setBodyText($body);
436                                                         
437                                if(imap_append($mbox_stream, "{".$this->imap_server.":".$this->imap_port."}".$folder, $mailService->getMessage(), "\\Seen \\Draft"))
438                                {
439                                    $status = imap_status($mbox_stream, "{".$this->imap_server.":".$this->imap_port."}".$folder, SA_UIDNEXT);
440                                    $return['id'] = $status->uidnext - 1;
441                                       
442                                    if($data['uidsSave'] )
443                                        $this->delete_msgs(array('folder'=> $folder , 'msgs_number' => $data['uidsSave']));
444                       
445                                }
446                 
447                                if($mbox_stream) imap_close($mbox_stream);
448                               
449                               
450                               
451                                return $return;
452                        }
453                }
454        }
455
456    public function delete( $URI, $justthese = false, $criteria = false )
457    {
458                switch( $URI['concept'] )
459                {
460                        case 'labeled':
461                        {
462                                list($messageId, $labelId) = explode('#', $URI['id']);
463                                $folderName = dirname($messageId);
464                                $messageNumber = basename($messageId);
465
466                                if ($folderName && $messageNumber && $labelId) {
467                                        $this->mbox = $this->open_mbox($folderName);
468                                        imap_clearflag_full($this->mbox, $messageNumber, '$Label' . $labelId, ST_UID);
469
470                                        imap_close($this->mbox);
471                                        $this->mbox = false;
472                                }
473                        }
474                        case 'followupflagged':
475                        {
476                                list($messageId, $followupflaggedId) = explode('#', $URI['id']);
477                                $folderName = basename($messageId);
478                                $messageNumber = dirname($messageId);
479                       
480                                if ($folderName && $messageNumber && $followupflaggedId) {
481                                        $this->mbox = $this->open_mbox($folderName);
482                                        imap_clearflag_full($this->mbox, $messageNumber, '$Followupflag' . $followupflaggedId, ST_UID);
483
484                                        imap_close($this->mbox);
485                                        $this->mbox = false;
486                                }
487                        }
488                }
489
490                //TODO - return
491        }
492
493    public function deleteAll( $URI, $justthese = false, $criteria = false ) // avaliar
494    {}
495
496    public function update( $URI, $data, $criteria = false )
497    {
498                /**
499                 * Os únicos atributos que podem ser alterados no IMAP são folderName e messageId,
500                 * porém a operação de update desses atributos não faz sentido para o usuário da DataLayer,
501                 * pois na prática elas são executadas através das operações de CREATE e DELETE.
502                 * Assim, para os conceitos "labeled" e "followupflagged", só faz sentido o update de
503                 * atributos gravados no banco de dados e nunca no IMAP.
504                 */
505        }
506
507//     public function retrieve( $concept, $id, $parents, $justthese = false, $criteria = false )
508//     {
509//                      return $this->read( array( 'id' => $id,
510//                          'concept' => $concept,
511//                          'context' => $parents ), $justthese );
512//     }
513
514    public function replace( $URI, $data, $criteria = false )
515    {}
516
517    public function close()
518    {}
519
520    public function setup()
521    {}
522
523    public function commit( $uri )
524    { return( true ); }
525
526    public function rollback( $uri )
527    {}
528
529    public function begin( $uri )
530    {}
531
532
533    public function teardown()
534    {}
535
536    function to_utf8($in)
537    {
538                if (is_array($in)) {
539                        foreach ($in as $key => $value) {
540                                $out[$this->to_utf8($key)] = $this->to_utf8($value);
541                        }
542                } elseif(is_string($in)) {
543                                return mb_convert_encoding( $in , 'UTF-8' , 'UTF-8 , ISO-8859-1' );
544                } else {
545                        return $in;
546                }
547                return $out;
548    }
549       
550           
551    private static function parseFilter( $filter ,&$map){
552               
553                if( !is_array( $filter ) || count($filter) <= 0) return null;
554                                       
555                $op = array_shift( $filter );
556                switch(strtolower($op))
557                {
558                        case 'and': {
559                                foreach ($filter as $term)
560                                        self::parseFilter($term ,&$map);
561                                return;
562                        }
563                        case 'in': {
564                                if(is_array($map[$filter[0]]) && is_array($filter[1]))
565                                        $map[$filter[0]] = array_unique(array_merge($map[$filter[0]], $filter[1]));
566                                return;
567                        }
568                        case '=': {
569                                $map[$filter[0]][] = $filter[1];
570                        }
571                }
572        }
573       
574}
Note: See TracBrowser for help on using the repository browser.