Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ The change log describes what is "Added", "Removed", "Changed" or "Fixed" betwee

# Version 2

# 2.1.0

- Added PluginConfigurator

# 2.0.0 - 2024-09-16

- Increased min PHP version to 8.1
Expand Down
16 changes: 16 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,22 @@ private function createClientPluginNode(): ArrayNodeDefinition
->end()
->end()
->end()
->arrayNode('configurator')
->canBeEnabled()
->info('Configure a plugin with a configurator')
->children()
->scalarNode('id')
->info('Service id of a plugin configurator')
->isRequired()
->cannotBeEmpty()
->end()
->arrayNode('config')
->normalizeKeys(false)
->prototype('variable')
->end()
->end()
->end()
->end()
->arrayNode('add_host')
->canBeEnabled()
->addDefaultsIfNotSet()
Expand Down
40 changes: 30 additions & 10 deletions src/DependencyInjection/HttplugExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Http\Client\HttpAsyncClient;
use Http\Client\Plugin\Vcr\RecordPlugin;
use Http\Client\Plugin\Vcr\ReplayPlugin;
use Http\HttplugBundle\PluginConfigurator;
use Http\Message\Authentication\BasicAuth;
use Http\Message\Authentication\Bearer;
use Http\Message\Authentication\Header;
Expand Down Expand Up @@ -427,17 +428,41 @@ private function configureClient(ContainerBuilder $container, string $clientName

switch ($pluginName) {
case 'reference':
$plugins[] = $pluginConfig['id'];
$plugins[] = new Reference($pluginConfig['id']);
break;
case 'configurator':
if (!is_a($pluginConfig['id'], PluginConfigurator::class, true)) {
throw new \LogicException(sprintf('The plugin "%s" is not a valid PluginConfigurator.', $pluginConfig['id']));
}

$config = $pluginConfig['id']::getConfigTreeBuilder()->buildTree()->finalize($pluginConfig['config']);

$definition = new Definition(null, [$config]);
$definition->setFactory([new Reference($pluginConfig['id']), 'create']);

$plugins[] = $definition;
break;
case 'authentication':
$plugins = array_merge($plugins, $this->configureAuthentication($container, $pluginConfig, $serviceId.'.authentication'));
$plugins = array_merge(
$plugins,
array_map(
fn ($id) => new Reference($id),
$this->configureAuthentication($container, $pluginConfig, $serviceId.'.authentication')
)
);
break;
case 'vcr':
$this->useVcrPlugin = true;
$plugins = array_merge($plugins, $this->configureVcrPlugin($container, $pluginConfig, $serviceId.'.vcr'));
$plugins = array_merge(
$plugins,
array_map(
fn ($id) => new Reference($id),
$this->configureVcrPlugin($container, $pluginConfig, $serviceId.'.vcr'),
),
);
break;
default:
$plugins[] = $this->configurePlugin($container, $serviceId, $pluginName, $pluginConfig);
$plugins[] = new Reference($this->configurePlugin($container, $serviceId, $pluginName, $pluginConfig));
}
}

Expand All @@ -456,12 +481,7 @@ private function configureClient(ContainerBuilder $container, string $clientName
->register($serviceId, PluginClient::class)
->setFactory([new Reference(PluginClientFactory::class), 'createClient'])
->addArgument(new Reference($serviceId.'.client'))
->addArgument(
array_map(
fn ($id) => new Reference($id),
$plugins
)
)
->addArgument($plugins)
->addArgument([
'client_name' => $clientName,
])
Expand Down
20 changes: 20 additions & 0 deletions src/PluginConfigurator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Http\HttplugBundle;

use Http\Client\Common\Plugin;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;

interface PluginConfigurator
{
public static function getConfigTreeBuilder(): TreeBuilder;

/**
* Creates the plugin with the given config.
*
* @param array<mixed> $config
*/
public function create(array $config): Plugin;
}
24 changes: 24 additions & 0 deletions tests/Resources/CustomPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Http\HttplugBundle\Tests\Resources;

use Http\Client\Common\Plugin;
use Http\Promise\Promise;
use Psr\Http\Message\RequestInterface;

final class CustomPlugin implements Plugin
{
private string $name;

public function __construct(string $name)
{
$this->name = $name;
}

public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise
{
return $next($request);
}
}
32 changes: 32 additions & 0 deletions tests/Resources/CustomPluginConfigurator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Http\HttplugBundle\Tests\Resources;

use Http\HttplugBundle\PluginConfigurator;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;

final class CustomPluginConfigurator implements PluginConfigurator
{
public static function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('custom_plugin');
$rootNode = $treeBuilder->getRootNode();

$rootNode
->children()
->scalarNode('name')
->isRequired()
->cannotBeEmpty()
->end()
->end();

return $treeBuilder;
}

public function create(array $config): CustomPlugin
{
return new CustomPlugin($config['name']);
}
}
10 changes: 10 additions & 0 deletions tests/Resources/Fixtures/config/full.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

