January 12, 2012

Fix the "Read more" link in Drupal 7

Drupal 7 has limitations that can be fairly funny, the "Read more" link always appears in the "Teaser" although the "Teaser" content is already the entire contents of the article, this problem does not exist in Drupal 6.

To fix this I simply use the template.php and make the function as follows:
function template_preprocess_node(&$variables) {

  $node = $variables['node'];
 
  // Check first the "body field" exists or not.
  $field = field_get_items('node', $node, 'body');

  // If available do execution ..  
  if($field){
    $body = $node->body['und'][0]['safe_value'];
    if ($variables['content']['body'][0]['#markup'] == $body){
      unset($variables['content']['links']['node']['#links']
      ['node-readmore']);
    }
  }

  // And if not available ..
  else{
    // Do nothing ..
  }

}
Note:
  1. Replace the word template on template_preprocess_node with the name of your theme.
  2. On unset ($ variables ['content'] ['link'] ['nodes']['# links'] ['node-readmore']); is one line. I press enter because of limited space in my blog.
At least this solution can be used for a while and waiting for the problem is fixed in Drupal 7.

9 comments:

  1. greatly appreciated, i shall know better now
    how about previously drupal version? is it the same?

    ReplyDelete
    Replies
    1. This problem does not exist in Drupal 6.

      Delete
  2. nice tips, thanks for sharing mas danang..

    ReplyDelete
  3. Works like a charm; thanks for the handy fix!

    ReplyDelete
  4. I am making a two language site on D 7.12. I had to make some changes to adapt your solution (Though, they are far from perfect):

    $node = $vars['node'];

    // Check first the "body field" exists or not.
    $field = field_get_items('node', $node, 'body');

    // If available do execution ..
    if($field){
    if(array_key_exists('uk', $node->body))
    {
    $body = $node->body['uk'][0]['safe_value'];
    $body = substr($body, 0, strpos($body, ""));
    if ($vars['content']['body'][0]['#markup'] == $body){
    unset($vars['content']['links']['node']['#links']['node-readmore']);
    }
    }
    if(array_key_exists('en', $node->body))
    {
    $body = $node->body['en'][0]['safe_value'];
    $body = substr($body, 0, strpos($body, ""));
    if ($vars['content']['body'][0]['#markup'] == $body){
    unset($vars['content']['links']['node']['#links']['node-readmore']);
    }
    }
    }
    // And if not available ..
    else{
    // Do nothing ..
    }

    You have an awesome solution! :-) Thanks! It should go to core some day. Post it to drupal.org! Lots of people are in need for this.

    ReplyDelete
    Replies
    1. Thanks, yes please post to Drupal.org. I see.. the language key :)

      Delete
    2. This is my final version :

      In the cases you want the teaser to show the full content (when is at the very end of the article), you may want the "Read more" link not to show up for this material.
      If it is a simple text node and there are no more additional fields (a simple text node) - this is how we can do it:

      In your theme template.php :
      function <your-template-name>_preprocess_node(&$variables) {
      ... // In some themes it can be '$variables' in the others - '$vars'.
      $node = $vars['node'];

      // Check first the "body field" exists or not.
      $field = field_get_items('node', $node, 'body');

      // If available do execution ..
      if($field) {
      $show_read_more = 1;
      if(array_key_exists($GLOBALS['language_content']->language, $node->body))
      {
      $body = $node->body[$GLOBALS['language_content']->language][0]['safe_value'];
      if(stristr($body, "<!--break-->")) // Lets make sure that this is indeed the end of article.
      {
      $rest_of_the_text = substr($body, strpos($body, "<!--break-->"));
      if(strlen($rest_of_the_text)<strlen("<!--break--></p><p>&nbsp;</p>"))
      $show_read_more = 0;
      }
      else if ($vars['content']['body'][0]['#markup'] == $body)
      $show_read_more = 0;
      }
      if($show_read_more == 0)
      unset($vars['content']['links']['node']['#links']['node-readmore']);
      }
      ...
      }

      Have a good day!

      Delete

Read the FAQ for commenting guidelines. Thanks for taking the time to respond.