1

I'd like to make a Drupal 7 view which displays nodes using the following behavior:

1) Show the body summary if it is populated. 2) Never show a trimmed version of anything. 3) If the body summary is empty, show the actual body. 4) If the body summary is not empty, display a "read more" link. 5) If the full body was displayed, don't display a "read more" link.

I've got this entirely working using a separate field for the summary (which may be what I end up with) but I'd hoped to use the body summary instead. As far as I can tell the only way to access the body summary in a view is to use the "summary or trimmed" formatter in the field display, which violates #2.

I looked for modules, and all I found was "Smart Trim" which appears to do the opposite of what I want.

Suggestions?

1
  • I'm considering writing a simple module with a field formatter to address this. I'd appreciate answers that consider whether that's a good way to approach this.
    – davidcl
    Commented May 7, 2014 at 20:43

6 Answers 6

4
+50

I think this is a good example for using custom formatters.

I Recommend you to use the custom formatters module as you cant get a fast result, but if you think this is useful, you should check the Field Formatter API to make more complex sollutions.

Install the module, and import this example:

$formatter = new stdClass();
$formatter->disabled = FALSE; /* Edit this to true to make a default formatter disabled initially */
$formatter->api_version = 2;
$formatter->name = 'test_body';
$formatter->label = 'test body';
$formatter->description = '';
$formatter->mode = 'php';
$formatter->field_types = 'text_with_summary';
$formatter->code = '$output = "";
foreach ($variables[\'#items\'] as $item) {
  if ( $item[\'summary\']) {
    $output = $item[\'summary\'];
  }else{
     $output = $item[\'value\'];
  }
}
return $output;';
$formatter->fapi = '';

it doesn't do all the job, but i think it can be enough for you to complete it.

Then go to your view and select the formatter for the body field.

2

What about using Rules... create a hidden field that would be used in the view, and use rules to automatically copy the contents of the summary to the new field when the content is created. Not sure if Rules can do that with a summary, but might be worth looking into.

8
  • Interesting idea. It does look like Rules lets you explicitly access the data in a summary field (node:body:summary). I don't think this solution is ideal because it involves moving data from place to place whereas philosophically I feel like the view should be able to access the summary data directly. It also looks like I'd need two Rules per summary field (one for create content, one for update content)... but all that said, this might solve my problem in a pinch.
    – davidcl
    Commented May 10, 2014 at 19:35
  • It complies with all of your requirements, but it does essentially create duplicate content. The problem is that you are trying to create an if, else statement using text length as a value in an SQL statement, and I don't believe you can, but I could be wrong.
    – Geoff
    Commented May 10, 2014 at 19:51
  • Sure you can. SELECT CASE WHEN foo IS NULL THEN bar ELSE foo END is exactly that. The bigger problem for me is that I don't understand how views map to SQL well enough...
    – davidcl
    Commented May 10, 2014 at 19:53
  • (Agreed that it complies with all of my requirements. It's just kind of inelegant. If nothing else pans out I'll certainly go with it).
    – davidcl
    Commented May 10, 2014 at 19:54
  • 1
    Views, Settings, near the bottom - Show the SQL query
    – Geoff
    Commented May 10, 2014 at 20:04
2

Following is the behaviour of the Body field in a view when the formatter is set to "Summary or Trimmed"

1) Display Summary if it is present 2) If Summary is not present, display trimmed version of body.

In your case since you do not need trimming for even the body, you can set the trim length to a very high value.

To implement the "Read More" link you can create a template file for body field in the view and implement the required logic. Here is the format of the template name that needs to be created views-view-field------body.tpl.php. The exact name of the template name can be found in the view configuration.

Advanced -> Theme: Information

1
  • 1
    Another interesting set of ideas. For some reason I thought I couldn't set the trim length high enough to cover all of my cases, but it appears I was wrong about that. This may end up being the easiest answer.
    – davidcl
    Commented May 10, 2014 at 19:57
2

You can use hook_views_query_alter() for that. Create a small module for it.

Some examples are listed here: https://api.drupal.org/api/views/views.api.php/function/hook_views_query_alter/7

You can alter the query to use field_body.body_summary table instead of field_body.body_value. If that has a value it will be returned. This will make your field empty (returns NULL) if there is no explicit summary for that node. Then you can use the textfield in no results behaviour to display the full body.

This can also be done with a views php field by the way, by running db_query() from that one on that field_body.body_summary tablerow.

It should be something like this if you use php field. You need a hidden nid field then and replace your body-field with this php-field.

<?php
$result = db_query('SELECT f.body_value, f.body_summary FROM {field_data_body} f WHERE f.entity_id = :nid', array(':nid' => $row->nid));

foreach ($result as $record) {
  if ($record->body_summary) {
    return $record->body_summary;
  }
  else {
    return $record->body_value;
  }
}
?>
2
  • Hm, I think I understand what you're suggesting, but I'm missing a few pieces of crucial knowledge required to implement such an override. Sample code, maybe? Why would this be preferred over a module that implements a simple field formatter? (I'm using the Smart Trim module as a model here; although it doesn't do what I want it seems like I could use it as a model to create a module that does).
    – davidcl
    Commented May 10, 2014 at 19:43
  • I think the views_query_alter solution is the 'drupal-way' of doing it. but that is a steeper learning curve than adding some php inside a views-php field.
    – Marcel
    Commented May 10, 2014 at 22:06
1

To create a summary only formatter within a view, make a custom module, add this code:

/**
 * Implements hook_field_formatter_info().
 */
function YOURMODULE_field_formatter_info() {
  return array(
    'summary_only' => array(
      'label' => t('Summary Only'),
      'field types' => array('text_with_summary'),
    ),
  );
}

/**
 * Implements hook_field_formatter_view().
 */
function YOURMODULE_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();

  // Go through each item and return only the summary value.
  foreach ($items as $delta => &$item) {
    switch ($display['type']) {
      case 'summary_only':
        $element[$delta] = array('#markup' => $item['summary']);
        break;
    }
  }

  return $element;
}

Then in your view, select the Summary Only formatter on your Text w/ Summary field = success.

1
  • You can use this logic to do all 4 items you asked in the original question as well
    – John O
    Commented Jun 29, 2016 at 20:24
0

The easiest way is to add the field, select "Rewrite results" and add the token [body-summary]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.