PageRenderTime 31ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/libs/flay.php

https://code.google.com/
PHP | 284 lines | 181 code | 9 blank | 94 comment | 26 complexity | 8638694bea3eae02be19a42421ee69c5 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * Text-to-HTML parser.
  5. *
  6. * Text-to-html parser, similar to {@link http://textism.com/tools/textile/ Textile} or {@link http://www.whytheluckystiff.net/ruby/redcloth/ RedCloth}.
  7. *
  8. * PHP versions 4 and 5
  9. *
  10. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  11. * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  12. *
  13. * Licensed under The MIT License
  14. * Redistributions of files must retain the above copyright notice.
  15. *
  16. * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  17. * @link http://cakephp.org CakePHP(tm) Project
  18. * @package cake
  19. * @subpackage cake.cake.libs
  20. * @since CakePHP(tm) v 0.2.9
  21. * @version $Revision$
  22. * @modifiedby $LastChangedBy$
  23. * @lastmodified $Date$
  24. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  25. */
  26. /**
  27. * Included libraries.
  28. *
  29. */
  30. if (!class_exists('Object')) {
  31. uses('object');
  32. }
  33. /**
  34. * Text-to-HTML parser.
  35. *
  36. * Text-to-html parser, similar to Textile or RedCloth, only with a little different syntax.
  37. *
  38. * @package cake
  39. * @subpackage cake.cake.libs
  40. */
  41. class Flay extends Object{
  42. /**
  43. * Text to be parsed.
  44. *
  45. * @var string
  46. * @access public
  47. */
  48. var $text = null;
  49. /**
  50. * Set this to allow HTML in the markup.
  51. *
  52. * @var boolean
  53. * @access public
  54. */
  55. var $allow_html = false;
  56. /**
  57. * Constructor.
  58. *
  59. * @param string $text Text to transform
  60. */
  61. function __construct($text = null) {
  62. $this->text = $text;
  63. parent::__construct();
  64. }
  65. /**
  66. * Returns given text translated to HTML using the Flay syntax.
  67. *
  68. * @param string $text String to format
  69. * @param boolean $bare Set this to only do <p> transforms and > to &gt;, no typography additions.
  70. * @param boolean $allowHtml Set this to trim whitespace and disable all HTML
  71. * @return string Formatted text
  72. * @access public
  73. */
  74. function toHtml($text = null, $bare = false, $allowHtml = false) {
  75. if (empty($text) && empty($this->text)) {
  76. return false;
  77. }
  78. $text = $text ? $text : $this->text;
  79. // trim whitespace and disable all HTML
  80. if ($allowHtml) {
  81. $text = trim($text);
  82. } else {
  83. $text = str_replace('<', '&lt;', str_replace('>', '&gt;', trim($text)));
  84. }
  85. if (!$bare) {
  86. // multi-paragraph functions
  87. $text=preg_replace('#(?:[\n]{0,2})"""(.*)"""(?:[\n]{0,2})#s', "\n\n%BLOCKQUOTE%\n\n\\1\n\n%ENDBLOCKQUOTE%\n\n", $text);
  88. $text=preg_replace('#(?:[\n]{0,2})===(.*)===(?:[\n]{0,2})#s', "\n\n%CENTER%\n\n\\1\n\n%ENDCENTER%\n\n", $text);
  89. }
  90. // pre-parse newlines
  91. $text=preg_replace("#\r\n#", "\n", $text);
  92. $text=preg_replace("#[\n]{2,}#", "%PARAGRAPH%", $text);
  93. $text=preg_replace('#[\n]{1}#', "%LINEBREAK%", $text);
  94. $out ='';
  95. foreach (split('%PARAGRAPH%', $text)as $line) {
  96. if ($line) {
  97. if (!$bare) {
  98. $links = array();
  99. $regs = null;
  100. if (preg_match_all('#\[([^\[]{4,})\]#', $line, $regs)) {
  101. foreach ($regs[1] as $reg) {
  102. $links[] = $reg;
  103. $line = str_replace("[{$reg}]", '%LINK' . (count($links) - 1) . '%', $line);
  104. }
  105. }
  106. // bold
  107. $line = ereg_replace("\*([^\*]*)\*", "<strong>\\1</strong>", $line);
  108. // italic
  109. $line = ereg_replace("_([^_]*)_", "<em>\\1</em>", $line);
  110. }
  111. // entities
  112. $line = str_replace(' - ', ' &ndash; ', $line);
  113. $line = str_replace(' -- ', ' &mdash; ', $line);
  114. $line = str_replace('(C)', '&copy;', $line);
  115. $line = str_replace('(R)', '&reg;', $line);
  116. $line = str_replace('(TM)', '&trade;', $line);
  117. // guess e-mails
  118. $emails = null;
  119. if (preg_match_all("#([_A-Za-z0-9+-+]+(?:\.[_A-Za-z0-9+-]+)*@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*)#", $line, $emails)) {
  120. foreach ($emails[1] as $email) {
  121. $line = str_replace($email, "<a href=\"mailto:{$email}\">{$email}</a>", $line);
  122. }
  123. }
  124. if (!$bare) {
  125. $urls = null;
  126. if (preg_match_all("#((?:http|https|ftp|nntp)://[^ ]+)#", $line, $urls)) {
  127. foreach ($urls[1] as $url) {
  128. $line = str_replace($url, "<a href=\"{$url}\">{$url}</a>", $line);
  129. }
  130. }
  131. if (preg_match_all("#(www\.[^\n\%\ ]+[^\n\%\,\.\ ])#", $line, $urls)) {
  132. foreach ($urls[1] as $url) {
  133. $line = str_replace($url, "<a href=\"http://{$url}\">{$url}</a>", $line);
  134. }
  135. }
  136. if ($count = count($links)) {
  137. for ($ii = 0; $ii < $count; $ii++) {
  138. if (preg_match("#^(http|https|ftp|nntp)://#", $links[$ii])) {
  139. $prefix = null;
  140. } else {
  141. $prefix = 'http://';
  142. }
  143. if (preg_match('#^[^\ ]+\.(jpg|jpeg|gif|png)$#', $links[$ii])) {
  144. $with = "<img src=\"{$prefix}{$links[$ii]}\" alt=\"\" />";
  145. } elseif (preg_match('#^([^\]\ ]+)(?:\ ([^\]]+))?$#', $links[$ii], $regs)) {
  146. if (isset($regs[2])) {
  147. if (preg_match('#\.(jpg|jpeg|gif|png)$#', $regs[2])) {
  148. $body = "<img src=\"{$prefix}{$regs[2]}\" alt=\"\" />";
  149. } else {
  150. $body = $regs[2];
  151. }
  152. } else {
  153. $body = $links[$ii];
  154. }
  155. $with = "<a href=\"{$prefix}{$regs[1]}\" target=\"_blank\">{$body}</a>";
  156. } else {
  157. $with = $prefix . $links[$ii];
  158. }
  159. $line = str_replace("%LINK{$ii}%", $with, $line);
  160. }
  161. }
  162. }
  163. $out .= str_replace('%LINEBREAK%', "<br />\n", "<p>{$line}</p>\n");
  164. }
  165. }
  166. if (!$bare) {
  167. $out = str_replace('<p>%BLOCKQUOTE%</p>', "<blockquote>", $out);
  168. $out = str_replace('<p>%ENDBLOCKQUOTE%</p>', "</blockquote>", $out);
  169. $out = str_replace('<p>%CENTER%</p>', "<center>", $out);
  170. $out = str_replace('<p>%ENDCENTER%</p>', "</center>", $out);
  171. }
  172. return $out;
  173. }
  174. /**
  175. * Return the words of the string as an array.
  176. *
  177. * @param string $string
  178. * @return array Array of words
  179. * @access public
  180. */
  181. function extractWords($string) {
  182. $split = preg_split('/[\s,\.:\/="!\(\)<>~\[\]]+/', $string);
  183. return $split;
  184. }
  185. /**
  186. * Return given string with words in array colorMarked, up to a number of times (defaults to 5).
  187. *
  188. * @param array $words Words to look for and markup
  189. * @param string $string String to look in
  190. * @param integer $max_snippets Max number of snippets to extract
  191. * @return string String with words marked
  192. * @see colorMark
  193. * @access public
  194. */
  195. function markedSnippets($words, $string, $max_snippets = 5) {
  196. $string = strip_tags($string);
  197. $snips = array();
  198. $rest = $string;
  199. foreach ($words as $word) {
  200. if (preg_match_all("/[\s,]+.{0,40}{$word}.{0,40}[\s,]+/i", $rest, $r)) {
  201. foreach ($r as $result) {
  202. $rest = str_replace($result, '', $rest);
  203. }
  204. $snips = array_merge($snips, $r[0]);
  205. }
  206. }
  207. if (count($snips) > $max_snippets) {
  208. $snips = array_slice($snips, 0, $max_snippets);
  209. }
  210. $joined = implode(' <b>...</b> ', $snips);
  211. $snips = $joined ? "<b>...</b> {$joined} <b>...</b>" : substr($string, 0, 80) . '<b>...</b>';
  212. return $this->colorMark($words, $snips);
  213. }
  214. /**
  215. * Returns string with EM elements with color classes added.
  216. *
  217. * @param array $words Array of words to be colorized
  218. * @param string $string Text in which the words might be found
  219. * @return string String with words colorized
  220. * @access public
  221. */
  222. function colorMark($words, $string) {
  223. $colors=array('yl', 'gr', 'rd', 'bl', 'fu', 'cy');
  224. $nextColorIndex = 0;
  225. foreach ($words as $word) {
  226. $string = preg_replace("/({$word})/i", '<em class="' . $colors[$nextColorIndex % count($colors)] . "\">\\1</em>", $string);
  227. $nextColorIndex++;
  228. }
  229. return $string;
  230. }
  231. /**
  232. * Returns given text with tags stripped out.
  233. *
  234. * @param string $text Text to clean
  235. * @return string Cleaned text
  236. * @access public
  237. */
  238. function toClean($text) {
  239. $strip = strip_tags(html_entity_decode($text, ENT_QUOTES));
  240. return $strip;
  241. }
  242. /**
  243. * Return parsed text with tags stripped out.
  244. *
  245. * @param string $text Text to parse and clean
  246. * @return string Cleaned text
  247. * @access public
  248. */
  249. function toParsedAndClean($text) {
  250. return $this->toClean(Flay::toHtml($text));
  251. }
  252. /**
  253. * Return a fragment of a text, up to $length characters long, with an ellipsis after it.
  254. *
  255. * @param string $text Text to be truncated.
  256. * @param integer $length Max length of text.
  257. * @param string $ellipsis Sign to print after truncated text.
  258. * @return string Fragment
  259. * @access public
  260. */
  261. function fragment($text, $length, $ellipsis = '...') {
  262. $soft = $length - 5;
  263. $hard = $length + 5;
  264. $rx = '/(.{' . $soft . ',' . $hard . '})[\s,\.:\/="!\(\)<>~\[\]]+.*/';
  265. if (preg_match($rx, $text, $r)) {
  266. $out = $r[1];
  267. } else {
  268. $out = substr($text, 0, $length);
  269. }
  270. $out = $out . (strlen($out) < strlen($text) ? $ellipsis : null);
  271. return $out;
  272. }
  273. }
  274. ?>