You are here

comment_notify.module in Comment Notify 8

This module provides comment follow-up e-mail notifications.

It works for anonymous and registered users.

File

comment_notify.module
View source
<?php

/**
 * @file
 * This module provides comment follow-up e-mail notifications.
 *
 * It works for anonymous and registered users.
 */
use Drupal\Core\Entity\EntityInterface;
use Drupal\comment\CommentInterface;
use Drupal\comment_notify\Form\CommentNotifySettings;
use Drupal\Component\Render\PlainTextOutput;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\user\Entity\User;
use Drupal\Core\Routing\RouteMatchInterface;
define('COMMENT_NOTIFY_DISABLED', 0);
define('COMMENT_NOTIFY_ENTITY', 1);
define('COMMENT_NOTIFY_COMMENT', 2);

/**
 * Provide an array of available options for notification on a comment.
 */
function _comment_notify_options() {
  $total_options = [
    COMMENT_NOTIFY_ENTITY => t('All comments'),
    COMMENT_NOTIFY_COMMENT => t('Replies to my comment'),
  ];
  $selected_options = array_filter(\Drupal::config('comment_notify.settings')
    ->get('available_alerts'));
  $available_options = array_intersect_key($total_options, $selected_options);
  return $available_options;
}

/**
 * Add the comment_notify fields in the comment form.
 */
function comment_notify_form_comment_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $user = \Drupal::currentUser();
  if (!($user
    ->hasPermission('subscribe to comments') || $user
    ->hasPermission('administer comments'))) {
    return;
  }

  /** @var \Drupal\Core\Entity\EntityInterface $comment_entity */
  $comment_entity = $form_state
    ->getFormObject()
    ->getEntity();
  $field_identifier = CommentNotifySettings::getCommentFieldIdentifier($comment_entity);

  // Only add the checkbox if this is an enabled content type.
  $enabled_types = \Drupal::config('comment_notify.settings')
    ->get('bundle_types');
  if (!in_array($field_identifier, $enabled_types)) {
    return;
  }
  $available_options = _comment_notify_options();

  // Add the checkbox for anonymous users.
  if ($user
    ->isAnonymous()) {

    // If anonymous users can't enter their e-mail don't tempt them with the
    // checkbox.
    if (empty($form['author']['mail'])) {
      return;
    }
    $form['#validate'][] = 'comment_notify_comment_validate';
  }
  module_load_include('inc', 'comment_notify', 'comment_notify');

  /** @var \Drupal\comment_notify\UserNotificationSettings $user_settings */
  $user_settings = \Drupal::service('comment_notify.user_settings');
  $preference = $user_settings
    ->getSetting($user
    ->id(), 'comment_notify');

  // If you want to hide this on your site see http://drupal.org/node/322482
  $form['comment_notify_settings'] = [
    '#attached' => [
      'library' => [
        'comment_notify/comment_notify',
      ],
    ],
  ];
  $form['#attributes']['class'][] = 'comment-notify-form';
  $form['comment_notify_settings']['notify'] = [
    '#type' => 'checkbox',
    '#title' => t('Notify me when new comments are posted'),
    '#default_value' => (bool) $preference,
    '#attributes' => [
      'class' => [
        'comment-notify',
      ],
    ],
  ];
  $form['comment_notify_settings']['notify_type'] = [
    '#type' => 'radios',
    '#options' => $available_options,
    '#default_value' => $preference != "none" ? $preference : 1,
    '#attributes' => [
      'class' => [
        'comment-notify-type',
      ],
    ],
  ];
  if (count($available_options) == 1) {
    $form['comment_notify_settings']['notify_type']['#type'] = 'hidden';
    $form['comment_notify_settings']['notify_type']['#value'] = key($available_options);
  }

  // If this is an existing comment we set the default value based on their
  // selection last time.

  /** @var \Drupal\comment\CommentInterface $comment */
  $comment = $form_state
    ->getFormObject()
    ->getEntity();
  if (!$comment
    ->isNew()) {
    $notify = comment_notify_get_notification_type($comment
      ->id());
    $form['comment_notify_settings']['notify']['#default_value'] = (bool) $notify;
    if (count($available_options) > 1) {
      $form['comment_notify_settings']['notify_type']['#default_value'] = empty($notify) ? COMMENT_NOTIFY_ENTITY : $notify;
    }
    else {
      $form['comment_notify_settings']['notify_type']['#default_value'] = key($available_options);
    }
  }
  $form['actions']['submit']['#submit'][] = '_comment_notify_submit_comment_form';
}

