flay.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: flay_8php-source.html 675 2008-12-26 00:27:14Z 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: 675 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-12-25 16:27:14 -0800 (Thu, 25 Dec 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  */
00050     var $text = null;
00051 /**
00052  * Set this to allow HTML in the markup.
00053  *
00054  * @var boolean
00055  */
00056     var $allow_html = false;
00057 /**
00058  * Constructor.
00059  *
00060  * @param string $text
00061  */
00062     function __construct($text = null) {
00063         $this->text = $text;
00064         parent::__construct();
00065     }
00066 /**
00067  * Returns given text translated to HTML using the Flay syntax.
00068  *
00069  * @param string $text String to format
00070  * @param boolean $bare Set this to only do <p> transforms and > to &gt;, no typography additions.
00071  * @param boolean $allowHtml Set this to trim whitespace and disable all HTML
00072  * @return string Formatted text
00073  */
00074     function toHtml($text = null, $bare = false, $allowHtml = false) {
00075         if (empty($text) && empty($this->text)) {
00076             return false;
00077         }
00078         $text = $text ? $text : $this->text;
00079         // trim whitespace and disable all HTML
00080         if ($allowHtml) {
00081             $text = trim($text);
00082         } else {
00083             $text = str_replace('<', '&lt;', str_replace('>', '&gt;', trim($text)));
00084         }
00085 
00086         if (!$bare) {
00087             // multi-paragraph functions
00088             $text=preg_replace('#(?:[\n]{0,2})"""(.*)"""(?:[\n]{0,2})#s', "\n\n%BLOCKQUOTE%\n\n\\1\n\n%ENDBLOCKQUOTE%\n\n", $text);
00089             $text=preg_replace('#(?:[\n]{0,2})===(.*)===(?:[\n]{0,2})#s', "\n\n%CENTER%\n\n\\1\n\n%ENDCENTER%\n\n", $text);
00090         }
00091 
00092         // pre-parse newlines
00093         $text=preg_replace("#\r\n#", "\n", $text);
00094         $text=preg_replace("#[\n]{2,}#", "%PARAGRAPH%", $text);
00095         $text=preg_replace('#[\n]{1}#', "%LINEBREAK%", $text);
00096         $out ='';
00097 
00098         foreach (split('%PARAGRAPH%', $text)as $line) {
00099             if ($line) {
00100                 if (!$bare) {
00101                     $links = array();
00102                     $regs = null;
00103 
00104                     if (preg_match_all('#\[([^\[]{4,})\]#', $line, $regs)) {
00105                         foreach ($regs[1] as $reg) {
00106                             $links[] = $reg;
00107                             $line = str_replace("[{$reg}]", '%LINK' . (count($links) - 1) . '%', $line);
00108                         }
00109                     }
00110                     // bold
00111                     $line = ereg_replace("\*([^\*]*)\*", "<strong>\\1</strong>", $line);
00112                     // italic
00113                     $line = ereg_replace("_([^_]*)_", "<em>\\1</em>", $line);
00114                 }
00115                 // entities
00116                 $line = str_replace(' - ', ' &ndash; ', $line);
00117                 $line = str_replace(' -- ', ' &mdash; ', $line);
00118                 $line = str_replace('(C)', '&copy;', $line);
00119                 $line = str_replace('(R)', '&reg;', $line);
00120                 $line = str_replace('(TM)', '&trade;', $line);
00121                 // guess e-mails
00122                 $emails = null;
00123                 if (preg_match_all("#([_A-Za-z0-9+-+]+(?:\.[_A-Za-z0-9+-]+)*@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*)#", $line, $emails)) {
00124                     foreach ($emails[1] as $email) {
00125                         $line = str_replace($email, "<a href=\"mailto:{$email}\">{$email}</a>", $line);
00126                     }
00127                 }
00128 
00129                 if (!$bare) {
00130                     $urls = null;
00131                     if (preg_match_all("#((?:http|https|ftp|nntp)://[^ ]+)#", $line, $urls)) {
00132                         foreach ($urls[1] as $url) {
00133                             $line = str_replace($url, "<a href=\"{$url}\">{$url}</a>", $line);
00134                         }
00135                     }
00136 
00137                     if (preg_match_all("#(www\.[^\n\%\ ]+[^\n\%\,\.\ ])#", $line, $urls)) {
00138                         foreach ($urls[1] as $url) {
00139                             $line = str_replace($url, "<a href=\"http://{$url}\">{$url}</a>", $line);
00140                         }
00141                     }
00142 
00143                     if (count($links)) {
00144                         for ($ii = 0; $ii < count($links); $ii++) {
00145                             if (preg_match("#^(http|https|ftp|nntp)://#", $links[$ii])) {
00146                                 $prefix = null;
00147                             } else {
00148                                 $prefix = 'http://';
00149                             }
00150                             if (preg_match('#^[^\ ]+\.(jpg|jpeg|gif|png)$#', $links[$ii])) {
00151                                 $with = "<img src=\"{$prefix}{$links[$ii]}\" alt=\"\" />";
00152                             } elseif (preg_match('#^([^\]\ ]+)(?:\ ([^\]]+))?$#', $links[$ii], $regs)) {
00153                                 if (isset($regs[2])) {
00154                                     if (preg_match('#\.(jpg|jpeg|gif|png)$#', $regs[2])) {
00155                                         $body = "<img src=\"{$prefix}{$regs[2]}\" alt=\"\" />";
00156                                     } else {
00157                                         $body = $regs[2];
00158                                     }
00159                                 } else {
00160                                     $body = $links[$ii];
00161                                 }
00162                                 $with = "<a href=\"{$prefix}{$regs[1]}\" target=\"_blank\">{$body}</a>";
00163                             } else {
00164                                 $with = $prefix . $links[$ii];
00165                             }
00166                             $line = str_replace("%LINK{$ii}%", $with, $line);
00167                         }
00168                     }
00169                 }
00170                 $out .= str_replace('%LINEBREAK%', "<br />\n", "<p>{$line}</p>\n");
00171             }
00172         }
00173 
00174         if (!$bare) {
00175             $out = str_replace('<p>%BLOCKQUOTE%</p>', "<blockquote>", $out);
00176             $out = str_replace('<p>%ENDBLOCKQUOTE%</p>', "</blockquote>", $out);
00177             $out = str_replace('<p>%CENTER%</p>', "<center>", $out);
00178             $out = str_replace('<p>%ENDCENTER%</p>', "</center>", $out);
00179         }
00180         return $out;
00181     }
00182 /**
00183  * Return the words of the string as an array.
00184  *
00185  * @param string $string
00186  * @return array Array of words
00187  */
00188     function extractWords($string) {
00189         $split = preg_split('/[\s,\.:\/="!\(\)<>~\[\]]+/', $string);
00190         return $split;
00191      }
00192 /**
00193  * Return given string with words in array colorMarked, up to a number of times (defaults to 5).
00194  *
00195  * @param array $words          Words to look for and markup
00196  * @param string $string        String to look in
00197  * @param integer $max_snippets Max number of snippets to extract
00198  * @return string
00199  * @see colorMark
00200  */
00201     function markedSnippets($words, $string, $max_snippets = 5) {
00202         $string = strip_tags($string);
00203         $snips = array();
00204         $rest = $string;
00205         foreach ($words as $word) {
00206             if (preg_match_all("/[\s,]+.{0,40}{$word}.{0,40}[\s,]+/i", $rest, $r)) {
00207                 foreach ($r as $result) {
00208                     $rest = str_replace($result, '', $rest);
00209                 }
00210                 $snips = array_merge($snips, $r[0]);
00211             }
00212         }
00213 
00214         if (count($snips) > $max_snippets) {
00215             $snips = array_slice($snips, 0, $max_snippets);
00216         }
00217         $joined = join(' <b>...</b> ', $snips);
00218         $snips = $joined ? "<b>...</b> {$joined} <b>...</b>" : substr($string, 0, 80) . '<b>...</b>';
00219         return $this->colorMark($words, $snips);
00220     }
00221 /**
00222  * Returns string with EM elements with color classes added.
00223  *
00224  * @param array $words Array of words to be colorized
00225  * @param string $string Text in which the words might be found
00226  * @return string
00227  */
00228     function colorMark($words, $string) {
00229         $colors=array('yl', 'gr', 'rd', 'bl', 'fu', 'cy');
00230         $nextColorIndex = 0;
00231         foreach ($words as $word) {
00232             $string = preg_replace("/({$word})/i", '<em class="' . $colors[$nextColorIndex % count($colors)] . "\">\\1</em>", $string);
00233             $nextColorIndex++;
00234         }
00235         return $string;
00236     }
00237 /**
00238  * Returns given text with tags stripped out.
00239  *
00240  * @param string $text
00241  * @return string
00242  */
00243     function toClean($text) {
00244         $strip = strip_tags(html_entity_decode($text, ENT_QUOTES));
00245         return $strip;
00246     }
00247 /**
00248  * Return parsed text with tags stripped out.
00249  *
00250  * @param string $text
00251  * @return string
00252  */
00253     function toParsedAndClean($text) {
00254         return $this->toClean(Flay::toHtml($text));
00255     }
00256 /**
00257  * Return a fragment of a text, up to $length characters long, with an ellipsis after it.
00258  *
00259  * @param string $text      Text to be truncated.
00260  * @param integer $length   Max length of text.
00261  * @param string $ellipsis  Sign to print after truncated text.
00262  * @return string
00263  */
00264     function fragment($text, $length, $ellipsis = '...') {
00265         $soft = $length - 5;
00266         $hard = $length + 5;
00267         $rx = '/(.{' . $soft . ',' . $hard . '})[\s,\.:\/="!\(\)<>~\[\]]+.*/';
00268 
00269         if (preg_match($rx, $text, $r)) {
00270             $out = $r[1];
00271         } else {
00272             $out = substr($text, 0, $length);
00273         }
00274         $out = $out . (strlen($out) < strlen($text) ? $ellipsis : null);
00275         return $out;
00276     }
00277 }
00278 ?>