? .cvsignore
? privatemsg.flush_messages.patch
? privatemsg.flush_messages2.patch
? translations
Index: privatemsg.install
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.install,v
retrieving revision 1.5.2.4.2.11.2.5
diff -u -p -r1.5.2.4.2.11.2.5 privatemsg.install
--- privatemsg.install	26 Jan 2009 19:53:26 -0000	1.5.2.4.2.11.2.5
+++ privatemsg.install	10 Feb 2009 02:53:32 -0000
@@ -387,4 +387,10 @@ function privatemsg_update_6000() {
   db_drop_table($ret, 'temp_pm_index');
 
   return $ret;
+}
+
+function privatemsg_update_6002() {
+  $ret = array();
+  $ret[] = update_sql('UPDATE {pm_index} SET deleted = UNIX_TIMESTAMP() WHERE deleted = 1');
+  return $ret;
 }
\ No newline at end of file
Index: privatemsg.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.module,v
retrieving revision 1.70.2.30.2.91.2.14
diff -u -p -r1.70.2.30.2.91.2.14 privatemsg.module
--- privatemsg.module	8 Feb 2009 18:13:06 -0000	1.70.2.30.2.91.2.14
+++ privatemsg.module	10 Feb 2009 02:53:32 -0000
@@ -214,6 +214,30 @@ function private_message_settings() {
     '#default_value' => variable_get('privatemsg_display_loginmessage', TRUE),
     '#description' => t('This option can safely be disabled if the "New message indication" block is used instead.'),
   );
+
+  $form['flush_deleted'] = array(
+    '#type'        => 'fieldset',
+    '#collapsible' => TRUE,
+    '#collapsed'   => TRUE,
+    '#title'       => t('Flush deleted messages'),
+    '#description' => t('By default, deleted messages are only hidden from the
+                         user but still saved in the database. These settings
+                         allow to control if and when they should be deleted.'),
+  );
+
+  $form['flush_deleted']['privatemsg_flush_enabled'] = array(
+    '#type'          => 'checkbox',
+    '#title'         => t('Flush deleted messages'),
+    '#default_value' => variable_get('privatemsg_flush_enabled', FALSE),
+    '#description'   => t('Enable the flushing of deleted messages. Requires that cron is enabled'),
+  );
+
+  $form['flush_deleted']['privatemsg_flush_days'] = array(
+    '#type' => 'select',
+    '#title' => t('Flush messages older than x days'),
+    '#default_value' => variable_get('privatemsg_flush_days', 30),
+    '#options' => drupal_map_assoc(array(0, 1, 2, 5, 10, 30, 100)),
+  );
   $form['#submit'][] = 'private_message_settings_submit';
   return system_settings_form($form);
 }
@@ -222,6 +246,46 @@ function private_message_settings_submit
   drupal_rebuild_theme_registry();
 }
 
