Custom queries

If you are doing a custom query yourself, there's only 1 important thing you need to do: put the build_mode key on the object you pass to the theming function. In this example we're using a node object.

  $output = '';

  $result = db_query("SELECT nid FROM {node} WHERE whatever");
  while ($row = db_fetch_object($result)) {

    // Load the node - You can also built the object yourself if you know which fields you need.
    $node = node_load($row->nid);

   // Put a build_mode key on the $node object
    $node->build_mode = 'teaser'; 

    // Check the teaser flag and show_links flag.
    $teaser = ($node->build_mode != 'full') ? TRUE : FALSE;
    $show_links = ds_show_field('nd', $node->type, $node->build_mode, 'links');

    // Use node_view to render.
    $output .= node_view($node, $teaser, FALSE, $links);
  }
  return $output;

Node displays fields

Because we can't include every single field out there by default, here are some PHP snippets you can use to create a custom field at admin/ds/module/fields or include in your own implementation of hook_ds_fields(). A lot of the snippets, especially those from Node displays, are single prints which are usually found in the $links variable, which is available by default as a field.

If you are using functions defined in modules, it's advised to wrap the code around the module_exists function. Take a look how we return the terms field when taxonomy is enabled in nd.module for inspiration.

Note: replace $object with $entity in the Drupal 7 version

Print the comment count

print $object->comment_count;

Print the node view stats

$statistics = statistics_get($object->nid);
if ($statistics) {
  print format_plural($statistics['totalcount'], '1 read', '@count reads');
}

or

echo $object->links['statistics_counter']['title'];

Flags

Read http://drupal.org/node/295383 and replace $node (or $user) by $object in the flag_create_link() function.

Webform

  return $object->content['webform']['#value'];

Organic Groups integration

OG description

  return $object->og_description;

OG mission

  return $object->body;

OG group post

  return l('Add something', 'node/add/nodetype', array('query' => array('gids[]' => $object->nid)));

OG User groups (for UD)

  return $object->content['summary']['groups']['#value'];

OG groups list
For this you'll need to create a preprocess field and use 'og_links' as the key and 'view' as the variable key.

Image

  return $object->content['image']['#value'];

Print

print $object->content['print_links']['#value'];

Note that on the settings page of print you need to select 'Content corner' at Printer-friendly page link.
You'll also have to reset the the css a bit, since it will be aligned right, but other than that, the link will show up (whether it's an icon or link)

Node displays: hide the title

When looking at a full node, the page template will also print the $title variable. It's possible however to display the title also with ND and you might wish to put this inside the available regions. Following snippet is an implementation of hook_preprocess_page which you can use in either template.php or in one of your own custom modules to hide title in page.tpl.

function template_preprocess_page(&$variables) {
  if ($node = menu_get_object()) {
    // Some extra checks: nid, type and arg(2) also being empty.
    if ($node->nid && $node->type == 'my_content_type' && arg(2) == '') {
      $variables['title'] = '';
    }
  }
}

Limit multiple field

When using views, you can choose if you want to limit the number of values of a field, eg from an image field. This is not possible by default and also pretty hard to implement since we'd have to override all theming functions defined by cck. We are not going
todo that for now. There is an easy way though to add new formatters. Code underneath adds a new formatter for an imagefield which uses a custom function in a module called 'imagecache_for_nd_contrib'.


/**
 * @file
 * Custom functions for this site.
 */

/**
* Implementation of CCK's hook_field_formatter_info().
*/
function imagecache_for_nd_contrib_field_formatter_info() {
  $formatters = array(
    'image_single' => array(
      'label' => t('Image single'),
      'field types' => array('filefield'),
      'description' => t('Displays image files single in a format.'),
    ),
  );
  return $formatters;
}

/**
 * Implementation of hook_theme().
 */
function imagecache_for_nd_contrib_theme() {
  return array(
    'imagecache_for_nd_contrib_formatter_image_single' => array(
      'arguments' => array('element' => NULL),
    ),
  );
}

/**
 * Only show the first image with a specific image cache.
 */
function theme_imagecache_for_nd_contrib_formatter_image_single($element) {
  static $images = array();

  $nid = $element['#node']->nid;

  // Stop after the first one.
  if (isset($images[$nid])) {
    return;
  }

  $images[$nid] = TRUE;

  if (empty($element['#item']['fid'])) {
    return '';
  }

  $item = $element['#item'];

  $alt = isset($item['data']['alt']) ? $item['data']['alt'] : '';
  $title = isset($item['data']['title']) ? $item['data']['title'] : NULL;

  return theme('imagecache', 'uc_category', $item['filepath'], $alt, $title);
}

Override block field through code