/**
 * Checks if the values used in the comment_notify fields are valid.
 */
function comment_notify_comment_validate(&$form, FormStateInterface $form_state) {
  $user = \Drupal::currentUser();

  // We assume that if they are non-anonymous then they have a valid mail.
  // For anonymous users, though, we verify that they entered a mail and let
  // comment.module validate it is real.
  if ($user
    ->isAnonymous() && $form['comment_notify_settings']['notify']['#value'] && empty($form['author']['mail']['#value'])) {
    $form_state
      ->setErrorByName('mail', t('If you want to subscribe to comments you must supply a valid e-mail address.'));
  }
}

/**
 * Sends the mail alerts if necessary.
 */
function comment_notify_comment_publish($comment) {

  // And send notifications - the real purpose of the module.
  _comment_notify_mailalert($comment);
}

/**
 * Additional submit handler for the comment form.
 */
function _comment_notify_submit_comment_form(array &$form, FormStateInterface $form_state) {
  module_load_include('inc', 'comment_notify', 'comment_notify');

  /** @var \Drupal\comment\CommentInterface $comment */
  $comment = $form_state
    ->getFormObject()
    ->getEntity();
  $user = \Drupal::currentUser();

  /** @var \Drupal\comment_notify\UserNotificationSettings $user_settings */
  $user_settings = \Drupal::service('comment_notify.user_settings');

  // If the form component is visible, these values should be in the form state.
  // Otherwise, use the user's preferences.
  if ($form_state
    ->hasValue('notify') && $form_state
    ->hasValue('notify_type')) {
    $status = $form_state
      ->getValue('notify') ? $form_state
      ->getValue('notify_type') : COMMENT_NOTIFY_DISABLED;

    // Update user's preference.
    // @todo are the user notifications allowed to be edited here?
    if (!$user
      ->isAnonymous()) {

      /** @var \Drupal\comment_notify\UserNotificationSettings $user_settings */
      $user_settings
        ->saveSettings($user
        ->id(), NULL, $status);
    }
  }
  else {
    $status = $user_settings
      ->getSetting($user
      ->id(), 'comment_notify');
  }

  // Save notification settings.
  if (comment_notify_get_notification_type($comment
    ->id())) {

    // Update existing record.
    comment_notify_update_notification($comment
      ->id(), $status);
  }
  else {

    // For new comments, we first build up a string to be used as the identifier
    // for the alert. This identifier is used to later unsubscribe the user or
    // allow them to potentially edit their comment / preferences if they are
    // anonymous. The string is built with token and their host and comment
    // identifier. It is stored and referenced, we really just need something
    // unique/unguessable. See comment_notify_unsubscribe_by_hash().
    // @todo make the comment_notify_add_notification() generate the hash.
    $hostname = !$comment
      ->getHostname() ? $comment
      ->getHostname() : (isset($user->hostname) ? $user->hostname : '');
    $notify_hash = \Drupal::csrfToken()
      ->get($hostname . $comment
      ->id());
    comment_notify_add_notification($comment
      ->id(), $status, $notify_hash, $comment->notified);
  }
}

/**
 * Implements hook_ENTITY_TYPE_update() for comment.
 */
function comment_notify_comment_update(CommentInterface $comment) {

  // And send notifications - the real purpose of the module.
  if ($comment
    ->isPublished()) {
    _comment_notify_mailalert($comment);
  }
}

/**
 * Implements hook_comment_insert().
 */
function comment_notify_comment_insert(CommentInterface $comment) {
  module_load_include('inc', 'comment_notify', 'comment_notify');

  // And send notifications - the real purpose of the module.
  if ($comment
    ->isPublished()) {
    _comment_notify_mailalert($comment);
  }
}

/**
 * Deletes all the notifications when a comment is deleted.
 */
function comment_notify_comment_delete(CommentInterface $comment) {
  module_load_include('inc', 'comment_notify', 'comment_notify');
  comment_notify_remove_all_notifications($comment
    ->id());
}

/**
 * Returns array of comment notify enabled entity type & bundles.
 */
function _comment_notify_get_comment_enabled_bundles() {
  $field_manager = \Drupal::service('entity_field.manager');
  $bundles_with_comment_fields = [];
  $comment_field_map = $field_manager
    ->getFieldMapByFieldType('comment');
  foreach ($comment_field_map as $entity_type => $comment_fields) {
    foreach ($comment_fields as $field_name => $field_info) {
      foreach ($field_info['bundles'] as $field_bundle) {
        $bundles_with_comment_fields[$entity_type] = $field_bundle;
      }
    }
  }
  return $bundles_with_comment_fields;
}

