From 3f1196cd5d4513ce092ecbee2a1a1b94f6d0e5f3 Mon Sep 17 00:00:00 2001
From: Bob Vincent
tag, but if the original + // formatted version was plaintext, then the summary should be plaintext + // also. + if ($text === strip_tags($text)) { + $output = strip_tags($output); } - $break_points[] = $line_breaks; + return trim($output); +} - // 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 summary. - foreach ($points as $point => $offset) { - // The summary is already reversed, but the break point isn't. - $rpos = strpos($reversed, strrev($point)); - if ($rpos !== FALSE) { - $min_rpos = min($rpos + $offset, $min_rpos); - } +/** + * Helper function for text_summary. + * + * Recursively copies elements from $body to $summary, subtracting the length + * of the textContent portions from $size until $size reaches zero. + * + * @param $body + * The source DOMNode. + * @param $size + * The maximum number of textContent characters to copy. + * @param $summary + * The destination DOMNode. + * @param $doc + * The destination DOMDocument. Should be the same as the + * $summary->ownerDocument property. + * + * @return + * The number of additional characters left to copy. + */ +function _text_summarize($body, $size, $summary, $doc) { + if ($body->nodeType === XML_TEXT_NODE) { + $text_length = drupal_strlen($body->textContent); + if ($text_length <= $size) { + $size -= $text_length; + $summary->appendChild($doc->createTextNode($body->textContent)); + return $size; } - - // If a break point was found in this group, slice and stop searching. - if ($min_rpos !== $max_rpos) { - // Don't slice with length 0. Length must be <0 to slice from RHS. - $summary = ($min_rpos === 0) ? $summary : substr($summary, 0, 0 - $min_rpos); - break; + // Split by sentence. + $lines = preg_split( + '/(?<=[[:alnum:]][\.\?\!。])(?=[^[:alnum:]])/', + $body->textContent, + NULL, + PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE + ); + $text = ''; + foreach ($lines as $line) { + $line_length = drupal_strlen($line); + // Only add the sentence if it fits within the length limit. + if ($line_length > $size) { + break; + } + $text .= $line; + $size -= $line_length; } + // Set size to zero to avoid adding subsequent text nodes. + $size = 0; + $summary->appendChild($doc->createTextNode($text)); + return $size; } - - // If the htmlcorrector filter is present, apply it to the generated summary. - if (isset($filters['filter_htmlcorrector'])) { - $summary = _filter_htmlcorrector($summary); + if ($body->hasChildNodes()) { + $node = $summary->appendChild($doc->createElement($body->tagName)); + foreach ($body->childNodes as $child) { + if ($size > 0) { + $size = _text_summarize($child, $size, $node, $doc); + } + else { + break; + } + } } - - return $summary; + return $size; } /** diff --git a/modules/field/modules/text/text.test b/modules/field/modules/text/text.test index b42fed7e09894d352b3ecdd27431234e6ae77f72..8689d05745104664ecc4813aa34cb422f64ef8fc 100644 --- a/modules/field/modules/text/text.test +++ b/modules/field/modules/text/text.test @@ -258,7 +258,8 @@ class TextSummaryTestCase extends DrupalWebTestCase { */ function testFirstSentenceQuestion() { $text = 'A question? A sentence. Another sentence.'; - $expected = 'A question? A sentence.'; + // The default format includes the auto-paragraph filter. + $expected = '
A question? A sentence.
'; $this->callTextSummary($text, $expected, NULL, 30); } @@ -270,9 +271,9 @@ class TextSummaryTestCase extends DrupalWebTestCase { 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' . // 108 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' . // 103 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; // 110 - $expected = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' . + $expected = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ' . 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ' . - 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'; + 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
'; // First three sentences add up to: 336, so add one for space and then 3 to get half-way into next word. $this->callTextSummary($text, $expected, NULL, 340); } @@ -286,95 +287,52 @@ class TextSummaryTestCase extends DrupalWebTestCase { // The summaries we expect text_summary() to return when $size is the index // of each array item. - // Using no text format: - $expected = array( - "\nHi\n
\n\nfolks\n
\n!\n
", - "
\n", - "
\nH", - "
\nHi", - "
\nHi\n", - "
\nHi\n<", - "
\nHi\n", - "
\nHi\n
\nHi\n", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
\n\nfolks\n
\n!\n
\nHi\n
\n\nfolks\n
\n!\n
\nHi\n
\n\nfolks\n
\n!\n
\nHi\n
\n\nfolks\n
\n!\n
\nHi
", - "\nHi
", - "\nHi
", - "\nHi
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
", - "\nHi\n
\n\nfolks\n
\n!\n
\nHi\n
\n\nfolks\n
\n!\n
\nHi\n
\n\nfolks\n
\n!\n
Hi
\nfolks
\n!
", + 1 => "", + 2 => "Hi
", + 3 => "Hi
", + 4 => "Hi
\n", + 5 => "Hi
\n", + 6 => "Hi
\n", + 7 => "Hi
\n", + 8 => "Hi
\nfolks
", + 9 => "Hi
\nfolks
", + 10 => "Hi
\nfolks
\n!
", + 11 => "Hi
\nfolks
\n!
", + 12 => "Hi
\nfolks
\n!
", + 13 => "Hi
\nfolks
\n!
", + 14 => "Hi
\nfolks
\n!
", + 15 => "Hi
\nfolks
\n!
", + 16 => "Hi
\nfolks
\n!
", + 17 => "Hi
\nfolks
\n!
", + 18 => "Hi
\nfolks
\n!
", + 19 => "Hi
\nfolks
\n!
", + 20 => "Hi
\nfolks
\n!
", + 21 => "Hi
\nfolks
\n!
", + 22 => "Hi
\nfolks
\n!
", + 23 => "Hi
\nfolks
\n!
", + 24 => "Hi
\nfolks
\n!
", + 25 => "Hi
\nfolks
\n!
", + 26 => "Hi
\nfolks
\n!
", + 27 => "Hi
\nfolks
\n!
", + 28 => "Hi
\nfolks
\n!
", + 29 => "Hi
\nfolks
\n!
", + 30 => "Hi
\nfolks
\n!
", + 31 => "Hi
\nfolks
\n!
", + 32 => "Hi
\nfolks
\n!
", + 33 => "Hi
\nfolks
\n!
", + 34 => "Hi
\nfolks
\n!
", + 35 => "Hi
\nfolks
\n!
", + 36 => "Hi
\nfolks
\n!
", + 37 => "Hi
\nfolks
\n!
", ); // Test text_summary() for different sizes. for ($i = 0; $i <= 37; $i++) { - $this->callTextSummary($text, $expected[$i], NULL, $i); - $this->callTextSummary($text, $expected_lb[$i], 'plain_text', $i); - $this->callTextSummary($text, $expected_lb[$i], 'filtered_html', $i); + $this->callTextSummary($text, $expected[$i], 'filtered_html', $i); } } @@ -383,7 +341,17 @@ class TextSummaryTestCase extends DrupalWebTestCase { */ function callTextSummary($text, $expected, $format = NULL, $size = NULL) { $summary = text_summary($text, $format, $size); - $this->assertIdentical($summary, $expected, t('Generated summary "@summary" matches expected "@expected".', array('@summary' => $summary, '@expected' => $expected))); + $this->assertIdentical( + $summary, + $expected, + t( + 'Generated summary "@summary" matches expected "@expected".', + array( + '@summary' => str_replace("\n", '\n', $summary), + '@expected' => str_replace("\n", '\n', $expected), + ) + ) + ); } /** -- 1.7.4.1