Index: pm_block_user/pm_block_user.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/pm_block_user/pm_block_user.module,v
retrieving revision 1.3
diff -u -p -r1.3 pm_block_user.module
--- pm_block_user/pm_block_user.module	2 Dec 2009 20:04:00 -0000	1.3
+++ pm_block_user/pm_block_user.module	12 Feb 2010 12:24:53 -0000
@@ -41,6 +41,17 @@ function pm_block_user_menu() {
     'weight'           => -10,
   );
 
+  $items['messages/blocked'] = array(
+    'title'            => 'Blocked users',
+    'page callback'    => 'drupal_get_form',
+    'page arguments'    => array('pm_block_user_list'),
+    'file'             => 'pm_block_user.pages.inc',
+    'access callback'  => 'privatemsg_user_access',
+    'access arguments' => array('read privatemsg'),
+    'type'             => MENU_LOCAL_TASK,
+    'weight'           => 10,
+  );
+
   $items['admin/settings/messages/block'] = array(
     'title'            => 'User blocking rules',
     'description'      => 'Configure rules for which users may block each other.',
@@ -67,8 +78,9 @@ function pm_block_user_menu() {
  */
 function pm_block_user_theme() {
   return array(
-    'pm_block_user_actions' => array(
+    'pm_block_user_list' => array(
       'arguments' => array('form' => NULL),
+      'file'      => 'pm_block_user.pages.inc',
     ),
   );
 }
Index: pm_block_user/pm_block_user.pages.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/pm_block_user/pm_block_user.pages.inc,v
retrieving revision 1.1
diff -u -p -r1.1 pm_block_user.pages.inc
--- pm_block_user/pm_block_user.pages.inc	2 Dec 2009 20:04:00 -0000	1.1
+++ pm_block_user/pm_block_user.pages.inc	12 Feb 2010 12:24:53 -0000
@@ -55,7 +55,7 @@ function pm_block_user_form($form_state,
 }
 
 /**
- * Implements hook_form_submit().
+ * Submit callback for block user confirmation form.
  */
 function pm_block_user_form_submit($form, &$form_state) {
   if ($form_state['values']['confirm']) {
@@ -71,4 +71,71 @@ function pm_block_user_form_submit($form
     }
   }
   $form_state['redirect'] = $form_state['values']['destination'];
+}
+
+/**
+ * Formbuilder function to build a simple form to block users.
+ */
+function pm_block_user_list() {
+  global $user;
+
+  $form['new'] = array(
+    '#type'   => 'fieldset',
+    '#title'  => t('Block a user'),
+  );
+  $form['new']['name'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Username'),
+    '#autocomplete_path' => 'messages/user-name-autocomplete',
+    '#description'        => t('Separate multiple names with commas.'),
+  );
+  $form['new']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Block user'),
+    '#submit' => array('pm_block_user_block_submit'),
+  );
+
+  $header = array(
+    array(
+      'data' => t('Username'),
+      'field' => 'u.name',
+      'sort'  => 'asc',
+      ),
+    array(
+      'data' => t('Operations'),
+      ),
+  );
+
+  $result = pager_query('SELECT * FROM {pm_block_user} pmb INNER JOIN {users} u ON (u.uid = pmb.author) WHERE pmb.recipient = %d ' . tablesort_sql($header), 20, 0, NULL, $user->uid);
+  $rows = array();
+  while ($row = db_fetch_object($result)) {
+    $rows[] = array(
+      theme('username', user_load($row->author)),
+      l(t('unblock'), 'messages/block/' . $row->author, array('query' => drupal_get_destination())),
+    );
+  }
+  $form['#header'] = $header;
+  $form['#rows'] = $rows;
+  return $form;
+}
+
+/**
+ * Submit callback for block user form.
+ */
+function pm_block_user_block_submit($form, &$form_state) {
+  global $user;
+  list($accounts, $invalid) = _privatemsg_parse_userstring($form_state['values']['name']);
+  if (!empty($accounts)) {
+    foreach ($accounts as $account) {
+      db_query('INSERT INTO {pm_block_user} (author, recipient) VALUES (%d, %d)', $account->uid, $user->uid);
+      drupal_set_message(t('!author has been blocked from sending you any further messages.', array('!author' => theme('username', $account))));
+    }
+  }
+}
+
+/**
+ * Theme function to theme the blocked user listing.
+ */
+function theme_pm_block_user_list($form) {
+  return drupal_render($form) . theme('table', $form['#header'], $form['#rows']) . theme('pager');
 }
\ No newline at end of file
Index: pm_block_user/pm_block_user.test
===================================================================
RCS file: pm_block_user/pm_block_user.test
diff -N pm_block_user/pm_block_user.test
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ pm_block_user/pm_block_user.test	12 Feb 2010 12:24:53 -0000
@@ -0,0 +1,132 @@
+<?php
+// $Id$
+/**
+ * @file
+ * Test file for pm_block_user.module
+ */
+
+class PrivatemsgBlockUserCase extends DrupalWebTestCase {
+  /**
+   * Implements getInfo().
+   */
+  function getInfo() {
+    return array
+    (
+      'name' => t('User blocking functionality.'),
+      'description' => t('Test blocking and unblocking of users'),
+      'group' => t('Privatemsg'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('privatemsg', 'pm_block_user');
+  }
+
+  function testBlockAndUnblock() {
+    // Create needed users.
+    $user1 = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg'));
+    $user2 = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg'));
+    $user3 = $this->drupalCreateUser(array('write privatemsg', 'read privatemsg'));
+
+    // Set up a simple conversation.
+    $return = privatemsg_new_thread(array($user2, $user3), $subject = $this->randomString(20), $this->randomString(50), array('author' => $user1));
+    privatemsg_reply($return['message']['thread_id'], $this->randomString(50), array('author' => $user2));
+    privatemsg_reply($return['message']['thread_id'], $this->randomString(50), array('author' => $user3));
+
+    $this->drupalLogin($user1);
+    $this->drupalGet('messages');
+    $this->clickLink($subject);
+
+    // Block user2.
+    $this->clickLink(t('Block author'));
+    $this->drupalPost(NULL, array(), t('Block @user', array('@user' => $user2->name)));
+    $this->assertText(t('@user has been blocked from sending you any further messages.', array('@user' => $user2->name)), t('Confirmation message displayed'));
+
+    // Block user3.
+    $this->clickLink(t('Block author'));
+    $this->drupalPost(NULL, array(), t('Block @user', array('@user' => $user3->name)));
+    $this->assertText(t('@user has been blocked from sending you any further messages.', array('@user' => $user3->name)), t('Confirmation message displayed'));
+
+    // Visit blocked users list.
+    $this->drupalGet('messages/blocked');
+
+    $this->assertText($user2->name, t('User 2 displayed as blocked'));
+    $this->assertText($user3->name, t('User 3 displayed as blocked'));
+
+    // Unblock user2.
+
+    // Blocked users are sorted alphabetically, check which one is the first
+    // one in the list and set index based on that.
+    $rows = $this->xpath('//tbody/tr');
+    $index = (int) !($user2->name == (string)$rows[0]->td[0]);
+    $this->clickLink(t('unblock'), $index);
+    $this->drupalPost(NULL, array(), t('Unblock @user', array('@user' => $user2->name)));
+    $this->assertText(t('@user is now allowed to send you new messages.', array('@user' => $user2->name)), t('Confirmation message displayed'));
+
+    $this->assertText($user3->name, t('User 3 still displayed as blocked'));
+
+    // Unblock user3.
+    $this->clickLink(t('unblock'));
+    $this->drupalPost(NULL, array(), t('Unblock @user', array('@user' => $user3->name)));
+    $this->assertText(t('@user is now allowed to send you new messages.', array('@user' => $user3->name)), t('Confirmation message displayed'));
+
+    $this->drupalGet('messages/blocked');
+    $this->assertNoText($user2->name, t('User 2 not displayed as blocked anymore'));
+    $this->assertNoText($user3->name, t('User 3 not displayed as blocked anymore'));
+
+    // Block users again.
+    $edit = array('name' => $user2->name . ', ' . $user3->name);
+    $this->drupalPost(NULL, $edit, t('Block user'));
+    $this->assertText(t('@user has been blocked from sending you any further messages.', array('@user' => $user2->name)), t('Confirmation message displayed'));
+    $this->assertText(t('@user has been blocked from sending you any further messages.', array('@user' => $user3->name)), t('Confirmation message displayed'));
+
+    $this->drupalGet('messages');
+    $this->clickLink($subject);
+
+    $this->assertNoText(t('Block user'), t('No "Block user" links displayed.'));
+
+    // Log in as user2 and try to send messages to user1.
+    $this->drupalLogin($user2);
+
+    $edit = array(
+      'recipient' => $user1->name,
+      'subject' => $subject2 = $this->randomName(20),
+      'body'    => $this->randomName(50),
+    );
+    $this->drupalPost('messages/new', $edit, t('Send message'));
+    $this->assertRaw(t('%user has chosen to not recieve any more messages from you.', array('%user' => $user1->name)), t('User 1 blocks user 2 message displayed'));
+    $this->assertText(t('Disallowed to send message because all recipients are blocked'), t('Disallowed to send message displayed'));
+
+    $edit = array(
+      'recipient' => $user1->name . ', ' . $user3->name,
+      'subject' => $subject3 = $this->randomName(20),
+      'body'    => $this->randomName(50),
+    );
+    $this->drupalPost('messages/new', $edit, t('Send message'));
+    $this->assertRaw(t('%user has chosen to not recieve any more messages from you.', array('%user' => $user1->name)), t('User 1 blocks user 2 message displayed'));
+    $this->assertText(t('A message has been sent to @user.', array('@user' => $user3->name)), t('Message sent to user 3'));
+  
+    
+    // Try to reply to an existing thread.
+    $this->drupalGet('messages');
+    $this->clickLink($subject);
+
+    $this->assertText(t('Recipients: @user', array('@user' => $user3->name)), t('User1 is not displayed as recipient'));
+    $edit = array('body' => $reply = $this->randomName(50));
+    $this->drupalPost(NULL, $edit, t('Send message'));
+    $this->assertRaw(t('%user has chosen to not recieve any more messages from you.', array('%user' => $user1->name)), t('User 1 blocks user 2 message displayed'));
+    $this->assertText(t('A message has been sent to @user.', array('@user' => $user3->name)), t('Message sent to user 3'));
+  
+    // Login as user1 again and check that we didn't recieve the messages.
+    $this->drupalLogin($user1);
+    $this->drupalGet('messages');
+
+    // Check that we didn't get the new messages.
+    $this->assertNoLink($subject2);
+    $this->assertNoLink($subject3);
+
+    // Check that we don't see the new messages.
+    $this->clickLink($subject);
+    $this->assertNoText($reply);
+  }
+}
\ No newline at end of file
