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 = Set::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: $text = preg_replace_callback(
105: '#(?<!href="|src="|">)((?:https?|ftp|nntp)://[^\s<>()]+)#i',
106: array(&$this, '_insertPlaceHolder'),
107: $text
108: );
109: $text = preg_replace_callback(
110: '#(?<!href="|">)(?<!\b[[:punct:]])(?<!http://|https://|ftp://|nntp://)www.[^\n\%\ <]+[^<\n\%\,\.\ <](?<!\))#i',
111: array(&$this, '_insertPlaceHolder'),
112: $text
113: );
114: if ($options['escape']) {
115: $text = h($text);
116: }
117: return $this->_linkUrls($text, $options);
118: }
119:
120: /**
121: * Saves the placeholder for a string, for later use. This gets around double
122: * escaping content in URL's.
123: *
124: * @param array $matches An array of regexp matches.
125: * @return string Replaced values.
126: */
127: protected function _insertPlaceHolder($matches) {
128: $key = md5($matches[0]);
129: $this->_placeholders[$key] = $matches[0];
130: return $key;
131: }
132:
133: /**
134: * Replace placeholders with links.
135: *
136: * @param string $text The text to operate on.
137: * @param array $htmlOptions The options for the generated links.
138: * @return string The text with links inserted.
139: */
140: protected function _linkUrls($text, $htmlOptions) {
141: $replace = array();
142: foreach ($this->_placeholders as $hash => $url) {
143: $link = $url;
144: if (!preg_match('#^[a-z]+\://#', $url)) {
145: $url = 'http://' . $url;
146: }
147: $replace[$hash] = $this->Html->link($link, $url, $htmlOptions);
148: }
149: return strtr($text, $replace);
150: }
151:
152: /**
153: * Links email addresses
154: *
155: * @param string $text The text to operate on
156: * @param array $options An array of options to use for the HTML.
157: * @return string
158: * @see TextHelper::autoLinkEmails()
159: */
160: protected function _linkEmails($text, $options) {
161: $replace = array();
162: foreach ($this->_placeholders as $hash => $url) {
163: $replace[$hash] = $this->Html->link($url, 'mailto:' . $url, $options);
164: }
165: return strtr($text, $replace);
166: }
167:
168: /**
169: * Adds email links (<a href="mailto:....) to a given text.
170: *
171: * ### Options
172: *
173: * - `escape` Control HTML escaping of input. Defaults to true.
174: *
175: * @param string $text Text
176: * @param array $options Array of HTML options, and options listed above.
177: * @return string The text with links
178: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::autoLinkEmails
179: */
180: public function autoLinkEmails($text, $options = array()) {
181: $options += array('escape' => true);
182: $this->_placeholders = array();
183:
184: $atom = '[a-z0-9!#$%&\'*+\/=?^_`{|}~-]';
185: $text = preg_replace_callback(
186: '/(' . $atom . '+(?:\.' . $atom . '+)*@[a-z0-9-]+(?:\.[a-z0-9-]+)+)/i',
187: array(&$this, '_insertPlaceholder'),
188: $text
189: );
190: if ($options['escape']) {
191: $text = h($text);
192: }
193: return $this->_linkEmails($text, $options);
194: }
195:
196: /**
197: * Convert all links and email addresses to HTML links.
198: *
199: * ### Options
200: *
201: * - `escape` Control HTML escaping of input. Defaults to true.
202: *
203: * @param string $text Text
204: * @param array $options Array of HTML options, and options listed above.
205: * @return string The text with links
206: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::autoLink
207: */
208: public function autoLink($text, $options = array()) {
209: $text = $this->autoLinkUrls($text, $options);
210: return $this->autoLinkEmails($text, array_merge($options, array('escape' => false)));
211: }
212:
213: /**
214: * @see String::highlight()
215: *
216: * @param string $text Text to search the phrase in
217: * @param string $phrase The phrase that will be searched
218: * @param array $options An array of html attributes and options.
219: * @return string The highlighted text
220: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::highlight
221: */
222: public function highlight($text, $phrase, $options = array()) {
223: return $this->_engine->highlight($text, $phrase, $options);
224: }
225:
226: /**
227: * @see String::stripLinks()
228: *
229: * @param string $text Text
230: * @return string The text without links
231: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::stripLinks
232: */
233: public function stripLinks($text) {
234: return $this->_engine->stripLinks($text);
235: }
236:
237: /**
238: * @see String::truncate()
239: *
240: * @param string $text String to truncate.
241: * @param integer $length Length of returned string, including ellipsis.
242: * @param array $options An array of html attributes and options.
243: * @return string Trimmed string.
244: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::truncate
245: */
246: public function truncate($text, $length = 100, $options = array()) {
247: return $this->_engine->truncate($text, $length, $options);
248: }
249:
250: /**
251: * @see String::excerpt()
252: *
253: * @param string $text String to search the phrase in
254: * @param string $phrase Phrase that will be searched for
255: * @param integer $radius The amount of characters that will be returned on each side of the founded phrase
256: * @param string $ending Ending that will be appended
257: * @return string Modified string
258: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::excerpt
259: */
260: public function excerpt($text, $phrase, $radius = 100, $ending = '...') {
261: return $this->_engine->excerpt($text, $phrase, $radius, $ending);
262: }
263:
264: /**
265: * @see String::toList()
266: *
267: * @param array $list The list to be joined
268: * @param string $and The word used to join the last and second last items together with. Defaults to 'and'
269: * @param string $separator The separator used to join all the other items together. Defaults to ', '
270: * @return string The glued together string.
271: * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::toList
272: */
273: public function toList($list, $and = 'and', $separator = ', ') {
274: return $this->_engine->toList($list, $and, $separator);
275: }
276:
277: }
278: