8000 [Config] Add `NodeDefinition::documentationUri()` · symfony/symfony@c7f73c8 · GitHub
[go: up one dir, main page]

Skip to content

Commit c7f73c8

Browse files
[Config] Add NodeDefinition::documentationUri()
1 parent ca6f399 commit c7f73c8

File tree

13 files changed

+90
-7
lines changed

13 files changed

+90
-7
lines changed

src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ public function getConfigTreeBuilder(): TreeBuilder
2626
$treeBuilder = new TreeBuilder('debug');
2727

2828
$rootNode = $treeBuilder->getRootNode();
29-
$rootNode->children()
29+
$rootNode
30+
->documentationUri('https://symfony.com/doc/{version:major}.{version:minor}/reference/configuration/debug.html', 'symfony/debug-bundle')
31+
->children()
3032
->integerNode('max_items')
3133
->info('Max number of displayed items past the first level, -1 means no limit.')
3234
->min(-1)

src/Symfony/Bundle/DebugBundle/composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@
1818
"require": {
1919
"php": ">=8.2",
2020
"ext-xml": "*",
21+
"composer-runtime-api": ">=2.1",
2122
"symfony/dependency-injection": "^6.4|^7.0",
2223
"symfony/http-kernel": "^6.4|^7.0",
2324
"symfony/twig-bridge": "^6.4|^7.0",
2425
"symfony/var-dumper": "^6.4|^7.0"
2526
},
2627
"require-dev": {
27-
"symfony/config": "^6.4|^7.0",
28+
"symfony/config": "^7.3",
2829
"symfony/web-profiler-bundle": "^6.4|^7.0"
2930
},
3031
"conflict": {

src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php

+19
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
104104
$io->title(
105105
\sprintf('Current configuration for %s', $name === $extensionAlias ? \sprintf('extension with alias "%s"', $extensionAlias) : \sprintf('"%s"', $name))
106106
);
107+
108+
$io->comment(\sprintf('Documentation at %s', $this->getDocumentationUrl($extension, $container)));
107109
}
108110

109111
$io->writeln($this->convertToFormat([$extensionAlias => $config], $format));
@@ -269,4 +271,21 @@ private fu 9E81 nction getAvailableFormatOptions(): array
269271
{
270272
return ['txt', 'yaml', 'json'];
271273
}
274+
275+
private function getDocumentationUrl(ExtensionInterface $extension, ContainerBuilder $container): ?string
276+
{
277+
$configuration = $extension instanceof ConfigurationInterface ?
278+
$extension :
279+
$extension->getConfiguration(
280+
$container->getExtensionConfig($extension->getAlias()),
281+
$container
282+
)
283+
;
284+
285+
return $configuration
286+
->getConfigTreeBuilder()
287+
->getRootNode()
288+
->getNode(true)
289+
->getAttribute('documentationUri');
290+
}
272291
}

src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php

+25
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Symfony\Component\Console\Input\InputOption;
2424
use Symfony\Component\Console\Output\OutputInterface;
2525
use Symfony\Component\Console\Style\SymfonyStyle;
26+
use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
2627
use Symfony\Component\Yaml\Yaml;
2728

2829
/**
@@ -123,6 +124,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
123124
$message .= \sprintf(' at path "%s"', $path);
124125
}
125126

127+
if ($documentationUri = $this->getExtensionDocumentationUri($extension)) {
128+
$message .= \sprintf(' (see %s)', $documentationUri);
129+
}
130+
126131
switch ($format) {
127132
case 'yaml':
128133
$io->writeln(\sprintf('# %s', $message));
@@ -182,4 +187,24 @@ private function getAvailableFormatOptions(): array
182187
{
183188
return ['yaml', 'xml'];
184189
}
190+
191+
private function getExtensionDocumentationUri(ConfigurationInterface|ConfigurationExtensionInterface $extension): ?string
192+
{
193+
$kernel = $this->getApplication()->getKernel();
194+
$container = $this->getContainerBuilder($kernel);
195+
196+
$configuration = $extension instanceof ConfigurationInterface ?
197+
$extension :
198+
$extension->getConfiguration(
199+
$container->getExtensionConfig($extension->getAlias()),
200+
$container
201+
)
202+
;
203+
204+
return $configuration
205+
->getConfigTreeBuilder()
206+
->getRootNode()
207+
->getNode(true)
208+
->getAttribute('documentationUri');
209+
}
185210
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public function getConfigTreeBuilder(): TreeBuilder
7575
$rootNode = $treeBuilder->getRootNode();
7676

7777
$rootNode
78+
->documentationUri('https://symfony.com/doc/{version:major}.{version:minor}/reference/configuration/framework.html', 'symfony/framework-bundle')
7879
->beforeNormalization()
7980
->ifTrue(fn ($v) => !isset($v['assets']) && isset($v['templating']) && class_exists(Package::class))
8081
->then(function ($v) {

src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public function getConfigTreeBuilder(): TreeBuilder
5555
$rootNode = $tb->getRootNode();
5656

5757
$rootNode
58+
->documentationUri('https://symfony.com/doc/{version:major}.{version:minor}/reference/configuration/security.html', 'symfony/security-bundle')
5859
->beforeNormalization()
5960
->always()
6061
->then(function ($v) {

src/Symfony/Bundle/SecurityBundle/composer.json

+1-src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php
+3-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ public function getConfigTreeBuilder(): TreeBuilder
3232
$treeBuilder = new TreeBuilder('twig');
3333
$rootNode = $treeBuilder->getRootNode();
3434

35-
$rootNode->beforeNormalization()
35+
$rootNode
36+
->documentationUri('https://symfony.com/doc/{version:major}.{version:minor}/reference/configuration/twig.html', 'symfony/twig-bundle')
37+
->beforeNormalization()
3638
->ifTrue(fn ($v) => \is_array($v) && \array_key_exists('exception_controller', $v))
3739
->then(function ($v) {
3840
if (isset($v['exception_controller'])) {

src/Symfony/Bundle/TwigBundle/composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"require": {
1919
"php": ">=8.2",
2020
"composer-runtime-api": ">=2.1",
21-
"symfony/config": "^6.4|^7.0",
21+
"symfony/config": "^7.3",
2222
"symfony/dependency-injection": "^6.4|^7.0",
< 1241 /code>
2323
"symfony/twig-bridge": "^6.4|^7.0",
2424
"symfony/http-foundation": "^6.4|^7.0",

src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Configuration.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ public function getConfigTreeBuilder(): TreeBuilder
3131
{
3232
$treeBuilder = new TreeBuilder('web_profiler');
3333

34-
$treeBuilder->getRootNode()
34+
$treeBuilder
35+
->getRootNode()
36+
->documentationUri('https://symfony.com/doc/{version:major}.{version:minor}/reference/configuration/web_profiler.html', 'symfony/web-profiler-bundle')
3537
->children()
3638
->arrayNode('toolbar')
3739
->info('Profiler toolbar configuration')

src/Symfony/Bundle/WebProfilerBundle/composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
],
1818
"require": {
1919
"php": ">=8.2",
20-
"symfony/config": "^6.4|^7.0",
20+
"composer-runtime-api": ">=2.1",
21+
"symfony/config": "^7.3",
2122
"symfony/framework-bundle": "^6.4|^7.0",
2223
"symfony/http-kernel": "^6.4|^7.0",
2324
"symfony/routing": "^6.4|^7.0",

src/Symfony/Component/Config/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Add `ExprBuilder::ifFalse()`
88
* Add support for info on `ArrayNodeDefinition::canBeEnabled()` and `ArrayNodeDefinition::canBeDisabled()`
9+
* Add `NodeDefinition::documentationUri()`
910

1011
7.2
1112
---

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

+28
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Config\Definition\Builder;
1313

14+
use Composer\InstalledVersions;
1415
use Symfony\Component\Config\Definition\BaseNode;
1516
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
1617
use Symfony\Component\Config\Definition\NodeInterface;
@@ -76,6 +77,33 @@ public function example(string|array $example): static
7677
return $this->attribute('example', $example);
7778
}
7879

80+
/**
81+
* Sets the documentation URI, as usually put in the "@see" tag of a doc block. This
82+
* can either be a URL or a file path. You can use the placeholders {package},
83+
* {version:major}, {version:minor}, and {version:patch} in the URI.
84+
*
85+
* @return $this
86+
*/
87+
public function documentationUri(string $uri, ?string $package = null): static
88+
{
89+
$installedVersion = [];
90+
if ($package) {
91+
try {
92+
preg_match('/\d+.\d+.\d+/', InstalledVersions::getVersion($package) ?? '', $m);
93+
$installedVersion = explode('.', $m[0] ?? '');
94+
} catch (\OutOfBoundsException) {
95+
// no-op
96+
}
97+
}
98+
99+
return $this->attribute('documentationUri', strtr($uri, [
100+
'{package}' => $package ?? '',
101+
'{version:major}' => $installedVersion[0] ?? '',
102+
'{version:minor}' => $installedVersion[1] ?? '',
103+
'{version:patch}' => $installedVersion[2] ?? '',
104+
]));
105+
}
106+
79107
/**
80108
* Sets an attribute on the node.
81109
*

0 commit comments

Comments
 (0)
0