Aleksander Machniak
2016-05-16 0b7e26c1bf6bc7a684eb3a214d92d3927306cd8a
commit | author | age
48e9c1 1 <?php
T 2
3 /**
4  * Archive
5  *
6  * Plugin that adds a new button to the mailbox toolbar
7  * to move messages to a (user selectable) archive folder.
8  *
7fce8f 9  * @version 2.3
48e9c1 10  * @license GNU GPLv3+
110759 11  * @author Andre Rodier, Thomas Bruederli, Aleksander Machniak
48e9c1 12  */
T 13 class archive extends rcube_plugin
14 {
15   function init()
16   {
17     $rcmail = rcmail::get_instance();
18
dc0b50 19     // register special folder type
AM 20     rcube_storage::$folder_types[] = 'archive';
21
48e9c1 22     if ($rcmail->task == 'mail' && ($rcmail->action == '' || $rcmail->action == 'show')
dc0b50 23         && ($archive_folder = $rcmail->config->get('archive_mbox'))
AM 24     ) {
48e9c1 25       $skin_path = $this->local_skin_path();
T 26       if (is_file($this->home . "/$skin_path/archive.css"))
27         $this->include_stylesheet("$skin_path/archive.css");
28
29       $this->include_script('archive.js');
30       $this->add_texts('localization', true);
31       $this->add_button(
32         array(
33             'type' => 'link',
34             'label' => 'buttontext',
35             'command' => 'plugin.archive',
36             'class' => 'button buttonPas archive disabled',
37             'classact' => 'button archive',
38             'width' => 32,
39             'height' => 32,
40             'title' => 'buttontitle',
41             'domain' => $this->ID,
42         ),
43         'toolbar');
22d48c 44
48e9c1 45       // register hook to localize the archive folder
T 46       $this->add_hook('render_mailboxlist', array($this, 'render_mailboxlist'));
47
67cb01 48       // set env variables for client
48e9c1 49       $rcmail->output->set_env('archive_folder', $archive_folder);
67cb01 50       $rcmail->output->set_env('archive_type', $rcmail->config->get('archive_type',''));
TB 51     }
52     else if ($rcmail->task == 'mail') {
53       // handler for ajax request
54       $this->register_action('plugin.move2archive', array($this, 'move_messages'));
48e9c1 55     }
T 56     else if ($rcmail->task == 'settings') {
57       $dont_override = $rcmail->config->get('dont_override', array());
58       if (!in_array('archive_mbox', $dont_override)) {
59         $this->add_hook('preferences_list', array($this, 'prefs_table'));
60         $this->add_hook('preferences_save', array($this, 'save_prefs'));
61       }
62     }
63   }
67cb01 64
TB 65   /**
66    * Hook to give the archive folder a localized name in the mailbox list
67    */
48e9c1 68   function render_mailboxlist($p)
T 69   {
70     $rcmail = rcmail::get_instance();
71     $archive_folder = $rcmail->config->get('archive_mbox');
22d48c 72     $show_real_name = $rcmail->config->get('show_real_foldernames');
48e9c1 73
T 74     // set localized name for the configured archive folder
22d48c 75     if ($archive_folder && !$show_real_name) {
48e9c1 76       if (isset($p['list'][$archive_folder]))
T 77         $p['list'][$archive_folder]['name'] = $this->gettext('archivefolder');
78       else // search in subfolders
79         $this->_mod_folder_name($p['list'], $archive_folder, $this->gettext('archivefolder'));
80     }
81
82     return $p;
83   }
84
67cb01 85   /**
TB 86    * Helper method to find the archive folder in the mailbox tree
87    */
88   private function _mod_folder_name(&$list, $folder, $new_name)
48e9c1 89   {
T 90     foreach ($list as $idx => $item) {
91       if ($item['id'] == $folder) {
92         $list[$idx]['name'] = $new_name;
93         return true;
94       } else if (!empty($item['folders']))
95         if ($this->_mod_folder_name($list[$idx]['folders'], $folder, $new_name))
dc0b50 96           return true;
48e9c1 97     }
T 98     return false;
99   }
100
67cb01 101   /**
TB 102    * Plugin action to move the submitted list of messages to the archive subfolders
103    * according to the user settings and their headers.
104    */
105   function move_messages()
106   {
107     $this->add_texts('localization');
108
d72a41 109     $rcmail         = rcmail::get_instance();
AM 110     $storage        = $rcmail->get_storage();
111     $delimiter      = $storage->get_hierarchy_delimiter();
112     $archive_folder = $rcmail->config->get('archive_mbox');
113     $archive_type   = $rcmail->config->get('archive_type', '');
08bb20 114     $current_mbox   = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST);
67cb01 115
d72a41 116     $result  = array('reload' => false, 'update' => false, 'errors' => array());
AM 117     $folders = array();
08bb20 118     $uids    = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST);
AM 119     $search_request = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GPC);
691cbc 120
AM 121     if ($uids == '*') {
122       $index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order());
7fce8f 123       $messageset = array($current_mbox => $index->get());
691cbc 124     }
AM 125     else {
7fce8f 126       $messageset = rcmail::get_uids();
691cbc 127     }
67cb01 128
7fce8f 129     foreach ($messageset as $mbox => $uids) {
TB 130       $storage->set_folder(($current_mbox = $mbox));
67cb01 131
7fce8f 132       foreach ($uids as $uid) {
TB 133         if (!$archive_folder || !($message = $rcmail->storage->get_message($uid))) {
134           continue;
2143a6 135         }
d72a41 136
7fce8f 137         $subfolder = null;
TB 138         switch ($archive_type) {
139           case 'year':
140             $subfolder = $rcmail->format_date($message->timestamp, 'Y');
141             break;
142
143           case 'month':
144             $subfolder = $rcmail->format_date($message->timestamp, 'Y') . $delimiter . $rcmail->format_date($message->timestamp, 'm');
145             break;
146
147           case 'folder':
148             $subfolder = $current_mbox;
149             break;
150
151           case 'sender':
152             $from = $message->get('from');
153             if (preg_match('/[\b<](.+@.+)[\b>]/i', $from, $m)) {
154               $subfolder = $m[1];
155             }
156             else {
157               $subfolder = $this->gettext('unkownsender');
158             }
159
160             // replace reserved characters in folder name
161             $repl = $delimiter == '-' ? '_' : '-';
162             $replacements[$delimiter] = $repl;
163             $replacements['.'] = $repl;  // some IMAP server do not allow . characters
164             $subfolder = strtr($subfolder, $replacements);
165             break;
166
167           default:
168             $subfolder = '';
169             break;
170         }
171
172         // compose full folder path
173         $folder = $archive_folder . ($subfolder ? $delimiter . $subfolder : '');
174
175         // create archive subfolder if it doesn't yet exist
176         // we'll create all folders in the path
177         if (!in_array($folder, $folders)) {
178           if (empty($list)) {
179             $list = $storage->list_folders('', $archive_folder . '*', 'mail', null, true);
180           }
181           $path = explode($delimiter, $folder);
182
183           for ($i=0; $i<count($path); $i++) {
184             $_folder = implode($delimiter, array_slice($path, 0, $i+1));
185             if (!in_array($_folder, $list)) {
186               if ($storage->create_folder($_folder, true)) {
187                 $result['reload'] = true;
188                 $list[] = $_folder;
189               }
d72a41 190             }
AM 191           }
7fce8f 192
TB 193           $folders[] = $folder;
d72a41 194         }
AM 195
7fce8f 196         // move message to target folder
TB 197         if ($storage->move_message(array($uid), $folder)) {
198           $result['update'] = true;
199         }
200         else {
201           $result['errors'][] = $uid;
202         }
203       }  // end for
204     }
67cb01 205
TB 206     // send response
207     if ($result['errors']) {
208       $rcmail->output->show_message($this->gettext('archiveerror'), 'warning');
209     }
210     if ($result['reload']) {
211       $rcmail->output->show_message($this->gettext('archivedreload'), 'confirmation');
212     }
213     else if ($result['update']) {
214       $rcmail->output->show_message($this->gettext('archived'), 'confirmation');
215     }
216
442f37 217     // refresh saved search set after moving some messages
AM 218     if ($search_request && $rcmail->storage->get_search_set()) {
219         $_SESSION['search'] = $rcmail->storage->refresh_search();
220     }
221
a6cc96 222     if ($_POST['_from'] == 'show' && !empty($result['update'])) {
08bb20 223       if ($next = rcube_utils::get_input_value('_next_uid', rcube_utils::INPUT_GPC)) {
a6cc96 224         $rcmail->output->command('show_message', $next);
AM 225       }
226       else {
227         $rcmail->output->command('command', 'list');
228       }
229     }
230     else {
231       $rcmail->output->command('plugin.move2archive_response', $result);
232     }
67cb01 233   }
TB 234
235   /**
236    * Hook to inject plugin-specific user settings
237    */
48e9c1 238   function prefs_table($args)
T 239   {
240     global $CURR_SECTION;
241
242     if ($args['section'] == 'folders') {
243       $this->add_texts('localization');
244
245       $rcmail = rcmail::get_instance();
246
247       // load folders list when needed
248       if ($CURR_SECTION)
61be82 249         $select = $rcmail->folder_selector(array('noselection' => '---', 'realnames' => true,
48e9c1 250           'maxlength' => 30, 'exceptions' => array('INBOX'), 'folder_filter' => 'mail', 'folder_rights' => 'w'));
T 251       else
252         $select = new html_select();
253
254       $args['blocks']['main']['options']['archive_mbox'] = array(
255           'title' => $this->gettext('archivefolder'),
256           'content' => $select->show($rcmail->config->get('archive_mbox'), array('name' => "_archive_mbox"))
257       );
67cb01 258
TB 259       // add option for structuring the archive folder
260       $archive_type = new html_select(array('name' => '_archive_type', 'id' => 'ff_archive_type'));
261       $archive_type->add($this->gettext('none'), '');
262       $archive_type->add($this->gettext('archivetypeyear'), 'year');
263       $archive_type->add($this->gettext('archivetypemonth'), 'month');
264       $archive_type->add($this->gettext('archivetypesender'), 'sender');
265       $archive_type->add($this->gettext('archivetypefolder'), 'folder');
266
267       $args['blocks']['archive'] = array(
74ce01 268         'name' => rcube::Q($this->gettext('settingstitle')),
67cb01 269         'options' => array('archive_type' => array(
TB 270             'title' => $this->gettext('archivetype'),
271             'content' => $archive_type->show($rcmail->config->get('archive_type'))
272           )
273         )
274       );
48e9c1 275     }
T 276
277     return $args;
278   }
279
67cb01 280   /**
TB 281    * Hook to save plugin-specific user settings
282    */
48e9c1 283   function save_prefs($args)
T 284   {
285     if ($args['section'] == 'folders') {
67cb01 286       $args['prefs']['archive_type'] = rcube_utils::get_input_value('_archive_type', rcube_utils::INPUT_POST);
48e9c1 287       return $args;
T 288     }
289   }
290
291 }