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