From 6c8c4851bffdd15e141e5cf85c8283f1f840eaac Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 02:03:08 +0200 Subject: [PATCH 01/17] phpstan: Ignore temp files --- phpstan.dist.neon | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/phpstan.dist.neon b/phpstan.dist.neon index ead69a6..3e2931a 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -7,3 +7,8 @@ parameters: paths: - src - examples + + excludePaths: + - examples/**/log/* + - examples/**/temp/* + From 9d9073d135174b2e4b1d21ecbee277a40597f1ee Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 08:55:54 +0200 Subject: [PATCH 02/17] ci: Remove PHP 8.0 It should still work but PHPStan would get angry: Error: Property Nette\Forms\Rendering\DefaultFormRenderer::$form (Nette\Forms\Form) in isset() is not nullable. Error: Property Nette\Forms\Rendering\DefaultFormRenderer::$form (Nette\Forms\Form) in isset() is not nullable. Error: Parameter #1 $object_or_class of function method_exists expects object|string, mixed given. Error: Cannot call method getLabelPrototype() on class-string|object. Error: Property Nette\Forms\Rendering\DefaultFormRenderer::$form (Nette\Forms\Form) in isset() is not nullable. Error: Parameter #1 $object_or_class of function method_exists expects object|string, mixed given. Error: Cannot call method getControlPrototype() on class-string|object. Error: Cannot call method getControlPrototype() on class-string|object. Error: Cannot call method getLabelPrototype() on class-string|object. Likely because on PHP 8.0 we need to use `nette/forms` 3.1.15 rather than 3.2.9 used by PHP 8.1, and the former uses PHPDoc instead of property type hints: https://github.com/nette/forms/blob/v3.1.15/src/Forms/Rendering/DefaultFormRenderer.php#L121 And we do not want to bother fixing it. --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2dca508..7d99d06 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - php-version: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] + php-version: [ '8.1', '8.2', '8.3', '8.4', '8.5' ] steps: - name: Checkout From 525f020f5ccaa43bf0c4b10c1ca772bcc589da61 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 02:03:08 +0200 Subject: [PATCH 03/17] LatteTags: Fix PHPStan error with nette/forms < 3.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On PHP 8.1, PHPStan would complain: Access to an undefined property Nextras\FormsRendering\LatteTags\LabelNode::$tagRanges. We could add a `property_exists` for that as well but PHPStan 2 will consider at least one of the `property_exists` checks always true so we would need to ignore them. Also, since there can be some overlap where both properties exist, we cannot specify `count` of how many times the error should be ignored: | PHP | latte | forms | count | | 8.1 | 3.0.26| 3.2.9 | 1 | | 8.2 | 3.1.4 | 3.2.9 | 2 | | 8.3 | 3.1.4 | 3.3.0 | 1 | But even with that, PHPStan 2 would complain on PHP 8.1: Parameter #1 $array of function end expects array|object, mixed given. We could try to ignore that as well but that is painful since PHPStan would complain about stale ignore on PHP > 8.1, unless we wrote the config file in PHP and made the ignore conditional on `latte` version. Let’s just lie to PHPStan using `@property` annotations and use `isset` to achieve the runtime functionality. --- src/LatteTags/LabelNode.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/LatteTags/LabelNode.php b/src/LatteTags/LabelNode.php index 33590b5..b8b3810 100644 --- a/src/LatteTags/LabelNode.php +++ b/src/LatteTags/LabelNode.php @@ -16,6 +16,13 @@ use Nette\Utils\Html; +/** + * These are fake properties to satisfy PHPStan, at least one of them + * should exist depending on the versions of installed dependencies. + * TODO: Drop these once we no longer support forms < 3.3. + * @property-read array $tagRanges + * @property-read mixed $endLine + */ abstract class LabelNode extends NetteLabelNode { public function print(PrintContext $context): string @@ -34,7 +41,7 @@ public function print(PrintContext $context): string $this->position, $this->content, // TODO: Drop the `endLine` support once we no longer support forms < 3.3. - property_exists($this, 'endLine') ? $this->endLine : end($this->tagRanges), + isset($this->endLine) ? $this->endLine : end($this->tagRanges), ); } From 109def1c94028015ba74a5c610dce97650476be2 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 02:17:26 +0200 Subject: [PATCH 04/17] Use class constant instead of local static variable PHPStan 2 would raise `argument.type` error: Parameter #2 $haystack of function in_array expects array, mixed given. --- src/LatteTags/Bs3/Bs3InputNode.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/LatteTags/Bs3/Bs3InputNode.php b/src/LatteTags/Bs3/Bs3InputNode.php index 12dd16f..1a571b8 100644 --- a/src/LatteTags/Bs3/Bs3InputNode.php +++ b/src/LatteTags/Bs3/Bs3InputNode.php @@ -18,14 +18,15 @@ class Bs3InputNode extends BaseInputNode { + private const INPUT_CONTROLS = ['radio', 'checkbox', 'file', 'hidden', 'range', 'image', 'submit', 'reset']; + public static function input(Html $input, BaseControl $control, bool $isSubItem): Html { - static $inputControls = ['radio', 'checkbox', 'file', 'hidden', 'range', 'image', 'submit', 'reset']; $name = $input->getName(); if ( $name === 'select' || $name === 'textarea' || - ($name === 'input' && !in_array($input->type, $inputControls, true)) + ($name === 'input' && !in_array($input->type, self::INPUT_CONTROLS, true)) ) { $input->addClass('form-control'); } elseif ($name === 'input' && ($input->type === 'submit' || $input->type === 'reset')) { From 473d1ff30fa82089d98267b5737e9891f6369197 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 09:43:19 +0200 Subject: [PATCH 05/17] Bs{4,5}FormRenderer: Assert duck-typed return value This will satisfy PHPStan 2. While it is not guaranteed that the methods will return `Html`, any reasonable control implementation probably does that. --- src/Renderers/Bs4FormRenderer.php | 5 ++++- src/Renderers/Bs5FormRenderer.php | 14 ++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Renderers/Bs4FormRenderer.php b/src/Renderers/Bs4FormRenderer.php index 2397ed4..1097b9d 100644 --- a/src/Renderers/Bs4FormRenderer.php +++ b/src/Renderers/Bs4FormRenderer.php @@ -148,7 +148,10 @@ private function controlsInit(): void foreach ($this->form->getControls() as $control) { if ($this->layout === FormLayout::INLINE && !$control instanceof Controls\Checkbox && method_exists($control, 'getLabelPrototype')) { - $control->getLabelPrototype()->addClass('my-1')->addClass('mr-2'); + $labelPrototype = $control->getLabelPrototype(); + \assert($labelPrototype instanceof Html); // For PHPStan + + $labelPrototype->addClass('my-1')->addClass('mr-2'); } if ($control instanceof Controls\Button) { diff --git a/src/Renderers/Bs5FormRenderer.php b/src/Renderers/Bs5FormRenderer.php index c920aef..e279be6 100644 --- a/src/Renderers/Bs5FormRenderer.php +++ b/src/Renderers/Bs5FormRenderer.php @@ -158,20 +158,26 @@ private function controlsInit(): void // The checkboxes are exception since they have their own inline class. if (!$control instanceof Controls\Checkbox && !$control instanceof Controls\CheckboxList && !$control instanceof Controls\RadioList && method_exists($control, 'getControlPrototype')) { - $control->getControlPrototype()->addClass('d-inline-block'); + $controlPrototype = $control->getControlPrototype(); + \assert($controlPrototype instanceof Html); // For PHPStan + + $controlPrototype->addClass('d-inline-block'); // But setting `display: inline-block` is not enough since the widgets will inherit // `width: 100%` from `.form-control` and end up wrapped anyway. // Let’s counter that using `width: auto`. - $control->getControlPrototype()->addClass('w-auto'); + $controlPrototype->addClass('w-auto'); if ($control instanceof Controls\TextBase && $control->control->type === 'color') { // `input[type=color]` is a special case since `width: auto` would make it squish. - $control->getControlPrototype()->addStyle('min-width', '3rem'); + $controlPrototype->addStyle('min-width', '3rem'); } } + $labelPrototype = $control->getLabelPrototype(); + \assert($labelPrototype instanceof Html); // For PHPStan + // Also, we need to add some spacing between the label and the control. - $control->getLabelPrototype()->addClass('me-2'); + $labelPrototype->addClass('me-2'); } if ($control instanceof Controls\Button) { From 0ec0be8e2a8e946aa0cc2e8b08b9f43c47986fea Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 09:55:33 +0200 Subject: [PATCH 06/17] Bs3InputNode: Fix `argument.type` error in PHPStan 2 `phpstan/phpstan-nette` registers `PropertyReflection` for `Html` class that changes property types to `mixed`: https://github.com/phpstan/phpstan-nette/blob/2.0.12/src/Reflection/Nette/HtmlPropertyReflection.php#L21 This seems to take precedence over the upstream `@property` PHPDoc annotations: https://github.com/nette/utils/commit/52d7e1bd734ef52e6e54ea835f9c98f632dcc036 As a result, PHPStan would complain: Parameter #1 $child of method Nette\Utils\Html::addHtml() expects Nette\HtmlStringable|string, mixed given. --- src/LatteTags/Bs3/Bs3InputNode.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/LatteTags/Bs3/Bs3InputNode.php b/src/LatteTags/Bs3/Bs3InputNode.php index 1a571b8..2627651 100644 --- a/src/LatteTags/Bs3/Bs3InputNode.php +++ b/src/LatteTags/Bs3/Bs3InputNode.php @@ -29,7 +29,8 @@ public static function input(Html $input, BaseControl $control, bool $isSubItem) ($name === 'input' && !in_array($input->type, self::INPUT_CONTROLS, true)) ) { $input->addClass('form-control'); - } elseif ($name === 'input' && ($input->type === 'submit' || $input->type === 'reset')) { + } elseif ($name === 'input' && ($input->type === 'submit' || $input->type === 'reset') && is_string($input->value)) { + // is_string above is needed by PHPStan since phpstan-nette claims all properties are mixed. $input->setName('button'); $input->addHtml($input->value); $input->addClass('btn'); From 05defe3967856f4ab2d1d62edcc6d7c1a7e8690f Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 10:03:12 +0200 Subject: [PATCH 07/17] Bs3FormRenderer: Fix `binaryOp.invalid` in PHPStan 2 Similarly to in previous commit, `phpstan/phpstan-nette` changes virtual property types to `mixed`. As a result, PHPStan would complain: Binary operation "." between mixed and '-inline' results in an error. --- src/Renderers/Bs3FormRenderer.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Renderers/Bs3FormRenderer.php b/src/Renderers/Bs3FormRenderer.php index fb382b1..4bda0ba 100644 --- a/src/Renderers/Bs3FormRenderer.php +++ b/src/Renderers/Bs3FormRenderer.php @@ -137,7 +137,11 @@ private function controlsInit(): void if ($control instanceof Controls\Checkbox) { $control->getContainerPrototype()->setName('div')->appendAttribute('class', $control->getControlPrototype()->type); } else { - $control->getItemLabelPrototype()->addClass($control->getControlPrototype()->type . '-inline'); + $type = $control->getControlPrototype()->type; + // For PHPStan: Both control types initialize it to constructor in string. + \assert(is_string($type)); + + $control->getItemLabelPrototype()->addClass($type . '-inline'); } } } From ecac184ef30082bc7cc4c20e9793af79f68e6a5f Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 10:20:32 +0200 Subject: [PATCH 08/17] composer: Upgrade to PHPStan 2.2 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 83ac8ac..64a713d 100644 --- a/composer.json +++ b/composer.json @@ -20,8 +20,8 @@ "nette/application": "^3.0", "nette/bootstrap": "^3.0", "nette/di": "^3.0", - "phpstan/phpstan": "~1.8", - "phpstan/phpstan-nette": "~1.0", + "phpstan/phpstan": "^2.2", + "phpstan/phpstan-nette": "^2.0", "tracy/tracy": "^2.5" }, "extra": { From 90ddcf1dacb45b10a2012dafc6824cf94643e842 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 11:11:24 +0200 Subject: [PATCH 09/17] examples: Create temp and log directories Without these, the examples will fail to start. Using the same pattern as https://github.com/nette/web-project/commit/0eae6609f2d7812a287397e5ccec0900b0cdb887 --- examples/.gitignore | 2 -- examples/lattemacros/log/.gitignore | 2 ++ examples/lattemacros/temp/.gitignore | 2 ++ examples/renderers/log/.gitignore | 2 ++ examples/renderers/temp/.gitignore | 2 ++ 5 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 examples/.gitignore create mode 100644 examples/lattemacros/log/.gitignore create mode 100644 examples/lattemacros/temp/.gitignore create mode 100644 examples/renderers/log/.gitignore create mode 100644 examples/renderers/temp/.gitignore diff --git a/examples/.gitignore b/examples/.gitignore deleted file mode 100644 index c1e0f82..0000000 --- a/examples/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -log -temp diff --git a/examples/lattemacros/log/.gitignore b/examples/lattemacros/log/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/examples/lattemacros/log/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/examples/lattemacros/temp/.gitignore b/examples/lattemacros/temp/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/examples/lattemacros/temp/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/examples/renderers/log/.gitignore b/examples/renderers/log/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/examples/renderers/log/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/examples/renderers/temp/.gitignore b/examples/renderers/temp/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/examples/renderers/temp/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore From 48ae105d4824ddfdca5827627e9cadbaa000a5e1 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 11:18:30 +0200 Subject: [PATCH 10/17] examples/renderers: Use `#[Persistent]` attribute Supported since 3.0.7: https://github.com/nette/application/commit/d2471134ed909210de8a3e8559931902b1bee67b Deprecated since 3.3.0: https://github.com/nette/application/commit/2b6117396dcdc4b60a1d7e7a5188d041549b1307 --- examples/renderers/RenderersPresenter.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/renderers/RenderersPresenter.php b/examples/renderers/RenderersPresenter.php index 8a03322..a062a3c 100644 --- a/examples/renderers/RenderersPresenter.php +++ b/examples/renderers/RenderersPresenter.php @@ -2,6 +2,7 @@ namespace NextrasDemos\FormsRendering\Renderers; +use Nette\Application\Attributes\Persistent; use Nette\Application\UI\Form; use Nette\Application\UI\Presenter; use Nextras\FormsRendering\Renderers\Bs3FormRenderer; @@ -14,14 +15,14 @@ class RenderersPresenter extends Presenter { /** * @var string - * @persistent */ + #[Persistent] public $renderer = 'bs3'; /** * @var bool - * @persistent */ + #[Persistent] public $showBulky = true; From 25755a06ced7158c9859ccfc1e1269e30b7fffb7 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 11:21:59 +0200 Subject: [PATCH 11/17] examples/lattemacros: Add comma before form macro arguments Missing comma is deprecated since 3.3.0: https://github.com/nette/forms/commit/118561dff1d8080cfc7ed24ef30cfb06605e6834 --- examples/lattemacros/LatteMacrosPresenter.latte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lattemacros/LatteMacrosPresenter.latte b/examples/lattemacros/LatteMacrosPresenter.latte index 1c38888..5dbb203 100644 --- a/examples/lattemacros/LatteMacrosPresenter.latte +++ b/examples/lattemacros/LatteMacrosPresenter.latte @@ -12,7 +12,7 @@

Form LatteMacros rendering


- {form form class => form-horizontal} + {form form, class => form-horizontal}
{bsLabel text class => "label-control col-sm-3" /}
{bsInput text}{inputError text}
From 10b22eccb4484429c4b3696d4ef0d148c8db3b73 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 11:47:42 +0200 Subject: [PATCH 12/17] LatteTags: Support nette/forms 3.3.0 `Runtime` is no longer static: https://github.com/nette/forms/commit/00de98de84c45f78532f4babc40d500b493d8c54 Keep compatibility with old version since 3.3 is too new. --- phpstan.dist.neon | 6 ++++++ src/LatteTags/InputNode.php | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/phpstan.dist.neon b/phpstan.dist.neon index 3e2931a..bdbc414 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -12,3 +12,9 @@ parameters: - examples/**/log/* - examples/**/temp/* + ignoreErrors: + - + message: '#^Call to function method_exists\(\) with ''Nette\\\\Bridges\\\\FormsLatte\\\\Runtime'' and ''renderFormBegin'' will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + reportUnmatched: false + path: src/LatteTags/InputNode.php diff --git a/src/LatteTags/InputNode.php b/src/LatteTags/InputNode.php index 93adbe7..cee666a 100644 --- a/src/LatteTags/InputNode.php +++ b/src/LatteTags/InputNode.php @@ -21,8 +21,10 @@ abstract class InputNode extends NetteInputNode public function print(PrintContext $context): string { $class = static::class; + $hasForms33 = method_exists(\Nette\Bridges\FormsLatte\Runtime::class, 'renderFormBegin'); + $input = $hasForms33 ? 'Nette\Bridges\FormsLatte\Runtime::item(%node, $this->global)' : '$this->global->forms->get(%node);'; return $context->format( - '$ʟ_input = Nette\Bridges\FormsLatte\Runtime::item(%node, $this->global);' + '$ʟ_input = ' . $input . 'echo ' . $class . '::input($ʟ_input->' . ($this->part ? ('getControlPart(%node)') : 'getControl()') . ($this->attributes->items ? '->addAttributes(%2.node)' : '') From b631ddb347ed960a418876da1cd77844100024c0 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 12:23:39 +0200 Subject: [PATCH 13/17] composer: Exclude temp directories from classmap Otherwise `composer dump-autoload -o` will warn when the temp directories contain generated containers: Class Template_e24d735b58 located in ./examples/renderers/temp/cache/latte/examples-renderers-RenderersPresenter.latte--e24d735b58.php does not comply with psr-4 autoloading standard (rule: NextrasDemos\FormsRendering\Renderers\ => ./examples/renderers). Skipping. Class Container_59e8c5ece8 located in ./examples/renderers/temp/cache/nette.configurator/Container_59e8c5ece8.php does not comply with psr-4 autoloading standard (rule: NextrasDemos\FormsRendering\Renderers\ => ./examples/renderers). Skipping. Class Template_e535838971 located in ./examples/lattemacros/temp/cache/latte/examples-lattemacros-LatteMacrosPresenter.latte--e535838971.php does not comply with psr-4 autoloading standard (rule: NextrasDemos\FormsRendering\LatteMacros\ => ./examples/lattemacros). Skipping. Class Container_c70388baf3 located in ./examples/lattemacros/temp/cache/nette.configurator/Container_c70388baf3.php does not comply with psr-4 autoloading standard (rule: NextrasDemos\FormsRendering\LatteMacros\ => ./examples/lattemacros). Skipping. --- composer.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 64a713d..c453db8 100644 --- a/composer.json +++ b/composer.json @@ -42,6 +42,10 @@ "psr-4": { "NextrasDemos\\FormsRendering\\LatteMacros\\": "examples/lattemacros/", "NextrasDemos\\FormsRendering\\Renderers\\": "examples/renderers/" - } + }, + "exclude-from-classmap": [ + "examples/lattemacros/temp/", + "examples/renderers/temp/" + ] } } From 5e84a78c94b300513d018dd9d9f887c52bbf7f22 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 12:36:43 +0200 Subject: [PATCH 14/17] Bs{4,5}FormRenderer: Fix deprecation of `Checkbox::getSeparatorPrototype()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `nette/forms` 3.1.0 renamed it to more sensible `getContainerPrototype()`: https://github.com/nette/forms/commit/53785022c9e21cd58633df10827168157c109465 Let’s bump the minimal version since it is old enough: https://github.com/nette/forms/releases/tag/v3.1.0 --- composer.json | 2 +- src/Renderers/Bs4FormRenderer.php | 3 ++- src/Renderers/Bs5FormRenderer.php | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index c453db8..e293933 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "require": { "php": ">=8.0", "latte/latte": "^3.0", - "nette/forms": "^3.0", + "nette/forms": "^3.1", "nette/utils": "^3.0 || ^4.0" }, "require-dev": { diff --git a/src/Renderers/Bs4FormRenderer.php b/src/Renderers/Bs4FormRenderer.php index 1097b9d..8afba02 100644 --- a/src/Renderers/Bs4FormRenderer.php +++ b/src/Renderers/Bs4FormRenderer.php @@ -170,7 +170,8 @@ private function controlsInit(): void } elseif ($control instanceof Controls\Checkbox || $control instanceof Controls\CheckboxList || $control instanceof Controls\RadioList) { $control->getControlPrototype()->addClass('form-check-input'); - $control->getSeparatorPrototype() + $wrapper = $control instanceof Controls\Checkbox ? $control->getContainerPrototype() : $control->getSeparatorPrototype(); + $wrapper ->setName('div') ->appendAttribute('class', 'form-check') ->appendAttribute('class', 'form-check-inline', $this->layout == FormLayout::INLINE); diff --git a/src/Renderers/Bs5FormRenderer.php b/src/Renderers/Bs5FormRenderer.php index e279be6..2a232a7 100644 --- a/src/Renderers/Bs5FormRenderer.php +++ b/src/Renderers/Bs5FormRenderer.php @@ -210,7 +210,8 @@ private function controlsInit(): void $control->getControlPrototype()->addClass('form-check-input'); // They also need to be individually wrapped in `div.form-check`. - $control->getSeparatorPrototype() + $wrapper = $control instanceof Controls\Checkbox ? $control->getContainerPrototype() : $control->getSeparatorPrototype(); + $wrapper ->setName('div') ->appendAttribute('class', 'form-check') // They support being displayed inline with `.form-check-inline`. From afe76682c60932d6648007c482e3304542d405b9 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 12:43:36 +0200 Subject: [PATCH 15/17] examples: Fix `Configurator` deprecations `nette/bootstrap` 3.1.0 renamed `Nette\Configurator` to `Nette\Bootstrap\Configurator`: https://github.com/nette/bootstrap/commit/8ff4ddb3c97c172b07f07a2bdeee36730ec02196 Also 3.2.0 deprecated `Configurator::enableDebugger()`: https://github.com/nette/bootstrap/commit/70f9e96249c1c66924c344e94974cd329c5e2d5b `enableTracy()` is available since 3.0.0 https://github.com/nette/bootstrap/commit/61f4ff53088d19deec7eb1da7cb762542db74576 Bumping since 3.1.0 is already pretty old: https://github.com/nette/bootstrap/releases/tag/v3.1.0 --- composer.json | 2 +- examples/lattemacros/index.php | 4 ++-- examples/renderers/index.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index e293933..514c3f4 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ }, "require-dev": { "nette/application": "^3.0", - "nette/bootstrap": "^3.0", + "nette/bootstrap": "^3.1", "nette/di": "^3.0", "phpstan/phpstan": "^2.2", "phpstan/phpstan-nette": "^2.0", diff --git a/examples/lattemacros/index.php b/examples/lattemacros/index.php index dadb9aa..1f90820 100644 --- a/examples/lattemacros/index.php +++ b/examples/lattemacros/index.php @@ -3,13 +3,13 @@ namespace NextrasDemos\FormsRendering\LatteMacros; use Nette\Application\Application; -use Nette\Configurator; +use Nette\Bootstrap\Configurator; require_once __DIR__ . '/../../vendor/autoload.php'; $configurator = new Configurator; -$configurator->enableDebugger(__DIR__ . '/log'); +$configurator->enableTracy(__DIR__ . '/log'); $configurator->setTempDirectory(__DIR__ . '/temp'); $configurator->addConfig(__DIR__ . '/config.neon'); diff --git a/examples/renderers/index.php b/examples/renderers/index.php index 70c1d06..f748bc6 100644 --- a/examples/renderers/index.php +++ b/examples/renderers/index.php @@ -3,13 +3,13 @@ namespace NextrasDemos\FormsRendering\Renderers; use Nette\Application\Application; -use Nette\Configurator; +use Nette\Bootstrap\Configurator; require_once __DIR__ . '/../../vendor/autoload.php'; $configurator = new Configurator; -$configurator->enableDebugger(__DIR__ . '/log'); +$configurator->enableTracy(__DIR__ . '/log'); $configurator->setTempDirectory(__DIR__ . '/temp'); $configurator->addConfig(__DIR__ . '/config.neon'); From 174c5c89f68da4dcb019cb7637afcddd6e47e747 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 12:43:59 +0200 Subject: [PATCH 16/17] phpstan: Check deprecations --- composer.json | 1 + phpstan.dist.neon | 1 + 2 files changed, 2 insertions(+) diff --git a/composer.json b/composer.json index 514c3f4..3f4d01f 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,7 @@ "nette/bootstrap": "^3.1", "nette/di": "^3.0", "phpstan/phpstan": "^2.2", + "phpstan/phpstan-deprecation-rules": "^2.0", "phpstan/phpstan-nette": "^2.0", "tracy/tracy": "^2.5" }, diff --git a/phpstan.dist.neon b/phpstan.dist.neon index bdbc414..f3f56a9 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -1,4 +1,5 @@ includes: + - vendor/phpstan/phpstan-deprecation-rules/rules.neon - vendor/phpstan/phpstan-nette/extension.neon - vendor/phpstan/phpstan-nette/rules.neon From 26c66e99568d7d6f39959a63437eda1378c6503a Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Tue, 14 Jul 2026 12:45:46 +0200 Subject: [PATCH 17/17] LatteTags: Remove unused import --- src/LatteTags/InputNode.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/LatteTags/InputNode.php b/src/LatteTags/InputNode.php index cee666a..3fa332c 100644 --- a/src/LatteTags/InputNode.php +++ b/src/LatteTags/InputNode.php @@ -9,7 +9,6 @@ namespace Nextras\FormsRendering\LatteTags; -use Latte\Compiler\Nodes\Php\Scalar\StringNode; use Latte\Compiler\PrintContext; use Nette\Bridges\FormsLatte\Nodes\InputNode as NetteInputNode; use Nette\Forms\Controls\BaseControl;