diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index bd07bb660..b2068accb 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.2 + php-version: 8.0 coverage: none - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 266902db6..16a6ea65e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -49,7 +49,7 @@ jobs: - uses: actions/checkout@v2 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer install --no-progress --prefer-dist diff --git a/composer.json b/composer.json index 9ae31e55f..a0130b8f9 100644 --- a/composer.json +++ b/composer.json @@ -24,13 +24,13 @@ "nette/application": "^3.0", "nette/di": "^3.0", "nette/tester": "^2.0", - "latte/latte": "^2.10.2", + "latte/latte": "^2.10.2 || ^3.0", "tracy/tracy": "^2.4", "phpstan/phpstan-nette": "^0.12" }, "conflict": { "nette/di": "<3.0-stable", - "latte/latte": ">=3.0" + "latte/latte": ">=3.1" }, "autoload": { "classmap": ["src/"] diff --git a/examples/latte.php b/examples/latte.php index 32bc421d4..3995b8441 100644 --- a/examples/latte.php +++ b/examples/latte.php @@ -39,8 +39,6 @@ } $latte = new Latte\Engine; -$latte->onCompile[] = function ($latte) { - Nette\Bridges\FormsLatte\FormMacros::install($latte->getCompiler()); -}; +$latte->addExtension(new Nette\Bridges\FormsLatte\FormsExtension); $latte->render(__DIR__ . '/latte/page.latte', ['form' => $form]); diff --git a/src/Bridges/FormsLatte/FormMacros.php b/src/Bridges/FormsLatte/FormMacros.php index b411d5bc8..f2d7fbdb7 100644 --- a/src/Bridges/FormsLatte/FormMacros.php +++ b/src/Bridges/FormsLatte/FormMacros.php @@ -17,7 +17,7 @@ /** - * Latte macros for Nette\Forms. + * Latte v2 macros for Nette\Forms. * * - {form name} ... {/form} * - {input name} diff --git a/src/Bridges/FormsLatte/FormsExtension.php b/src/Bridges/FormsLatte/FormsExtension.php new file mode 100644 index 000000000..71fd693d1 --- /dev/null +++ b/src/Bridges/FormsLatte/FormsExtension.php @@ -0,0 +1,34 @@ + [Nodes\FormNode::class, 'create'], + 'formContext' => [Nodes\FormNode::class, 'create'], + 'formContainer' => [Nodes\FormContainerNode::class, 'create'], + 'label' => [Nodes\LabelNode::class, 'create'], + 'input' => [Nodes\InputNode::class, 'create'], + 'inputError' => [Nodes\InputErrorNode::class, 'create'], + 'formPrint' => [Nodes\FormPrintNode::class, 'create'], + 'formClassPrint' => [Nodes\FormPrintNode::class, 'create'], + 'n:name' => [Nodes\NNameNode::class, 'create'], + ]; + } +} diff --git a/src/Bridges/FormsLatte/Nodes/FormContainerNode.php b/src/Bridges/FormsLatte/Nodes/FormContainerNode.php new file mode 100644 index 000000000..18eed8aac --- /dev/null +++ b/src/Bridges/FormsLatte/Nodes/FormContainerNode.php @@ -0,0 +1,64 @@ + */ + public static function create(Tag $tag): \Generator + { + $tag->outputMode = $tag::OutputRemoveIndentation; + $tag->expectArguments(); + + $node = new static; + $node->name = $tag->parser->parseUnquotedStringOrExpression(); + [$node->content] = yield; + return $node; + } + + + public function print(PrintContext $context): string + { + return $context->format( + '$this->global->formsStack[] = $formContainer = ' + . ($this->name instanceof StringNode + ? 'end($this->global->formsStack)[%node]' + : 'is_object($ʟ_tmp = %node) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp]') + . ' %line; %node ' + . 'array_pop($this->global->formsStack); $formContainer = end($this->global->formsStack);' + . "\n\n", + $this->name, + $this->position, + $this->content, + ); + } + + + public function &getIterator(): \Generator + { + yield $this->name; + yield $this->content; + } +} diff --git a/src/Bridges/FormsLatte/Nodes/FormNode.php b/src/Bridges/FormsLatte/Nodes/FormNode.php new file mode 100644 index 000000000..c2902d78d --- /dev/null +++ b/src/Bridges/FormsLatte/Nodes/FormNode.php @@ -0,0 +1,92 @@ + */ + public static function create(Tag $tag): \Generator + { + if ($tag->isNAttribute()) { + throw new CompileException('Did you mean
?', $tag->position); + } + + $tag->outputMode = $tag::OutputKeepIndentation; + $tag->expectArguments(); + $node = new static; + $node->name = $tag->parser->parseUnquotedStringOrExpression(); + $tag->parser->stream->tryConsume(','); + $node->attributes = $tag->parser->parseArguments(); + $node->print = $tag->name === 'form'; + + [$node->content, $endTag] = yield; + $node->endLine = $endTag?->position; + if ($endTag && $node->name instanceof StringNode) { + $endTag->parser->stream->tryConsume($node->name->value); + } + + return $node; + } + + + public function print(PrintContext $context): string + { + return $context->format( + '$form = $this->global->formsStack[] = ' + . ($this->name instanceof StringNode + ? '$this->global->uiControl[%node]' + : 'is_object($ʟ_tmp = %node) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp]') + . ' %line;' + . ($this->print + ? 'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form, %node) %1.line;' + : '') + . ' %3.node ' + . ($this->print + ? 'echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack))' + : 'array_pop($this->global->formsStack)') + . " %4.line;\n\n", + $this->name, + $this->position, + $this->attributes, + $this->content, + $this->endLine, + ); + } + + + public function &getIterator(): \Generator + { + yield $this->name; + yield $this->attributes; + yield $this->content; + } +} diff --git a/src/Bridges/FormsLatte/Nodes/FormPrintNode.php b/src/Bridges/FormsLatte/Nodes/FormPrintNode.php new file mode 100644 index 000000000..ef148995e --- /dev/null +++ b/src/Bridges/FormsLatte/Nodes/FormPrintNode.php @@ -0,0 +1,63 @@ +name = $tag->parser->isEnd() + ? null + : $tag->parser->parseUnquotedStringOrExpression(); + $node->mode = $tag->name; + return $node; + } + + + public function print(PrintContext $context): string + { + return $context->format( + 'Nette\Bridges\FormsLatte\Runtime::render%raw(' + . match (true) { + !$this->name => 'end($this->global->formsStack)', + $this->name instanceof StringNode => '$this->global->uiControl[%node]', + default => 'is_object($ʟ_tmp = %node) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp]', + } + . ') %line; exit;', + $this->mode, + $this->name, + $this->position, + ); + } + + + public function &getIterator(): \Generator + { + if ($this->name) { + yield $this->name; + } + } +} diff --git a/src/Bridges/FormsLatte/Nodes/InputErrorNode.php b/src/Bridges/FormsLatte/Nodes/InputErrorNode.php new file mode 100644 index 000000000..c619aee22 --- /dev/null +++ b/src/Bridges/FormsLatte/Nodes/InputErrorNode.php @@ -0,0 +1,67 @@ +outputMode = $tag::OutputKeepIndentation; + $node = new static; + $node->name = $tag->parser->isEnd() + ? null + : $tag->parser->parseUnquotedStringOrExpression(); + return $node; + } + + + public function print(PrintContext $context): string + { + if (!$this->name) { + return $context->format('echo %escape($ʟ_input->getError()) %line;', $this->position); + + } elseif ($this->name instanceof StringNode) { + return $context->format( + 'echo %escape(end($this->global->formsStack)[%node]->getError()) %line;', + $this->name, + $this->position, + ); + + } else { + return $context->format( + '$ʟ_input = is_object($ʟ_tmp = %node) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];' + . 'echo %escape($ʟ_input->getError()) %line;', + $this->name, + $this->position, + ); + } + } + + + public function &getIterator(): \Generator + { + if ($this->name) { + yield $this->name; + } + } +} diff --git a/src/Bridges/FormsLatte/Nodes/InputNode.php b/src/Bridges/FormsLatte/Nodes/InputNode.php new file mode 100644 index 000000000..310405f8d --- /dev/null +++ b/src/Bridges/FormsLatte/Nodes/InputNode.php @@ -0,0 +1,73 @@ +outputMode = $tag::OutputKeepIndentation; + $tag->expectArguments(); + + $node = new static; + $node->name = $tag->parser->parseUnquotedStringOrExpression(colon: false); + if ($tag->parser->stream->tryConsume(':') && !$tag->parser->stream->is(',')) { + $node->part = $tag->parser->isEnd() + ? new StringNode('') + : $tag->parser->parseUnquotedStringOrExpression(); + } + $tag->parser->stream->tryConsume(','); + $node->attributes = $tag->parser->parseArguments(); + return $node; + } + + + public function print(PrintContext $context): string + { + return $context->format( + ($this->name instanceof StringNode + ? 'echo end($this->global->formsStack)[%node]->' + : '$ʟ_input = is_object($ʟ_tmp = %node) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp]; echo $ʟ_input->') + . ($this->part ? ('getControlPart(%node)') : 'getControl()') + . ($this->attributes->items ? '->addAttributes(%2.node)' : '') + . ' %3.line;', + $this->name, + $this->part, + $this->attributes, + $this->position, + ); + } + + + public function &getIterator(): \Generator + { + yield $this->name; + if ($this->part) { + yield $this->part; + } + yield $this->attributes; + } +} diff --git a/src/Bridges/FormsLatte/Nodes/LabelNode.php b/src/Bridges/FormsLatte/Nodes/LabelNode.php new file mode 100644 index 000000000..42176a7ac --- /dev/null +++ b/src/Bridges/FormsLatte/Nodes/LabelNode.php @@ -0,0 +1,92 @@ + */ + public static function create(Tag $tag): \Generator + { + if ($tag->isNAttribute()) { + throw new CompileException('Did you mean
+ global->formsStack)['username']; + echo $ʟ_input->getControlPart()->addAttributes(['value' => null, 'type' => null, 'class' => null])->attributes() /* line %d% */; + echo '> + + global->formsStack)[$ʟ_tmp]; + echo $ʟ_input->getLabelPart()->attributes() /* line %d% */; + echo '> + global->formsStack)[$ʟ_tmp]; + echo $ʟ_input->getLabelPart()->attributes() /* line %d% */; + echo '>'; + echo $ʟ_input->getLabelPart()->getHtml() /* line %d% */; + echo ' + global->formsStack)[$ʟ_tmp]; + echo $ʟ_input->getControlPart()->attributes() /* line %d% */; + echo '> + + '; + if ($ʟ_label = end($this->global->formsStack)['my']->getLabel()) echo $ʟ_label /* line %d% */; + echo end($this->global->formsStack)['my']->getControl() /* line %d% */; + echo "\n"; + echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack)) /* line %d% */; + + echo ' + + +'; + $form = $this->global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */; + echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form, []) /* line %d% */; + echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack)) /* line %d% */; + + echo ' + +'; + $form = $this->global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */; + echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form, []) /* line %d% */; + echo "\n"; + foreach ($form['sex']->items as $key => $label) /* line %d% */ { + echo ' '; + if ($ʟ_label = end($this->global->formsStack)['sex']->getLabelPart($key)) echo $ʟ_label->startTag() /* line %d% */; + echo ' '; + echo end($this->global->formsStack)['sex']->getControlPart($key) /* line %d% */; + echo ' '; + echo LR\Filters::escapeHtmlText($label) /* line %d% */; + if ($ʟ_label) echo $ʟ_label->endTag() /* line %d% */; + echo ' + global->formsStack)['sex']; + echo $ʟ_input->getLabelPart($key)->addAttributes(['title' => null])->attributes() /* line %d% */; + echo ' title=hello> global->formsStack)['sex']; + echo $ʟ_input->getControlPart($key)->attributes() /* line %d% */; + echo '> +'; + + } + + echo 'global->formsStack)['sex']; + echo $ʟ_input->getLabelPart()->attributes() /* line %d% */; + echo '> +global->formsStack)['sex']; + echo $ʟ_input->getLabelPart()->attributes() /* line %d% */; + echo '>'; + echo $ʟ_input->getLabelPart()->getHtml() /* line %d% */; + echo ' +global->formsStack)['sex']; + echo $ʟ_input->getLabelPart()->addAttributes(['title' => null])->attributes() /* line %d% */; + echo ' title="hello">'; + echo $ʟ_input->getLabelPart()->getHtml() /* line %d% */; + echo ' +global->formsStack)[$ʟ_tmp]; + echo $ʟ_input->getControlPart("{$key}")->attributes() /* line %d% */; + echo '> + + +'; + if ($ʟ_label = end($this->global->formsStack)['checkbox']->getLabelPart('')) echo $ʟ_label->startTag() /* line %d% */; + echo ' '; + echo end($this->global->formsStack)['checkbox']->getControlPart('') /* line %d% */; + echo ' Label'; + if ($ʟ_label) echo $ʟ_label->endTag() /* line %d% */; + echo ' +global->formsStack)['checkbox']; + echo $ʟ_input->getLabelPart('')->addAttributes(['title' => null])->attributes() /* line %d% */; + echo ' title=hello> global->formsStack)['checkbox']; + echo $ʟ_input->getControlPart('')->attributes() /* line %d% */; + echo '> +global->formsStack)['checkbox']; + echo $ʟ_input->getLabelPart()->addAttributes(['title' => null])->attributes() /* line %d% */; + echo ' title=hello> global->formsStack)['checkbox']; + echo $ʟ_input->getControlPart()->attributes() /* line %d% */; + echo '> +global->formsStack)['checkbox']; + echo $ʟ_input->getLabelPart('')->attributes() /* line %d% */; + echo '>'; + echo $ʟ_input->getLabelPart()->getHtml() /* line %d% */; + echo ' +global->formsStack)['checkbox']; + echo $ʟ_input->getLabelPart()->addAttributes(['title' => null])->attributes() /* line %d% */; + echo ' title=hello>'; + echo $ʟ_input->getLabelPart()->getHtml() /* line %d% */; + echo ' + + +'; + foreach ($form['checklist']->items as $key => $label) /* line %d% */ { + echo ' '; + if ($ʟ_label = end($this->global->formsStack)['checklist']->getLabelPart($key)) echo $ʟ_label->startTag() /* line %d% */; + echo ' '; + echo end($this->global->formsStack)['checklist']->getControlPart($key) /* line %d% */; + echo ' '; + echo LR\Filters::escapeHtmlText($label) /* line %d% */; + if ($ʟ_label) echo $ʟ_label->endTag() /* line %d% */; + echo ' + global->formsStack)['checklist']; + echo $ʟ_input->getLabelPart($key)->attributes() /* line %d% */; + echo '> global->formsStack)['checklist']; + echo $ʟ_input->getControlPart($key)->addAttributes(['title' => null])->attributes() /* line %d% */; + echo ' title=hello> +'; + + } + + echo 'global->formsStack)['checklist']; + echo $ʟ_input->getLabelPart()->attributes() /* line %d% */; + echo '> +global->formsStack)['checklist']; + echo $ʟ_input->getLabelPart()->attributes() /* line %d% */; + echo '>'; + echo $ʟ_input->getLabelPart()->getHtml() /* line %d% */; + echo ' +global->formsStack)['checklist']; + echo $ʟ_input->getLabelPart()->addAttributes(['title' => null])->attributes() /* line %d% */; + echo ' title="hello">'; + echo $ʟ_input->getLabelPart()->getHtml() /* line %d% */; + echo ' + + +'; + if (1) /* line %d% */ { + echo 'global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */; + echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin(end($this->global->formsStack), ['id' => null, 'class' => null], false) /* line %d% */; + echo ' id="myForm" class="ajax"> + global->formsStack)['username']; + echo $ʟ_input->getControlPart()->attributes() /* line %d% */; + echo '> +'; + echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack), false) /* line %d% */; + echo ' +'; + } + echo ' + +global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */; + echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin(end($this->global->formsStack), ['class' => null], false) /* line %d% */; + echo ($ʟ_tmp = array_filter(['nclass'])) ? ' class="' . LR\Filters::escapeHtmlAttr(implode(" ", array_unique($ʟ_tmp))) . '"' : "" /* line %d% */; + echo '> + global->formsStack)['username']; + echo $ʟ_input->getControlPart()->addAttributes(['class' => null])->attributes() /* line %d% */; + echo ($ʟ_tmp = array_filter(['nclass'])) ? ' class="' . LR\Filters::escapeHtmlAttr(implode(" ", array_unique($ʟ_tmp))) . '"' : "" /* line %d% */; + echo '> +'; + echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack), false) /* line %d% */; + echo ' + + +global->formsStack[] = is_object($ʟ_tmp = $this->global->uiControl['myForm']) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp] /* line %d% */; + echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin(end($this->global->formsStack), [], false) /* line %d% */; + echo '> + global->formsStack)['username']; + echo $ʟ_input->getControlPart()->attributes() /* line %d% */; + echo '> +'; + echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack), false) /* line %d% */; + echo ' + + +global->formsStack)['select']; + echo $ʟ_input->getControlPart()->attributes() /* line %d% */; + echo '>'; + echo $ʟ_input->getControl()->getHtml() /* line %d% */; + echo ' + + +global->formsStack)['area']; + echo $ʟ_input->getControlPart()->addAttributes(['title' => null])->attributes() /* line %d% */; + echo ' title="'; + echo LR\Filters::escapeHtmlAttr(10) /* line %d% */; + echo '">'; + echo $ʟ_input->getControl()->getHtml() /* line %d% */; + echo ' + + +global->formsStack)['select']; + echo $ʟ_input->getControlPart()->attributes() /* line %d% */; + echo '>'; + echo $ʟ_input->getControl()->getHtml() /* line %d% */; + echo ' +'; + echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack)) /* line %d% */; + + echo ' + + +'; + $form = $this->global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */; + echo ' +global->formsStack)['sex']; + echo $ʟ_input->getLabelPart()->attributes() /* line %d% */; + echo '>'; + echo $ʟ_input->getLabelPart()->getHtml() /* line %d% */; + echo ' +global->formsStack)['username']; + echo $ʟ_input->getControlPart()->attributes() /* line %d% */; + echo '> +'; + array_pop($this->global->formsStack) /* line %d% */; +%A% diff --git a/tests/Forms.Latte3/forms.button.phpt b/tests/Forms.Latte3/forms.button.phpt new file mode 100644 index 000000000..a1cb3ac94 --- /dev/null +++ b/tests/Forms.Latte3/forms.button.phpt @@ -0,0 +1,31 @@ +addSubmit('send', 'Sign in'); + +$latte = new Latte\Engine; +$latte->addExtension(new FormsExtension); +$latte->addProvider('uiControl', ['myForm' => $form]); + +Assert::matchFile( + __DIR__ . '/expected/forms.button.phtml', + $latte->compile(__DIR__ . '/templates/forms.button.latte') +); + +Assert::matchFile( + __DIR__ . '/expected/forms.button.html', + $latte->renderToString(__DIR__ . '/templates/forms.button.latte') +); diff --git a/tests/Forms.Latte3/forms.error.phpt b/tests/Forms.Latte3/forms.error.phpt new file mode 100644 index 000000000..01f7e7d6a --- /dev/null +++ b/tests/Forms.Latte3/forms.error.phpt @@ -0,0 +1,51 @@ +setLoader(new Latte\Loaders\StringLoader); +$latte->addExtension(new FormsExtension); + +Assert::exception(function () use ($latte) { + $latte->compile('
'); +}, Latte\CompileException::class, 'Did you mean
? (at column 7)'); + +Assert::exception(function () use ($latte) { + $latte->compile('
'); +}, Latte\CompileException::class, 'Missing arguments in n:name (at column 7)'); + +Assert::exception(function () use ($latte) { + $latte->compile('
'); +}, Latte\CompileException::class, 'Unexpected attribute n:inner-name, did you mean n:inner-label? (at column 7)'); + + +Assert::exception(function () use ($latte) { + $latte->compile('{form /}'); +}, Latte\CompileException::class, 'Missing arguments in {form} (at column 7)'); + +Assert::exception(function () use ($latte) { + $latte->compile('{formContainer /}'); +}, Latte\CompileException::class, 'Missing arguments in {formContainer} (at column 7)'); + + +Assert::exception(function () use ($latte) { + $latte->compile('{label /}'); +}, Latte\CompileException::class, 'Missing arguments in {label} (at column 7)'); + +Assert::exception(function () use ($latte) { + $latte->compile('{input /}'); +}, Latte\CompileException::class, 'Missing arguments in {input} (at column 7)'); + +Assert::exception(function () use ($latte) { + $latte->compile('{name /}'); +}, Latte\CompileException::class, 'Unexpected tag {name} (at column 7)'); diff --git a/tests/Forms.Latte3/forms.formContainer.phpt b/tests/Forms.Latte3/forms.formContainer.phpt new file mode 100644 index 000000000..fc5b3a901 --- /dev/null +++ b/tests/Forms.Latte3/forms.formContainer.phpt @@ -0,0 +1,51 @@ +addText('input1', 'Input 1'); + +$cont1 = $form->addContainer('cont1'); +$cont1->addText('input2', 'Input 2'); +$cont1->addText('input3', 'Input 3'); + +$cont2 = $cont1->addContainer('cont2'); +$cont2->addCheckbox('input4', 'Input 4'); +$cont2->addCheckbox('input5', 'Input 5'); +$cont2->addCheckbox('input6', 'Input 6'); + +$cont1->addText('input7', 'Input 7'); + +$contItems = $form->addContainer('items'); +$items = [1, 3]; +foreach ($items as $item) { + $contItem = $contItems->addContainer($item); + $contItem->addText('input', 'Input'); +} + +$form->addSubmit('input8', 'Input 8'); + + +$latte = new Latte\Engine; +$latte->addExtension(new FormsExtension); +$latte->addProvider('uiControl', ['myForm' => $form]); + +Assert::matchFile( + __DIR__ . '/expected/forms.formContainer.phtml', + $latte->compile(__DIR__ . '/templates/forms.formContainer.latte') +); +Assert::matchFile( + __DIR__ . '/expected/forms.formContainer.html', + $latte->renderToString(__DIR__ . '/templates/forms.formContainer.latte') +); diff --git a/tests/Forms.Latte3/forms.get.phpt b/tests/Forms.Latte3/forms.get.phpt new file mode 100644 index 000000000..76f253873 --- /dev/null +++ b/tests/Forms.Latte3/forms.get.phpt @@ -0,0 +1,32 @@ +setMethod('get'); +$form->setAction('?arg=val'); +$form->addSubmit('send', 'Sign in'); + +$latte = new Latte\Engine; +$latte->addExtension(new FormsExtension); +$latte->addProvider('uiControl', ['myForm' => $form]); + +Assert::matchFile( + __DIR__ . '/expected/forms.get.phtml', + $latte->compile(__DIR__ . '/templates/forms.get.latte') +); +Assert::matchFile( + __DIR__ . '/expected/forms.get.html', + $latte->renderToString(__DIR__ . '/templates/forms.get.latte') +); diff --git a/tests/Forms.Latte3/forms.phpt b/tests/Forms.Latte3/forms.phpt new file mode 100644 index 000000000..86cab7ff1 --- /dev/null +++ b/tests/Forms.Latte3/forms.phpt @@ -0,0 +1,57 @@ +My'; + } + + + public function getControl() + { + return ''; + } +} + + +$form = new Form; +$form->getElementPrototype()->addClass('form-class'); +$form->addHidden('id'); +$form->addText('username', 'Username:'); // must have just one textfield to generate IE fix +$form['username']->getControlPrototype()->addClass('control-class'); +$form->addRadioList('sex', 'Sex:', ['m' => 'male', 'f' => 'female']); +$form->addSelect('select', null, ['m' => 'male', 'f' => 'female']); +$form->addTextArea('area', null)->setValue('oneaddCheckbox('checkbox', 'Checkbox'); +$form->addCheckboxList('checklist', 'CheckboxList:', ['m' => 'male', 'f' => 'female']); +$form->addSubmit('send', 'Sign in'); +$form['my'] = new MyControl; + +$latte = new Latte\Engine; +$latte->addExtension(new FormsExtension); +$latte->addProvider('uiControl', ['myForm' => $form]); + +$form['username']->addError('error'); + +Assert::matchFile( + __DIR__ . '/expected/forms.phtml', + $latte->compile(__DIR__ . '/templates/forms.latte') +); +Assert::matchFile( + __DIR__ . '/expected/forms.html', + $latte->renderToString(__DIR__ . '/templates/forms.latte') +); diff --git a/tests/Forms.Latte3/templates/forms.button.latte b/tests/Forms.Latte3/templates/forms.button.latte new file mode 100644 index 000000000..8e9969b37 --- /dev/null +++ b/tests/Forms.Latte3/templates/forms.button.latte @@ -0,0 +1,9 @@ +
+ + + + +