1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Bridges\ApplicationLatte;
9:
10: use Nette;
11: use Latte;
12: use Latte\MacroNode;
13: use Latte\PhpWriter;
14: use Latte\CompileException;
15: use 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, $param[0] === '[' ? 1 : 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
104: ? 'if ($_presenter->isLinkCurrent(%node.word, %node.array?)) {'
105: : 'if ($_presenter->getLastCreatedRequestFlag("current")) {'
106: );
107: }
108:
109:
110:
111:
112:
113: public static function renderSnippets(Nette\Application\UI\Control $control, \stdClass $local, array $params)
114: {
115: $control->snippetMode = FALSE;
116: $payload = $control->getPresenter()->getPayload();
117: if (isset($local->blocks)) {
118: foreach ($local->blocks as $name => $function) {
119: if ($name[0] !== '_' || !$control->isControlInvalid((string) substr($name, 1))) {
120: continue;
121: }
122: ob_start();
123: $function = reset($function);
124: $snippets = $function($local, $params + array('_snippetMode' => TRUE));
125: $payload->snippets[$id = $control->getSnippetId((string) substr($name, 1))] = ob_get_clean();
126: if ($snippets !== NULL) {
127: if ($snippets) {
128: $payload->snippets += $snippets;
129: }
130: unset($payload->snippets[$id]);
131: }
132: }
133: }
134: $control->snippetMode = TRUE;
135: if ($control instanceof Nette\Application\UI\IRenderable) {
136: $queue = array($control);
137: do {
138: foreach (array_shift($queue)->getComponents() as $child) {
139: if ($child instanceof Nette\Application\UI\IRenderable) {
140: if ($child->isControlInvalid()) {
141: $child->snippetMode = TRUE;
142: $child->render();
143: $child->snippetMode = FALSE;
144: }
145: } elseif ($child instanceof Nette\ComponentModel\IContainer) {
146: $queue[] = $child;
147: }
148: }
149: } while ($queue);
150: }
151: }
152:
153: }
154: