If you wish to display a block only while showing a page from level 1 or 2 of a specific book (note in Drupal 6 this code does not work below that level), try the following:

  1. Go to the block you want to edit and click configure
  2. Go to the "Page specific visibility settings"
  3. Choose the option: "Show if the following PHP code returns TRUE"
  4. Paste in the code below
  5. Change the two values of 46 to the node ID of the book you're testing against

Then the block should only display if you're inside that particular book.

Drupal 5

if (arg(0) == "node" && is_numeric(arg(1))) {
  if (46 == arg(1)) {
    return TRUE;
  }
  $result = db_fetch_object(db_query("SELECT parent FROM {book} WHERE nid = %d", arg(1)));
  if (46 == $result->parent) {
    return TRUE;
  } else {
    return FALSE;
  }
} else {
  return FALSE;
}

Drupal 6

In Drupal 6 the column 'parent' is now BID (book ID).

if (arg(0) == "node" && is_numeric(arg(1))) {
  if (46 == arg(1)) {
    return TRUE;
  }
  $result = db_fetch_object(db_query("SELECT bid FROM {book} WHERE nid = %d", arg(1)));
  if (46 == $result->bid) {
    return TRUE;
  }
  else {
    return FALSE;
  }
} 
else {
  return FALSE;
}

'46' is the nid of your book and needs to be changed to the nid of the specific book you are attaching this block to.

These snippets are from help provided in this forum thread: http://drupal.org/node/125344. Thanks to all who helped!

Comments

biggena’s picture

I have modified this script to support more than 2 levels of book hierarchy.

Note, you need to replace 46 with your own book id (the most top level book node).

$book_id = 46;

if (arg(0) == "node" && is_numeric(arg(1))) {
  $current_nid = arg(1);
  if($book_id == $current_nid) {
    return TRUE;
  }
  // Get parent book (recursion)
  while(true) {
    $result = db_fetch_object(db_query("SELECT bid FROM {book} WHERE nid = %d", $current_nid));
    if( $result === FALSE ) {
      return FALSE;
    }
    else if ($book_id == $result->bid) {
      return TRUE;
    }
    else {
      $current_nid = $result->bid;
    }
  }
}
else {
  return FALSE;
}

This code works in Drupal 6.

david@thrale.com’s picture

This works when the book_id is the top level book node. Your work on this is really appreciated.

However, there are two issues for me, which make this code pretty unusable:
1. when I try to open nodes that are outside the book, they take a very long time (a minute or so). After I delete the block containing the code, the all nodes load at normal speed; and
2. when the book_id is not a top level node, all children nodes from the node id entered don't render at all. Whereas the D5 version of this PHP code did work if the id was not the top level. I'd love it if the D6 version could start at any level of the book, like D5 did.

Miri Meltzer’s picture

<?php
$book_id = 46;

if (arg(0) == "node" && is_numeric(arg(1))) {
  $current_nid = arg(1);
  if($book_id == $current_nid) {
    return TRUE;
  }
  // Get parent book (recursion)
  while(true) {
    $result = db_fetch_object(db_query("SELECT * FROM {book} WHERE nid = %d", $current_nid));
    if( $result === FALSE ) {
      return FALSE;
    }
    else if ($book_id == $result->bid) {
      return TRUE;
    }
    // Top parent of another book.
    else if ($result->bid === $result->nid) {
      return FALSE;
    }
    else {
      $current_nid = $result->bid;
    }
  }
}
else {
  return FALSE;
}
?>
stefan81’s picture

How can I show a block on any page containing to any book?
So, just check if the current page belongs to a book.