1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Bridges\FormsLatte;
9:
10: use Nette;
11: use Latte;
12: use Latte\MacroNode;
13: use Latte\PhpWriter;
14: use Latte\CompileException;
15: use Latte\Macros\MacroSet;
16: use Nette\Forms\Form;
17:
18:
19: 20: 21: 22: 23: 24: 25: 26: 27:
28: class FormMacros extends MacroSet
29: {
30:
31: public static function install(Latte\Compiler $compiler)
32: {
33: $me = new static($compiler);
34: $me->addMacro('form', [$me, 'macroForm'], 'echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack));');
35: $me->addMacro('formContainer', [$me, 'macroFormContainer'], 'array_pop($this->global->formsStack); $formContainer = $_form = end($this->global->formsStack)');
36: $me->addMacro('label', [$me, 'macroLabel'], [$me, 'macroLabelEnd'], NULL, self::AUTO_EMPTY);
37: $me->addMacro('input', [$me, 'macroInput']);
38: $me->addMacro('name', [$me, 'macroName'], [$me, 'macroNameEnd'], [$me, 'macroNameAttr']);
39: $me->addMacro('inputError', [$me, 'macroInputError']);
40: }
41:
42:
43:
44:
45:
46: 47: 48:
49: public function macroForm(MacroNode $node, PhpWriter $writer)
50: {
51: if ($node->modifiers) {
52: throw new CompileException('Modifiers are not allowed in ' . $node->getNotation());
53: }
54: if ($node->prefix) {
55: throw new CompileException('Did you mean <form n:name=...> ?');
56: }
57: $name = $node->tokenizer->fetchWord();
58: if ($name === FALSE) {
59: throw new CompileException('Missing form name in ' . $node->getNotation());
60: }
61: $node->replaced = TRUE;
62: $node->tokenizer->reset();
63: return $writer->write(
64: "/* line $node->startLine */\n"
65: . 'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form = $_form = $this->global->formsStack[] = '
66: . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
67: . '$this->global->uiControl[%node.word], %node.array);'
68: );
69: }
70:
71:
72: 73: 74:
75: public function macroFormContainer(MacroNode $node, PhpWriter $writer)
76: {
77: if ($node->modifiers) {
78: throw new CompileException('Modifiers are not allowed in ' . $node->getNotation());
79: }
80: $name = $node->tokenizer->fetchWord();
81: if ($name === FALSE) {
82: throw new CompileException('Missing name in ' . $node->getNotation());
83: }
84: $node->tokenizer->reset();
85: return $writer->write(
86: '$this->global->formsStack[] = $formContainer = $_form = '
87: . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
88: . 'end($this->global->formsStack)[%node.word];'
89: );
90: }
91:
92:
93: 94: 95:
96: public function macroLabel(MacroNode $node, PhpWriter $writer)
97: {
98: if ($node->modifiers) {
99: throw new CompileException('Modifiers are not allowed in ' . $node->getNotation());
100: }
101: $words = $node->tokenizer->fetchWords();
102: if (!$words) {
103: throw new CompileException('Missing name in ' . $node->getNotation());
104: }
105: $node->replaced = true;
106: $name = array_shift($words);
107: return $writer->write(
108: ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : end($this->global->formsStack)[%0.word]; if ($_label = $_input' : 'if ($_label = end($this->global->formsStack)[%0.word]')
109: . '->%1.raw) echo $_label'
110: . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''),
111: $name,
112: $words ? ('getLabelPart(' . implode(', ', array_map([$writer, 'formatWord'], $words)) . ')') : 'getLabel()'
113: );
114: }
115:
116:
117: 118: 119:
120: public function macroLabelEnd(MacroNode $node, PhpWriter $writer)
121: {
122: if ($node->content != NULL) {
123: $node->openingCode = rtrim($node->openingCode, '?> ') . '->startTag() ?>';
124: return $writer->write('if ($_label) echo $_label->endTag()');
125: }
126: }
127:
128:
129: 130: 131:
132: public function macroInput(MacroNode $node, PhpWriter $writer)
133: {
134: if ($node->modifiers) {
135: throw new CompileException('Modifiers are not allowed in ' . $node->getNotation());
136: }
137: $words = $node->tokenizer->fetchWords();
138: if (!$words) {
139: throw new CompileException('Missing name in ' . $node->getNotation());
140: }
141: $node->replaced = true;
142: $name = array_shift($words);
143: return $writer->write(
144: ($name[0] === '$' ? '$_input = is_object(%0.word) ? %0.word : end($this->global->formsStack)[%0.word]; echo $_input' : 'echo end($this->global->formsStack)[%0.word]')
145: . '->%1.raw'
146: . ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : '')
147: . " /* line $node->startLine */",
148: $name,
149: $words ? 'getControlPart(' . implode(', ', array_map([$writer, 'formatWord'], $words)) . ')' : 'getControl()'
150: );
151: }
152:
153:
154: 155: 156:
157: public function macroNameAttr(MacroNode $node, PhpWriter $writer)
158: {
159: $words = $node->tokenizer->fetchWords();
160: if (!$words) {
161: throw new CompileException('Missing name in ' . $node->getNotation());
162: }
163: $name = array_shift($words);
164: $tagName = strtolower($node->htmlNode->name);
165: $node->empty = $tagName === 'input';
166:
167: if ($tagName === 'form') {
168: $node->openingCode = $writer->write(
169: '<?php $form = $_form = $this->global->formsStack[] = '
170: . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
171: . '$this->global->uiControl[%0.word]; ?>',
172: $name
173: );
174: return $writer->write(
175: 'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin(end($this->global->formsStack), %0.var, FALSE)',
176: array_fill_keys(array_keys($node->htmlNode->attrs), NULL)
177: );
178: } else {
179: $method = $tagName === 'label' ? 'getLabel' : 'getControl';
180: return $writer->write(
181: '$_input = ' . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
182: . 'end($this->global->formsStack)[%0.word]; echo $_input->%1.raw'
183: . ($node->htmlNode->attrs ? '->addAttributes(%2.var)' : '') . '->attributes()',
184: $name,
185: $method . 'Part(' . implode(', ', array_map([$writer, 'formatWord'], $words)) . ')',
186: array_fill_keys(array_keys($node->htmlNode->attrs), NULL)
187: );
188: }
189: }
190:
191:
192: public function macroName(MacroNode $node, PhpWriter $writer)
193: {
194: if (!$node->prefix) {
195: throw new CompileException("Unknown macro {{$node->name}}, use n:{$node->name} attribute.");
196: } elseif ($node->prefix !== MacroNode::PREFIX_NONE) {
197: throw new CompileException("Unknown attribute n:{$node->prefix}-{$node->name}, use n:{$node->name} attribute.");
198: }
199: }
200:
201:
202: public function macroNameEnd(MacroNode $node, PhpWriter $writer)
203: {
204: $tagName = strtolower($node->htmlNode->name);
205: if ($tagName === 'form') {
206: $node->innerContent .= '<?php echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack), FALSE); ?>';
207: } elseif ($tagName === 'label') {
208: if ($node->htmlNode->empty) {
209: $node->innerContent = "<?php echo \$_input->getLabelPart()->getHtml() ?>";
210: }
211: } elseif ($tagName === 'button') {
212: if ($node->htmlNode->empty) {
213: $node->innerContent = '<?php echo htmlspecialchars($_input->caption) ?>';
214: }
215: } else {
216: $node->innerContent = '<?php echo $_input->getControl()->getHtml() ?>';
217: }
218: }
219:
220:
221: 222: 223:
224: public function macroInputError(MacroNode $node, PhpWriter $writer)
225: {
226: if ($node->modifiers) {
227: throw new CompileException('Modifiers are not allowed in ' . $node->getNotation());
228: }
229: $name = $node->tokenizer->fetchWord();
230: $node->replaced = true;
231: if (!$name) {
232: return $writer->write('echo %escape($_input->getError());');
233: } elseif ($name[0] === '$') {
234: return $writer->write('$_input = is_object(%0.word) ? %0.word : end($this->global->formsStack)[%0.word]; echo %escape($_input->getError());', $name);
235: } else {
236: return $writer->write('echo %escape(end($this->global->formsStack)[%0.word]->getError());', $name);
237: }
238: }
239:
240:
241:
242: public static function renderFormBegin(Form $form, array $attrs, $withTags = TRUE)
243: {
244: trigger_error(__METHOD__ . '() is deprecated, use Nette\Bridges\FormsLatte\Runtime::renderFormBegin()', E_USER_DEPRECATED);
245: echo Runtime::renderFormBegin($form, $attrs, $withTags);
246: }
247:
248:
249:
250: public static function renderFormEnd(Form $form, $withTags = TRUE)
251: {
252: trigger_error(__METHOD__ . '() is deprecated, use Nette\Bridges\FormsLatte\Runtime::renderFormEnd()', E_USER_DEPRECATED);
253: echo Runtime::renderFormEnd($form, $withTags);
254: }
255:
256: }
257: