Skip to content

[Config] deprecate tree builders without root nodes #27476

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 25, 2018

Conversation

xabbuh
Copy link
Member

@xabbuh xabbuh commented Jun 2, 2018

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? yes
Tests pass? yes
Fixed tickets
License MIT
Doc PR

While reviewing #27472 I wondered if we really need support config trees without a root node. If we did not support it, users wouldn't create pseudo configuration classes when they were actually not needed.

@xabbuh xabbuh added this to the next milestone Jun 2, 2018
@xabbuh xabbuh force-pushed the deprecate-tree-builder-with-root-node branch from 4e83499 to f981459 Compare June 2, 2018 19:09
@nicolas-grekas
Copy link
Member

rebase needed

@@ -25,6 +25,7 @@
"require-dev": {
"symfony/asset": "~3.4|~4.0",
"symfony/browser-kit": "~3.4|~4.0",
"symfony/config": "~4.2",
Copy link
Member

Choose a reason for hiding this comment

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

I think this can be a normal requirement instead. I don't think it is currently possible to avoid it anyway.

@@ -24,13 +24,13 @@
"twig/twig": "~1.34|~2.4"
},
"require-dev": {
"symfony/config": "~3.4|~4.0",
"symfony/config": "~4.2",
Copy link
Member

Choose a reason for hiding this comment

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

As TwigBundle depends on it, and WebProfilerBundle depends on TwigBundle, this gets installed all the time already. I suggest making it a normal requirement instead of a conflict rule (this might even perform better in Composer, as a <4.2 conflict rule matches lots of packages)

public function __construct(string $name = null, string $type = 'array', NodeBuilder $builder = null)
{
if (null === $name) {
@trigger_error('A tree builder without a root node is deprecated since Symfony 4.2 and will not be supported anymore with 5.0.', E_USER_DEPRECATED);
Copy link
Member

Choose a reason for hiding this comment

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

shoudln't it be in 5.0 ?

@@ -41,6 +50,11 @@ public function root($name, $type = 'array', NodeBuilder $builder = null)
return $this->root = $builder->node($name, $type)->setParent($this);
}

public function getRootNode(): NodeDefinition
Copy link
Member

Choose a reason for hiding this comment

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

this return type is broken when using the deprecated API and not calling ->root(). I suggest throwing an exception with a meaningful message instead of letting PHP throw a TypeError (which will get reported as a bug in Symfony):

throw new \RuntimeException(sprintf('Calling %s before creating the root node is not supported. Migrate to the new constructor signature instead', __METHOD__));

if (null === $name) {
@trigger_error('A tree builder without a root node is deprecated since Symfony 4.2 and will not be supported anymore with 5.0.', E_USER_DEPRECATED);
} else {
$this->root($name, $type, $builder);
Copy link
Contributor

@ro0NL ro0NL Jun 5, 2018

Choose a reason for hiding this comment

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

should we deprecate public calls to root() as well? or is it still intended as a feature?

both the methods (root + getRootNode) can be seen confusing.

Copy link
Member Author

Choose a reason for hiding this comment

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

I do not really care to be honest. Since this is a builder there may be use cases to still call root() later. But I also see that we could probably discuss this as part of a follow up PR if you would like to open one. :)

@@ -23,6 +23,15 @@ class TreeBuilder implements NodeParentInterface
protected $tree;
protected $root;

public function __construct(string $name = null, string $type = 'array', NodeBuilder $builder = null)
Copy link
Contributor

Choose a reason for hiding this comment

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

how about ?NodeBuilder instead ? Use a nullable typehint instead of relying on 7.0's hackish way.

Copy link
Member

Choose a reason for hiding this comment

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

There is nothing hackish here, optional arguments are just fit here IMHO.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's not about the fact that this is optionnal or not. It's because NodeBuilder $builder = null, instead of ?Nodebuilder $builder = null. Yes it's one more char, but it's more pertinent. It was a hack in 7.0 to allow a null value.

Copy link
Member

Choose a reason for hiding this comment

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

@Taluu it's not "more pertinent", is exactly the same, meaning wise. It's not a hack at all but how the language is defined.

Copy link
Member

Choose a reason for hiding this comment

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

<?php

interface A {
    public function dummy(int $arg = null);
}

class B implements A {
    public function dummy(int $arg) { }
}

Fatal error: Declaration of B::dummy(int $arg) must be compatible with A::dummy(?int $arg = NULL) in nullable.php on line 7

Note the ? in the stack trace while it is not in the signature, it's really the same for the engine

@xabbuh xabbuh force-pushed the deprecate-tree-builder-with-root-node branch 3 times, most recently from a588420 to 9bd6ade Compare June 7, 2018 06:56
Copy link
Member

@fabpot fabpot left a comment

Choose a reason for hiding this comment

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

with. a minor comment

public function getRootNode(): NodeDefinition
{
if (null === $this->root) {
throw new \RuntimeException(sprintf('Calling %s() before creating the root node is not supported. Migrate to the new constructor signature instead', __METHOD__));
Copy link
Member

Choose a reason for hiding this comment

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

missing dot at the end of the exception message.

Copy link
Member

Choose a reason for hiding this comment

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

upported, migrate

@xabbuh xabbuh force-pushed the deprecate-tree-builder-with-root-node branch from 9bd6ade to b8e8890 Compare June 10, 2018 10:19
@nicolas-grekas
Copy link
Member

(rebase needed + comment to address)

@xabbuh xabbuh force-pushed the deprecate-tree-builder-with-root-node branch from b8e8890 to 056768d Compare June 19, 2018 12:33
@xabbuh xabbuh force-pushed the deprecate-tree-builder-with-root-node branch from 056768d to c2ce153 Compare June 19, 2018 12:34
@fabpot
Copy link
Member

fabpot commented Jun 25, 2018

Thank you @xabbuh.

@fabpot fabpot merged commit c2ce153 into symfony:master Jun 25, 2018
fabpot added a commit that referenced this pull request Jun 25, 2018
…abbuh)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[Config] deprecate tree builders without root nodes

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

While reviewing #27472 I wondered if we really need support config trees without a root node. If we did not support it, users wouldn't create pseudo configuration classes when they were actually not needed.

Commits
-------

c2ce153 deprecate tree builders without root nodes
@xabbuh xabbuh deleted the deprecate-tree-builder-with-root-node branch June 25, 2018 17:40
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.2 Nov 1, 2018
@apfelbox
Copy link
Contributor

How can we now write code that works deprecation-free in both Symfony 4.1 and 4.2?

The only thing I can come up with is:

$treeBuilder = new TreeBuilder("my_node");
$rootNode = method_exists($treeBuilder, "getRootNode")
    ? $treeBuilder->getRootNode()
    : $treeBuilder->root("my_node");

which is super hacky in two ways:

  1. needing to duplicate the key name
  2. code that needs to rely on method_exists() always looks like a hack to me.

@xabbuh do you have a better way?

@xabbuh
Copy link
Member Author

xabbuh commented Jan 27, 2019

That's indeed the way to go as long as you do not want to drop support for Symfony 4.1.

@apfelbox
Copy link
Contributor

All right. Thanks for the super fast response! 🙌

fabpot added a commit that referenced this pull request Apr 1, 2019
…ee builder (Koc)

This PR was merged into the 4.2 branch.

Discussion
----------

[Config] Improve PHPdoc / IDE autocomplete for config tree builder

| Q             | A
| ------------- | ---
| Branch?       | 4.2
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

follow up of #27476 and #21047

Commits
-------

21f7977 Improve PHPdoc / IDE autocomplete for config tree builder
richgerdes pushed a commit to richgerdes/jade that referenced this pull request Aug 6, 2019
As of Symfony 4.2, creating a config tree without a root node, is deprecated.

See symfony/symfony#27476.
richgerdes pushed a commit to richgerdes/jade that referenced this pull request Aug 6, 2019
As of Symfony 4.2, creating a config tree without a root node, is deprecated.

See symfony/symfony#27476.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants