summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--privatemsg.api.php16
-rw-r--r--privatemsg.install12
-rw-r--r--privatemsg.module100
-rw-r--r--privatemsg.test52
4 files changed, 152 insertions, 28 deletions
diff --git a/privatemsg.api.php b/privatemsg.api.php
index dcdeb5b..8563ecb 100644
--- a/privatemsg.api.php
+++ b/privatemsg.api.php
@@ -279,22 +279,6 @@ function hook_privatemsg_message_load($message) {
}
/**
- * Is called when a message is deleted.
- *
- * Note: The message is actually only marked as deleted and only for the current
- * user.
- * @todo There is no "undelete" hook
- *
- * @param $pmid
- * ID of the message that has been deleted
- * @param $deleted_by_all
- * Boolean to show whether the message has been deleted by all users or not
- */
-function hook_privatemsg_message_delete($pmid, $deleted_by_all) {
-
-}
-
-/**
* Is called when a message is flushed.
*
* The message will be deleted from the database, remove any related data here.
diff --git a/privatemsg.install b/privatemsg.install
index 3ab2cc9..5e156a7 100644
--- a/privatemsg.install
+++ b/privatemsg.install
@@ -459,4 +459,16 @@ function privatemsg_update_6005() {
$ret = array();
$ret[] = update_sql("UPDATE {permission} SET perm = REPLACE(perm, 'read privatemsg', 'read privatemsg, delete privatemsg') WHERE perm LIKE '%read privatemsg%'");
return $ret;
+}
+
+/**
+ * Set the deleted timestamp of all messages to now.
+ */
+function privatemsg_update_6006() {
+ $ret = array();
+
+ $sql = "UPDATE {pm_index} SET deleted = %d WHERE deleted = 1";
+ $result = db_query($sql, time());
+ $ret[] = array('success' => $result !== FALSE, 'query' => check_plain($sql));
+ return $ret;
} \ No newline at end of file
diff --git a/privatemsg.module b/privatemsg.module
index 872cac7..e9c939a 100644
--- a/privatemsg.module
+++ b/privatemsg.module
@@ -390,6 +390,38 @@ 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 stored in the database. These settings
+ control if and when messages should be removed.'),
+ );
+
+ $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 after they have been deleted for more days than'),
+ '#default_value' => variable_get('privatemsg_flush_days', 30),
+ '#options' => drupal_map_assoc(array(0, 1, 2, 5, 10, 30, 100)),
+ );
+
+ $form['flush_deleted']['privatemsg_flush_max'] = array(
+ '#type' => 'select',
+ '#title' => t('Maximum number of messages to flush per cron run'),
+ '#default_value' => variable_get('privatemsg_flush_max', 200),
+ '#options' => drupal_map_assoc(array(50, 100, 200, 500, 1000)),
+ );
+
$form['privatemsg_listing'] = array(
'#type' => 'fieldset',
'#title' => t('Configure listings'),
@@ -417,6 +449,31 @@ function private_message_settings_submit() {
drupal_rebuild_theme_registry();
}
+/**
+ * Implementation of hook_cron().
+ *
+ * If the flush feature is enabled, a given amount of deleted messages that are
+ * old enough are flushed.
+ */
+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']);
+
+ $flushed = 0;
+ while (($row = db_fetch_array($result)) && ($flushed < variable_get('privatemsg_flush_max', 200))) {
+ $message = _privatemsg_load($row['mid']);
+ module_invoke_all('privatemsg_message_flush', $message);
+
+ // Delete recipients of the message.
+ db_query('DELETE FROM {pm_index} WHERE mid = %d', $row['mid']);
+ // Delete message itself.
+ db_query('DELETE FROM {pm_message} WHERE mid = %d', $row['mid']);
+ $flushed++;
+ }
+ }
+}
+
function privatemsg_theme() {
return array(
'privatemsg_view' => array(
@@ -1117,6 +1174,30 @@ function privatemsg_sql_autocomplete(&$fragments, $search, $names) {
}
/**
+ * Query Builder function to load all messages that should be flushed.
+ *
+ * @param $fragments
+ * Query fragments array.
+ * @param $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'][] = 'MIN(pmi.deleted) > 0';
+ $fragments['having'][] = 'MAX(pmi.deleted) < %d';
+ $fragments['query_args']['having'][] = time() - $days * 86400;
+}
+
+/**
* @}
*/
@@ -1304,23 +1385,18 @@ function privatemsg_delete_submit($form, &$form_state) {
* @ingroup api
*/
function privatemsg_message_change_delete($pmid, $delete, $account = NULL) {
+ $delete_value = 0;
+ if ($delete == TRUE) {
+ $delete_value = time();
+ }
+
if ($account){
- db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = %d AND uid = %d', $delete, $pmid, $account->uid);
+ db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = %d AND uid = %d', $delete_value, $pmid, $account->uid);
}
else {
// Mark deleted for all users.
- db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = %d', $delete, $pmid);
+ db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = %d', $delete_value, $pmid);
}
-
- $result = db_query("SELECT MIN(deleted) AS deleted_by_all FROM {pm_index} WHERE mid = %d", $pmid);
- $deleted = db_fetch_array($result);
-
- $deleted_by_all = FALSE;
- if ($deleted['deleted_by_all'] > 0) {
- $deleted_by_all = TRUE;
- }
-
- module_invoke_all('privatemsg_message_delete', $pmid, $deleted_by_all);
}
/**
diff --git a/privatemsg.test b/privatemsg.test
index 2ab1e55..78a600d 100644
--- a/privatemsg.test
+++ b/privatemsg.test
@@ -110,6 +110,58 @@ class PrivatemsgTestCase extends DrupalWebTestCase {
}
}
+ /**
+ * Tests for the flush feature
+ */
+ function testPrivatemsgFlush()
+ {
+ $author = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg'));
+ $recipient = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg'));
+
+ // Send 10 messages.
+ for ($i = 0; $i < 10; $i++) {
+ privatemsg_new_thread(array($recipient), 'Message #'. $i, 'This is the body', array('author' => $author));
+ }
+
+ // Delete message 1, 3, 4, 6, 9 for author.
+ foreach (array(1, 3, 4, 6, 9) as $pmid) {
+ privatemsg_message_change_delete($pmid, TRUE, $author);
+ }
+
+ // Delete message 1, 2, 4, 6, 8 for recipient.
+ foreach (array(1, 3, 4, 6, 9) as $pmid) {
+ privatemsg_message_change_delete($pmid, TRUE, $recipient);
+ }
+
+ // Now, mid 1, 4 and 6 have been deleted by both.
+
+ // Flush configuration, enable, delay is default, 30 days
+ variable_set('privatemsg_flush_enabled', TRUE);
+
+ // Set back the deleted timestamp 35 days back of mid 4.
+ db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = 4', time() - 35 * 86400);
+ // Set back the deleted timestamp of mid 6, but only 20 back.
+ db_query('UPDATE {pm_index} SET deleted = %d WHERE mid = 6', time() - 20 * 86400);
+
+ // Run flush.
+ privatemsg_cron();
+
+ // Check if the undeleted messages are still there.
+ foreach (array(2, 3, 5, 7, 8, 9, 10) as $pmid) {
+ $message = _privatemsg_load($pmid, $author);
+ $this->assertTrue(!empty($message), t('Undeleted message #%id is still in the system', array('%id' => $pmid)));
+ }
+
+ // Check if the "recently" deleted messages are still there.
+ foreach (array(1, 6) as $pmid) {
+ $message = _privatemsg_load($pmid, $author);
+ $this->assertTrue(!empty($message), t('Deleted message #%id is still in the system', array('%id' => $pmid)));
+ }
+
+ // Mid 4 should have been flushed.
+ $message = _privatemsg_load(4, $author);
+ $this->assertTrue(empty($message), t('Message #4 has been flushed'));
+ }
/**
* Implementation of tearDown().