Source for file CurlyBracketsFilter.php
Documentation is available at CurlyBracketsFilter.php
- 1: <?php
- 3: /**
- 4: * Nette Framework
- 5: *
- 6: * Copyright (c) 2004, 2009 David Grudl (http://davidgrudl.com)
- 7: *
- 8: * This source file is subject to the "Nette license" that is bundled
- 9: * with this package in the file license.txt.
- 10: *
- 11: * For more information please see https://nette.org
- 12: *
- 19: */
- 27: /**
- 28: * Template filter curlyBrackets: support for {...} in template.
- 29: *
- 30: * - {$variable} with escaping
- 31: * - {!$variable} without escaping
- 32: * - {*comment*} will be removed
- 33: * - {=expression} echo with escaping
- 34: * - {!=expression} echo without escaping
- 35: * - {?expression} evaluate PHP statement
- 36: * - {_expression} echo translation with escaping
- 37: * - {!_expression} echo translation without escaping
- 38: * - {link destination ...} control link
- 39: * - {plink destination ...} presenter link
- 40: * - {ajaxlink destination ...} ajax link
- 41: * - {if ?} ... {elseif ?} ... {else} ... {/if} // or <%else%>, <%/if%>, <%/foreach%> ?
- 42: * - {for ?} ... {/for}
- 43: * - {foreach ?} ... {/foreach}
- 44: * - {include ?}
- 45: * - {cache ?} ... {/cache} cached block
- 46: * - {snippet ?} ... {/snippet ?} control snippet
- 47: * - {attr ?} HTML element attributes
- 48: * - {block|texy} ... {/block} capture of filter block
- 49: * - {contentType ...} HTTP Content-Type header
- 50: * - {assign $var value} set template parameter
- 51: * - {debugbreak}
- 52: *
- 56: */
- 58: {
- 65: 'snippet' => '<?php } if ($_cb->foo = $template->snippet($control%:macroSnippet%)) { $_cb->snippets[] = $_cb->foo; ?>',
- 66: '/snippet' => '<?php array_pop($_cb->snippets)->finish(); } if (SnippetHelper::$outputAllowed) { ?>',
- 68: 'cache' => '<?php if ($_cb->foo = $template->cache($_cb->key = md5(__FILE__) . __LINE__, $template->getFile(), array(%%))) { $_cb->caches[] = $_cb->foo; ?>',
- 69: '/cache' => '<?php array_pop($_cb->caches)->save(); } if (!empty($_cb->caches)) end($_cb->caches)->addItem($_cb->key); ?>',
- 88: 'ifCurrent' => '<?php %:macroIfCurrent%; if ($presenter->getLastCreatedRequestFlag("current")): ?>',
- 114: /**#@+ Context-aware escaping states */
- 121: /**#@-*/
- 125: /**
- 126: * Invokes filter.
- 129: */
- 131: {
- 134: }
- 138: /**
- 139: * Invokes filter.
- 142: */
- 144: {
- 148: // context-aware escaping
- 153: // remove comments
- 156: // snippets support (temporary solution)
- 157: $s = "<?php\nif (SnippetHelper::\$outputAllowed) {\n?>\n$s<?php\n}\n?>"; // \n$s is required by following RE
- 161: $s
- 164: // process all {tags} and <tags/>
- 166: <(/?)([a-z]+)| ## 1,2) start tag: <tag </tag ; ignores <!-- <!DOCTYPE
- 167: (>)| ## 3) end tag
- 168: (?<=\\s)(style|on[a-z]+)\s*=\s*(["\'])| ## 4,5) attribute
- 169: (["\'])| ## 6) attribute delimiter
- 170: (\n[ \t]*)?\\{([^\\s\'"{}][^}]*?)(\\|[a-z](?:[^\'"}\s|]+|\\|[a-z]|\'[^\']*\'|"[^"]*")*)?\\}([ \t]*(?=\r|\n))? ## 7,8,9,10) indent & macro & modifiers & newline
- 173: $s
- 176: // named blocks
- 179: $s = preg_replace_callback("#{block\#($name)} \?>(.*)<\?php {/block\#$name}#sU", array($this, 'cbNamedBlocks'), $s);
- 180: }
- 183: }
- 185: // internal state holder
- 191: }
- 195: /**
- 196: * Searches for curly brackets, HTML tags and attributes.
- 197: */
- 199: {
- 200: // [1] => /
- 201: // [2] => tag
- 202: // [3] => >
- 203: // [4] => style|on...
- 204: // [5] => '"
- 205: // [6] => '"
- 206: // [7] => indent
- 207: // [8] => {macro
- 208: // [9] => {...|modifiers}
- 209: // [10] => newline?
- 219: }
- 226: }
- 227: }
- 228: }
- 232: // skip analyse
- 240: }
- 244: $this->context = $matches[5]; // self::CONTEXT_ATTRIBUTE_SINGLE || self::CONTEXT_ATTRIBUTE_DOUBLE
- 245: $this->escape = strncasecmp($matches[4], 'on', 2) ? 'TemplateHelpers::escapeHtmlCss' : 'TemplateHelpers::escapeHtmlJs';
- 246: }
- 252: $this->escape = $this->tag === 'script' ? 'TemplateHelpers::escapeJs' : 'TemplateHelpers::escapeCss';
- 256: }
- 257: }
- 264: }
- 267: if ($this->context === self::CONTEXT_TEXT || ($this->context === self::CONTEXT_CDATA && $this->tag === strtolower($matches[2]))) {
- 271: }
- 272: }
- 274: }
- 278: /**
- 279: * Process specified macro.
- 280: */
- 282: {
- 285: }
- 292: /**
- 293: * Callback for self::macro().
- 294: */
- 296: {
- 303: throw new InvalidStateException("CurlyBrackets macro handler '$textual' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
- 304: }
- 309: }
- 310: }
- 314: /**
- 315: * {$var |modifiers}
- 316: */
- 318: {
- 320: }
- 324: /**
- 325: * {include ...}
- 326: */
- 328: {
- 334: throw new InvalidStateException("Included block name must be alphanumeric string, '$name' given.");
- 335: }
- 337: $params = ($params ? "array($params) + " : '') . '$template->getParams()'; // or get_defined_vars() ?
- 344: }
- 346: }
- 349: return $modifiers ? $this->macroBlock('', $modifiers) . $cmd . ";" . $this->macroBlockEnd(NULL) : $cmd;
- 350: }
- 352: return 'echo ' . $this->macroModifiers('$template->subTemplate(' . $this->formatVars($var) . ')->__toString(TRUE)', $modifiers);
- 353: }
- 357: /**
- 358: * {extends ...}
- 359: */
- 361: {
- 363: }
- 367: /**
- 368: * {block ...}
- 369: */
- 371: {
- 379: }
- 384: }
- 389: }
- 392: }
- 396: /**
- 397: * {/block ...}
- 398: */
- 400: {
- 411: : '} catch (Exception $_e) { ob_end_clean(); throw $_e; } '
- 414: }
- 415: }
- 419: /**
- 420: * Converts {block#named}...{/block} to functions.
- 421: */
- 423: {
- 429: }
- 433: /**
- 434: * {foreach ...}
- 435: */
- 437: {
- 438: return '$iterator = $_cb->its[] = new SmartCachingIterator(' . preg_replace('# +as +#i', ') as ', $var, 1);
- 439: }
- 443: /**
- 444: * {attr ...}
- 445: */
- 447: {
- 449: }
- 453: /**
- 454: * {contentType ...}
- 455: */
- 457: {
- 477: }
- 479: // temporary solution
- 481: }
- 485: /**
- 486: * {snippet ...}
- 487: */
- 489: {
- 492: }
- 494: }
- 498: /**
- 499: * {link ...}
- 500: */
- 502: {
- 504: }
- 508: /**
- 509: * {plink ...}
- 510: */
- 512: {
- 514: }
- 518: /**
- 519: * {ifCurrent ...}
- 520: */
- 522: {
- 523: return $var ? $this->macroModifiers('$presenter->link(' . $this->formatVars($var) .')', $modifiers) : '';
- 524: }
- 528: /**
- 529: * {ajaxlink ...}
- 530: */
- 532: {
- 533: return $this->macroModifiers('$control->ajaxlink(' . $this->formatVars($var) .')', $modifiers);
- 534: }
- 538: /**
- 539: * {assign ...}
- 540: */
- 542: {
- 544: return '$template->' . $m[1] . ' = $' . $m[1] . ' = ' . $this->macroModifiers($m[2] === '' ? 'NULL' : $m[2], $modifiers);
- 545: }
- 549: /**
- 550: * Escaping helper.
- 551: */
- 553: {
- 555: }
- 559: /**
- 560: * Applies modifiers.
- 561: */
- 563: {
- 568: $tokens
- 581: }
- 589: }
- 592: }
- 593: }
- 595: }
- 599: /**
- 600: * Formats {*link ...} parameters.
- 601: */
- 603: {
- 608: }
- 609: }
- 611: }
- 615: /**
- 616: * Initializes state holder $_cb in template.
- 619: */
- 621: {
- 624: }
- 627: }
- 629: }
- 631: }