123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- <?php
- /**
- * @file
- * Copy of drupal_html_to_text improvements from issue #299138.
- */
- /**
- * Perform format=flowed soft wrapping for mail (RFC 3676).
- *
- * We use delsp=yes wrapping, but only break non-spaced languages when
- * absolutely necessary to avoid compatibility issues.
- *
- * We deliberately use variable_get('mail_line_endings', MAIL_LINE_ENDINGS)
- * rather than "\r\n".
- *
- * @param $text
- * The plain text to process.
- * @param array $options
- * (optional) An array containing one or more of the following keys:
- * - indent: A string to indent the text with. Only '>' characters are
- * repeated on subsequent wrapped lines. Others are replaced by spaces.
- * - max: The maximum length at which to wrap each line. Defaults to 80.
- * - stuff: Whether to space-stuff special lines. Defaults to TRUE.
- * - hard: Whether to enforce the maximum line length even if no convenient
- * space character is available. Defaults to FALSE.
- * - pad: A string to use for padding short lines to 'max' characters. If
- * more than one character, only the last will be repeated.
- * - break: The line break sequence to insert. The default is one of the
- * following:
- * - "\r\n": Windows, when $text does not contain a space character.
- * - "\n": Non-Windows, when $text does not contain a space character.
- * - " \r\n": On Windows, when $text contains at least one space.
- * - " \n": Non-Windows, when $text contains at least one space.
- *
- * @see drupal_mail()
- */
- function mailsystem_wrap_mail($text, array $options = array()) {
- static $defaults;
- if (!isset($defaults)) {
- $defaults = array(
- 'indent' => '',
- 'pad' => '',
- 'pad_repeat' => '',
- 'max' => 80,
- 'stuff' => TRUE,
- 'hard' => FALSE,
- 'eol' => variable_get('mail_line_endings', MAIL_LINE_ENDINGS),
- );
- }
- $options += $defaults;
- if (!isset($options['break'])) {
- // Allow soft-wrap spaces only when $text contains at least one space.
- $options['break'] = (strpos($text, ' ') === FALSE ? '' : ' ') . $defaults['eol'];
- }
- $options['wrap'] = $options['max'] - drupal_strlen($options['indent']);
- if ($options['pad']) {
- $options['pad_repeat'] = drupal_substr($options['pad'], -1, 1);
- }
- // The 'clean' indent is applied to all lines after the first one.
- $options['clean'] = _mailsystem_html_to_text_clean($options['indent']);
- // Wrap lines according to RFC 3676.
- $lines = explode($defaults['eol'], $text);
- array_walk($lines, '_mailsystem_wrap_mail_line', $options);
- // Expand the lines array on newly-inserted line breaks.
- $lines = explode($defaults['eol'], implode($defaults['eol'], $lines));
- // Apply indentation, space-stuffing, and padding.
- array_walk($lines, '_mailsystem_indent_mail_line', $options);
- return implode($defaults['eol'], $lines);
- }
- /**
- * Transform an HTML string into plain text, preserving the structure of the
- * markup. Useful for preparing the body of a node to be sent by e-mail.
- *
- * The output will be suitable for use as 'format=flowed; delsp=yes' text
- * (RFC 3676) and can be passed directly to drupal_mail() for sending.
- *
- * We deliberately use variable_get('mail_line_endings', MAIL_LINE_ENDINGS)
- * rather than "\r\n".
- *
- * This function provides suitable alternatives for the following tags:
- *
- * <a> <address> <b> <blockquote> <br /> <caption> <cite> <dd> <div> <dl> <dt>
- * <em> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <ol> <p> <pre> <strong>
- * <table> <tbody> <td> <tfoot> <thead> <tr> <u> <ul>
- *
- * The following tag attributes are supported:
- * - <a href=...>: Hyperlink destination urls.
- * - <li value=...>: Ordered list item numbers.
- * - <ol start=...>: Ordered list start number.
- *
- * @param $string
- * The string to be transformed.
- * @param $allowed_tags
- * (optional) If supplied, a list of tags that will be transformed. If
- * omitted, all supported tags are transformed.
- *
- * @return
- * The transformed string.
- *
- * @see drupal_mail()
- */
- function mailsystem_html_to_text($string, $allowed_tags = NULL) {
- $eol = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
- // Cache list of supported tags.
- static $supported_tags;
- if (!isset($supported_tags)) {
- $supported_tags = array(
- 'a', 'address', 'b', 'blockquote', 'br', 'cite', 'dd', 'div', 'dl',
- 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'li',
- 'ol', 'p', 'pre', 'strong', 'table', 'td', 'tr', 'u', 'ul',
- );
- }
- // Make sure only supported tags are kept.
- $allowed_tags = isset($allowed_tags) ? array_intersect($supported_tags, $allowed_tags) : $supported_tags;
- // Parse $string into a DOM tree.
- $dom = filter_dom_load($string);
- $notes = array();
- // Recursively convert the DOM tree into plain text.
- $text = _mailsystem_html_to_text($dom->documentElement, $allowed_tags, $notes);
- // Hard-wrap at 1000 characters (including the line break sequence)
- // and space-stuff special lines.
- $text = mailsystem_wrap_mail($text, array('max' => 1000 - strlen($eol), 'hard' => TRUE));
- // Change non-breaking spaces back to regular spaces, and trim line breaks.
- // chr(160) is the non-breaking space character.
- $text = str_replace(chr(160), ' ', trim($text, $eol));
- // Add footnotes;
- if ($notes) {
- // Add a blank line before the footnote list.
- $text .= $eol;
- foreach ($notes as $url => $note) {
- $text .= $eol . '[' . $note . '] ' . $url;
- }
- }
- return $text;
- }
- /**
- * Helper function for drupal_html_to_text().
- *
- * Recursively converts $node to text, wrapping and indenting as necessary.
- *
- * @param $node
- * The source DOMNode.
- * @param $allowed_tags
- * A list of tags that will be transformed.
- * @param array &$notes
- * A writeable array of footnote reference numbers, keyed by their
- * respective hyperlink destination urls.
- * @param $line_length
- * The maximum length of a line, for wrapping. Defaults to 80 characters.
- * @param array $parents
- * The list of ancestor tags, from nearest to most distant. Defaults to an
- * empty array().
- * @param $count
- * The number to use for the next list item within an ordered list. Defaults
- * to 1.
- */
- function _mailsystem_html_to_text(DOMNode $node, array $allowed_tags, array &$notes, $line_length = 80, array $parents = array(), &$count = NULL) {
- if (!isset($count)) {
- $count = 1;
- }
- $eol = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
- if ($node->nodeType === XML_TEXT_NODE) {
- // For text nodes, we just copy the text content.
- $text = $node->textContent;
- // Convert line breaks and trim trailing spaces.
- $text = preg_replace('/ *\r?\n/', $eol, $text);
- if (in_array('pre', $parents)) {
- // Within <pre> tags, all spaces become non-breaking.
- // chr(160) is the non-breaking space character.
- $text = str_replace(' ', chr(160), $text);
- }
- else {
- // Outside <pre> tags, collapse whitespace.
- $text = preg_replace('/[[:space:]]+/', ' ', $text);
- }
- return $text;
- }
- // Non-text node.
- $tag = '';
- $text = '';
- $child_text = '';
- $child_count = 1;
- $indent = '';
- $prefix = '';
- $suffix = '';
- $pad = '';
- if (isset($node->tagName) && in_array($node->tagName, $allowed_tags)) {
- $tag = $node->tagName;
- switch ($tag) {
- // Turn links with valid hrefs into footnotes.
- case 'a':
- $test = !empty($node->attributes);
- $test = $test && ($href = $node->attributes->getNamedItem('href'));
- $test = $test && ($url = url(preg_replace('|^' . base_path() . '|', '', $href->nodeValue), array('absolute' => TRUE)));
- $test = $test && valid_url($url);
- if ($test) {
- // Only add links that have not already been added.
- if (isset($notes[$url])) {
- $note = $notes[$url];
- }
- else {
- $note = count($notes) + 1;
- $notes[$url] = $note;
- }
- $suffix = ' [' . $note . ']';
- }
- break;
- // Generic block-level tags.
- case 'address':
- case 'caption':
- case 'div':
- case 'p':
- case 'pre':
- // Start on a new line except as the first child of a list item.
- if (!isset($parents[0]) || $parents[0] !== 'li' || !$node->isSameNode($node->parentNode->firstChild)) {
- $text = $eol;
- }
- $suffix = $eol;
- break;
- // Forced line break.
- case 'br':
- $text = $eol;
- break;
- // Boldface by wrapping with "*" characters.
- case 'b':
- case 'strong':
- $prefix = '*';
- $suffix = '*';
- break;
- // Italicize by wrapping with "/" characters.
- case 'cite':
- case 'em':
- case 'i':
- $prefix = '/';
- $suffix = '/';
- break;
- // Underline by wrapping with "_" characters.
- case 'u':
- $prefix = '_';
- $suffix = '_';
- break;
- // Blockquotes are indented by "> " at each level.
- case 'blockquote':
- $text = $eol;
- // chr(160) is the non-breaking space character.
- $indent = '>' . chr(160);
- $suffix = $eol;
- break;
- // Dictionary definitions are indented by four spaces.
- case 'dd':
- // chr(160) is the non-breaking space character.
- $indent = chr(160) . chr(160) . chr(160) . chr(160);
- $suffix = $eol;
- break;
- // Dictionary list.
- case 'dl':
- // Start on a new line as the first child of a list item.
- if (!isset($parents[0]) || $parents[0] !== 'li' || !$node->isSameNode($node->parentNode->firstChild)) {
- $text = $eol;
- }
- $suffix = $eol;
- break;
- // Dictionary term.
- case 'dt':
- $suffix = $eol;
- break;
- // Header level 1 is prefixed by eight "=" characters.
- case 'h1':
- $text = "$eol$eol";
- // chr(160) is the non-breaking space character.
- $indent = '========' . chr(160);
- $pad = chr(160) . '=';
- $suffix = $eol;
- break;
- // Header level 2 is prefixed by six "-" characters.
- case 'h2':
- $text = "$eol$eol";
- // chr(160) is the non-breaking space character.
- $indent = '------' . chr(160);
- $pad = chr(160) . '-';
- $suffix = $eol;
- break;
- // Header level 3 is prefixed by four "." characters and a space.
- case 'h3':
- $text = "$eol$eol";
- // chr(160) is the non-breaking space character.
- $indent = '....' . chr(160);
- $suffix = $eol;
- break;
- // Header level 4 is prefixed by three "." characters and a space.
- case 'h4':
- $text = "$eol$eol";
- // chr(160) is the non-breaking space character.
- $indent = '...' . chr(160);
- $suffix = $eol;
- break;
- // Header level 5 is prefixed by two "." character and a space.
- case 'h5':
- $text = "$eol$eol";
- // chr(160) is the non-breaking space character.
- $indent = '..' . chr(160);
- $suffix = $eol;
- break;
- // Header level 6 is prefixed by one "." character and a space.
- case 'h6':
- $text = "$eol$eol";
- // chr(160) is the non-breaking space character.
- $indent = '.' . chr(160);
- $suffix = $eol;
- break;
- // Horizontal rulers become a line of "-" characters.
- case 'hr':
- $text = $eol;
- $child_text = '-';
- $pad = '-';
- $suffix = $eol;
- break;
- // List items are treated differently depending on the parent tag.
- case 'li':
- // Ordered list item.
- if (reset($parents) === 'ol') {
- // Check the value attribute.
- $test = !empty($node->attributes);
- $test = $test && ($value = $node->attributes->getNamedItem('value'));
- if ($test) {
- $count = $value->nodeValue;
- }
- // chr(160) is the non-breaking space character.
- $indent = ($count < 10 ? chr(160) : '') . chr(160) . "$count)" . chr(160);
- $count++;
- }
- // Unordered list item.
- else {
- // chr(160) is the non-breaking space character.
- $indent = chr(160) . '*' . chr(160);
- }
- $suffix = $eol;
- break;
- // Ordered lists.
- case 'ol':
- // Start on a new line as the first child of a list item.
- if (!isset($parents[0]) || $parents[0] !== 'li' || !$node->isSameNode($node->parentNode->firstChild)) {
- $text = $eol;
- }
- // Check the start attribute.
- $test = !empty($node->attributes);
- $test = $test && ($value = $node->attributes->getNamedItem('start'));
- if ($test) {
- $child_count = $value->nodeValue;
- }
- break;
- // Tables require special handling.
- case 'table':
- return _mailsystem_html_to_text_table($node, $allowed_tags, $notes, $line_length);
- // Separate adjacent table cells by two non-breaking spaces.
- case 'td':
- if (!empty($node->nextSibling)) {
- // chr(160) is the non-breaking space character.
- $suffix = chr(160) . chr(160);
- }
- break;
- // End each table row with a newline.
- case 'tr':
- $suffix = $eol;
- break;
- // Unordered lists.
- case 'ul':
- // Start on a new line as the first child of a list item.
- if (!isset($parents[0]) || $parents[0] !== 'li' || !$node->isSameNode($node->parentNode->firstChild)) {
- $text = $eol;
- }
- break;
- default:
- // Coder review complains if there is no default case.
- break;
- }
- // Only add allowed tags to the $parents array.
- array_unshift($parents, $tag);
- }
- // Copy each child node to output.
- if ($node->hasChildNodes()) {
- foreach ($node->childNodes as $child) {
- $child_text .= _mailsystem_html_to_text($child, $allowed_tags, $notes, $line_length - drupal_strlen($indent), $parents, $child_count); }
- }
- // We only add prefix and suffix if the child nodes were non-empty.
- if ($child_text > '') {
- // We capitalize the contents of h1 and h2 tags.
- if ($tag === 'h1' || $tag === 'h2') {
- $child_text = drupal_strtoupper($child_text);
- }
- // Don't add a newline to an existing newline.
- if ($suffix === $eol && drupal_substr($child_text, - drupal_strlen($eol)) === $eol) {
- $suffix = '';
- }
- // Trim spaces around newlines except with <pre> or inline tags.
- if (!in_array($tag, array('a', 'b', 'cite', 'em', 'i', 'pre', 'strong', 'u'))) {
- $child_text = preg_replace('/ *' . $eol . ' */', $eol, $child_text);
- }
- // Soft-wrap at effective line length, but don't space-stuff.
- $child_text = mailsystem_wrap_mail(
- $prefix . $child_text,
- array(
- // chr(160) is the non-breaking space character.
- 'break' => chr(160) . $eol,
- 'indent' => $indent,
- 'max' => $line_length,
- 'pad' => $pad,
- 'stuff' => FALSE,
- )
- ) . $suffix;
- if ($tag === 'pre') {
- // Perform RFC-3676 soft-wrapping.
- // chr(160) is the non-breaking space character.
- $child_text = str_replace(chr(160), ' ', $child_text);
- $child_text = mailsystem_wrap_mail(
- $child_text,
- array('max' => $line_length, 'stuff' => FALSE)
- );
- // chr(160) is the non-breaking space character.
- $child_text = str_replace(' ', chr(160), $child_text);
- }
- $text .= $child_text;
- }
- return $text;
- }
- /**
- * Helper function for _mailsystem_html_to_text().
- *
- * Renders a <table> DOM Node into plain text. Attributes such as rowspan,
- * colspan, padding, border, etc. are ignored.
- *
- * @param DOMNode $node
- * The DOMNode corresponding to the <table> tag and its contents.
- * @param $allowed_tags
- * The list of allowed tags passed to _mailsystem_html_to_text().
- * @param array &$notes
- * A writeable array of footnote reference numbers, keyed by their
- * respective hyperlink destination urls.
- * @param $table_width
- * The desired maximum table width, after word-wrapping each table cell.
- *
- * @return
- * A plain text representation of the table.
- *
- * @see _mailsystem_html_to_text()
- */
- function _mailsystem_html_to_text_table(DOMNode $node, $allowed_tags = NULL, array &$notes = array(), $table_width = 80) {
- $eol = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
- $header = array();
- $footer = array();
- $body = array();
- $text = $eol;
- $current = $node;
- while (TRUE) {
- if (isset($current->tagName)) {
- switch ($current->tagName) {
- case 'caption': // The table caption is added first.
- $text = _mailsystem_html_to_text($current, $allowed_tags, $notes, $table_width);
- break;
- case 'tr':
- switch ($current->parentNode->tagName) {
- case 'thead':
- $header[] = $current;
- break;
- case 'tfoot':
- $footer[] = $current;
- break;
- default: // Either 'tbody' or 'table'
- $body[] = $current;
- break;
- }
- break;
- default:
- if ($current->hasChildNodes()) {
- $current = $current->firstChild;
- continue 2;
- }
- }
- }
- do {
- if ($current->nextSibling) {
- $current = $current->nextSibling;
- continue 2;
- }
- $current = $current->parentNode;
- } while ($current && !$current->isSameNode($node));
- break;
- }
- // Merge the thead, tbody, and tfoot sections together.
- if ($rows = array_merge($header, $body, $footer)) {
- $num_rows = count($rows);
- // First just count the number of columns.
- $num_cols = 0;
- foreach ($rows as $row) {
- $row_cols = 0;
- foreach ($row->childNodes as $cell) {
- if (isset($cell->tagName) && in_array($cell->tagName, array('td', 'th'))) {
- $row_cols++;
- }
- }
- $num_cols = max($num_cols, $row_cols);
- }
- // If any columns were found, calculate each column height and width.
- if ($num_cols) {
- // Set up a binary search for best wrap width for each column.
- $max = max($table_width - $num_cols - 1, 1);
- $max_wraps = array_fill(0, $num_cols, $max);
- $try = max(intval(($table_width - 1) / $num_cols - 1), 1);
- $try_wraps = array_fill(0, $num_cols, $try);
- $min_wraps = array_fill(0, $num_cols, 1);
- // Start searching...
- $change = FALSE;
- do {
- $change = FALSE;
- $widths = array_fill(0, $num_cols, 0);
- $heights = array_fill(0, $num_rows, 0);
- $table = array_fill(0, $num_rows, array_fill(0, $num_cols, ''));
- $breaks = array_fill(0, $num_cols, FALSE);
- foreach ($rows as $i => $row) {
- $j = 0;
- foreach ($row->childNodes as $cell) {
- if (!isset($cell->tagName) || !in_array($cell->tagName, array('td', 'th'))) {
- // Skip text nodes.
- continue;
- }
- // Render the cell contents.
- $cell = _mailsystem_html_to_text($cell, $allowed_tags, $notes, $try_wraps[$j]);
- // Trim leading line-breaks and trailing whitespace.
- // chr(160) is the non-breaking space character.
- $cell = rtrim(ltrim($cell, $eol), ' ' . $eol . chr(160));
- $table[$i][$j] = $cell;
- if ($cell > '') {
- // Split the cell into lines.
- $lines = explode($eol, $cell);
- // The row height is the maximum number of lines among all the
- // cells in that row.
- $heights[$i] = max($heights[$i], count($lines));
- foreach ($lines as $line) {
- $this_width = drupal_strlen($line);
- // The column width is the maximum line width among all the
- // lines in that column.
- if ($this_width > $widths[$j]) {
- $widths[$j] = $this_width;
- // If the longest line in a column contains at least one
- // space character, then the table can be made narrower.
- $breaks[$j] = strpos(' ', $line) !== FALSE;
- }
- }
- }
- $j++;
- }
- }
- // Calculate the total table width;
- $this_width = array_sum($widths) + $num_cols + 1;
- if ($this_width > $table_width) {
- // Wider than desired.
- if (!in_array(TRUE, $breaks)) {
- // If there are no more break points, then the table is already as
- // narrow as it can get, so we're done.
- break;
- }
- foreach ($try_wraps as $i => $wrap) {
- $max_wraps[$i] = min($max_wraps[$i], $wrap);
- if ($breaks[$i]) {
- $new_wrap = intval(($min_wraps[$i] + $max_wraps[$i]) / 2);
- $new_wrap = min($new_wrap, $widths[$i] - 1);
- $new_wrap = max($new_wrap, $min_wraps[$i]);
- }
- else {
- // There's no point in trying to make the column narrower than
- // the widest un-wrappable line in the column.
- $min_wraps[$i] = $widths[$i];
- $new_wrap = $widths[$i];
- }
- if ($try_wraps[$i] > $new_wrap) {
- $try_wraps[$i] = $new_wrap;
- $change = TRUE;
- }
- }
- }
- elseif ($this_width < $table_width) {
- // Narrower than desired.
- foreach ($try_wraps as $i => $wrap) {
- if ($min_wraps[$i] < $wrap) {
- $min_wraps[$i] = $wrap;
- }
- $new_wrap = intval(($min_wraps[$i] + $max_wraps[$i]) / 2);
- $new_wrap = max($new_wrap, $widths[$i] + 1);
- $new_wrap = min($new_wrap, $max_wraps[$i]);
- if ($try_wraps[$i] < $new_wrap) {
- $try_wraps[$i] = $new_wrap;
- $change = TRUE;
- }
- }
- }
- } while ($change);
- // Pad each cell to column width and line height.
- for ($i = 0; $i < $num_rows; $i++) {
- if ($heights[$i]) {
- for ($j = 0; $j < $num_cols; $j++) {
- $cell = $table[$i][$j];
- // Pad each cell to the maximum number of lines in that row.
- $lines = array_pad(explode($eol, $cell), $heights[$i], '');
- foreach ($lines as $k => $line) {
- // Pad each line to the maximum width in that column.
- $repeat = $widths[$j] - drupal_strlen($line);
- if ($repeat > 0) {
- // chr(160) is the non-breaking space character.
- $lines[$k] .= str_repeat(chr(160), $repeat);
- }
- }
- $table[$i][$j] = $lines;
- }
- }
- }
- // Generate the row separator line.
- $separator = '+';
- for($i = 0; $i < $num_cols; $i++) {
- $separator .= str_repeat('-', $widths[$i]) . '+';
- }
- $separator .= $eol;
- for ($i = 0; $i < $num_rows; $i++) {
- $text .= $separator;
- if (!$heights[$i]) {
- continue;
- }
- $row = $table[$i];
- // For each row, iterate first by lines within the row.
- for ($k = 0; $k < $heights[$i]; $k++) {
- // Add a vertical-bar at the beginning of each row line.
- $row_line = '|';
- $trimmed = '';
- // Within each row line, iterate by cells within that line.
- for ($j = 0; $j < $num_cols; $j++) {
- // Add a vertical bar at the end of each cell line.
- $row_line .= $row[$j][$k] . '|';
- // chr(160) is the non-breaking space character.
- $trimmed .= trim($row[$j][$k], ' ' . $eol . chr(160));
- }
- if ($trimmed > '') {
- // Only print rows that are non-empty.
- $text .= $row_line . $eol;
- }
- }
- }
- // Final output ends with a row separator.
- $text .= $separator;
- }
- }
- // Make sure formatted table content doesn't line-wrap.
- // chr(160) is the non-breaking space character.
- return str_replace(' ', chr(160), $text);
- }
- /**
- * Helper function for array_walk in drupal_wrap_mail().
- *
- * Inserts $values['break'] sequences to break up $line into parts of no more
- * than $values['wrap'] characters. Only breaks at space characters, unless
- * $values['hard'] is TRUE.
- */
- function _mailsystem_wrap_mail_line(&$line, $key, $values) {
- $line = wordwrap($line, $values['wrap'], $values['break'], $values['hard']);
- }
- /**
- * Helper function for array_walk in drupal_wrap_mail().
- *
- * If $values['pad'] is non-empty, $values['indent'] will be added at the start
- * of each line, and $values['pad'] at the end, repeating the last character of
- * $values['pad'] until the line length equals $values['max'].
- *
- * If $values['pad'] is empty, $values['indent'] will be added at the start of
- * the first line, and $values['clean'] at the start of subsequent lines.
- *
- * If $values['stuff'] is true, then an extra space character will be added at
- * the start of any line beginning with a space, a '>', or the word 'From'.
- *
- * @see http://www.ietf.org/rfc/rfc3676.txt
- */
- function _mailsystem_indent_mail_line(&$line, $key, $values) {
- if ($line == '') {
- return;
- }
- if ($values['pad']) {
- $line = $values['indent'] . $line;
- $count = $values['max'] - drupal_strlen($line) - drupal_strlen($values['pad']);
- if ($count >= 0) {
- $line .= $values['pad'] . str_repeat($values['pad_repeat'], $count);
- }
- }
- else {
- $line = $values[$key === 0 ? 'indent' : 'clean'] . $line;
- }
- if ($values['stuff']) {
- // chr(160) is the non-breaking space character.
- $line = preg_replace('/^(' . chr(160) . '| |>|From)/', ' $1', $line);
- }
- }
- /**
- * Helper function for drupal_wrap_mail() and drupal_html_to_text().
- *
- * Replace all non-quotation markers from a given piece of indentation with
- * non-breaking space characters.
- */
- function _mailsystem_html_to_text_clean($indent) {
- // chr(160) is the non-breaking space character.
- return preg_replace('/[^>]/', chr(160), $indent);
- }
|