declare(strict_types=1);

use Http\HttplugBundle\Tests\Resources\CustomPluginConfigurator;

$container->loadFromExtension('httplug', [
'default_client_autowiring' => false,
'main_alias' => [
Expand All @@ -27,6 +29,14 @@
'http_methods_client' => true,
'plugins' => [
'httplug.plugin.redirect',
[
'configurator' => [
'id' => CustomPluginConfigurator::class,
'config' => [
'name' => 'foo',
],
],
],
[
'add_host' => [
'host' => 'http://localhost',
Expand Down
7 changes: 7 additions & 0 deletions tests/Resources/Fixtures/config/full.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
</classes>
<client name="test" factory="httplug.factory.guzzle7" http-methods-client="true">
<plugin>httplug.plugin.redirect</plugin>
<plugin>
<configurator id="Http\HttplugBundle\Tests\Resources\CustomPluginConfigurator">
<config>
<name>foo</name>
</config>
</configurator>
</plugin>
<plugin>
<add-host host="http://localhost"/>
</plugin>
Expand Down
5 changes: 5 additions & 0 deletions tests/Resources/Fixtures/config/full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ httplug:
http_methods_client: true
plugins:
- 'httplug.plugin.redirect'
-
configurator:
id: Http\HttplugBundle\Tests\Resources\CustomPluginConfigurator
config:
name: foo
-
add_host:
host: http://localhost
Expand Down
10 changes: 10 additions & 0 deletions tests/Unit/DependencyInjection/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Http\Adapter\Guzzle7\Client;
use Http\HttplugBundle\DependencyInjection\Configuration;
use Http\HttplugBundle\DependencyInjection\HttplugExtension;
use Http\HttplugBundle\Tests\Resources\CustomPluginConfigurator;
use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionConfigurationTestCase;
use Nyholm\Psr7\Factory\Psr17Factory;
use Symfony\Component\Config\Definition\ConfigurationInterface;
Expand Down Expand Up @@ -155,6 +156,15 @@ public function testSupportsAllConfigFormats(): void
'id' => 'httplug.plugin.redirect',
],
],
[
'configurator' => [
'enabled' => true,
'id' => CustomPluginConfigurator::class,
'config' => [
'name' => 'foo',
],
],
],
[
'add_host' => [
'enabled' => true,
Expand Down
36 changes: 36 additions & 0 deletions tests/Unit/DependencyInjection/HttplugExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
use Http\Adapter\Guzzle7\Client;
use Http\Client\Plugin\Vcr\Recorder\InMemoryRecorder;
use Http\HttplugBundle\DependencyInjection\HttplugExtension;
use Http\HttplugBundle\Tests\Resources\CustomPluginConfigurator;
use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase;
use Psr\Http\Client\ClientInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

/**
Expand Down Expand Up @@ -203,6 +205,40 @@ public function testClientPlugins(): void
$this->assertContainerBuilderHasService('httplug.client.mock');
}

public function testPluginConfiguratorConfig(): void
{
$config = [
'clients' => [
'acme' => [
'factory' => 'httplug.factory.curl',
'plugins' => [
[
'configurator' => [
'id' => CustomPluginConfigurator::class,
'config' => [
'name' => 'foo',
],
],
],
],
],
],
];

$this->load($config);

$definition = new Definition(null, [
['name' => 'foo'],
]);
$definition->setFactory([CustomPluginConfigurator::class, 'create']);

$this->assertContainerBuilderHasService('httplug.client.acme');
$this->assertContainerBuilderHasServiceDefinitionWithArgument('httplug.client.acme', 1, [
$definition,
]);
$this->assertContainerBuilderHasService('httplug.client.mock');
}

public function testNoProfilingWhenNotInDebugMode(): void
{
$this->setParameter('kernel.debug', false);
Expand Down