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