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