Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • FileTemplate
  • Helpers
  • Template

Interfaces

  • IFileTemplate
  • ITemplate

Exceptions

  • FilterException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  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:  * Template helpers.
 18:  *
 19:  * @author     David Grudl
 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:     /** @var string default date format */
 46:     public static $dateFormat = '%x';
 47: 
 48: 
 49:     /**
 50:      * Try to load the requested helper.
 51:      * @param  string  helper name
 52:      * @return callable
 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:      * Escapes string for use inside HTML template.
 66:      * @param  mixed  UTF-8 encoding
 67:      * @param  int    optional attribute quotes
 68:      * @return string
 69:      */
 70:     public static function escapeHtml($s, $quotes = ENT_QUOTES)
 71:     {
 72:         if (is_object($s) && ($s instanceof ITemplate || $s instanceof Html || $s instanceof Form)) {
 73:             return $s->__toString(TRUE);
 74:         }
 75:         return htmlSpecialChars($s, $quotes);
 76:     }
 77: 
 78: 
 79:     /**
 80:      * Escapes string for use inside HTML comments.
 81:      * @param  string  UTF-8 encoding
 82:      * @return string
 83:      */
 84:     public static function escapeHtmlComment($s)
 85:     {
 86:         return ' ' . str_replace('-', '- ', $s); // dash is very problematic character in comments
 87:     }
 88: 
 89: 
 90:     /**
 91:      * Escapes string for use inside XML 1.0 template.
 92:      * @param  string UTF-8 encoding
 93:      * @return string
 94:      */
 95:     public static function escapeXML($s)
 96:     {
 97:         // XML 1.0: \x09 \x0A \x0D and C1 allowed directly, C0 forbidden
 98:         // XML 1.1: \x00 forbidden directly and as a character reference,
 99:         //   \x09 \x0A \x0D \x85 allowed directly, C0, C1 and \x7F allowed as character references
100:         return htmlSpecialChars(preg_replace('#[\x00-\x08\x0B\x0C\x0E-\x1F]+#', '', $s), ENT_QUOTES);
101:     }
102: 
103: 
104:     /**
105:      * Escapes string for use inside CSS template.
106:      * @param  string UTF-8 encoding
107:      * @return string
108:      */
109:     public static function escapeCss($s)
110:     {
111:         // http://www.w3.org/TR/2006/WD-CSS21-20060411/syndata.html#q6
112:         return addcslashes($s, "\x00..\x1F!\"#$%&'()*+,./:;<=>?@[\\]^`{|}~");
113:     }
114: 
115: 
116:     /**
117:      * Escapes variables for use inside <script>.
118:      * @param  mixed  UTF-8 encoding
119:      * @return string
120:      */
121:     public static function escapeJs($s)
122:     {
123:         if (is_object($s) && ($s instanceof ITemplate || $s instanceof Html || $s instanceof Form)) {
124:             $s = $s->__toString(TRUE);
125:         }
126:         return str_replace(array(']]>', '<!'), array(']]\x3E', '\x3C!'), Nette\Utils\Json::encode($s));
127:     }
128: 
129: 
130:     /**
131:      * Escapes string for use inside iCal template.
132:      * @param  mixed  UTF-8 encoding
133:      * @return string
134:      */
135:     public static function escapeICal($s)
136:     {
137:         // http://www.ietf.org/rfc/rfc5545.txt
138:         return addcslashes(preg_replace('#[\x00-\x08\x0B\x0C-\x1F]+#', '', $s), "\";\\,:\n");
139:     }
140: 
141: 
142:     /**
143:      * Sanitizes string for use inside href attribute.
144:      * @param  string
145:      * @return string
146:      */
147:     public static function safeUrl($s)
148:     {
149:         return preg_match('#^(https?://.+|ftp://.+|mailto:.+|[^:]+)\z#i', $s) ? $s : '';
150:     }
151: 
152: 
153:     /**
154:      * Replaces all repeated white spaces with a single space.
155:      * @param  string UTF-8 encoding or 8-bit
156:      * @return string
157:      */
158:     public static function strip($s)
159:     {
160:         return Strings::replace(
161:             $s,
162:             '#(</textarea|</pre|</script|^).*?(?=<textarea|<pre|<script|\z)#si',
163:             function($m) {
164:                 return trim(preg_replace('#[ \t\r\n]+#', " ", $m[0]));
165:             });
166:     }
167: 
168: 
169:     /**
170:      * Indents the HTML content from the left.
171:      * @param  string UTF-8 encoding or 8-bit
172:      * @param  int
173:      * @param  string
174:      * @return string
175:      */
176:     public static function indent($s, $level = 1, $chars = "\t")
177:     {
178:         if ($level >= 1) {
179:             $s = Strings::replace($s, '#<(textarea|pre).*?</\\1#si', function($m) {
180:                 return strtr($m[0], " \t\r\n", "\x1F\x1E\x1D\x1A");
181:             });
182:             $s = Strings::indent($s, $level, $chars);
183:             $s = strtr($s, "\x1F\x1E\x1D\x1A", " \t\r\n");
184:         }
185:         return $s;
186:     }
187: 
188: 
189:     /**
190:      * Date/time formatting.
191:      * @param  string|int|DateTime
192:      * @param  string
193:      * @return string
194:      */
195:     public static function date($time, $format = NULL)
196:     {
197:         if ($time == NULL) { // intentionally ==
198:             return NULL;
199:         }
200: 
201:         if (!isset($format)) {
202:             $format = self::$dateFormat;
203:         }
204: 
205:         $time = Nette\DateTime::from($time);
206:         return Strings::contains($format, '%')
207:             ? strftime($format, $time->format('U')) // formats according to locales
208:             : $time->format($format); // formats using date()
209:     }
210: 
211: 
212:     /**
213:      * Converts to human readable file size.
214:      * @param  int
215:      * @param  int
216:      * @return string
217:      */
218:     public static function bytes($bytes, $precision = 2)
219:     {
220:         $bytes = round($bytes);
221:         $units = array('B', 'kB', 'MB', 'GB', 'TB', 'PB');
222:         foreach ($units as $unit) {
223:             if (abs($bytes) < 1024 || $unit === end($units)) {
224:                 break;
225:             }
226:             $bytes = $bytes / 1024;
227:         }
228:         return round($bytes, $precision) . ' ' . $unit;
229:     }
230: 
231: 
232:     /**
233:      * Returns array of string length.
234:      * @param  mixed
235:      * @return int
236:      */
237:     public static function length($var)
238:     {
239:         return is_string($var) ? Strings::length($var) : count($var);
240:     }
241: 
242: 
243:     /**
244:      * Performs a search and replace.
245:      * @param  string
246:      * @param  string
247:      * @param  string
248:      * @return string
249:      */
250:     public static function replace($subject, $search, $replacement = '')
251:     {
252:         return str_replace($search, $replacement, $subject);
253:     }
254: 
255: 
256:     /**
257:      * The data: URI generator.
258:      * @param  string
259:      * @param  string
260:      * @return string
261:      */
262:     public static function dataStream($data, $type = NULL)
263:     {
264:         if ($type === NULL) {
265:             $type = Nette\Utils\MimeTypeDetector::fromString($data);
266:         }
267:         return 'data:' . ($type ? "$type;" : '') . 'base64,' . base64_encode($data);
268:     }
269: 
270: 
271:     /**
272:      * /dev/null.
273:      * @param  mixed
274:      * @return string
275:      */
276:     public static function null()
277:     {
278:         return '';
279:     }
280: 
281: 
282:     /**
283:      * @param  string
284:      * @return string
285:      */
286:     public static function nl2br($value)
287:     {
288:         return nl2br($value, Html::$xhtml);
289:     }
290: 
291: 
292:     /********************* Template tools ****************d*g**/
293: 
294: 
295:     /**
296:      * Removes unnecessary blocks of PHP code.
297:      * @param  string
298:      * @return string
299:      */
300:     public static function optimizePhp($source, $lineLength = 80, $existenceOfThisParameterSolvesDamnBugInPHP535 = NULL)
301:     {
302:         $res = $php = '';
303:         $lastChar = ';';
304:         $tokens = new \ArrayIterator(token_get_all($source));
305:         foreach ($tokens as $key => $token) {
306:             if (is_array($token)) {
307:                 if ($token[0] === T_INLINE_HTML) {
308:                     $lastChar = '';
309:                     $res .= $token[1];
310: 
311:                 } elseif ($token[0] === T_CLOSE_TAG) {
312:                     $next = isset($tokens[$key + 1]) ? $tokens[$key + 1] : NULL;
313:                     if (substr($res, -1) !== '<' && preg_match('#^<\?php\s*\z#', $php)) {
314:                         $php = ''; // removes empty (?php ?), but retains ((?php ?)?php
315: 
316:                     } elseif (is_array($next) && $next[0] === T_OPEN_TAG) { // remove ?)(?php
317:                         if (!strspn($lastChar, ';{}:/')) {
318:                             $php .= $lastChar = ';';
319:                         }
320:                         if (substr($next[1], -1) === "\n") {
321:                             $php .= "\n";
322:                         }
323:                         $tokens->next();
324: 
325:                     } elseif ($next) {
326:                         $res .= preg_replace('#;?(\s)*\z#', '$1', $php) . $token[1]; // remove last semicolon before ?)
327:                         if (strlen($res) - strrpos($res, "\n") > $lineLength
328:                             && (!is_array($next) || strpos($next[1], "\n") === FALSE)
329:                         ) {
330:                             $res .= "\n";
331:                         }
332:                         $php = '';
333: 
334:                     } else { // remove last ?)
335:                         if (!strspn($lastChar, '};')) {
336:                             $php .= ';';
337:                         }
338:                     }
339: 
340:                 } elseif ($token[0] === T_ELSE || $token[0] === T_ELSEIF) {
341:                     if ($tokens[$key + 1] === ':' && $lastChar === '}') {
342:                         $php .= ';'; // semicolon needed in if(): ... if() ... else:
343:                     }
344:                     $lastChar = '';
345:                     $php .= $token[1];
346: 
347:                 } else {
348:                     if (!in_array($token[0], array(T_WHITESPACE, T_COMMENT, T_DOC_COMMENT, T_OPEN_TAG))) {
349:                         $lastChar = '';
350:                     }
351:                     $php .= $token[1];
352:                 }
353:             } else {
354:                 $php .= $lastChar = $token;
355:             }
356:         }
357:         return $res . $php;
358:     }
359: 
360: }
361: 
Nette Framework 2.0.14 API API documentation generated by ApiGen 2.8.0