8000 Added tests and ConfigBuilderInterface · symfony/symfony@e274178 · GitHub
[go: up one dir, main page]

Skip to content

Commit e274178

Browse files
committed
Added tests and ConfigBuilderInterface
1 parent 5ec7d70 commit e274178

File tree

11 files changed

+131
-17
lines changed

11 files changed

+131
-17
lines changed

src/Symfony/Component/Config/Builder/ClassBuilder.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class ClassBuilder
3434
/** @var Method[] */
3535
private $methods = [];
3636
private $require = [];
37+
private $implements = [];
3738

3839
public function __construct(string $namespace, string $name)
3940
{
@@ -73,6 +74,7 @@ public function build(): string
7374
$require .= strtr('require_once __DIR__.\'FILE\';', ['FILE' => \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $path)]).\PHP_EOL;
7475
}
7576

77+
$implements = [] === $this->implements ? '' : 'implements ' . implode(', ', $this->implements);
7678
$body = '';
7779
foreach ($this->properties as $property) {
7880
$body .= self::INDENTATION.$property->getContent().\PHP_EOL;
@@ -95,11 +97,11 @@ public function build(): string
9597
*
9698
* @experimental in 5.3
9799
*/
98-
class CLASS
100+
class CLASS IMPLEMENTS
99101
{
100102
BODY
101103
}
102-
', ['NAMESPACE' => $this->namespace, 'REQUIRE' => $require, 'CLASS' => $this->getName(), 'BODY' => $body]);
104+
', ['NAMESPACE' => $this->namespace, 'REQUIRE' => $require, 'CLASS' => $this->getName(), 'IMPLEMENTS' => $implements, 'BODY' => $body]);
103105

104106
return $content;
105107
}
@@ -109,6 +111,11 @@ public function addRequire(self $class)
109111
$this->require[] = $class;
110112
}
111113

