background image
HomeRecent PostsDrupalSearchTagsRSSContactAboutAccount
Eric.London's picture

When creating your theme, you may need absolute control over your node fields, and creating a node specific template file (CONTENTTYPE.tpl.php) does not give you enough flexibility. This code snippet defines a preprocess_node hook to modify the $content variable, so the field html has already been modified before it reaches your theme.

<?php
function MYMODULE_preprocess_node(&$variables) {
 
// test for your node type that you'd like to modify
 
if ($variables['type']=='MYNODETYPE') {
   
// prepare your node object so the fields can be rendered individually
   
$newNode = node_build_content(node_load($variables['nid']));

   
// define a variable to hold your rendered content
   
$newContent = "";

   
// example: define a list of fields to show in an item list
   
$itemListFields = array('field_itemlist_1','field_itemlist_2','field_itemlist_3');
   
$itemListFieldsData = array();

   
// loop through the node content
   
foreach ($newNode->content as $k => $v) {
     
// example: to prevent a field from being shown,
      // simply render the field and don't capture the output
     
if ($k == 'MYFIELDTOHIDE') {
       
drupal_render($v);
      } elseif (
in_array($k, $itemListFields)) {
       
// example: group some fields in an item list
       
$itemListFieldsData[] = drupal_render($v);
      } elseif (
$k == 'MYOTHERFIELD') {
       
// example: surround a field in a div
       
$newContent .= "<div id='MYHTMLID'>" . drupal_render($v) . "</div>";
      } else {
       
// render the remaining fields and capture the output
       
$newContent .= drupal_render($v);
      }

    }

   
// example: generate the output for the item list
   
if (count($itemListFieldsData)) $newContent .= theme('item_list', $itemListFieldsData);

   
// replace the content variable
   
if (strlen($newContent)) $variables['content'] = $newContent;

  }

}
?>

Eric.London's picture

Sometimes the default theming layout of a CCK node cannot simply be adjusted using CSS. In this example, I'll explain how to modify the layout of a CCK node form and group some form elements into a table, item list, etc. NOTE: this code has to reside in you template.php file.

<?php
// first, modify the theme registry so Drupal knows you'd like to override the theming of your CCK node type
function MYTHEME_theme($existing, $type, $theme, $path) {
  return array(
   
'MYCCKTYPE_node_form' => array(
     
'arguments' => array(
       
'form' => NULL
     
)
    )
  );
}

// now, define the function that will modify the structure of the form object
function MYTHEME_MYCCKTYPE_node_form($form) {

 
// create a variable to store the form html
 
$html = "";

 
// loop through the $form object
 
$fields = array();
  foreach (
$form as $k => $v) {
   
// check if the current key is a field
   
if (substr($k, 0, 6)=='field_') {
     
// NOTE: you can use the drupal_render() function to generate the output on $v
      // in this example, I'll create the html for each field and store it in an array
     
$fields[$k] = drupal_render($v);

     
// NOTE: since we're executing drupal_render on $v, and not directly on $form,
      // we'll have to remove this field from $form so it will not be rendered twice
      // Normally, drupal will not render a form object if it has already been rendered
     
unset($form[$k]);

    }
  }

 
// Now the html has been stored in the associative array $fields variable in the format:
  // [field name] => [field html]
  // At this point you could use a theme function
  // (theme_table, theme_item_list, theme_fieldset, etc)
  // to generate the html for a common layout format,
  // or you could create your own html/css layout
  // For example, you could put the fields in an item list:
 
$html .= theme('item_list', array_values($fields));

 
// Lastly, you'll need to generate the html for the rest of the form fields
 
$html .= drupal_render($form);

  return
$html;
}
?>

Here's a screen shot of a CCK node form that I rebuilt in a table:

This problem comes up a lot in my Drupal module development: How do I generate the html for an individual CCK field? After much examination of the CCK, Views, and Node modules, I came up with this code snippet:

<?php
// load the node object
$node = node_load(MYNODEID);

// at this point the node object contains preprocessed data. build the content
$node = node_build_content($node);

// loop through content
foreach ($node->content as $k => $v) {
 
// specify a delimiter
 
$delimiter = "\n";

 
// ensure field items exist
 
if (is_array($v['field']['items'])) {
   
// create a container for the items html
   
$content = array();

   
// loop through items
   
foreach($v['field']['items'] as $i) {
     
// theme item
     
$content[] = theme($i['#theme'], $i);
    }

   
// roll up items html using delimiter
   
$content = implode($delimiter, $content);
  } else {
   
// NOTE: drupal_render includes divs, field labels, etc, which you may not want
   
$content = drupal_render($k);
  }

 
// NOTE: at this point, the data will be stored in $content, and you can now do whatever you want with it.
  // The date module gave me some headaches with this code snippet, BTW

}
?>

Syndicate content