Skip to content

Fix compatibility with component-model 4.0#72

Open
jtojnar wants to merge 7 commits into
Kdyby:masterfrom
jtojnar:deprecations
Open

Fix compatibility with component-model 4.0#72
jtojnar wants to merge 7 commits into
Kdyby:masterfrom
jtojnar:deprecations

Conversation

@jtojnar

@jtojnar jtojnar commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

No description provided.

For some reason, it was introduced escaped in 23a0df9, which is not supported and would fail with:

    sh: line 1: [@lint,: command not found

The proper format is using JSON arrays:

https://getcomposer.org/doc/articles/scripts.md#referencing-scripts
@jtojnar

jtojnar commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Bisected the failure to nette/component-model@b4e82e1

@jtojnar jtojnar force-pushed the deprecations branch 2 times, most recently from f90d587 to 2a7a997 Compare July 14, 2026 23:58
jtojnar added 6 commits July 15, 2026 01:59
Calling monitor with implicit handlers has been deprecated since component-model 3.0:

nette/component-model@857a493

And has been removed in 4.0:

nette/component-model@71321c9

Let’s switch to explicit handler.

Using different name to avoid deprecation warnings with nette/component-model 3.2.0.
component-model 4.0 removes the use of `Nette\SmartObject` so we can no longer access the private properties:

nette/component-model@c07bbee
PHPStan is confused by stubs, and infers that `Container::getComponents()` returns an untyped `array`. Perhaps because the stubs claim to return `Iterator` while upstream returns an `IComponent[]`.

phpstan/phpstan-nette#141
component-model 4.0 seems to have fixed the issue by changing the return type hint to `array`:

nette/component-model@c40aa8e
We are passing a function that has extra arguments compared to the `callable` in `extensionMethod` parameter type. Since a function with extra arguments is a supertype of a function without them, not a subtype, it will be rejected as per contravariance of arguments rule.

See nette/forms#354

Let’s ignore it for now.
After the dependency bump, the tests started to fail:

    Nette\InvalidStateException: Component 'users' is not attached to 'Nette\Forms\Form'.

    1. tests/Replicator/ContainerTest.php:376
       Tester\TestCase->run()
    2. vendor/nette/tester/src/Framework/TestCase.php:53
       Tester\TestCase->runTest()
    3. vendor/nette/tester/src/Framework/TestCase.php:132
       KdybyTests\Replicator\ContainerTest->testAddContainer()
    4. tests/Replicator/ContainerTest.php:257
       KdybyTests\Replicator\BaseForm->addDynamic()
    5. tests/Replicator/ContainerTest.php:350
       Nette\Forms\Container->offsetSet()
    6. vendor/nette/component-model/src/ComponentModel/ArrayAccess.php:27
       Nette\Forms\Container->addComponent()
    7. vendor/nette/forms/src/Forms/Container.php:299
       Nette\ComponentModel\Container->addComponent()
    8. vendor/nette/component-model/src/ComponentModel/Container.php:76
       Nette\ComponentModel\Component->setParent()
    9. vendor/nette/component-model/src/ComponentModel/Component.php:181
       Nette\ComponentModel\Component->refreshMonitors()
    10. vendor/nette/component-model/src/ComponentModel/Component.php:230
       Kdyby\Replicator\Container->attached()
    11. src/Replicator/Container.php:105
       Kdyby\Replicator\Container->loadHttpData()
    12. src/Replicator/Container.php:221
       Nette\Forms\Container->getForm()
    13. vendor/nette/forms/src/Forms/Container.php:330
       Nette\ComponentModel\Component->lookup()
    14. vendor/nette/component-model/src/ComponentModel/Component.php:67

Bisected that to nette/component-model@b4e82e1

@davidsolc-ai davidsolc-ai left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding component-model 4 compatibility. Please preserve the existing protected attached() extension point so this can remain a backward-compatible v3.0.1 fix. FormsReplicator 3.0 already permits nette/forms ^3.2.3, which includes Forms 3.3 and therefore component-model 4 on PHP 8.3+, so the incompatibility is a bug inside the currently advertised dependency range.

Nette requires explicit monitor() callbacks, but the callback may still be the existing protected method. Renaming it to a private method silently stops subclasses overriding attached() from receiving these events, even on component-model 3.x. The two inline suggestions retain that surface while removing the obsolete parent::attached() call.

Could you also add a regression test with a Container subclass that overrides attached(), calls parent::attached(), and records the callback? The existing PHP 8.3/8.4 highest jobs already verify Forms 3.3 with component-model 4.0.1.

Comment on lines +69 to +70
$this->monitor(Nette\Forms\Form::class, $this->componentAttached(...));
$this->monitor(Nette\Application\UI\Presenter::class, $this->componentAttached(...));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the existing protected method as the explicit callback. This follows component-model 4’s required monitor() API without dropping FormsReplicator’s subclass hook.

Suggested change
$this->monitor(Nette\Forms\Form::class, $this->componentAttached(...));
$this->monitor(Nette\Application\UI\Presenter::class, $this->componentAttached(...));
$this->monitor(Nette\Forms\Form::class, $this->attached(...));
$this->monitor(Nette\Application\UI\Presenter::class, $this->attached(...));

* Magical component factory
*/
protected function attached(Nette\ComponentModel\IComponent $obj): void
private function componentAttached(Nette\ComponentModel\IComponent $obj): void

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please retain the protected method. It has been subclass-visible since 2019 and is not marked @internal; making the replacement private creates an avoidable BC break. With the explicit callbacks above, no parent::attached() call is needed and this remains compatible with both component-model 3 and 4.

Suggested change
private function componentAttached(Nette\ComponentModel\IComponent $obj): void
protected function attached(Nette\ComponentModel\IComponent $obj): void

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants