'Notifications', 'file' => 'workflow_notify.pages.inc', 'access arguments' => array('administer workflow'), 'page callback' => 'drupal_get_form', 'page arguments' => array('workflow_notify_settings_form', $id_count + 1), 'type' => MENU_CALLBACK, ); return $items; } /** * Implements hook_workflow_operations(). */ function workflow_notify_workflow_operations($op, Workflow $workflow = NULL) { $admin_path = WORKFLOW_ADMIN_UI_PATH; switch ($op) { case 'workflow': $actions = array(); if ($workflow && $workflow->getStates()) { $wid = $workflow->getWorkflowId(); $alt = t('Notify users about state changes.'); $actions = array( 'workflow_notify_settings' => array( 'title' => t('Notifications'), 'href' => "$admin_path/manage/$wid/notify", 'attributes' => array('alt' => $alt, 'title' => $alt), ), ); } else { // Generate a dummy, if no states exist. $actions = array( 'workflow_notify_settings' => array( 'title' => '', 'href' => '', ), ); } return $actions; } } /** * Implements hook_permission(). */ function workflow_notify_permission() { return array( 'workflow notify' => array( 'title' => t('Receive workflow notifications'), 'description' => t('The user may be notified of a workflow state change.'), ), ); } /** * Implements hook_help(). */ function workflow_notify_help($path, $arg) { switch ($path) { case WORKFLOW_ADMIN_UI_PATH . '/notify/%': return '

' . t('The selected roles will be notified of each state change selected.') . '

'; } } /** * Implements hook_theme(). */ function workflow_notify_theme() { return array( 'workflow_notify_settings_form' => array( 'render element' => 'form', 'file' => 'workflow_notify.pages.inc', ), ); } /** * Implements hook_hook_info(). */ function workflow_notify_hook_info() { $hooks['workflow_notify'] = array( 'group' => 'workflow', ); return $hooks; } /** * Implements hook_workflow(). * Calls drupal_mail via _workflow_notify() for Workflow Field; * * @param $op * The current workflow operation: 'transition permitted', 'transition pre', or 'transition post'. * @param $old_state * The state ID of the current state. * @param $new_state * The state ID of the new state. * @param $node * The node whose workflow state is changing. * @param $force * The caller indicated that the transition should be forced. (bool). * This is only available on the "pre" and "post" calls. */ function workflow_notify_workflow($op, $old_state, $new_state, $entity, $force, $entity_type = '', $field_name = '', $transition = NULL, $user = NULL) { global $user; switch ($op) { // React to a transition after it's done. case 'transition post': // This is only called for Workfow Node. For Workflow Field, see workflow_entity_entity_update(). _workflow_notify($new_state, $entity, $entity_type, $field_name, $transition, $user); return; } } /** * Implements hook_entity_insert(). * Calls drupal_mail via _workflow_notify() for Workflow Field; * * @param $entity * @param $entity_type */ function workflow_notify_entity_insert($entity, $entity_type) { _workflow_notify_entity_update($entity, $entity_type); } /** * Implements hook_entity_update(). * Calls drupal_mail via _workflow_notify() for Workflow Field; * * @param $entity * @param $entity_type */ function workflow_notify_entity_update($entity, $entity_type) { _workflow_notify_entity_update($entity, $entity_type); } /** * Calls drupal_mail via _workflow_notify() for Workflow Field; * * @param $entity * @param $entity_type */ function _workflow_notify_entity_update($entity, $entity_type) { if (isset($entity->workflow_transitions)) { $new_state = workflow_node_current_state($entity, $entity_type, $field_name); foreach ($entity->workflow_transitions as $field_name => &$transition) { $new_state = workflow_node_current_state($entity, $entity_type, $field_name); _workflow_notify($new_state, $entity, $entity_type, $field_name, $transition, $user = NULL); } } return; } /** * Implements hook_mail(); * Build email messages. */ function workflow_notify_mail($key, &$message, $params) { switch ($key) { case 'workflow_notify': $filter = $params['filter']; $message['send'] = TRUE; $entity_type = $params['data']['entity_type']; $entity = isset($params['data']['entity']) ? $params['data']['entity'] : $params['data']['node']; $entity_uri = entity_uri($entity_type, $entity); list($entity_id, , $entity_bundle) = entity_extract_ids($entity_type, $entity); $message['subject'] = filter_xss(token_replace($params['context']['subject'], $params['data'], $params)); $message['body'][] = check_markup(token_replace($params['context']['body'], $params['data'], $params), $filter); watchdog('workflow_notify', '', array( '@subject' => $message['subject'], '@body' => implode('
', $message['body']), '@to' => $message['to'], '@from' => $message['from'], ), WATCHDOG_INFO, l(t('view'), $entity_uri['path'])); return; } } /** * Calls drupal_mail() to notify users. * * @param $new_state * @param $entity * @param string $entity_type * @param string $field_name * @param null $transition * @param null $user * @throws EntityMalformedException */ function _workflow_notify($new_state, $entity, $entity_type = '', $field_name = '', $transition = NULL, $user = NULL) { global $user; // See if this is a state that we notify for. $notify = variable_get('workflow_notify_roles', array()); if (!isset($notify[$new_state])) { return; } // The name of the person making the change. $changer = format_username($user); $changer_mail = $user->mail; // Okay, we are notifying someone of this change. // So let's get the workflow object. $entity_uri = entity_uri($entity_type, $entity); list($entity_id, , $entity_bundle) = entity_extract_ids($entity_type, $entity); /* @var $workflow Workflow */ $workflow = workflow_get_workflows_by_type($entity_bundle, $entity_type); $wid = $workflow->getWorkflowId(); // And all the states. $states = $workflow->getStates(TRUE); // Get the specific roles to notify. $notify = $notify[$new_state]; // See if we want to notify the author too? $notify_author = in_array(-1, $notify); unset($notify[-1]); // There could be no roles set. if ($notify) { // Get all the user accounts in those roles. $query = "SELECT DISTINCT ur.uid " . "FROM {users_roles} ur " . "INNER JOIN {users} u ON u.uid = ur.uid " . "WHERE ur.rid IN (:rids) " . "AND u.status = 1 "; $users = db_query($query, array(':rids' => $notify))->fetchCol(); } else { $users = array(); } // Some entities (like Term) have no Author. if ($notify_author && isset($entity->uid)) { $users[] = $entity->uid; } // Load all the user entities, making sure there are no duplicates. $accounts = entity_load('user', array_unique($users, SORT_NUMERIC)); // Call all modules that want to limit the list. $args = array( 'users' => $accounts, 'entity_type' => $entity_type, 'state' => $new_state, 'roles' => $notify, 'workflow' => $workflow, ); // Preparing for entities, keeping backward compatibility. $args += $entity_type == 'node' ? array('node' => $entity) : array('entity' => $entity); foreach (module_implements('workflow_notify') as $module) { $function = $module . '_workflow_notify'; $function('users', $args); } // Retrieve the remaining list without duplicates. $accounts = $args['users']; // Just quit if there are no users. if (empty($accounts)) { watchdog('workflow_notify', 'No recipients - email skipped.', array(), WATCHDOG_DEBUG, l(t('view'), $entity_uri['path'])); return; } $addr_list = array(); foreach ($accounts as $uid => $account) { $addr_list[] = format_username($account) . ' <' . $account->mail . '>'; } // The to-parameter to drupal_mail is a string, not an array, separated by commas. $to = implode(', ', $addr_list); // Retrieve the params parameter for drupal_mail. $params = array( 'clear' => TRUE, 'sanitize' => FALSE, 'data' => array( 'user' => $user, 'entity_type' => $entity_type, ), 'filter' => variable_get('workflow_notify_filter_format_' . $wid, 'filtered_html'), ); // Preparing for entities, keeping backward compatibility. $params['data'] += $entity_type == 'node' ? array('node' => $entity) : array('entity' => $entity); // Build the subject and body of the mail. // Token replacement occurs in hook_mail(). // @todo: Currently no translation occurs. $params['context']['subject'] = variable_get("workflow_notify_subject_$new_state", '[node:title] is now "[workflow:workflow-current-state-name]"'); $params['context']['body'] = variable_get("workflow_notify_body_$new_state", '[node:title] is now "@state".'); // Retrieve the from-address. switch (variable_get('workflow_notify_from_address_' . $wid, 'site')) { case 'site': $from = variable_get('site_mail', ini_get('sendmail_from')); break; case 'changer': $from = $user->mail; break; } // Send the mail, and check for success. Note that this does not guarantee // message delivery; only that there were no PHP-related issues encountered // while sending. $module = 'workflow_notify'; $key = 'workflow_notify'; $language = language_default(); // https://api.drupal.org/api/drupal/includes!mail.inc/function/drupal_mail/7.x $result = drupal_mail($module, $key, $to, $language, $params, $from); /* if ($result['result'] == TRUE) { drupal_set_message(t('Your message has been sent.')); } else { drupal_set_message(t('There was a problem sending your message and it was not sent.'), 'error'); } */ }