/**
 * Implements hook_form_alter().
 */
function comment_notify_form_user_form_alter(&$form, FormStateInterface &$form_state, $form_id) {
  module_load_include('inc', 'comment_notify', 'comment_notify');

  /** @var \Drupal\user\UserInterface $user */
  $user = $form_state
    ->getFormObject()
    ->getEntity();

  /** @var \Drupal\comment_notify\UserNotificationSettings $user_settings */
  $user_settings = \Drupal::service('comment_notify.user_settings');
  $notify_settings = $user
    ->id() && $user_settings
    ->getSettings($user
    ->id()) ? $user_settings
    ->getSettings($user
    ->id()) : $user_settings
    ->getDefaultSettings();

  // Only show the entity followup UI if the user has permission to create
  // entities.
  $bundles = FALSE;
  foreach (_comment_notify_get_comment_enabled_bundles() as $entity_type => $bundle) {
    if (\Drupal::entityTypeManager()
      ->getAccessControlHandler($entity_type)
      ->createAccess($bundle)) {
      $bundles = TRUE;
      break;
    }
  }

  // If the user cannot create nodes nor has the 'subscribe to comments'
  // permission then there is no need to alter the user_form.
  if (!\Drupal::currentUser()
    ->hasPermission('administer nodes') && $bundles === FALSE && $user
    ->hasPermission('subscribe to comments') === FALSE) {
    return;
  }
  $form['comment_notify_settings'] = [
    '#type' => 'details',
    '#title' => t('Comment follow-up notification settings'),
    '#weight' => 4,
    '#open' => TRUE,
  ];
  if (\Drupal::currentUser()
    ->hasPermission('administer nodes') || $bundles) {
    $form['comment_notify_settings']['entity_notify'] = [
      '#type' => 'checkbox',
      '#title' => t('Receive content follow-up notification e-mails'),
      '#default_value' => isset($notify_settings['entity_notify']) ? $notify_settings['entity_notify'] : NULL,
      '#description' => t('Check this box to receive e-mail notifications for comments on your <strong>content</strong> (e.g. an article authored by you). You cannot disable notifications for individual threads.'),
    ];
  }
  else {
    $form['comment_notify_settings']['entity_notify'] = [
      '#type' => 'hidden',
      '#value' => COMMENT_NOTIFY_DISABLED,
    ];
  }
  if ($user
    ->hasPermission('subscribe to comments')) {
    $available_options[COMMENT_NOTIFY_DISABLED] = t('No notifications');
    $available_options += _comment_notify_options();
    $form['comment_notify_settings']['comment_notify'] = [
      '#type' => 'select',
      '#title' => t('Receive comment follow-up notification e-mails'),
      '#default_value' => isset($notify_settings['comment_notify']) ? $notify_settings['comment_notify'] : NULL,
      '#options' => $available_options,
      '#description' => t("Choose whether, by default, to subscribe to e-mail notifications for replies to your own <strong>comments</strong>. Your site administrator may have customised the options available. You can change this setting on a per-comment basis, and later unsubscribe from individual posts."),
    ];
  }
  else {
    $form['comment_notify_settings']['comment_notify'] = [
      '#type' => 'hidden',
      '#value' => COMMENT_NOTIFY_DISABLED,
    ];
  }
  $form['actions']['submit']['#submit'][] = '_comment_notify_submit_user_form';
}

/**
 * Additional submit handler for the user form.
 */
function _comment_notify_submit_user_form(array &$form, FormStateInterface $form_state) {
  module_load_include('inc', 'comment_notify', 'comment_notify');

  /** @var \Drupal\user\UserInterface $user */
  $user = $form_state
    ->getFormObject()
    ->getEntity();
  if (!$user
    ->isAnonymous() && is_numeric($form_state
    ->getValue('entity_notify')) && is_numeric($form_state
    ->getValue('comment_notify'))) {

    /** @var \Drupal\comment_notify\UserNotificationSettings $user_settings */
    $user_settings = \Drupal::service('comment_notify.user_settings');
    $user_settings
      ->saveSettings($user
      ->id(), $form_state
      ->getValue('entity_notify'), $form_state
      ->getValue('comment_notify'));
  }
}

