Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Extend archive plugin with user-configurable options to move messages…

… into subfolders according to their date, sender or originating folder
  • Loading branch information...
commit 67cb017b0cdda3c2dcc7d9434fdbaca5f4ead938 1 parent 1ef4033
Thomas B. authored
23  plugins/archive/archive.js
... ...
@@ -1,6 +1,6 @@
1 1
 /*
2 2
  * Archive plugin script
3  
- * @version @package_version@
  3
+ * @version 2.0
4 4
  */
5 5
 
6 6
 function rcmail_archive(prop)
@@ -8,8 +8,19 @@ function rcmail_archive(prop)
8 8
   if (!rcmail.env.uid && (!rcmail.message_list || !rcmail.message_list.get_selection().length))
9 9
     return;
10 10
   
11  
-  if (rcmail.env.mailbox != rcmail.env.archive_folder)
12  
-    rcmail.command('moveto', rcmail.env.archive_folder);
  11
+  if (rcmail.env.mailbox.indexOf(rcmail.env.archive_folder) != 0) {
  12
+    if (!rcmail.env.archive_type) {
  13
+      // simply move to archive folder (if no partition type is set)
  14
+      rcmail.command('moveto', rcmail.env.archive_folder);
  15
+    }
  16
+    else {
  17
+      // let the server sort the messages to the according subfolders
  18
+      rcmail.http_post(
  19
+        'plugin.move2archive',
  20
+        { _uid: rcmail.message_list.get_selection().join(','), _mbox: rcmail.env.mailbox }
  21
+      );
  22
+    }
  23
+  }
13 24
 }
14 25
 
15 26
 // callback for app-onload event
@@ -29,6 +40,12 @@ if (window.rcmail) {
29 40
     var li;
30 41
     if (rcmail.env.archive_folder && (li = rcmail.get_folder_li(rcmail.env.archive_folder, '', true)))
31 42
       $(li).addClass('archive');
  43
+
  44
+    // callback for server response
  45
+    rcmail.addEventListener('plugin.move2archive_response', function(result) {
  46
+      if (result.update)
  47
+        rcmail.command('checkmail');  // refresh list
  48
+    });
32 49
   })
33 50
 }
34 51
 
136  plugins/archive/archive.php
@@ -6,7 +6,7 @@
6 6
  * Plugin that adds a new button to the mailbox toolbar
7 7
  * to move messages to a (user selectable) archive folder.
8 8
  *
9  
- * @version @package_version@
  9
+ * @version 2.0
10 10
  * @license GNU GPLv3+
11 11
  * @author Andre Rodier, Thomas Bruederli
12 12
  */
@@ -45,14 +45,19 @@ function init()
45 45
       // register hook to localize the archive folder
46 46
       $this->add_hook('render_mailboxlist', array($this, 'render_mailboxlist'));
47 47
 
48  
-      // set env variable for client
  48
+      // set env variables for client
49 49
       $rcmail->output->set_env('archive_folder', $archive_folder);
  50
+      $rcmail->output->set_env('archive_type', $rcmail->config->get('archive_type',''));
50 51
 
51 52
       // add archive folder to the list of default mailboxes
52 53
       if (($default_folders = $rcmail->config->get('default_folders')) && !in_array($archive_folder, $default_folders)) {
53 54
         $default_folders[] = $archive_folder;
54 55
         $rcmail->config->set('default_folders', $default_folders);
55  
-      }  
  56
+      }
  57
+    }
  58
+    else if ($rcmail->task == 'mail') {
  59
+      // handler for ajax request
  60
+      $this->register_action('plugin.move2archive', array($this, 'move_messages'));
56 61
     }
57 62
     else if ($rcmail->task == 'settings') {
58 63
       $dont_override = $rcmail->config->get('dont_override', array());
@@ -62,7 +67,10 @@ function init()
62 67
       }
63 68
     }
64 69
   }
65  
-  
  70
+
  71
+  /**
  72
+   * Hook to give the archive folder a localized name in the mailbox list
  73
+   */
66 74
   function render_mailboxlist($p)
67 75
   {
68 76
     $rcmail = rcmail::get_instance();
@@ -80,7 +88,10 @@ function render_mailboxlist($p)
80 88
     return $p;
81 89
   }
82 90
 
83  
-  function _mod_folder_name(&$list, $folder, $new_name)
  91
+  /**
  92
+   * Helper method to find the archive folder in the mailbox tree
  93
+   */
  94
+  private function _mod_folder_name(&$list, $folder, $new_name)
84 95
   {
85 96
     foreach ($list as $idx => $item) {
86 97
       if ($item['id'] == $folder) {
@@ -93,6 +104,100 @@ function _mod_folder_name(&$list, $folder, $new_name)
93 104
     return false;
94 105
   }
95 106
 
  107
+  /**
  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
+    $rcmail = rcmail::get_instance();
  114
+    $this->add_texts('localization');
  115
+
  116
+    $storage = $rcmail->get_storage();
  117
+    $storage->set_folder(($current_mbox = rcube_utils::get_input_value('_mbox', RCUBE_INPUT_POST)));
  118
+
  119
+    $delimiter = $storage->get_hierarchy_delimiter();
  120
+    $archive_folder = $rcmail->config->get('archive_mbox');
  121
+    $archive_type = $rcmail->config->get('archive_type', '');
  122
+
  123
+    $result = array('reload' => false, 'update' => false, 'errors' => array());
  124
+
  125
+    $uids = explode(',', rcube_utils::get_input_value('_uid', RCUBE_INPUT_POST));
  126
+    foreach ($uids as $uid) {
  127
+      if (!$archive_folder || !($message = $rcmail->storage->get_message($uid))) {
  128
+        continue;
  129
+      }
  130
+
  131
+      $subfolder = null;
  132
+      switch ($archive_type) {
  133
+        case 'year':
  134
+          $subfolder = $rcmail->format_date($message->timestamp, 'Y');
  135
+          break;
  136
+
  137
+        case 'month':
  138
+          $subfolder = $rcmail->format_date($message->timestamp, 'Y') . $delimiter . $rcmail->format_date($message->timestamp, 'm');
  139
+          break;
  140
+
  141
+        case 'folder':
  142
+          $subfolder = $current_mbox;
  143
+          break;
  144
+
  145
+        case 'sender':
  146
+          $from = $message->get('from');
  147
+          if (preg_match('/[\b<](.+@.+)[\b>]/i', $from, $m)) {
  148
+            $subfolder = $m[1];
  149
+          }
  150
+          else {
  151
+            $subfolder = $this->gettext('unkownsender');
  152
+          }
  153
+
  154
+          // replace reserved characters in folder name
  155
+          $repl = $delimiter == '-' ? '_' : '-';
  156
+          $replacements[$delimiter] = $repl;
  157
+          $replacements['.'] = $repl;  // some IMAP server do not allow . characters
  158
+          $subfolder = strtr($subfolder, $replacements);
  159
+          break;
  160
+
  161
+        default:
  162
+          $subfolder = '';
  163
+          break;
  164
+      }
  165
+
  166
+      // compose full folder path
  167
+      $folder =  $archive_folder . ($subfolder ? $delimiter . $subfolder : '');
  168
+
  169
+      // create archive subfolder if it doesn't yet exist
  170
+      if (!$storage->folder_exists($folder, false)) {
  171
+        if ($storage->create_folder($folder, true))
  172
+          $result['reload'] = true;
  173
+      }
  174
+
  175
+      // move message to target folder
  176
+      if ($storage->move_message(array($uid), $folder)) {
  177
+        $result['update'] = true;
  178
+      }
  179
+      else {
  180
+        $result['errors'][] = $uid;
  181
+      }
  182
+    }  // end for
  183
+
  184
+    // send response
  185
+    if ($result['errors']) {
  186
+      $rcmail->output->show_message($this->gettext('archiveerror'), 'warning');
  187
+    }
  188
+    if ($result['reload']) {
  189
+      $rcmail->output->show_message($this->gettext('archivedreload'), 'confirmation');
  190
+    }
  191
+    else if ($result['update']) {
  192
+      $rcmail->output->show_message($this->gettext('archived'), 'confirmation');
  193
+    }
  194
+
  195
+    $rcmail->output->command('plugin.move2archive_response', $result);
  196
+  }
  197
+
  198
+  /**
  199
+   * Hook to inject plugin-specific user settings
  200
+   */
96 201
   function prefs_table($args)
97 202
   {
98 203
     global $CURR_SECTION;
@@ -113,15 +218,36 @@ function prefs_table($args)
113 218
           'title' => $this->gettext('archivefolder'),
114 219
           'content' => $select->show($rcmail->config->get('archive_mbox'), array('name' => "_archive_mbox"))
115 220
       );
  221
+
  222
+      // add option for structuring the archive folder
  223
+      $archive_type = new html_select(array('name' => '_archive_type', 'id' => 'ff_archive_type'));
  224
+      $archive_type->add($this->gettext('none'), '');
  225
+      $archive_type->add($this->gettext('archivetypeyear'), 'year');
  226
+      $archive_type->add($this->gettext('archivetypemonth'), 'month');
  227
+      $archive_type->add($this->gettext('archivetypesender'), 'sender');
  228
+      $archive_type->add($this->gettext('archivetypefolder'), 'folder');
  229
+
  230
+      $args['blocks']['archive'] = array(
  231
+        'name' => Q(rcube_label('settingstitle', 'archive')),
  232
+        'options' => array('archive_type' => array(
  233
+            'title' => $this->gettext('archivetype'),
  234
+            'content' => $archive_type->show($rcmail->config->get('archive_type'))
  235
+          )
  236
+        )
  237
+      );
116 238
     }
117 239
 
118 240
     return $args;
119 241
   }
