Meta tag description from teaser does not work together with excerpt module

Helmut Debes - November 5, 2009 - 05:32
Project:Nodewords
Version:6.x-1.x-dev
Component:Third-party modules integration
Category:bug report
Priority:normal
Assigned:Unassigned
Status:closed
Description

Option "Use the node teaser if the description meta tag is not set" does not work in context with the excerpt module. The teaser specified via the excerpt module http://drupal.org/project/excerpt is ignored and instead the top of the body is used instead.

It seems to behave as if no teaser has been specified using the standard Drupal 6.x method (not using the excerpt module) when NOT clicking on "split summary at cursor".

#1

kiamlaluno - November 5, 2009 - 13:23

Nodewords uses as teaser what Drupal code reports to be the teaser. I don't know what the other module does, but it could be it doesn't call the correct Drupal functions to alter the node teaser.

#2

kiamlaluno - November 5, 2009 - 13:40

Pardon... Nodewords uses code taken from node_teaser() to get the node teaser.

<?php
function node_teaser($body, $format = NULL, $size = NULL) {

  if (!isset(
$size)) {
   
$size = variable_get('teaser_length', 600);
  }

 
// Find where the delimiter is in the body
 
$delimiter = strpos($body, '<!--break-->');

 
// If the size is zero, and there is no delimiter, the entire body is the teaser.
 
if ($size == 0 && $delimiter === FALSE) {
    return
$body;
  }

 
// If a valid delimiter has been specified, use it to chop off the teaser.
 
if ($delimiter !== FALSE) {
    return
substr($body, 0, $delimiter);
  }

 
// We check for the presence of the PHP evaluator filter in the current
  // format. If the body contains PHP code, we do not split it up to prevent
  // parse errors.
 
if (isset($format)) {
   
$filters = filter_list_format($format);
    if (isset(
$filters['php/0']) && strpos($body, '<?') !== FALSE) {
      return
$body;
    }
  }

 
// If we have a short body, the entire body is the teaser.
 
if (drupal_strlen($body) <= $size) {
    return
$body;
  }

 
// If the delimiter has not been specified, try to split at paragraph or
  // sentence boundaries.

  // The teaser may not be longer than maximum length specified. Initial slice.
 
$teaser = truncate_utf8($body, $size);

 
// Store the actual length of the UTF8 string -- which might not be the same
  // as $size.
 
$max_rpos = strlen($teaser);

 
// How much to cut off the end of the teaser so that it doesn't end in the
  // middle of a paragraph, sentence, or word.
  // Initialize it to maximum in order to find the minimum.
 
$min_rpos = $max_rpos;

 
// Store the reverse of the teaser.  We use strpos on the reversed needle and
  // haystack for speed and convenience.
 
$reversed = strrev($teaser);

 
// Build an array of arrays of break points grouped by preference.
 
$break_points = array();

 
// A paragraph near the end of sliced teaser is most preferable.
 
$break_points[] = array('</p>' => 0);

 
// If no complete paragraph then treat line breaks as paragraphs.
 
$line_breaks = array('<br />' => 6, '<br>' => 4);
 
// Newline only indicates a line break if line break converter
  // filter is present.
 
if (isset($filters['filter/1'])) {
   
$line_breaks["\n"] = 1;
  }
 
$break_points[] = $line_breaks;

 
// If the first paragraph is too long, split at the end of a sentence.
 
$break_points[] = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);

 
// Iterate over the groups of break points until a break point is found.
 
foreach ($break_points as $points) {
   
// Look for each break point, starting at the end of the teaser.
   
foreach ($points as $point => $offset) {
     
// The teaser is already reversed, but the break point isn't.
     
$rpos = strpos($reversed, strrev($point));
      if (
$rpos !== FALSE) {
       
$min_rpos = min($rpos + $offset, $min_rpos);
      }
    }

   
// If a break point was found in this group, slice and return the teaser.
   
if ($min_rpos !== $max_rpos) {
     
// Don't slice with length 0.  Length must be <0 to slice from RHS.
     
return ($min_rpos === 0) ? $teaser : substr($teaser, 0, 0 - $min_rpos);
    }
  }

 
// If a break point was not found, still return a teaser.
 
return $teaser;
}
?>

<?php
function nodewords_metatag_from_teaser($body, $format, $alt_attribute, $size = 0) {
  if (!
$size) {
   
$size = variable_get('nodewords_max_size', 350);
  }

 
// We check for the presence of the PHP evaluator filter in the current
  // format. If the body contains PHP code, we do not split it up to prevent
  // parse errors.
 
if (isset($format)) {
   
$filters = filter_list_format($format);
    if (isset(
$filters['php/0']) && strpos($body, '<?') !== FALSE) {
      return
'';
    }
  }

 
// If a valid delimiter has been specified, use it to chop off the teaser.
 
if (($delimiter = strpos($body, '<!--break-->')) !== FALSE) {
   
$body = substr($body, 0, $delimiter);
  }

 
// Initialize the helper function used for preg_replace_callback.
 
_nodewords_teaser_match_callback($alt_attribute, TRUE);

 
// Replace the meta tag img with the attribute alt, and strip off all the
  // HTML tags.
 
$body = strip_tags(
   
preg_replace_callback('/<img\s[^>]*alt=["\']([^"\']*)["\'][^>]*>/i',
     
'_nodewords_teaser_match_callback',
     
$body
   
)
  );

 
// Truncate the string at last space within the given size.
 
return truncate_utf8($body, $size, TRUE);
}
?>

#3

kiamlaluno - November 5, 2009 - 14:38

I think that the module could simply use the value of $node->teaser, and verify if doesn't contain any PHP code, as it already does.
In this way, it should be compatible with any modules that change the teaser.

#4

kiamlaluno - November 5, 2009 - 18:26
Version:6.x-1.3-beta5» 6.x-1.x-dev
Status:active» fixed

The code has been changed, and committed in CVS.

Thanks for your report.

#5

Helmut Debes - November 6, 2009 - 03:38

I have successfully tested the 6.x-1.x-dev (from November 6). Now it is working together with the excerpt module. Thanks for having fixed this!

#6

kiamlaluno - November 6, 2009 - 10:53

The fix was easy.
Why should have the module created the teaser when it was already present in $node->teaser? I changed the existing code, but I have never thought that the object node contains a property that contain the node teaser; it contains the teaser, whatever it's created from Drupal core, of from a third-party module.

Thanks again for your report; not using a third-party to create the teaser, I would not have noticed the problem.

#7

System Message - November 20, 2009 - 11:00
Status:fixed» closed

Automatically closed -- issue fixed for 2 weeks with no activity.

 
 

Drupal is a registered trademark of Dries Buytaert.