text.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: text.php 8241 2009-07-21 20:57:39Z DarkAngelBGE $ */
00003 /**
00004  * Text Helper
00005  *
00006  * Text manipulations: Highlight, excerpt, truncate, strip of links, convert email addresses to mailto: links...
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. (http://www.cakefoundation.org)
00012  *
00013  * Licensed under The MIT License
00014  * Redistributions of files must retain the above copyright notice.
00015  *
00016  * @filesource
00017  * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
00018  * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00019  * @package       cake
00020  * @subpackage    cake.cake.libs.view.helpers
00021  * @since         CakePHP(tm) v 0.10.0.1076
00022  * @version       $Revision: 8241 $
00023  * @modifiedby    $LastChangedBy: DarkAngelBGE $
00024  * @lastmodified  $Date: 2009-07-21 16:57:39 -0400 (Tue, 21 Jul 2009) $
00025  * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
00026  */
00027 /**
00028  * Included libraries.
00029  *
00030  */
00031 if (!class_exists('HtmlHelper')) {
00032     App::import('Helper', 'Html');
00033 }
00034 if (!class_exists('Multibyte')) {
00035     App::import('Core', 'Multibyte');
00036 }
00037 /**
00038  * Text helper library.
00039  *
00040  * Text manipulations: Highlight, excerpt, truncate, strip of links, convert email addresses to mailto: links...
00041  *
00042  * @package       cake
00043  * @subpackage    cake.cake.libs.view.helpers
00044  */
00045 class TextHelper extends AppHelper {
00046 /**
00047  * Highlights a given phrase in a text. You can specify any expression in highlighter that
00048  * may include the \1 expression to include the $phrase found.
00049  *
00050  * @param string $text Text to search the phrase in
00051  * @param string $phrase The phrase that will be searched
00052  * @param string $highlighter The piece of html with that the phrase will be highlighted
00053  * @param boolean $considerHtml If true, will ignore any HTML tags, ensuring that only the correct text is highlighted
00054  * @return string The highlighted text
00055  * @access public
00056  */
00057     function highlight($text, $phrase, $highlighter = '<span class="highlight">\1</span>', $considerHtml = false) {
00058         if (empty($phrase)) {
00059             return $text;
00060         }
00061 
00062         if (is_array($phrase)) {
00063             $replace = array();
00064             $with = array();
00065 
00066             foreach ($phrase as $key => $value) {
00067                 $key = $value;
00068                 $value = $highlighter;
00069                 $key = '(' . $key . ')';
00070                 if ($considerHtml) {
00071                     $key = '(?![^<]+>)' . $key . '(?![^<]+>)';
00072                 }
00073                 $replace[] = '|' . $key . '|iu';
00074                 $with[] = empty($value) ? $highlighter : $value;
00075             }
00076 
00077             return preg_replace($replace, $with, $text);
00078         } else {
00079             $phrase = '(' . $phrase . ')';
00080             if ($considerHtml) {
00081                 $phrase = '(?![^<]+>)' . $phrase . '(?![^<]+>)';
00082             }
00083 
00084             return preg_replace('|'.$phrase.'|iu', $highlighter, $text);
00085         }
00086     }
00087 /**
00088  * Strips given text of all links (<a href=....)
00089  *
00090  * @param string $text Text
00091  * @return string The text without links
00092  * @access public
00093  */
00094     function stripLinks($text) {
00095         return preg_replace('|<a\s+[^>]+>|im', '', preg_replace('|<\/a>|im', '', $text));
00096     }
00097 /**
00098  * Adds links (<a href=....) to a given text, by finding text that begins with
00099  * strings like http:// and ftp://.
00100  *
00101  * @param string $text Text to add links to
00102  * @param array $htmlOptions Array of HTML options.
00103  * @return string The text with links
00104  * @access public
00105  */
00106     function autoLinkUrls($text, $htmlOptions = array()) {
00107         $options = 'array(';
00108         foreach ($htmlOptions as $option => $value) {
00109                 $value = var_export($value, true);
00110                 $options .= "'$option' => $value, ";
00111         }
00112         $options .= ')';
00113 
00114         $text = preg_replace_callback('#(?<!href="|">)((?:http|https|ftp|nntp)://[^ <]+)#i', create_function('$matches',
00115             '$Html = new HtmlHelper(); $Html->tags = $Html->loadConfig(); return $Html->link($matches[0], $matches[0],' . $options . ');'), $text);
00116 
00117         return preg_replace_callback('#(?<!href="|">)(?<!http://|https://|ftp://|nntp://)(www\.[^\n\%\ <]+[^<\n\%\,\.\ <])(?<!\))#i',
00118             create_function('$matches', '$Html = new HtmlHelper(); $Html->tags = $Html->loadConfig(); return $Html->link($matches[0], "http://" . strtolower($matches[0]),' . $options . ');'), $text);
00119     }
00120 /**
00121  * Adds email links (<a href="mailto:....) to a given text.
00122  *
00123  * @param string $text Text
00124  * @param array $htmlOptions Array of HTML options.
00125  * @return string The text with links
00126  * @access public
00127  */
00128     function autoLinkEmails($text, $htmlOptions = array()) {
00129         $options = 'array(';
00130 
00131         foreach ($htmlOptions as $option => $value) {
00132             $options .= "'$option' => '$value', ";
00133         }
00134         $options .= ')';
00135 
00136         return preg_replace_callback('#([_A-Za-z0-9+-]+(?:\.[_A-Za-z0-9+-]+)*@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*)#',
00137                         create_function('$matches', '$Html = new HtmlHelper(); $Html->tags = $Html->loadConfig(); return $Html->link($matches[0], "mailto:" . $matches[0],' . $options . ');'), $text);
00138     }
00139 /**
00140  * Convert all links and email adresses to HTML links.
00141  *
00142  * @param string $text Text
00143  * @param array $htmlOptions Array of HTML options.
00144  * @return string The text with links
00145  * @access public
00146  */
00147     function autoLink($text, $htmlOptions = array()) {
00148         return $this->autoLinkEmails($this->autoLinkUrls($text, $htmlOptions), $htmlOptions);
00149     }
00150 /**
00151  * Truncates text.
00152  *
00153  * Cuts a string to the length of $length and replaces the last characters
00154  * with the ending if the text is longer than length.
00155  *
00156  * @param string  $text String to truncate.
00157  * @param integer $length Length of returned string, including ellipsis.
00158  * @param mixed $ending If string, will be used as Ending and appended to the trimmed string. Can also be an associative array that can contain the last three params of this method.
00159  * @param boolean $exact If false, $text will not be cut mid-word
00160  * @param boolean $considerHtml If true, HTML tags would be handled correctly
00161  * @return string Trimmed string.
00162  */
00163     function truncate($text, $length = 100, $ending = '...', $exact = true, $considerHtml = false) {
00164         if (is_array($ending)) {
00165             extract($ending);
00166         }
00167         if ($considerHtml) {
00168             if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
00169                 return $text;
00170             }
00171             $totalLength = mb_strlen($ending);
00172             $openTags = array();
00173             $truncate = '';
00174             preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER);
00175             foreach ($tags as $tag) {
00176                 if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) {
00177                     if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) {
00178                         array_unshift($openTags, $tag[2]);
00179                     } else if (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) {
00180                         $pos = array_search($closeTag[1], $openTags);
00181                         if ($pos !== false) {
00182                             array_splice($openTags, $pos, 1);
00183                         }
00184                     }
00185                 }
00186                 $truncate .= $tag[1];
00187 
00188                 $contentLength = mb_strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3]));
00189                 if ($contentLength + $totalLength > $length) {
00190                     $left = $length - $totalLength;
00191                     $entitiesLength = 0;
00192                     if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE)) {
00193                         foreach ($entities[0] as $entity) {
00194                             if ($entity[1] + 1 - $entitiesLength <= $left) {
00195                                 $left--;
00196                                 $entitiesLength += mb_strlen($entity[0]);
00197                             } else {
00198                                 break;
00199                             }
00200                         }
00201                     }
00202 
00203                     $truncate .= mb_substr($tag[3], 0 , $left + $entitiesLength);
00204                     break;
00205                 } else {
00206                     $truncate .= $tag[3];
00207                     $totalLength += $contentLength;
00208                 }
00209                 if ($totalLength >= $length) {
00210                     break;
00211                 }
00212             }
00213 
00214         } else {
00215             if (mb_strlen($text) <= $length) {
00216                 return $text;
00217             } else {
00218                 $truncate = mb_substr($text, 0, $length - strlen($ending));
00219             }
00220         }
00221         if (!$exact) {
00222             $spacepos = mb_strrpos($truncate, ' ');
00223             if (isset($spacepos)) {
00224                 if ($considerHtml) {
00225                     $bits = mb_substr($truncate, $spacepos);
00226                     preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
00227                     if (!empty($droppedTags)) {
00228                         foreach ($droppedTags as $closingTag) {
00229                             if (!in_array($closingTag[1], $openTags)) {
00230                                 array_unshift($openTags, $closingTag[1]);
00231                             }
00232                         }
00233                     }
00234                 }
00235                 $truncate = mb_substr($truncate, 0, $spacepos);
00236             }
00237         }
00238 
00239         $truncate .= $ending;
00240 
00241         if ($considerHtml) {
00242             foreach ($openTags as $tag) {
00243                 $truncate .= '</'.$tag.'>';
00244             }
00245         }
00246 
00247         return $truncate;
00248     }
00249 /**
00250  * Alias for truncate().
00251  *
00252  * @see TextHelper::truncate()
00253  * @access public
00254  */
00255     function trim() {
00256         $args = func_get_args();
00257         return call_user_func_array(array(&$this, 'truncate'), $args);
00258     }
00259 /**
00260  * Extracts an excerpt from the text surrounding the phrase with a number of characters on each side determined by radius.
00261  *
00262  * @param string $text String to search the phrase in
00263  * @param string $phrase Phrase that will be searched for
00264  * @param integer $radius The amount of characters that will be returned on each side of the founded phrase
00265  * @param string $ending Ending that will be appended
00266  * @return string Modified string
00267  * @access public
00268  */
00269     function excerpt($text, $phrase, $radius = 100, $ending = "...") {
00270         if (empty($text) or empty($phrase)) {
00271             return $this->truncate($text, $radius * 2, $ending);
00272         }
00273 
00274         $phraseLen = strlen($phrase);
00275         if ($radius < $phraseLen) {
00276             $radius = $phraseLen;
00277         }
00278 
00279         $pos = strpos(strtolower($text), strtolower($phrase));
00280 
00281         $startPos = 0;
00282         if ($pos > $radius) {
00283             $startPos = $pos - $radius;
00284         }
00285 
00286         $textLen = strlen($text);
00287 
00288         $endPos = $pos + $phraseLen + $radius;
00289         if ($endPos >= $textLen) {
00290             $endPos = $textLen;
00291         }
00292 
00293         $excerpt = substr($text, $startPos, $endPos - $startPos);
00294         if ($startPos != 0) {
00295             $excerpt = substr_replace($excerpt, $ending, 0, $phraseLen);
00296         }
00297 
00298         if ($endPos != $textLen) {
00299             $excerpt = substr_replace($excerpt, $ending, -$phraseLen);
00300         }
00301 
00302         return $excerpt;
00303     }
00304 /**
00305  * Creates a comma separated list where the last two items are joined with 'and', forming natural English
00306  *
00307  * @param array $list The list to be joined
00308  * @return string
00309  * @access public
00310  */
00311     function toList($list, $and = 'and') {
00312         $r = '';
00313         $c = count($list) - 1;
00314         foreach ($list as $i => $item) {
00315             $r .= $item;
00316             if ($c > 0 && $i < $c)
00317             {
00318                 $r .= ($i < $c - 1 ? ', ' : " {$and} ");
00319             }
00320         }
00321         return $r;
00322     }
00323 /**
00324  * Text-to-html parser, similar to Textile or RedCloth, only with a little different syntax.
00325  *
00326  * @param string $text String to "flay"
00327  * @param boolean $allowHtml Set to true if if html is allowed
00328  * @return string "Flayed" text
00329  * @access public
00330  * @todo Change this. We need a real Textile parser.
00331  * @codeCoverageIgnoreStart
00332  */
00333     function flay($text, $allowHtml = false) {
00334         trigger_error(__('(TextHelper::flay) Deprecated: the Flay library is no longer supported and will be removed in a future version.', true), E_USER_WARNING);
00335         if (!class_exists('Flay')) {
00336             uses('flay');
00337         }
00338         return Flay::toHtml($text, false, $allowHtml);
00339     }
00340 /**
00341  * @codeCoverageIgnoreEnd
00342  */
00343 }
00344 ?>

Generated on Sun Nov 22 00:30:54 2009 for CakePHP 1.2.x.x (v1.2.4.8284) by doxygen 1.4.7