You are here

notifications_content.module in Notifications 5

Subscriptions to content events

File

notifications_content/notifications_content.module
View source
<?php

/**
 * @file
 * Subscriptions to content events
 */

// Max number of elements per page for user account tabs
define('NOTIFICATIONS_CONTENT_PAGER', 20);

/**
 * Implementation of hook_help()
 */
function notifications_content_help($section) {
  if (arg(0) == 'admin' && arg(1) == 'messaging' && arg(2) == 'template' && arg(3) == 'edit' && ($group = arg(4))) {
    switch ($group) {
      case 'notifications-digest-node-nid':
      case 'notifications-digest-node-type':
        $help = '<p>' . t('This is the format for each digest group. A message may consist on one or many of these groups:') . '</p>';
        $help .= '<small><pre>';
        $help .= '' . t('Group subject') . "\n";
        $help .= '- ' . t('Digest line.') . "\n";
        $help .= '- ' . t('Digest line.') . "\n";
        $help .= '-  ...' . "\n";
        $help .= t('Group footer') . "\n";
        $help .= '</pre></small>';
        return $help;
    }
  }
}

/**
 * Implementation of hook_menu_()
 */
function notifications_content_menu($may_cache) {
  global $user;

  // we need the user to to build some urls
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/messaging/notifications/content',
      'title' => t('Content types'),
      'type' => MENU_LOCAL_TASK,
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'notifications_content_settings_form',
      ),
    );
  }
  else {
    if ($user->uid && arg(0) == 'user' && is_numeric(arg(1)) && arg(2) == 'notifications' && ($user->uid == arg(1) || user_access('administer notifications'))) {
      $account = $user->uid == arg(1) ? $user : user_load(array(
        'uid' => arg(1),
      ));
      $items[] = array(
        'path' => 'user/' . $account->uid . '/notifications/thread',
        'type' => MENU_LOCAL_TASK,
        'access' => user_access('subscribe to content'),
        'title' => t('Thread'),
        'callback' => 'notifications_content_page_thread',
        'callback arguments' => array(
          $account,
        ),
        'weight' => 10,
      );
      $items[] = array(
        'path' => 'user/' . $account->uid . '/notifications/nodetype',
        'type' => MENU_LOCAL_TASK,
        'access' => user_access('subscribe to content type'),
        'title' => t('Content type'),
        'callback' => 'notifications_content_page_nodetype',
        'callback arguments' => array(
          $account,
        ),
        'weight' => 10,
      );
      $items[] = array(
        'path' => 'user/' . $account->uid . '/notifications/author',
        'type' => MENU_LOCAL_TASK,
        'access' => user_access('subscribe to author'),
        'title' => t('Author'),
        'callback' => 'notifications_content_page_author',
        'callback arguments' => array(
          $account,
        ),
        'weight' => 10,
      );
    }
  }
  return $items;
}

/**
 * Implementation of hook_perm()
 */
function notifications_content_perm() {
  return array(
    'subscribe to content',
    'subscribe to content type',
    'subscribe to author',
  );
}

/**
 * Admin settings form
 */
function notifications_content_settings_form() {

  // Allowed content types settings
  $form['content'] = array(
    '#type' => 'fieldset',
    '#title' => t('Content type subscriptions'),
    '#weight' => -10,
    '#collapsible' => TRUE,
  );
  $form['content']['notifications_content_types'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Allowed content types'),
    '#default_value' => notifications_content_types('type'),
    '#options' => node_get_types('names'),
    '#description' => t('Select content types which should be <em>allowed</em> for subscriptions to content type.'),
    '#multiple' => TRUE,
  );
  return system_settings_form($form);
}

/**
 * Implementation of hook_notifications()
 */
function notifications_content_notifications($op, &$arg0, $arg1 = NULL, $arg2 = NULL) {
  switch ($op) {
    case 'names':
      $subs =& $arg0;
      if ($subs->event_type == 'node') {
        $subs->type_name = t('Content');
        if (!empty($subs->fields['type'])) {
          $subs->names['type'] = t('Content type: %type', array(
            '%type' => node_get_types('name', $subs->fields['type']),
          ));
        }
        if (!empty($subs->fields['author']) && ($author = user_load(array(
          'uid' => $subs->fields['author'],
        )))) {
          $subs->names['author'] = t('Author: %name', array(
            '%name' => $author->name,
          ));
        }
        if (!empty($subs->fields['nid']) && ($node = node_load($subs->fields['nid']))) {
          $subs->names['thread'] = t('Thread: %title', array(
            '%title' => $node->title,
          ));
        }
      }
      break;
    case 'subscription types':
      $types['thread'] = array(
        'event_type' => 'node',
        'title' => t('Thread'),
        'access' => 'subscribe to content',
        'page' => 'notifications_content_page_thread',
        'fields' => array(
          'nid',
        ),
      );
      $types['nodetype'] = array(
        'event_type' => 'node',
        'title' => t('Content type'),
        'access' => 'subscribe to content type',
        'page' => 'notifications_content_page_nodetype',
        'fields' => array(
          'type',
        ),
      );
      $types['author'] = array(
        'event_type' => 'node',
        'title' => t('Author'),
        'access' => 'subscribe to author',
        'page' => 'notifications_content_page_author',
        'fields' => array(
          'author',
        ),
      );
      return $types;
    case 'subscription fields':

      // Information about available fields for subscriptions
      $fields['nid'] = array(
        'name' => t('Node'),
        'field' => 'nid',
        'type' => 'int',
      );
      $fields['author'] = array(
        'name' => t('Author'),
        'field' => 'author',
        'type' => 'int',
      );
      $fields['type'] = array(
        'name' => t('Node type'),
        'field' => 'author',
        'type' => 'string',
        'options callback' => 'node_get_types',
        'options arguments' => array(
          'names',
        ),
      );
      return $fields;
    case 'query':

      // This returns query elements for queue or user queries:
      // - If $arg0 is 'event', $arg1 is event type and $arg2 is $event object.
      // - If $arg0 is 'user', $arg1 is object type ('node') and $arg2 is object ($node)
      if ($arg0 == 'event' && $arg1 == 'node' && ($node = $arg2->node) || $arg0 == 'user' && $arg1 == 'node' && ($node = $arg2)) {
        $query[]['fields'] = array(
          'nid' => $node->nid,
          'type' => $node->type,
          'author' => $node->uid,
        );
        return $query;
      }
      break;
    case 'node options':
      return _notifications_content_node_options($arg0, $arg1);
    case 'event load':

      // $arg0 is event
      $event =& $arg0;
      $load = array();
      if ($event->type == 'node') {
        if (!empty($event->params['nid'])) {
          $event->objects['node'] = node_load($event->params['nid']);
        }
        if (!empty($event->params['cid'])) {
          $event->objects['comment'] = notifications_content_comment_load($event->params['cid']);
        }
      }
      break;
    case 'event types':

      // Node inserts are not grouped by node but all together. The digest will look like:
      //   New content has been submitted
      //   - Story Title1 by Author1
      //   - Event Title2 by Author2
      $types[] = array(
        'type' => 'node',
        'action' => 'insert',
        'name' => t('New content of type [type-name] has been submitted'),
        'line' => t('[type-name] [title] by [author-name]'),
        'digest' => array(
          'node',
          'type',
        ),
        'description' => t('Node creation'),
      );

      // These other events are grouped for each node. The digest will look like:
      //   Story: Title of the story
      //   - The story has been updated
      //   - New comment by User: Comment title
      $types[] = array(
        'type' => 'node',
        'action' => 'update',
        'name' => t('[type-name]: [title]'),
        'line' => t('The [type-name] has been updated'),
        'digest' => array(
          'node',
          'nid',
        ),
        'description' => t('Node update'),
      );
      $types[] = array(
        'type' => 'node',
        'action' => 'comment',
        'name' => t('[type-name]: [title]'),
        'line' => t('New comment by [comment-author-name]: [comment-title]'),
        'digest' => array(
          'node',
          'nid',
        ),
        'description' => t('Node comment'),
      );
      return $types;
    case 'access':
      $type = $arg0;
      $account =& $arg1;
      $object =& $arg2;
      $access = TRUE;

      // For events we check that node and comment are allowed
      if ($type == 'event' && $object->type == 'node') {
        if (!empty($object->objects['node'])) {
          $access = notifications_content_node_allow($account, $object->objects['node']);
        }

        // If no access to node, we don't check more
        if ($access && !empty($object->objects['comment'])) {
          $access = $access && notifications_content_comment_allow($account, $object->objects['comment']);
        }

        // For node subscriptions we check that user can view the node
      }
      elseif ($type == 'subscription') {
        $access = TRUE;
        if (!empty($object->fields['nid'])) {
          if ($node = node_load($object->fields['nid'])) {
            $access = notifications_content_node_allow($account, $node);
          }
          else {
            $access = FALSE;
          }
        }
        if (!empty($object->fields['type'])) {
          $access = $access && array_key_exists($object->fields['type'], notifications_content_types());
        }
      }
      return array(
        $access,
      );
      break;
  }
}

/**
 * Implementation of hook_messaging()
 * 
 * @see notifications_messaging()
 */
function notifications_content_messaging($op, $arg1 = NULL, $arg2 = NULL, $arg3 = NULL, $arg4 = NULL) {
  switch ($op) {
    case 'message groups':

      // These are the main entries for the template configuration page
      // Each message group will have a number of elements to be put together
      $help = t('The header and footer will be taken from Notification events');

      // Generic notifications event
      $info['notifications-event-node'] = array(
        'module' => 'notifications_content',
        'name' => t('Notifications for node events'),
        'description' => t('Defaults for all notifications related to node events.'),
        'help' => $help,
      );
      $info['notifications-event-node-insert'] = array(
        'module' => 'notifications_content',
        'name' => t('Notifications for node creation'),
        'description' => t('Notifications produced when a new node is created.'),
        'help' => $help,
      );
      $info['notifications-event-node-update'] = array(
        'module' => 'notifications_content',
        'name' => t('Notifications for node updates'),
        'description' => t('Notifications produced when a node is updated.'),
        'help' => $help,
      );
      $info['notifications-event-node-comment'] = array(
        'module' => 'notifications_content',
        'name' => t('Notifications for node comments'),
        'description' => t('Notifications produced when a comment is posted to a node.'),
        'help' => $help,
      );

      // Extra help for group digests
      $info['notifications-digest-node-nid'] = array(
        'module' => 'notifications-content',
        'name' => t('Groups digests per node'),
        'description' => t('Group of events digested for each node.'),
      );
      $info['notifications-digest-node-type'] = array(
        'module' => 'notifications-content',
        'name' => t('Groups digests per node type'),
        'description' => t('Group of events digested for each node type.'),
      );
      return $info;
    case 'message keys':

      // For each message group, there will be a number of elements, each one being part of the
      // final message. They'll usually have at least subject and content parts.
      // Some other elements (header and subject) will be taken from default Notifications templates
      $type = $arg1;
      switch ($type) {
        case 'notifications-event-node':
        case 'notifications-event-node-insert':
        case 'notifications-event-node-update':
        case 'notifications-event-node-comment':

          // Some parts will be re-used from 'notifications-event' group
          // So we specify only subject and main message
          $parts['subject'] = t('Subject');
          $parts['main'] = t('Content');
          $parts['digest'] = t('Digest line');
          return $parts;
        case 'notifications-digest-node-nid':
        case 'notifications-digest-node-type':
          $parts['title'] = t('Group title');
          $parts['footer'] = t('Group footer');
          return $parts;
      }
      break;
    case 'messages':
      $type = $arg1;

      // Default texts for node notifications templates
      switch ($type) {
        case 'notifications-event-node':
        case 'notifications-event-node-update':
          return array(
            'subject' => t('Update for [type-name]: [title]'),
            'main' => array(
              '[node-teaser]',
              t('Read more [node-url]'),
            ),
            'digest' => t('The [type-name] has been updated'),
          );
        case 'notifications-event-node-insert':
          return array(
            'subject' => t('New [type-name]: [title]'),
            'main' => array(
              '[node-teaser]',
              t('Read more [node-url]'),
            ),
            'digest' => t('[type-name] [title] by [author-name]'),
          );
        case 'notifications-event-node-comment':
          return array(
            'subject' => t('Comment for [type-name]: [title]'),
            'main' => array(
              t('Comment by [comment-author-name]: [comment-title]'),
              '[comment-body]',
              t('Read more [comment-url]'),
            ),
            'digest' => t('New comment by [comment-author-name]: [comment-title]'),
          );
        case 'notifications-digest-node-nid':
          return array(
            'title' => t('Updates for [type-name]: [title]'),
            'footer' => t('Read more [node-url]'),
          );
        case 'notifications-digest-node-type':
          return array(
            'title' => t('New content of type [type-name] has been submitted'),
            'footer' => '<none>',
          );
      }
      break;
    case 'tokens':
      $type = explode('-', $arg1);
      $tokens = array();

      // These are the token groups that will be used for this module's messages
      if ($type[0] == 'notifications' && $type[2] == 'node') {
        if ($type[1] == 'event') {
          $tokens[] = 'node';
          if ($type[3] == 'comment') {
            $tokens[] = 'comment';
          }
        }
        elseif ($type[1] == 'digest') {
          if ($type[3] == 'nid') {
            $tokens[] = 'node';
          }
          elseif ($type[3] == 'type') {
            $tokens[] = 'node-type';
          }
        }
      }
      return $tokens;
  }
}
function _notifications_content_node_options($account, $node) {

  // Default node, field are the first three indexes, but they can be overridden in params
  // Thread
  $options[] = array(
    'name' => t('This post'),
    'type' => 'thread',
    'fields' => array(
      'nid' => $node->nid,
    ),
  );

  // Content type
  $options[] = array(
    'name' => t('Posts of type %type', array(
      '%type' => node_get_types('name', $node->type),
    )),
    'type' => 'nodetype',
    'fields' => array(
      'type' => $node->type,
    ),
  );

  // Author
  $options[] = array(
    'name' => t('Posts by %name', array(
      '%name' => $node->name,
    )),
    'type' => 'author',
    'fields' => array(
      'author' => $node->uid,
    ),
  );
  return $options;
}

/**
 * Implementation of hook_nodeapi()
 */
function notifications_content_nodeapi(&$node, $op, $arg = 0) {
  global $user;
  switch ($op) {
    case 'update':

      // If inmediate sending is active, need to reset the node cache so we don't send old versions of the node
      if ($node->status && variable_get('notifications_send_immediate', 0)) {
        node_load(0, NULL, TRUE);
      }

    // else, fall through
    case 'insert':
      if ($node->status) {
        $event = array(
          'module' => 'node',
          'oid' => $node->nid,
          'type' => 'node',
          'action' => $op,
          'node' => $node,
          'params' => array(
            'nid' => $node->nid,
          ),
        );
        notifications_event($event);
      }
      break;
    case 'delete':

      // Remove all subscriptions for this node
      notifications_delete_subscriptions(array(
        'event_type' => 'node',
      ), array(
        'nid' => $node->nid,
      ));
  }
}

/**
 * Implementation of hook_comment()
 */
function notifications_content_comment($comment, $op) {
  global $user;

  // $comment can be an object or an array.
  $comment = (array) $comment;
  if (!isset($comment['nomail']) && $comment['status'] == 0 && ($op == 'insert' || $op == 'publish')) {
    $event = array(
      'module' => 'node',
      'type' => 'node',
      'action' => 'comment',
      // $op,
      'node' => node_load($comment['nid']),
      'comment' => (object) $comment,
      'params' => array(
        'nid' => $comment['nid'],
        'cid' => $comment['cid'],
      ),
    );
    notifications_event($event);
  }
}

/**
 * Implementation of hook node_type
 */
function notifications_content_node_type($op, $info) {
  if ($op == 'delete') {

    // Remove all subscriptions for this node type
    notifications_delete_subscriptions(array(
      'event_type' => 'node',
    ), array(
      'type' => $info->type,
    ));
  }
}

/**
 * Load comments with caching
 * @ TODO See if this may be some use, or drop
 */
function notifications_content_comment_load($cid) {
  static $cache;
  if (!isset($cache[$cid])) {
    $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d', $cid));
    $comment = drupal_unpack($comment);
    $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
    $cache[$cid] = $comment;
  }
  return $cache[$cid];
}

/**
 * Subscriptions page callback: List thread subscriptions
 */
function notifications_content_page_thread($account = NULL) {
  global $user;
  if (is_null($account)) {
    $account = $user;
  }

  // query string for node subscriptions
  $query = "SELECT s.*, f.value AS nid, n.type AS node_type, n.title FROM {notifications} s \n    INNER JOIN {notifications_fields} f ON s.sid = f.sid LEFT JOIN {node} n ON f.value = CAST(n.nid AS CHAR(255))\n    WHERE s.uid = %d AND s.type = 'thread' AND s.event_type = 'node' AND s.conditions = 1 AND f.field = 'nid'\n    ORDER BY node_type, n.title";
  $results = pager_query($query, NOTIFICATIONS_CONTENT_PAGER, 0, NULL, $account->uid);
  $subscriptions = $list = array();
  $content_types = notifications_content_types('name');
  while ($sub = db_fetch_object($results)) {
    $subscriptions[$sub->nid] = $sub;
    $list[$sub->nid] = '[' . $content_types[$sub->node_type] . '] ' . l($sub->title, 'node/' . $sub->nid);
  }
  if (!$subscriptions) {
    $output = t('You are not currently subscribed to any active threads');
  }
  else {
    $output = t('You are currently subscribed to the following threads:');
    $defaults = array(
      'type' => 'thread',
      'event_type' => 'node',
    );
    $options = array(
      'title' => t('Title'),
    );
    $output .= drupal_get_form('notifications_user_form', $account, 'thread', $subscriptions, $list, $defaults, $options);
    $output .= theme('pager', NULL, NOTIFICATIONS_CONTENT_PAGER);
  }
  return $output;
}

/**
 * User subscriptions to content types
 */
function notifications_content_page_nodetype($account = NULL) {
  global $user;
  if (!isset($account)) {
    $account = $user;
  }

  // List of all subscribed node types
  $subscriptions = notifications_get_subscriptions(array(
    'type' => 'nodetype',
    'uid' => $account->uid,
  ), array(
    'type' => NULL,
  ), TRUE, 'value');
  $types = notifications_content_types('name');
  if (!$types) {
    $output = t('There are no active content types.');
  }
  else {
    $defaults = array(
      'type' => 'nodetype',
      'event_type' => 'node',
    );
    $options = array(
      'title' => t('Type'),
    );
    $output .= drupal_get_form('notifications_user_form', $account, 'nodetype', $subscriptions, $types, $defaults, $options);
  }
  return $output;
}

/**
 * User subscriptions to content types
 */
function notifications_content_page_author($account = NULL) {
  global $user;
  if (!isset($account)) {
    $account = $user;
  }

  // List of all subscribed node types
  $subscriptions = notifications_get_subscriptions(array(
    'type' => 'author',
    'event_type' => 'node',
    'uid' => $account->uid,
  ), array(
    'author' => NULL,
  ), TRUE, 'value', NOTIFICATIONS_CONTENT_PAGER);
  if (!$subscriptions) {
    $output = t('There are no active author subscriptions.');
  }
  else {

    // Build author list
    $list = array();
    $result = db_query("SELECT uid, name FROM {users} WHERE uid IN (" . implode(',', array_keys($subscriptions)) . ')');
    while ($author = db_fetch_object($result)) {
      $list[$author->uid] = theme('username', $author);
    }
    $defaults = array(
      'type' => 'author',
      'event_type' => 'node',
    );

    //$output = drupal_get_form('notifications_content_form', $account, $subscriptions, $list, 'author', t('Author'), $defaults);
    $options = array(
      'title' => t('Author'),
    );
    $output = drupal_get_form('notifications_user_form', $account, 'author', $subscriptions, $list, $defaults, $options);
    $output .= theme('pager', NULL, NOTIFICATIONS_CONTENT_PAGER);
  }
  return $output;
}

/**
 * Generic subscriptions content form
 */
