1: <?php
2: /**
3: * Text Helper
4: *
5: * Text manipulations: Highlight, excerpt, truncate, strip of links, convert email addresses to mailto: links...
6: *
7: * PHP 5
8: *
9: * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
10: * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
11: *
12: * Licensed under The MIT License
13: * Redistributions of files must retain the above copyright notice.
14: *
15: * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
16: * @link http://cakephp.org CakePHP(tm) Project
17: * @package Cake.View.Helper
18: * @since CakePHP(tm) v 0.10.0.1076
19: * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
20: */
21:
22: App::uses('AppHelper', 'View/Helper');
23:
24: /**
25: * Text helper library.
26: *
27: * Text manipulations: Highlight, excerpt, truncate, strip of links, convert email addresses to mailto: links...
28: *
29: * @package Cake.View.Helper
30: * @property HtmlHelper $Html
31: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html
32: * @see String
33: */
34: class TextHelper extends AppHelper {
35:
36: /**
37: * helpers
38: *
39: * @var array
40: */
41: public $helpers = array('Html');
42:
43: /**
44: * An array of md5sums and their contents.
45: * Used when inserting links into text.
46: *
47: * @var array
48: */
49: protected $_placeholders = array();
50:
51: /**
52: * String utility instance
53: */
54: protected $_engine;
55:
56: /**
57: * Constructor
58: *
59: * ### Settings:
60: *
61: * - `engine` Class name to use to replace String functionality.
62: * The class needs to be placed in the `Utility` directory.
63: *
64: * @param View $View the view object the helper is attached to.
65: * @param array $settings Settings array Settings array
66: * @throws CakeException when the engine class could not be found.
67: */
68: public function __construct(View $View, $settings = array()) {
69: $settings = Hash::merge(array('engine' => 'String'), $settings);
70: parent::__construct($View, $settings);
71: list($plugin, $engineClass) = pluginSplit($settings['engine'], true);
72: App::uses($engineClass, $plugin . 'Utility');
73: if (class_exists($engineClass)) {
74: $this->_engine = new $engineClass($settings);
75: } else {
76: throw new CakeException(__d('cake_dev', '%s could not be found', $engineClass));
77: }
78: }
79:
80: /**
81: * Call methods from String utility class
82: */
83: public function __call($method, $params) {
84: return call_user_func_array(array($this->_engine, $method), $params);
85: }
86:
87: /**
88: * Adds links (<a href=....) to a given text, by finding text that begins with
89: * strings like http:// and ftp://.
90: *
91: * ### Options
92: *
93: * - `escape` Control HTML escaping of input. Defaults to true.
94: *
95: * @param string $text Text
96: * @param array $options Array of HTML options, and options listed above.
97: * @return string The text with links
98: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::autoLinkUrls
99: */
100: public function autoLinkUrls($text, $options = array()) {
101: $this->_placeholders = array();
102: $options += array('escape' => true);
103:
104: $pattern = '#(?<!href="|src="|">)((?:https?|ftp|nntp)://[a-z0-9.\-:]+(?:/[^\s]*)?)#i';
105: $text = preg_replace_callback(
106: $pattern,
107: array(&$this, '_insertPlaceHolder'),
108: $text
109: );
110: $text = preg_replace_callback(
111: '#(?<!href="|">)(?<!\b[[:punct:]])(?<!http://|https://|ftp://|nntp://)www.[^\n\%\ <]+[^<\n\%\,\.\ <](?<!\))#i',
112: array(&$this, '_insertPlaceHolder'),
113: $text
114: );
115: if ($options['escape']) {
116: $text = h($text);
117: }
118: return $this->_linkUrls($text, $options);
119: }
120:
121: /**
122: * Saves the placeholder for a string, for later use. This gets around double
123: * escaping content in URL's.
124: *
125: * @param array $matches An array of regexp matches.
126: * @return string Replaced values.
127: */
128: protected function _insertPlaceHolder($matches) {
129: $key = md5($matches[0]);
130: $this->_placeholders[$key] = $matches[0];
131: return $key;
132: }
133:
134: /**
135: * Replace placeholders with links.
136: *
137: * @param string $text The text to operate on.
138: * @param array $htmlOptions The options for the generated links.
139: * @return string The text with links inserted.
140: */
141: protected function _linkUrls($text, $htmlOptions) {
142: $replace = array();
143: foreach ($this->_placeholders as $hash => $url) {
144: $link = $url;
145: if (!preg_match('#^[a-z]+\://#', $url)) {
146: $url = 'http://' . $url;
147: }
148: $replace[$hash] = $this->Html->link($link, $url, $htmlOptions);
149: }
150: return strtr($text, $replace);
151: }
152:
153: /**
154: * Links email addresses
155: *
156: * @param string $text The text to operate on
157: * @param array $options An array of options to use for the HTML.
158: * @return string
159: * @see TextHelper::autoLinkEmails()
160: */
161: protected function _linkEmails($text, $options) {
162: $replace = array();
163: foreach ($this->_placeholders as $hash => $url) {
164: $replace[$hash] = $this->Html->link($url, 'mailto:' . $url, $options);
165: }
166: return strtr($text, $replace);
167: }
168:
169: /**
170: * Adds email links (<a href="mailto:....) to a given text.
171: *
172: * ### Options
173: *
174: * - `escape` Control HTML escaping of input. Defaults to true.
175: *
176: * @param string $text Text
177: * @param array $options Array of HTML options, and options listed above.
178: * @return string The text with links
179: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::autoLinkEmails
180: */
181: public function autoLinkEmails($text, $options = array()) {
182: $options += array('escape' => true);
183: $this->_placeholders = array();
184:
185: $atom = '[a-z0-9!#$%&\'*+\/=?^_`{|}~-]';
186: $text = preg_replace_callback(
187: '/(' . $atom . '+(?:\.' . $atom . '+)*@[a-z0-9-]+(?:\.[a-z0-9-]+)+)/i',
188: array(&$this, '_insertPlaceholder'),
189: $text
190: );
191: if ($options['escape']) {
192: $text = h($text);
193: }
194: return $this->_linkEmails($text, $options);
195: }
196:
197: /**
198: * Convert all links and email addresses to HTML links.
199: *
200: * ### Options
201: *
202: * - `escape` Control HTML escaping of input. Defaults to true.
203: *
204: * @param string $text Text
205: * @param array $options Array of HTML options, and options listed above.
206: * @return string The text with links
207: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::autoLink
208: */
209: public function autoLink($text, $options = array()) {
210: $text = $this->autoLinkUrls($text, $options);
211: return $this->autoLinkEmails($text, array_merge($options, array('escape' => false)));
212: }
213:
214: /**
215: * @see String::highlight()
216: *
217: * @param string $text Text to search the phrase in
218: * @param string $phrase The phrase that will be searched
219: * @param array $options An array of html attributes and options.
220: * @return string The highlighted text
221: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::highlight
222: */
223: public function highlight($text, $phrase, $options = array()) {
224: return $this->_engine->highlight($text, $phrase, $options);
225: }
226:
227: /**
228: * @see String::stripLinks()
229: *
230: * @param string $text Text
231: * @return string The text without links
232: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::stripLinks
233: */
234: public function stripLinks($text) {
235: return $this->_engine->stripLinks($text);
236: }
237:
238: /**
239: * @see String::truncate()
240: *
241: * @param string $text String to truncate.
242: * @param integer $length Length of returned string, including ellipsis.
243: * @param array $options An array of html attributes and options.
244: * @return string Trimmed string.
245: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::truncate
246: */
247: public function truncate($text, $length = 100, $options = array()) {
248: return $this->_engine->truncate($text, $length, $options);
249: }
250:
251: /**
252: * @see String::excerpt()
253: *
254: * @param string $text String to search the phrase in
255: * @param string $phrase Phrase that will be searched for
256: * @param integer $radius The amount of characters that will be returned on each side of the founded phrase
257: * @param string $ending Ending that will be appended
258: * @return string Modified string
259: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::excerpt
260: */
261: public function excerpt($text, $phrase, $radius = 100, $ending = '...') {
262: return $this->_engine->excerpt($text, $phrase, $radius, $ending);
263: }
264:
265: /**
266: * @see String::toList()
267: *
268: * @param array $list The list to be joined
269: * @param string $and The word used to join the last and second last items together with. Defaults to 'and'
270: * @param string $separator The separator used to join all the other items together. Defaults to ', '
271: * @return string The glued together string.
272: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::toList
273: */
274: public function toList($list, $and = 'and', $separator = ', ') {
275: return $this->_engine->toList($list, $and, $separator);
276: }
277:
278: }
279: