flay.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: flay_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 /**
00004  * Text-to-HTML parser.
00005  *
00006  * Text-to-html parser, similar to {@link http://textism.com/tools/textile/ Textile} or {@link http://www.whytheluckystiff.net/ruby/redcloth/ RedCloth}.
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00011  * Copyright 2005-2008, Cake Software Foundation, Inc.
00012  *                              1785 E. Sahara Avenue, Suite 490-204
00013  *                              Las Vegas, Nevada 89104
00014  *
00015  * Licensed under The MIT License
00016  * Redistributions of files must retain the above copyright notice.
00017  *
00018  * @filesource
00019  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00020  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00021  * @package         cake
00022  * @subpackage      cake.cake.libs
00023  * @since           CakePHP(tm) v 0.2.9
00024  * @version         $Revision: 580 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00027  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00028  */
00029 /**
00030  * Included libraries.
00031  *
00032  */
00033     if (!class_exists('Object')) {
00034          uses ('object');
00035     }
00036 /**
00037  * Text-to-HTML parser.
00038  *
00039  * Text-to-html parser, similar to Textile or RedCloth, only with a little different syntax.
00040  *
00041  * @package     cake
00042  * @subpackage  cake.cake.libs
00043  */
00044 class Flay extends Object{
00045 /**
00046  * Text to be parsed.
00047  *
00048  * @var string
00049  * @access public
00050  */
00051     var $text = null;
00052 /**
00053  * Set this to allow HTML in the markup.
00054  *
00055  * @var boolean
00056  * @access public
00057  */
00058     var $allow_html = false;
00059 /**
00060  * Constructor.
00061  *
00062  * @param string $text Text to transform
00063  */
00064     function __construct($text = null) {
00065         $this->text = $text;
00066         parent::__construct();
00067     }
00068 /**
00069  * Returns given text translated to HTML using the Flay syntax.
00070  *
00071  * @param string $text String to format
00072  * @param boolean $bare Set this to only do <p> transforms and > to &gt;, no typography additions.
00073  * @param boolean $allowHtml Set this to trim whitespace and disable all HTML
00074  * @return string Formatted text
00075  * @access public
00076  */
00077     function toHtml($text = null, $bare = false, $allowHtml = false) {
00078         if (empty($text) && empty($this->text)) {
00079             return false;
00080         }
00081         $text = $text ? $text : $this->text;
00082         // trim whitespace and disable all HTML
00083         if ($allowHtml) {
00084             $text = trim($text);
00085         } else {
00086             $text = str_replace('<', '&lt;', str_replace('>', '&gt;', trim($text)));
00087         }
00088 
00089         if (!$bare) {
00090             // multi-paragraph functions
00091             $text=preg_replace('#(?:[\n]{0,2})"""(.*)"""(?:[\n]{0,2})#s', "\n\n%BLOCKQUOTE%\n\n\\1\n\n%ENDBLOCKQUOTE%\n\n", $text);
00092             $text=preg_replace('#(?:[\n]{0,2})===(.*)===(?:[\n]{0,2})#s', "\n\n%CENTER%\n\n\\1\n\n%ENDCENTER%\n\n", $text);
00093         }
00094 
00095         // pre-parse newlines
00096         $text=preg_replace("#\r\n#", "\n", $text);
00097         $text=preg_replace("#[\n]{2,}#", "%PARAGRAPH%", $text);
00098         $text=preg_replace('#[\n]{1}#', "%LINEBREAK%", $text);
00099         $out ='';
00100 
00101         foreach (split('%PARAGRAPH%', $text)as $line) {
00102             if ($line) {
00103                 if (!$bare) {
00104                     $links = array();
00105                     $regs = null;
00106 
00107                     if (preg_match_all('#\[([^\[]{4,})\]#', $line, $regs)) {
00108                         foreach ($regs[1] as $reg) {
00109                             $links[] = $reg;
00110                             $line = str_replace("[{$reg}]", '%LINK' . (count($links) - 1) . '%', $line);
00111                         }
00112                     }
00113                     // bold
00114                     $line = ereg_replace("\*([^\*]*)\*", "<strong>\\1</strong>", $line);
00115                     // italic
00116                     $line = ereg_replace("_([^_]*)_", "<em>\\1</em>", $line);
00117                 }
00118                 // entities
00119                 $line = str_replace(' - ', ' &ndash; ', $line);
00120                 $line = str_replace(' -- ', ' &mdash; ', $line);
00121                 $line = str_replace('(C)', '&copy;', $line);
00122                 $line = str_replace('(R)', '&reg;', $line);
00123                 $line = str_replace('(TM)', '&trade;', $line);
00124                 // guess e-mails
00125                 $emails = null;
00126                 if (preg_match_all("#([_A-Za-z0-9+-+]+(?:\.[_A-Za-z0-9+-]+)*@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*)#", $line, $emails)) {
00127                     foreach ($emails[1] as $email) {
00128                         $line = str_replace($email, "<a href=\"mailto:{$email}\">{$email}</a>", $line);
00129                     }
00130                 }
00131 
00132                 if (!$bare) {
00133                     $urls = null;
00134                     if (preg_match_all("#((?:http|https|ftp|nntp)://[^ ]+)#", $line, $urls)) {
00135                         foreach ($urls[1] as $url) {
00136                             $line = str_replace($url, "<a href=\"{$url}\">{$url}</a>", $line);
00137                         }
00138                     }
00139 
00140                     if (preg_match_all("#(www\.[^\n\%\ ]+[^\n\%\,\.\ ])#", $line, $urls)) {
00141                         foreach ($urls[1] as $url) {
00142                             $line = str_replace($url, "<a href=\"http://{$url}\">{$url}</a>", $line);
00143                         }
00144                     }
00145 
00146                     if (count($links)) {
00147                         for ($ii = 0; $ii < count($links); $ii++) {
00148                             if (preg_match("#^(http|https|ftp|nntp)://#", $links[$ii])) {
00149                                 $prefix = null;
00150                             } else {
00151                                 $prefix = 'http://';
00152                             }
00153                             if (preg_match('#^[^\ ]+\.(jpg|jpeg|gif|png)$#', $links[$ii])) {
00154                                 $with = "<img src=\"{$prefix}{$links[$ii]}\" alt=\"\" />";
00155                             } elseif (preg_match('#^([^\]\ ]+)(?:\ ([^\]]+))?$#', $links[$ii], $regs)) {
00156                                 if (isset($regs[2])) {
00157                                     if (preg_match('#\.(jpg|jpeg|gif|png)$#', $regs[2])) {
00158                                         $body = "<img src=\"{$prefix}{$regs[2]}\" alt=\"\" />";
00159                                     } else {
00160                                         $body = $regs[2];
00161                                     }
00162                                 } else {
00163                                     $body = $links[$ii];
00164                                 }
00165                                 $with = "<a href=\"{$prefix}{$regs[1]}\" target=\"_blank\">{$body}</a>";
00166                             } else {
00167                                 $with = $prefix . $links[$ii];
00168                             }
00169                             $line = str_replace("%LINK{$ii}%", $with, $line);
00170                         }
00171                     }
00172                 }
00173                 $out .= str_replace('%LINEBREAK%', "<br />\n", "<p>{$line}</p>\n");
00174             }
00175         }
00176 
00177         if (!$bare) {
00178             $out = str_replace('<p>%BLOCKQUOTE%</p>', "<blockquote>", $out);
00179             $out = str_replace('<p>%ENDBLOCKQUOTE%</p>', "</blockquote>", $out);
00180             $out = str_replace('<p>%CENTER%</p>', "<center>", $out);
00181             $out = str_replace('<p>%ENDCENTER%</p>', "</center>", $out);
00182         }
00183         return $out;
00184     }
00185 /**
00186  * Return the words of the string as an array.
00187  *
00188  * @param string $string
00189  * @return array Array of words
00190  * @access public
00191  */
00192     function extractWords($string) {
00193         $split = preg_split('/[\s,\.:\/="!\(\)<>~\[\]]+/', $string);
00194         return $split;
00195      }
00196 /**
00197  * Return given string with words in array colorMarked, up to a number of times (defaults to 5).
00198  *
00199  * @param array $words          Words to look for and markup
00200  * @param string $string        String to look in
00201  * @param integer $max_snippets Max number of snippets to extract
00202  * @return string String with words marked
00203  * @see colorMark
00204  * @access public
00205  */
00206     function markedSnippets($words, $string, $max_snippets = 5) {
00207         $string = strip_tags($string);
00208         $snips = array();
00209         $rest = $string;
00210         foreach ($words as $word) {
00211             if (preg_match_all("/[\s,]+.{0,40}{$word}.{0,40}[\s,]+/i", $rest, $r)) {
00212                 foreach ($r as $result) {
00213                     $rest = str_replace($result, '', $rest);
00214                 }
00215                 $snips = array_merge($snips, $r[0]);
00216             }
00217         }
00218 
00219         if (count($snips) > $max_snippets) {
00220             $snips = array_slice($snips, 0, $max_snippets);
00221         }
00222         $joined = join(' <b>...</b> ', $snips);
00223         $snips = $joined ? "<b>...</b> {$joined} <b>...</b>" : substr($string, 0, 80) . '<b>...</b>';
00224         return $this->colorMark($words, $snips);
00225     }
00226 /**
00227  * Returns string with EM elements with color classes added.
00228  *
00229  * @param array $words Array of words to be colorized
00230  * @param string $string Text in which the words might be found
00231  * @return string String with words colorized
00232  * @access public
00233  */
00234     function colorMark($words, $string) {
00235         $colors=array('yl', 'gr', 'rd', 'bl', 'fu', 'cy');
00236         $nextColorIndex = 0;
00237         foreach ($words as $word) {
00238             $string = preg_replace("/({$word})/i", '<em class="' . $colors[$nextColorIndex % count($colors)] . "\">\\1</em>", $string);
00239             $nextColorIndex++;
00240         }
00241         return $string;
00242     }
00243 /**
00244  * Returns given text with tags stripped out.
00245  *
00246  * @param string $text Text to clean
00247  * @return string Cleaned text
00248  * @access public
00249  */
00250     function toClean($text) {
00251         $strip = strip_tags(html_entity_decode($text, ENT_QUOTES));
00252         return $strip;
00253     }
00254 /**
00255  * Return parsed text with tags stripped out.
00256  *
00257  * @param string $text Text to parse and clean
00258  * @return string Cleaned text
00259  * @access public
00260  */
00261     function toParsedAndClean($text) {
00262         return $this->toClean(Flay::toHtml($text));
00263     }
00264 /**
00265  * Return a fragment of a text, up to $length characters long, with an ellipsis after it.
00266  *
00267  * @param string $text      Text to be truncated.
00268  * @param integer $length   Max length of text.
00269  * @param string $ellipsis  Sign to print after truncated text.
00270  * @return string Fragment
00271  * @access public
00272  */
00273     function fragment($text, $length, $ellipsis = '...') {
00274         $soft = $length - 5;
00275         $hard = $length + 5;
00276         $rx = '/(.{' . $soft . ',' . $hard . '})[\s,\.:\/="!\(\)<>~\[\]]+.*/';
00277 
00278         if (preg_match($rx, $text, $r)) {
00279             $out = $r[1];
00280         } else {
00281             $out = substr($text, 0, $length);
00282         }
00283         $out = $out . (strlen($out) < strlen($text) ? $ellipsis : null);
00284         return $out;
00285     }
00286 }
00287 ?>