? .cvsignore
? fix_form.patch
? fix_update_query.patch
? privatemsg_permissions.patch
? privatemsg_permissions2.patch
? privatemsg_recipient_types13.patch
Index: privatemsg.pages.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.pages.inc,v
retrieving revision 1.14
diff -u -p -r1.14 privatemsg.pages.inc
--- privatemsg.pages.inc	16 Aug 2010 08:12:25 -0000	1.14
+++ privatemsg.pages.inc	7 Sep 2010 14:56:51 -0000
@@ -393,7 +393,7 @@ function privatemsg_new_validate($form, 
   }
   $form_state['validate_built_message'] = $message;
   if (!empty($invalid)) {
-    drupal_set_message(t('The following users will not receive this private message: @invalid', array('@invalid' => implode(", ", $invalid))), 'error');
+    drupal_set_message(t('The following recipients will not receive this private message: @invalid.', array('@invalid' => implode(", ", $invalid))), 'error');
   }
 }
 
Index: privatemsg.test
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg.test,v
retrieving revision 1.22
diff -u -p -r1.22 privatemsg.test
--- privatemsg.test	17 Aug 2010 13:05:41 -0000	1.22
+++ privatemsg.test	7 Sep 2010 14:56:51 -0000
@@ -277,7 +277,7 @@ class PrivatemsgTestCase extends DrupalW
 
     $this->drupalPost('messages/new', $editinvalid, t('Send message'));
     $this->assertText(t('You must include at least one valid recipient.'), 'Message was not sent.');
-    $this->assertText(t('The following users will not receive this private message: @recipients', array('@recipients' => $editinvalid['recipient'])), 'Message about non-existing user displayed.');
+    $this->assertText(t('The following recipients will not receive this private message: @recipients.', array('@recipients' => $editinvalid['recipient'])), 'Message about non-existing user displayed.');
 
     $this->drupalPost('messages/new', $editnobody, t('Send message'));
     $this->assertText(t('A message has been sent to @recipients.', array('@recipients' => $recipient->name)), 'Message sent confirmation displayed.');
@@ -290,7 +290,7 @@ class PrivatemsgTestCase extends DrupalW
 
     $this->drupalPost('messages/new', $editmixed, t('Send message'));
     $this->assertText(t('A message has been sent to @recipients.', array('@recipients' => $recipient->name)), 'Message sent confirmation displayed.');
-    $this->assertText(t('The following users will not receive this private message: @recipients', array('@recipients' => $invalidmixed)), 'Message about non-existing user displayed.');
+    $this->assertText(t('The following recipients will not receive this private message: @recipients.', array('@recipients' => $invalidmixed)), 'Message about non-existing user displayed.');
 
     $this->drupalPost('messages/new', $editformatted, t('Send message'));
     $this->assertText(t('A message has been sent to @recipients.', array('@recipients' => $recipient2->name)), 'Message sent confirmation displayed.');
Index: privatemsg_roles/privatemsg_roles.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg_roles/privatemsg_roles.module,v
retrieving revision 1.3
diff -u -p -r1.3 privatemsg_roles.module
--- privatemsg_roles/privatemsg_roles.module	12 Jul 2010 19:45:49 -0000	1.3
+++ privatemsg_roles/privatemsg_roles.module	7 Sep 2010 14:56:51 -0000
@@ -10,9 +10,11 @@
  * Implements hook_perm().
  */
 function privatemsg_roles_perm() {
-  return array(
-    'write privatemsg to roles', 'view roles recipients',
-  );
+  $perms = array('view roles recipients', 'write privatemsg to all roles');
+  foreach (user_roles(TRUE) as $role) {
+    $perms[] = 'write privatemsg to role ' . $role;
+  }
+  return $perms;
 }
 
 function privatemsg_roles_theme() {
@@ -36,13 +38,40 @@ function privatemsg_roles_privatemsg_rec
       'autocomplete' => 'privatemsg_roles_autocomplete',
       'generate recipients' => 'privatemsg_roles_load_recipients',
       'count' => 'privatemsg_roles_count_recipients',
-      'write access' => 'write privatemsg to roles',
+      'write callback' => 'privatemsg_roles_write_access',
       'view access' => 'view roles recipients',
     ),
   );
 }
 
 /**
+ * Write permission check for roles recipients.
+ */
+function privatemsg_roles_write_access($recipient) {
+
+  // Check if user has permission to write to all roles.
+  if (user_access('write privatemsg to all roles')) {
+    return TRUE;
+  }
+
+  if ($recipient) {
+    if (empty($recipient->name)) {
+      $recipient = reset(privatemsg_roles_load_multiple(array($recipient->recipient)));
+    }
+    // Check permission for this recipient.
+    return user_access('write privatemsg to role ' . $recipient->name);
+  }
+  // Check if user has permission to write at least one role.
+  foreach (user_roles(TRUE) as $role) {
+    if (user_access('write privatemsg to role ' . $role)) {
+      return TRUE;
+    }
+  }
+  // No permission, return FALSE.
+  return FALSE;
+}
+
+/**
  * Load a number of roles based on their rid.
  */
 function privatemsg_roles_load_multiple($rids) {
@@ -107,7 +136,9 @@ function privatemsg_roles_autocomplete($
   // 3: Build proper suggestions and print.
   $matches = array();
   while ($role = db_fetch_object($result)) {
-    $matches[] = $role->name . ' ' . t('[role]');
+    if (user_access('write privatemsg to all roles') || user_access('write privatemsg to role ' . $role->name)) {
+      $matches[] = $role->name . ' ' . t('[role]');
+    }
   }
   return $matches;
 }
Index: privatemsg_roles/privatemsg_roles.test
===================================================================
RCS file: /cvs/drupal/contributions/modules/privatemsg/privatemsg_roles/privatemsg_roles.test,v
retrieving revision 1.6
diff -u -p -r1.6 privatemsg_roles.test
--- privatemsg_roles/privatemsg_roles.test	17 Aug 2010 13:05:41 -0000	1.6
+++ privatemsg_roles/privatemsg_roles.test	7 Sep 2010 14:56:51 -0000
@@ -23,7 +23,7 @@ class PrivatemsgRolesTestCase extends Dr
   }
 
   function testSendMessagetoRoleAPI() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
     $user2 = $this->drupalCreateUser();
 
@@ -43,7 +43,6 @@ class PrivatemsgRolesTestCase extends Dr
   }
 
   function testSendMessagetoRoleCron() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
 
     variable_set('privatemsg_recipient_small_threshold', 20);
@@ -58,7 +57,13 @@ class PrivatemsgRolesTestCase extends Dr
       user_save($users[$i], $edit);
     }
 
-    $recipient = (object)array('recipient' => 4, 'type' => 'role', 'name' => $user1->roles[4]);
+    // Update permissions.
+    $this->checkPermissions(array(), TRUE);
+
+    // Create user with specific role permission.
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to role ' . $user1->roles[3]));
+
+    $recipient = (object)array('recipient' => 3, 'type' => 'role', 'name' => $user1->roles[3]);
     privatemsg_new_thread(array($recipient), $subject = $this->randomName(10), $body = $this->randomName(50), array('author' => $admin));
 
     // Run cron.
@@ -97,7 +102,7 @@ class PrivatemsgRolesTestCase extends Dr
    * Disabled as it produces exceptions on some testslaves.
    */
   function disabledSendMessagetoRoleBatch() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
 
     variable_set('privatemsg_recipient_small_threshold', 20);
@@ -133,12 +138,16 @@ class PrivatemsgRolesTestCase extends Dr
 
   function testPermission() {
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
-    $user2 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
-    $this->drupalLogin($user1);
+    // Update permissions.
+    $this->checkPermissions(array(), TRUE);
+    // Give permission to write only a specific role.
+    $user2 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to role ' . $user1->roles[3]));
+
+    $this->drupalLogin($user2);
 
     // Send a message to the role of user 1 and 2.
     $edit = array(
-      'recipient' => $user2->roles[4] . '[role]',
+      'recipient' => $user1->roles[DRUPAL_AUTHENTICATED_RID] . '[role]',
       'subject' => $this->randomName(10),
       'body' => $this->randomName(50),
     );
@@ -147,22 +156,26 @@ class PrivatemsgRolesTestCase extends Dr
   }
 
   function testSendMessageToRole() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
     $user2 = $this->drupalCreateUser(array('view roles recipients'));
 
     // Add role of user 1 to user 2;
     $edit = array('roles' => $user2->roles + $user1->roles);
     user_save($user2, $edit);
+
+    // Update permissions.
+    $this->checkPermissions(array(), TRUE);
+
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'view roles recipients', 'write privatemsg to role ' . $user1->roles[3]));
     $this->drupalLogin($admin);
 
     // Verify autocomplete feature.
-    $json = $this->drupalGet('messages/user-name-autocomplete/' . drupal_substr($user1->roles[4], 0, 2));
+    $json = $this->drupalGet('messages/user-name-autocomplete/' . drupal_substr($user1->roles[3], 0, 2));
     $autocomplete = (array)json_decode($json);
-    $this->assertEqual($autocomplete[$user1->roles[4] . ' [role], '], $user1->roles[4] . ' [role]');
+    $this->assertEqual($autocomplete[$user1->roles[3] . ' [role], '], $user1->roles[3] . ' [role]');
 
     // Access the form through a url that pre-fills the recipient field.
-    $this->drupalGet('messages/new/role_4');
+    $this->drupalGet('messages/new/role_3');
 
     // Send a message to the role of user 1 and 2.
     $edit = array(
@@ -170,7 +183,7 @@ class PrivatemsgRolesTestCase extends Dr
       'body' => $this->randomName(50),
     );
     $this->drupalPost(NULL, $edit, t('Send message'));
-    $this->assertText(t('A message has been sent to @role (role).', array('@role' => $user1->roles[4])));
+    $this->assertText(t('A message has been sent to @role (role).', array('@role' => $user1->roles[3])));
 
     // Log in as user1 and check that the message is listed, is marked as new
     // and can be marked as read.
@@ -182,7 +195,7 @@ class PrivatemsgRolesTestCase extends Dr
     $this->assertText($edit['body'], t('Thread starter body displayed.'));
 
     // Make sure that the user does not see the role.
-    $this->assertNoText(t('@role (role)', array('@role' => $user1->roles[4])));
+    $this->assertNoText(t('@role (role)', array('@role' => $user1->roles[3])));
 
     // Reply to the message, only admin should see this.
     $reply1 = array(
@@ -212,7 +225,7 @@ class PrivatemsgRolesTestCase extends Dr
     $this->drupalGet('messages');
     $this->assertRaw($edit['subject'] . '</a> <span class="marker">new</span>', t('Message is displayed as new'));
     $this->clickLink($edit['subject']);
-    $this->assertText(t('@role (role)', array('@role' => $user1->roles[4])));
+    $this->assertText(t('@role (role)', array('@role' => $user1->roles[3])));
 
     $this->assertText($edit['body'], t('Thread starter body is displayed'));
     $this->assertNoText($reply1['body'], t('Reply1 is not displayed'));
@@ -220,7 +233,7 @@ class PrivatemsgRolesTestCase extends Dr
   }
 
   function testSendMessageToRoleBlocked() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
     $user2 = $this->drupalCreateUser();
 
@@ -263,7 +276,7 @@ class PrivatemsgRolesTestCase extends Dr
   }
 
   function testNewUser() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user1 = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
 
     // Send a message to the role of user 1.
@@ -292,7 +305,7 @@ class PrivatemsgRolesTestCase extends Dr
    * Verify that deleting a user does not leave stale data behind.
    */
   function testDeleteUser() {
-    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to roles'));
+    $admin = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg', 'write privatemsg to all roles'));
     $user = $this->drupalCreateUser(array('read privatemsg', 'write privatemsg'));
 
     // Send a message to the role of user 1.
