diff --git a/includes/message.admin.inc b/includes/message.admin.inc index 1327214..8ead16b 100644 --- a/includes/message.admin.inc +++ b/includes/message.admin.inc @@ -105,6 +105,13 @@ function message_user_admin_settings($form_state) { ); } + $form['message_entity_delete_use_queue'] = array( + '#type' => 'checkbox', + '#title' => t('Use queue'), + '#description' => t('Delete messages with out existing reference via queue.'), + '#default_value' => variable_get('message_entity_delete_use_queue', FALSE), + ); + return system_settings_form($form); } diff --git a/message.module b/message.module index a25d808..a3ce795 100644 --- a/message.module +++ b/message.module @@ -271,6 +271,29 @@ function message_entity_delete($entity, $entity_type) { return; } + if (!$fields = _message_get_referenced_fields($entity, $entity_type)) { + return; + } + + if (variable_get('message_entity_delete_use_queue')) { + $data = array( + 'range' => 200, + 'last_mid' => 1, + 'fields' => $fields, + ); + $queue = DrupalQueue::get('message_entity_delete'); + + return $queue->createItem($data); + } + + _message_delete_messages($fields); +} + +/** + * Helper function for getting the fields which holds the reference to the + * message. + */ +function _message_get_referenced_fields($entity, $entity_type) { $entity_types = variable_get('message_delete_on_entity_delete', array('node', 'user', 'taxonomy_term', 'comment')); if (!$entity_types || !in_array($entity_type, $entity_types)) { return; @@ -278,14 +301,7 @@ function message_entity_delete($entity, $entity_type) { list($id, , $bundle) = entity_extract_ids($entity_type, $entity); - // List of messages to delete. - $deletable_mids = array(); - // List of messages that might be deleted; - // Messages with references to fields with mutiple cardinality will be - // stored in $check_mids in order to check if the entity being deleted - // is the last one referenced by a given field. - // Keyd by message ID, pointing to array of the relevant field names. - $check_mids = array(); + $fields = array(); // Search for fields in which messages referenced the deleted entity. foreach (field_info_fields() as $field) { @@ -319,18 +335,56 @@ function message_entity_delete($entity, $entity_type) { continue; } + $fields[] = array( + 'field_name' => $field['field_name'], + 'column' => $column, + 'cardinality' => $field['cardinality'], + 'id' => $id, + ); + } + + return $fields; +} + +/** + * Delete messages that the reference two is still exists. + * @param $fields + * Array of fields data which holds the reference to the message. + * @param $last_mid + * The last Message ID we process. + * @param $range + * The number of message to process each time. Optional. + * @return The last Message ID we process. + */ +function _message_delete_messages($fields, $last_mid = 0, $range = NULL) { + // List of messages to delete. + $deletable_mids = array(); + // List of messages that might be deleted; + // Messages with references to fields with multiple cardinality will be + // stored in $check_mids in order to check if the entity being deleted + // is the last one referenced by a given field. + // Keyed by message ID, pointing to array of the relevant field names. + $check_mids = array(); + + foreach ($fields as $field) { // Fetch messages with fields referencing the deleted entity. $query = new EntityFieldQuery(); - $result = $query->entityCondition('entity_type', 'message') - ->fieldCondition($field['field_name'], $column, $id) - ->execute(); + $query->entityCondition('entity_type', 'message') + ->propertyCondition('mid', $last_mid, '>') + ->fieldCondition($field['field_name'], $field['column'], $field['id']); + + if ($range) { + $query->range(0, $range); + } + + $result = $query->execute(); // Continue to next field if no such messages exist. if (empty($result['message'])) { continue; } - // If the field has single cardinallity it's safe to delete the + // If the field has single cardinality it's safe to delete the // messages. if ($field['cardinality'] == 1) { $deletable_mids += array_keys($result['message']); @@ -349,7 +403,7 @@ function message_entity_delete($entity, $entity_type) { } } - // Check messages with multiple cardinallity refrences; Only delete such + // Check messages with multiple cardinality references; Only delete such // messages if the entity being deleted is the last one referenced by the // message. if ($check_mids) { @@ -381,7 +435,10 @@ function message_entity_delete($entity, $entity_type) { if ($deletable_mids) { message_delete_multiple($deletable_mids); + return reset($deletable_mids); } + + return; } /** @@ -930,3 +987,38 @@ function message_features_pipe_message_type_alter(&$pipe, $data, $export) { $pipe['variable'][] = "field_bundle_settings_message__{$message_type}"; } } + +/** + * Implements hook_cron_queue_info(). + */ +function message_cron_queue_info() { + $items['message_entity_delete'] = array( + 'title' => t('Message'), + 'worker callback' => 'message_entity_delete_queue_worker', + 'time' => 60, + ); + return $items; +} + +/** + * Queue API worker; Process a queue item. + * + * The item holds the fields information(field name, column, id and cardinality), + * the last Message ID we processed and the range. + */ +function message_entity_delete_queue_worker($data, $end_time = FALSE) { + extract($data); + + if (!$mid = _message_delete_messages($fields, $last_mid, $range)) { + return; + } + + $data = array( + 'range' => 200, + 'last_mid' => $mid, + 'fields' => $fields, + ); + + $queue = DrupalQueue::get('message_entity_delete'); + return $queue->createItem($data); +}