Skip to content

Commit

Permalink
bug #40603 [Config] Fixed support for nodes not extending BaseNode (N…
Browse files Browse the repository at this point in the history
…yholm)

This PR was merged into the 4.4 branch.

Discussion
----------

[Config] Fixed support for nodes not extending BaseNode

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       |
| License       | MIT
| Doc PR        |

Too many times we assume that a `NodeInterface` extends `BaseNode`. This PR adds a small test with a new `CustomNodeDefinition` and `CustomNode` that implements `NodeInterface`.

Commits
-------

6827656 Fixed support for nodes not extending BaseNode
  • Loading branch information
nicolas-grekas committed Apr 1, 2021
2 parents cc7d126 + 6827656 commit bd90627
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 39 deletions.
2 changes: 1 addition & 1 deletion src/Symfony/Component/Config/Definition/ArrayNode.php
Expand Up @@ -68,7 +68,7 @@ protected function preNormalize($value)
/**
* Retrieves the children of this node.
*
* @return array The children
* @return array<string, NodeInterface>
*/
public function getChildren()
{
Expand Down
Expand Up @@ -127,7 +127,9 @@ public function getNode($forceRootNode = false)
}

$node = $this->createNode();
$node->setAttributes($this->attributes);
if ($node instanceof BaseNode) {
$node->setAttributes($this->attributes);
}

return $node;
}
Expand Down
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\Config\Definition\Dumper;

use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\BaseNode;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\EnumNode;
use Symfony\Component\Config\Definition\NodeInterface;
Expand Down Expand Up @@ -126,50 +127,52 @@ private function writeNode(NodeInterface $node, int $depth = 0, bool $root = fal

// get attributes and elements
foreach ($children as $child) {
if (!$child instanceof ArrayNode) {
// get attributes
if ($child instanceof ArrayNode) {
// get elements
$rootChildren[] = $child;

// metadata
$name = str_replace('_', '-', $child->getName());
$value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world
continue;
}

// comments
$comments = [];
if ($info = $child->getInfo()) {
$comments[] = $info;
}
// get attributes

if ($example = $child->getExample()) {
$comments[] = 'Example: '.$example;
}
// metadata
$name = str_replace('_', '-', $child->getName());
$value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world

if ($child->isRequired()) {
$comments[] = 'Required';
}
// comments
$comments = [];
if ($child instanceof BaseNode && $info = $child->getInfo()) {
$comments[] = $info;
}

if ($child->isDeprecated()) {
$comments[] = sprintf('Deprecated (%s)', $child->getDeprecationMessage($child->getName(), $node->getPath()));
}
if ($child instanceof BaseNode && $example = $child->getExample()) {
$comments[] = 'Example: '.$example;
}

if ($child instanceof EnumNode) {
$comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues()));
}
if ($child->isRequired()) {
$comments[] = 'Required';
}

if (\count($comments)) {
$rootAttributeComments[$name] = implode(";\n", $comments);
}
if ($child instanceof BaseNode && $child->isDeprecated()) {
$comments[] = sprintf('Deprecated (%s)', $child->getDeprecationMessage($child->getName(), $node->getPath()));
}

// default values
if ($child->hasDefaultValue()) {
$value = $child->getDefaultValue();
}
if ($child instanceof EnumNode) {
$comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues()));
}

// append attribute
$rootAttributes[$name] = $value;
} else {
// get elements
$rootChildren[] = $child;
if (\count($comments)) {
$rootAttributeComments[$name] = implode(";\n", $comments);
}

// default values
if ($child->hasDefaultValue()) {
$value = $child->getDefaultValue();
}

// append attribute
$rootAttributes[$name] = $value;
}
}

Expand Down
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\Config\Definition\Dumper;

use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\BaseNode;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\EnumNode;
use Symfony\Component\Config\Definition\NodeInterface;
Expand Down Expand Up @@ -76,7 +77,10 @@ private function writeNode(NodeInterface $node, NodeInterface $parentNode = null
$default = '';
$defaultArray = null;
$children = null;
$example = $node->getExample();
$example = null;
if ($node instanceof BaseNode) {
$example = $node->getExample();
}

// defaults
if ($node instanceof ArrayNode) {
Expand Down Expand Up @@ -123,7 +127,7 @@ private function writeNode(NodeInterface $node, NodeInterface $parentNode = null
}

// deprecated?
if ($node->isDeprecated()) {
if ($node instanceof BaseNode && $node->isDeprecated()) {
$comments[] = sprintf('Deprecated (%s)', $node->getDeprecationMessage($node->getName(), $parentNode ? $parentNode->getPath() : $node->getPath()));
}

Expand All @@ -138,7 +142,7 @@ private function writeNode(NodeInterface $node, NodeInterface $parentNode = null
$key = $prototypedArray ? '-' : $node->getName().':';
$text = rtrim(sprintf('%-21s%s %s', $key, $default, $comments), ' ');

if ($info = $node->getInfo()) {
if ($node instanceof BaseNode && $info = $node->getInfo()) {
$this->writeLine('');
// indenting multi-line info
$info = str_replace("\n", sprintf("\n%".($depth * 4).'s# ', ' '), $info);
Expand Down
Expand Up @@ -57,6 +57,7 @@ private function getConfigurationAsString()
node-with-a-looong-name=""
enum-with-default="this"
enum=""
custom-node="true"
>
<!-- some info -->
Expand Down
Expand Up @@ -137,6 +137,7 @@ enum: ~ # One of "this"; "that"
# Prototype
name: []
custom_node: true
EOL;
}
Expand Down
@@ -0,0 +1,49 @@
<?php


namespace Symfony\Component\Config\Tests\Fixtures\Configuration;

use Symfony\Component\Config\Definition\NodeInterface;

class CustomNode implements NodeInterface
{
public function getName()
{
return 'custom_node';
}

public function getPath()
{
return 'custom';
}

public function isRequired()
{
return false;
}

public function hasDefaultValue()
{
return true;
}

public function getDefaultValue()
{
return true;
}

public function normalize($value)
{
return $value;
}

public function merge($leftSide, $rightSide)
{
return array_merge($leftSide, $rightSide);
}

public function finalize($value)
{
return $value;
}
}
@@ -0,0 +1,14 @@
<?php


namespace Symfony\Component\Config\Tests\Fixtures\Configuration;

use Symfony\Component\Config\Definition\Builder\NodeDefinition;

class CustomNodeDefinition extends NodeDefinition
{
protected function createNode()
{
return new CustomNode();
}
}
Expand Up @@ -93,6 +93,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->end()
->end()
->append(new CustomNodeDefinition('acme'))
->end()
;

Expand Down

0 comments on commit bd90627

Please sign in to comment.