1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Templating;
9:
10: use Nette,
11: Nette\Utils\Strings,
12: Nette\Forms\Form,
13: Nette\Utils\Html;
14:
15:
16: 17: 18: 19: 20:
21: class Helpers
22: {
23: private static $helpers = array(
24: 'normalize' => 'Nette\Utils\Strings::normalize',
25: 'toascii' => 'Nette\Utils\Strings::toAscii',
26: 'webalize' => 'Nette\Utils\Strings::webalize',
27: 'truncate' => 'Nette\Utils\Strings::truncate',
28: 'lower' => 'Nette\Utils\Strings::lower',
29: 'upper' => 'Nette\Utils\Strings::upper',
30: 'firstupper' => 'Nette\Utils\Strings::firstUpper',
31: 'capitalize' => 'Nette\Utils\Strings::capitalize',
32: 'trim' => 'Nette\Utils\Strings::trim',
33: 'padleft' => 'Nette\Utils\Strings::padLeft',
34: 'padright' => 'Nette\Utils\Strings::padRight',
35: 'reverse' => 'Nette\Utils\Strings::reverse',
36: 'replacere' => 'Nette\Utils\Strings::replace',
37: 'url' => 'rawurlencode',
38: 'striptags' => 'strip_tags',
39: 'substr' => 'Nette\Utils\Strings::substring',
40: 'repeat' => 'str_repeat',
41: 'implode' => 'implode',
42: 'number' => 'number_format',
43: );
44:
45:
46: public static $dateFormat = '%x';
47:
48:
49: 50: 51: 52: 53:
54: public static function loader($helper)
55: {
56: if (method_exists(__CLASS__, $helper)) {
57: return new Nette\Callback(__CLASS__, $helper);
58: } elseif (isset(self::$helpers[$helper])) {
59: return self::$helpers[$helper];
60: }
61: }
62:
63:
64: 65: 66: 67: 68: 69:
70: public static function escapeHtml($s, $quotes = ENT_QUOTES)
71: {
72: if ($quotes === ENT_NOQUOTES && ($s instanceof ITemplate || $s instanceof Html || $s instanceof Form)) {
73: return $s->__toString(TRUE);
74: }
75: $s = (string) $s;
76: if ($quotes !== ENT_NOQUOTES && strpos($s, '`') !== FALSE && strpbrk($s, ' <>"\'') === FALSE) {
77: $s .= ' ';
78: }
79: return htmlSpecialChars($s, $quotes);
80: }
81:
82:
83: 84: 85: 86: 87:
88: public static function ($s)
89: {
90: $s = (string) $s;
91: if ($s && ($s[0] === '-' || $s[0] === '>' || $s[0] === '!')) {
92: $s = ' ' . $s;
93: }
94: return str_replace('-', '- ', $s);
95: }
96:
97:
98: 99: 100: 101: 102:
103: public static function escapeXML($s)
104: {
105:
106:
107:
108: return htmlSpecialChars(preg_replace('#[\x00-\x08\x0B\x0C\x0E-\x1F]+#', '', $s), ENT_QUOTES);
109: }
110:
111:
112: 113: 114: 115: 116:
117: public static function escapeCss($s)
118: {
119:
120: return addcslashes($s, "\x00..\x1F!\"#$%&'()*+,./:;<=>?@[\\]^`{|}~");
121: }
122:
123:
124: 125: 126: 127: 128:
129: public static function escapeJs($s)
130: {
131: if (is_object($s) && ($s instanceof ITemplate || $s instanceof Html || $s instanceof Form)) {
132: $s = $s->__toString(TRUE);
133: }
134: return str_replace(array(']]>', '<!'), array(']]\x3E', '\x3C!'), Nette\Utils\Json::encode($s));
135: }
136:
137:
138: 139: 140: 141: 142:
143: public static function escapeICal($s)
144: {
145:
146: return addcslashes(preg_replace('#[\x00-\x08\x0B\x0C-\x1F]+#', '', $s), "\";\\,:\n");
147: }
148:
149:
150: 151: 152: 153: 154:
155: public static function safeUrl($s)
156: {
157: return preg_match('~^(?:(?:https?|ftp)://[^@]+(?:/.*)?|mailto:.+|[/?#].*|[^:]+)\z~i', $s) ? $s : '';
158: }
159:
160:
161: 162: 163: 164: 165:
166: public static function strip($s)
167: {
168: return Strings::replace(
169: $s,
170: '#(</textarea|</pre|</script|^).*?(?=<textarea|<pre|<script|\z)#si',
171: function($m) {
172: return trim(preg_replace('#[ \t\r\n]+#', " ", $m[0]));
173: });
174: }
175:
176:
177: 178: 179: 180: 181: 182: 183:
184: public static function indent($s, $level = 1, $chars = "\t")
185: {
186: if ($level >= 1) {
187: $s = Strings::replace($s, '#<(textarea|pre).*?</\\1#si', function($m) {
188: return strtr($m[0], " \t\r\n", "\x1F\x1E\x1D\x1A");
189: });
190: $s = Strings::indent($s, $level, $chars);
191: $s = strtr($s, "\x1F\x1E\x1D\x1A", " \t\r\n");
192: }
193: return $s;
194: }
195:
196:
197: 198: 199: 200: 201: 202:
203: public static function date($time, $format = NULL)
204: {
205: if ($time == NULL) {
206: return NULL;
207: }
208:
209: if (!isset($format)) {
210: $format = self::$dateFormat;
211: }
212:
213: $time = Nette\DateTime::from($time);
214: return Strings::contains($format, '%')
215: ? strftime($format, $time->format('U'))
216: : $time->format($format);
217: }
218:
219:
220: 221: 222: 223: 224: 225:
226: public static function bytes($bytes, $precision = 2)
227: {
228: $bytes = round($bytes);
229: $units = array('B', 'kB', 'MB', 'GB', 'TB', 'PB');
230: foreach ($units as $unit) {
231: if (abs($bytes) < 1024 || $unit === end($units)) {
232: break;
233: }
234: $bytes = $bytes / 1024;
235: }
236: return round($bytes, $precision) . ' ' . $unit;
237: }
238:
239:
240: 241: 242: 243: 244:
245: public static function length($var)
246: {
247: return is_string($var) ? Strings::length($var) : count($var);
248: }
249:
250:
251: 252: 253: 254: 255: 256: 257:
258: public static function replace($subject, $search, $replacement = '')
259: {
260: return str_replace($search, $replacement, $subject);
261: }
262:
263:
264: 265: 266: 267: 268: 269:
270: public static function dataStream($data, $type = NULL)
271: {
272: if ($type === NULL) {
273: $type = Nette\Utils\MimeTypeDetector::fromString($data);
274: }
275: return 'data:' . ($type ? "$type;" : '') . 'base64,' . base64_encode($data);
276: }
277:
278:
279: 280: 281: 282: 283:
284: public static function null()
285: {
286: return '';
287: }
288:
289:
290: 291: 292: 293:
294: public static function nl2br($value)
295: {
296: return nl2br($value, Html::$xhtml);
297: }
298:
299:
300:
301:
302:
303: 304: 305: 306: 307:
308: public static function optimizePhp($source, $lineLength = 80, $existenceOfThisParameterSolvesDamnBugInPHP535 = NULL)
309: {
310: $res = $php = '';
311: $lastChar = ';';
312: $tokens = new \ArrayIterator(token_get_all($source));
313: foreach ($tokens as $key => $token) {
314: if (is_array($token)) {
315: if ($token[0] === T_INLINE_HTML) {
316: $lastChar = '';
317: $res .= $token[1];
318:
319: } elseif ($token[0] === T_CLOSE_TAG) {
320: $next = isset($tokens[$key + 1]) ? $tokens[$key + 1] : NULL;
321: if (substr($res, -1) !== '<' && preg_match('#^<\?php\s*\z#', $php)) {
322: $php = '';
323:
324: } elseif (is_array($next) && $next[0] === T_OPEN_TAG) {
325: if (!strspn($lastChar, ';{}:/')) {
326: $php .= $lastChar = ';';
327: }
328: if (substr($next[1], -1) === "\n") {
329: $php .= "\n";
330: }
331: $tokens->next();
332:
333: } elseif ($next) {
334: $res .= preg_replace('#;?(\s)*\z#', '$1', $php) . $token[1];
335: if (strlen($res) - strrpos($res, "\n") > $lineLength
336: && (!is_array($next) || strpos($next[1], "\n") === FALSE)
337: ) {
338: $res .= "\n";
339: }
340: $php = '';
341:
342: } else {
343: if (!strspn($lastChar, '};')) {
344: $php .= ';';
345: }
346: }
347:
348: } elseif ($token[0] === T_ELSE || $token[0] === T_ELSEIF) {
349: if ($tokens[$key + 1] === ':' && $lastChar === '}') {
350: $php .= ';';
351: }
352: $lastChar = '';
353: $php .= $token[1];
354:
355: } else {
356: if (!in_array($token[0], array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT, T_OPEN_TAG), TRUE)) {
357: $lastChar = '';
358: }
359: $php .= $token[1];
360: }
361: } else {
362: $php .= $lastChar = $token;
363: }
364: }
365: return $res . $php;
366: }
367:
368: }
369: