blob: 30cec31489c153c384f1f31196e88c45dfe78665 [file] [log] [blame]
Derek Allard3d879d52008-01-18 19:41:32 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author ExpressionEngine Dev Team
9 * @copyright Copyright (c) 2006, EllisLab, Inc.
Derek Jones7a9193a2008-01-21 18:39:20 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
Derek Allard3d879d52008-01-18 19:41:32 +000012 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * CodeIgniter Text Helpers
20 *
21 * @package CodeIgniter
22 * @subpackage Helpers
23 * @category Helpers
24 * @author ExpressionEngine Dev Team
Derek Jones7a9193a2008-01-21 18:39:20 +000025 * @link http://codeigniter.com/user_guide/helpers/text_helper.html
Derek Allard3d879d52008-01-18 19:41:32 +000026 */
27
28// ------------------------------------------------------------------------
29
30/**
31 * Word Limiter
32 *
33 * Limits a string to X number of words.
34 *
35 * @access public
36 * @param string
37 * @param integer
38 * @param string the end character. Usually an ellipsis
39 * @return string
40 */
Derek Jones269b9422008-01-28 21:00:20 +000041if (! function_exists('word_limiter'))
Derek Allard3d879d52008-01-18 19:41:32 +000042{
Derek Jones269b9422008-01-28 21:00:20 +000043 function word_limiter($str, $n = 100, $end_char = '&#8230;')
Derek Allard3d879d52008-01-18 19:41:32 +000044 {
Derek Jones269b9422008-01-28 21:00:20 +000045 if (strlen($str) < $n)
46 {
47 return $str;
48 }
Derek Allard3d879d52008-01-18 19:41:32 +000049
Derek Jones269b9422008-01-28 21:00:20 +000050 $words = explode(' ', preg_replace("/\s+/", ' ', preg_replace("/(\r\n|\r|\n)/", " ", $str)));
Derek Allard3d879d52008-01-18 19:41:32 +000051
Derek Jones269b9422008-01-28 21:00:20 +000052 if (count($words) <= $n)
53 {
54 return $str;
55 }
Derek Allard3d879d52008-01-18 19:41:32 +000056
Derek Jones269b9422008-01-28 21:00:20 +000057 $str = '';
58 for ($i = 0; $i < $n; $i++)
59 {
60 $str .= $words[$i].' ';
61 }
Derek Allard3d879d52008-01-18 19:41:32 +000062
Derek Jones269b9422008-01-28 21:00:20 +000063 return trim($str).$end_char;
64 }
Derek Allard3d879d52008-01-18 19:41:32 +000065}
66
67// ------------------------------------------------------------------------
68
69/**
70 * Character Limiter
71 *
72 * Limits the string based on the character count. Preserves complete words
73 * so the character count may not be exactly as specified.
74 *
75 * @access public
76 * @param string
77 * @param integer
78 * @param string the end character. Usually an ellipsis
79 * @return string
80 */
Derek Jones269b9422008-01-28 21:00:20 +000081if (! function_exists('character_limiter'))
Derek Allard3d879d52008-01-18 19:41:32 +000082{
Derek Jones269b9422008-01-28 21:00:20 +000083 function character_limiter($str, $n = 500, $end_char = '&#8230;')
Derek Allard3d879d52008-01-18 19:41:32 +000084 {
Derek Jones269b9422008-01-28 21:00:20 +000085 if (strlen($str) < $n)
Derek Allard3d879d52008-01-18 19:41:32 +000086 {
Derek Jones269b9422008-01-28 21:00:20 +000087 return $str;
88 }
89
90 $str = preg_replace("/\s+/", ' ', preg_replace("/(\r\n|\r|\n)/", " ", $str));
91
92 if (strlen($str) <= $n)
93 {
94 return $str;
95 }
96
97 $out = "";
98 foreach (explode(' ', trim($str)) as $val)
99 {
100 $out .= $val.' ';
101 if (strlen($out) >= $n)
102 {
103 return trim($out).$end_char;
104 }
105 }
Derek Allard3d879d52008-01-18 19:41:32 +0000106 }
107}
108
109// ------------------------------------------------------------------------
110
111/**
112 * High ASCII to Entities
113 *
114 * Converts High ascii text and MS Word special characters to character entities
115 *
116 * @access public
117 * @param string
118 * @return string
119 */
Derek Jones269b9422008-01-28 21:00:20 +0000120if (! function_exists('ascii_to_entities'))
Derek Allard3d879d52008-01-18 19:41:32 +0000121{
Derek Jones269b9422008-01-28 21:00:20 +0000122 function ascii_to_entities($str)
123 {
124 $count = 1;
125 $out = '';
126 $temp = array();
Derek Allard3d879d52008-01-18 19:41:32 +0000127
Derek Jones269b9422008-01-28 21:00:20 +0000128 for ($i = 0, $s = strlen($str); $i < $s; $i++)
129 {
130 $ordinal = ord($str[$i]);
Derek Allard3d879d52008-01-18 19:41:32 +0000131
Derek Jones269b9422008-01-28 21:00:20 +0000132 if ($ordinal < 128)
Derek Allard3d879d52008-01-18 19:41:32 +0000133 {
Derek Jones269b9422008-01-28 21:00:20 +0000134 $out .= $str[$i];
Derek Allard3d879d52008-01-18 19:41:32 +0000135 }
Derek Jones269b9422008-01-28 21:00:20 +0000136 else
Derek Allard3d879d52008-01-18 19:41:32 +0000137 {
Derek Jones269b9422008-01-28 21:00:20 +0000138 if (count($temp) == 0)
139 {
140 $count = ($ordinal < 224) ? 2 : 3;
141 }
142
143 $temp[] = $ordinal;
144
145 if (count($temp) == $count)
146 {
147 $number = ($count == 3) ? (($temp['0'] % 16) * 4096) + (($temp['1'] % 64) * 64) + ($temp['2'] % 64) : (($temp['0'] % 32) * 64) + ($temp['1'] % 64);
Derek Allard3d879d52008-01-18 19:41:32 +0000148
Derek Jones269b9422008-01-28 21:00:20 +0000149 $out .= '&#'.$number.';';
150 $count = 1;
151 $temp = array();
152 }
Derek Allard3d879d52008-01-18 19:41:32 +0000153 }
154 }
Derek Allard3d879d52008-01-18 19:41:32 +0000155
Derek Jones269b9422008-01-28 21:00:20 +0000156 return $out;
157 }
Derek Allard3d879d52008-01-18 19:41:32 +0000158}
159
160// ------------------------------------------------------------------------
161
162/**
163 * Entities to ASCII
164 *
165 * Converts character entities back to ASCII
166 *
167 * @access public
168 * @param string
169 * @param bool
170 * @return string
171 */
Derek Jones269b9422008-01-28 21:00:20 +0000172if (! function_exists('entities_to_ascii'))
Derek Allard3d879d52008-01-18 19:41:32 +0000173{
Derek Jones269b9422008-01-28 21:00:20 +0000174 function entities_to_ascii($str, $all = TRUE)
175 {
176 if (preg_match_all('/\&#(\d+)\;/', $str, $matches))
177 {
178 for ($i = 0, $s = count($matches['0']); $i < $s; $i++)
179 {
180 $digits = $matches['1'][$i];
Derek Allard3d879d52008-01-18 19:41:32 +0000181
Derek Jones269b9422008-01-28 21:00:20 +0000182 $out = '';
Derek Allard3d879d52008-01-18 19:41:32 +0000183
Derek Jones269b9422008-01-28 21:00:20 +0000184 if ($digits < 128)
185 {
186 $out .= chr($digits);
Derek Allard3d879d52008-01-18 19:41:32 +0000187
Derek Jones269b9422008-01-28 21:00:20 +0000188 }
189 elseif ($digits < 2048)
190 {
191 $out .= chr(192 + (($digits - ($digits % 64)) / 64));
192 $out .= chr(128 + ($digits % 64));
193 }
194 else
195 {
196 $out .= chr(224 + (($digits - ($digits % 4096)) / 4096));
197 $out .= chr(128 + ((($digits % 4096) - ($digits % 64)) / 64));
198 $out .= chr(128 + ($digits % 64));
199 }
Derek Allard3d879d52008-01-18 19:41:32 +0000200
Derek Jones269b9422008-01-28 21:00:20 +0000201 $str = str_replace($matches['0'][$i], $out, $str);
202 }
Derek Allard3d879d52008-01-18 19:41:32 +0000203 }
Derek Allard3d879d52008-01-18 19:41:32 +0000204
Derek Jones269b9422008-01-28 21:00:20 +0000205 if ($all)
206 {
207 $str = str_replace(array("&amp;", "&lt;", "&gt;", "&quot;", "&apos;", "&#45;"),
208 array("&","<",">","\"", "'", "-"),
209 $str);
210 }
Derek Allard3d879d52008-01-18 19:41:32 +0000211
Derek Jones269b9422008-01-28 21:00:20 +0000212 return $str;
213 }
Derek Allard3d879d52008-01-18 19:41:32 +0000214}
215
216// ------------------------------------------------------------------------
217
218/**
219 * Word Censoring Function
220 *
221 * Supply a string and an array of disallowed words and any
222 * matched words will be converted to #### or to the replacement
223 * word you've submitted.
224 *
225 * @access public
226 * @param string the text string
227 * @param string the array of censoered words
228 * @param string the optional replacement value
229 * @return string
230 */
Derek Jones269b9422008-01-28 21:00:20 +0000231if (! function_exists('word_censor'))
Derek Allard3d879d52008-01-18 19:41:32 +0000232{
Derek Jones269b9422008-01-28 21:00:20 +0000233 function word_censor($str, $censored, $replacement = '')
Derek Allard3d879d52008-01-18 19:41:32 +0000234 {
Derek Jones269b9422008-01-28 21:00:20 +0000235 if ( ! is_array($censored))
236 {
237 return $str;
238 }
Derek Allard3d879d52008-01-18 19:41:32 +0000239
Derek Jones269b9422008-01-28 21:00:20 +0000240 $str = ' '.$str.' ';
241 foreach ($censored as $badword)
Derek Allard3d879d52008-01-18 19:41:32 +0000242 {
Derek Jones269b9422008-01-28 21:00:20 +0000243 if ($replacement != '')
244 {
245 $str = preg_replace("/\b(".str_replace('\*', '\w*?', preg_quote($badword)).")\b/i", $replacement, $str);
246 }
247 else
248 {
249 $str = preg_replace("/\b(".str_replace('\*', '\w*?', preg_quote($badword)).")\b/ie", "str_repeat('#', strlen('\\1'))", $str);
250 }
Derek Allard3d879d52008-01-18 19:41:32 +0000251 }
Derek Allard3d879d52008-01-18 19:41:32 +0000252
Derek Jones269b9422008-01-28 21:00:20 +0000253 return trim($str);
254 }
Derek Allard3d879d52008-01-18 19:41:32 +0000255}
256
257// ------------------------------------------------------------------------
258
259/**
260 * Code Highlighter
261 *
262 * Colorizes code strings
263 *
264 * @access public
265 * @param string the text string
266 * @return string
267 */
Derek Jones269b9422008-01-28 21:00:20 +0000268if (! function_exists('highlight_code'))
269{
270 function highlight_code($str)
271 {
272 // The highlight string function encodes and highlights
273 // brackets so we need them to start raw
274 $str = str_replace(array('&lt;', '&gt;'), array('<', '>'), $str);
Derek Allard3d879d52008-01-18 19:41:32 +0000275
Derek Jones269b9422008-01-28 21:00:20 +0000276 // Replace any existing PHP tags to temporary markers so they don't accidentally
277 // break the string out of PHP, and thus, thwart the highlighting.
Derek Allard3d879d52008-01-18 19:41:32 +0000278
Derek Jones269b9422008-01-28 21:00:20 +0000279 $str = str_replace(array('<?', '?>', '<%', '%>', '\\', '</script>'),
280 array('phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'), $str);
Derek Jones9468f3e2008-01-22 19:19:27 +0000281
Derek Jones269b9422008-01-28 21:00:20 +0000282 // The highlight_string function requires that the text be surrounded
283 // by PHP tags. Since we don't know if A) the submitted text has PHP tags,
284 // or B) whether the PHP tags enclose the entire string, we will add our
285 // own PHP tags around the string along with some markers to make replacement easier later
Derek Allard3d879d52008-01-18 19:41:32 +0000286
Derek Jones269b9422008-01-28 21:00:20 +0000287 $str = '<?php tempstart'."\n".$str.'tempend ?>';
Derek Allard3d879d52008-01-18 19:41:32 +0000288
Derek Jones269b9422008-01-28 21:00:20 +0000289 // All the magic happens here, baby!
290 $str = highlight_string($str, TRUE);
Derek Allard3d879d52008-01-18 19:41:32 +0000291
Derek Jones269b9422008-01-28 21:00:20 +0000292 // Prior to PHP 5, the highlight function used icky font tags
293 // so we'll replace them with span tags.
294 if (abs(phpversion()) < 5)
295 {
296 $str = str_replace(array('<font ', '</font>'), array('<span ', '</span>'), $str);
297 $str = preg_replace('#color="(.*?)"#', 'style="color: \\1"', $str);
298 }
Derek Allard3d879d52008-01-18 19:41:32 +0000299
Derek Jones269b9422008-01-28 21:00:20 +0000300 // Remove our artificially added PHP
301 $str = preg_replace("#\<code\>.+?tempstart\<br />(?:\</span\>)?#is", "<code>\n", $str);
302 $str = preg_replace("#tempend.+#is", "</span>\n</code>", $str);
Derek Allard3d879d52008-01-18 19:41:32 +0000303
Derek Jones269b9422008-01-28 21:00:20 +0000304 // Replace our markers back to PHP tags.
305 $str = str_replace(array('phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'),
306 array('&lt;?', '?&gt;', '&lt;%', '%&gt;', '\\', '&lt;/script&gt;'), $str);
Derek Jones9468f3e2008-01-22 19:19:27 +0000307
Derek Jones269b9422008-01-28 21:00:20 +0000308 return $str;
309 }
Derek Allard3d879d52008-01-18 19:41:32 +0000310}
311
312// ------------------------------------------------------------------------
313
314/**
315 * Phrase Highlighter
316 *
317 * Highlights a phrase within a text string
318 *
319 * @access public
320 * @param string the text string
321 * @param string the phrase you'd like to highlight
322 * @param string the openging tag to precede the phrase with
323 * @param string the closing tag to end the phrase with
324 * @return string
325 */
Derek Jones269b9422008-01-28 21:00:20 +0000326if (! function_exists('highlight_phrase'))
Derek Allard3d879d52008-01-18 19:41:32 +0000327{
Derek Jones269b9422008-01-28 21:00:20 +0000328 function highlight_phrase($str, $phrase, $tag_open = '<strong>', $tag_close = '</strong>')
Derek Allard3d879d52008-01-18 19:41:32 +0000329 {
Derek Jones269b9422008-01-28 21:00:20 +0000330 if ($str == '')
331 {
332 return '';
333 }
Derek Allard3d879d52008-01-18 19:41:32 +0000334
Derek Jones269b9422008-01-28 21:00:20 +0000335 if ($phrase != '')
336 {
337 return preg_replace('/('.preg_quote($phrase, '/').')/i', $tag_open."\\1".$tag_close, $str);
338 }
Derek Allard3d879d52008-01-18 19:41:32 +0000339
Derek Jones269b9422008-01-28 21:00:20 +0000340 return $str;
341 }
Derek Allard3d879d52008-01-18 19:41:32 +0000342}
343
344// ------------------------------------------------------------------------
345
346/**
347 * Word Wrap
348 *
349 * Wraps text at the specified character. Maintains the integrity of words.
350 * Anything placed between {unwrap}{/unwrap} will not be word wrapped, nor
351 * will URLs.
352 *
353 * @access public
354 * @param string the text string
355 * @param integer the number of characters to wrap at
356 * @return string
357 */
Derek Jones269b9422008-01-28 21:00:20 +0000358if (! function_exists('word_wrap'))
Derek Allard3d879d52008-01-18 19:41:32 +0000359{
Derek Jones269b9422008-01-28 21:00:20 +0000360 function word_wrap($str, $charlim = '76')
Derek Allard3d879d52008-01-18 19:41:32 +0000361 {
Derek Jones269b9422008-01-28 21:00:20 +0000362 // Se the character limit
363 if ( ! is_numeric($charlim))
364 $charlim = 76;
Derek Allard3d879d52008-01-18 19:41:32 +0000365
Derek Jones269b9422008-01-28 21:00:20 +0000366 // Reduce multiple spaces
367 $str = preg_replace("| +|", " ", $str);
Derek Allard3d879d52008-01-18 19:41:32 +0000368
Derek Jones269b9422008-01-28 21:00:20 +0000369 // Standardize newlines
370 $str = preg_replace("/\r\n|\r/", "\n", $str);
371
372 // If the current word is surrounded by {unwrap} tags we'll
373 // strip the entire chunk and replace it with a marker.
374 $unwrap = array();
375 if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches))
Derek Allard3d879d52008-01-18 19:41:32 +0000376 {
Derek Jones269b9422008-01-28 21:00:20 +0000377 for ($i = 0; $i < count($matches['0']); $i++)
Derek Allard3d879d52008-01-18 19:41:32 +0000378 {
Derek Jones269b9422008-01-28 21:00:20 +0000379 $unwrap[] = $matches['1'][$i];
380 $str = str_replace($matches['1'][$i], "{{unwrapped".$i."}}", $str);
381 }
382 }
383
384 // Use PHP's native function to do the initial wordwrap.
385 // We set the cut flag to FALSE so that any individual words that are
386 // too long get left alone. In the next step we'll deal with them.
387 $str = wordwrap($str, $charlim, "\n", FALSE);
388
389 // Split the string into individual lines of text and cycle through them
390 $output = "";
391 foreach (explode("\n", $str) as $line)
392 {
393 // Is the line within the allowed character count?
394 // If so we'll join it to the output and continue
395 if (strlen($line) <= $charlim)
396 {
397 $output .= $line."\n";
398 continue;
399 }
400
401 $temp = '';
402 while((strlen($line)) > $charlim)
403 {
404 // If the over-length word is a URL we won't wrap it
405 if (preg_match("!\[url.+\]|://|wwww.!", $line))
406 {
407 break;
408 }
409
410 // Trim the word down
411 $temp .= substr($line, 0, $charlim-1);
412 $line = substr($line, $charlim-1);
413 }
414
415 // If $temp contains data it means we had to split up an over-length
416 // word into smaller chunks so we'll add it back to our current line
417 if ($temp != '')
418 {
419 $output .= $temp . "\n" . $line;
420 }
421 else
422 {
423 $output .= $line;
Derek Allard3d879d52008-01-18 19:41:32 +0000424 }
425
Derek Jones269b9422008-01-28 21:00:20 +0000426 $output .= "\n";
Derek Allard3d879d52008-01-18 19:41:32 +0000427 }
428
Derek Jones269b9422008-01-28 21:00:20 +0000429 // Put our markers back
430 if (count($unwrap) > 0)
431 {
432 foreach ($unwrap as $key => $val)
433 {
434 $output = str_replace("{{unwrapped".$key."}}", $val, $output);
435 }
436 }
437
438 // Remove the unwrap tags
439 $output = str_replace(array('{unwrap}', '{/unwrap}'), '', $output);
440
441 return $output;
Derek Allard3d879d52008-01-18 19:41:32 +0000442 }
Derek Allard3d879d52008-01-18 19:41:32 +0000443}
Derek Allard3d879d52008-01-18 19:41:32 +0000444
445?>