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

Classes

  • FileTemplate
  • Helpers
  • Template

Interfaces

  • IFileTemplate
  • ITemplate

Exceptions

  • FilterException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  • Nette homepage
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://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 ($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:      * Escapes string for use inside HTML comments.
 85:      * @param  string  UTF-8 encoding
 86:      * @return string
 87:      */
 88:     public static function escapeHtmlComment($s)
 89:     {
 90:         $s = (string) $s;
 91:         if ($s && ($s[0] === '-' || $s[0] === '>' || $s[0] === '!')) {
 92:             $s = ' ' . $s;
 93:         }
 94:         return str_replace('-', '- ', $s); // dash is very problematic character in comments
 95:     }
 96: 
 97: 
 98:     /**
 99:      * Escapes string for use inside XML 1.0 template.
100:      * @param  string UTF-8 encoding
101:      * @return string
102:      */
103:     public static function escapeXML($s)
104:     {
105:         // XML 1.0: \x09 \x0A \x0D and C1 allowed directly, C0 forbidden
106:         // XML 1.1: \x00 forbidden directly and as a character reference,
107:         //   \x09 \x0A \x0D \x85 allowed directly, C0, C1 and \x7F allowed as character references
108:         return htmlSpecialChars(preg_replace('#[\x00-\x08\x0B\x0C\x0E-\x1F]+#', '', $s), ENT_QUOTES);
109:     }
110: 
111: 
112:     /**
113:      * Escapes string for use inside CSS template.
114:      * @param  string UTF-8 encoding
115:      * @return string
116:      */
117:     public static function escapeCss($s)
118:     {
119:         // http://www.w3.org/TR/2006/WD-CSS21-20060411/syndata.html#q6
120:         return addcslashes($s, "\x00..\x1F!\"#$%&'()*+,./:;<=>?@[\\]^`{|}~");
121:     }
122: 
123: 
124:     /**
125:      * Escapes variables for use inside <script>.
126:      * @param  mixed  UTF-8 encoding
127:      * @return string
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:      * Escapes string for use inside iCal template.
140:      * @param  mixed  UTF-8 encoding
141:      * @return string
142:      */
143:     public static function escapeICal($s)
144:     {
145:         // http://www.ietf.org/rfc/rfc5545.txt
146:         return addcslashes(preg_replace('#[\x00-\x08\x0B\x0C-\x1F]+#', '', $s), "\";\\,:\n");
147:     }
148: 
149: 
150:     /**
151:      * Sanitizes string for use inside href attribute.
152:      * @param  string
153:      * @return string
154:      */
155:     public static function safeUrl($s)
156:     {
157:         return preg_match('~^(?:(?:https?|ftp)://[^@]+(?:/.*)?|mailto:.+|[/?#].*|[^:]+)\z~i', $s) ? $s : '';
158:     }
159: 
160: 
161:     /**
162:      * Replaces all repeated white spaces with a single space.
163:      * @param  string UTF-8 encoding or 8-bit
164:      * @return string
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:      * Indents the HTML content from the left.
179:      * @param  string UTF-8 encoding or 8-bit
180:      * @param  int
181:      * @param  string
182:      * @return string
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:      * Date/time formatting.
199:      * @param  string|int|DateTime
200:      * @param  string
201:      * @return string
202:      */
203:     public static function date($time, $format = NULL)
204:     {
205:         if ($time == NULL) { // intentionally ==
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')) // formats according to locales
216:             : $time->format($format); // formats using date()
217:     }
218: 
219: 
220:     /**
221:      * Converts to human readable file size.
222:      * @param  int
223:      * @param  int
224:      * @return string
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:      * Returns array of string length.
242:      * @param  mixed
243:      * @return int
244:      */
245:     public static function length($var)
246:     {
247:         return is_string($var) ? Strings::length($var) : count($var);
248:     }
249: 
250: 
251:     /**
252:      * Performs a search and replace.
253:      * @param  string
254:      * @param  string
255:      * @param  string
256:      * @return string
257:      */
258:     public static function replace($subject, $search, $replacement = '')
259:     {
260:         return str_replace($search, $replacement, $subject);
261:     }
262: 
263: 
264:     /**
265:      * The data: URI generator.
266:      * @param  string
267:      * @param  string
268:      * @return string
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:      * /dev/null.
281:      * @param  mixed
282:      * @return string
283:      */
284:     public static function null()
285:     {
286:         return '';
287:     }
288: 
289: 
290:     /**
291:      * @param  string
292:      * @return string
293:      */
294:     public static function nl2br($value)
295:     {
296:         return nl2br($value, Html::$xhtml);
297:     }
298: 
299: 
300:     /********************* Template tools ****************d*g**/
301: 
302: 
303:     /**
304:      * Removes unnecessary blocks of PHP code.
305:      * @param  string
306:      * @return string
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 = ''; // removes empty (?php ?), but retains ((?php ?)?php
323: 
324:                     } elseif (is_array($next) && $next[0] === T_OPEN_TAG) { // remove ?)(?php
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]; // remove last semicolon before ?)
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 { // remove last ?)
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 .= ';'; // semicolon needed in if(): ... if() ... else:
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: 
Nette 2.0 API documentation generated by ApiGen 2.8.0