Community Documentation

Block visible for specific nodes/terms and their children

Last updated April 4, 2008. Created by add1sun on April 7, 2007.
Log in to edit this page.

I really wanted to create multiple image galleries and for each gallery have a different menu. It was also necessary to display this menu for all child galleries and images. I didn't particularly feel like adding each node to the pages box on the configure menu block screen, as the number of images and galleries would be growing all the time. I decided that I needed block inheritance, so I created my own includes file to contain functions to do this for me. It's a bit messy and may not suit everyone's taxonomy structure, but it meets my needs.

Steps
1. Set up your menu / block.

2. Set the "page specific visibility settings" to be "Show if the following PHP code returns TRUE" on the block configuration screen.

3. In the "Pages" field, put something similar to the following:

<?php
include_once "./includes/inherit_blocks.inc";

if (
check_path("node/1")) return TRUE;

return
inherit_display_block(123);
?>

The first line just includes the file containing the functions. The check_path() function is for those nodes that you just want to hardcode the paths for, while the last line calls the function which handles the inheritance for tid 123.

4. Create the inherit_blocks.inc file and add the following:

<?php
function inherit_display_block($tid = 0) {
 
$is_child = FALSE;
  if (
$tid != 0) {
   
$this_page = drupal_get_path_alias($_GET['q']);
   
$url_parts = split("/", $this_page);
   
$num_parts = count($url_parts);

    if (
$url_parts[$num_parts-2] == "tid") {
     
$this_tid = $url_parts[$num_parts-1];
      if (
$this_tid == $tid) return TRUE;
     
$is_child = get_child_tids($tid, $this_tid);
    } elseif (
$url_parts[$num_parts-2] == "node") {
     
$this_node = $url_parts[$num_parts-1];
     
$is_child = check_child_node($tid, $this_node);
    }
  }


  return
$is_child;
}

function
get_child_tids($parent, $tid) {
 
$child = false;
 
$result = db_query("select tid from term_hierarchy where parent=$parent");
  while (
$child_tid = db_fetch_object($result)) {
    if (
$tid == $child_tid->tid) return true;
   
$child = get_child_tids($child_tid->tid, $tid);
    if (
$child) return true;
  }
  return
false;
}


function
check_child_node($parent, $node) {
 
$child = false;
 
$result = db_query("select tid from term_node where nid=$node");
  while (
$node_tid = db_fetch_object($result)) {
   
$tid = $node_tid->tid;
   
$result2 = db_query("select tid from term_hierarchy where parent=$parent");
    while (
$child_tid = db_fetch_object($result2)) {
      if (
$tid == $child_tid->tid) return true;
     
$child = get_child_tids($child_tid->tid, $tid);
      if (!
$child) return true;
    }
  }
  return
false;
}

function
check_path($path) {

 
$this_path = drupal_get_path_alias($_GET['q']);

 
$regexp = '/^'. preg_replace(
    array(
'/(\r\n?|\n)/', '/\\\\\*/''/(^|\|)\\\\<front\\\\>($|\|)/'),
    array(
'|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'),
       
'/') .'\2'), preg_quote("$path", '/')) .'$/';

  return
preg_match($regexp, $this_path);
}

?>

Comments

PHP HELP block on single node?????

Hey all,

I am completely useless when it comes to PHP and new to Drupal, and have spent hours trawling the forum for something like this. I basically need a simple PHP script to show a block on a node when using the "Show if the following PHP code returns TRUE" option on a block. the URL is /Pictures and the node is number 9. Someone please give me hand with this, there must be a simple way?

Sam

www.solarfly.com - Under construction and still learning Drupal

Sam, just put node/9 in the

Sam, just put node/9 in the "display only on these pages" box.

Meanwhile, for those who want to display a block only on pages which are tagged with a particular taxonomy term, here is a script you can use in D5 and an update for D6:

http://drupal.org/node/507540

You need to look up the term IDs for the terms you want to filter on, and enter them in the first line of this script (inside the "myterms" array). I go to the taxonomy admin, list terms from the vocabulary I want to use, and then roll my mouse over the edit link for the term I want. That shows the term and vocabulary IDs in the status line of the browser.

Hi! Can anyone help me in

Hi! Can anyone help me in making this code appear also on children of multiple terms?

<?php
 
// This snippet returns TRUE if the node we are
  // currently viewing is tagged with all the desired  terms
  // and we are not in edit mode (arg(2)).

  // put here the terms you are interested in the array
  // they must all be found for TRUE to be returned

 
$desired_terms = 11, 1, 6, 7, 5, 4, 2;
 
$found = 0;

  if (
arg(0) == 'node' and is_numeric(arg(1)) and arg(2) == FALSE ) {
   
// Yes, we're viewing a node in view mode.

   
$node = node_load(arg(1)); // cached
    // If the term does not exist we're done
   
if (is_array($node->taxonomy)) {
      foreach (
$node->taxonomy as $term) {
        if (
in_array($term->tid, $desired_terms) ) {
         
$found++;
        }
      }
      if (
$found == count($desired_terms) ) {
        return
FALSE;
      }
    }
  }
  return
TRUE;
?>

Any prompt help will be very much appreciated. Thanks

You can teach a student a lesson for a day; but if you can teach him to learn by creating curiosity, he will continue the learning process as long as he lives. ~Clay P. Bedford
www.magazinesnation.com | www.magazinesmags.com/blog

I have no answers, but this

I have no answers, but this line worries me :

        if ( in_array($term->tid, $desired_terms) ) {

PHP doesn't get nuance...

Try

$desired_terms = array(11, 1, 6, 7, 5, 4, 2);

//instead of
// $desired_terms = 11, 1, 6, 7, 5, 4, 2;

--
"I'm not concerned about all hell breaking loose, but that a PART of hell will break loose... it'll be much harder to detect." - George Carlin
--
Personal: http://www.nicklewis.org
Work: http://www.chapterthree.com

It seems that what your

It seems that what your snippet actually does is hide the block in case ALL the desired terms are found. Otherwise, the block is shown. If you want to show your block in case ONE OR MORE of the desired terms is found, then something like this is probably more what you want:

<?php
    $desired_terms
= array(11, 1, 6, 7, 5, 4, 2);
   
$found = 0;
    if (
arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == FALSE ) {
     
// Yes, we're viewing a node in view mode.
     
$node = node_load(arg(1)); // cached
      // If the term does not exist we're done
     
if (is_array($node->taxonomy)) {
        foreach (
$node->taxonomy as $term) {
          if (
in_array($term->tid, $desired_terms) ) {
            return
TRUE;
          }
//if
       
} //foreach term
     
} //if
   
} //if node
   
return FALSE;
?>

A Million Thanks!

wow, this definitely answered my problem. Yes, you're right. This is much simpler and easy to understand. Thanks a ton...

@Nick Lewis. Thank you as well for your input. Really really appreciated them.

God Bless You both and the Drupal Community. Now, I can take a nap. =)

You can teach a student a lesson for a day; but if you can teach him to learn by creating curiosity, he will continue the learning process as long as he lives. ~Clay P. Bedford
www.magazinesnation.com | www.magazinesmags.com/blog

problem with multiple vocabularies?

Thanks @cmjns for this snippet. I tried it out and found that I couldn't get it to work as is, perhaps because I have multiple vocabularies on my nodes.

Instead, I modified the core foreach thusly:

foreach ($node->taxonomy as $key => $val) {
if ( in_array($key, $desired_terms) ) {
return TRUE;

Thanks again!

Christian Nally - B.C., Canada - http://sticksallison.com

xx

xx my mistake, I apologize.

Please delete

Reference

Drupal’s online documentation is © 2000-2012 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.
nobody click here