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