+/**
+ * hook_cron implementation, flushes deleted queries
+ */
+function privatemsg_cron() {
+  if (variable_get('privatemsg_flush_enabled', FALSE)) {
+    $query = _privatemsg_assemble_query('deleted', variable_get('privatemsg_flush_days', 30));
+    $result = db_query($query['query']);
+
+    while ($row = db_fetch_array($result)) {
+      // Delete recipients
+      db_query('DELETE FROM {pm_index} WHERE mid = %d', $row['mid']);
+
+      // Delete message
+      db_query('DELETE FROM {pm_message} WHERE mid = %d', $row['mid']);
+    }
+  }
+}
+
+/**
+ * Sql function for the deleted messages query
+ *
+ * @param array $fragments Query-fragments
+ * @param int   $days      Select messages older than x days
+ */
+function privatemsg_sql_deleted(&$fragments, $days) {
+  $fragments['primary_table'] = '{pm_message} pm';
+
+  $fragments['select'][] = 'pm.mid';
+  $fragments['select'][] = 'MIN(pmi.deleted) as is_deleted';
+  $fragments['select'][] = 'MAX(pmi.deleted) as last_deleted';
+
+  $fragments['inner_join'][] = 'INNER JOIN {pm_index} pmi ON (pmi.mid = pm.mid)';
+
+  $fragments['group_by'][] = 'pm.mid';
+
+  $fragments['having'][] = 'is_deleted > 0';
+  $fragments['having'][] = 'last_deleted < %d';
+  $fragments['query_args'][] = time() - $days * 86400;
+}
+
 function privatemsg_theme() {
   return array(
     'privatemsg_view'    => array(
@@ -1079,7 +1143,7 @@ function privatemsg_delete($form_state, 
 
 function privatemsg_delete_submit($form, &$form_state) {
   global $user;
-  $deleted = 1;
+  $deleted = time();
 
   if ($form_state['values']['confirm']) {
     db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = %d AND uid = %d', $deleted, $form_state['values']['pmid'], $user->uid);
Index: privatemsgapi/privatemsgapi.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsgapi/privatemsgapi.inc,v
retrieving revision 1.8.2.2
diff -u -p -r1.8.2.2 privatemsgapi.inc
--- privatemsgapi/privatemsgapi.inc	8 Feb 2009 18:13:06 -0000	1.8.2.2
+++ privatemsgapi/privatemsgapi.inc	10 Feb 2009 02:53:32 -0000
@@ -83,6 +83,7 @@ function _privatemsg_assemble_query($que
   $INNER_JOIN = array();
   $WHERE = array();
   $GROUP_BY = array();
+  $HAVING   = array();
   $ORDER_BY = array();
   $QUERY_ARGS = array();
   $primary_table = '';
@@ -92,6 +93,7 @@ function _privatemsg_assemble_query($que
     'inner_join'  => $INNER_JOIN,
     'where'       => $WHERE,
     'group_by'    => $GROUP_BY,
+    'having'      => $HAVING,
     'order_by'    => $ORDER_BY,
     'query_args'  => $QUERY_ARGS,
     'primary_table'  => $primary_table,
@@ -125,6 +127,7 @@ function _privatemsg_assemble_query($que
   $INNER_JOIN = $fragments['inner_join'];
   $WHERE = $fragments['where'];
   $GROUP_BY = $fragments['group_by'];
+  $HAVING   = $fragments['having'];
   $ORDER_BY = $fragments['order_by'];
   $QUERY_ARGS = $fragments['query_args'];
   $primary_table = $fragments['primary_table'];
@@ -144,8 +147,9 @@ function _privatemsg_assemble_query($que
     if (!empty($GROUP_BY)) {
       // PostgreSQL does not support COUNT(sometextfield, someintfield), so I'm only using the first one
       // Works fine for thread_id/list but may generate an error when a more complex GROUP BY is used.
+      // But for HAVING, we still need all selected field, so that HAVING works
       $str_group_by_count = current($GROUP_BY);
-      $count = "SELECT COUNT(DISTINCT {$str_group_by_count}) FROM ". $primary_table;
+      $count = "SELECT COUNT(DISTINCT {$str_group_by_count}), $str_select FROM ". $primary_table;
     }
     else {
       $count = "SELECT COUNT(*) FROM ". $primary_table;
@@ -165,6 +169,12 @@ function _privatemsg_assemble_query($que
       $str_group_by = ' GROUP BY '. implode(", ", $GROUP_BY) ;
       $query .= " {$str_group_by}";
     }
+    if (!empty($HAVING)) {
+      $str_having = '('. implode(') AND (', $HAVING) .')';
+      $query .= " HAVING {$str_having}";
+      $count .= " HAVING {$str_having}";
+    }
+
     if (!empty($ORDER_BY)) {
       $str_order_by = ' ORDER BY '. implode(", ", $ORDER_BY) ;
       $query .= " {$str_order_by}";
@@ -175,6 +185,7 @@ function _privatemsg_assemble_query($que
       _db_query_callback($QUERY_ARGS, TRUE);
       $count = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $count);
     }
+    drupal_set_message($query);
     return array('query' => $query, 'count' => $count);
   }
   return FALSE;