120 242
 
  243
+  /**
  244
+   * Hook to save plugin-specific user settings
  245
+   */
121 246
   function save_prefs($args)
122 247
   {
123 248
     if ($args['section'] == 'folders') {
124 249
       $args['prefs']['archive_mbox'] = rcube_utils::get_input_value('_archive_mbox', rcube_utils::INPUT_POST);
  250
+      $args['prefs']['archive_type'] = rcube_utils::get_input_value('_archive_type', rcube_utils::INPUT_POST);
125 251
       return $args;
126 252
     }
127 253
   }
11  plugins/archive/localization/en_US.inc
@@ -5,7 +5,7 @@
5 5
  | plugins/archive/localization/<lang>.inc                                |
6 6
  |                                                                       |
7 7
  | Localization file of the Roundcube Webmail Archive plugin             |
8  
- | Copyright (C) 2012, The Roundcube Dev Team                            |
  8
+ | Copyright (C) 2013, The Roundcube Dev Team                            |
9 9
  |                                                                       |
10 10
  | Licensed under the GNU General Public License version 3 or            |
11 11
  | any later version with exceptions for skins & plugins.                |
@@ -20,6 +20,15 @@ $labels = array();
20 20
 $labels['buttontext'] = 'Archive';
21 21
 $labels['buttontitle'] = 'Archive this message';
22 22
 $labels['archived'] = 'Successfully archived';
  23
+$labels['archivedreload'] = 'Successfully archived. Reload the page to see the new archive folders.';
  24
+$labels['archiveerror'] = 'Some messages could not be archived';
23 25
 $labels['archivefolder'] = 'Archive';
  26
+$labels['settingstitle'] = 'Archive';
  27
+$labels['archivetype'] = 'Divide archive by';
  28
+$labels['archivetypeyear'] = 'Year (e.g. Archive/2012)';
  29
+$labels['archivetypemonth'] = 'Month (e.g. Archive/2012/06)';
  30
+$labels['archivetypefolder'] = 'Original folder';
  31
+$labels['archivetypesender'] = 'Sender email';
  32
+$labels['unkownsender'] = 'unknown';
24 33
 
25 34
 ?>
21  plugins/archive/localization/nb_NB.inc
... ...
@@ -1,21 +0,0 @@
1  
-<?php
2  
-
3  
-/*
4  
- +-----------------------------------------------------------------------+
5  
- | localization/nb_NB/labels.inc                                         |
6  
- |                                                                       |
7  
- | Language file of the Roundcube Webmail client                         |
8  
- | Copyright (C) 2012, The Roundcube Dev Team                            |
9  
- | Licensed under the GNU General Public License                         |
10  
- |                                                                       |
11  
- +-----------------------------------------------------------------------+
12  
- | Author: Tobias V. Langhoff <spug@thespug.net>                         |
13  
- +-----------------------------------------------------------------------+
14  
-*/
15  
-
16  
-$labels = array();
17  
-$labels['buttontext'] = 'Arkiv';
18  
-$labels['archivefolder'] = 'Arkiv';
19  
-$labels['buttontitle'] = 'Arkiver meldingen';
20  
-$labels['archived'] = 'Arkivert';
21  
-
42  plugins/archive/package.xml
@@ -6,17 +6,17 @@
6 6
 	<name>archive</name>
7 7
 	<channel>pear.roundcube.net</channel>
8 8
 	<summary>Archive feature for Roundcube</summary>
9  
-	<description>This adds a button to move the selected messages to an archive folder. The folder can be selected in the settings panel.</description>
  9
+	<description>This adds a button to move the selected messages to an archive folder. The folder (and the optional structure of subfolders) can be selected in the settings panel.</description>
10 10
 	<lead>
11 11
 		<name>Thomas Bruederli</name>
12 12
 		<user>thomasb</user>
13 13
 		<email>roundcube@gmail.com</email>
