To simplify our users' interaction we wanted users to only start a new private message using links embedded in a page. This meant hiding the 'Write new message' tab when reading messages. We also wanted to allow users with a custom permission 'write blank new message' to see and use the tab as normal.
This is not a 100% fool-proof method as it relies on the arguments provided by those links (and so urls could be crafted). This technique is good enough for us and may be enhanced as needed. Whilst actually writing a permitted message the 'Write new message' tab will still appear.

We need to deny access to SITE/messages/new if:

  • a user doesn't have the 'write blank new message' permission.
  • a user is looking at a privatemsg page that isn't the /new one.
  • a recipient uid and a subject are not provided as arguments to the /new page.

First off, we override the privatemsg_menu hook and add a few extra arguments to our new access callback function:

function MODULE_menu_alter(&$items) {
  $url_prefix = variable_get('privatemsg_url_prefix', 'messages');
  // Find how many arguments are in the prefix.
  $url_prefix_arg_count = substr_count($url_prefix, '/') + 1;

  $items[$url_prefix . '/new']['access callback'] = 'MODULE_write_new_privatemsg_access';
  $items[$url_prefix . '/new']['access arguments'] = array('write privatemsg', TRUE, $url_prefix_arg_count, $url_prefix_arg_count + 1, $url_prefix_arg_count + 2);
}

In our access callback function we first check if the user has our custom permission to allow to see the new message tab, if they don't then check that both a recipient uid and subject are present, if not return false.
We then pass the original access arguments on to the original access callback to allow normal checking of permissions.

function MODULE_write_new_privatemsg_access($permission = 'read privatemsg', $deny_if_other = FALSE, $message_arg_0, $message_arg_1, $message_arg_2) {
  if( !user_access('write blank new message')) {
    if( $message_arg_0 != 'new' ) return FALSE;  // hide the tab if it's not the new message page
    else if( !($message_arg_1 && $message_arg_2) ) return FALSE;  // no recipient uid and subject
  }

  $module_path = drupal_get_path('module', 'privatemsg');
  require_once($module_path . '/privatemsg.module');

  return privatemsg_menu_access($permission, $deny_if_other);
}

Comments

beumont’s picture

Do I have to plase this in a new module? Because this is not working for me at all.

cousin_itt’s picture

Yes, you will have to place it in your own module. There are many tutorials on how to write your own modules.
Replace the word 'MODULE' in the above code for your module name.

oskar_calvo’s picture

seems that there is a problem with

  return privatemsg_menu_access($permission, $deny_if_other);

the function doesn't exist.

Oskar

cousin_itt’s picture

That function does exist; it's in privatemsg.module about line 304.
Please note this is a tutorial for the 6.x branch of privatemsg.
The 7.x branch has different user access functions.

ptmkenny’s picture

It would be great to have a Drupal 7 version of this.

(EDIT: I posted some code but upon closer inspection it doesn't work as intended.)

jibize’s picture

<?php
/**
 * Implements hook_permission().
 */
function MYMODULE_permission() {
  return array(
    'write blank new message' => array(
      'title' => 'Write blank new Private Message',
    ),
  );
}

/**
 * Implements hook_menu_alter().
 */
function MYMODULE_menu_alter(&$items) {
  $url_prefix = variable_get('privatemsg_url_prefix', 'messages');
  // Find how many arguments are in the prefix.
  $url_prefix_arg_count = substr_count($url_prefix, '/') + 1;

  $items[$url_prefix . '/new']['access callback'] = 'MYMODULE_write_new_privatemsg_access';
  $items[$url_prefix . '/new']['access arguments'] = array('write privatemsg', NULL, $url_prefix_arg_count, $url_prefix_arg_count + 1);

}

function MYMODULE_write_new_privatemsg_access($permission = 'read privatemsg', $account = NULL, $message_arg_0, $message_arg_1) {
  if(!user_access('write blank new message')) {
    if($message_arg_0 != 'new' || !$message_arg_1){
      return FALSE;  // hide the tab if it's not the new message page or there is no recipient uid
    }
  }

  $module_path = drupal_get_path('module', 'privatemsg');
  require_once($module_path . '/privatemsg.module');

  return privatemsg_user_access($permission, $account);
}
?>
ptmkenny’s picture

This worked for me!

sksshed’s picture

I could be hoping but does this still work in the lates version of 7?, I have created a module and the permission appears but links to to create a new message with the User UID and subject in the link do not seem to work. I'm seeing access is denied. Any help appreciated.