/**
 * Implements hook_user_delete().
 */
function comment_notify_user_predelete(EntityInterface $entity) {

  // This hook is invoked when the account is deleted.
  comment_notify_remove_user_settings($entity
    ->id());
}

/**
 * Implements hook_user_cancel().
 */
function comment_notify_user_cancel($edit, $account, $method) {

  // This hook is invoked when the account is disabled.
  comment_notify_remove_user_settings($account
    ->id());
}

/**
 * Remove the user settings of of the user with the given $uid.
 *
 * @param int $uid
 *   The user id.
 */
function comment_notify_remove_user_settings($uid) {

  /** @var \Drupal\comment_notify\UserNotificationSettings $user_settings */
  $user_settings = \Drupal::service('comment_notify.user_settings');
  $user_settings
    ->deleteSettings($uid);
}

/**
 * Implements hook_comment_load().
 */
function comment_notify_comment_load($comments) {

  // Load some comment_notify specific information into the comment object.
  $query = \Drupal::database()
    ->select('comment_notify', 'cn');
  $query
    ->join('comment_field_data', 'c', 'c.cid = cn.cid');
  $query
    ->leftJoin('users_field_data', 'u', 'c.uid = u.uid');
  $query
    ->condition('c.cid', array_keys($comments), 'IN');
  $query
    ->fields('cn', [
    'cid',
    'notify',
    'notify_hash',
    'notified',
  ]);
  $query
    ->addField('c', 'mail', 'cmail');
  $query
    ->addField('u', 'init', 'uinit');
  $query
    ->addField('u', 'mail', 'umail');
  $records = $query
    ->execute()
    ->fetchAllAssoc('cid');
  foreach ($records as $cid => $record) {
    $comments[$cid]->notify = $record->notify;
    $comments[$cid]->notify_type = $record->notify;
    $comments[$cid]->notify_hash = $record->notify_hash;
    $comments[$cid]->notified = $record->notified;
    $comments[$cid]->cmail = $record->cmail;
    $comments[$cid]->uinit = $record->uinit;
    $comments[$cid]->umail = $record->umail;
  }
}

/**
 * Private function to send the notifications.
 *
 * @param \Drupal\comment\CommentInterface $comment
 *   The comment entity.
 */
function _comment_notify_mailalert(CommentInterface $comment) {
  module_load_include('inc', 'comment_notify', 'comment_notify');
  $config = \Drupal::config('comment_notify.settings');
  $user = \Drupal::currentUser();
  $entity_id = $comment
    ->getCommentedEntityId();
  $entity_type = $comment
    ->getCommentedEntityTypeId();
  $field_identifier = CommentNotifySettings::getCommentFieldIdentifier($comment);
  $comment_type = $comment
    ->get('comment_type')
    ->getString();

  // Check to see if a notification has already been sent for this
  // comment so that edits to a comment don't trigger an additional
  // notification.
  if (!empty($comment->notified)) {
    return;
  }

  /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
  $entity = \Drupal::entityTypeManager()
    ->getStorage($entity_type)
    ->load($entity_id);

  // No mails if this is not an enabled content type.
  $enabled_types = $config
    ->get('bundle_types');
  if (!empty($enabled_types) && !in_array($field_identifier, $enabled_types)) {
    return;
  }
  if (empty($comment
    ->getAuthorEmail())) {

    /** @var \Drupal\user\UserInterface $comment_account */
    if ($comment_account = user_load_by_name($comment
      ->getAuthorName())) {
      $comment_mail = $comment_account
        ->getEmail() ?: '';
    }
    else {
      $comment_mail = '';
    }
  }
  else {
    $comment_mail = $comment
      ->getAuthorEmail();
  }
  $sent_to = [];

  // @todo Add hook to allow entity types to specify their type's author field?
  $author_fields = [
    'uid',
    'user_id',
  ];
  foreach ($author_fields as $author_field) {

    // Send to a subscribed author if they are not the current commenter.
    if ($entity
      ->hasField($author_field)) {

      // If the entity is a user object, then the user object is the "author'.
      if ($entity instanceof User) {
        $author = $entity;
      }
      else {
        $author = $entity
          ->getOwner();
      }

      /** @var \Drupal\comment_notify\UserNotificationSettings $user_settings */
      $user_settings = \Drupal::service('comment_notify.user_settings');
      $author_notify_settings = $user_settings
        ->getSettings($author
        ->id()) ?: $user_settings
        ->getDefaultSettings();
      $author_email = $author
        ->getEmail();

      // Do they explicitly want this? Or is it default to send to users? Is
      // the comment author not the entity author? Do they have access? Do they
      // have an email (e.g. anonymous)?
      $entity_notify_a = !empty($author_notify_settings['entity_notify']) && $author_notify_settings['entity_notify'] == 1;
      $entity_notify_b = $config
        ->get('enable_default.entity_author') == 1 && !isset($author_notify_settings['entity_notify']);
      if (!empty($author_email) && ($entity_notify_a || $entity_notify_b) && $user
        ->id() != $author
        ->id() && $entity
        ->access('view', $author)) {
        if (in_array($author_email, $sent_to)) {
          continue;
        }
        $raw_values = $config
          ->get('mail_templates.entity_author.' . $entity
          ->getEntityTypeId());
        $token_data = [
          'comment' => $comment,
          'user' => $author,
        ];
        if ($entity_type == 'node') {
          $token_data['node'] = $entity;
        }
        $message['subject'] = PlainTextOutput::renderFromHtml(\Drupal::token()
          ->replace($raw_values['subject'], $token_data));
        $message['body'] = \Drupal::token()
          ->replace($raw_values['body'], $token_data);
        $language = $author
          ->getPreferredLangcode();
        \Drupal::service('plugin.manager.mail')
          ->mail('comment_notify', 'comment_notify_mail', $author
          ->getEmail(), $language, $message);
        $sent_to[] = strtolower($author
          ->getEmail());
      }

      // This field existed, so there's no need to try again.
      break;
    }
  }

  // For "reply to my comments" notifications, figure out what thread this is.
  $thread = $comment
    ->getThread() ?: '';

  // Get the list of commenters to notify.
  $watchers = comment_notify_get_watchers($entity_id, $comment_type);
  foreach ($watchers as $alert) {

    // If the user is not anonymous, always load the current e-mail address
    // from his or her user account instead of trusting $comment->mail.
    $recipient_user = $alert
      ->getOwner();
    $mail = !empty($recipient_user
      ->getEmail()) ? $recipient_user
      ->getEmail() : $alert
      ->getAuthorEmail();

    // Trim the trailing / off the thread, if present.
    $alert_thread = rtrim((string) $alert
      ->getThread(), '/');
    $relevant_thread = mb_substr($thread, 0, mb_strlen($alert_thread));
    if ($alert->notify == COMMENT_NOTIFY_COMMENT && strcmp($relevant_thread, $alert_thread) != 0) {
      continue;
    }
    if ($mail != $comment_mail && !in_array(strtolower($mail), $sent_to) && ($alert
      ->getOwnerId() != $comment
      ->getOwnerId() || $alert
      ->getOwnerId() == 0)) {
      $message = [];

      // Make sure they have access to this entity before showing a bunch of
      // entity information.
      if (!$entity
        ->access('view', $recipient_user)) {
        continue;
      }
      $raw_values = $config
        ->get('mail_templates.watcher.' . $entity
        ->getEntityTypeId());
      $token_data = [
        'comment' => $comment,
        'comment-subscribed' => $alert,
      ];
      if ($entity_type == 'node') {
        $token_data['node'] = $entity;
      }
      $message['subject'] = PlainTextOutput::renderFromHtml(\Drupal::token()
        ->replace($raw_values['subject'], $token_data));
      $message['body'] = \Drupal::token()
        ->replace($raw_values['body'], $token_data);
      $language = !empty($alert->uid) ? $recipient_user
        ->getPreferredLangcode() : LanguageInterface::LANGCODE_DEFAULT;
      \Drupal::service('plugin.manager.mail')
        ->mail('comment_notify', 'comment_notify_mail', $mail, $language, $message);
      $sent_to[] = strtolower($mail);

      // Make the mail link to user's /edit, unless it's an anonymous user.
      if ($alert
        ->getOwnerId() != 0) {
        $user_mail = $alert
          ->toLink($mail, 'edit-form')
          ->toString();
      }
      else {
        $user_mail = Html::escape($mail);
      }

      // Add an entry to the watchdog log.
      $args = [
        '@user_mail' => $user_mail,
        'link' => $alert
          ->toLink(t('source comment'))
          ->toString(),
      ];
      \Drupal::logger('comment_notify')
        ->notice('Notified: @user_mail', $args);
    }
  }

  // Record that a notification was sent for this comment so that
  // notifications aren't sent again if the comment is later edited.
  comment_notify_mark_comment_as_notified($comment);
}

