diff --git a/src/AwsBundle/Client/AwsSdks.php b/src/AwsBundle/Client/AwsSdks.php new file mode 100644 index 0000000..80665a9 --- /dev/null +++ b/src/AwsBundle/Client/AwsSdks.php @@ -0,0 +1,30 @@ +container = $container; + $this->defaultName = $defaultName; + } + + public function has(string $name): bool + { + return $this->container->has($name); + } + + public function get(?string $name = null): Sdk + { + return $this->container->get($name ?? $this->defaultName); + } +} diff --git a/src/AwsBundle/DependencyInjection/Configuration.php b/src/AwsBundle/DependencyInjection/Configuration.php index 2ccb3ef..3b85573 100644 --- a/src/AwsBundle/DependencyInjection/Configuration.php +++ b/src/AwsBundle/DependencyInjection/Configuration.php @@ -19,13 +19,48 @@ public function getConfigTreeBuilder() // @formatter:off return (new TreeBuilder()) ->root('ruwork_aws') + ->beforeNormalization() + ->ifTrue(function ($value): bool { + return \is_array($value) && [] !== $value && !\array_key_exists('sdks', $value); + }) + ->then(function (array $value): array { + return [ + 'sdks' => [ + 'default' => $value, + ], + 'default_sdk' => 'default', + ]; + }) + ->end() ->children() - ->scalarNode('http_handler') - ->defaultValue(\interface_exists(HttpClient::class) ? HttplugHandler::class : null) + ->arrayNode('sdks') + ->isRequired() + ->arrayPrototype() + ->children() + ->scalarNode('http_handler') + ->defaultValue(\interface_exists(HttpClient::class) ? HttplugHandler::class : null) + ->end() + ->end() + ->ignoreExtraKeys(false) + ->end() + ->end() + ->scalarNode('default_sdk') + ->isRequired() + ->cannotBeEmpty() ->end() ->end() - ->ignoreExtraKeys(false) - ->end(); + ->validate() + ->ifTrue(function ($value): bool { + return \is_array($value) + && isset($value['default_sdk']) + && isset($value['sdks']) + && !isset($value['sdks'][$value['default_sdk']]); + }) + ->then(function (array $value): void { + throw new \InvalidArgumentException(\sprintf('SDK "%s" is not defined and cannot be used as default.', $value['default_sdk'])); + }) + ->end() + ->end(); // @formatter:on } } diff --git a/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php b/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php index c03fd0d..5254cb2 100644 --- a/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php +++ b/src/AwsBundle/DependencyInjection/RuworkAwsExtension.php @@ -6,9 +6,13 @@ use Aws\Sdk; use Http\Client\HttpClient; +use Ruwork\AwsBundle\Client\AwsSdks; use Ruwork\AwsBundle\HttpHandler\HttplugHandler; use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension; @@ -24,16 +28,41 @@ public function loadInternal(array $config, ContainerBuilder $container): void $loader = new PhpFileLoader($container, $locator); $loader->load('services.php'); - if (isset($config['http_handler'])) { - $config['http_handler'] = new Reference($config['http_handler']); - } + if (\class_exists(Sdk::class)) { + $references = []; + foreach ($config['sdks'] as $name => $value) { + if (isset($value['http_handler'])) { + $value['http_handler'] = new Reference($value['http_handler']); + } + $references[$name] = $this->registerSdk($container, $name, $value); + } - $container - ->findDefinition(Sdk::class) - ->setArgument(0, $config); + $sdkAlias = new Alias('ruwork_aws.sdk.'.$config['default_sdk'], false); + $container->setAlias(Sdk::class, $sdkAlias); + $container->setAlias('ruwork_aws.sdk._default', $sdkAlias); + + $container + ->findDefinition(AwsSdks::class) + ->setArguments([ + '$container' => ServiceLocatorTagPass::register($container, $references), + '$defaultName' => $config['default_sdk'], + ]); + } if (!\interface_exists(HttpClient::class)) { $container->removeDefinition(HttplugHandler::class); } } + + public function registerSdk(ContainerBuilder $container, string $name, array $config): Reference + { + $id = 'ruwork_aws.sdk.'.$name; + + $container + ->setDefinition($id, new Definition(Sdk::class)) + ->setPublic(false) + ->setArgument(0, $config); + + return new Reference($id); + } } diff --git a/src/AwsBundle/Resources/config/services.php b/src/AwsBundle/Resources/config/services.php index 0d4c479..0a88f5b 100644 --- a/src/AwsBundle/Resources/config/services.php +++ b/src/AwsBundle/Resources/config/services.php @@ -6,6 +6,7 @@ use Aws\Sdk; use Aws\Ses\SesClient; +use Ruwork\AwsBundle\Client\AwsSdks; use Ruwork\AwsBundle\HttpHandler\HttplugHandler; return function (ContainerConfigurator $container): void { @@ -23,6 +24,10 @@ ->set(SesClient::class) ->factory([ref(Sdk::class), 'createSes']); + // Sdks + + $services->set(AwsSdks::class); + // HttpHandler $services diff --git a/tests/AwsBundle/DependencyInjection/ConfigurationTest.php b/tests/AwsBundle/DependencyInjection/ConfigurationTest.php index 1189005..7d7c967 100644 --- a/tests/AwsBundle/DependencyInjection/ConfigurationTest.php +++ b/tests/AwsBundle/DependencyInjection/ConfigurationTest.php @@ -15,24 +15,41 @@ class ConfigurationTest extends TestCase { use ConfigurationTestCaseTrait; - public function testDefault(): void + public function testDefaults(): void { - $this->assertProcessedConfigurationEquals([], [ - 'http_handler' => HttplugHandler::class, - ]); + $this->assertProcessedConfigurationEquals( + [ + 'sdks' => [ + 'extra_value' => 'value', + ], + ], + [ + 'sdks' => [ + 'default' => [ + 'http_handler' => HttplugHandler::class, + 'extra_value' => 'value', + ], + ], + 'default_sdk' => 'default', + ] + ); } - public function testExtraValues(): void + public function testSingleSdkExpanding(): void { $this->assertProcessedConfigurationEquals( [ - [ - 'extra' => 'value', + 'sdks' => [ + 'http_handler' => HttplugHandler::class, ], ], [ - 'extra' => 'value', - 'http_handler' => HttplugHandler::class, + 'sdks' => [ + 'default' => [ + 'http_handler' => HttplugHandler::class, + ], + ], + 'default_sdk' => 'default', ] ); }