We had someone create some custom modules for us (no longer around) and we're trying to understand them.

For example the module below sends and email when it's a users birthday - we want to be able to edit the actual email that's sent but can't find it anywhere! Can you give us an idea of where we should look?

Thanks!

<?php
/**
 * ODL Birthday Notifications
 * =================================
 *
 * Send out an e-mail/pm/sms on a users birthday
 * Uses the notification_log to log that a notification has been sent for this year
 */

/**
 * Implements hook_notifications().
 */
function odl_notifications_birthday_notifications() {
  return array(
    'user_birthday' => array(
      'title' => 'Birthday Message',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_CRON,
      'trigger_cron' => array('callback' => 'odl_notifications_birthday_run'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail', 'textanywhere', 'privatemsg'),
      ),
    ),
  );
}

/**
 * Run the cron job that sends notifications for a user's birthday.
 * @return array
 */
function odl_notifications_birthday_run() {

  $day = (int) date('w');
  $current_hour = (int) date('H');

  // TODO: Base this on the user's timezone information.
  if ($day == 0 || $day == 6) {
    // Send between 1pm and 6pm on weekends
    if (!($current_hour > 13 && $current_hour < 18)) return;
  } else {
    // Send between 10am and 6pm on weekdays
    if (!($current_hour > 10 && $current_hour < 18)) return;
  }



  // Find all user's that have a birthday TODAY (if we have missed the notification then don't send one!)
  $accounts = _odl_notifications_birthday_fetch_users();

  // Filter out those that have had a notification sent today
  odl_notifications_birthday_filter_sent_notifications($accounts);

  // Return a context for the notifications containing the recipient and node
  $notification_contexts = array();

  foreach ($accounts as $account) {

    $notification_context = array(
      'recipient' => $account,
    );
    $notification_contexts[] = $notification_context;

  }

  return $notification_contexts;
}

/**
 * Look at the notification log and filter out any notifications that have already been
 * sent today.
 * @param $accounts
 */
