diff --git a/Builder/ClientBuilder.php b/Builder/ClientBuilder.php new file mode 100644 index 0000000..dce1d2f --- /dev/null +++ b/Builder/ClientBuilder.php @@ -0,0 +1,80 @@ +clientClass = $clientClass; + $this->descriptionClass = $descriptionClass; + $this->dispatcher = $dispatcher; + $this->inspector = $inspector; + $this->commands = $commands; + $this->config = $config; + } + + /** + * Create client instance + * + * @param string $clientId Client id, needed for commands association + * @param string $baseUrl Base url + * @param string $username User name + * @param string $password Password + * @param array $config Other config options, optional + * + * @return Client + */ + public function factory($clientId, $baseUrl, $username, $password, array $config = array()) + { + /** @var $client Client */ + $client = new $this->clientClass($baseUrl, array_merge($this->config, $config, array( + 'username' => $username, + 'password' => $password + ))); + $client->setEventDispatcher($this->dispatcher); + $client->setInspector($this->inspector); + + /** @var $serviceDescription ServiceDescription */ + $commands = $this->commands[$clientId]; + + $serviceDescription = new $this->descriptionClass($commands); + $client->setDescription($serviceDescription); + + return $client; + } +} diff --git a/Builder/CommandBuilder.php b/Builder/CommandBuilder.php new file mode 100644 index 0000000..ba06002 --- /dev/null +++ b/Builder/CommandBuilder.php @@ -0,0 +1,50 @@ +toArray(); + $resolvedParams = array_merge($resolvedParams, $toArray['params']); + $command = array_merge($toArray, $command); + } + + $params = array_merge($resolvedParams, $params); + } + + return new ApiCommand(array_merge($command, array( + 'params' => $params, + 'class' => $class ? str_replace('.', '\\', $class) : $this->defaultClass, + ))); + } +} diff --git a/Builder/TypeBuilder.php b/Builder/TypeBuilder.php new file mode 100644 index 0000000..2f27c57 --- /dev/null +++ b/Builder/TypeBuilder.php @@ -0,0 +1,15 @@ +inspector = $inspector; + + return $inspector; + } + /** + * {@inheritDoc} + */ + public function getCommand($name, array $args = array()) + { + $command = parent::getCommand($name, $args); + /** @var $command AbstractCommand */ + $command->setInspector($this->inspector); + + return $command; + } +} diff --git a/DdeboerGuzzleBundle.php b/DdeboerGuzzleBundle.php index 95f381f..bd877c3 100644 --- a/DdeboerGuzzleBundle.php +++ b/DdeboerGuzzleBundle.php @@ -12,7 +12,21 @@ namespace Ddeboer\GuzzleBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; + +use Ddeboer\GuzzleBundle\DependencyInjection\Compiler\GrabCommandsPass; + class DdeboerGuzzleBundle extends Bundle { + /** + * {@inheritdoc} + */ + public function build(ContainerBuilder $container) + { + parent::build($container); + + $container->addCompilerPass(new GrabCommandsPass()); + } } diff --git a/DependencyInjection/CommandConfiguration.php b/DependencyInjection/CommandConfiguration.php new file mode 100644 index 0000000..f4a31e9 --- /dev/null +++ b/DependencyInjection/CommandConfiguration.php @@ -0,0 +1,54 @@ +root('guzzle') + ->children() + ->arrayNode('clients') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->scalarNode('name')->end() + ->arrayNode('commands') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->scalarNode('name')->end() + ->scalarNode('method')->defaultValue('GET')->end() + ->scalarNode('uri')->end() + ->scalarNode('class')->end() + ->scalarNode('extends')->end() + ->scalarNode('doc')->end() + ->arrayNode('params') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->scalarNode('doc')->end() + ->scalarNode('name')->end() + ->scalarNode('type')->end() + ->booleanNode('required')->defaultValue(false)->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end(); + + return $builder; + } +} diff --git a/DependencyInjection/Compiler/GrabCommandsPass.php b/DependencyInjection/Compiler/GrabCommandsPass.php new file mode 100644 index 0000000..87a297b --- /dev/null +++ b/DependencyInjection/Compiler/GrabCommandsPass.php @@ -0,0 +1,53 @@ +getDefinition('guzzle.inspector'); + + foreach ($definitions as $name => $definition) { + $properties = $definition->getProperties(); + $inspector->addMethodCall('setConstraint', array( + $name, + $definition, + $properties + )); + } + + $definitionGroups = Util::getDefinitionsByTag('guzzle_command', $container, true); + + $result = array(); + foreach ($definitionGroups as $clientId => $definitions) { + foreach ($definitions as $definition) { + $args = $definition->getArguments(); + $result[$clientId][$args['name']] = $definition; + } + } + + $container->getDefinition('guzzle.client_builder')->replaceArgument(4, $result); + } +} diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 56c43f2..8e3ed5b 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -34,6 +34,22 @@ public function getConfigTreeBuilder() ->scalarNode('configuration_file') ->defaultValue('%kernel.root_dir%/config/webservices.xml') ->end() + ->arrayNode('configuration') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->scalarNode('name')->end() + ->scalarNode('method')->defaultValue('GET')->end() + ->scalarNode('uri')->end() + ->scalarNode('class')->end() + ->scalarNode('extends')->end() + ->arrayNode('params') + ->useAttributeAsKey('params')->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->end() ->end() ->booleanNode('logging')->defaultValue($this->debug)->end() diff --git a/DependencyInjection/DdeboerGuzzleExtension.php b/DependencyInjection/DdeboerGuzzleExtension.php index d8b0279..8736799 100644 --- a/DependencyInjection/DdeboerGuzzleExtension.php +++ b/DependencyInjection/DdeboerGuzzleExtension.php @@ -18,13 +18,25 @@ public function load(array $configs, ContainerBuilder $container) new FileLocator(__DIR__.'/../Resources/config') ); $loader->load('services.xml'); + $loader->load('validators.xml'); $processor = new Processor(); $configuration = new Configuration($container->getParameter('kernel.debug')); $config = $processor->processConfiguration($configuration, $configs); - $container->setParameter('guzzle.service_builder.configuration_file', - $config['service_builder']['configuration_file']); + if (isset($config['service_builder'])) { + $container->setParameter('guzzle.service_builder.configuration', + $config['service_builder']['configuration']); + + if (empty($config['service_builder']['configuration'])) { + $container->setParameter('guzzle.service_builder.configuration', + $config['service_builder']['configuration_file']); + } + } + + $clients = isset($config['clients']) ? $config['clients'] : array(); + + $container->setParameter('guzzle.clients', $clients); if ($config['logging']) { $container->findDefinition('guzzle.data_collector') diff --git a/Inspector.php b/Inspector.php new file mode 100644 index 0000000..4f51dde --- /dev/null +++ b/Inspector.php @@ -0,0 +1,88 @@ +constraints[$name] = $constraint; + $this->constraintArgs[$name] = $args; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function getConstraint($name) + { + if (!isset($this->constraints[$name])) { + throw new InvalidArgumentException($name . ' has not been registered'); + } + + return $this->constraints[$name]; + } + + /** + * {@inheritDoc} + */ + public function validateConstraint($name, $value, array $args = null) + { + if (!$args) { + $args = isset($this->constraintArgs[$name]) ? $this->constraintArgs[$name] : array(); + } + + return $this->getConstraint($name)->validate($value, $args); + } +} diff --git a/README.md b/README.md index e6a667e..850badd 100644 --- a/README.md +++ b/README.md @@ -85,9 +85,33 @@ public function registerBundles() ``` yaml # app/config/config.yml -ddeboer_guzzle: +ddeboer_guzzle: service_builder: - configuration_file: "%kernel.root_dir%/config/webservices.xml" + configuration: + aws: + params: + access_key: 12345 + secret_key: abcd + s3: + class: Guzzle\Aws\S3\S3Client + extends: aws + params: + subdomain: michael + unfuddle: + class: Guzzle\Unfuddle\UnfuddleClient + params: + username: test-user + password: test-password + subdomain: test +``` + +Or + +``` yaml +# app/config/config.yml +ddeboer_guzzle: + service_builder: + configuration_file: %kernel.root_dir%/config/webservices.xml ``` And add a Guzzle services configuration file. See the [Guzzle documentation](http://guzzlephp.org/tour/using_services.html#instantiating-web-service-clients-using-a-servicebuilder). diff --git a/Resources/config/services.xml b/Resources/config/services.xml index c7b931d..4223c78 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -7,6 +7,18 @@ Guzzle\Service\Builder\ServiceBuilder Guzzle\Service\Builder\ServiceBuilder + Guzzle\Service\Description\ServiceDescription + + + Ddeboer\GuzzleBundle\Client + Ddeboer\GuzzleBundle\Builder\ClientBuilder + + + + Guzzle\Service\Description\ApiCommand + Ddeboer\GuzzleBundle\Builder\CommandBuilder + + Ddeboer\GuzzleBundle\Inspector Guzzle\Service\Plugin\PluginCollectionPlugin Ddeboer\GuzzleBundle\Guzzle\Http\Plugin\DataCollectorPlugin @@ -23,8 +35,25 @@ + + + + + + %guzzle.client.class% + %guzzle.service_description.class% + + + %guzzle.clients% + %guzzle.client_builder.config% + + + + + + - %guzzle.service_builder.configuration_file% + %guzzle.service_builder.configuration% diff --git a/Resources/config/validators.xml b/Resources/config/validators.xml new file mode 100644 index 0000000..4e1f41d --- /dev/null +++ b/Resources/config/validators.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + string + + + + + file + + + + + array + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + string + + + + + string + + + + + string + + + + diff --git a/composer.json b/composer.json index 8e83851..64ef27e 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,8 @@ "require": { "php": ">=5.3.2", "symfony/symfony": ">=2.0,<2.2", - "guzzle/guzzle": "*" + "guzzle/guzzle": "*", + "zerkalica/millwright-configuration-bundle": "dev-master" }, "autoload": {