diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md
deleted file mode 100644
index a4cd12634..000000000
--- a/.github/ISSUE_TEMPLATE/Bug_report.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-name: "🐛 Bug Report"
-about: "If something isn't working as expected 🤔"
-
----
-
-Version: ?.?.?
-
-### Bug Description
-... A clear and concise description of what the bug is. A good bug report shouldn't leave others needing to chase you up for more information.
-
-### Steps To Reproduce
-... If possible a minimal demo of the problem ...
-
-### Expected Behavior
-... A clear and concise description of what you expected to happen.
-
-### Possible Solution
-... Only if you have suggestions on a fix for the bug
diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md
deleted file mode 100644
index d2e219489..000000000
--- a/.github/ISSUE_TEMPLATE/Feature_request.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-name: "🚀 Feature Request"
-about: "I have a suggestion (and may want to implement it) 🙂"
-
----
-
-- Is your feature request related to a problem? Please describe.
-- Explain your intentions.
-- It's up to you to make a strong case to convince the project's developers of the merits of this feature.
diff --git a/.github/ISSUE_TEMPLATE/Support_question.md b/.github/ISSUE_TEMPLATE/Support_question.md
deleted file mode 100644
index 75c48b6ed..000000000
--- a/.github/ISSUE_TEMPLATE/Support_question.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-name: "🤗 Support Question"
-about: "If you have a question 💬, please check out our forum!"
-
----
-
---------------^ Click "Preview" for a nicer view!
-We primarily use GitHub as an issue tracker; for usage and support questions, please check out these resources below. Thanks! 😁.
-
-* Nette Forum: https://forum.nette.org
-* Nette Gitter: https://gitter.im/nette/nette
-* Slack (czech): https://pehapkari.slack.com/messages/C2R30BLKA
diff --git a/.github/ISSUE_TEMPLATE/Support_us.md b/.github/ISSUE_TEMPLATE/Support_us.md
deleted file mode 100644
index 92d8a4c3a..000000000
--- a/.github/ISSUE_TEMPLATE/Support_us.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-name: "❤️ Support us"
-about: "If you would like to support our efforts in maintaining this project 🙌"
-
----
-
---------------^ Click "Preview" for a nicer view!
-
-> https://nette.org/donate
-
-Help support Nette!
-
-We develop Nette Framework for more than 14 years. In order to make your life more comfortable. Nette cares about the safety of your sites. Nette saves you time. And gives job opportunities.
-
-Nette earns you money. And is absolutely free.
-
-To ensure future development and improving the documentation, we need your donation.
-
-Whether you are chief of IT company which benefits from Nette, or developer who goes for advice on our forum, if you like Nette, [please make a donation now](https://nette.org/donate).
-
-Thank you!
diff --git a/.github/funding.yml b/.github/funding.yml
deleted file mode 100644
index 25adc9520..000000000
--- a/.github/funding.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-github: dg
-custom: "https://nette.org/donate"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
deleted file mode 100644
index f8aa3f408..000000000
--- a/.github/pull_request_template.md
+++ /dev/null
@@ -1,11 +0,0 @@
-- bug fix / new feature?
-- BC break? yes/no
-- doc PR: nette/docs#???
-
-
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/static-analysis.yml b/.github/workflows/static-analysis.yml
index 28fd47e63..e09916b5e 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -10,7 +10,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/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 266902db6..82b6f1861 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- php: ['7.2', '7.3', '7.4', '8.0', '8.1']
+ php: ['8.0', '8.1']
fail-fast: false
@@ -35,7 +35,7 @@ jobs:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
- php-version: 7.2
+ php-version: 8.0
coverage: none
- run: composer update --no-progress --prefer-dist --prefer-lowest --prefer-stable
@@ -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..00d6a31b8 100644
--- a/composer.json
+++ b/composer.json
@@ -15,22 +15,22 @@
}
],
"require": {
- "php": ">=7.2 <8.2",
- "nette/component-model": "^3.0",
- "nette/http": "^3.1",
- "nette/utils": "^3.2.1"
+ "php": ">=8.0 <8.2",
+ "nette/component-model": "^4.0",
+ "nette/http": "^4.0",
+ "nette/utils": "^4.0"
},
"require-dev": {
- "nette/application": "^3.0",
- "nette/di": "^3.0",
- "nette/tester": "^2.0",
- "latte/latte": "^2.10.2",
- "tracy/tracy": "^2.4",
- "phpstan/phpstan-nette": "^0.12"
+ "nette/application": "^4.0",
+ "nette/di": "^4.0",
+ "nette/tester": "^2.4",
+ "latte/latte": "^2.10.2 || ^3.0",
+ "tracy/tracy": "^2.8",
+ "phpstan/phpstan-nette": "^1.0"
},
"conflict": {
"nette/di": "<3.0-stable",
- "latte/latte": ">=3.0"
+ "latte/latte": ">=3.1"
},
"autoload": {
"classmap": ["src/"]
@@ -42,7 +42,7 @@
},
"extra": {
"branch-alias": {
- "dev-master": "3.1-dev"
+ "dev-master": "4.0-dev"
}
}
}
diff --git a/contributing.md b/contributing.md
deleted file mode 100644
index 184152c02..000000000
--- a/contributing.md
+++ /dev/null
@@ -1,33 +0,0 @@
-How to contribute & use the issue tracker
-=========================================
-
-Nette welcomes your contributions. There are several ways to help out:
-
-* Create an issue on GitHub, if you have found a bug
-* Write test cases for open bug issues
-* Write fixes for open bug/feature issues, preferably with test cases included
-* Contribute to the [documentation](https://nette.org/en/writing)
-
-Issues
-------
-
-Please **do not use the issue tracker to ask questions**. We will be happy to help you
-on [Nette forum](https://forum.nette.org) or chat with us on [Gitter](https://gitter.im/nette/nette).
-
-A good bug report shouldn't leave others needing to chase you up for more
-information. Please try to be as detailed as possible in your report.
-
-**Feature requests** are welcome. But take a moment to find out whether your idea
-fits with the scope and aims of the project. It's up to *you* to make a strong
-case to convince the project's developers of the merits of this feature.
-
-Contributing
-------------
-
-If you'd like to contribute, please take a moment to read [the contributing guide](https://nette.org/en/contributing).
-
-The best way to propose a feature is to discuss your ideas on [Nette forum](https://forum.nette.org) before implementing them.
-
-Please do not fix whitespace, format code, or make a purely cosmetic patch.
-
-Thanks! :heart:
diff --git a/examples/custom-control.php b/examples/custom-control.php
index 0d21740ed..b8e06b32b 100644
--- a/examples/custom-control.php
+++ b/examples/custom-control.php
@@ -18,12 +18,11 @@
class DateInput extends Nette\Forms\Controls\BaseControl
{
- /** @var string */
- private $day = '';
+ private string $day = '';
- private $month = '';
+ private string $month = '';
- private $year = '';
+ private string $year = '';
public function __construct($label = null)
@@ -88,7 +87,7 @@ public function getControl()
. Helpers::createSelectBox(
[1 => 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[],
- $this->month
+ $this->month,
)->name($name . '[month]')
. Html::el('input', [
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/readme.md b/readme.md
index 945ea9a94..f6196c3a2 100644
--- a/readme.md
+++ b/readme.md
@@ -44,7 +44,7 @@ The recommended way to install is via Composer:
composer require nette/forms
```
-It requires PHP version 7.2 and supports PHP up to 8.1.
+It requires PHP version 8.0 and supports PHP up to 8.1.
Client-side support can be installed with npm or yarn:
diff --git a/src/Bridges/FormsDI/FormsExtension.php b/src/Bridges/FormsDI/FormsExtension.php
index 58281781b..5b4989f89 100644
--- a/src/Bridges/FormsDI/FormsExtension.php
+++ b/src/Bridges/FormsDI/FormsExtension.php
@@ -21,7 +21,7 @@ public function __construct()
{
$this->config = new class {
/** @var string[] */
- public $messages = [];
+ public array $messages = [];
};
}
diff --git a/src/Bridges/FormsLatte/FormMacros.php b/src/Bridges/FormsLatte/FormMacros.php
index 3b125a8ff..c92c1c59b 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}
@@ -68,9 +68,11 @@ public function macroForm(MacroNode $node, PhpWriter $writer)
$node->tokenizer->reset();
return $writer->write(
'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form = $this->global->formsStack[] = '
- . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
- . '$this->global->uiControl[%node.word], %node.array)'
- . " /* line $node->startLine */;"
+ . ($name[0] === '$'
+ ? 'is_object($ʟ_tmp = %node.word) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp]'
+ : '$this->global->uiControl[%node.word]')
+ . ', %node.array)'
+ . " /* line $node->startLine */;",
);
}
@@ -96,9 +98,10 @@ public function macroFormContext(MacroNode $node, PhpWriter $writer)
$node->tokenizer->reset();
return $writer->write(
'$form = $this->global->formsStack[] = '
- . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
- . '$this->global->uiControl[%node.word]'
- . " /* line $node->startLine */;"
+ . ($name[0] === '$'
+ ? 'is_object($ʟ_tmp = %node.word) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp]'
+ : '$this->global->uiControl[%node.word]')
+ . " /* line $node->startLine */;",
);
}
@@ -120,9 +123,10 @@ public function macroFormContainer(MacroNode $node, PhpWriter $writer)
$node->tokenizer->reset();
return $writer->write(
'$this->global->formsStack[] = $formContainer = '
- . ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
- . 'end($this->global->formsStack)[%node.word]'
- . " /* line $node->startLine */;"
+ . ($name[0] === '$'
+ ? 'is_object($ʟ_tmp = %node.word) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp]'
+ : 'end($this->global->formsStack)[%node.word]')
+ . " /* line $node->startLine */;",
);
}
@@ -145,13 +149,13 @@ public function macroLabel(MacroNode $node, PhpWriter $writer)
$name = array_shift($words);
return $writer->write(
($name[0] === '$'
- ? '$ʟ_input = is_object(%0.word) ? %0.word : end($this->global->formsStack)[%0.word]; if ($ʟ_label = $ʟ_input'
+ ? '$ʟ_input = is_object($ʟ_tmp = %0.word) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp]; if ($ʟ_label = $ʟ_input'
: 'if ($ʟ_label = end($this->global->formsStack)[%0.word]'
)
. '->%1.raw) echo $ʟ_label'
. ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : ''),
$name,
- $words ? ('getLabelPart(' . implode(', ', array_map([$writer, 'formatWord'], $words)) . ')') : 'getLabel()'
+ $words ? ('getLabelPart(' . implode(', ', array_map([$writer, 'formatWord'], $words)) . ')') : 'getLabel()',
);
}
@@ -185,12 +189,14 @@ public function macroInput(MacroNode $node, PhpWriter $writer)
$node->replaced = true;
$name = array_shift($words);
return $writer->write(
- ($name[0] === '$' ? '$ʟ_input = $_input = is_object(%0.word) ? %0.word : end($this->global->formsStack)[%0.word]; echo $ʟ_input' : 'echo end($this->global->formsStack)[%0.word]')
- . '->%1.raw'
+ ($name[0] === '$'
+ ? '$ʟ_input = $_input = is_object($ʟ_tmp = %word) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp]; echo $ʟ_input'
+ : 'echo end($this->global->formsStack)[%word]')
+ . '->%raw'
. ($node->tokenizer->isNext() ? '->addAttributes(%node.array)' : '')
. " /* line $node->startLine */;",
$name,
- $words ? 'getControlPart(' . implode(', ', array_map([$writer, 'formatWord'], $words)) . ')' : 'getControl()'
+ $words ? 'getControlPart(' . implode(', ', array_map([$writer, 'formatWord'], $words)) . ')' : 'getControl()',
);
}
@@ -217,24 +223,29 @@ public function macroNameAttr(MacroNode $node, PhpWriter $writer)
if ($tagName === 'form') {
$node->openingCode = $writer->write(
'global->formsStack[] = '
- . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
- . "\$this->global->uiControl[%0.word] /* line $node->startLine */; ?>",
- $name
+ . ($name[0] === '$'
+ ? 'is_object($ʟ_tmp = %0.word) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp]'
+ : '$this->global->uiControl[%0.word]')
+ . " /* line $node->startLine */; ?>",
+ $name,
);
return $writer->write(
'echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin(end($this->global->formsStack), %0.var, false)',
- array_fill_keys($definedHtmlAttributes, null)
+ array_fill_keys($definedHtmlAttributes, null),
);
} else {
$method = $tagName === 'label' ? 'getLabel' : 'getControl';
return $writer->write(
- '$ʟ_input = $_input = ' . ($name[0] === '$' ? 'is_object(%0.word) ? %0.word : ' : '')
- . 'end($this->global->formsStack)[%0.word]; echo $ʟ_input->%1.raw'
+ '$ʟ_input = $_input = '
+ . ($name[0] === '$'
+ ? 'is_object($ʟ_tmp = %0.word) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp]'
+ : 'end($this->global->formsStack)[%0.word]')
+ . '; echo $ʟ_input->%1.raw'
. ($definedHtmlAttributes ? '->addAttributes(%2.var)' : '') . '->attributes()'
. " /* line $node->startLine */;",
$name,
$method . 'Part(' . implode(', ', array_map([$writer, 'formatWord'], $words)) . ')',
- array_fill_keys($definedHtmlAttributes, null)
+ array_fill_keys($definedHtmlAttributes, null),
);
}
}
@@ -285,9 +296,9 @@ public function macroInputError(MacroNode $node, PhpWriter $writer)
return $writer->write("echo %escape(\$ʟ_input->getError()) /* line $node->startLine */;");
} elseif ($name[0] === '$') {
return $writer->write(
- '$ʟ_input = is_object(%0.word) ? %0.word : end($this->global->formsStack)[%0.word];'
+ '$ʟ_input = is_object($ʟ_tmp = %0.word) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];'
. "echo %escape(\$ʟ_input->getError()) /* line $node->startLine */;",
- $name
+ $name,
);
} else {
return $writer->write("echo %escape(end(\$this->global->formsStack)[%0.word]->getError()) /* line $node->startLine */;", $name);
@@ -310,7 +321,7 @@ public function macroFormPrint(MacroNode $node, PhpWriter $writer)
return $writer->write(
'Nette\Bridges\FormsLatte\Runtime::render' . $node->name . '('
. ($name[0] === '$' ? 'is_object(%node.word) ? %node.word : ' : '')
- . '$this->global->uiControl[%node.word]); exit;'
+ . '$this->global->uiControl[%node.word]); exit;',
);
}
}
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..287c32419
--- /dev/null
+++ b/src/Bridges/FormsLatte/Nodes/FormContainerNode.php
@@ -0,0 +1,65 @@
+ */
+ 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)[%raw]'
+ : 'is_object($ʟ_tmp = %raw) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp]')
+ . '%line;'
+ . '%raw'
+ . '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..b739278a0
--- /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
%A%',
- html_entity_decode($res)
+ html_entity_decode($res),
);
diff --git a/tests/Forms.Latte/expected/FormMacros.button.html b/tests/Forms.Latte/expected/forms.button.html
similarity index 100%
rename from tests/Forms.Latte/expected/FormMacros.button.html
rename to tests/Forms.Latte/expected/forms.button.html
diff --git a/tests/Forms.Latte/expected/forms.button.phtml b/tests/Forms.Latte/expected/forms.button.phtml
new file mode 100644
index 000000000..d53179144
--- /dev/null
+++ b/tests/Forms.Latte/expected/forms.button.phtml
@@ -0,0 +1,29 @@
+global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */;
+ echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin(end($this->global->formsStack), [], false) /* line %d% */;
+ echo '>
+
+
+
+
+
+';
+ echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack), false) /* line %d% */;
+ echo '
+';
+%A%
diff --git a/tests/Forms.Latte/expected/FormMacros.formContainer.html b/tests/Forms.Latte/expected/forms.formContainer.html
similarity index 100%
rename from tests/Forms.Latte/expected/FormMacros.formContainer.html
rename to tests/Forms.Latte/expected/forms.formContainer.html
diff --git a/tests/Forms.Latte/expected/forms.formContainer.phtml b/tests/Forms.Latte/expected/forms.formContainer.phtml
new file mode 100644
index 000000000..677857a0c
--- /dev/null
+++ b/tests/Forms.Latte/expected/forms.formContainer.phtml
@@ -0,0 +1,105 @@
+global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */;
+ echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form, []) /* line %d% */;
+ echo '
+
+
+ ';
+ if ($ʟ_label = end($this->global->formsStack)['input1']->getLabel()) echo $ʟ_label /* line %d% */;
+ echo ' |
+ ';
+ echo end($this->global->formsStack)['input1']->getControl() /* line %d% */;
+ echo ' |
+
+';
+ $this->global->formsStack[] = $formContainer = end($this->global->formsStack)['cont1'] /* line %d% */;
+ echo '
+ ';
+ if ($ʟ_label = end($this->global->formsStack)['input2']->getLabel()) echo $ʟ_label /* line %d% */;
+ echo ' |
+ ';
+ echo end($this->global->formsStack)['input2']->getControl() /* line %d% */;
+ echo ' |
+
+
+ ';
+ if ($ʟ_label = end($this->global->formsStack)['input3']->getLabel()) echo $ʟ_label /* line %d% */;
+ echo ' |
+ ';
+ echo end($this->global->formsStack)['input3']->getControl() /* line %d% */;
+ echo ' |
+
+
+ Checkboxes |
+
+';
+ $this->global->formsStack[] = $formContainer = end($this->global->formsStack)['cont2'] /* line %d% */;
+ echo '
+';
+ $iterations = 0;
+ foreach ($formContainer->controls as $name => $field) /* line %d% */ {
+ echo ' - ';
+ $ʟ_input = is_object($ʟ_tmp = $field) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
+ echo $ʟ_input->getControl() /* line %d% */;
+ echo '
+';
+ $iterations++;
+ }
+
+ echo '
+';
+ array_pop($this->global->formsStack);
+ $formContainer = end($this->global->formsStack);
+
+ echo ' |
+
+
+ ';
+ if ($ʟ_label = end($this->global->formsStack)['input7']->getLabel()) echo $ʟ_label /* line %d% */;
+ echo ' |
+ ';
+ echo end($this->global->formsStack)['input7']->getControl() /* line %d% */;
+ echo ' |
+
+';
+ array_pop($this->global->formsStack);
+ $formContainer = end($this->global->formsStack);
+
+ $this->global->formsStack[] = $formContainer = end($this->global->formsStack)['items'] /* line %d% */;
+ echo '
+ Items |
+
+';
+ $items = [1, 2, 3] /* line %d% */;
+ $iterations = 0;
+ foreach ($items as $item) /* line %d% */ {
+ if (!isset($formContainer[$item])) /* line %d% */ continue;
+ $this->global->formsStack[] = $formContainer = is_object($ʟ_tmp = $item) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp] /* line %d% */;
+ echo ' ';
+ echo end($this->global->formsStack)['input']->getControl() /* line %d% */;
+ echo "\n";
+ array_pop($this->global->formsStack);
+ $formContainer = end($this->global->formsStack);
+
+ $iterations++;
+ }
+
+ echo ' |
+
+';
+ array_pop($this->global->formsStack);
+ $formContainer = end($this->global->formsStack);
+
+ echo '
+ ';
+ if ($ʟ_label = end($this->global->formsStack)['input8']->getLabel()) echo $ʟ_label /* line %d% */;
+ echo ' |
+ ';
+ echo end($this->global->formsStack)['input8']->getControl() /* line %d% */;
+ echo ' |
+
+
+';
+ echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack)) /* line %d% */;
+%A%
diff --git a/tests/Forms.Latte/expected/FormMacros.get.html b/tests/Forms.Latte/expected/forms.get.html
similarity index 100%
rename from tests/Forms.Latte/expected/FormMacros.get.html
rename to tests/Forms.Latte/expected/forms.get.html
diff --git a/tests/Forms.Latte/expected/forms.get.phtml b/tests/Forms.Latte/expected/forms.get.phtml
new file mode 100644
index 000000000..358aef9c8
--- /dev/null
+++ b/tests/Forms.Latte/expected/forms.get.phtml
@@ -0,0 +1,17 @@
+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 '
+
+
+';
+%A%
diff --git a/tests/Forms.Latte/expected/forms.html b/tests/Forms.Latte/expected/forms.html
new file mode 100644
index 000000000..fc662eba5
--- /dev/null
+++ b/tests/Forms.Latte/expected/forms.html
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Forms.Latte/expected/forms.phtml b/tests/Forms.Latte/expected/forms.phtml
new file mode 100644
index 000000000..a29a323a6
--- /dev/null
+++ b/tests/Forms.Latte/expected/forms.phtml
@@ -0,0 +1,300 @@
+global->formsStack[] = $this->global->uiControl['myForm'] /* line %d% */;
+ echo Nette\Bridges\FormsLatte\Runtime::renderFormBegin($form, ['id' => 'myForm', 'class' => 'ajax']) /* line %d% */;
+ echo "\n";
+ $iterations = 0;
+ foreach (['id', 'username', 'select', 'area', 'send'] as $name) /* line %d% */ {
+ echo ' ';
+ $ʟ_input = is_object($ʟ_tmp = $name) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
+ if ($ʟ_label = $ʟ_input->getLabel()) echo $ʟ_label /* line %d% */;
+ echo '
+ ';
+ $ʟ_input = is_object($ʟ_tmp = $name) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
+ echo $ʟ_input->getControl()->addAttributes(['title' => 'Hello', 'size' => 10]) /* line %d% */;
+ echo '
+ ';
+ echo LR\Filters::escapeHtmlText($ʟ_input->getError()) /* line %d% */;
+ echo '
+ ';
+ $ʟ_input = is_object($ʟ_tmp = $name) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
+ echo LR\Filters::escapeHtmlText($ʟ_input->getError()) /* line %d% */;
+ echo '
+
+
+
+ ';
+ $ʟ_input = is_object($ʟ_tmp = $form[$name]) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
+ if ($ʟ_label = $ʟ_input->getLabel()) echo $ʟ_label->addAttributes(['title' => 'hello'])->startTag() /* line %d% */;
+ echo ' ';
+ $ʟ_input = is_object($ʟ_tmp = $form[$name]) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
+ echo $ʟ_input->getControl()->addAttributes(['title' => 'Hello', 'size' => 10]) /* line %d% */;
+ echo ' ';
+ if ($ʟ_label) echo $ʟ_label->endTag() /* line %d% */;
+ echo '
+ ';
+ $ʟ_input = is_object($ʟ_tmp = $form[$name]) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
+ echo LR\Filters::escapeHtmlText($ʟ_input->getError()) /* line %d% */;
+ echo "\n";
+ $iterations++;
+ }
+
+ echo '
+ ';
+ $ʟ_input = is_object($ʟ_tmp = $form['username']) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
+ if ($ʟ_label = $ʟ_input->getLabel()) echo $ʟ_label /* line %d% */;
+ echo '
+
+
+ global->formsStack)['username'];
+ echo $ʟ_input->getControlPart()->addAttributes(['value' => null, 'type' => null, 'class' => null])->attributes() /* 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";
+ $iterations = 0;
+ 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 '
+
+';
+ $iterations++;
+ }
+
+ 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 '
+
+
+
+
+
+
+';
+ $iterations = 0;
+ 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 '
+
+';
+ $iterations++;
+ }
+
+ echo '
+
+
+
+
+';
+ if (1) /* line %d% */ {
+ echo '
+';
+ }
+ 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)['username'];
+ echo $ʟ_input->getControlPart()->attributes() /* line %d% */;
+ echo '>
+';
+ array_pop($this->global->formsStack) /* line %d% */;
+%A%
diff --git a/tests/Forms.Latte/forms.button.phpt b/tests/Forms.Latte/forms.button.phpt
new file mode 100644
index 000000000..a1cb3ac94
--- /dev/null
+++ b/tests/Forms.Latte/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.Latte/forms.error.phpt b/tests/Forms.Latte/forms.error.phpt
new file mode 100644
index 000000000..01f7e7d6a
--- /dev/null
+++ b/tests/Forms.Latte/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 ');
+}, 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.Latte/forms.formContainer.phpt b/tests/Forms.Latte/forms.formContainer.phpt
new file mode 100644
index 000000000..fc5b3a901
--- /dev/null
+++ b/tests/Forms.Latte/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.Latte/forms.get.phpt b/tests/Forms.Latte/forms.get.phpt
new file mode 100644
index 000000000..76f253873
--- /dev/null
+++ b/tests/Forms.Latte/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.Latte/forms.phpt b/tests/Forms.Latte/forms.phpt
new file mode 100644
index 000000000..86cab7ff1
--- /dev/null
+++ b/tests/Forms.Latte/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.Latte/templates/forms.formContainer.latte b/tests/Forms.Latte/templates/forms.formContainer.latte
index 5abd962bc..cbc69cbb9 100644
--- a/tests/Forms.Latte/templates/forms.formContainer.latte
+++ b/tests/Forms.Latte/templates/forms.formContainer.latte
@@ -16,7 +16,7 @@
Checkboxes |
-
+
- {input $field}
|
diff --git a/tests/Forms.Latte/templates/forms.latte b/tests/Forms.Latte/templates/forms.latte
index 0c4f5bc38..f4f3604f8 100644
--- a/tests/Forms.Latte/templates/forms.latte
+++ b/tests/Forms.Latte/templates/forms.latte
@@ -11,7 +11,7 @@
{inputError $form[$name]}
{/foreach}
- {label $form[username]}
+ {label $form[username] /}
@@ -35,6 +35,7 @@
+
{* partial rendering of Checkbox *}
diff --git a/tests/Forms.Latte/FormMacros.button.phpt b/tests/Forms.Latte2/FormMacros.button.phpt
similarity index 77%
rename from tests/Forms.Latte/FormMacros.button.phpt
rename to tests/Forms.Latte2/FormMacros.button.phpt
index 66f76da9e..5fce6fdc4 100644
--- a/tests/Forms.Latte/FormMacros.button.phpt
+++ b/tests/Forms.Latte2/FormMacros.button.phpt
@@ -10,9 +10,12 @@ use Nette\Bridges\FormsLatte\FormMacros;
use Nette\Forms\Form;
use Tester\Assert;
-
require __DIR__ . '/../bootstrap.php';
+if (version_compare(Latte\Engine::VERSION, '3', '>')) {
+ Tester\Environment::skip('Test for Latte 2');
+}
+
$form = new Form;
$form->addSubmit('send', 'Sign in');
@@ -23,10 +26,10 @@ $latte->addProvider('uiControl', ['myForm' => $form]);
Assert::matchFile(
__DIR__ . '/expected/FormMacros.button.phtml',
- $latte->compile(__DIR__ . '/templates/forms.button.latte')
+ $latte->compile(__DIR__ . '/templates/forms.button.latte'),
);
Assert::matchFile(
__DIR__ . '/expected/FormMacros.button.html',
- $latte->renderToString(__DIR__ . '/templates/forms.button.latte')
+ $latte->renderToString(__DIR__ . '/templates/forms.button.latte'),
);
diff --git a/tests/Forms.Latte/FormMacros.error.phpt b/tests/Forms.Latte2/FormMacros.error.phpt
similarity index 93%
rename from tests/Forms.Latte/FormMacros.error.phpt
rename to tests/Forms.Latte2/FormMacros.error.phpt
index eb520fe27..68dc2a5b0 100644
--- a/tests/Forms.Latte/FormMacros.error.phpt
+++ b/tests/Forms.Latte2/FormMacros.error.phpt
@@ -9,9 +9,12 @@ declare(strict_types=1);
use Nette\Bridges\FormsLatte\FormMacros;
use Tester\Assert;
-
require __DIR__ . '/../bootstrap.php';
+if (version_compare(Latte\Engine::VERSION, '3', '>')) {
+ Tester\Environment::skip('Test for Latte 2');
+}
+
$latte = new Latte\Engine;
$latte->setLoader(new Latte\Loaders\StringLoader);
diff --git a/tests/Forms.Latte/FormMacros.formContainer.phpt b/tests/Forms.Latte2/FormMacros.formContainer.phpt
similarity index 90%
rename from tests/Forms.Latte/FormMacros.formContainer.phpt
rename to tests/Forms.Latte2/FormMacros.formContainer.phpt
index f6f916c27..5f80985b0 100644
--- a/tests/Forms.Latte/FormMacros.formContainer.phpt
+++ b/tests/Forms.Latte2/FormMacros.formContainer.phpt
@@ -10,9 +10,12 @@ use Nette\Bridges\FormsLatte\FormMacros;
use Nette\Forms\Form;
use Tester\Assert;
-
require __DIR__ . '/../bootstrap.php';
+if (version_compare(Latte\Engine::VERSION, '3', '>')) {
+ Tester\Environment::skip('Test for Latte 2');
+}
+
$form = new Form;
$form->addText('input1', 'Input 1');
@@ -44,9 +47,9 @@ $latte->addProvider('uiControl', ['myForm' => $form]);
Assert::matchFile(
__DIR__ . '/expected/FormMacros.formContainer.phtml',
- $latte->compile(__DIR__ . '/templates/forms.formContainer.latte')
+ $latte->compile(__DIR__ . '/templates/forms.formContainer.latte'),
);
Assert::matchFile(
__DIR__ . '/expected/FormMacros.formContainer.html',
- $latte->renderToString(__DIR__ . '/templates/forms.formContainer.latte')
+ $latte->renderToString(__DIR__ . '/templates/forms.formContainer.latte'),
);
diff --git a/tests/Forms.Latte/FormMacros.forms.phpt b/tests/Forms.Latte2/FormMacros.forms.phpt
similarity index 80%
rename from tests/Forms.Latte/FormMacros.forms.phpt
rename to tests/Forms.Latte2/FormMacros.forms.phpt
index 20f36fd8f..b99317691 100644
--- a/tests/Forms.Latte/FormMacros.forms.phpt
+++ b/tests/Forms.Latte2/FormMacros.forms.phpt
@@ -10,19 +10,22 @@ use Nette\Bridges\FormsLatte\FormMacros;
use Nette\Forms\Form;
use Tester\Assert;
-
require __DIR__ . '/../bootstrap.php';
+if (version_compare(Latte\Engine::VERSION, '3', '>')) {
+ Tester\Environment::skip('Test for Latte 2');
+}
+
class MyControl extends Nette\Forms\Controls\BaseControl
{
- public function getLabel($c = null)
+ public function getLabel($c = null): string
{
return '';
}
- public function getControl()
+ public function getControl(): string
{
return '';
}
@@ -50,9 +53,9 @@ $form['username']->addError('error');
Assert::matchFile(
__DIR__ . '/expected/FormMacros.forms.phtml',
- $latte->compile(__DIR__ . '/templates/forms.latte')
+ $latte->compile(__DIR__ . '/templates/forms.latte'),
);
Assert::matchFile(
__DIR__ . '/expected/FormMacros.forms.html',
- $latte->renderToString(__DIR__ . '/templates/forms.latte')
+ $latte->renderToString(__DIR__ . '/templates/forms.latte'),
);
diff --git a/tests/Forms.Latte/FormMacros.get.phpt b/tests/Forms.Latte2/FormMacros.get.phpt
similarity index 71%
rename from tests/Forms.Latte/FormMacros.get.phpt
rename to tests/Forms.Latte2/FormMacros.get.phpt
index 894873d53..cd55b3886 100644
--- a/tests/Forms.Latte/FormMacros.get.phpt
+++ b/tests/Forms.Latte2/FormMacros.get.phpt
@@ -10,9 +10,12 @@ use Nette\Bridges\FormsLatte\FormMacros;
use Nette\Forms\Form;
use Tester\Assert;
-
require __DIR__ . '/../bootstrap.php';
+if (version_compare(Latte\Engine::VERSION, '3', '>')) {
+ Tester\Environment::skip('Test for Latte 2');
+}
+
$form = new Form;
$form->setMethod('get');
@@ -25,9 +28,9 @@ $latte->addProvider('uiControl', ['myForm' => $form]);
Assert::matchFile(
__DIR__ . '/expected/FormMacros.get.phtml',
- $latte->compile(__DIR__ . '/templates/forms.get.latte')
+ $latte->compile(__DIR__ . '/templates/forms.get.latte'),
);
Assert::matchFile(
__DIR__ . '/expected/FormMacros.get.html',
- $latte->renderToString(__DIR__ . '/templates/forms.get.latte')
+ $latte->renderToString(__DIR__ . '/templates/forms.get.latte'),
);
diff --git a/tests/Forms.Latte2/expected/FormMacros.button.html b/tests/Forms.Latte2/expected/FormMacros.button.html
new file mode 100644
index 000000000..97a6686cc
--- /dev/null
+++ b/tests/Forms.Latte2/expected/FormMacros.button.html
@@ -0,0 +1,10 @@
+
diff --git a/tests/Forms.Latte/expected/FormMacros.button.phtml b/tests/Forms.Latte2/expected/FormMacros.button.phtml
similarity index 100%
rename from tests/Forms.Latte/expected/FormMacros.button.phtml
rename to tests/Forms.Latte2/expected/FormMacros.button.phtml
diff --git a/tests/Forms.Latte2/expected/FormMacros.formContainer.html b/tests/Forms.Latte2/expected/FormMacros.formContainer.html
new file mode 100644
index 000000000..2e45cf0d6
--- /dev/null
+++ b/tests/Forms.Latte2/expected/FormMacros.formContainer.html
@@ -0,0 +1,41 @@
+
diff --git a/tests/Forms.Latte/expected/FormMacros.formContainer.phtml b/tests/Forms.Latte2/expected/FormMacros.formContainer.phtml
similarity index 91%
rename from tests/Forms.Latte/expected/FormMacros.formContainer.phtml
rename to tests/Forms.Latte2/expected/FormMacros.formContainer.phtml
index a296c5b42..02cb5b99f 100644
--- a/tests/Forms.Latte/expected/FormMacros.formContainer.phtml
+++ b/tests/Forms.Latte2/expected/FormMacros.formContainer.phtml
@@ -39,7 +39,7 @@
$iterations = 0;
foreach ($formContainer->controls AS $name => $field) /* line 19 */ {
echo ' ';
- $ʟ_input = $_input = is_object($field) ? $field : end($this->global->formsStack)[$field];
+ $ʟ_input = $_input = is_object($ʟ_tmp = $field) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
echo $ʟ_input->getControl() /* line 20 */;
echo '
';
@@ -71,7 +71,7 @@
$iterations = 0;
foreach ($items as $item) /* line 34 */ {
if (!isset($formContainer[$item])) /* line 35 */ continue;
- $this->global->formsStack[] = $formContainer = is_object($item) ? $item : end($this->global->formsStack)[$item] /* line 36 */;
+ $this->global->formsStack[] = $formContainer = is_object($ʟ_tmp = $item) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp] /* line 36 */;
echo ' ';
echo end($this->global->formsStack)["input"]->getControl() /* line 37 */;
echo "\n";
diff --git a/tests/Forms.Latte/expected/FormMacros.forms.html b/tests/Forms.Latte2/expected/FormMacros.forms.html
similarity index 100%
rename from tests/Forms.Latte/expected/FormMacros.forms.html
rename to tests/Forms.Latte2/expected/FormMacros.forms.html
diff --git a/tests/Forms.Latte/expected/FormMacros.forms.phtml b/tests/Forms.Latte2/expected/FormMacros.forms.phtml
similarity index 89%
rename from tests/Forms.Latte/expected/FormMacros.forms.phtml
rename to tests/Forms.Latte2/expected/FormMacros.forms.phtml
index 1cf2f425f..ffb93af75 100644
--- a/tests/Forms.Latte/expected/FormMacros.forms.phtml
+++ b/tests/Forms.Latte2/expected/FormMacros.forms.phtml
@@ -5,41 +5,41 @@
$iterations = 0;
foreach (['id', 'username', 'select', 'area', 'send'] as $name) /* line 2 */ {
echo ' ';
- $ʟ_input = is_object($name) ? $name : end($this->global->formsStack)[$name];
+ $ʟ_input = is_object($ʟ_tmp = $name) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
if ($ʟ_label = $ʟ_input->getLabel()) echo $ʟ_label;
echo '
';
- $ʟ_input = $_input = is_object($name) ? $name : end($this->global->formsStack)[$name];
+ $ʟ_input = $_input = is_object($ʟ_tmp = $name) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
echo $ʟ_input->getControl()->addAttributes(['title' => 'Hello', 'size' => 10]) /* line 4 */;
echo '
';
echo LR\Filters::escapeHtmlText($ʟ_input->getError()) /* line 5 */;
echo '
';
- $ʟ_input = is_object($name) ? $name : end($this->global->formsStack)[$name];
+ $ʟ_input = is_object($ʟ_tmp = $name) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
echo LR\Filters::escapeHtmlText($ʟ_input->getError()) /* line 6 */;
echo '
';
- $ʟ_input = is_object($form[$name]) ? $form[$name] : end($this->global->formsStack)[$form[$name]];
+ $ʟ_input = is_object($ʟ_tmp = $form[$name]) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
if ($ʟ_label = $ʟ_input->getLabel()) echo $ʟ_label->addAttributes(['title' => 'hello'])->startTag();
echo ' ';
- $ʟ_input = $_input = is_object($form[$name]) ? $form[$name] : end($this->global->formsStack)[$form[$name]];
+ $ʟ_input = $_input = is_object($ʟ_tmp = $form[$name]) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
echo $ʟ_input->getControl()->addAttributes(['title' => 'Hello', 'size' => 10]) /* line 10 */;
echo ' ';
if ($ʟ_label) echo $ʟ_label->endTag();
echo '
';
- $ʟ_input = is_object($form[$name]) ? $form[$name] : end($this->global->formsStack)[$form[$name]];
+ $ʟ_input = is_object($ʟ_tmp = $form[$name]) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
echo LR\Filters::escapeHtmlText($ʟ_input->getError()) /* line 11 */;
echo "\n";
$iterations++;
}
echo '
';
- $ʟ_input = is_object($form['username']) ? $form['username'] : end($this->global->formsStack)[$form['username']];
+ $ʟ_input = is_object($ʟ_tmp = $form['username']) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
if ($ʟ_label = $ʟ_input->getLabel()) echo $ʟ_label;
echo '
@@ -53,17 +53,17 @@
echo '>
global->formsStack)[$form['username']];
+ $ʟ_input = $_input = is_object($ʟ_tmp = $form['username']) ? $ʟ_tmp : end($this->global->formsStack)[$ʟ_tmp];
echo $ʟ_input->getControlPart()->attributes() /* line 21 */;
echo '>
@@ -229,7 +229,7 @@
';
- $form = $this->global->formsStack[] = is_object($this->global->uiControl['myForm']) ? $this->global->uiControl['myForm'] : $this->global->uiControl[$this->global->uiControl['myForm']] /* line 68 */;
+ $form = $this->global->formsStack[] = is_object($ʟ_tmp = $this->global->uiControl['myForm']) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp] /* line 68 */;
echo '
+
+
+
diff --git a/tests/Forms.Latte/expected/FormMacros.get.phtml b/tests/Forms.Latte2/expected/FormMacros.get.phtml
similarity index 100%
rename from tests/Forms.Latte/expected/FormMacros.get.phtml
rename to tests/Forms.Latte2/expected/FormMacros.get.phtml
diff --git a/tests/Forms.Latte2/templates/forms.button.latte b/tests/Forms.Latte2/templates/forms.button.latte
new file mode 100644
index 000000000..8e9969b37
--- /dev/null
+++ b/tests/Forms.Latte2/templates/forms.button.latte
@@ -0,0 +1,9 @@
+
diff --git a/tests/Forms.Latte2/templates/forms.formContainer.latte b/tests/Forms.Latte2/templates/forms.formContainer.latte
new file mode 100644
index 000000000..5abd962bc
--- /dev/null
+++ b/tests/Forms.Latte2/templates/forms.formContainer.latte
@@ -0,0 +1,48 @@
+{form myForm}
+
+
+ {label input1 /} |
+ {input input1} |
+
+ {formContainer cont1}
+
+ {label input2 /} |
+ {input input2} |
+
+
+ {label input3 /} |
+ {input input3} |
+
+
+ Checkboxes |
+
+
+ - {input $field}
+
+ |
+
+
+ {label input7 /} |
+ {input input7} |
+
+ {/formContainer}
+ {formContainer items}
+
+ Items |
+
+ {var $items = array(1, 2, 3)}
+ {foreach $items as $item}
+ {continueIf !isset($formContainer[$item])}
+ {formContainer $item}
+ {input input}
+ {/formContainer}
+ {/foreach}
+ |
+
+ {/formContainer}
+
+ {label input8 /} |
+ {input input8} |
+
+
+{/form}
diff --git a/tests/Forms.Latte2/templates/forms.get.latte b/tests/Forms.Latte2/templates/forms.get.latte
new file mode 100644
index 000000000..c514a0202
--- /dev/null
+++ b/tests/Forms.Latte2/templates/forms.get.latte
@@ -0,0 +1,4 @@
+{form myForm /}
+
+
diff --git a/tests/Forms.Latte2/templates/forms.latte b/tests/Forms.Latte2/templates/forms.latte
new file mode 100644
index 000000000..adf5a60c8
--- /dev/null
+++ b/tests/Forms.Latte2/templates/forms.latte
@@ -0,0 +1,86 @@
+{form myForm id => myForm, class=>"ajax"}
+ {foreach [id, username, select, area, send] as $name}
+ {label $name /}
+ {input $name title => Hello, size => 10}
+ {inputError}
+ {inputError $name}
+
+
+
+ {label $form[$name] title => hello} {input $form[$name] title => Hello, size => 10} {/label}
+ {inputError $form[$name]}
+ {/foreach}
+
+ {label $form[username] /}
+
+
+
+
+
+
+
+
+ {label my/}{input my}
+{/form myForm}
+
+
+{form myForm /}
+
+{form myForm}
+{* partial rendering of RadioList *}
+{foreach $form[sex]->items as $key => $label}
+ {label sex:$key} {input sex:$key} {$label}{/label}
+
+{/foreach}
+
+
+
+
+
+{* partial rendering of Checkbox *}
+{label checkbox:} {input checkbox:} Label{/label}
+
+
+
+
+
+
+{* partial rendering of CheckboxList *}
+{foreach $form[checklist]->items as $key => $label}
+ {label checklist:$key} {input checklist:$key} {$label}{/label}
+
+{/foreach}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{/form}
+
+
+{formContext myForm}
+
+
+{/formContext myForm}
diff --git a/tests/Forms/Container.values.array.phpt b/tests/Forms/Container.values.array.phpt
index 417f2259d..5cef74e76 100644
--- a/tests/Forms/Container.values.array.phpt
+++ b/tests/Forms/Container.values.array.phpt
@@ -64,11 +64,11 @@ test('setDefaults() + array', function () {
'city' => 'zzz',
],
],
- ], $form->getValues(true));
+ ], $form->getValues('array'));
});
-test('submitted form + getValues(true)', function () {
+test('submitted form + getValues(array)', function () {
$_SERVER['REQUEST_METHOD'] = 'POST';
$form = createForm();
@@ -82,7 +82,7 @@ test('submitted form + getValues(true)', function () {
'city' => 'sent city',
],
],
- ], $form->getValues(true));
+ ], $form->getValues('array'));
});
@@ -104,7 +104,7 @@ test('submitted form + reset()', function () {
'city' => '',
],
],
- ], $form->getValues(true));
+ ], $form->getValues('array'));
});
@@ -130,7 +130,7 @@ test('setValues() + array', function () {
'city' => 'sent city',
],
],
- ], $form->getValues(true));
+ ], $form->getValues('array'));
// erase
$form->setValues([
@@ -149,7 +149,7 @@ test('setValues() + array', function () {
'city' => '',
],
],
- ], $form->getValues(true));
+ ], $form->getValues('array'));
});
@@ -261,7 +261,7 @@ test('onSuccess test', function () {
});
-test('submitted form + setValidationScope() + getValues(true)', function () {
+test('submitted form + setValidationScope() + getValues(array)', function () {
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['send'] = '';
@@ -275,11 +275,28 @@ test('submitted form + setValidationScope() + getValues(true)', function () {
'age' => 999,
'second' => [],
],
- ], $form->getValues(true));
+ ], $form->getValues('array'));
});
-test('submitted form + setValidationScope() + getValues(true)', function () {
+test('submitted form + setValidationScope() + getValues(array)', function () {
+ $_SERVER['REQUEST_METHOD'] = 'POST';
+ $_POST['send'] = '';
+
+ $form = createForm();
+ $form->addSubmit('send')->setValidationScope([$form['first']]);
+
+ Assert::truthy($form->isSubmitted());
+ Assert::equal([
+ 'name' => '',
+ 'age' => 999,
+ 'second' => [
+ 'city' => 'sent city',
+ ],
+ ], $form['first']->getValues('array'));
+});
+
+test('submitted form + setValidationScope() + getValues(array)', function () {
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['send'] = '';
@@ -294,5 +311,5 @@ test('submitted form + setValidationScope() + getValues(true)', function () {
'city' => 'sent city',
],
],
- ], $form->getValues(true));
+ ], $form->getValues('array'));
});
diff --git a/tests/Forms/Container.values.mapping-constructor.phpt b/tests/Forms/Container.values.mapping-constructor.phpt
index 8c0c8988b..d6b85a45d 100644
--- a/tests/Forms/Container.values.mapping-constructor.phpt
+++ b/tests/Forms/Container.values.mapping-constructor.phpt
@@ -1,9 +1,5 @@
$value) {
- $obj->$key = $value;
- }
-
- return $obj;
-}
-
-
-$_COOKIE[Nette\Http\Helpers::STRICT_COOKIE_NAME] = '1';
-$_POST = [
- 'title' => 'sent title',
- 'first' => [
- 'age' => '999',
- 'second' => [
- 'city' => 'sent city',
- ],
- ],
-];
-
-
-function createForm(): Form
-{
- Form::initialize(true);
-
- $form = new Form;
- $form->addText('title');
-
- $first = $form->addContainer('first');
- $first->addText('name');
- $first->addInteger('age');
-
- $second = $first->addContainer('second');
- $second->addText('city');
- return $form;
-}
-
-
-test('setDefaults() + object', function () {
- $form = createForm();
- Assert::false($form->isSubmitted());
-
- $form->setDefaults(hydrate(FormData::class, [
- 'title' => 'xxx',
- 'extra' => '50',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => 'yyy',
- 'age' => 30,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => 'zzz',
- ]),
- ]),
- ]));
-
- Assert::same([
- 'title' => 'xxx',
- 'first' => [
- 'name' => 'yyy',
- 'age' => 30,
- 'second' => [
- 'city' => 'zzz',
- ],
- ],
- ], $form->getValues(true));
-});
-
-
-test('submitted form + getValues()', function () {
- $_SERVER['REQUEST_METHOD'] = 'POST';
-
- $form = createForm();
- $form->setMappedType(FormData::class);
-
- Assert::truthy($form->isSubmitted());
- Assert::equal(hydrate(FormData::class, [
- 'title' => 'sent title',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => '',
- 'age' => 999,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => 'sent city',
- ]),
- ]),
- ]), $form->getValues());
-});
-
-
-test('submitted form + reset()', function () {
- $_SERVER['REQUEST_METHOD'] = 'POST';
-
- $form = createForm();
- $form->setMappedType(FormData::class);
-
- Assert::truthy($form->isSubmitted());
-
- $form->reset();
-
- Assert::false($form->isSubmitted());
- Assert::equal(hydrate(FormData::class, [
- 'title' => '',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => '',
- 'age' => null,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => '',
- ]),
- ]),
- ]), $form->getValues());
-});
-
-
-test('setValues() + object', function () {
- $_SERVER['REQUEST_METHOD'] = 'POST';
-
- $form = createForm();
- $form->setMappedType(FormData::class);
-
- Assert::truthy($form->isSubmitted());
-
- $form->setValues(hydrate(FormData::class, [
- 'title' => 'new1',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => 'new2',
- // age => null
- ]),
- ]));
-
- Assert::equal(hydrate(FormData::class, [
- 'title' => 'new1',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => 'new2',
- 'age' => null,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => 'sent city',
- ]),
- ]),
- ]), $form->getValues());
-
- // erase
- $form->setValues(hydrate(FormData::class, [
- 'title' => 'new1',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => 'new2',
- ]),
- ]), true);
-
- Assert::equal(hydrate(FormData::class, [
- 'title' => 'new1',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => 'new2',
- 'age' => null,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => '',
- ]),
- ]),
- ]), $form->getValues());
-});
-
-
-test('getValues(...arguments...)', function () {
- $_SERVER['REQUEST_METHOD'] = null;
-
- $form = createForm();
-
- $form->setValues([
- 'title' => 'new1',
- 'first' => [
- 'name' => 'new2',
- ],
- ]);
-
- Assert::equal(hydrate(FormData::class, [
- 'title' => 'new1',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => 'new2',
- 'age' => null,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => '',
- ]),
- ]),
- ]), $form->getValues(FormData::class));
-
- $form->setMappedType(FormData::class);
- $form['first']->setMappedType(FormFirstLevel::class);
- $form['first-second']->setMappedType(FormSecondLevel::class);
-
- Assert::equal(hydrate(FormData::class, [
- 'title' => 'new1',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => 'new2',
- 'age' => null,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => '',
- ]),
- ]),
- ]), $form->getValues());
-
- Assert::equal([
- 'title' => 'new1',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => 'new2',
- 'age' => null,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => '',
- ]),
- ]),
- ], $form->getValues(true));
-});
-
-
-test('onSuccess test', function () {
- $_SERVER['REQUEST_METHOD'] = 'POST';
-
- $form = createForm();
- $form->setMappedType(FormData::class);
-
- $form->onSuccess[] = function (Form $form, array $values) {
- Assert::same([
- 'title' => 'sent title',
- 'first' => [
- 'name' => '',
- 'age' => 999,
- 'second' => [
- 'city' => 'sent city',
- ],
- ],
- ], $values);
- };
-
- $form->onSuccess[] = function (Form $form, ArrayHash $values) {
- Assert::equal(ArrayHash::from([
- 'title' => 'sent title',
- 'first' => ArrayHash::from([
- 'name' => '',
- 'age' => 999,
- 'second' => ArrayHash::from([
- 'city' => 'sent city',
- ]),
- ]),
- ]), $values);
- };
-
- $form->onSuccess[] = function (Form $form, $values) {
- Assert::equal(hydrate(FormData::class, [
- 'title' => 'sent title',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => '',
- 'age' => 999,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => 'sent city',
- ]),
- ]),
- ]), $values);
- };
-
- $form->onSuccess[] = function (Form $form, FormData $values) {
- Assert::equal(hydrate(FormData::class, [
- 'title' => 'sent title',
- 'first' => hydrate(FormFirstLevel::class, [
- 'name' => '',
- 'age' => 999,
- 'second' => hydrate(FormSecondLevel::class, [
- 'city' => 'sent city',
- ]),
- ]),
- ]), $values);
- };
-
- $ok = false;
- $form->onSuccess[] = function () use (&$ok) {
- $ok = true;
- };
-
- $form->fireEvents();
- Assert::true($ok);
-});
diff --git a/tests/Forms/Container.values.mapping.phpt b/tests/Forms/Container.values.mapping.phpt
index ee09d5cdf..341d15e79 100644
--- a/tests/Forms/Container.values.mapping.phpt
+++ b/tests/Forms/Container.values.mapping.phpt
@@ -12,35 +12,29 @@ require __DIR__ . '/../bootstrap.php';
class FormData
{
- /** @var string */
- public $title;
+ public string $title;
- /** @var FormFirstLevel */
- public $first;
+ public FormFirstLevel $first;
}
class FormFirstLevel
{
- /** @var string */
- public $name;
+ public string $name;
- /** @var int */
- public $age;
+ public ?int $age = null;
- /** @var FormSecondLevel */
- public $second;
+ public ?FormSecondLevel $second;
}
class FormSecondLevel
{
- /** @var string */
- public $city;
+ public string $city;
}
-function hydrate(string $class, array $data)
+function hydrate(string $class, array $data): object
{
$obj = new $class;
foreach ($data as $key => $value) {
@@ -89,7 +83,7 @@ test('setDefaults() + object', function () {
'extra' => '50',
'first' => hydrate(FormFirstLevel::class, [
'name' => 'yyy',
- 'age' => '30',
+ 'age' => 30,
'second' => hydrate(FormSecondLevel::class, [
'city' => 'zzz',
]),
@@ -100,12 +94,12 @@ test('setDefaults() + object', function () {
'title' => 'xxx',
'first' => [
'name' => 'yyy',
- 'age' => '30',
+ 'age' => 30,
'second' => [
'city' => 'zzz',
],
],
- ], $form->getValues(true));
+ ], $form->getValues('array'));
});
@@ -118,10 +112,10 @@ test('submitted form + getValues()', function () {
Assert::truthy($form->isSubmitted());
Assert::equal(hydrate(FormData::class, [
'title' => 'sent title',
- 'first' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
'name' => '',
'age' => 999,
- 'second' => ArrayHash::from([
+ 'second' => hydrate(FormSecondLevel::class, [
'city' => 'sent city',
]),
]),
@@ -142,10 +136,10 @@ test('submitted form + reset()', function () {
Assert::false($form->isSubmitted());
Assert::equal(hydrate(FormData::class, [
'title' => '',
- 'first' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
'name' => '',
'age' => null,
- 'second' => ArrayHash::from([
+ 'second' => hydrate(FormSecondLevel::class, [
'city' => '',
]),
]),
@@ -171,10 +165,10 @@ test('setValues() + object', function () {
Assert::equal(hydrate(FormData::class, [
'title' => 'new1',
- 'first' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
'name' => 'new2',
'age' => null,
- 'second' => ArrayHash::from([
+ 'second' => hydrate(FormSecondLevel::class, [
'city' => 'sent city',
]),
]),
@@ -190,10 +184,10 @@ test('setValues() + object', function () {
Assert::equal(hydrate(FormData::class, [
'title' => 'new1',
- 'first' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
'name' => 'new2',
'age' => null,
- 'second' => ArrayHash::from([
+ 'second' => hydrate(FormSecondLevel::class, [
'city' => '',
]),
]),
@@ -215,10 +209,10 @@ test('getValues(...arguments...)', function () {
Assert::equal(hydrate(FormData::class, [
'title' => 'new1',
- 'first' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
'name' => 'new2',
'age' => null,
- 'second' => ArrayHash::from([
+ 'second' => hydrate(FormSecondLevel::class, [
'city' => '',
]),
]),
@@ -248,7 +242,7 @@ test('getValues(...arguments...)', function () {
'city' => '',
]),
]),
- ], $form->getValues(true));
+ ], $form->getValues('array'));
});
@@ -287,10 +281,10 @@ test('onSuccess test', function () {
$form->onSuccess[] = function (Form $form, $values) {
Assert::equal(hydrate(FormData::class, [
'title' => 'sent title',
- 'first' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
'name' => '',
'age' => 999,
- 'second' => ArrayHash::from([
+ 'second' => hydrate(FormSecondLevel::class, [
'city' => 'sent city',
]),
]),
@@ -300,10 +294,10 @@ test('onSuccess test', function () {
$form->onSuccess[] = function (Form $form, FormData $values) {
Assert::equal(hydrate(FormData::class, [
'title' => 'sent title',
- 'first' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
'name' => '',
'age' => 999,
- 'second' => ArrayHash::from([
+ 'second' => hydrate(FormSecondLevel::class, [
'city' => 'sent city',
]),
]),
@@ -328,10 +322,10 @@ test('getValues() + object', function () {
Assert::equal(hydrate(FormData::class, [
'title' => 'sent title',
- 'first' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
'name' => '',
'age' => 999,
- 'second' => ArrayHash::from([
+ 'second' => hydrate(FormSecondLevel::class, [
'city' => 'sent city',
]),
]),
@@ -341,7 +335,7 @@ test('getValues() + object', function () {
});
-test('submitted form + setValidationScope() + getValues(true)', function () {
+test('submitted form + setValidationScope() + getValues()', function () {
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['send'] = '';
@@ -351,15 +345,15 @@ test('submitted form + setValidationScope() + getValues(true)', function () {
Assert::truthy($form->isSubmitted());
Assert::equal(hydrate(FormData::class, [
'title' => 'sent title',
- 'first' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
'age' => 999,
- 'second' => ArrayHash::from([]),
+ 'second' => hydrate(FormSecondLevel::class, []),
]),
]), $form->getValues(FormData::class));
});
-test('submitted form + setValidationScope() + getValues(true)', function () {
+test('submitted form + setValidationScope() + getValues()', function () {
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['send'] = '';
@@ -369,8 +363,8 @@ test('submitted form + setValidationScope() + getValues(true)', function () {
Assert::truthy($form->isSubmitted());
Assert::equal(hydrate(FormData::class, [
'title' => 'sent title',
- 'first' => ArrayHash::from([
- 'second' => ArrayHash::from([
+ 'first' => hydrate(FormFirstLevel::class, [
+ 'second' => hydrate(FormSecondLevel::class, [
'city' => 'sent city',
]),
]),
diff --git a/tests/Forms/Controls.BaseControl.phpt b/tests/Forms/Controls.BaseControl.phpt
index 8d8466136..ea46a90bd 100644
--- a/tests/Forms/Controls.BaseControl.phpt
+++ b/tests/Forms/Controls.BaseControl.phpt
@@ -14,6 +14,12 @@ use Tester\Assert;
require __DIR__ . '/../bootstrap.php';
+enum TestEnum: string {
+ case CASE_1 = 'case 1';
+ case CASE_2 = 'case 2';
+}
+
+
before(function () {
Form::initialize(true);
});
@@ -53,7 +59,6 @@ test('validators', function () {
Assert::true(Validator::validateFilled($input));
Assert::true(Validator::validateValid($input));
- Assert::false(Validator::validateLength($input, null));
Assert::false(Validator::validateLength($input, 2));
Assert::true(Validator::validateLength($input, 3));
@@ -77,6 +82,18 @@ test('validators', function () {
});
+test('validators for enums', function () {
+ $form = new Form;
+ $input = $form->addText('text');
+ $input->setValue(TestEnum::CASE_1->value);
+
+ Assert::true(Validator::validateEqual($input, TestEnum::CASE_1));
+ Assert::true(Validator::validateEqual($input, 'case 1'));
+ Assert::false(Validator::validateEqual($input, TestEnum::CASE_2));
+ Assert::false(Validator::validateEqual($input, 1));
+});
+
+
test('validators for array', function () {
$form = new Form;
$input = $form->addMultiSelect('select', null, ['a', 'b', 'c', 'd']);
@@ -89,7 +106,6 @@ test('validators for array', function () {
Assert::true(Validator::validateFilled($input));
Assert::true(Validator::validateValid($input));
- Assert::false(Validator::validateLength($input, null));
Assert::false(Validator::validateLength($input, 2));
Assert::true(Validator::validateLength($input, 3));
diff --git a/tests/Forms/Controls.HiddenField.loadData.phpt b/tests/Forms/Controls.HiddenField.loadData.phpt
index c68ce26ed..ef9db0372 100644
--- a/tests/Forms/Controls.HiddenField.loadData.phpt
+++ b/tests/Forms/Controls.HiddenField.loadData.phpt
@@ -81,9 +81,7 @@ test('object from string by filter', function () {
$_POST = ['text' => (string) $date];
$form = new Form;
$input = $form->addHidden('text');
- $input->addFilter(function ($value) {
- return $value ? new Nette\Utils\DateTime($value) : $value;
- });
+ $input->addFilter(fn($value) => $value ? new Nette\Utils\DateTime($value) : $value);
Assert::same((string) $date, $input->getValue());
$input->validate();
diff --git a/tests/Forms/Controls.TestBase.validators.phpt b/tests/Forms/Controls.TestBase.validators.phpt
index 88395d1dd..0c9e7cc8d 100644
--- a/tests/Forms/Controls.TestBase.validators.phpt
+++ b/tests/Forms/Controls.TestBase.validators.phpt
@@ -99,7 +99,7 @@ test('', function () {
$control = new TextInput;
$control->value = new class () {
- public $lorem = 'ipsum';
+ public string $lorem = 'ipsum';
public function __toString(): string
@@ -125,7 +125,7 @@ test('', function () {
test('', function () {
class MockUploadControl extends UploadControl
{
- public function setValue($value)
+ public function setValue($value): static
{
$this->value = $value;
return $this;
diff --git a/tests/Forms/Controls.TextBase.loadData.phpt b/tests/Forms/Controls.TextBase.loadData.phpt
index 2d7996e76..cbb715d3f 100644
--- a/tests/Forms/Controls.TextBase.loadData.phpt
+++ b/tests/Forms/Controls.TextBase.loadData.phpt
@@ -199,9 +199,7 @@ test('filter in BLANK condition', function () {
$form = new Form;
$input = $form->addText('text');
$input->addCondition($form::BLANK)
- ->addFilter(function () use ($input) {
- return 'default';
- });
+ ->addFilter(fn() => 'default');
Assert::same('', $input->getValue());
$input->validate();
@@ -216,9 +214,7 @@ test('filter in !FILLED condition', function () {
$input = $form->addText('text');
$input->addCondition($form::FILLED)
->elseCondition()
- ->addFilter(function () use ($input) {
- return 'default';
- });
+ ->addFilter(fn() => 'default');
Assert::same('', $input->getValue());
$input->validate();
diff --git a/tests/Forms/Controls.TextInput.valueObjectValidation.phpt b/tests/Forms/Controls.TextInput.valueObjectValidation.phpt
index 5238423b6..2304c7673 100644
--- a/tests/Forms/Controls.TextInput.valueObjectValidation.phpt
+++ b/tests/Forms/Controls.TextInput.valueObjectValidation.phpt
@@ -15,8 +15,7 @@ require __DIR__ . '/../bootstrap.php';
class ValueObject
{
- /** @var string */
- private $value;
+ private string $value;
public function __construct(string $value)
diff --git a/tests/Forms/Controls.translate().phpt b/tests/Forms/Controls.translate().phpt
index 7d0ec0ccb..9b097e37f 100644
--- a/tests/Forms/Controls.translate().phpt
+++ b/tests/Forms/Controls.translate().phpt
@@ -17,7 +17,7 @@ class Translator implements Nette\Localization\ITranslator
{
public function translate($message, ...$parameters): string
{
- return is_object($message) ? get_class($message) : $message;
+ return is_object($message) ? $message::class : $message;
}
}
diff --git a/tests/Forms/DataClassGenerator.phpt b/tests/Forms/DataClassGenerator.phpt
index 04d1e9acb..4016394a3 100644
--- a/tests/Forms/DataClassGenerator.phpt
+++ b/tests/Forms/DataClassGenerator.phpt
@@ -40,7 +40,7 @@ class SignContFormData
public ?string $name;
}
',
- $res
+ $res,
);
$generator->propertyPromotion = true;
@@ -68,5 +68,5 @@ class SignContFormData
}
}
',
- $res
+ $res,
);
diff --git a/tests/Forms/Forms.getHttpData.get.2.phpt b/tests/Forms/Forms.getHttpData.get.2.phpt
index 187ec8d8b..fb4ce75fd 100644
--- a/tests/Forms/Forms.getHttpData.get.2.phpt
+++ b/tests/Forms/Forms.getHttpData.get.2.phpt
@@ -29,5 +29,5 @@ test('', function () {
Assert::truthy($form->isSubmitted());
Assert::same(['item'], $form->getHttpData());
- Assert::same([], $form->getValues(true));
+ Assert::same([], $form->getValues('array'));
});
diff --git a/tests/Forms/Forms.getHttpData.get.phpt b/tests/Forms/Forms.getHttpData.get.phpt
index 795ff6a8f..10090f1ff 100644
--- a/tests/Forms/Forms.getHttpData.get.phpt
+++ b/tests/Forms/Forms.getHttpData.get.phpt
@@ -28,7 +28,7 @@ test('', function () {
Assert::false($form->isSubmitted());
Assert::false($form->isSuccess());
Assert::same([], $form->getHttpData());
- Assert::same([], $form->getValues(true));
+ Assert::same([], $form->getValues('array'));
});
@@ -38,7 +38,7 @@ test('', function () {
Assert::false($form->isSubmitted());
Assert::same([], $form->getHttpData());
- Assert::same([], $form->getValues(true));
+ Assert::same([], $form->getValues('array'));
});
@@ -53,6 +53,6 @@ test('', function () {
Assert::truthy($form->isSubmitted());
Assert::same([Form::TRACKER_ID => $name], $form->getHttpData());
- Assert::same([], $form->getValues(true));
+ Assert::same([], $form->getValues('array'));
Assert::same($name, $form[Form::TRACKER_ID]->getValue());
});
diff --git a/tests/Forms/Forms.getHttpData.post.phpt b/tests/Forms/Forms.getHttpData.post.phpt
index 219e3a3be..b4fdd2852 100644
--- a/tests/Forms/Forms.getHttpData.post.phpt
+++ b/tests/Forms/Forms.getHttpData.post.phpt
@@ -29,7 +29,7 @@ test('', function () {
Assert::truthy($form->isSubmitted());
Assert::true($form->isSuccess());
Assert::same([], $form->getHttpData());
- Assert::same([], $form->getValues(true));
+ Assert::same([], $form->getValues('array'));
});
@@ -42,7 +42,7 @@ test('', function () {
Assert::false($form->isSubmitted());
Assert::false($form->isSuccess());
Assert::same([], $form->getHttpData());
- Assert::same([], $form->getValues(true));
+ Assert::same([], $form->getValues('array'));
});
@@ -54,7 +54,7 @@ test('', function () {
Assert::false($form->isSubmitted());
Assert::false($form->isSuccess());
Assert::same([], $form->getHttpData());
- Assert::same([], $form->getValues(true));
+ Assert::same([], $form->getValues('array'));
});
@@ -67,7 +67,7 @@ test('', function () {
Assert::truthy($form->isSubmitted());
Assert::same([Form::TRACKER_ID => $name], $form->getHttpData());
- Assert::same([], $form->getValues(true));
+ Assert::same([], $form->getValues('array'));
Assert::same($name, $form[Form::TRACKER_ID]->getValue());
});
diff --git a/tests/Forms/Forms.omittedValue.phpt b/tests/Forms/Forms.omittedValue.phpt
index 54e952b3a..ae5ed9882 100644
--- a/tests/Forms/Forms.omittedValue.phpt
+++ b/tests/Forms/Forms.omittedValue.phpt
@@ -20,7 +20,7 @@ $form->addText('input');
$form->addText('omittedInput')
->setOmitted();
-Assert::same(['input' => ''], $form->getValues(true));
+Assert::same(['input' => ''], $form->getValues('array'));
Assert::true((new TextInput)->setDisabled()->isOmitted());
diff --git a/tests/Forms/Forms.renderer.translate.phpt b/tests/Forms/Forms.renderer.translate.phpt
index 9a367e4ac..5fdb7b45f 100644
--- a/tests/Forms/Forms.renderer.translate.phpt
+++ b/tests/Forms/Forms.renderer.translate.phpt
@@ -15,7 +15,7 @@ require __DIR__ . '/../bootstrap.php';
class Translator implements ITranslator
{
- public $counter = [];
+ public array $counter = [];
public function translate($message, ...$parameters): string
diff --git a/tests/Forms/Helpers.createInputList.phpt b/tests/Forms/Helpers.createInputList.phpt
index 129ff988a..afe75c8e8 100644
--- a/tests/Forms/Helpers.createInputList.phpt
+++ b/tests/Forms/Helpers.createInputList.phpt
@@ -17,24 +17,24 @@ require __DIR__ . '/../bootstrap.php';
test('', function () {
Assert::same(
'',
- Helpers::createInputList([])
+ Helpers::createInputList([]),
);
Assert::same(
'',
- Helpers::createInputList(['a'])
+ Helpers::createInputList(['a']),
);
Assert::same(
'',
- Helpers::createInputList([1])
+ Helpers::createInputList([1]),
);
Assert::same(
'',
Helpers::createInputList(
- ['a' => 'First', 'b' => 'Second']
- )
+ ['a' => 'First', 'b' => 'Second'],
+ ),
);
Assert::same(
@@ -42,8 +42,8 @@ test('', function () {
Helpers::createInputList(
['a' => 'First', 'b' => 'Second'],
['type' => 'checkbox'],
- ['class' => 'button']
- )
+ ['class' => 'button'],
+ ),
);
Assert::same(
@@ -58,8 +58,8 @@ test('', function () {
[
'class:' => ['a' => ['class1', 'class2']],
'style' => ['color' => 'blue'],
- ]
- )
+ ],
+ ),
);
Assert::same(
@@ -68,8 +68,8 @@ test('', function () {
['a' => 'First', 'b' => 'Second'],
null,
null,
- '
'
- )
+ '
',
+ ),
);
Assert::same(
@@ -78,8 +78,8 @@ test('', function () {
['a' => 'First', 'b' => 'Second'],
null,
null,
- Html::el('div')
- )
+ Html::el('div'),
+ ),
);
Assert::same(
@@ -88,7 +88,7 @@ test('', function () {
['a' => 'First', 'b' => 'Second'],
null,
null,
- Html::el(null)
- )
+ Html::el(null),
+ ),
);
});
diff --git a/tests/Forms/Helpers.createSelectBox.phpt b/tests/Forms/Helpers.createSelectBox.phpt
index fe61a3b1f..a9609d092 100644
--- a/tests/Forms/Helpers.createSelectBox.phpt
+++ b/tests/Forms/Helpers.createSelectBox.phpt
@@ -17,24 +17,24 @@ require __DIR__ . '/../bootstrap.php';
test('', function () {
Assert::type(
Html::class,
- Helpers::createSelectBox([])
+ Helpers::createSelectBox([]),
);
Assert::same(
'',
- (string) Helpers::createSelectBox([])
+ (string) Helpers::createSelectBox([]),
);
Assert::same(
'',
- (string) Helpers::createSelectBox(['a'])
+ (string) Helpers::createSelectBox(['a']),
);
Assert::same(
'',
(string) Helpers::createSelectBox(
- ['a' => 'First', 'b' => 'Second']
- )
+ ['a' => 'First', 'b' => 'Second'],
+ ),
);
Assert::same(
@@ -43,8 +43,8 @@ test('', function () {
[
'a' => 'First',
'Group' => ['A', 'B'],
- ]
- )
+ ],
+ ),
);
Assert::same(
@@ -53,8 +53,8 @@ test('', function () {
[
'a' => Html::el('', 'Hello')->id('item-a'),
'Group' => [Html::el('', 'World')->id('item-b')],
- ]
- )
+ ],
+ ),
);
Assert::same(
@@ -67,16 +67,16 @@ test('', function () {
'title' => 'Hello',
'style' => ['color' => 'blue'],
'a' => 'b',
- ]
- )
+ ],
+ ),
);
Assert::same(
'',
(string) Helpers::createSelectBox(
['a' => 'First', 'b' => 'Second'],
- ['disabled:' => true, 'selected?' => 'b']
- )
+ ['disabled:' => true, 'selected?' => 'b'],
+ ),
);
Assert::same(
@@ -84,8 +84,8 @@ test('', function () {
(string) Helpers::createSelectBox(
['a' => 'First', 'b' => 'Second'],
[],
- 'b'
- )
+ 'b',
+ ),
);
Assert::same(
@@ -93,8 +93,8 @@ test('', function () {
(string) Helpers::createSelectBox(
[['a' => 'First'], ['a' => 'First']],
[],
- 'a'
- )
+ 'a',
+ ),
);
Assert::same(
@@ -102,8 +102,8 @@ test('', function () {
(string) Helpers::createSelectBox(
['a' => 'First', 'b' => 'Second'],
[],
- ['a', 'b']
- )
+ ['a', 'b'],
+ ),
);
Assert::same(
@@ -111,7 +111,7 @@ test('', function () {
(string) Helpers::createSelectBox(
[['a' => 'First'], ['a' => 'First']],
[],
- ['a', 'b']
- )
+ ['a', 'b'],
+ ),
);
});
diff --git a/tests/Forms/LatteRenderer.phpt b/tests/Forms/LatteRenderer.phpt
index c653be0a0..02068799e 100644
--- a/tests/Forms/LatteRenderer.phpt
+++ b/tests/Forms/LatteRenderer.phpt
@@ -82,5 +82,5 @@ Assert::match(
',
- $res
+ $res,
);
diff --git a/tests/Forms/Rules.valid.phpt b/tests/Forms/Rules.valid.phpt
index 964679b92..9b161292e 100644
--- a/tests/Forms/Rules.valid.phpt
+++ b/tests/Forms/Rules.valid.phpt
@@ -45,9 +45,7 @@ test('', function () {
test('', function () {
$form = new Form;
$form->addText('foo')
- ->addFilter(function ($value) {
- return str_replace(' ', '', $value);
- })
+ ->addFilter(fn($value) => str_replace(' ', '', $value))
->addRule($form::PATTERN, 'only numbers', '\d{5}');
$form['foo']->setValue('160 00');
@@ -65,9 +63,7 @@ test('', function () {
$foo = $form->addText('foo');
$rules = $foo->getRules();
$rules->addFilter(
- function ($value) {
- return str_replace(' ', '', $value);
- }
+ fn($value) => str_replace(' ', '', $value),
);
$rules->addRule($form::PATTERN, 'only numbers', '\d{5}');
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 039552af1..abb911275 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -15,7 +15,7 @@
date_default_timezone_set('Europe/Prague');
-function before(Closure $function = null)
+function before(?Closure $function = null)
{
static $val;
if (!func_num_args()) {
diff --git a/tests/types/ControlsReturnTypeTest.php b/tests/types/ControlsReturnTypeTest.php
new file mode 100644
index 000000000..d7ba40882
--- /dev/null
+++ b/tests/types/ControlsReturnTypeTest.php
@@ -0,0 +1,31 @@
+ */
+ public function dataFileAsserts(): iterable
+ {
+ yield from $this->gatherAssertTypes(__DIR__ . '/data/Controls.getValue().php');
+ }
+
+
+ /** @dataProvider dataFileAsserts */
+ public function testFileAsserts(string $assertType, string $file, mixed ...$args): void
+ {
+ $this->assertFileAsserts($assertType, $file, ...$args);
+ }
+}
+
+
+$testCase = new ControlsReturnTypeTest;
+$testCase->run();
diff --git a/tests/types/TestCase.php b/tests/types/TestCase.php
new file mode 100644
index 000000000..26d4771fe
--- /dev/null
+++ b/tests/types/TestCase.php
@@ -0,0 +1,22 @@
+addText('Text');
+assertType('string|null', $input->getValue());
+
+$input = $form->addPassword('Password');
+assertType('string|null', $input->getValue());
+
+$input = $form->addTextArea('TextArea');
+assertType('string|null', $input->getValue());
+
+$input = $form->addEmail('Email');
+assertType('string|null', $input->getValue());
+
+$input = $form->addInteger('Integer');
+assertType('string|null', $input->getValue());
+
+$input = $form->addUpload('Upload');
+assertType('array|Nette\Http\FileUpload|null', $input->getValue());
+
+$input = $form->addMultiUpload('MultiUpload');
+assertType('array|Nette\Http\FileUpload|null', $input->getValue());
+
+$input = $form->addHidden('Hidden');
+assertType('string|null', $input->getValue());
+
+$input = $form->addCheckbox('Checkbox');
+assertType('bool|null', $input->getValue());
+
+$input = $form->addRadioList('RadioList');
+assertType('int|string|null', $input->getValue());
+
+$input = $form->addCheckboxList('CheckboxList');
+assertType('array<(int|string)>', $input->getValue());
+
+$input = $form->addSelect('Select');
+assertType('int|string|null', $input->getValue());
+
+$input = $form->addMultiSelect('MultiSelect');
+assertType('array<(int|string)>', $input->getValue());
+
+$input = $form->addSubmit('Submit');
+assertType('string|null', $input->getValue());
+
+$input = $form->addButton('Button');
+assertType('string|null', $input->getValue());
+
+$input = $form->addImageButton('ImageButton');
+assertType('array|null', $input->getValue());
+
+$input = $form->addImage('Image');
+assertType('array|null', $input->getValue());