Skip to main content

Drupal Book Permissions: Only Let Users Add Content to their Own Books

Today's project required me to fine tune Drupal's standard book module. Basically, I needed to limit the choices in the 'Book Outline' area to only display books that the user was the author of. Unfortunately, Drupal's default permissions don't allow for this. Either the user can administer all outlines or none, nothing in between.

Form Alter to the Rescue

So I created a custom module with a hook_form_alter() function and started inspecting the $form variable. The book outline form options are keyed with the node id, which I can use to check the author. If the user is the author, we keep the options in the list, otherwise we unset them.

The Full Code

  1. function CUSTOMMODULE_form_alter(&$form, &$form_state, $form_id){
  2.   switch($form_id){
  3.     case 'course_node_form':
  4.     case 'course_materials_node_form':
  5.       // If the user doesn't have adminster content permission, limit the book list to their own nodes.      
  6.       if(!user_access('administer content')) {
  7.         _HELPER_limit_book_list($form, TRUE);
  8.       }
  9.     break;
  11.   }
  12. }
  14. function _HELPER_limit_book_list(&$form, $remove_new = FALSE) {
  15.   global $user;
  16.   $author_nids = array();
  17.   // Get an array of node id's from the options.
  18.   $book_nids = array_keys($form['book']['bid']['#options']);
  19.   // Query the database and get the authors nodes.
  20.   // Wanted to avoid the overhead of node_load. Especially since this list could grow decently large.
  21.   db_query("SELECT nid, uid FROM {node} WHERE nid in (:nids)", array(':nids' => $book_nids));
  22.   $results = db_query("SELECT nid, uid FROM {node} WHERE nid in (:nids) and uid = :uid", array(':nids' => $book_nids, ':uid' => $user->uid));
  23.   foreach($results as $row) {
  24.     $author_nids[$row->nid] = $row->nid;
  25.   }
  27.   foreach($form['book']['bid']['#options'] as $key => $value) {
  28.     // If the $key (the nid in this case) is not in the $author_nid array, unset it from the options list.
  29.     if (!$remove_new && $key == 'new') {
  30.       continue;
  31.     }
  32.     // If the logged in user is not the author, remove the option from view.
  33.     if (!isset($author_nids[$key])) {
  34.       unset($form['book']['bid']['#options'][$key]);
  35.     }
  36.   }
  37. }