function odl_notifications_birthday_filter_sent_notifications(&$accounts) {
  $uids = array();
  $sent_uids = array();

  foreach ($accounts as $account) {
    $uids[] = $account->uid;
  }

  $result = db_query("SELECT recipient_uid FROM {notification_log} date_of_birth
    WHERE notification_identifier='user_birthday'
    AND FROM_UNIXTIME(date_sent, '%d-%m') = :current_date", array(':current_date' => date('d-m')));

  foreach ($result as $record) {
    $sent_uids[] = $record->recipient_uid;
  }

  foreach ($accounts as $index => $account) {
    if (array_search($account->uid, $sent_uids) !== FALSE) {
      unset($accounts[$index]);
    }
  }

}

/**
 * Return a list of users that have a birthday set for today.
 * @return array
 */
function _odl_notifications_birthday_fetch_users() {

  $result = db_query("SELECT entity_id FROM {field_revision_field_date_of_birth} date_of_birth
    WHERE entity_type='user'
    AND DATE_FORMAT(field_date_of_birth_value, '%d-%m') = :current_date", array(':current_date' => date('d-m')));

  $uids = array();

  foreach ($result as $record) {
    $uids[] = $record->entity_id;
  }

  return user_load_multiple($uids);

}





/**
 * Implementation of hook_form_odl_notifications_edit_form_alter().
 */
function odl_notifications_birthday_form_odl_notifications_edit_form_alter(&$form, &$form_state) {

  $identifier = $form_state['storage']['identifier'];

  // Only add fields to the event reminder form
  if ($identifier != "user_birthday") {
    return;
  }

  $form['#submit'][] = 'odl_notifications_birthday_notifications_edit_form_submit';

  $form['test'] = array(
    '#type' => 'fieldset',
    '#title' => 'Test',
  );

  $form['test'][] = array(
    '#type' => 'submit',
    '#value' => 'TEST',
  );
}

/**
 * Submit handler to save the event reminder frequency settings
 * @param $form
 * @param $form_state
 */
function odl_notifications_birthday_notifications_edit_form_submit($form, $form_state) {
  if ($form_state['clicked_button']['#value'] == 'TEST') {

    /*db_insert('reminders')->fields(array(
      'type' => 'payday_reminder',
      'uid' => 1,
      'created' => time(),
      'reminder_date' => time() - 300
    ))->execute();*/

    odl_notifications_cron();
  }
}

Comments

dotmundo’s picture

It looks like your site is using the Notifications module. Thus it is most likely that the email is actually managed by this module which means it's probably stored in the database. See https://www.drupal.org/project/notifications

Go to your Configuration screen, locate Notifications and have a look. Good luck.

Anonymous’s picture

I agree with dotmundo. It appears the developer used the 'notifications' module. The custom email template it uses should be available in the configuration options.

simonDRPL2183’s picture

Thanks both. Yes, we do seem to have the notifications module installed but it looks like a custom/modified version. There's nothing in config/admin :( I've looked through the database too and can't see the email body text in there either.

This is killing me!

simonDRPL2183’s picture

So I found this below but STILL can't see where the actual email body comes from!

<?php
/**
 * ODL Notifications
 * =================
 *
 * This is a custom notification framework for controlling different types of messages
 * sent through the site. It makes use of the messages framework to actually send the messages
 * just providing a way for other modules to implement different types of notifications
 *
 * Notifications are registered through hook_notifications() which will return different information
 * about a notification.
 *
 * Notifications can be triggered by an e-mail being sent, a cron task, or manually invoked
 */

require_once dirname(__FILE__) . '/includes/odl_notifications.classes.inc';

/**
 * Implements hook_theme().
 */
function odl_notifications_theme() {
  return array(
    'odl_notifications_checkbox_table' => array(
      'render element' => 'form',
    ),
  );
}

/**
 * Implements hook_menu().
 */
function odl_notifications_menu() {
  $items = array();

  // A list of site wide notifications
  $items['admin/config/odl-notification'] = array(
    'page callback' => 'odl_notifications_list',
    'file' => 'includes/odl_notifications.admin.inc',
    'title' => 'Notifications',
    'type' => MENU_NORMAL_ITEM,
    'access arguments' => array('administer site content'),
  );

  // An edit page for a specific notification
  $items['admin/config/odl-notification/%/edit'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array('odl_notifications_edit_form', 3),
    'title callback' => 'odl_notifications_edit_page_title',
    'title arguments' => array(3),
    'file' => 'includes/odl_notifications.admin.inc',
    'type' => MENU_CALLBACK,
    'access arguments' => array('administer site content'),
  );

  return $items;
}

/**
 * Callback to get the title/name of the identifier
 * @param $identifier
 * @return mixed
 */
function odl_notifications_edit_page_title($identifier) {
  $notification = odl_notifications_load_notification($identifier);
  if ($notification) {
    return $notification->get_title();
  }
}

/**
 * Implements hook_notifications().
 */
function odl_notifications_notifications() {
  return array(
    'support_ticket_created' => array(
      'title' => 'Support Ticket Created',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'support_ticket_new'),
      'handler_config' => array(
        'allowed_handlers' => array('privatemsg'),
        'odl_mail' => array(
          'body_variable_key' => 'support_mail_ticket_new_body',
          'subject_variable_key' => 'support_mail_ticket_new_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
    'support_ticket_updated' => array(
      'title' => 'Support Ticket Updated',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'support_ticket_comment_new'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail'),
        'odl_mail' => array(
          'body_variable_key' => 'support_mail_ticket_comment_new_body',
          'subject_variable_key' => 'support_mail_ticket_comment_new_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
    'user_register_admin_created' => array(
      'title' => 'Register Account by Admin',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'user_register_admin_created'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail'),
        'odl_mail' => array(
          'body_variable_key' => 'user_mail_register_admin_created_body',
          'subject_variable_key' => 'user_mail_register_admin_created_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
    'user_register_pending_approval' => array(
      'title' => 'Register Account Pending Approval',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'user_register_pending_approval'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail'),
        'odl_mail' => array(
          'body_variable_key' => 'user_mail_register_pending_approval_body',
          'subject_variable_key' => 'user_mail_register_pending_approval_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
    'user_register_no_approval_required' => array(
      'title' => 'Register Account No Approval',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'user_register_no_approval_required'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail'),
        'odl_mail' => array(
          'body_variable_key' => 'user_mail_register_no_approval_required_body',
          'subject_variable_key' => 'user_mail_register_no_approval_required_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
    'user_password_reset' => array(
      'title' => 'Password Reset',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'user_password_reset'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail'),
        'odl_mail' => array(
          'body_variable_key' => 'user_mail_password_reset_body',
          'subject_variable_key' => 'user_mail_password_reset_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
    'user_status_activated' => array(
      'title' => 'Account Activated',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'user_status_activated'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail'),
        'odl_mail' => array(
          'body_variable_key' => 'user_mail_status_activated_body',
          'subject_variable_key' => 'user_mail_status_activated_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
    'user_status_blocked' => array(
      'title' => 'Account Blocked',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'user_status_blocked'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail'),
        'odl_mail' => array(
          'body_variable_key' => 'user_mail_status_blocked_body',
          'subject_variable_key' => 'user_mail_status_blocked_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
    'user_cancel_confirm' => array(
      'title' => 'Account Cancellation Confirmation',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'user_cancel_confirm'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail'),
        'odl_mail' => array(
          'body_variable_key' => 'user_mail_cancel_confirm_body',
          'subject_variable_key' => 'user_mail_cancel_confirm_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
    'user_status_canceled' => array(
      'title' => 'Account Cancelled',
      'trigger_type' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
      'trigger_email' => array('id' => 'user_status_canceled'),
      'handler_config' => array(
        'allowed_handlers' => array('odl_mail'),
        'odl_mail' => array(
          'body_variable_key' => 'user_mail_status_canceled_body',
          'subject_variable_key' => 'user_mail_status_canceled_subject',
        ),
        'user_editable' => FALSE,
      ),
    ),
  );
}

/**
 * Load a single notification class by identifier
 *
 * The identifier is the array key of the notifications a module may define in hook_notifications()
 * @param $identifier
 * @return Notification|null
 */
function odl_notifications_load_notification($identifier) {
  $notifications = odl_notifications_load_notifications();
  if (isset($notifications[$identifier])) {
    return $notifications[$identifier];
  }
}

/**
 * Load and process all notifications.
 *
 * @return array
 *   Returns an array of notification classes
 */
function odl_notifications_load_notifications() {
  $notifications = &drupal_static(__FUNCTION__, array());

  if (empty($notifications)) {
    $notifications_array = module_invoke_all('notifications');
    drupal_alter('notifications', $notifications_array);

    foreach ($notifications_array as $identifier => $notification_array) {
      $title = _odl_notifications_get_single_config_value($notification_array, 'title', TRUE);
      $class = NULL;
      // Allow either a custom class to be specified,
      if ($class_name = _odl_notifications_get_single_config_value($notification_array, 'handler_class')) {
        $class = new $class_name($identifier);
        $class->set_title = $title;
        $trigger_class_names = _odl_notifications_get_single_config_value($notification_array, 'trigger_classes', FALSE, array());
        $trigger_class_name = _odl_notifications_get_single_config_value($notification_array, 'trigger_class');
        if ($trigger_class_name) {
          $trigger_class_names[] = $trigger_class_name;
        }

        foreach ($trigger_class_names as $class_name) {
          $trigger_class = new $class_name;
          $class->add_trigger($trigger_class);
        }

        $notifications[$identifier] = $class;
      }
      // Or create a generic class based on the trigger type (email/cron).
      else {
        $trigger_type = _odl_notifications_get_config_value($notification_array, 'trigger_type', TRUE);
        $default_handlers = _odl_notifications_get_config_value($notification_array, array('handler_config' => 'allowed_handlers'), TRUE);
        $handler = new Notification($identifier);
        $handler->set_title($title);
        $handler->set_config($notification_array);
        $handler->set_default_message_handlers($default_handlers);
        $trigger = NULL;

        switch ($trigger_type) {
          case NOTIFICATION_TRIGGER_SOURCE_EMAIL:
            $email_id = _odl_notifications_get_config_value($notification_array, array('trigger_email' => 'id'), TRUE);

            $trigger = new EmailTrigger();
            $trigger->set_email_id($email_id);

            break;
          case NOTIFICATION_TRIGGER_SOURCE_CRON:
            $callback = _odl_notifications_get_config_value($notification_array, array('trigger_cron' => 'callback'), TRUE);

            $trigger = new CronTrigger();
            $trigger->set_callback($callback);

            break;
          case NOTIFICATION_TRIGGER_SOURCE_CODE:
            // No Triggers
            break;
          default:
            var_export($notification_array);
            // TODO: Throw error
            die("unhandled notification trigger type");
        }
        $handler->add_trigger($trigger_type, $trigger);

        $notifications[$identifier] = $handler;
      }
    }

  }

  return $notifications;
}


/**
 * Trigger notifications based on an e-mail being sent
 *
 * This allows drupal_mail() to trigger other types of notifications.
 * @param $mail
 */
function odl_notifications_trigger_from_email($mail) {
  $notifications = odl_notifications_load_notifications();

  $context = array(
    // Make sure another e-mail is not sent if this is triggered
    // from drupal_mail!
    'triggered_from' => NOTIFICATION_TRIGGER_SOURCE_EMAIL,
    'email_id' => $mail['id'],
    // TODO: Is this always set?
    'recipient' => $mail['params']['account'],
    'subject' => $mail['subject'],
    'body' => $mail['body'],
  );

  foreach ($notifications as $notification) {
    // Check for any e-mail triggers than match the criteria
    // Normally this is just checking the e-mail id, however more
    // complex trigger criteria may be implemented.
    $matches = $notification->check_triggers(NOTIFICATION_TRIGGER_SOURCE_EMAIL, $context);
    if (!empty($matches)) {
      $notification->send_notifications($context);
    }
  }

}

/**
 * Implementation of hook_cron().
 */
function odl_notifications_cron() {

  // Load all notifications and process any that have cron triggers
  $notifications = odl_notifications_load_notifications();

  $global_context = array(
    'triggered_from' => NOTIFICATION_TRIGGER_SOURCE_CRON,
  );

  foreach ($notifications as $notification) {

    // See if this notification has any cron triggers that match the current context
    $matches = $notification->check_triggers(NOTIFICATION_TRIGGER_SOURCE_CRON, $global_context);

    if (!empty($matches)) {

      // Get a callback which will return one context per notification to send.
      $callback = $notification->get_config_value(array('trigger_cron' => 'callback'));

      if ($callback) {
        $contexts = call_user_func($callback);

        foreach ($contexts as $user_context) {
          // Merge the user specific context with the global one
          $context = array_merge($user_context, $global_context);
          $notification->send_notifications($context);
        }
      }
    }
  }

  // Process any event reminder triggers which are stored differently.
  $frequencies = odl_reminders_events_get_frequencies();
  sort($frequencies, SORT_NUMERIC);
  $sent = array();
  foreach ($frequencies as $frequency_days) {
    // Convert the reminder frequency to seconds.
    $frequency_seconds = $frequency_days * 86400;

    $query = new EntityFieldQuery();
    $results = $query->entityCondition('entity_type', 'node')
      ->propertyCondition('type', 'node_event')
      ->fieldCondition('field_date', 'value', time() + $frequency_seconds, '<')
      ->fieldCondition('field_date', 'value', time(), '>')
      ->execute();

    // If there are no results then don't do anything for this frequency.
    if (empty($results['node'])) {
      continue;
    }

    // For every event that's happening in the desired timeframe, fire
    // notifications to signed up users.
    foreach ($results['node'] as $nid => $event) {
      $attending = cti_user_lists_users_attending($nid, TRUE);
      foreach ($attending as $account) {
        // If the user has already been sent notifications about this event
        // then don't send another because it is also within the next frequency
        // boundary.
        if (!empty($sent[$account->uid]) && in_array($event->nid, $sent[$account->uid])) {
          continue;
        }

        // If the user has already been sent notifications about this event
        // for this frequency on a previous occasion then don't send another.
        $result = db_query(
            "SELECT nid FROM {reminders_events} WHERE uid = :uid AND nid = :nid AND days <= :days",
            array(':uid' => $account->uid, ':nid' => $event->nid, ':days' => $frequency_days)
          )
          ->fetchCol();

        if (!empty($result)) {
          continue;
        }


        $account_settings = odl_notifications_load_user_settings($account);

        if (empty($account_settings) || empty($account_settings['event_reminder'])) {
          $account_handlers = array();
        }
        else {
          foreach ($account_settings['event_reminder'] as $handler => $handler_setting) {
            if (!$handler_setting->enabled || !$handler_setting->settings[$frequency_days]) {
              continue;
            }

            $account_handlers[] = $handler;
          }
        }

        // If the user does not have any handlers enabled for this frequency
        // then don't notify them.
        if (empty($account_handlers)) {
          continue;
        }

        // Load Notification object & full event for replacements.
        $notifications = odl_notifications_load_notifications();
        $notification = $notifications['event_reminder'];
        $full_event = node_load($event->nid);
        $context = array(
          'node' => $full_event,
          'subject' => t('OutdoorLads Event Reminder'),
          'recipient' => $account,
          'triggered_from' => NOTIFICATION_TRIGGER_SOURCE_CRON,
          'handlers' => $account_handlers,
          'tokens' => array(
            '[event_reminder:days]' => _odl_reminders_events_format_days_until($full_event),
          ),
        );

        // Send the notifications.
        $notification->send_notifications($context);

        // Add to sent array to prevent resending.
        $sent[$account->uid][] = $event->nid;
        // Record sending to prevent duplication.
        db_merge('reminders_events')
          ->key(array(
            'uid' => $account->uid,
            'nid' => $event->nid,
            'days' => $frequency_days,
          ))
          ->fields(array(
            'uid' => $account->uid,
            'nid' => $event->nid,
            'days' => $frequency_days,
          ))
          ->execute();
      }
    }
  }
}


/**
 * Implements hook_user_update().
 */
function odl_notifications_user_update(&$edit, $account, $category) {

  // Save all the selected sending methods for each notification.
  odl_notifications_save_user_notification_settings($edit, $account);
}



/**
 * Implements hook_form_TYPE_alter().
 *
 * Adds checkboxes of what messages to send for each notification to the
 * user edit form.
 */
function odl_notifications_form_user_profile_form_alter(&$form, &$form_state) {
  if ($form['#user_category'] == 'account') {

    $account = $form_state['user'];

    // Create array to be able to merge in fieldset and avoid overwriting
    // already added options.
    if (!isset($form['notifications'])) {
      $form['notifications'] = array();
    }

    $form['notifications'] += array(
      '#type' => 'fieldset',
      '#title' => t('Notifications'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#weight' => 11,
      '#theme' => 'odl_notifications_checkbox_table',
    );

    $notifications = odl_notifications_load_notifications();

    foreach ($notifications as $notification) {

      // Get a form of checkboxes for each notification method (if enabled)
      $partial_form = odl_notifications_handler_form_partial($notification, $account);

      if ($partial_form) {
        $form['notifications'][$notification->get_id()] = $partial_form;
      }

    }

  }
}

/**
 * Load a users preferences for a specific notification, one line per handler
 * @param $account
 * @param null $identifier
 *   The notification id
 * @return array
 *   Returns an array of either all settings or just those for an identifier
 */
function odl_notifications_load_user_settings($account, $identifier = NULL) {
  $settings = array();

  $result = db_query("SELECT * FROM {notification_settings} WHERE uid = :uid", array(':uid' => $account->uid));
  foreach ($result as $record) {
    if (!isset($settings[$record->type])) {
      $settings[$record->type] = array();
    }

    // For some reason ->settings column is not automatically un-serialized
    // If this is not done, we get recursive serialization.
    $record->settings = unserialize($record->settings);

    $settings[$record->type][$record->notification_method] = $record;
  }

  if ($identifier) {
    if (!isset($settings[$identifier])) {
      return NULL;
    }
    return $settings[$identifier];
  }

  return $settings;

}

/**
 * Save the settings for a single handler, such as what message handlers are enabled
 * @param $values
 * @param $account
 */
function odl_notifications_save_user_notification_settings($values, $account) {

  $all_handler_values = _odl_notifications_collect_user_edit_values($values, 'handlers', 'notifications');
  $notification_current_settings = odl_notifications_load_user_settings($account);

  foreach ($all_handler_values as $identifier => $handler_values) {

    foreach ($handler_values as $handler_id => $enabled) {
      // Private Message handlers should always be enabled
      if($handler_id == 'privatemsg') {
        $enabled = 1;
      }

      $primary_keys = array();

      if (isset($notification_current_settings[$identifier][$handler_id])) {
        $settings = $notification_current_settings[$identifier][$handler_id];

        $settings->enabled = (bool) $enabled;
        $primary_keys[] = 'id';
      }
      // If the handler does not currently exist, create it
      else {
        $settings = (object) array(
          'type' => $identifier,
          'notification_method' => $handler_id,
          'uid' => $account->uid,
          'enabled' => (bool) $enabled,
          'settings' => array(),
        );
      }

      drupal_write_record('notification_settings', $settings, $primary_keys);
    }
  }

}

function odl_notifications_get_checkbox_options($handlers) {
  $handler_options = array();
  $handler_display_names = array(
    'odl_mail' => 'E-Mail',
    'textanywhere' => 'Text Message',
    'privatemsg' => 'Private Message'
  );

  foreach ($handlers as $handler) {
    if (isset($handler_display_names[$handler])) {
      $handler_options[$handler] = $handler_display_names[$handler];
    } else {
      $handler_options[$handler] = $handler;
    }

  }

  return $handler_options;
}

/**
 * Returns checkboxes for each of the notification handlers for the specified notification.
 * @param $notification
 * @param null $account
 * @return array|null
 */
function odl_notifications_handler_form_partial($notification, $account=NULL) {

  // Skip any handlers that are not user editable
  if ($notification->get_config_value(array('handler_config' => 'user_editable')) === FALSE) {
    return NULL;
  }

  // Get all handlers that are not disabled by the admin
  $handlers = $notification->get_enabled_handlers(NULL);

  $handler_options = odl_notifications_get_checkbox_options($handlers);
  $default_values = $notification->get_enabled_handlers($account);

  $checkboxes = array(
    '#type' => 'checkboxes',
    '#options' => $handler_options,
    '#default_value' => $default_values,
    '#title' => $notification->get_title(),
  );

  //Add Disabled to privatemsg option
  foreach($handlers as $handler) {
    $checkboxes[$handler] = array('#disabled' => $handler == 'privatemsg' ? TRUE : FALSE);
  }

  $form = array();
  $form['notifications__handlers__' . $notification->get_id()] = $checkboxes;

  return $form;
}


/**
 * Theme a fieldset containing groups of checkboxes into a table of checkboxes
 * @param $form
 * @return string
 */
function theme_odl_notifications_checkbox_table($form) {

  // Note: this array is multi-dimensional as we may have more than one
  // type of form field to keep track of.
  $unique_headers = array();
  $notifications = odl_notifications_load_notifications();

  // First we need to gather the global list of unique headers for all entries
  foreach (element_children($form['form']) as $notification_identifier) {
    // Each notification row may have multiple forms to render to the row
    foreach (element_children($form['form'][$notification_identifier]) as $index => $form_key) {
      $f = $form['form'][$notification_identifier][$form_key];

      if ($f['#type'] == 'checkboxes') {
        // If we have a group of checkboxes, render each one individually
        foreach (element_children($f) as $checkbox_id) {
          _odl_notifications_add_header($index, $f[$checkbox_id]['#title'], $unique_headers);
        }
      }
      else {
          _odl_notifications_add_header($index, $f['#title'], $unique_headers);
      }
    }
  }


  $rows = array();

  // Now we render out the form elements to table cells
  // This will add an empty cell if there is no value for a specific header
  foreach (element_children($form['form']) as $notification_identifier) {

    // Add a column for the title of the notification
    $cells = array($notifications[$notification_identifier]->get_title());

    foreach (element_children($form['form'][$notification_identifier]) as $index => $form_key) {

      $headers = $unique_headers[$index];
      $f = $form['form'][$notification_identifier][$form_key];
      $c = array();

      if ($f['#type'] == 'checkboxes') {
        // If we have a group of checkboxes, render each one individually
        foreach (element_children($f) as $checkbox_id) {
          $checkbox = $f[$checkbox_id];
          $title = $checkbox['#title'];
          // The title is set as the table column header so remove from output
          unset($checkbox['#title']);
          $c[$title] = drupal_render($checkbox);
        }
      } else {
        $c[$f['#title']] = drupal_render($f);
      }

      // Some rows may have a different number of options(columns) available
      // Make sure every row has the same number of columns
      foreach ($headers as $header_title) {
        if (isset($c[$header_title])) {
          $cells[] = $c[$header_title];
        }
        else {
          $cells[] = '';
        }
      }

    }

    $rows[] = $cells;
  }

  // Add a column for the title of the notification
  $headers = array('Title');
  // Merge the multi-dimensional array unique headers into a flat array of headers
  foreach ($unique_headers as $header_row) {
    $headers = array_merge($headers, $header_row);
  }

  $attributes = array('class' => array('notifications-settings-table'));

  return theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => $attributes));
}

/**
 * Helper to keep track of unique headers for a table of form elements
 * @param $index
 * @param $title
 * @param $unique_headers
 */
function _odl_notifications_add_header($index, $title, &$unique_headers) {

  if (!isset($unique_headers[$index])) {
    $unique_headers[$index] = array();
  }

  // Only add this option as a header if it does not already exist
  if (array_search($title, $unique_headers[$index]) === FALSE) {
    $unique_headers[$index][] = $title;
  }

}

/**
 * Parse out a single array of keys and values into a multi-dimensional array
 * @param $edit
 * @param $key
 * @param string $identifier
 * @return array
 */
function _odl_notifications_collect_user_edit_values($edit, $key, $identifier='notifications') {
  $key = "{$identifier}__{$key}__";
  $index_values = array();
  foreach ($edit as $form_key => $values) {
    if (!strncmp($form_key, $key, strlen($key))) {
      // Get the index/identifier which is the last part of the key
      $index = str_replace($key, '', $form_key);
      $index_values[$index] = $values;
    }
  }
  return $index_values;
}

/**
 * Helper function to get a value from the config based on a single dimensional array key.
 * @param array $info
 * @param $key
 * @param bool $throw_error_if_not_set
 * @param null $default
 * @return null
 */
function _odl_notifications_get_single_config_value(array $info, $key, $throw_error_if_not_set=FALSE, $default=NULL) {
  if (isset($info[$key])) {
    return $info[$key];
  }
  if ($throw_error_if_not_set) {
    drupal_set_message("Notifications: Could not find key " . check_plain($key));
    // TODO: Watchdog entry
  }
  return $default;
}

/**
 * Helper function to get a config value, supports the key being passed in as an array to traverse into the config.
 *
 * For example array('handler_config' => 'odl_mail') as the keys will end up looking
 * at $info['handler_config']['odl_mail']
 * @param array $info
 * @param $keys
 * @param bool $throw_error_if_not_set
 * @param null $default
 * @return null
 */
function _odl_notifications_get_config_value(array $info, $keys, $throw_error_if_not_set=FALSE, $default=NULL) {

  if (!is_array($keys)) {
    return _odl_notifications_get_single_config_value($info, $keys, $throw_error_if_not_set, $default);
  }

  $new_info = $info;

  // Recursively process the keys passed in
  foreach ($keys as $k => $v) {
    if (!is_numeric($k)) {
      $new_info = _odl_notifications_get_single_config_value($info, $k, $throw_error_if_not_set, $default);
    }
    if ($new_info === NULL) {
      return NULL;
    }
    return _odl_notifications_get_config_value($new_info, $v, $throw_error_if_not_set, $default);
  }

  return NULL;
}
Anonymous’s picture

Without seeing all of the code for the module, it's going to be hard to give you an exact answer. In looking at the code you provided, the module creates two menu items using hook_menu:

admin/config/odl-notification
and
admin/config/odl-notification/%/edit

The first one is a list view of all the site-wide notifications, and the second one is the edit page for those individual notifications (the % is accepting an argument, most likely the notification id). You should start by viewing the listing page first to see if you can edit them individually from there, to see if editing the message body is possible.

If you want to just disable the notifications, you can do that by commenting out the three calls to $notification->send_notifications($context); in the code you provided.

Also, the body of the message being sent is stored in the $mail['body'] value, which is stored in the $context array. If I believe correctly, the $mail['body'] variable is used with drupals drupal_mail() system, so you could also start by looking at the default mail template for the site to see if the language is in there. If it's not, start looking at any included (usually denoted as .inc file extension) files that came with the module to see if the body is dynamically generated somewhere.

Again, without having all of the code for the module, it's difficult to solve the problem or you so all I can do is offer suggestions to help you find the solution yourself.

simonDRPL2183’s picture

Thanks justinfurnas. Where might I find the default mail template for the site?

Anonymous’s picture

That's a good question. Are you using Drupal's default mail system, or is another one installed?

'Configuration>System>Mail System' will give you the information you need. By default it should say 'DefaultMailSystem', but if you have another mail system installed (such as MimeMail or HTMLMail), then it may be changed. I haven't used the notifications module extensively enough to know if it uses it's own extension of the mail system. If it's still set to 'DefaultSystemMail', then it's probably generating the body of the email somewhere in the module, and not in the actual template for the email. For that, you'll need to dig further into the modules code to find out where it's generating the body.

Do you have the devel module installed? If not, install it. If so, run a dpm($mail['body']); before the sendnotifications functions are called and see if that array actually contains the text you are seeing in the email. From there you can trace back to where it's being set at.

It will give you a very nice krumo style collapsible tree of the array/object structure of the variable you pass to it. Very useful for debugging.

dotmundo’s picture

Looking at the code isn't going to help especially if you are new to Drupal. There is a configuration screen, it just may not be upfront and might be a sub-option. Looking at the Notifications module, it does have a UI screen for configuration and it looks like its part of the Messaging configuration screen. The .info file also shows Messaging is a dependency. Therefore in your Configuration screen look for the Messaging option and from there you might see an option for Notifications.

simonDRPL2183’s picture

Thanks both for your help. I'll keep trying!