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