114+
public function addImplements(string $interface)
115+
{
116+
$this->implements[] = '\\'.ltrim($interface, '\\');
117+
}
118+
112119
public function addMethod(string $name, string $body, array $params = []): void
113120
{
114121
$this->methods[] = new Method(strtr($body, ['NAME' => $this->camelCase($name)] + $params));
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
4+
namespace Symfony\Component\Config\Builder;
5+
6+
/**
7+
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
8+
*
9+
* @experimental in 5.3
10+
*/
11+
interface ConfigBuilderInterface
12+
{
13+
/**
14+
* Get all configuration represented as an array.
15+
*/
16+
public function toArray(): array;
17+
18+
/**
19+
* Get the alias for the extension which config we are building.
20+
*/
21+
public function getExtensionAlias(): string;
22+
}

src/Symfony/Component/Config/Builder/ConfigGenerator.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public function build(ConfigurationInterface $configuration, string $outputDir):
4040

4141
$rootNode = $configuration->getConfigTreeBuilder()->buildTree();
4242
$rootClass = new ClassBuilder('Symfony\\Config\\'.$rootNode->getPath(), $rootNode->getName());
43+
$rootClass->addImplements(ConfigBuilderInterface::class);
4344
$this->classes[] = $rootClass;
4445

4546
$this->buildNode($rootNode, $rootClass, $rootClass->getNamespace());

src/Symfony/Component/Config/Tests/Builder/GeneratedConfigTest.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Symfony\Component\Config\Tests\Builder;
44

55
use PHPUnit\Framework\TestCase;
6+
use Symfony\Component\Config\Builder\ConfigBuilderInterface;
67
use Symfony\Component\Config\Builder\ConfigGenerator;
78

89
/**
@@ -36,15 +37,16 @@ public function testConfig(string $name, string $alias)
3637

3738
$outputDir = sys_get_temp_dir();
3839
// This line is helpful for debugging
39-
$outputDir = __DIR__.'/.build';
40+
// $outputDir = __DIR__.'/.build';
4041

4142
$loader = (new ConfigGenerator())->build(new $configuration(), $outputDir);
42-
$configObject = $loader();
43+
$configBuilder = $loader();
4344
$callback = include $basePath.$name.'.config.php';
4445
$expectedOutput = include $basePath.$name.'.output.php';
45-
$callback($configObject);
46+
$callback($configBuilder);
4647

47-
$this->assertSame($alias, $configObject->getExtensionAlias());
48-
$this->assertSame($expectedOutput, $configObject->toArray());
48+
$this->assertInstanceOf(ConfigBuilderInterface::class, $configBuilder);
49+
$this->assertSame($alias, $configBuilder->getExtensionAlias());
50+
$this->assertSame($expectedOutput, $configBuilder->toArray());
4951
}
5052
}

src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
1313

14+
use Symfony\Component\Config\Builder\ConfigBuilderInterface;
1415
use Symfony\Component\Config\Builder\ConfigGenerator;
1516
use Symfony\Component\Config\Builder\GeneratorInterface;
1617
use Symfony\Component\DependencyInjection\Argument\AbstractArgument;
@@ -69,8 +70,8 @@ final public function extensionBuilder(string $namespace)
6970
throw new \LogicException('You cannot use the config builder as the Config component is not installed. Try running "composer require symfony/config".');
7071
}
7172

72-
if (class_exists($namespace) && method_exists($namespace, 'getExtensionAlias')) {
73-
$namespace = \call_user_func([$namespace, 'getExtensionAlias']);
73+
if (class_exists($namespace) && is_subclass_of($namespace, ConfigBuilderInterface::class)) {
74+
return new $namespace();
7475
} elseif ('Symfony\\Config\\' === substr($namespace, 0, 15)) {
7576
$namespace = Container::underscore(substr($namespace, 15, strpos($namespace, '\\', 15) - 15));
7677
}

src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Loader;
1313

14+
use Symfony\Component\Config\Builder\ConfigBuilderInterface;
1415
use Symfony\Component\DependencyInjection\Container;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
1617
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -81,7 +82,7 @@ private function executeCallback(callable $callback, ContainerConfigurator $cont
8182
}
8283

8384
$arguments = [];
84-
$configClasses = [];
85+
$configBuilders = [];
8586
$parameters = ($reflector ?? new \ReflectionFunction($callback))->getParameters();
8687
foreach ($parameters as $parameter) {
8788
$reflectionType = $parameter->getType();
@@ -105,19 +106,20 @@ private function executeCallback(callable $callback, ContainerConfigurator $cont
105106
$arguments[] = $this;
106107
break;
107108
default:
108-
if ('Config' === !substr($type, -6)) {
109+
if (!is_subclass_of($type, ConfigBuilderInterface::class)) {
109110
throw new \InvalidArgumentException(sprintf('Could not resolve argument "%s" for "%s".', $type.' '.$parameter->getName(), $path));
110111
}
111-
$configClass = $containerConfigurator->extensionBuilder($type);
112-
$configClasses[] = $configClass;
113-
$arguments[] = $configClass;
112+
$configBuilder = $containerConfigurator->extensionBuilder($type);
113+
$configBuilders[] = $configBuilder;
114+
$arguments[] = $configBuilder;
114115
}
115116
}
116117

117118
$callback(...$arguments);
118119

119-
foreach ($configClasses as $configClass) {
120-
$containerConfigurator->extension($configClass->getExtensionAlias(), $configClass->toArray());
120+
/** @var ConfigBuilderInterface $configBuilder */
121+
foreach ($configBuilders as $configBuilder) {
122+
$containerConfigurator->extension($configBuilder->getExtensionAlias(), $configBuilder->toArray());
121123
}
122124
}
123125
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
4+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
5+
6+
7+
use Symfony\Component\Config\Builder\ConfigBuilderInterface;
8+
9+
class AcmeConfigBuilder implements ConfigBuilderInterface
10+
{
11+
private $color;
12+
13+
public function color($value)
14+
{
15+
$this->color = $value;
16+
}
17+
18+
public function toArray(): array
19+
{
20+
return [
21+
'color' => $this->color
22+
];
23+
}
24+
25+
public function getExtensionAlias(): string
26+
{
27+
return 'acme';
28+
}
29+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
parameters:
2+
acme.configs: [{ color: blue }]
3+
4+
services:
5+
service_container:
6+
class: Symfony\Component\DependencyInjection\ContainerInterface
< 10000 /code>7+
public: true
8+
synthetic: true
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Tests\Fixtures\AcmeConfigBuilder;
4+
5+
return static function (AcmeConfigBuilder $config) {
6+
$config->color('blue');
7+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\ContainerBuilder;
4+
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
5+
6+
class AcmeExtension implements ExtensionInterface
7+
{
8+
public function load(array $configs, ContainerBuilder $configuration)
9+
{
10+
$configuration->setParameter('acme.configs', $configs);
11+
12+
return $configuration;
13+
}
14+
15+
public function getXsdValidationBasePath()
16+
{
17+
return false;
18+
}
19+
20+
public function getNamespace(): string
21+
{
22+
return 'http://www.example.com/schema/acme';
23+
}
24+
25+
public function getAlias(): string
26+
{
27+
return 'acme';
28+
}
29+
}

src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Tests\Loader;
1313

14+
require_once __DIR__.'/../Fixtures/includes/AcmeExtension.php';
15+
1416
use PHPUnit\Framework\TestCase;
1517
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
1618
use Symfony\Component\Config\FileLocator;
1719
use Symfony\Component\DependencyInjection\ContainerBuilder;
1820
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
1921
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
2022
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
23+
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
2124
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
2225

2326
class PhpFileLoaderTest extends TestCase
@@ -60,7 +63,9 @@ public function testConfigServices()
6063
public function testConfig($file)
6164
{
6265
$fixtures = realpath(__DIR__.'/../Fixtures');
63-
$loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator());
66+
$container = new ContainerBuilder();
67+
$container->registerExtension(new \AcmeExtension());
68+
$loader = new PhpFileLoader($container, new FileLocator());
6469
$loader->load($fixtures.'/config/'.$file.'.php');
6570

6671
$container->compile();
@@ -82,6 +87,7 @@ public function provideConfig()
8287
yield ['anonymous'];
8388
yield ['lazy_fqcn'];
8489
yield ['remove'];
90+
yield 'config_builder'=>['config_builder'];
8591
}
8692

8793
public function testAutoConfigureAndChildDefinition()

0 commit comments

Comments
 (0)
0