By default, when you create a block field, Display suite will call theme_ds_eval_block and will execute the block with module_invoke($module, 'block', 'view', $delta); There are situations where you'd like to pass an argument to a block.

Use case:

  • You have a list of product categories - which is a content type rendered through a page view
  • You need to list a random set of products from that category: in our case we created a block view called random products which has a fixed node reference argument.
  • This block is available as a field in the display of product category, however, it will always display the same products because of the fixed node reference argument. We now need a way to change this value.

Solution: implement hook_ds_fields_alter().

/**
 * Implementation of hook_ds_fields_alter().
 */
function module_ds_fields_alter(&$fields) {
  if (isset($fields['random_products'])) {

    // We change the type of the field to function instead of blocK
    $fields['random_products']['type'] = DS_FIELD_TYPE_FUNCTION;
    $fields['random_products']['properties']['formatters']['render_view_block_arguments'] = t('Default');

    // Add some extra properties which we can use in the function later on.
    $fields['random_products']['properties']['arguments'] = array(
      'field_product_category_reference_nid' => array(
        'key' => 'default_argument_fixed', 'field_object_value' => 'nid'
      )
    );
  }
}

Now create the render_view_block function.

/**
 * Render a ds field which was originally a block through this function.
 */
function render_view_block_arguments($field) {
  $data = '';
  list($module, $delta) = explode('|', $field['properties']['block']);
  list($name, $display_id) = explode('-', $delta);
  // Load the view.
  if ($view = views_get_view($name)) {
    if ($view->access($display_id)) {
      if (isset($field['properties']['arguments'])) {
        foreach ($field['properties']['arguments'] as $argument => $value) {
         $view->display[$display_id]->handler->options['arguments'][$argument][$value['key']] = $field['object']->{$value['field_object_value']};
        }
      }
      $output = $view->execute_display($display_id);
      if (!empty($output['content'])) {
        $data = theme('block', (object) $output);
      }
    }
    $view->destroy();
  }
  return $data;
}

This could also be a filter, or a sort or whatever property you'd like to change.

Note in case you don't get any output when altering a block view, take a look at http://drupal.org/node/854112 your view block string might be md5'd

Show all authors / contributors of a node

$query = db_select('node_revision', 'r');
$node_id = arg(1);
$query->fields('u', array('name'));
$query->distinct();
$query->condition('r.nid', $node_id, '=');
$query->leftJoin('users', 'u', 'r.uid = u.uid');
$query->leftJoin('node', 'n', 'r.uid = n.uid');
$query->range(0, 50);
$result = $query->execute();
//foreach ($result as $record) { print_r($record); }
$numResults = $result->rowCount();
$counter = 0;
print "By ";
foreach ($result as $record) {
	print "<a href='/users/".$record->name."'>".$record->name."</a>";
	if($counter < $numResults-1) print ", ";
	$counter++;
}
print " lastly on ".format_date($entity->changed,'short').".";

Hide Display Suite shipped templates

If you are sure you won't be using any of the Display Suite templates and will be defining only custom templates. Then the following snippet will keep your layouts select list clean:

/**
 * Hide all the default DS layouts.
 * @param unknown $layouts
 */
function ds_layouts_ds_layout_info_alter(&$layouts) {
    $ds_path = drupal_get_path('module', 'ds');
    $ds_patern = '#' . $ds_path . '#Uis';
    
    foreach ($layouts as $key => $layout) {
        if (preg_match($ds_patern, $layout['path'])) {
            unset($layouts[$key]);
        }
    }
}

Comments

spacereactor’s picture

for watcher module http://drupal.org/project/watcher, you can add print $object->content[watcher]['#value']; to get the link to display. Hope this help someone.

spoit’s picture

When writing the formatter for limiting a multiple field, showing the same formatter twice for a node (eg. on multiple views on the same page) won't work with the code provided, since once the static $images is set, the image won't be displayed twide.

/**
 * Only show the first image with a specific image cache.
 */
function theme_imagecache_for_nd_contrib_formatter_image_single($element) {

  if (empty($element['#item']['fid']) || $element['#item']['#delta'] != 0) {
    return '';
  }

  $item = $element['#item'];

  $alt = isset($item['data']['alt']) ? $item['data']['alt'] : '';
  $title = isset($item['data']['title']) ? $item['data']['title'] : NULL;

  return theme('imagecache', 'uc_category', $item['filepath'], $alt, $title);
}
recidive’s picture

I just contributed a module for limiting images and other multiple values display in Drupal 7. I think it might be useful posting it here:

http://drupal.org/project/field_multiple_limit

Henrique Recidive

swentel’s picture

Display suite for Drupal 7 has this built in now also, see http://realize.be/limit-number-fields-display-field-ui-display-suite

broncomania’s picture

Has someone a solution for getting the apache solr score value into the display suite search as a field or block?