1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Bridges\ApplicationLatte;
9:
10: use Nette,
11: Latte,
12: Latte\MacroNode,
13: Latte\PhpWriter,
14: Latte\CompileException,
15: Nette\Utils\Strings;
16:
17:
18: 19: 20: 21: 22: 23: 24: 25: 26:
27: class UIMacros extends Latte\Macros\MacroSet
28: {
29:
30: public static function install(Latte\Compiler $compiler)
31: {
32: $me = new static($compiler);
33: $me->addMacro('control', array($me, 'macroControl'));
34:
35: $me->addMacro('href', NULL, NULL, function(MacroNode $node, PhpWriter $writer) use ($me) {
36: return ' ?> href="<?php ' . $me->macroLink($node, $writer) . ' ?>"<?php ';
37: });
38: $me->addMacro('plink', array($me, 'macroLink'));
39: $me->addMacro('link', array($me, 'macroLink'));
40: $me->addMacro('ifCurrent', array($me, 'macroIfCurrent'), '}');
41: }
42:
43:
44: 45: 46: 47:
48: public function finalize()
49: {
50: $prolog = '
51: // snippets support
52: if (empty($_l->extends) && !empty($_control->snippetMode)) {
53: return Nette\Bridges\ApplicationLatte\UIMacros::renderSnippets($_control, $_b, get_defined_vars());
54: }';
55: return array($prolog, '');
56: }
57:
58:
59:
60:
61:
62: 63: 64:
65: public function macroControl(MacroNode $node, PhpWriter $writer)
66: {
67: $words = $node->tokenizer->fetchWords();
68: if (!$words) {
69: throw new CompileException('Missing control name in {control}');
70: }
71: $name = $writer->formatWord($words[0]);
72: $method = isset($words[1]) ? ucfirst($words[1]) : '';
73: $method = Strings::match($method, '#^\w*\z#') ? "render$method" : "{\"render$method\"}";
74: $param = $writer->formatArray();
75: if (!Strings::contains($node->args, '=>')) {
76: $param = substr($param, 6, -1);
77: }
78: return ($name[0] === '$' ? "if (is_object($name)) \$_l->tmp = $name; else " : '')
79: . '$_l->tmp = $_control->getComponent(' . $name . '); '
80: . 'if ($_l->tmp instanceof Nette\Application\UI\IRenderable) $_l->tmp->redrawControl(NULL, FALSE); '
81: . ($node->modifiers === '' ? "\$_l->tmp->$method($param)" : $writer->write("ob_start(); \$_l->tmp->$method($param); echo %modify(ob_get_clean())"));
82: }
83:
84:
85: 86: 87: 88: 89:
90: public function macroLink(MacroNode $node, PhpWriter $writer)
91: {
92: $node->modifiers = preg_replace('#\|safeurl\s*(?=\||\z)#i', '', $node->modifiers);
93: return $writer->using($node, $this->getCompiler())
94: ->write('echo %escape(%modify(' . ($node->name === 'plink' ? '$_presenter' : '$_control') . '->link(%node.word, %node.array?)))');
95: }
96:
97:
98: 99: 100:
101: public function macroIfCurrent(MacroNode $node, PhpWriter $writer)
102: {
103: return $writer->write(($node->args ? 'try { $_presenter->link(%node.word, %node.array?); } catch (Nette\Application\UI\InvalidLinkException $e) {}' : '')
104: . '; if ($_presenter->getLastCreatedRequestFlag("current")) {');
105: }
106:
107:
108:
109:
110:
111: public static function renderSnippets(Nette\Application\UI\Control $control, \stdClass $local, array $params)
112: {
113: $control->snippetMode = FALSE;
114: $payload = $control->getPresenter()->getPayload();
115: if (isset($local->blocks)) {
116: foreach ($local->blocks as $name => $function) {
117: if ($name[0] !== '_' || !$control->isControlInvalid(substr($name, 1))) {
118: continue;
119: }
120: ob_start();
121: $function = reset($function);
122: $snippets = $function($local, $params + array('_snippetMode' => TRUE));
123: $payload->snippets[$id = $control->getSnippetId(substr($name, 1))] = ob_get_clean();
124: if ($snippets !== NULL) {
125: if ($snippets) {
126: $payload->snippets += $snippets;
127: }
128: unset($payload->snippets[$id]);
129: }
130: }
131: }
132: $control->snippetMode = TRUE;
133: if ($control instanceof Nette\Application\UI\IRenderable) {
134: $queue = array($control);
135: do {
136: foreach (array_shift($queue)->getComponents() as $child) {
137: if ($child instanceof Nette\Application\UI\IRenderable) {
138: if ($child->isControlInvalid()) {
139: $child->snippetMode = TRUE;
140: $child->render();
141: $child->snippetMode = FALSE;
142: }
143: } elseif ($child instanceof Nette\ComponentModel\IContainer) {
144: $queue[] = $child;
145: }
146: }
147: } while ($queue);
148: }
149: }
150:
151: }
152: