From d6b35fcecd878f2248ce1f56162418e2ae9f0d66 Mon Sep 17 00:00:00 2001
From: Bob Vincent 
Date: Thu, 12 May 2011 23:22:58 -0400
Subject: [PATCH 1/2] Example profile for testing.
---
 profiles/standard/standard.info    |    4 +---
 profiles/standard/standard.install |   30 ------------------------------
 profiles/standard/standard.profile |   11 ++++++++++-
 3 files changed, 11 insertions(+), 34 deletions(-)
diff --git a/profiles/standard/standard.info b/profiles/standard/standard.info
index 56e43086a839dd44f6e1cda3e31d3f3901130c2e..c190009e076d913708f948e51236dbe8a4f349b1 100644
--- a/profiles/standard/standard.info
+++ b/profiles/standard/standard.info
@@ -5,8 +5,6 @@ core = 8.x
 dependencies[] = block
 dependencies[] = color
 dependencies[] = comment
-dependencies[] = contextual
-dependencies[] = dashboard
 dependencies[] = help
 dependencies[] = image
 dependencies[] = list
@@ -19,8 +17,8 @@ dependencies[] = dblog
 dependencies[] = search
 dependencies[] = shortcut
 dependencies[] = toolbar
-dependencies[] = overlay
 dependencies[] = field_ui
 dependencies[] = file
 dependencies[] = rdf
+dependencies[] = simpletest
 files[] = standard.profile
diff --git a/profiles/standard/standard.install b/profiles/standard/standard.install
index 70829064d1bc3c929f20c3c112bbc0957e1e752d..2216b691c261687982ade99ef26959a5bcadf292 100644
--- a/profiles/standard/standard.install
+++ b/profiles/standard/standard.install
@@ -87,16 +87,6 @@ function standard_install() {
       'cache' => -1,
     ),
     array(
-      'module' => 'node',
-      'delta' => 'recent',
-      'theme' => $admin_theme,
-      'status' => 1,
-      'weight' => 10,
-      'region' => 'dashboard_main',
-      'pages' => '',
-      'cache' => -1,
-    ),
-    array(
       'module' => 'user',
       'delta' => 'login',
       'theme' => $default_theme,
@@ -166,26 +156,6 @@ function standard_install() {
       'pages' => '',
       'cache' => -1,
     ),
-    array(
-      'module' => 'user',
-      'delta' => 'new',
-      'theme' => $admin_theme,
-      'status' => 1,
-      'weight' => 0,
-      'region' => 'dashboard_sidebar',
-      'pages' => '',
-      'cache' => -1,
-    ),
-    array(
-      'module' => 'search',
-      'delta' => 'form',
-      'theme' => $admin_theme,
-      'status' => 1,
-      'weight' => -10,
-      'region' => 'dashboard_sidebar',
-      'pages' => '',
-      'cache' => -1,
-    ),
   );
   $query = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache'));
   foreach ($values as $record) {
diff --git a/profiles/standard/standard.profile b/profiles/standard/standard.profile
index 7671c12a2d992cdd8753847214ededbeaaa4663d..fb0e8af2bdd188792866f28b6c1504abfededa1b 100644
--- a/profiles/standard/standard.profile
+++ b/profiles/standard/standard.profile
@@ -7,5 +7,14 @@
  */
 function standard_form_install_configure_form_alter(&$form, $form_state) {
   // Pre-populate the site name with the server name.
-  $form['site_information']['site_name']['#default_value'] = $_SERVER['SERVER_NAME'];
+  $form['site_information']['site_name']['#default_value'] = 'Example';
+  $form['site_information']['site_mail']['#default_value'] = 'user@example.com';
+  $form['admin_account']['account']['name']['#default_value'] = 'User';
+  $form['admin_account']['account']['mail']['#default_value'] = 'user@example.com';
+  $form['admin_account']['account']['pass']['#default_value']['pass1'] = 'pass';
+  $form['admin_account']['account']['pass']['#default_value']['pass2'] = 'pass';
+  $form['admin_account']['account']['pass']['pass1']['#default_value'] = 'pass';
+  $form['admin_account']['account']['pass']['pass2']['#default_value'] = 'pass';
+  $form['server_settings']['site_default_country'] = 'US';
+  $form['update_notifications']['update_status_module'] = array();
 }
-- 
1.7.4.1
From 738e7701c5c9f2cf29b61dbdda8a87a693b76388 Mon Sep 17 00:00:00 2001
From: Bob Vincent 
Date: Fri, 13 May 2011 09:01:35 -0400
Subject: [PATCH 2/2] Issue #221257 by pillarsdotnet: text_summary() should be HTML-aware.
---
 modules/field/modules/text/text.module |  172 ++++++++++++++++----------------
 modules/field/modules/text/text.test   |  141 ++++++++++----------------
 2 files changed, 138 insertions(+), 175 deletions(-)
diff --git a/modules/field/modules/text/text.module b/modules/field/modules/text/text.module
index 89c605cf2c046eb48d448e20d27a63ef88a8583f..d0abbcd55bfddf494939ffa5b3c22ce0d43f9031 100644
--- a/modules/field/modules/text/text.module
+++ b/modules/field/modules/text/text.module
@@ -330,49 +330,36 @@ function _text_sanitize($instance, $langcode, $item, $column) {
  * @param $text
  *   The content for which a summary will be generated.
  * @param $format
- *   The format of the content.
- *   If the PHP filter is present and $text contains PHP code, we do not
- *   split it up to prevent parse errors.
- *   If the line break filter is present then we treat newlines embedded in
- *   $text as line breaks.
- *   If the htmlcorrector filter is present, it will be run on the generated
- *   summary (if different from the incoming $text).
+ *   The format of the content. The $text string will be passed through
+ *   check_markup() before generating a summary.
  * @param $size
- *   The desired character length of the summary. If omitted, the default
- *   value will be used. Ignored if the special delimiter is present
- *   in $text.
+ *   The desired character length of the summary, not counting HTML tags. If
+ *   omitted, the default value will be used. Ignored if the special delimiter
+ *   is present in $text.
  * @return
  *   The generated summary.
  */
 function text_summary($text, $format = NULL, $size = NULL) {
-
-  if (!isset($size)) {
-    // What used to be called 'teaser' is now called 'summary', but
-    // the variable 'teaser_length' is preserved for backwards compatibility.
-    $size = variable_get('teaser_length', 600);
-  }
-
   // Find where the delimiter is in the body
   $delimiter = strpos($text, '');
 
-  // If the size is zero, and there is no delimiter, the entire body is the summary.
-  if ($size == 0 && $delimiter === FALSE) {
-    return $text;
-  }
-
   // If a valid delimiter has been specified, use it to chop off the summary.
   if ($delimiter !== FALSE) {
-    return substr($text, 0, $delimiter);
+    return trim(check_markup(substr($text, 0, $delimiter), $format));
   }
 
-  // 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_code']) && $filters['php_code']->status && strpos($text, '') !== FALSE) {
-      return $text;
-    }
+  // Start with the trimmed, formatted version of $text
+  $text = trim(check_markup($text, $format));
+
+  if (!isset($size)) {
+    // What used to be called 'teaser' is now called 'summary', but
+    // the variable 'teaser_length' is preserved for backwards compatibility.
+    $size = variable_get('teaser_length', 600);
+  }
+
+  // If the size is zero, the entire body is the summary.
+  if ($size == 0) {
+    return $text;
   }
 
   // If we have a short body, the entire body is the summary.
@@ -380,68 +367,79 @@ function text_summary($text, $format = NULL, $size = NULL) {
     return $text;
   }
 
-  // If the delimiter has not been specified, try to split at paragraph or
-  // sentence boundaries.
-
-  // The summary may not be longer than maximum length specified. Initial slice.
-  $summary = truncate_utf8($text, $size);
-
-  // Store the actual length of the UTF8 string -- which might not be the same
-  // as $size.
-  $max_rpos = strlen($summary);
-
-  // How much to cut off the end of the summary 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 summary. We use strpos on the reversed needle and
-  // haystack for speed and convenience.
-  $reversed = strrev($summary);
-
-  // Build an array of arrays of break points grouped by preference.
-  $break_points = array();
-
-  // A paragraph near the end of sliced summary is most preferable.
-  $break_points[] = array('
' => 0);
-
-  // If no complete paragraph then treat line breaks as paragraphs.
-  $line_breaks = array('
' => 6, '
' => 4);
-  // Newline only indicates a line break if line break converter
-  // filter is present.
-  if (isset($filters['filter_autop'])) {
-    $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 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);
-      }
-    }
-
-    // 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);
+  // Generate a DOM Document to hold the full body.
+  $body_doc = new DOMDocument();
+  $body_doc->loadHTML('' . $text . '');
+  $body_node = $body_doc->getElementsByTagName('body')->item(0);
+
+  // Generate a DOM Document to hold the summary.
+  $summary_doc = new DOMDocument();
+  $summary_doc->loadHTML('');
+  $summary_node = $summary_doc->getElementsByTagName('body')->item(0);
+
+  // Recursively copy each child node from $body_node to $summary_node
+  // until $size limit is reached.
+  foreach ($body_node->childNodes as $node) {
+    if ($size <= 0) {
       break;
     }
+    _text_summarize($node, $size, $summary_node, $summary_doc);
   }
 
-  // If the htmlcorrector filter is present, apply it to the generated summary.
-  if (isset($filters['filter_htmlcorrector'])) {
-    $summary = _filter_htmlcorrector($summary);
+  // Export and return the summary document.
+  $output = '';
+  foreach ($summary_doc->getElementsByTagName('body')->item(0)->childNodes as $node) {
+    $output .= $summary_doc->saveXml($node);
   }
+  // If the original format was plaintext, the summary should be, too.
+  if ($text === strip_tags($text)) {
+    $output = strip_tags($output);
+  }
+  return trim($output);
+}
 
-  return $summary;
+function _text_summarize(&$body, &$size, &$summary, &$doc) {
+  if ($body->nodeType === XML_TEXT_NODE) {
+    $text_length = strlen($body->textContent);
+    if ($text_length <= $size) {
+      $size -= $text_length;
+      $summary->appendChild($doc->createTextNode($body->textContent));
+      return;
+    }
+    // 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 = 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;
+  }
+  if ($body->hasChildNodes()) {
+    $node = $summary->appendChild($doc->createElement($body->tagName));
+    foreach ($body->childNodes as $child) {
+      if ($size > 0) {
+        _text_summarize($child, $size, $node, $doc);
+      }
+      else {
+        break;
+      }
+    }
+  }
+  return;
 }
 
 /**
diff --git a/modules/field/modules/text/text.test b/modules/field/modules/text/text.test
index b42fed7e09894d352b3ecdd27431234e6ae77f72..55656997a58e571e43c4e94ff2ad01ef03b89c53 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
",
-    );
 
-    // And using a text format WITH the line-break and htmlcorrector filters.
-    $expected_lb = array(
-      "\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
",
+    // Using the filtered_html format:
+    $expected = array (
+      0 => "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,14 @@ 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