/**
 * Implements hook_mail().
 */
function comment_notify_mail($key, &$message, $params) {
  $message['subject'] = $params['subject'];
  $message['body'][] = $params['body'];
}

/**
 * Get the unsubscribe link for a comment subscriber.
 *
 * @param \Drupal\comment\CommentInterface $comment
 *   The subscribed comment object.
 *
 * @return string|null
 *   An absolute URL string for the unsubscribe page, or NULL if the comment is
 *   missing a notification hash.
 *
 * @todo In what case would a comment be missing its notification hash?
 */
function comment_notify_get_unsubscribe_url(CommentInterface $comment) {
  if (!empty($comment->notify_hash)) {
    return Url::fromRoute('comment_notify.disable', [
      'hash' => $comment->notify_hash,
    ])
      ->setAbsolute()
      ->toString();
  }
  return NULL;
}

/**
 * Implements hook_field_extra_fields().
 */
function comment_notify_entity_extra_field_info() {
  module_load_include('inc', 'comment_notify', 'comment_notify');
  $extras = [];
  $config = \Drupal::config('comment_notify.settings');
  foreach ($config
    ->get('bundle_types') as $bundle_type) {
    $field_identifier = explode('--', $bundle_type);
    $comment_field = FieldConfig::loadByName($field_identifier[0], $field_identifier[1], $field_identifier[2]);
    if ($comment_field) {
      $bundle_info = \Drupal::service("entity_type.bundle.info")
        ->getBundleInfo($field_identifier[0]);
      $bundle_label = $bundle_info[$field_identifier[1]]['label'];
      $comment_type = $comment_field
        ->getSetting('comment_type');
      $extras['comment'][$comment_type]['form']['comment_notify_settings'] = [
        'label' => t('Comment Notify settings'),
        'description' => t('@bundle_type settings for Comment Notify', [
          '@bundle_type' => $bundle_label,
        ]),
        'weight' => 1,
      ];
    }
  }
  $extras['user']['user']['form']['comment_notify_settings'] = [
    'label' => t('Comment Notify settings'),
    'description' => t('User settings for Comment Notify'),
    'weight' => 4,
  ];
  return $extras;
}

/**
 * Implements hook_help().
 */
function comment_notify_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.comment_notify':
      $text = file_get_contents(dirname(__FILE__) . '/README.md');
      if (!\Drupal::moduleHandler()
        ->moduleExists('markdown')) {
        return '<pre>' . $text . '</pre>';
      }
      else {

        // Use the Markdown filter to render the README.
        $filter_manager = \Drupal::service('plugin.manager.filter');
        $settings = \Drupal::configFactory()
          ->get('markdown.settings')
          ->getRawData();
        $config = [
          'settings' => $settings,
        ];
        $filter = $filter_manager
          ->createInstance('markdown', $config);
        return $filter
          ->process($text, 'en');
      }
  }
  return NULL;
}

Functions

Namesort descending Description
comment_notify_comment_delete Deletes all the notifications when a comment is deleted.
comment_notify_comment_insert Implements hook_comment_insert().
comment_notify_comment_load Implements hook_comment_load().
comment_notify_comment_publish Sends the mail alerts if necessary.
comment_notify_comment_update Implements hook_ENTITY_TYPE_update() for comment.
comment_notify_comment_validate Checks if the values used in the comment_notify fields are valid.
comment_notify_entity_extra_field_info Implements hook_field_extra_fields().
comment_notify_form_comment_form_alter Add the comment_notify fields in the comment form.
comment_notify_form_user_form_alter Implements hook_form_alter().
comment_notify_get_unsubscribe_url Get the unsubscribe link for a comment subscriber.
comment_notify_help Implements hook_help().
comment_notify_mail Implements hook_mail().
comment_notify_remove_user_settings Remove the user settings of of the user with the given $uid.
comment_notify_user_cancel Implements hook_user_cancel().
comment_notify_user_predelete Implements hook_user_delete().
_comment_notify_get_comment_enabled_bundles Returns array of comment notify enabled entity type & bundles.
_comment_notify_mailalert Private function to send the notifications.
_comment_notify_options Provide an array of available options for notification on a comment.
_comment_notify_submit_comment_form Additional submit handler for the comment form.
_comment_notify_submit_user_form Additional submit handler for the user form.

Constants