$name) { if (messaging_method_info($method, 'anonymous')) { $method_list[$method] = $name; } } return $method_list; } /** * Query subscriptions for destination */ function notifications_destination_get_subscriptions($destination, $pager = 0) { return notifications_get_subscriptions(array('mdid' => $destination->mdid), array(), FALSE, 'sid', $pager); } /** * Validate destination for method */ function notifications_destination_validate($method, $address, $account) { // Check the method is valid for this account $valid_methods = notifications_send_methods($account); return isset($valid_methods[$method]) && Messaging_Destination::validate_method($method, $address, $account); } /** * Subform elements for destination data */ function notifications_destination_subform($destination, $links = array()) { // Count subscriptions for this destination $count = db_result(db_query("SELECT COUNT(*) FROM {notifications} WHERE mdid = %d", $destination->mdid)); $form['destination'] = array('#type' => 'value', '#value' => $destination); $form['destination_view'] = array( '#title' => $destination->address_name(), '#type' => 'item', '#value' => $destination->format_address(TRUE), '#description' => format_plural($count, "There is one subscription for this destination.", 'There are @count subscriptions for this destination.'), ); if ($links) { $form['destination_options'] = array( '#type' => 'item', '#value' => implode(' | ', $links), ); } return $form; } /** * Subform with method and address */ function notifications_destination_method_subform($account, $send_method = NULL, $destination = NULL) { $form['destination_account'] = array('#type' => 'value', '#value' => $account); $send_methods = notifications_send_methods($account); $form['destination_method'] = array( '#type' => 'fieldset', '#tree' => TRUE, ); $form['destination_method']['method'] = array( '#type' => 'select', '#title' => t('Send method'), '#options' => $send_methods, '#default_value' => $send_method ? $send_method : messaging_method_default($account), '#disabled' => count($send_methods) < 2, ); $form['destination_method']['address'] = array( '#type' => 'textfield', '#title' => t('Address'), '#size' => 40, '#required' => TRUE, '#default_value' => $destination ? $destination->address : '', ); return $form; } /** * Displays a destination field for each method * * @param $account * User account the destination is for * @param $destination * Destination object to populate one of the addresses * @param $send_methods * Array method => name to restrict the number of sending methods * @param $size * Address text field size */ function notifications_destination_address_subform($account, $destination = NULL, $send_methods = NULL, $size = 40) { $send_methods = isset($send_methods) ? $send_methods : notifications_send_methods($account); if (!$send_methods) { $form['warning']['#value'] = '
' . t('No sending methods available.') . '
'; return $form; } // Get address types for all these methods, without duplicates $address_types = $address_method = array(); foreach ($send_methods as $method => $method_name) { // We use method name if we don't have address name $type = messaging_method_info($method, 'address_type'); $name = messaging_address_info($type, 'name'); $address_types[$type] = $name ? $name : $method_name; $address_method[$method] = $type; } // This address type to method mapping will allow us to get a valid method from a destination $form['destination_methods'] = array('#type' => 'value', '#value' => $address_method); $form['destination_account'] = array('#type' => 'value', '#value' => $account); $form['destination_address'] = array( //'#type' => 'fieldset', '#tree' => TRUE, ); // Now depending on how many address types we adjust the title if (count($address_types) > 1) { $form['destination_address'] += array( '#title' => t('Enter only a destination address.'), '#type' => 'fieldset', ); } // We present a field for each address type foreach ($address_types as $type => $name) { $form['destination_address'][$type] = array( '#title' => $name, '#type' => 'textfield', '#size' => $size, '#default_value' => $destination && $type == $destination->type ? $destination->address : '', ); } return $form; } /** * Parse submitted destination */ function notifications_destination_parse_submitted(&$values, $validate = FALSE) { $account = !empty($values['destination_account']) ? $values['destination_account'] : NULL; $method = $addres = $type = NULL; $dest = array(); $field = ''; // Destination can come in any of these configurations if (!$validate && !empty($values['destination_parsed'])) { return $values['destination_parsed']; } else { if (!empty($values['destination_method'])) { $field = 'destination_method'; $method = $values['destination_method']['method']; $address = $values['destination_method']['address']; $type = messaging_method_info($method, 'address_type'); } elseif (!empty($values['destination_address'])) { $field = 'destination_address'; $destination = $values['destination_address']; if (is_array($destination)) { $destination = array_filter($destination); if ($destination && count($destination) == 1) { $type = key($destination); $address = current($destination); $method = $values['destination_methods'][$type]; } } } } $dest = array( 'method' => $method, 'type' => $type, 'address' => $address, 'uid' => messaging_user_uid($account), ); if ($validate) { if (!$method || !$address) { form_set_error($field, t('You need to enter exactly one destination address.')); } elseif (!notifications_destination_validate($method, $address, $account)) { form_set_error($field, t('This destination address is not valid.')); } else { // If this is a valid one, we store it on the form values $values['destination_parsed'] = $dest; } } return $dest; } /** * Edit destination form */ function notifications_destination_edit_form($form_state, $destination, $options = array()) { global $user; $form = notifications_destination_subform($destination, $options); $form += notifications_destination_method_subform($user, $destination); $form['update'] = array('#type' => 'submit', '#value' => t('Update')); //$form['delete'] = array('#type' => 'submit', '#value' => t('Delete')); return $form; } /** * Edit destination validate */ function notifications_destination_edit_form_validate($form, $form_state) { notifications_destination_parse_submitted($form_state['values'], TRUE); } /** * Edit destinatin submission */ function notifications_destination_edit_form_submit($form, $form_state) { $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : NULL; $destination = $form_state['values']['destination']; switch ($op) { case t('Update'): $dest = notifications_destination_parse_submitted($form_state['values']); if ($destination = Messaging_Destination::create($dest)) { $object->save(); drupal_set_message(t('The destination address has been updated.')); } else { drupal_set_message(t('The destination cannot be updated.'), 'error'); } break; } } /** * Form for unsubscription confirmation * * It works for both single subscription or account (all subscriptions) */ function notifications_destination_delete_confirm($form_state, $destination, $options = array()) { // Pass on destination values and display them $form = notifications_destination_subform($destination, $options); return confirm_form($form, t('Are you sure you want to delete this destination and all its subscriptions?'), isset($_GET['destination']) ? $_GET['destination'] : '', t('This action cannot be undone.'), t('Delete'), t('Cancel') ); } /** * Destination deletion confirmed */ function notifications_destination_delete_confirm_submit($form, $form_state) { if ($destination = $form_state['values']['destination']) { notifications_destination_delete($destination->mdid); drupal_set_message('The destination and all its subscriptions have been deleted.'); } } /** * Unsubscribe form */ function notifications_destination_unsubscribe_form($form_state, $destination, $options = array()) { $form = notifications_destination_subform($destination, $options); return confirm_form($form, t('This will delete this address and all its subscriptions.'), isset($_GET['destination']) ? $_GET['destination'] : '', t('This action cannot be undone.'), t('Unsubscribe'), t('Cancel') ); } /** * Unsubscribe form submit */ function notifications_destination_unsubscribe_form_submit($form, $form_state) { $destination = $form_state['values']['destination']; notifications_delete_destination($destination->mdid); drupal_set_message(t('The destination and all its subscriptions have been deleted.')); } /** * Destination manage subscriptions form */ function notifications_destination_manage_form($form_state, $destination, $options = array()) { module_load_include('inc', 'notifications', 'notifications.pages'); $account = $destination->get_account(); if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') { $form = notifications_multiple_delete_confirm($form_state, array_filter($form_state['values']['subscriptions'])); return $form; } $form['description'] = notifications_destination_subform($destination, $options); $form['admin'] = notifications_destination_manage_subform($destination); $form['admin'] += notifications_destination_manage_subscriptions_form_options($account); //$form['options'] = array('#type' => 'fieldset', '#title' => t('Options')); return $form; } /** * Destination manage subform. List/edit subscriptions for destination. */ function notifications_destination_manage_subform($destination) { module_load_include('manage.inc', 'notifications'); $subscriptions = notifications_destination_get_subscriptions($destination, 20); // List of subscriptions for selection $select = array(); $status = Notifications_Subscription::status_list(); $send_methods = messaging_method_info(NULL, 'name'); $send_intervals = notifications_send_intervals(); $drupal_destination = drupal_get_destination(); foreach ($subscriptions as $subs) { $select[$subs->sid] = ''; $form['type'][$subs->sid] = array('#value' => notifications_subscription_types($subs->type, 'title')); $form['description'][$subs->sid] = array('#value' => $subs->get_name()); $form['send_interval'][$subs->sid] = array('#value' => !empty($send_intervals[$subs->send_interval]) ? $send_intervals[$subs->send_interval] : $subs->send_interval); $form['status'][$subs->sid] = array('#value' => $status[$subs->status]); $operations = array(); if ($destination->uid || user_access('administer notifications')) { // Links for subscription for user. Permissions will be checked later. $operations[] = l(t('edit'), 'notifications/subscription/' . $subs->sid, array('query' => $drupal_destination)); $operations[] = l(t('drop'), 'notifications/unsubscribe/sid/' . $subs->sid, array('query' => $drupal_destination)); } elseif (function_exists('notifications_anonymous_manage_links')) { $operations[] = notifications_anonymous_manage_links('subscription', $subs); } $form['operations'][$subs->sid] = array('#value' => implode(', ', $operations)); } $form['subscriptions'] = array('#type' => 'checkboxes', '#options' => $select); $form['pager'] = array('#value' => theme('pager', NULL, 20, 0)); $form['#theme'] = 'notifications_manage_subscriptions'; return $form; } /** * Form options */ function notifications_destination_manage_subscriptions_form_options($account) { $form['options'] = array( '#type' => 'fieldset', '#title' => t('Update options'), '#prefix' => '' . implode('
', $help) . '
'; $form['account'] = array('#type' => 'value', '#value' => $account); // And we don't pass an account here because we don't want address validated for it $form['send_method'] = notifications_destination_address_subform(NULL, NULL, $send_methods); $form['submit'] = array('#type' => 'submit', '#value' => t('Unsubscribe')); return $form; } /** * Validate submitted values */ function notifications_destination_request_form_validate($form, &$form_state) { $dest = notifications_destination_parse_submitted($form_state['values'], TRUE); } /** * Process submitted values */ function notifications_destination_request_form_submit($form, &$form_state) { $dest = notifications_destination_parse_submitted($form_state['values']); if ($dest['type'] && $dest['address'] && ($destination = Messaging_Destination::get_by_address($dest['type'], $dest['address']))) { if ($destination->uid && ($account = $destination->get_account())) { // It is possible also that a registered user has used someone else's address. // If so, we send a link to delete all user's subscriptions. Fuck them! $result = notifications_destination_message_send('user-unsubscribe', $destination, $dest['method'], array('user' => $account)); } else { // It is a destination for an anonymous user $result = notifications_destination_message_send('destination-unsubscribe', $destination, $dest['method']); } if (!empty($result)) { drupal_set_message(t('A message has been sent to that address with instructions to unsubscribe.')); } else { drupal_set_message(t('Cannot send message to that address. Please contact the site administrator.'), 'warning'); } } else { drupal_set_message(t('We cannot find that address on this site.'), 'error'); } } /** * Send message to destination * * @param $message * Message data or message template name ('notifications-' will be prepended) * @param $destination * Destination object */ function notifications_destination_message_send($message, $destination, $send_method = NULL, $objects = array(), $priority = 0) { if (is_string($message) && $send_method) { // We have a template name, message needs to be built $template = 'notifications-' . $message; $account = $destination->get_account(); $objects += array('destination' => $destination, 'user' => $account); $language = user_preferred_language($account); $message = messaging_template_build($template, $send_method, $language, $objects); $message->set_destination($destination); $message->priority = $priority; } if ($message && $send_method) { return messaging_message_send_destination($send_method, $destination, $message); } else { // Something's gone wrong return FALSE; } } /** * Update sending destinations when disabled a send method * * @todo This may be better in a batch * * @param $old * Old sending method * @param $new * Optional new sending method to replace the old one */ function notifications_destination_method_replace($old, $new) { // Purge notifications queue, we may lose some notifications but it's the safest option. $deleted = notifications_queue()->queue_delete(array('send_method' => $old)); if ($new) { $old_type = messaging_method_info($old, 'address_type'); $new_type = messaging_method_info($new, 'address_type'); // If both methods have the same address type, just replace methods if ($old_type == $new_type) { db_query("UPDATE {notifications} SET send_method = '%s' WHERE send_method = '%s'", $new, $old); $replaced = db_affected_rows(); } else { // First try a bulk replacement for users that have both types of destination db_query("UPDATE {notifications} s INNER JOIN {messaging_destination} d ON s.uid = d.uid SET s.mdid = d.mdid, s.send_method = '%s', s.destination = d.address WHERE s.uid > 0 AND s.send_method = '%s' AND d.type = '%s'", $new, $old, $new_type); $replaced = db_affected_rows(); // Now find a replacement for the rest. In case there are more than one subscription for a destination, process all at once // Unless this was a database field, which we should have already fixed. When no destination user has no data $result = db_query("SELECT DISTINCT uid, mdid FROM {notifications} WHERE uid > 0 AND send_method = '%s'", $old); if (!$new_type || !$field || !$table) { while ($subs = db_fetch_object($result)) { if (($account = notifications_load_user($subs->uid)) && ($dest = messaging_account_build_destination($account, $new))) { db_query("UPDATE {notifications} SET mdid = %d, send_method = '%s', destination = '%s' WHERE mdid = %d", $dest->mdid, $new, $dest->address, $subs->mdid); $replaced += db_affected_rows(); $created++; } } } } } // Block remaining subscriptions for old sending method db_query("UPDATE {notifications} SET status = %d WHERE send_method = '%s'", Notifications_Subscription::STATUS_BLOCKED, $old); $blocked = db_affected_rows(); // Print out some messages about what's happened if (!empty($replaced)) { drupal_set_message(t("Updated @count user subscriptions with a new destination.", array('@count' => $replaced))); } if (!empty($blocked)) { drupal_set_message(t("Blocked @count subscriptions as we cannot find a replacement destination.", array('@count' => $blocked)), 'warning'); } if (!empty($deleted)) { drupal_set_message(t("Deleted @count notifications from queue, corresponding to the disabled method.", array('@count' => $deleted))); } } /** * Bulk create destinations for users in notifications table */