? .git
Index: comment_notify.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/comment_notify/comment_notify.info,v
retrieving revision 1.3
diff -u -r1.3 comment_notify.info
--- comment_notify.info	6 Aug 2008 23:27:08 -0000	1.3
+++ comment_notify.info	15 Nov 2009 06:11:23 -0000
@@ -2,4 +2,7 @@
 name = Comment Notify
 description = "Comment follow-up e-mail notification for anonymous as well as registered users."
 dependencies[] = comment
-core = 6.x
+core = 7.x
+files[] = comment_notify.install
+files[] = comment_notify.module
+files[] = comment_notify.test
Index: comment_notify.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/comment_notify/comment_notify.install,v
retrieving revision 1.16
diff -u -r1.16 comment_notify.install
--- comment_notify.install	8 Apr 2009 01:52:02 -0000	1.16
+++ comment_notify.install	15 Nov 2009 06:11:23 -0000
@@ -11,17 +11,26 @@
 function comment_notify_install() {
   // Create the table.
   drupal_install_schema('comment_notify');
-
-  // Insert a record for each existing comment.
-  if ( $GLOBALS['db_type']=='pgsql') {
-    db_query("INSERT INTO {comment_notify} (cid, notify, notify_hash) SELECT c.cid, 0, md5(c.mail || coalesce(u.mail, u.init) || c.uid || c.name || c.nid) FROM {comments} c LEFT OUTER JOIN {users} u on c.uid = u.uid");
+  
+  $comments_select = db_select('comment', 'c');
+  $comments_select->join('users', 'u', 'c.uid = u.uid');
+  $comments_select->addField('c', 'cid');
+  $comments_select->addExpression('0', 'notify');
+  if (db_driver() == 'pgsql') {
+    $comments_select->addExpression('md5(c.mail || coalesce(u.mail, u.init) || c.uid || c.name || c.nid)', 'notify_hash');
   }
   else {
-    db_query("INSERT INTO {comment_notify} (cid, notify, notify_hash) SELECT c.cid, 0, md5(concat(c.mail, ifnull(u.mail, u.init), c.uid, c.name, c.nid)) FROM {comments} c LEFT OUTER JOIN {users} u on c.uid = u.uid");
+  	$comments_select->addExpression('md5(concat(c.mail, ifnull(u.mail, u.init), c.uid, c.name, c.nid))', 'notify_hash');
   }
-
+  $comments_select->addField('c', 'cid');
+  
   // Set module weight low so that other modules act on the comment first.
-  db_query("UPDATE {system} SET weight = 10 WHERE name = 'comment_notify'");
+  db_insert('comment_notify')->from($comments_select)->execute();
+  db_update('system')->
+  	fields(array(
+  	'weight' => 10
+  	))
+  	->condition('name', 'comment_notify');
 }
 
 /**
@@ -30,7 +39,8 @@
 function comment_notify_uninstall() {
   drupal_uninstall_schema('comment_notify');
   variable_del('node_notify_default_mailtext');
-  db_query("DELETE FROM {variable} WHERE name LIKE 'comment_notify_%'");
+  db_delete('variable')
+  	->where('name', "comment_notify_%", 'LIKE');
 }
 
 /**
@@ -95,208 +105,4 @@
   );
 
   return $schema;
-}
-
-/**
- * Sync up the two tables after as part of http://drupal.org/node/297791
- */
-function comment_notify_update_6000() {
-  $return[] = update_sql("DELETE FROM {comment_notify} WHERE cid NOT IN (SELECT cid FROM {comments})");
-  return $return;
-}
-
-/**
- * Permissions got renamed, update them.
- */
-function comment_notify_update_6001() {
-  $ret = array();
-  $result = db_query("SELECT pid, perm FROM {permission}");
-  while ($row = db_fetch_object($result)) {
-    $permissions = explode(', ', $row->perm);
-    if (in_array('Subscribe to comments', $permissions) && !in_array('subscribe to comments', $permissions)) {
-      $permissions[] = 'subscribe to comments';
-    }
-    if (in_array('Administer comment notify', $permissions) && !in_array('administer comment notify', $permissions)) {
-      $permissions[] = 'administer comment notify';
-    }
-
-    $permissions = implode(', ', $permissions);
-    $ret[] = update_sql("UPDATE {permission} SET perm = '%s' WHERE pid = %d", $permissions, $row->pid);
-  }
-  return $ret;
-}
-
-/**
- * Drop the notify column from the {comments} table.  This column will only exist
- * if the 5.x-1.x version of comment_notify was installed at some point.  Since
- * the 5.x-2.x version of the module {comment_notify}.notify has been used instead.
- */
-function comment_notify_update_6002() {
-  $ret = array();
-  if (db_column_exists('comments', 'notify')) {
-    db_drop_field($ret, 'comments', 'notify');
-  }
-  return $ret;
-}
-
-/**
- * Create a new table to store user preferences and move the $user->data there.
- */
-function comment_notify_update_6003() {
-  $ret = array();
-  // This determines how many users will be processed in each batch run.
-  $num_users_per_batch = 100;
-
-  // Multi-part update.
-  if (!isset($_SESSION['comment_notify_update_6003'])) {
-    // We need to start at uid 1, so initialize our variable
-    // to the value below that.
-    $_SESSION['comment_notify_update_6003'] = 1;
-    $_SESSION['comment_notify_update_6003_max'] = db_result(db_query("SELECT MAX(uid) FROM {users}"));
-
-    // Create the table.
-    $schema['comment_notify_user_settings'] = array(
-      'fields' => array(
-          'uid' => array(
-            'type' => 'serial',
-            'unsigned' => TRUE,
-            'description' => 'The user id from {users}.cid',
-            'not null' => TRUE,
-            'disp-width' => '11'),
-          'node_notify' => array(
-            'type' => 'int',
-            'size' => 'tiny',
-            'not null' => TRUE,
-            'default' => 0,
-            'disp-width' => '11'),
-          'comment_notify' => array(
-            'type' => 'int',
-            'size' => 'tiny',
-            'not null' => TRUE,
-            'default' => 0,
-            'disp-width' => '11'),
-      ),
-      'primary key' => array('uid'),
-    );
-
-    db_create_table($ret, 'comment_notify_user_settings', $schema['comment_notify_user_settings']);
-  }
-  // Do the next batch of the deed.
-
-  // Find the next N records to update, or do the final batch.
-  $next = min($_SESSION['comment_notify_update_6003'] + $num_users_per_batch, $_SESSION['comment_notify_update_6003_max']);
-
-  // Check to make sure that the {comment_notify_user_settings} table exists.
-  // If for some reason it was not created above, we might lose data when
-  // we delete the comment_notify data that is currently in {users}.data.
-  // If the table doesn't exist, then alert the user and don't allow any
-  // more batches to be processed.
-  if (!db_table_exists('comment_notify_user_settings')) {
-    unset($_SESSION['comment_notify_update_6003']);
-    unset($_SESSION['comment_notify_update_6003_max']);
-
-    // Alert the user that there was an error.
-    $ret[] = array('success' => FALSE, 'query' => t('For some reason the {comment_notify_user_settings} table was not properly created, and so per-user comment_notify settings could not be copied from {users}.data.  You will need to run this update again.'));
-    return $ret;
-  }
-
-  // Transfer the data in our specified range of uid values.
-  $uid = $_SESSION['comment_notify_update_6003'];
-  while ($uid <= $next) {
-    // Get the value of {users}.data.
-    $data = db_result(db_query('SELECT data FROM {users} WHERE uid = %d', $uid));
-    $settings = array('uid' => $uid);
-    if (!empty($data)) {
-      $data = unserialize($data);
-      if (isset($data['node_notify_mailalert'])) {
-        $settings['node_notify'] = $data['node_notify_mailalert'];
-        unset($data['node_notify_mailalert']);
-      }
-      if (isset($data['comment_notify_mailalert'])) {
-        $settings['comment_notify'] = $data['comment_notify_mailalert'];
-        unset($data['comment_notify_mailalert']);
-      }
-      $fields_sql = '';
-      $values_sql = '';
-      foreach ($settings as $field => $value) {
-        $fields_sql .= "$field, ";
-        $values_sql .= '%d, ';
-      }
-      // Trim off any trailing commas and spaces.
-      $fields_sql = rtrim($fields_sql, ', ');
-      $values_sql = rtrim($values_sql, ', ');
-
-      // Add this user and settings to {comment_notify_user_settings} only if
-      // at least one setting was found in {users}.data for this user.
-      if (count($settings) > 1) {
-        db_query("INSERT INTO {comment_notify_user_settings} ($fields_sql) VALUES ($values_sql)", $settings);
-
-        // Remove this comment_notify data from {users}.data.
-        db_query("UPDATE {users} SET data = '%s' WHERE uid = %d", serialize($data), $uid);
-      }
-    }
-    $uid++;
-  }
-
-  // Remember where we left off.
-  $_SESSION['comment_notify_update_6003'] = $next;
-
-  if ($_SESSION['comment_notify_update_6003'] == $_SESSION['comment_notify_update_6003_max']) {
-    // We're done, clear these out.
-    unset($_SESSION['comment_notify_update_6003']);
-    unset($_SESSION['comment_notify_update_6003_max']);
-
-    // Provide an explaination of what we did.
-    $ret[] = array('success' => TRUE, 'query' => t('Moved comment_notify user settings data from the {users} table into the {comment_notify_user_settings} table.'));
-  }
-  elseif ($uid == $next) {
-    unset($_SESSION['comment_notify_update_6003']);
-    unset($_SESSION['comment_notify_update_6003_max']);
-    $ret[] = array('success' => FALSE, 'query' => t('Something is maybe not right.'));
-  }
-  else {
-    // Report how much is left to complete.
-    $ret['#finished'] = $_SESSION['comment_notify_update_6003'] / $_SESSION['comment_notify_update_6003_max'];
-  }
-
-  return $ret;
-}
-
-/**
- * Add a "notified" column to {comment_notify} to keep track of whether
- * notifications have already been sent out for a given comment.  This
- * prevents new notifications from being sent when a comment is edited.
- */
-function comment_notify_update_6004() {
-  $ret = array();
-
-  db_add_field($ret, 'comment_notify', 'notified', array('type' => 'int', 'size' => 'small', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
-
-  // Set the value in the notified column to 1 for all existing records.
-  $ret[] = update_sql('UPDATE {comment_notify} SET notified = 1');
-
-  return $ret;
-}
-
-/**
- * Having our foreign keys auto_increment could lead to unexpected results.
- */
-function comment_notify_update_6005() {
-  $ret = array();
-
-  db_change_field($ret, 'comment_notify', 'cid', 'cid',
-    array('type' => 'int',
-      'unsigned' => TRUE,
-      'description' => 'The comment id from {comments}.cid',
-      'not null' => TRUE,
-      'disp-width' => '11'));
-
-  db_change_field($ret, 'comment_notify_user_settings', 'uid', 'uid',
-    array('type' => 'int',
-      'unsigned' => TRUE,
-      'description' => 'The user id from {users}.cid',
-      'not null' => TRUE,
-      'disp-width' => '11'));
-
-  return $ret;
 }
\ No newline at end of file
Index: comment_notify.lib.inc
===================================================================
RCS file: comment_notify.lib.inc
diff -N comment_notify.lib.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ comment_notify.lib.inc	15 Nov 2009 06:11:24 -0000
@@ -0,0 +1,360 @@
+<?php
+// $Id;
+
+/**
+ * @file
+ *
+ * Contains functions which utilize the database and other internal helpers.
+ */
+
+/**
+ * Get the notification preferences for a specific user.
+ * 
+ * @param integer $uid
+ * @return StdClass
+ */
+function comment_notify_get_user_notification_setting($uid) {
+  $users = &drupal_static(__FUNCTION__);
+  if (!isset($users[$uid])) {
+    if (is_null($uid)) {
+      throw new Exception('Cannot get user preference, uid missing');
+    }
+    // Handle anonymous users with defaults.
+    if ($uid == 0) {
+      $users[0] = new StdClass();
+      $users[0]->comment_notify = comment_notify_variable_registry_get('default_registered_mailalert'); 
+      $users[0]->node_notify = comment_notify_variable_registry_get('node_notify_default_mailalert');
+    } else {
+      $result = db_select('comment_notify_user_settings', 'cnus')
+       ->fields('cnus')
+       ->condition('uid', $uid)
+       ->execute();
+      $users[$uid] = $result->fetchObject();
+    }
+  }
+  return $users[$uid];
+}
+
+/**
+ * Remove comment notification preferences for a user.
+ *  
+ * @param integer $uid
+ * @return boolean
+ */
+function comment_notify_delete_user_notification_setting($uid) {
+  return (bool)db_delete('comment_notify_user_settings')
+    ->condition('uid', $uid)
+    ->execute();
+}
+
+/**
+ * Get a user's default preference for comment notification.
+ * 
+ * @param integer $uid
+ * @return integer
+ */
+function comment_notify_get_user_comment_notify_preference($uid) {
+  $setting = comment_notify_get_user_notification_setting($uid);
+  return is_null($setting->comment_notify) ? comment_notify_variable_registry_get('node_notify_default_mailalert') : $setting->comment_notify;
+}
+
+/**
+ * Get a user's default preference for node update notification.
+ * 
+ * This is notification on nodes where the user is the author.
+ * 
+ * @param integer $uid
+ * @return integer
+ */
+function comment_notify_get_user_node_notify_preference($uid) {
+  $setting = comment_notify_get_user_notification_setting($uid);
+  return is_null($setting->node_notify) ? comment_notify_variable_registry_get('default_registered_mailalert') : $setting->node_notify;
+}
+
+/**
+ * Sets the notification preferences for a specific user.
+ * 
+ * @param integer $uid
+ * @param integer $node_notification
+ * @param integer $comment_notification
+ * @return boolean
+ */
+function comment_notify_set_user_notification_setting($uid, $node_notification = NULL, $comment_notification = NULL) {
+  if (!$uid) {
+    throw new Exception('Cannot set user preference, uid missing');
+  }
+  $fields = array('uid' => $uid);
+  if (!is_null($node_notification)) {
+    $fields['node_notify'] = $node_notification;
+  }
+  if (!is_null($comment_notification)) {
+    $fields['comment_notify'] = $comment_notification;  
+  }
+  if (comment_notify_get_user_notification_setting($uid)) {
+    $query = db_update('comment_notify_user_settings');
+    $query->condition('uid', $uid);
+  } else {
+    $query = db_insert('comment_notify_user_settings');
+  }
+  return (bool)$query
+    ->fields($fields)
+    ->execute();
+}
+
+/**
+ * Add a notification against a comment.
+ * 
+ * @param integer $cid
+ * @param integer $notify
+ * @param string $notify_hash
+ * @return boolean
+ */
+function comment_notify_add_notification($cid, $notify, $notify_hash) {
+  return (bool)db_insert('comment_notify')
+    ->fields(array(
+    	'cid' => $cid,
+      'notify' => $notify,
+      'notify_hash' =>$notify_hash,
+    ))
+    ->execute();
+}
+
+/**
+ * Remove all the notifications linked with a comment
+ * 
+ * @param integer $cid
+ * @return boolean
+ */
+function comment_notify_remove_all_notifications($cid) {
+  return (bool)db_delete('comment_notify')
+    ->condition('cid', $cid)
+    ->execute();
+}
+
+/**
+ * Updated a notification with a different notification type
+ * 
+ * @param integer $cid
+ * @param integer $notify
+ * @return boolean
+ */
+function comment_notify_update_notification($cid, $notify) {
+  return (bool)db_update('comment_notify')
+    ->fields(array(
+      'notify' => $notify,
+    ))
+    ->condition('cid', $cid)
+    ->execute();
+}
+
+/**
+ * Returns TRUE if the owner of this comment notification has already been notified.
+ * 
+ * @param integer $cid
+ * @return boolean
+ */
+function comment_notify_is_notification_already_sent($cid) {
+  return (bool) db_select('comment_notify', 'cn')
+    ->fields('cn', array('cid'))
+    ->condition('cid', $cid)
+    ->condition('notified', 1)
+    ->execute()
+    ->fetchField();
+}
+
+/**
+ * Get the unique identification hash for a comment notification record.
+ * 
+ * @param integer $cid
+ * @return string
+ */
+function comment_notify_get_notify_hash($cid) {
+ return db_select('comment_notify', 'cn')
+    ->fields('cn', array('notify_hash'))
+    ->condition('cid', $cid)
+    ->execute()
+    ->fetchField();
+}
+
+/**
+ * Get the type of notification for a comment notification record.
+ * 
+ * @param integer $cid
+ * @return integer
+ */
+function comment_notify_get_notification_type($cid) {
+ return db_select('comment_notify', 'cn')
+    ->fields('cn', array('notify'))
+    ->condition('cid', $cid)
+    ->execute()
+    ->fetchField();
+}
+
+/**
+ * Returns the thread which a comment belongs to.
+ * 
+ * @param integer $cid
+ * @return string
+ *  The thread identifier.
+ */
+function comment_notify_get_thread($cid) {
+  return db_select('comment', 'c')
+    ->fields('c', array('thread'))
+    ->condition('cid', $cid)
+    ->execute()
+    ->fetchField();
+}
+
+/**
+ * Get a list of mails which need to be contacted for a node.
+ * 
+ * @param integer $nid
+ * @return QueryStatement
+ */
+function comment_notify_get_watchers($nid) {
+  $query = db_select('comment', 'c');
+  $query->join('comment_notify', 'cn', 'c.cid = cn.cid');
+  $query->leftJoin('users', 'u', 'c.uid = u.uid');
+  $query
+    ->condition('nid', $nid)
+    ->condition('notify', COMMENT_NOTIFY_DISABLED, '<>')
+    ->condition('c.status', COMMENT_PUBLISHED)
+    ->condition(
+      db_or()
+        ->condition('u.uid', 0)
+        ->condition('u.status', 1)
+    )
+    ->fields('c', array('cid', 'nid', 'uid', 'name', 'thread'))
+    ->fields('cn', array('notify', 'notify_hash'));
+  $query->addField('c', 'mail', 'cmail');
+  $query->addField('u', 'init', 'uinit');
+  $query->addField('u', 'mail', 'umail');
+  
+  return $query->execute();
+}
+
+/**
+ * Record that the owner of a comment notification request has already been notified.
+ * 
+ * @param integer $cid
+ * @return boolean
+ */
+function comment_notify_mark_comment_as_notified($cid) {
+  return (bool)db_update('comment_notify')
+    ->fields(array(
+    	'notified' => 1,
+    ))
+    ->condition('cid', $cid)
+    ->execute();
+}
+
+/**
+ * Unsubscribe all comment notification requests associated with an email.
+ *
+ * If the email belongs to a user, it will unsubscribe all of their comment notify records.
+ * If it does not, then it will unsubscribe all anonymous users.
+ * 
+ * @param string $mail
+ * @return boolean
+ */
+function comment_notify_unsubscribe_by_email($mail) {
+  $update_query = db_update('comment_notify');
+  $update_query->fields(array('notify' => 0));
+  
+  $comment_query = db_select('comment', 'c');
+  $comment_query->fields('c', array('cid'));
+  
+  $uid = db_select('users', 'u')
+    ->fields('u', array('uid'))
+    ->condition('mail', $mail)
+    ->execute()
+    ->fetchField();
+  if ($uid) {
+    $comment_query->condition('uid', $uid);  
+  } else {
+    $comment_query->condition('mail', $mail);
+  }
+  $update_query->condition('cid', $comment_query, 'IN');
+  
+  return (bool)$update_query->execute();
+}
+
+/**
+ * Unsubscribe all comment notification requests associated with a hash.
+ * 
+ * This is used in the unsubscribe link.
+ * 
+ * @param string $hash
+ * @return boolean
+ */
+function comment_notify_unsubscribe_by_hash($hash) {
+  return (bool)db_update('comment_notify')
+    ->fields(array(
+    	'notify' => 0,
+    ))
+    ->condition('notify_hash', $hash)
+    ->execute();
+}
+  
+/**
+ * Helper function to centralize variable management and defaults.
+ * 
+ * All variables full under the "comment_notify" psuedo namespace.  This ensures
+ * consistancy, and eliminates some verbosity in the calling code.  In addition
+ * by storing all of the variables in one place, we avoid repeating duplicate
+ * defaults which are harder to maintain.
+ * 
+ * @param string $name
+ * @return mixed
+ */
+function comment_notify_variable_registry_get($name) {
+  $variables = array ();
+  $variables['author_subject'] = '[site:name] :: new comment for your post.';
+  $variables['available_alerts'] = array(COMMENT_NOTIFY_NODE, COMMENT_NOTIFY_COMMENT);
+  $variables['default_anon_mailalert'] = COMMENT_NOTIFY_NODE;
+  $variables['node_notify_default_mailtext'] = AUTHOR_MAILTEXT;
+  $variables['default_registered_mailalert'] = COMMENT_NOTIFY_DISABLED;
+  $variables['node_notify_default_mailalert'] = FALSE;
+  $variables['comment_notify_default_registered_mailalert'] = COMMENT_NOTIFY_DISABLED;
+  $variables['watcher_subject'] = '[site:name] :: new comment on [node:title]';
+  $variables['comment_notify_default_mailtext'] = DEFAULT_MAILTEXT;
+  $variables['node_types'] = array('article' =>'article');
+  
+  // Errors
+  $variables['error_anonymous_email_missing'] = 'If you want to subscribe to comments you must supply a valid e-mail address.';
+  return variable_get("comment_notify_" . $name, $variables[$name]);
+}
+
+/**
+ * Helper function to centralize setting variables.
+ * 
+ * @param string $name
+ * @param mixed $value
+ * @return boolean
+ */
+function comment_notify_variable_registry_set($name, $value) {
+  return variable_set("comment_notify_" . $name, $value);
+}
+
+/**
+ * Helper function to tokenize a piece of text for a comment notify mail.
+ * 
+ * @param string $text
+ * @param StdClass $comment
+ *  A comment object.
+ * @param StdClass $node
+ *  A node object.
+ * @param StdClass $user
+ *  A user object.
+ * @return string
+ *  The processed string.
+ */
+function comment_notify_tokenize($text, $comment, $node, $user) {
+  $data = array(
+    'node' => $node,
+    'comment' => $comment,
+    'user' => $user,
+  );
+  return token_replace($text, $data);
+}
+
Index: comment_notify.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/comment_notify/comment_notify.module,v
retrieving revision 1.72
diff -u -r1.72 comment_notify.module
--- comment_notify.module	7 Nov 2009 18:39:55 -0000	1.72
+++ comment_notify.module	15 Nov 2009 06:11:25 -0000
@@ -1,64 +1,70 @@
 <?php
 // $Id: comment_notify.module,v 1.72 2009/11/07 18:39:55 greggles Exp $
 
+// Contains functions which utilize the database and other internal helpers.
+include_once 'comment_notify.lib.inc';
+
 /**
  * @file
  *
  * This module provides comment follow-up e-mail notification for anonymous and registered users.
  */
 
+define('COMMENT_NOTIFY_DISABLED', 0);
+define('COMMENT_NOTIFY_NODE', 1);
+define('COMMENT_NOTIFY_COMMENT', 2);
+
+
 define('AUTHOR_MAILTEXT',
-'Hi !name,
+'Hi [user:name],
 
-You have received a comment on: "!node_title"
+You have received a comment on: "[node:title]"
 
 You can view the comment at the following url
-!comment_url
+[comment:url]
 
 You will receive emails like this for all replies to your posts. You can disable this by logging in and going to your account settings.
 
-Webmaster of !site
-!mission
-!uri');
+Webmaster of [site:name]
+[site:mission]
+[site:url]');
 
 define('DEFAULT_MAILTEXT',
-'Hi !name,
+'Hi [user:name],
 
-!commname has commented on: "!node_title"
+[comment:name] has commented on: "[node:title]"
 
 The post is about
 ----
-!node_teaser
+[node:summary]
 ----
 
 You can view the comment at the following url
-!comment_url
+[comment:url]
 
 You can stop receiving emails when someone replies to this post,
-by going to !link1
+by going to [comment:unsubscribe_url]
 
 If you have auto-following enabled in your account, you will receive emails like this for all replies to a blog post you commented on. You can disable this by logging in and going to your account settings or unchecking the flag at the time you post the comment.
 
 You can set up auto-following feature for all future posts
-by creating your own user with a few clicks here !uri/user/register
+by creating your own user with a few clicks here [site:url]/user/register
 
 Thanks for your feedback,
 
-Webmaster of !site
-!mission
-!uri');
+Webmaster of [site:name]
+[site:mission]
+[site:url]');
+
 
-define('COMMENT_NOTIFY_DISABLED', 0);
-define('COMMENT_NOTIFY_NODE', 1);
-define('COMMENT_NOTIFY_COMMENT', 2);
 
 /**
  * Provide an array of available options for notification on a comment.
  */
 function _comment_notify_options() {
   $total_options = array(
-    COMMENT_NOTIFY_NODE     => t('All comments'),
-    COMMENT_NOTIFY_COMMENT  => t('Replies to my comment')
+  COMMENT_NOTIFY_NODE     => t('All comments'),
+  COMMENT_NOTIFY_COMMENT  => t('Replies to my comment')
   );
 
   $available_options = array();
@@ -72,93 +78,99 @@
   return $available_options;
 }
 
-/**
- * Insert our checkbox, add a submit button, and populate fields.
- */
-function comment_notify_form_alter(&$form, &$form_state, $form_id) {
+
+function comment_notify_form_comment_form_alter(&$form, &$form_state, $form_id) {
   global $user;
+  if (!(user_access('subscribe to comments') || user_access('administer comments'))) {
+    return;
+  }
 
-  // Only alter the form if it's a comment form and the user has the permission to subscribe.
-  if ($form_id == 'comment_form' && (user_access('subscribe to comments') || user_access('administer comments'))) {
-    // Only add the checkbox if this is an enabled content type
-    $node = node_load($form['nid']['#value'] ? $form['nid']['#value'] : $form['nid']['#default_value']);
-    $enabled_types = variable_get('comment_notify_node_types', drupal_map_assoc(array($node->type)));
-    if (empty($enabled_types[$node->type])) {
-      return;
-    }
+  // Only add the checkbox if this is an enabled content type
+  $node = node_load($form['nid']['#value'] ? $form['nid']['#value'] : $form['nid']['#default_value']);
+  $enabled_types = variable_get('comment_notify_node_types', drupal_map_assoc(array($node->type)));
+  if (empty($enabled_types[$node->type])) {
+    return;
+  }
 
-    $available_options = _comment_notify_options();
+  $available_options = _comment_notify_options();
 
-    drupal_add_css(drupal_get_path('module', 'comment_notify') .'/comment_notify.css');
-    drupal_add_js(drupal_get_path('module', 'comment_notify') .'/comment_notify.js');
+  drupal_add_css(drupal_get_path('module', 'comment_notify') .'/comment_notify.css');
+  drupal_add_js(drupal_get_path('module', 'comment_notify') .'/comment_notify.js');
 
-    // Add the checkbox for anonymous users and set the default based on admin settings.
-    if ($user->uid == 0) {
-      // If anonymous user's can't enter their e-mail don't tempt them with the checkbox.
-      if (empty($form['mail'])) {
-        return;
-      }
-      $preference = variable_get('comment_notify_default_anon_mailalert', COMMENT_NOTIFY_DISABLED);
-    }
-    else {
-      $user_preference = db_result(db_query("SELECT comment_notify FROM {comment_notify_user_settings} WHERE uid = %d", $user->uid));
-      $preference = strlen($user_preference) ? $user_preference : variable_get('comment_notify_default_registered_mailalert', COMMENT_NOTIFY_DISABLED);
+  // Add the checkbox for anonymous users and set the default based on admin settings.
+  if ($user->uid == 0) {
+    // If anonymous user's can't enter their e-mail don't tempt them with the checkbox.
+    if (empty($form['mail'])) {
+      return;
     }
+    $preference = variable_get('comment_notify_default_anon_mailalert', COMMENT_NOTIFY_DISABLED);
+  }
+  else {
+    $preference = comment_notify_get_user_comment_notify_preference($user->uid);
+  }
 
-    // If you want to hide this on your site see http://drupal.org/node/322482
-    $form['notify_settings'] = array(
+  // If you want to hide this on your site see http://drupal.org/node/322482
+  $form['notify_settings'] = array(
       '#prefix' => '<div class="clear-block">',
       '#suffix' => '</div>',
-    );
+  );
 
-    $form['notify_settings']['notify'] = array(
+  $form['notify_settings']['notify'] = array(
       '#type' => 'checkbox',
       '#title' => t('Notify me when new comments are posted'),
       '#default_value' => $preference,
-    );
+  );
 
-    if (count($available_options) > 1) {
-      $form['notify_settings']['notify_type'] = array(
+  if (count($available_options) > 1) {
+    $form['notify_settings']['notify_type'] = array(
         '#type' => 'radios',
         '#options' => $available_options,
         '#default_value' => $preference,
-      );
-    }
-    else {
-      $form['notify_settings']['notify_type'] = array(
+    );
+  }
+  else {
+    $form['notify_settings']['notify_type'] = array(
         '#type' => 'hidden',
         '#value' => key($available_options),
-      );
-    }
-    $form['notify_settings']['notify_type']['#default_value'] = $preference;
+    );
+  }
+  $form['notify_settings']['notify_type']['#default_value'] = $preference;
 
-    // If this is an existing comment we set the default value based on their selection last time.
-    if ($form['cid']['#value'] != '') {
-      $notify = db_result(db_query("SELECT notify FROM {comment_notify} WHERE cid = %d", $form['cid']['#value']));
-      $form['notify_settings']['notify']['#default_value'] = $notify;
-      if (count($available_options) > 1) {
-        $form['notify_settings']['notify_type']['#default_value'] = $notify;
-      }
-      else {
-        $form['notify_settings']['notify_type']['#default_value'] = key($available_options);
-      }
+  // If this is an existing comment we set the default value based on their selection last time.
+  if ($form['cid']['#value'] != '') {
+    $notify = comment_notify_get_notification_type($form['cid']['#value']);
+    $form['notify_settings']['notify']['#default_value'] = $notify;
+    if (count($available_options) > 1) {
+      $form['notify_settings']['notify_type']['#default_value'] = $notify;
+    }
+    else {
+      $form['notify_settings']['notify_type']['#default_value'] = key($available_options);
     }
   }
 }
 
 /**
- * Implementation of hook_perm().
+ * Implement of hook_permission().
  */
-function comment_notify_perm() {
-  return array('administer comment notify', 'subscribe to comments');
+function comment_notify_permission() {
+  return array(
+    'administer comment notify' => array(
+      'title' => 'Administer Comment Notify',
+      'description' => 'Change global comment notification settings.',
+  ),
+    'subscribe to comments' => array(
+      'title' => 'Subscribe to comment notifications',
+      'description' => 'Subscribe to recieve notifications when new comments are posted.',
+  ),
+  );
 }
 
 /**
- * Implementation of hook_menu().
+ * Implement of hook_menu().
  */
 function comment_notify_menu() {
 
-  $items['admin/settings/comment_notify'] = array(
+  $items['admin/config/people/comment_notify'] = array(
     'title' => 'Comment notify',
     'description' => 'Configure settings for e-mails about new comments.',
     'page callback' => 'drupal_get_form',
@@ -166,7 +178,7 @@
     'access arguments' => array('administer comment notify'),
     'type' => MENU_NORMAL_ITEM,
   );
-  $items['admin/settings/comment_notify/settings'] = array(
+  $items['admin/config/people/comment_notify/settings'] = array(
     'title' => 'Settings',
     'description' => 'Configure settings for e-mails about new comments.',
     'page callback' => 'drupal_get_form',
@@ -175,7 +187,7 @@
     'type' => MENU_DEFAULT_LOCAL_TASK,
   );
 
-  $items['admin/settings/comment_notify/unsubscribe'] = array(
+  $items['admin/config/people/comment_notify/unsubscribe'] = array(
     'title' => 'Unsubscribe',
     'description' => 'Unsubscribe an email from all notifications.',
     'weight' => 2,
@@ -199,158 +211,188 @@
  * Page callback to allow users to unsubscribe simply by visiting the page.
  */
 function comment_notify_disable_page($hash) {
-  db_query("UPDATE {comment_notify} SET notify = 0 WHERE notify_hash = '%s'", $hash);
-
-  drupal_set_message(t('Your comment follow-up notification for this post was disabled. Thanks.'));
+  if (comment_notify_unsubscribe_by_hash($hash)) {
+    drupal_set_message(t('Your comment follow-up notification for this post was disabled. Thanks.'));
+  } else {
+    drupal_set_message(t('Sorry, there was a problem unsubscribing from notifications.'));
+  }
   return ' ';
 }
 
 /**
- * Implementation of hook_comment().
+ * Implement hook_comment_validate().
  */
-function comment_notify_comment($comment, $op) {
+function comment_notify_comment_validate($comment) {
   global $user;
+  // 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->uid && $comment->notify && empty($comment->mail)) {
+    form_set_error('mail', t(comment_notify_variable_registry_get('error_anonymous_email_missing')));
+  }
+}
 
-  // In theory, the update or insert operations are duplicates with publish which
-  // would lead to duplicate messages.  _comment_notify_mailalert() protects against that.
-  switch ($op) {
-    case 'validate':
-       // 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->uid && $comment['notify'] && empty($comment['mail'])) {
-        form_set_error('mail', t('If you want to subscribe to comments you must supply a valid e-mail address.'));
-      }
-      break;
-    case 'publish':
-      // And send notifications - the real purpose of the module.
-      _comment_notify_mailalert($comment);
-      break;
-    case 'update':
-      // In case they have changed their status, save it in the database.
-      $sql = 'UPDATE {comment_notify} SET notify = %d WHERE cid = %d';
-      if ($comment['notify']) {
-        db_query($sql, $comment['notify_type'], $comment['cid']);
-      }
-      else {
-        db_query($sql, 0, $comment['cid']);
-      }
-      // And send notifications - the real purpose of the module.
-      if ($comment['status'] == COMMENT_PUBLISHED) {
-        _comment_notify_mailalert($comment);
-      }
-      break;
-    case 'insert':
-      // For new comments, we first build up a string to be used as the identifier for the alert
-      $mail = empty($comment['mail']) ? $user->mail : $comment['mail'];
-      $notify_hash = drupal_get_token($mail . $comment['cid']);
-
-      if ($comment['notify']) {
-        $notify = $comment['notify_type'];
-        // If they don't have a preference, save one.
-        $current = db_result(db_query("SELECT count(1) from {comment_notify_user_settings} WHERE uid = %d", $user->uid));
-        if ($current == 0 && $user->uid) {
-          db_query("INSERT INTO {comment_notify_user_settings} (uid, comment_notify) VALUES (%d, %d)", $user->uid, $comment['notify_type']);
-        }
-      }
-      else {
-        $notify = $comment['notify'];
-      }
-      // And then save the data.
-      db_query("INSERT INTO {comment_notify} (cid, notify, notify_hash) values (%d, %d, '%s')", $comment['cid'], $notify, $notify_hash);
+/**
+ * Implement hook_comment_publish().
+ */
+function comment_notify_comment_publish($comment) {
+  // And send notifications - the real purpose of the module.
+  _comment_notify_mailalert($comment);
+}
 
-      // And send notifications - the real purpose of the module.
-      if ($comment['status'] == COMMENT_PUBLISHED) {
-        _comment_notify_mailalert($comment);
-      }
-      break;
-    case 'delete':
-      db_query("DELETE FROM {comment_notify} WHERE cid = %d", $comment->cid);
-      break;
+/**
+ * Implement hook_comment_update().
+ */
+function comment_notify_comment_update($comment) {
+  // In case they have changed their status, save it in the database.
+  comment_notify_update_notification($comment->cid, $comment->notify_type);
+  // And send notifications - the real purpose of the module.
+  if ($comment->status == COMMENT_PUBLISHED) {
+    _comment_notify_mailalert($comment);
   }
 }
 
 /**
- * Implementation of hook_user().
+ * Implement hook_comment_insert().
  */
-function comment_notify_user($type, &$edit, &$user, $category = NULL) {
-  switch ($type) {
-    case 'form':
-      if ($category == 'account' && user_access('subscribe to comments', $user)) {
-        $form = array();
-        $form['comment_notify_settings'] = array(
-          '#type' => 'fieldset',
-          '#title' => t('Comment follow-up notification settings'),
-          '#weight' => 4,
-          '#collapsible' => TRUE
-        );
-
-        // Only show the node followup UI if the user has permission to create nodes.
-        $nodes = FALSE;
-        foreach (node_get_types() as $type) {
-          if (user_access('create '. $type->type .' content')) {
-            $nodes = TRUE;
-            break;
-          }
-        }
-        if (user_access('administer nodes') || $nodes) {
-          $form['comment_notify_settings']['node_notify_mailalert'] = array(
+function comment_notify_comment_insert($comment) {
+  global $user;
+  // For new comments, we first build up a string to be used as the identifier for the alert
+  $mail = empty($comment->mail) ? $user->mail : $comment->mail;
+  $notify_hash = drupal_get_token($mail . $comment->cid);
+
+  if ($comment->notify) {
+    $notify = $comment->notify_type;
+    // If they don't have a preference, save one.
+    $current = comment_notify_get_user_comment_notify_preference($user->uid);
+    if ($current == 0 && $user->uid) {
+      comment_notify_set_user_notification_setting($user->uid, NULL, $comment->notify_type);
+    }
+  }
+  else {
+    $notify = 0;
+  }
+  // And then save the data.
+  comment_notify_add_notification($comment->cid, $notify, $notify_hash);
+
+  // And send notifications - the real purpose of the module.
+  if ($comment->status == COMMENT_PUBLISHED) {
+    _comment_notify_mailalert($comment);
+  }
+}
+
+/**
+ * Implement hook_comment_delete().
+ */
+function comment_notify_comment_delete($comment) {
+  comment_notify_remove_all_notifications($comment->cid);
+}
+
+/**
+ * Implement hook_form_alter().
+ */
+function comment_notify_form_alter(&$form, &$form_state, $form_id) {
+  if (!($form_id == 'user_register_form' || $form_id == 'user_profile_form')) {
+    return;
+  }
+  elseif ($form['#user_category'] != 'account'){
+    return;
+  }
+
+  $user = $form['#user'];
+  if ($user->comment_notify_settings) {
+    $node_notify = $user->comment_notify_settings->node_notify;
+    $comment_notify = $user->comment_notify_settings->comment_notify;
+  }
+
+
+  $form['comment_notify_settings'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Comment follow-up notification settings'),
+    '#weight' => 4,          '#collapsible' => TRUE
+  );
+
+
+  // Only show the node followup UI if the user has permission to create nodes.
+  $nodes = FALSE;
+  foreach (node_type_get_names() as $type) {
+    if (user_access('create '. $type .' content')) {
+      $nodes = TRUE;
+      break;
+    }
+  }
+
+  if (user_access('administer nodes') || $nodes) {
+    $form['comment_notify_settings']['node_notify'] = array(
             '#type' => 'checkbox',
             '#title' => t('Receive node follow-up notification e-mails'),
-            '#default_value' => isset($edit['node_notify_mailalert']) ? $edit['node_notify_mailalert'] : variable_get('node_notify_default_mailalert', FALSE),
+            '#default_value' => isset($node_notify) ? $node_notify : comment_notify_variable_registry_get('node_notify_default_mailalert'),
             '#description' => t('Check this box to receive an e-mail notification for follow-ups on your nodes (pages, forum topics, etc). You can not disable notifications for individual threads.')
-          );
-        }
-        else {
-          $form['comment_notify_settings']['node_notify_mailalert'] = array(
+    );
+  }
+  else {
+    $form['comment_notify_settings']['node_notify'] = array(
             '#type' => 'hidden',
             '#value' => COMMENT_NOTIFY_DISABLED,
-          );
-        }
+    );
+  }
 
-        $available_options[COMMENT_NOTIFY_DISABLED] = t('No notifications');
-        $available_options += _comment_notify_options();
-        $form['comment_notify_settings']['comment_notify_mailalert'] = array(
+  $available_options[COMMENT_NOTIFY_DISABLED] = t('No notifications');
+  $available_options += _comment_notify_options();
+  $form['comment_notify_settings']['comment_notify'] = array(
           '#type' => 'select',
           '#title' => t('Receive comment follow-up notification e-mails'),
-          '#default_value' => isset($edit['comment_notify_mailalert']) ? $edit['comment_notify_mailalert'] : variable_get('comment_notify_default_registered_mailalert', COMMENT_NOTIFY_DISABLED),
+          '#default_value' => isset($comment_notify) ? array($comment_notify) : array(comment_notify_variable_registry_get('comment_notify_default_registered_mailalert')),
           '#options' => $available_options,
           '#description' => t("Check this box to receive e-mail notification for follow-up comments to comments you posted. You can later disable this on a post-by-post basis... so if you leave this to YES, you can still disable follow-up notifications for comments you don't want follow-up mails anymore - i.e. for very popular posts.")
-        );
-        return $form;
-      }
-      break;
+  );
+  return $form;
+  // Construct the user form
+}
+/**
+ * Implement hook_user_update().
+ */
+function comment_notify_user_update(&$edit, $account, $category) {
+  if ($category != 'account') {
+    return;
+  }
 
-    case 'submit':
-      // Save the values of node_notify_mailalert and comment_notify_mailalert
-      // to {comment_notify_user_settings}.
-      db_query('UPDATE {comment_notify_user_settings} SET node_notify = %d, comment_notify = %d WHERE uid = %d', $edit['node_notify_mailalert'], $edit['comment_notify_mailalert'], $user->uid);
-      if (!db_affected_rows()) {
-        db_query('INSERT INTO {comment_notify_user_settings} (uid, node_notify, comment_notify) VALUES (%d, %d, %d)', $user->uid, $edit['node_notify_mailalert'], $edit['comment_notify_mailalert']);
-      }
+  // Save the values of node_notify_mailalert and comment_notify_mailalert
+  // to {comment_notify_user_settings}.
+  comment_notify_set_user_notification_setting($account->uid, $edit['node_notify'], $edit['comment_notify']);
 
-      // Unset them from $user so they don't also get saved into {users}.data.
-      unset($edit['node_notify_mailalert']);
-      unset($edit['comment_notify_mailalert']);
-      break;
+  // Unset them from $user so they don't also get saved into {users}.data.
+  unset($edit['node_notify']);
+  unset($edit['comment_notify']);
 
-    case 'load':
-      $user_settings = db_fetch_array(db_query('SELECT node_notify AS node_notify_mailalert, comment_notify AS comment_notify_mailalert FROM {comment_notify_user_settings} WHERE uid = %d', $user->uid));
-      if (!empty($user_settings)) {
-        foreach ($user_settings as $property => $value) {
-          $user->$property = $value;
-        }
-      }
-      break;
+}
 
-    case 'delete':
-      db_query('DELETE FROM {comment_notify_user_settings} WHERE uid = %d', $user->uid);
-      break;
+/**
+ * Implement hook_user_load().
+ */
+function comment_notify_user_load(&$users) {
+  // Why would we want to load this on every user load?
+  foreach ($users as &$user) {
+    $user->comment_notify_settings = comment_notify_get_user_notification_setting($user->uid);
+  }
+  return;
 
-      break;
+  // @todo: Fix this naming weirdness.
+  foreach ($users as $user) {
+    $result = db_select('comment_notify_user_settings', 'cnus')
+    ->fields('cnus', array('node_notify' => 'node_notify_mailalert', 'comment_notify' => 'comment_notify_mailalert'))
+    ->condition('uid', $user->uid)
+    ->execute();
   }
 }
 
 /**
+ * Implement hook_user_cancel().
+ */
+function comment_notify_user_cancel(&$edit, $account, $method) {
+  comment_notify_delete_user_notification_setting($account->uid);
+}
+
+/**
  * Private function to send the notifications.
  *
  * @param $comment
@@ -368,7 +410,7 @@
   // 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 (db_result(db_query('SELECT cid from {comment_notify} WHERE cid = %d AND notified = %d', $cid, 1))) {
+  if (comment_notify_is_notification_already_sent($cid)) {
     return;
   }
 
@@ -376,16 +418,10 @@
 
   if (function_exists('locale')) {
     $languages = locale_language_list();
-    $languages = $languages['name'];
   }
 
   $node = node_load($nid);
 
-  // Render up the node and comment.
-  $node_teaser = node_view($node, TRUE, TRUE, FALSE);
-  $node_body = node_view($node, FALSE, TRUE, FALSE);
-  $comment_text = check_markup($comment->comment, $comment->format);
-
   // No mails if this is not an enabled content type.
   $enabled_types = variable_get('comment_notify_node_types', array($node->type => TRUE));
   if (empty($enabled_types[$node->type])) {
@@ -402,47 +438,31 @@
   $sent_to = array();
 
   // Send to a subscribed author if they are not the current commenter
-  $author = user_load(array('uid' => $node->uid));
-  if (!empty($author->node_notify_mailalert) && $author->node_notify_mailalert == 1 && $user->uid != $author->uid && node_access('view', $node, $author)) {
+  $author = user_load($node->uid);
 
+  if (!empty($author->comment_notify_settings->node_notify) && $author->node_notify_mailalert == 1 && $user->uid != $author->uid && node_access('view', $node, $author)) {
     // Get the author's language.
     $language = user_preferred_language($author);
-    $message['subject'] = t('!site :: new comment for your post.', array('!site' => variable_get('site_name', 'drupal')));
-    $message['body'] = t(
-      variable_get('node_notify_default_mailtext', AUTHOR_MAILTEXT),
-      array(
-        '!commname' => $comment->name,
-        '!commtext' => drupal_html_to_text($comment_text),
-        '!commsubj' => $comment->subject,
-        '!comment_url' => url('node/'. $nid, array('absolute' => TRUE, 'fragment' => 'comment-'. $cid)),
-        '!node_title' =>  $node->title,
-        '!node_teaser' => drupal_html_to_text($node_teaser),
-        '!mission' => variable_get('site_mission', ''),
-        '!node_body' =>  drupal_html_to_text($node_body),
-        '!name' => $author->name,
-        '!site' => variable_get('site_name', 'drupal'),
-        '!uri' => $base_url,
-        '!uri_brief' => preg_replace('!^https?://!', '', $base_url),
-        '!date' => format_date(time()),
-        '!login_uri' => url('user', array('absolute' => TRUE)),
-        '!edit_uri' => url('user/'. $author->uid .'/edit', array('absolute' => TRUE))
-      )
+    $raw_values = array (
+      'subject' => comment_notify_variable_registry_get('author_subject'),
+      'body'  => comment_notify_variable_registry_get('node_notify_default_mailtext'), //JS @todo:change this.
     );
+    foreach ($raw_values as $k => $v) {
+      $message[$k] = comment_notify_tokenize(t($v), $comment, $node, $user);
+    }
+
     drupal_mail('comment_notify', 'comment_notify_mail', $author->mail, $language, $message);
     $sent_to[] = $author->mail;
   }
 
   // For "reply to my comments" notifications, figure out what thread this is.
-  $thread = db_result(db_query("SELECT thread FROM {comments} WHERE cid = %d", $cid));
+  $thread = comment_notify_get_thread($cid);
 
-  //Get the list of commenters to notify
-  $result = db_query(db_rewrite_sql("SELECT c.cid, c.nid, c.uid, c.name, c.mail AS cmail, u.mail AS umail, u.init AS uinit, c.uid, c.name, cn.notify, cn.notify_hash, c.thread
-    FROM {comments} c INNER JOIN {comment_notify} cn on c.cid = cn.cid LEFT OUTER JOIN {users} u ON c.uid = u.uid
-    WHERE c.nid = %d AND cn.notify > 0 AND c.status = 0 AND (u.status = 1 OR u.uid = 0)", 'c', 'cid'), $nid
-  );
   // TODO? the original big query had stuff making sure the mail was populated and contained .+@.+ Perhaps check for that here and set notify = 0 if that is the case for this cid
+  // Get the list of commenters to notify.
+  $watchers = comment_notify_get_watchers($nid);
 
-  while ($alert = db_fetch_object($result)) {
+  foreach ($watchers as $alert) {
     $umail = empty($alert->umail) ? $alert->uinit : $alert->umail;
     $mail = empty($alert->cmail) ? $umail : $alert->cmail;
 
@@ -450,7 +470,9 @@
     if ($alert->notify == COMMENT_NOTIFY_COMMENT && strcmp($relevant_thread . '/', $alert->thread) != 0) {
       continue;
     }
+
     if ($mail != $comment_mail && !in_array($mail, $sent_to) && $alert->uid != $comment->uid) {
+
       $message = array();
       if (!empty($alert->uid)) {
         $recipient_user = user_load(array('uid' => $alert->uid));
@@ -465,28 +487,15 @@
         continue;
       }
 
-      $message['subject'] = t('!site :: new comment for your post.', array('!site' => variable_get('site_name', 'drupal')));
-      $message['body'] = t(
-        variable_get('comment_notify_default_mailtext', DEFAULT_MAILTEXT),
-        array(
-          '!commname' => $comment->name,
-          '!commtext' => drupal_html_to_text($comment_text),
-          '!commsubj' => $comment->subject,
-          '!comment_url' => url('node/'. $nid, array('absolute' => TRUE, 'fragment' => 'comment-'. $cid)),
-          '!node_title' =>  $node->title,
-          '!node_teaser' => drupal_html_to_text($node_teaser),
-          '!mission' => variable_get('site_mission', ''),
-          '!node_body' =>  drupal_html_to_text($node_body),
-          '!name' => $alert->name,
-          '!site' => variable_get('site_name', 'drupal'),
-          '!uri' => $base_url,
-          '!uri_brief' => preg_replace('!^https?://!', '', $base_url),
-          '!date' => format_date(time()),
-          '!login_uri' => url('user', array('absolute' => TRUE)),
-          '!edit_uri' => url('user/'. $alert->uid .'/edit', array('absolute' => TRUE)),
-          '!link1' => url('comment_notify/disable/'. $alert->notify_hash, array('absolute' => TRUE))
-        )
+      $raw_values = array (
+        'subject' => comment_notify_variable_registry_get('watcher_subject'),
+        'body'  => comment_notify_variable_registry_get('comment_notify_default_mailtext'), //JS @todo:change this var name.
       );
+
+      foreach ($raw_values as $k => $v) {
+        $message[$k] = comment_notify_tokenize(t($v), $comment, $node, $user);
+      }
+
       drupal_mail('comment_notify', 'comment_notify_mail', $mail, $language, $message);
       $sent_to[] = $mail;
 
@@ -515,11 +524,12 @@
   }
   // Record that a notification was sent for this comment so that
   // notifications aren't sent again if the comment is later edited.
-  db_query('UPDATE {comment_notify} SET notified = 1 WHERE cid = %d', $cid);
+
+  comment_notify_mark_comment_as_notified($cid);
 }
 
 /**
- * Implementation of hook_mail().
+ * Implement hook_mail().
  */
 function comment_notify_mail($key, &$message, $params) {
   $message['subject'] = $params['subject'];
@@ -529,7 +539,7 @@
 /**
  * Callback for an administrative form to unsubscribe users by e-mail address.
  */
-function comment_notify_unsubscribe() {
+function comment_notify_unsubscribe($form, &$form_state) {
   $form['comment_notify_unsubscribe'] = array();
   $form['comment_notify_unsubscribe']['email_to_unsubscribe'] = array(
     '#type' => 'textfield',
@@ -547,16 +557,7 @@
  */
 function comment_notify_unsubscribe_submit($form, &$form_state) {
   $email = trim($form_state['values']['email_to_unsubscribe']);
-  // If they have a uid, use that, otherwise update comments directly
-  $result = db_result(db_query_range("SELECT uid FROM {users} WHERE mail = '%s'", $email, 0, 1));
-  if ($result > 0) {
-    $comments = db_result(db_query("SELECT COUNT(1) FROM {comments} c INNER JOIN {comment_notify} cn ON c.cid = cn.cid WHERE c.uid = %d AND cn.notify > 0", $result));
-    db_query("UPDATE {comment_notify} SET notify = 0 WHERE cid IN (SELECT cid FROM  {comments} WHERE uid = %d)", $result);
-  }
-  else {
-    $comments = db_result(db_query("SELECT COUNT(1) FROM {comments} c INNER JOIN {comment_notify} cn ON c.cid = cn.cid WHERE c.mail = '%s' AND cn.notify > 0", $email));
-    db_query("UPDATE {comment_notify} SET notify = 0 WHERE cid IN (SELECT cid FROM {comments} WHERE mail = '%s')", $email);
-  }
+  $comments = comment_notify_unsubscribe_by_email($email);
   // Update the admin about the state of this comment notification subscription.
   if ($comments == 0) {
     drupal_set_message(t("There were no active comment notifications for that email."));
@@ -573,16 +574,16 @@
 function comment_notify_settings() {
   $form['comment_notify_settings'] = array();
 
-  // Only perform comment_notify for certain node types (default, all)
-  $enabled_types = variable_get('comment_notify_node_types', FALSE);
+  // Only perform comment_notify for certain node types.
+  $enabled_types = comment_notify_variable_registry_get('node_types');
   $anonymous_problems = '';
-  foreach (node_get_types('names') as $type => $name) {
+  foreach (node_type_get_names() as $type => $name) {
     $checkboxes[$type] = check_plain($name);
     $default[] = $type;
 
     // If they don't have the ability to leave contact info, then we make a report
     if (isset($enabled_types[$type]) && $enabled_types[$type] && variable_get('comment_anonymous_'. $type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
-      $account = user_load(array('uid' => 0));
+      $account = drupal_anonymous_user();
       if (user_access('subscribe to comments', $account)) {
         $anonymous_problems[] = l(t('@content-type', array('@content-type' => $name)), 'admin/content/node-type/'. $type);
       }
@@ -596,7 +597,7 @@
   $form['comment_notify_settings']['comment_notify_node_types'] = array(
     '#type' => 'checkboxes',
     '#title' => t('Content types to enable for comment notification'),
-    '#default_value' => variable_get('comment_notify_node_types', $default),
+    '#default_value' => $enabled_types,
     '#options' => $checkboxes,
     '#description' => t('Comments on content types enabled here will have the option of comment notification.'),
   );
@@ -605,7 +606,7 @@
     '#type' => 'checkboxes',
     '#title' => t('Available subscription modes'),
     '#return_value' => 1,
-    '#default_value' => variable_get('comment_notify_available_alerts', array(COMMENT_NOTIFY_NODE, COMMENT_NOTIFY_COMMENT)),
+    '#default_value' => comment_notify_variable_registry_get('available_alerts'),
     '#description' => t('Choose which notification subscription styles are available for users'),
     '#options' => array(
       COMMENT_NOTIFY_NODE     => t('All comments'),
@@ -619,7 +620,7 @@
     '#type' => 'select',
     '#title' => t('Default state for the notification selection box for anonymous users'),
     '#return_value' => 1,
-    '#default_value' => variable_get('comment_notify_default_anon_mailalert', COMMENT_NOTIFY_NODE),
+    '#default_value' => comment_notify_variable_registry_get('default_anon_mailalert'),
     '#options' => $available_options,
   );
 
@@ -627,73 +628,35 @@
     '#type' => 'select',
     '#title' => t('Default state for the notification selection box for registered users'),
     '#return_value' => 1,
-    '#default_value' => variable_get('comment_notify_default_registered_mailalert', COMMENT_NOTIFY_NODE),
+    '#default_value' => comment_notify_variable_registry_get('default_registered_mailalert'),
     '#description' => t('This flag presets the flag for the follow-up notification on the form that anon users will see when posting a comment'),
     '#options' => $available_options,
   );
 
-  $form['comment_notify_settings']['node_notify_default_mailalert'] = array(
+  $form['comment_notify_settings']['comment_notify_node_notify_default_mailalert'] = array(
     '#type' => 'checkbox',
     '#title' => t('Subscribe users to their node follow-up notification emails by default'),
-    '#default_value' => variable_get('node_notify_default_mailalert', FALSE),
+    '#default_value' => comment_notify_variable_registry_get('node_notify_default_mailalert'),
     '#description' => t('If this is checked, new users will receive e-mail notifications for follow-ups on their nodes by default until they individually disable the feature.'),
   );
 
+  $token_help = "Need a theme_token_info :(";
 
-  $form['comment_notify_settings']['comment_notify_default_mailtext'] = array(
+  $form['comment_notify_settings']['comment_notify_comment_notify_default_mailtext'] = array(
     '#type' => 'textarea',
     '#title' => t('Default mail text for sending out notifications to commenters'),
-    '#description' => t(
-      'You can use the following variables to be replaced:
-      <ul>
-      <li>!commname = the username who posted the comment
-      <li>!commtext = the text of the posted comment
-      <li>!commsubj = the subject of the posted comment
-      <li>!comment_url = the full url of the post and comment - note: if you have paging enabled, this does not work correct - set your max comments per page so that all fit on one page or reverse order them
-      <li>!node_title = the title of the node that was commented on
-      <li>!node_teaser = the teaser of the node that was commented on
-      <li>!node_body = the body of the node that was commented on
-      <li>!mission = site_mission text
-      <li>!name = username receiving the alert
-      <li>!site = your site
-      <li>!uri = base_url of site
-      <li>!uri_brief = base_url of site w/o http
-      <li>!date = the current time
-      <li>!login_uri  uri to login the user
-      <li>!edit_uri = uri to edit user profile
-      <li>!link1 the QUICKLINK to disable future follow-up notifications for the user
-      </ul>'
-    ),
-    '#default_value' => variable_get('comment_notify_default_mailtext', t(DEFAULT_MAILTEXT)),
+    '#suffix' => $token_help,
+    '#default_value' => comment_notify_variable_registry_get('comment_notify_default_mailtext'),
     '#return_value' => 1,
     '#cols' => 80,
     '#rows' => 15
   );
 
-  $form['comment_notify_settings']['node_notify_default_mailtext'] = array(
+  $form['comment_notify_settings']['comment_notify_node_notify_default_mailtext'] = array(
     '#type' => 'textarea',
     '#title' => t('Default mail text for sending out the notifications to node authors'),
-    '#description' => t(
-      'You can use the following variables to be replaced:
-      <ul>
-      <li>!commname = the username who posted the comment
-      <li>!commtext = the text of the posted comment
-      <li>!commsubj = the subject of the posted comment
-      <li>!comment_url = the full url of the post and comment - note: if you have paging enabled, this does not work correct - set your max comments per page so that all fit on one page or reverse order them
-      <li>!node_title = the title of the node that was commented on
-      <li>!node_teaser = the teaser of the node that was commented on
-      <li>!node_body = the body of the node that was commented on
-      <li>!mission = site_mission text
-      <li>!name = username receiving the alert
-      <li>!site = your site
-      <li>!uri = base_url of site
-      <li>!uri_brief = base_url of site w/o http
-      <li>!date = the current time
-      <li>!login_uri  uri to login the user
-      <li>!edit_uri = uri to edit user profile
-      </ul>'
-    ),
-    '#default_value' => variable_get('node_notify_default_mailtext', t(AUTHOR_MAILTEXT)),
+    '#suffix' => $token_help,
+    '#default_value' => comment_notify_variable_registry_get('node_notify_default_mailtext'),
      '#return_value' => 1,
      '#cols' => 80,
      '#rows' => 15
@@ -713,3 +676,23 @@
     form_set_error('comment_notify_available_alerts', 'You must enable at least one subscription mode.');
   }
 }
+
+
+/**
+ * Implement hook_tokens();
+ */
+function comment_notify_tokens($type, $tokens, array $data = array(), array $options = array()) {
+  // Add the tokens for unsubscribe links
+  if ($type != "comment" ||!isset($data['comment'])) {
+    return;
+  }
+  $cid = $data['comment']->cid;
+  $hash = comment_notify_get_notify_hash($cid);
+  if (!$hash) {
+    return;
+  }
+  $replacements = array();
+  $replacements['comment:unsubscribe_url'] = url('comment_notify/disable/'. $hash, array('absolute' => TRUE));
+  return $replacements;
+
+}
Index: comment_notify.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/comment_notify/comment_notify.test,v
retrieving revision 1.3
diff -u -r1.3 comment_notify.test
--- comment_notify.test	7 Nov 2009 18:39:55 -0000	1.3
+++ comment_notify.test	15 Nov 2009 06:11:25 -0000
@@ -45,17 +45,20 @@
     $this->drupalGet('comment/reply/' . $this->node->nid);
 
     // Ensure that the contact form won't be shown without categories.
-    $this->setPermission('anonymous user', array('access comments' => TRUE, 'access content' => TRUE, 'post comments' => TRUE, 'post comments without approval' => TRUE, 'subscribe to comments' => TRUE));
+    $this->setPermission('anonymous', array('access comments' => TRUE, 'access content' => TRUE, 'post comments' => TRUE, 'post comments without approval' => TRUE, 'subscribe to comments' => TRUE));
     $this->drupalLogout();
 
     $subscribe_1 = array('notify' => TRUE, 'notify_type' => 1);
     $this->postCommentNotifyComment($this->node, $this->randomName(), $this->randomName(), TRUE, TRUE, $subscribe_1);
-    $this->assertText(t('If you want to subscribe to comments you must supply a valid e-mail address.'), t('Anonymous user must leave E-mail if they want to get notifications.'));
+    
+    // This is still a bad test to test for a static string showing on the page, but at least the definition of the string is centralized.
+    $expected_error = comment_notify_variable_registry_get('error_anonymous_email_missing');
+    $this->assertText(t($expected_error));
 
     $anonymous_comment_1 = $this->postCommentNotifyComment($this->node, $this->randomName(), $this->randomName(), TRUE, $subscribe_1, array('mail' => $this->randomName() .'@'. $this->randomName()));
 
     // Confirm that the notification is saved.
-    $result = db_result(db_query("SELECT notify FROM {comment_notify} WHERE cid = %d", $anonymous_comment_1['id']));
+    $result = comment_notify_get_notification_type($anonymous_comment_1['id']);
     $this->assertEqual($result, $subscribe_1['notify_type'], 'Notify selection option 1 is saved properly.');
 
     // Notify type 2.
@@ -63,7 +66,7 @@
     $anonymous_comment_2 = $this->postCommentNotifyComment($this->node, $this->randomName(), $this->randomName(), TRUE, $subscribe_2, array('mail' => $this->randomName() .'@'. $this->randomName()));
 
     // Confirm that the notification is saved.
-    $result = db_result(db_query("SELECT notify FROM {comment_notify} WHERE cid = %d", $anonymous_comment_2['id']));
+    $result = comment_notify_get_notification_type($anonymous_comment_2['id']);
     $this->assertEqual($result, $subscribe_2['notify_type'], 'Notify selection option 2 is saved properly.');
 
     // Notify type 0 (i.e. only one mode is enabled).
@@ -72,11 +75,9 @@
     $anonymous_comment_0 = $this->postCommentNotifyComment($this->node, $this->randomName(), $this->randomName(), TRUE, $subscribe_0, array('mail' => $this->randomName() .'@'. $this->randomName()));
 
     // Confirm that the notification is saved.
-    $result = db_result(db_query("SELECT notify FROM {comment_notify} WHERE cid = %d", $anonymous_comment_0['id']));
+    $result = comment_notify_get_notification_type($anonymous_comment_0['id']);
     $this->assertEqual($result, 2, 'Notify selection option 0 is saved properly.');
 
-
-
     // TODO a whole bunch more tests that check if mail was "sent".
   }
 
@@ -87,21 +88,13 @@
    * @param string $role User role to set permissions for.
    * @param array $permissions Key-value array of permissions to set.
    */
-  function setPermission($role, $permissions) {
+  function setPermission($role_name, $permissions) {
     // Get role id (rid) for specified role.
-    $rid = db_result(db_query("SELECT rid FROM {role} WHERE name = '%s'", array('%s' => $role)));
-    if ($rid === FALSE) {
-      $this->fail(t(' [permission] Role "' . $role . '" not found.'));
-    }
-
-    // Create edit array from permission.
-    $edit = array();
-    foreach ($permissions as $name => $value) {
-      $edit[$rid . '[' . $name . ']'] = $value;
+    $role = user_role_load($role_name);
+    if ($role) {
+      $this->fail('Unable to load role: ' . $role_name);
     }
-
-    $this->drupalPost('admin/user/permissions', $edit, t('Save permissions'));
-    $this->assertText(t('The changes have been saved.'), t(' [permission] Saved changes.'));
+    user_role_change_permissions($role->rid, $permissions);
   }
 
   /////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
