Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ccfede1

Browse files
committed
[Config] Introduce NodeFinder to ease configuration tree manipulation for better reusability
- added class and methods docs - fixed code style - finalzed tests
1 parent cdaa4d6 commit ccfede1

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-0
lines changed

src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ public function __construct(?string $name, NodeParentInterface $parent = null)
4444
$this->name = $name;
4545
}
4646

47+
public function getName(): string
48+
{
49+
return $this->name;
50+
}
51+
4752
/**
4853
* Sets the parent node.
4954
*
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Config\Definition\Builder;
13+
14+
/**
15+
* This class finds nodes in a node tree.
16+
*
17+
* @author Jan Schädlich <[email protected]>
18+
*/
19+
class NodeFinder
20+
{
21+
/**
22+
* Finds a node defined by $nodePath within the given $rootNode.
23+
*
24+
* @param string $nodePath The path of the node to find. e.g "doctrine.orm.mappings"
25+
*/
26+
public function find(string $nodePath, NodeDefinition $rootNode): NodeDefinition
27+
{
28+
if (!$rootNode instanceof ArrayNodeDefinition) {
29+
if ($nodePath !== $rootNode->getName()) {
30+
throw new \RuntimeException(sprintf('Node with name "%s" does not exist in the given root node "%s"!', $nodePath, $rootNode->getName()));
31+
}
32+
33+
return $rootNode;
34+
}
35+
36+
$explodedNodePaths = explode('.', $nodePath);
37+
38+
if (!\array_key_exists($explodedNodePaths[0], $rootNode->getChildNodeDefinitions())) {
39+
throw new \RuntimeException(sprintf('Node with name "%s" does not exist in the given root node "%s"!', $explodedNodePaths[0], $rootNode->getName()));
40+
}
41+
42+
$node = $rootNode->getChildNodeDefinitions()[$explodedNodePaths[0]];
43+
44+
if (1 === \count($explodedNodePaths)) {
45+
return $node;
46+
}
47+
48+
array_shift($explodedNodePaths);
49+
50+
return $this->find(implode('.', $explodedNodePaths), $node);
51+
}
52+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Config\Tests\Definition\Builder;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
16+
use Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition;
17+
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
18+
use Symfony\Component\Config\Definition\Builder\NodeFinder;
19+
use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
20+
21+
/**
22+
* @author Jan Schädlich <[email protected]>
23+
*/
24+
class NodeFinderTest extends TestCase
25+
{
26+
public function testItShouldFindRootNode()
27+
{
28+
$rootNode = new ScalarNodeDefinition('root');
29+
30+
$nodeFinder = new NodeFinder();
31+
$foundNode = $nodeFinder->find('root', $rootNode);
32+
33+
$this->assertSame('root', $foundNode->getName());
34+
}
35+
36+
public function testItShouldThrowExceptionIfNodeDoesNotExistInScalarRootNode()
37+
{
38+
$this->expectException(\RuntimeException::class);
39+
$this->expectExceptionMessage('Node with name "child" does not exist in the given root node "root"!');
40+
41+
$rootNode = new ScalarNodeDefinition('root');
42+
43+
$nodeFinder = new NodeFinder();
44+
$nodeFinder->find('child', $rootNode);
45+
}
46+
47+
public function testItShouldThrowExceptionIfNodeDoesNotExistInArrayRootNode()
48+
{
49+
$this->expectException(\RuntimeException::class);
50+
$this->expectExceptionMessage('Node with name "child" does not exist in the given root node "root"!');
51+
52+
$rootNode = new ArrayNodeDefinition('root');
53+
$rootNode
54+
->children()
55+
->arrayNode('social_media_channels')->end()
56+
->end()
57+
;
58+
59+
$nodeFinder = new NodeFinder();
60+
$nodeFinder->find('child', $rootNode);
61+
}
62+
63+
public function testItShouldHandleComplexConfigurationProbably()
64+
{
65+
$rootNode = new ArrayNodeDefinition('root');
66+
$rootNode
67+
->children()
68+
->arrayNode('social_media_channels')
69+
->children()
70+
->booleanNode('enable')->end()
71+
->arrayNode('twitter')->end()
72+
->arrayNode('facebook')->end()
73+
->arrayNode('instagram')
74+
->children()
75+
->booleanNode('enable')->end()
76+
->arrayNode('accounts')->end()
77+
->end()
78+
->end()
79+
->end()
80+
->end()
81+
;
82+
83+
$nodeFinder = new NodeFinder();
84+
85+
$socialMediaChannelsNode = $nodeFinder->find('social_media_channels', $rootNode);
86+
$socialMediaChannelsEnableNode = $nodeFinder->find('social_media_channels.enable', $rootNode);
87+
88+
$twitterNode = $nodeFinder->find('social_media_channels.twitter', $rootNode);
89+
$facebookNode = $nodeFinder->find('social_media_channels.facebook', $rootNode);
90+
$instagramNode = $nodeFinder->find('social_media_channels.instagram', $rootNode);
91+
$instagramEnableNode = $nodeFinder->find('social_media_channels.instagram.enable', $rootNode);
92+
$instagramAccountsNode = $nodeFinder->find('social_media_channels.instagram.accounts', $rootNode);
93+
94+
$this->assertNode($socialMediaChannelsNode, 'social_media_channels', ArrayNodeDefinition::class);
95+
$this->assertNode($socialMediaChannelsEnableNode, 'enable', BooleanNodeDefinition::class);
96+
97+
$this->assertNode($twitterNode, 'twitter', ArrayNodeDefinition::class);
98+
$this->assertNode($facebookNode, 'facebook', ArrayNodeDefinition::class);
99+
$this->assertNode($instagramNode, 'instagram', ArrayNodeDefinition::class);
100+
$this->assertNode($instagramEnableNode, 'enable', BooleanNodeDefinition::class);
101+
$this->assertNode($instagramAccountsNode, 'accounts', ArrayNodeDefinition::class);
102+
}
103+
104+
private function assertNode(NodeDefinition $actualNode, string $expectedName, string $expectedType): void
105+
{
106+
$this->assertSame($expectedName, $actualNode->getName());
107+
$this->assertInstanceOf($expectedType, $actualNode);
108+
}
109+
}

0 commit comments

Comments
 (0)