Skip to content

Commit

Permalink
feature #20689 [Config][FrameworkBundle] Allow to dump extension conf…
Browse files Browse the repository at this point in the history
…ig reference sub-path (ogizanagi)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[Config][FrameworkBundle] Allow to dump extension config reference sub-path

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

Same as #18940 but for the `config:dump-reference` command:

<img width="975" alt="screenshot 2016-11-29 a 19 09 04" src="https://cloud.githubusercontent.com/assets/2211145/20722577/6c9f9b98-b667-11e6-9683-9a304ff80895.PNG">

Only available for yaml, because it's the most common format when developing an end-application, and dumping a sub xml document causes some issues and raises more questions with the current `XmlReferenceDumper` implementation (namespaces, root name, ...).

Commits
-------

869bb15 [Config][FrameworkBundle] Allow to dump extension config reference sub path
  • Loading branch information
fabpot committed Jan 10, 2017
2 parents 16d33e1 + 869bb15 commit 629de96
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 4 deletions.
Expand Up @@ -37,6 +37,7 @@ protected function configure()
->setName('config:dump-reference')
->setDefinition(array(
new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'),
new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (yaml or xml)', 'yaml'),
))
->setDescription('Dumps the default configuration for an extension')
Expand All @@ -54,6 +55,10 @@ protected function configure()
When the option is not provided, <comment>yaml</comment> is used.
<info>php %command.full_name% FrameworkBundle --format=xml</info>
For dumping a specific option, add its path as second argument (only available for the yaml format):
<info>php %command.full_name% framework profiler.matcher</info>
EOF
)
Expand All @@ -71,7 +76,10 @@ protected function execute(InputInterface $input, OutputInterface $output)

if (null === $name = $input->getArgument('name')) {
$this->listBundles($io);
$io->comment('Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. <comment>config:dump-reference FrameworkBundle</comment>)');
$io->comment(array(
'Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. <comment>config:dump-reference FrameworkBundle</comment>)',
'For dumping a specific option, add its path as the second argument of this command. (e.g. <comment>config:dump-reference FrameworkBundle profiler.matcher</comment> to dump the <comment>framework.profiler.matcher</comment> configuration)',
));

return;
}
Expand All @@ -82,13 +90,26 @@ protected function execute(InputInterface $input, OutputInterface $output)

$this->validateConfiguration($extension, $configuration);

$format = $input->getOption('format');
$path = $input->getArgument('path');

if ($path !== null && 'yaml' !== $format) {
$io->error('The "path" option is only available for the "yaml" format.');

return 1;
}

if ($name === $extension->getAlias()) {
$message = sprintf('Default configuration for extension with alias: "%s"', $name);
} else {
$message = sprintf('Default configuration for "%s"', $name);
}

switch ($input->getOption('format')) {
if ($path !== null) {
$message .= sprintf(' at path "%s"', $path);
}

switch ($format) {
case 'yaml':
$io->writeln(sprintf('# %s', $message));
$dumper = new YamlReferenceDumper();
Expand All @@ -102,6 +123,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
throw new \InvalidArgumentException('Only the yaml and xml formats are supported.');
}

$io->writeln($dumper->dump($configuration, $extension->getNamespace()));
$io->writeln(null === $path ? $dumper->dump($configuration, $extension->getNamespace()) : $dumper->dumpAtPath($configuration, $path));
}
}
Expand Up @@ -18,6 +18,13 @@ public function addConfiguration($rootNode)
$rootNode
->children()
->scalarNode('custom')->end()
->arrayNode('array')
->children()
->scalarNode('child1')->end()
->scalarNode('child2')->end()
->end()
->end()
->end()
->end()
;
}
Expand Down
Expand Up @@ -40,6 +40,39 @@ public function testDumpBundleName()
$this->assertContains(' custom:', $tester->getDisplay());
}

public function testDumpAtPath()
{
$tester = $this->createCommandTester();
$ret = $tester->execute(array(
'name' => 'test',
'path' => 'array',
));

$this->assertSame(0, $ret, 'Returns 0 in case of success');
$this->assertSame(<<<'EOL'
# Default configuration for extension with alias: "test" at path "array"
array:
child1: ~
child2: ~
EOL
, $tester->getDisplay(true));
}

public function testDumpAtPathXml()
{
$tester = $this->createCommandTester();
$ret = $tester->execute(array(
'name' => 'test',
'path' => 'array',
'--format' => 'xml',
));

$this->assertSame(1, $ret);
$this->assertContains('[ERROR] The "path" option is only available for the "yaml" format.', $tester->getDisplay());
}

/**
* @return CommandTester
*/
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Bundle/FrameworkBundle/composer.json
Expand Up @@ -20,7 +20,7 @@
"symfony/cache": "~3.3",
"symfony/class-loader": "~3.2",
"symfony/dependency-injection": "~3.3",
"symfony/config": "~2.8|~3.0",
"symfony/config": "~3.3",
"symfony/event-dispatcher": "~2.8|~3.0",
"symfony/http-foundation": "~3.1",
"symfony/http-kernel": "~3.3",
Expand Down
Expand Up @@ -33,6 +33,32 @@ public function dump(ConfigurationInterface $configuration)
return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree());
}

public function dumpAtPath(ConfigurationInterface $configuration, $path)
{
$rootNode = $node = $configuration->getConfigTreeBuilder()->buildTree();

foreach (explode('.', $path) as $step) {
if (!$node instanceof ArrayNode) {
throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s"', $rootNode->getName(), $path));
}

/** @var NodeInterface[] $children */
$children = $node instanceof PrototypedArrayNode ? $this->getPrototypeChildren($node) : $node->getChildren();

foreach ($children as $child) {
if ($child->getName() === $step) {
$node = $child;

continue 2;
}
}

throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s"', $rootNode->getName(), $path));
}

return $this->dumpNode($node);
}

public function dumpNode(NodeInterface $node)
{
$this->reference = '';
Expand Down
Expand Up @@ -25,6 +25,61 @@ public function testDumper()
$this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration));
}

public function provideDumpAtPath()
{
return array(
'Regular node' => array('scalar_true', <<<EOL
scalar_true: true
EOL
),
'Array node' => array('array', <<<EOL
# some info
array:
child1: ~
child2: ~
# this is a long
# multi-line info text
# which should be indented
child3: ~ # Example: example setting
EOL
),
'Regular nested' => array('array.child2', <<<EOL
child2: ~
EOL
),
'Prototype' => array('cms_pages.page', <<<EOL
# Prototype
page:
# Prototype
locale:
title: ~ # Required
path: ~ # Required
EOL
),
'Nested prototype' => array('cms_pages.page.locale', <<<EOL
# Prototype
locale:
title: ~ # Required
path: ~ # Required
EOL
),
);
}

/**
* @dataProvider provideDumpAtPath
*/
public function testDumpAtPath($path, $expected)
{
$configuration = new ExampleConfiguration();

$dumper = new YamlReferenceDumper();

$this->assertSame(trim($expected), trim($dumper->dumpAtPath($configuration, $path)));
}

private function getConfigurationAsString()
{
return <<<'EOL'
Expand Down

0 comments on commit 629de96

Please sign in to comment.