/** * prepare a multi-part message * * @param string message HTML tags or ASCII content * @return array containing message parts ($type => $content) */ public static function build_multipart($text) { global $context; // make a full html entity --body attributes are ignored most of the time $text = '<html><body>' . MAIL_FONT_PREFIX . $text . MAIL_FONT_SUFFIX . '</body></html>'; // change links to include host name $text = str_replace(' href="/', ' href="' . $context['url_to_home'] . '/', $text); $text = str_replace(' src="/', ' src="' . $context['url_to_home'] . '/', $text); // remove invisible tags, such as scripts, etc. $text = xml::strip_invisible_tags($text); // one element per type $message = array(); // text/plain part has no tag anymore $replacements = array('#<a [^>]*?><img [^>]*?></a>#i' => '', "#<a href=\"([^\"]+?)\"([^>]*?)>\$1</a>#i" => "\$1", '#<a href="([^"]+?)" ([^>]*?)>(.*?)</a>#i' => "\$3 \$1", '/<a href=\\"([^\\"]+?)">(.*?)<\\/a>/i' => "\$2 \$1", '/<hr[^>]*?>/i' => "-------\n", '/ /' => ' '); // text/plain part $message['text/plain; charset=utf-8'] = utf8::from_unicode(utf8::encode(trim(html_entity_decode(xml::strip_visible_tags(preg_replace(array_keys($replacements), array_values($replacements), $text), ''), ENT_QUOTES, 'UTF-8')))); // transform the text/html part $replacements = array('#<dl[^>]*?>(.*?)</dl>#siu' => '<table>$1</table>', '#<dt[^>]*?>(.*?)</dt>#siu' => '<tr><td>' . MAIL_FONT_PREFIX . '$1' . MAIL_FONT_SUFFIX . '</td>', '#<dd[^>]*?>(.*?)</dd>#siu' => '<td>' . MAIL_FONT_PREFIX . '$1' . MAIL_FONT_SUFFIX . '</td></tr>', '#class="grid"#i' => 'border="1" cellspacing="0" cellpadding="10"', '#on(click|keypress)="([^"]+?)"#i' => '', '#/>#i' => '>'); // text/html part $message['text/html; charset=utf-8'] = preg_replace(array_keys($replacements), array_values($replacements), $text); // return all parts return $message; }
/** * strip some text, by suppressing codes, html and limiting words * * To limit the size of a string and preserve HTML tagging, you should rather consider [code]cap()[/code]. * * A stripped string is a short set of words aiming to introduce a longer page. It is * usually followed by a link to jump to the full text. * * Alternatively, this function may also be used to limit the number of words * for a plain text string. * * In both cases the calling script should be able to use the resulting directly, without any additional processing. * * Most HTML tags are suppressed by [code]Skin::strip()[/code], except <a>, <br>, <img> and <span>. * You can provide the full list of allowed tags. * * This function will strip YACS codes as well, except if you explicitly ask for codes to be processed. * * * Example: * [snippet] * Skin::strip('This is my very interesting page', 3); * [/snippet] * * will return: * [snippet] * 'This is my...' * [/snippet] * * @param string the text to abbreviate * @param int the maximum number of words in the output * @param an optional url to go to the full version, if any * @param the list of allowed HTML tags, if any * @param boolean set to TRUE if YACS codes should be rendered, else codes will be removed * @return the HTML to display */ public static function &strip($text, $count = 20, $url = NULL, $allowed_html = '<a><br><img><span>', $render_codes = FALSE) { global $context; // no follow-up yet $with_more = FALSE; // process YACS codes if ($render_codes) { // suppress dynamic tables, they would probably take too much space if (preg_match('/\\[table=(.+?)\\]/s', $text)) { $text = preg_replace(array('/\\[table=(.+?)\\]/s'), ' (table) ', $text); // append a link to the full page $with_more = TRUE; } // render all codes $text = Codes::beautify($text); } // remove invisible tags, such as scripts, etc. $text = xml::strip_invisible_tags($text); // strip most visible tags $text = trim(xml::strip_visible_tags($text, $allowed_html)); // count overall words $overall = count(preg_split("/[ \t,\\.;\\?!]+/", $text, -1, PREG_SPLIT_NO_EMPTY)); // no parsing overhead in case of short labels if ($overall <= $count) { return $text; } // skip html tags $areas = preg_split('/(<\\/{0,1}[\\w]+[^>]*>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE); $text = ''; $index = 0; $overall = 0; foreach ($areas as $area) { // tag to be preserved if ($index % 2) { $text .= $area; // check boundary after last HTML tag -- else <a>text</a> could loose closing tag if ($count < 0) { break; } // regular text } else { // count words from this area $words = preg_split("/([ \t,\\.;\\?!]+)/", $area, -1, PREG_SPLIT_DELIM_CAPTURE); // we still have some room if (count($words) <= 2 * $count) { $text .= $area; } elseif ($count > 0) { $overall += intval(count($words) / 2 - $count); // drop the tail array_splice($words, 2 * $count); // reassemble displayed words $text .= implode('', $words) . '...'; // append a link to the full page $with_more = TRUE; } else { $overall += intval(count($words) / 2); } // less words to accept $count -= intval(count($words) / 2); } $index++; } // there is more to read if ($with_more && $url) { // indicate the number of words to read, if significant text to read if ($overall > 30) { $text .= ' (' . sprintf(i18n::s('%d words to read'), $overall) . ') '; } // add a link $text .= ' ' . Skin::build_link($url, MORE_IMG, 'more', i18n::s('View the page')) . ' '; } return $text; }
/** * make a string out of something * * @param mixed something to be printed * @param boolean TRUE if HTML tags should be suppressed, FALSE otherwise * @return string */ public static function &to_string($value = '', $strip_tags = TRUE) { global $context; // a boolean if ($value === TRUE) { $value = 'TRUE'; } elseif ($value === FALSE) { $value = 'FALSE'; } elseif (isset($value) && !is_string($value)) { $value = print_r($value, TRUE); } // stick to simple line returns $value = str_replace("\r", '', $value); // log simple messages if ($strip_tags) { $value = trim(xml::strip_visible_tags(xml::strip_invisible_tags($value))); } else { $value = trim($value); } // return a clean string return $value; }
if ($url) { $text .= ' <link rel="alternate" type="text/html" href="' . str_replace('&', '&', $url) . '" />' . "\n" . ' <id>' . str_replace('&', '&', $url) . '</id>' . "\n"; } if ($author) { $text .= ' <author><name>' . encode_field($author) . '</name></author>' . "\n"; } if ($introduction) { $text .= ' <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"> ' . xml::strip_invisible_tags($introduction) . "</div></summary>\n"; } else { $text .= ' <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"> ' . "</div></summary>\n"; } if ($description) { $text .= ' <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"> ' . xml::strip_invisible_tags($description) . "</div></content>\n"; } if (intval($time)) { $text .= ' <updated>' . gmdate('Y-m-d\\TH:i:s\\Z', intval($time)) . "</updated>\n"; } if ($section) { $text .= ' <dc:source>' . encode_field($section) . '</dc:source>' . "\n"; } if ($author) { $text .= ' <dc:creator>' . encode_field($author) . '</dc:creator>' . "\n"; } $text .= ' <dc:publisher>' . encode_field($context['site_owner']) . '</dc:publisher>' . "\n" . ' <dc:format>text/html</dc:format>' . "\n" . ' <dc:language>' . $context['preferred_language'] . '</dc:language>' . "\n" . ' <dc:rights>Copyright ' . encode_field($context['site_copyright']) . '</dc:rights>' . "\n" . "\t</entry>\n"; } } // the postamble $text .= "\n" . '</feed>';