diff -u -r1.10 inactive_user.module
--- inactive_user.module	20 Jun 2009 04:38:26 -0000	1.10
+++ inactive_user.module	17 Dec 2009 02:36:32 -0000
@@ -236,7 +236,7 @@
 function inactive_user_cron() {
   if ((time() - variable_get('inactive_user_timestamp', '0')) >= 86100) { // Only check once every almost-day, so we slide around the clock and don't overload the server.
     variable_set('inactive_user_timestamp', time());
-    unset($user_list);
+    $user_list = '';
 
     // reset notifications if recent user activity
     $users = db_fetch_object(db_query('SELECT uid FROM {inactive_users} WHERE uid <> 1'));
@@ -264,7 +264,7 @@
           $user_list .= "$user->name ($user->mail) last active on ". format_date($user->access, 'large') .".\n";
         }
       }
-      if ($user_list) {
+      if (isset($user_list)) {
         _inactive_user_mail(t('[@sitename] Inactive users', array('@sitename' => variable_get('site_name', 'drupal'))), _inactive_user_mail_text('notify_admin_text'), $notify_time, NULL, $user_list);
         unset($user_list);
       }
@@ -288,9 +288,10 @@
     // warn users when they are about to be blocked
     if (($warn_time = variable_get('inactive_user_auto_block_warn', 0)) &&
         ($block_time = variable_get('inactive_user_auto_block', 0))) {
-      $result = db_query('SELECT * FROM {users} WHERE ((access <> 0 AND login <> 0 AND access < (%d - %d - %d)) OR (login = 0 AND created < (%d - %d - %d))) AND status <> 0 AND uid <> 1', time(), $warn_time, $block_time, time(), $warn_time, $block_time);
+//      $result = db_query('SELECT * FROM {users} WHERE ((access <> 0 AND login <> 0 AND access < (%d - %d - %d)) OR (login = 0 AND created < (%d - %d - %d))) AND status <> 0 AND uid <> 1', time(), $warn_time, $block_time, time(), $warn_time, $block_time);
+      $result = db_query('SELECT * FROM {users} WHERE ((access <> 0 AND login <> 0 AND access < (%d - %d)) OR (login = 0 AND created < (%d - %d))) AND status <> 0 AND uid <> 1', time(), $warn_time, time(), $warn_time);
       while ($user = db_fetch_object($result)) {
-        if ($user->uid && !db_fetch_object(db_query('SELECT uid FROM {inactive_users} WHERE uid = %d AND warned_user_block_timestamp > 0', $user->uid)) && ($user->created < (time() - $warn_time - $block_time))) {
+        if ($user->uid && !db_fetch_object(db_query('SELECT uid FROM {inactive_users} WHERE uid = %d AND warned_user_block_timestamp > 0', $user->uid)) && ($user->created < (time() - $warn_time))) {
           db_query('UPDATE {inactive_users} SET warned_user_block_timestamp = %d WHERE uid = %d', time() + $warn_time, $user->uid);
           if (!db_affected_rows()) {
             @db_query('INSERT INTO {inactive_users} (uid, warned_user_block_timestamp) VALUES (%d, %d)', $user->uid, time() + $warn_time);
@@ -342,9 +343,9 @@
     // warn users when they are about to be deleted
     if (($warn_time = variable_get('inactive_user_auto_delete_warn', 0)) &&
         ($delete_time = variable_get('inactive_user_auto_delete', 0))) {
-      $result = db_query('SELECT * FROM {users} WHERE ((access <> 0 AND login <> 0 AND access < (%d - %d - %d)) OR (login = 0 AND created < (%d - %d - %d))) AND uid <> 1', time(), $warn_time, $delete_time, time(), $warn_time, $delete_time);
+      $result = db_query('SELECT * FROM {users} WHERE ((access <> 0 AND login <> 0 AND access < (%d - %d)) OR (login = 0 AND created < (%d - %d))) AND uid <> 1', time(), $warn_time, time(), $warn_time);
       while ($user = db_fetch_object($result)) {
-        if ($user->uid && !db_fetch_object(db_query('SELECT uid FROM {inactive_users} WHERE uid = %d AND warned_user_delete_timestamp > 0', $user->uid)) && ($user->created < (time() - $warn_time - $delete_time))) {
+        if ($user->uid && !db_fetch_object(db_query('SELECT uid FROM {inactive_users} WHERE uid = %d AND warned_user_delete_timestamp > 0', $user->uid)) && ($user->created < (time() - $warn_time))) {
           if (variable_get('inactive_user_preserve_content', 1) && _inactive_user_with_content($user->uid)) {
             $protected = 1;
           }
@@ -407,6 +408,7 @@
  */
 function _format_interval($timestamp, $granularity = 2) {
   $units = array('1 year|@count years' => 31536000, '1 month|@count months' => 2592000, '1 week|@count weeks' => 604800, '1 day|@count days' => 86400, '1 hour|@count hours' => 3600, '1 min|@count min' => 60, '1 sec|@count sec' => 1);
+  $output = '';
   foreach ($units as $key => $value) {
     $key = explode('|', $key);
     if ($timestamp >= $value) {
@@ -460,7 +462,7 @@
       '%siteurl' => $base_url
     );
   }
-  if ($to) {
+  if (isset($to)) {
     $from = variable_get('site_mail', ini_get('sendmail_from'));
     $headers = array(
       'Reply-to' => $from,
@@ -476,7 +478,7 @@
         'headers' => $headers
       );
       $user = user_load(array('mail' => $recipient));
-      $language = user_preferred_language($account);
+      $language = isset($user->uid) ? user_preferred_language($user) :  language_default();
       drupal_mail('inactive_user', 'inactive_user_notice', $recipient, $language, $params, $from, TRUE);
     }
   }
diff -u -r1.1 inactive_user.test
--- inactive_user.test	20 Jun 2009 05:37:56 -0000	1.1
+++ inactive_user.test	17 Dec 2009 02:57:32 -0000
@@ -6,7 +6,18 @@
  * Test the basic functions of the Inactive User module.
  */
 
+/**
+ * Inactive user module testcase.
+ */
 class InactiveUserTest extends DrupalWebTestCase {
+
+  /**
+   * User with administration privileges for inactive user module.
+   *
+   * @var stdlcass
+   */
+  protected $admin;
+
   public static function getInfo() {
     return array(
       'name' => t('Inactive User'),
@@ -17,5 +28,446 @@
 
   function setUp() {
     parent::setUp('inactive_user');
+
+    // Create an admin user to configure inactive user module.
+    $this->admin = $this->drupalCreateUser(array('change inactive user settings'));
+    $this->drupalLogin($this->admin);
+  }
+
+  /**
+   * Check inactive user and administrator notifications are working
+   */
+  function testInactiveUserNotification() {
+
+    // Change user and admin notify options:
+    // Notify user about one weeks of inactivity.
+    // Notify admin about two week of inactivity
+    $settings = array(
+      'inactive_user_admin_email'  => 'test@email.com',
+      'inactive_user_notify'       => '604800',
+      'inactive_user_notify_admin' => '1209600',
+    );
+    $this->inactiveUserSettings($settings);
+
+    // Create an inactive user for more than a week.
+    $inactive = $this->drupalCreateInactiveUser( (604800 + 3600) );
+
+    // Perform inactive validations
+    $this->checkInactiveAccounts();
+
+    // One email should have been sent to the inactive user.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      1,
+      t('Only one email has been sent for this inactivity validation.')
+    );
+
+    // Get the last email, and verify it was sent to user's email address
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $inactive->mail,
+      t('User has been notified of its inactiviy period.')
+    );
+
+    // Create an inactive user for more than two weeks
+    $inactive = $this->drupalCreateInactiveUser( (1209600 + 3600) );
+
+    // Perform inactive validations
+    $this->checkInactiveAccounts();
+
+    // Two emails should have been sent: one for the user, other for the admin.
+    // Note that the other inactive user has already been notified, and should
+    // not generate any more emails.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      3,
+      t('Two new emails have been sent for this inactivity validation.')
+    );
+
+    // Get the last email, and verify it was sent to user's email address
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $inactive->mail,
+      t('User has been notified of its inactiviy period.')
+    );
+
+    // Get the other email, and verify it was sent to admin's email address
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $settings['inactive_user_admin_email'],
+      t('Administrator has been notified of inactive users.')
+    );
+    
   }
+
+  /**
+   * Check inactive user blocking and notifications are working
+   */
+  function testInactiveUserBlocking() {
+
+    // Change user and admin blocking options:
+    // Notify user about being blocked after one week of inactivity.
+    // Block user after two weeks of inactivity.
+    // Notify both about blocking: user and admin
+    $settings = array(
+      'inactive_user_admin_email'  => 'test@email.com',
+      'inactive_user_auto_block_warn' => '604800',
+      'inactive_user_auto_block' => '1209600',
+      'inactive_user_notify_block' => '1',
+      'inactive_user_notify_block_admin' => '1',
+    );
+    $this->inactiveUserSettings($settings);
+
+    // Create an inactive user for more than a week.
+    $inactive = $this->drupalCreateInactiveUser( (604800 + 3600) );
+
+    // Perform inactive validations
+    $this->checkInactiveAccounts();
+
+    // One email should have been sent to the inactive user about being blocked.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      1,
+      t('Only one email has been sent for this inactivity validation.')
+    );
+
+    // Get the last email, and verify it was sent to user's email address
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $inactive->mail,
+      t('User has been notified that its accout will be blocked.')
+    );
+
+    // Create an inactive user for more than two weeks
+    $inactive = $this->drupalCreateInactiveUser( (1209600 + 3600) );
+
+    // Perform inactive validations
+    $this->checkInactiveAccounts();
+
+    // One more email should have been sent, notifying the user its account will
+    // be blocked, but blocking operation will not happen because the user was
+    // notified at the time of 'notify'. The notification period should last for
+    // a whole week before the account is blocked.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      2,
+      t('One new email have been sent for this inactivity validation.')
+    );
+
+    // Get the last email, and verify it was sent to user's email address
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $inactive->mail,
+      t('User has been notified that its accout will be blocked.')
+    );
+
+    // Inactive_user keeps the time of blocking notification in a separate table
+    // as the timestamp of the operation, need to be moved back in time. We are
+    // modifying the notification period so on next validation the account will
+    // be blocked.
+    db_query("UPDATE {inactive_users} SET warned_user_block_timestamp = %d WHERE uid = %d", (604800 + 3600), $inactive->uid);
+
+    // Perform inactive validations again
+    $this->checkInactiveAccounts();
+
+    // Now, two more emails have been sent.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      4,
+      t('Two new emails have been sent for this inactivity validation.')
+    );
+
+    // Get the other email, and verify it was sent to admin's email address
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $settings['inactive_user_admin_email'],
+      t('Administrator has been notified of blocked accounts.')
+    );
+
+    // Admin has been notified that its account has been blocked.
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $inactive->mail,
+      t('User has been notified of its blocked account.')
+    );
+
+    // Verify the user has been blocked. user_load does not work with blocked
+    // accounts.
+    $status = db_result(db_query('SELECT status FROM {users} WHERE uid = %d', $inactive->uid));
+    $this->assertEqual(
+      $status,
+      0,
+      t('Inactive user %name has been blocked.', array('%name' => $inactive->name))
+    );
+
+  }
+
+  /**
+   * Check inactive user deleting and notifications are working
+   */
+  function testInactiveUserDeleting() {
+
+    // Change user and admin deleting options:
+    // Notify user about being deleted after one week of inactivity.
+    // Delete user after two weeks of inactivity.
+    // Notify both about deleting: user and admin
+    // Do not delete users with content.
+    $settings = array(
+      'inactive_user_admin_email'  => 'test@email.com',
+      'inactive_user_auto_delete_warn' => '604800',
+      'inactive_user_auto_delete' => '1209600',
+      'inactive_user_notify_delete' => '1',
+      'inactive_user_notify_delete_admin' => '1',
+      'inactive_user_preserve_content' => '1',
+    );
+    $this->inactiveUserSettings($settings);
+
+    // Create an inactive user for more than a week.
+    $inactive = $this->drupalCreateInactiveUser( (604800 + 3600) );
+
+    // Perform inactive validations
+    $this->checkInactiveAccounts();
+
+    // One email should have been sent to the inactive user about being deleted.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      1,
+      t('Only one email has been sent for this inactivity validation.')
+    );
+
+    // Get the last email, and verify it was sent to user's email address
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $inactive->mail,
+      t('User has been notified that its accout will be deleted.')
+    );
+
+    // Create an inactive user for more than two weeks
+    $inactive = $this->drupalCreateInactiveUser( (1209600 + 3600) );
+
+    // Perform inactive validations
+    $this->checkInactiveAccounts();
+
+    // One more email should have been sent, notifying the user its account will
+    // be deleted, but deleting operation will not happen because the user was
+    // notified at the time of 'notify'. The notification period should last for
+    // a whole week before the account is deleted.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      2,
+      t('One new email have been sent for this inactivity validation.')
+    );
+
+    // Get the last email, and verify it was sent to user's email address
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $inactive->mail,
+      t('User has been notified that its accout will be deleted.')
+    );
+
+    // Inactive_user keeps the time of deleting notification in a separate table
+    // as the timestamp of the operation, need to be moved back in time. We are
+    // modifying the notification period so on next validation the account will
+    // be deleted.
+    db_query("UPDATE {inactive_users} SET warned_user_delete_timestamp = %d WHERE uid = %d", (604800 + 3600), $inactive->uid);
+
+    // Perform inactive validations again
+    $this->checkInactiveAccounts();
+
+    // Now, two more emails have been sent.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      4,
+      t('Two new emails have been sent for this inactivity validation.')
+    );
+
+    // Get the other email, and verify it was sent to admin's email address
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $settings['inactive_user_admin_email'],
+      t('Administrator has been notified of deleted accounts.')
+    );
+
+    // Admin has been notified that its account has been blocked.
+    $notification = array_pop($emails);
+    $this->assertEqual(
+      $notification['to'],
+      $inactive->mail,
+      t('User has been notified of its deleted account.')
+    );
+
+    // Verify the user has been deleted.
+    $status = db_result(db_query('SELECT uid FROM {users} WHERE uid = %d', $inactive->uid));
+    $this->assertEqual(
+      $status,
+      NULL,
+      t('Inactive user %name has been deleted.', array('%name' => $inactive->name))
+    );
+
+  }
+
+  /**
+   * Check inactive user (with content) deleting and notifications are working
+   */
+  function testInactiveUserWithContentDeleting() {
+
+    // Change user and admin deleting options:
+    // Notify user about being deleted after one week of inactivity.
+    // Delete user after two weeks of inactivity.
+    // Notify both about deleting: user and admin
+    // Do not delete users with content.
+    $settings = array(
+      'inactive_user_admin_email'  => 'test@email.com',
+      'inactive_user_auto_delete_warn' => '604800',
+      'inactive_user_auto_delete' => '1209600',
+      'inactive_user_notify_delete' => '1',
+      'inactive_user_notify_delete_admin' => '1',
+      'inactive_user_preserve_content' => '1',
+    );
+    $this->inactiveUserSettings($settings);
+
+    // Create an inactive user for more than a week.
+    $inactive = $this->drupalCreateInactiveUser( (604800 + 3600) );
+
+    // Create a node for this user.
+    $this->drupalCreateNode(array('uid' => $inactive->uid));
+
+    // Perform inactive validations
+    $this->checkInactiveAccounts();
+
+    // One email should have been sent to the inactive user about being deleted.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      0,
+      t('Users with content should not be advised about deleting their account.')
+    );
+
+    // Create an inactive user for more than two weeks
+    $inactive = $this->drupalCreateInactiveUser( (1209600 + 3600) );
+
+    // Create a node for this user.
+    $this->drupalCreateNode(array('uid' => $inactive->uid));
+
+    // Perform inactive validations
+    $this->checkInactiveAccounts();
+
+    // One more email should have been sent, notifying the user its account will
+    // be deleted, but deleting operation will not happen because the user was
+    // notified at the time of 'notify'. The notification period should last for
+    // a whole week before the account is deleted.
+    $emails = $this->drupalGetMails();
+    $this->assertEqual(
+      count($emails),
+      0,
+      t('Users with content should not be advised about deleting their account.')
+    );
+
+    // Inactive_user keeps the time of deleting notification in a separate table
+    // as the timestamp of the operation, need to be moved back in time. We are
+    // modifying the notification period so on next validation the account will
+    // be deleted.
+    db_query("UPDATE {inactive_users} SET warned_user_delete_timestamp = %d WHERE uid = %d", (604800 + 3600), $inactive->uid);
+
+    // Verify the user is protected.
+    $protected = db_result(db_query('SELECT protected FROM {inactive_users} WHERE uid = %d', $inactive->uid));
+    $this->assertEqual(
+      $protected,
+      1,
+      t('Inactive user %name is protected becuase it owns content..', array('%name' => $inactive->name))
+    );
+
+    // Perform inactive validations again
+    $this->checkInactiveAccounts();
+
+    // Now, two more emails have been sent.
+    $emails = $this->drupalGetMails();
+    $this->pass(count($emails));
+    $this->assertEqual(
+      count($emails),
+      0,
+      t('Inactive users with content are protected and are not deleted, neither generates notifications.')
+    );
+
+    // Verify the user has not been deleted.
+    $status = db_result(db_query('SELECT uid FROM {users} WHERE uid = %d', $inactive->uid));
+    $this->assertEqual(
+      $status,
+      $inactive->uid,
+      t('Inactive user %name owning content has not been deleted.', array('%name' => $inactive->name))
+    );
+
+  }
+
+
+  /**
+   * Perform inactivity validation
+   */
+  function checkInactiveAccounts() {
+    // Make sure inactive user will be checked.
+    variable_set('inactive_user_timestamp', '0');
+    // run inactive user cron hook
+    inactive_user_cron();     
+  }
+
+  /**
+   * Configure Inactive user module
+   */
+  function inactiveUserSettings($options = array()) {
+    $this->drupalPost('admin/user/inactive-user', $options, t('Save configuration'));
+    $this->assertRaw(t('The configuration options have been saved.'), t('Inactive user settings saved.'));
+    foreach ($options as $option => $value) {
+      $this->assertEqual(
+        $value,
+        variable_get($option, ''),
+        t('Inactive user setting %option successfully saved.', array('%option' => $option))
+      );
+    }
+  }
+
+  /**
+   * Creates a drupal user and sets as inactive for a value of seconds.
+   *
+   * @param integer $seconds
+   *   number of seconds the user has been inactive.
+   * @return stdclass
+   *   Created user object.
+   */
+  function drupalCreateInactiveUser($seconds = 0) {
+    // Create a default user
+    $account = $this->drupalCreateUser();
+
+    // Mark as inactive..
+    $timestamp = time() - $seconds;
+    db_query('UPDATE {users} SET login = %d, created = %d, access = %d WHERE uid = %d', $timestamp, $timestamp, $timestamp, $account->uid);
+
+    // Verify inactivity.
+    $access = db_result(db_query("SELECT access FROM {users} WHERE uid = %d", $account->uid));
+    $this->assertEqual(
+      $timestamp,
+      $access,
+      t('User successfully updated as inactive since %date.', array('%date' => format_date($timestamp)))
+    );
+    
+    return $account;
+  }
+
 }