14 14
 		<active>yes</active>
15 15
 	</lead>
16  
-	<date>2011-11-23</date>
  16
+	<date>2013-01-20</date>
17 17
 	<version>
18  
-		<release>1.6</release>
19  
-		<api>1.6</api>
  18
+		<release>2.0</release>
  19
+		<api>2.0</api>
20 20
 	</version>
21 21
 	<stability>
22 22
 		<release>stable</release>
@@ -34,21 +34,55 @@
34 34
 				<tasks:replace from="@name@" to="name" type="package-info"/>
35 35
 				<tasks:replace from="@package_version@" to="version" type="package-info"/>
36 36
 			</file>
  37
+			<file name="localization/ar_SA.inc" role="data"></file>
  38
+			<file name="localization/az_AZ.inc" role="data"></file>
  39
+			<file name="localization/be_BE.inc" role="data"></file>
  40
+			<file name="localization/bg_BG.inc" role="data"></file>
  41
+			<file name="localization/bs_BA.inc" role="data"></file>
  42
+			<file name="localization/ca_ES.inc" role="data"></file>
37 43
 			<file name="localization/cs_CZ.inc" role="data"></file>
  44
+			<file name="localization/cy_GB.inc" role="data"></file>
  45
+			<file name="localization/da_DK.inc" role="data"></file>
38 46
 			<file name="localization/de_CH.inc" role="data"></file>
39 47
 			<file name="localization/de_DE.inc" role="data"></file>
  48
+			<file name="localization/el_GR.inc" role="data"></file>
  49
+			<file name="localization/eb_GB.inc" role="data"></file>
40 50
 			<file name="localization/en_US.inc" role="data"></file>
41 51
 			<file name="localization/es_AR.inc" role="data"></file>
42 52
 			<file name="localization/es_ES.inc" role="data"></file>
43 53
 			<file name="localization/et_EE.inc" role="data"></file>
  54
+			<file name="localization/fa_IR.inc" role="data"></file>
  55
+			<file name="localization/fi_FI.inc" role="data"></file>
44 56
 			<file name="localization/fr_FR.inc" role="data"></file>
45 57
 			<file name="localization/gl_ES.inc" role="data"></file>
  58
+			<file name="localization/he_IL.inc" role="data"></file>
  59
+			<file name="localization/hr_HR.inc" role="data"></file>
  60
+			<file name="localization/hu_HU.inc" role="data"></file>
  61
+			<file name="localization/hy_AM.inc" role="data"></file>
  62
+			<file name="localization/id_ID.inc" role="data"></file>
  63
+			<file name="localization/it_IT.inc" role="data"></file>
46 64
 			<file name="localization/ja_JP.inc" role="data"></file>
  65
+			<file name="localization/km_KH.inc" role="data"></file>
  66
+			<file name="localization/ko_KR.inc" role="data"></file>
  67
+			<file name="localization/lt_LT.inc" role="data"></file>
  68
+			<file name="localization/lv_LV.inc" role="data"></file>
  69
+			<file name="localization/ml_IN.inc" role="data"></file>
  70
+			<file name="localization/nb_NO.inc" role="data"></file>
47 71
 			<file name="localization/nl_NL.inc" role="data"></file>
  72
+			<file name="localization/nn_NO.inc" role="data"></file>
48 73
 			<file name="localization/pl_PL.inc" role="data"></file>
49 74
 			<file name="localization/pt_BR.inc" role="data"></file>
  75
+			<file name="localization/pt_PT.inc" role="data"></file>
50 76
 			<file name="localization/ru_RU.inc" role="data"></file>
  77
+			<file name="localization/si_LK.inc" role="data"></file>
  78
+			<file name="localization/sk_SK.inc" role="data"></file>
  79
+			<file name="localization/sl_SI.inc" role="data"></file>
  80
+			<file name="localization/sr_CS.inc" role="data"></file>
51 81
 			<file name="localization/sv_SE.inc" role="data"></file>
  82
+			<file name="localization/tr_TR.inc" role="data"></file>
  83
+			<file name="localization/uk_UA.inc" role="data"></file>
  84
+			<file name="localization/vi_VN.inc" role="data"></file>
  85
+			<file name="localization/zh_CN.inc" role="data"></file>
52 86
 			<file name="localization/zh_TW.inc" role="data"></file>
53 87
 			<file name="skins/classic/archive_act.png" role="data"></file>
54 88
 			<file name="skins/classic/archive_pas.png" role="data"></file>

0 notes on commit 67cb017

Please sign in to comment.
Something went wrong with that request. Please try again.