function notifications_content_form($account, $subscriptions, $list, $field, $field_title, $defaults = array()) {

  // Complete defaults
  $defaults += array(
    'sid' => 0,
    'send_interval' => notifications_user_setting('send_interval', $account),
    'send_method' => notifications_user_setting('send_method', $account),
    'event_type' => 'node',
  );
  $form['defaults'] = array(
    '#type' => 'value',
    '#value' => $defaults,
  );
  $form['account'] = array(
    '#type' => 'value',
    '#value' => $account,
  );
  $form['current'] = array(
    '#type' => 'value',
    '#value' => $subscriptions,
  );
  $form['subscription_fields'] = array(
    '#type' => 'value',
    '#value' => array(),
  );
  $form['subscriptions'] = array(
    '#tree' => TRUE,
    '#theme' => 'notifications_form_table',
    '#header' => array(
      '',
      $field_title,
      t('Send interval'),
      t('Send method'),
    ),
  );
  foreach ($list as $key => $title) {
    $rowdefaults = isset($subscriptions[$key]) ? (array) $subscriptions[$key] : $defaults;
    $rowdefaults += $rowdefaults;
    $form['subscriptions']['checkbox'][$key] = array(
      '#type' => 'checkbox',
      '#default_value' => $rowdefaults['sid'],
    );
    $form['subscriptions']['title'][$key] = array(
      '#value' => $title,
    );
    $form['subscriptions']['send_interval'][$key] = array(
      '#type' => 'select',
      '#options' => _notifications_send_intervals(),
      '#default_value' => $rowdefaults['send_interval'],
    );
    $form['subscriptions']['send_method'][$key] = array(
      '#type' => 'select',
      '#options' => _notifications_send_methods(),
      '#default_value' => $rowdefaults['send_method'],
    );

    // Pass on the fields for processing
    $form['subscription_fields']['#value'][$key] = array(
      $field => $key,
    );
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}

/**
 * Process generic form submission
 */
function notifications_content_form_submit($form_id, $form_values) {
  $account = $form_values['account'];
  $current = $form_values['current'];
  $defaults = $form_values['defaults'];
  $defaults += array(
    'type' => 'node',
    'uid' => $account->uid,
  );
  $fields = $form_values['subscription_fields'];
  $values = $form_values['subscriptions'];
  $check = 'checkbox';
  foreach ($values[$check] as $index => $value) {
    $subscription = NULL;
    if ($value) {

      // Checked, save only if new or changed
      if (!isset($current[$index])) {
        $subscription = $defaults;
      }
      elseif ($current[$index]->send_interval != $values['send_interval'][$index] || $current[$index]->send_method != $values['send_method'][$index]) {
        $subscription = (array) $current[$index];
      }

      // Complete and save
      if ($subscription) {
        $subscription['send_interval'] = $values['send_interval'][$index];
        $subscription['send_method'] = $values['send_method'][$index];
        $subscription['fields'] = $fields[$index];
        notifications_save_subscription($subscription);
      }
    }
    elseif (isset($current[$index])) {
      notifications_delete_subscription($current[$index]->sid);
    }
  }
  drupal_set_message(t('Your subscriptions have been updated.'));
}

/**
 * Get content types available for subscriptions
 * 
 * @param $field
 *   Optional field to return as array value. If none it will return the full objects.
 */
function notifications_content_types($field = NULL) {

  // Get list of available node types, all of them will be allowed by default
  $types = array();
  if ($allowed = variable_get('notifications_content_types', array())) {
    $allowed = array_filter($allowed);
    foreach (node_get_types() as $type => $info) {
      if (!empty($allowed[$type])) {
        $types[$type] = $info;
      }
    }
  }
  else {
    $types = node_get_types();
  }
  if ($field) {
    foreach (array_keys($types) as $type) {
      $types[$type] = $types[$type]->{$field};
    }
  }
  return $types;
}

/**
 * Implementation of hook_token_list(). Documents the individual
 * tokens handled by the module.
 */
function notifications_content_token_list($type = 'all') {
  $tokens = array();
  if ($type == 'node' || $type == 'all') {
    $tokens['node']['node-teaser'] = t('The node teaser.');
    $tokens['node']['node-body'] = t('The node body.');
    $tokens['node']['node-url'] = t('The node view url for read more links.');
    $tokens['node']['node-teaser-raw'] = t('Unfiltered node teaser. WARNING - raw user input.');
    $tokens['node']['node-body-raw'] = t('Unfiltered node body. WARNING - raw user input.');
  }
  if ($type == 'comment' || $type == 'all') {
    $tokens['comment']['comment-url'] = t('The comment view url.');
    $tokens['comment']['comment-reply-url'] = t('The comment reply url.');
  }

  // Special case for node type
  if ($type == 'node-type' || $type == 'all') {
    $tokens['node-type']['type-name'] = t('Node type (user-friendly version)');
  }
  return $tokens;
}

/**
 * Implementation of hook_token_values()
 */
function notifications_content_token_values($type, $object = NULL, $options = array()) {
  switch ($type) {
    case 'node':
      if ($node = $object) {
        $values['node-teaser'] = $node->teaser ? check_markup($node->teaser, $node->format, FALSE) : '';
        $values['node-body'] = $node->body ? check_markup($node->body, $node->format, FALSE) : '';
        $values['node-url'] = url('node/' . $node->nid, NULL, NULL, TRUE);
        $values['node-teaser-raw'] = $node->teaser ? $node->teaser : '';
        $values['node-body-raw'] = $node->body ? $node->body : '';
        return $values;
      }
      break;
    case 'comment':
      if ($comment = (object) $object) {
        $values['comment-url'] = url('node/' . $comment->nid, NULL, 'comment-' . $comment->cid, TRUE);
        $values['comment-reply-url'] = url('comment/reply/' . $comment->nid . '/' . $comment->cid, NULL, NULL, TRUE);
        return $values;
      }
      break;
  }
}

/**
 * Determine whether the specified user may view the specified node.
 *
 * Does a user switching and checks for node permissions. Looking for a better way
 * but it seems that all the node_access hooks cant be invokes without this.
 */
function notifications_content_node_allow($account, $node) {
  static $access;
  global $user;
  if (!isset($access[$account->uid][$node->nid])) {

    // Security! Prevent session saving while user switching
    session_save_session(FALSE);
    $current = $user;
    $user = $account;
    $access[$account->uid][$node->nid] = node_access('view', $node);
    $user = $current;
    session_save_session(TRUE);
  }
  return $access[$account->uid][$node->nid];
}

/**
 * Determine whether the specified user may view the specified comment.
 *
 * Does a user switching and checks for node permissions. Looking for a better way
 * but it seems that all the node_access hooks cant be invokes without this.
 */
function notifications_content_comment_allow($account, $comment) {
  static $access;
  $comment = is_object($comment) ? $comment : db_fetch_object(db_query("SELECT * FROM {comments} WHERE cid = %d", $comment));
  if (!isset($access[$account->uid][$comment->cid])) {
    if (($account->uid == $comment->uid || $comment->status == COMMENT_PUBLISHED) && user_access('access comments', $account) || user_access('administer comments', $account)) {
      $access[$account->uid][$comment->cid] = TRUE;
    }
    else {
      $access[$account->uid][$comment->cid] = FALSE;
    }
  }
  return $access[$account->uid][$comment->cid];
}

Functions

Namesort descending Description
notifications_content_comment Implementation of hook_comment()
notifications_content_comment_allow Determine whether the specified user may view the specified comment.
notifications_content_comment_load Load comments with caching @ TODO See if this may be some use, or drop
notifications_content_form Generic subscriptions content form
notifications_content_form_submit Process generic form submission
notifications_content_help Implementation of hook_help()
notifications_content_menu Implementation of hook_menu_()
notifications_content_messaging Implementation of hook_messaging()
notifications_content_nodeapi Implementation of hook_nodeapi()
notifications_content_node_allow Determine whether the specified user may view the specified node.
notifications_content_node_type Implementation of hook node_type
notifications_content_notifications Implementation of hook_notifications()
notifications_content_page_author User subscriptions to content types
notifications_content_page_nodetype User subscriptions to content types
notifications_content_page_thread Subscriptions page callback: List thread subscriptions
notifications_content_perm Implementation of hook_perm()
notifications_content_settings_form Admin settings form
notifications_content_token_list Implementation of hook_token_list(). Documents the individual tokens handled by the module.
notifications_content_token_values Implementation of hook_token_values()
notifications_content_types Get content types available for subscriptions
_notifications_content_node_options

Constants