From 8b1d3fe2a2128c044f95a7ea5c4569f04ae923ac Mon Sep 17 00:00:00 2001 From: Orest Divintari Date: Mon, 8 Dec 2025 23:45:18 +0100 Subject: [PATCH] Replace xml with php config Convert all service configuration files from deprecated XML format to PHP format to eliminate Symfony deprecation warnings and for Symfony 8.0 compatibility. --- CHANGELOG.md | 3 + src/DependencyInjection/HttplugExtension.php | 14 +- src/Resources/config/data-collector.php | 146 +++++++++++++++++++ src/Resources/config/data-collector.xml | 103 ------------- src/Resources/config/mock-client.php | 23 +++ src/Resources/config/mock-client.xml | 15 -- src/Resources/config/plugins.php | 124 ++++++++++++++++ src/Resources/config/plugins.xml | 74 ---------- src/Resources/config/services.php | 130 +++++++++++++++++ src/Resources/config/services.xml | 92 ------------ src/Resources/config/vcr-plugin.php | 26 ++++ src/Resources/config/vcr-plugin.xml | 22 --- 12 files changed, 459 insertions(+), 313 deletions(-) create mode 100644 src/Resources/config/data-collector.php delete mode 100644 src/Resources/config/data-collector.xml create mode 100644 src/Resources/config/mock-client.php delete mode 100644 src/Resources/config/mock-client.xml create mode 100644 src/Resources/config/plugins.php delete mode 100644 src/Resources/config/plugins.xml create mode 100644 src/Resources/config/services.php delete mode 100644 src/Resources/config/services.xml create mode 100644 src/Resources/config/vcr-plugin.php delete mode 100644 src/Resources/config/vcr-plugin.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index dc6796e5..2f82761b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ The change log describes what is "Added", "Removed", "Changed" or "Fixed" betwee # Version 2 +# 2.2.0 - 2025-12-08 +- Replaced XML configuration with PHP configuration. + # 2.1.0 - 2024-11-24 - Added [PluginConfigurator](https://docs.php-http.org/en/latest/integrations/symfony-bundle.html#configure-a-custom-plugin) diff --git a/src/DependencyInjection/HttplugExtension.php b/src/DependencyInjection/HttplugExtension.php index d8c913c3..403676b0 100644 --- a/src/DependencyInjection/HttplugExtension.php +++ b/src/DependencyInjection/HttplugExtension.php @@ -33,7 +33,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Extension\Extension; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\RateLimiter\LimiterInterface; use Twig\Environment as TwigEnvironment; @@ -56,12 +56,12 @@ public function load(array $configs, ContainerBuilder $container): void $configuration = $this->getConfiguration($configs, $container); $config = $this->processConfiguration($configuration, $configs); - $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); - $loader->load('services.xml'); - $loader->load('plugins.xml'); + $loader->load('services.php'); + $loader->load('plugins.php'); if (\class_exists(MockClient::class)) { - $loader->load('mock-client.xml'); + $loader->load('mock-client.php'); } // Register default services @@ -79,7 +79,7 @@ public function load(array $configs, ContainerBuilder $container): void // Configure toolbar $profilingEnabled = $this->isConfigEnabled($container, $config['profiling']); if ($profilingEnabled) { - $loader->load('data-collector.xml'); + $loader->load('data-collector.php'); if (!empty($config['profiling']['formatter'])) { // Add custom formatter @@ -117,7 +117,7 @@ public function load(array $configs, ContainerBuilder $container): void throw new InvalidConfigurationException('You need to require the VCR plugin to be able to use it: "composer require --dev php-http/vcr-plugin".'); } - $loader->load('vcr-plugin.xml'); + $loader->load('vcr-plugin.php'); } } diff --git a/src/Resources/config/data-collector.php b/src/Resources/config/data-collector.php new file mode 100644 index 00000000..46f25c7f --- /dev/null +++ b/src/Resources/config/data-collector.php @@ -0,0 +1,146 @@ +services(); + + $services->set('httplug.formatter.full_http_message', FullHttpMessageFormatter::class); + + $services->set('httplug.collector.formatter', Formatter::class) + ->args([ + service('httplug.formatter.full_http_message'), + inline_service(CurlCommandFormatter::class), + ]); + + $services->set('httplug.collector.collector', Collector::class) + ->tag('data_collector', [ + 'template' => '@Httplug/webprofiler.html.twig', + 'priority' => 200, + 'id' => 'httplug', + ]) + ->tag('kernel.reset', ['method' => 'reset']); + + $services->set('httplug.plugin.stack', StackPlugin::class) + ->args([ + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + ]) + ->abstract(); + + $services->set('httplug.collector.twig.http_message', HttpMessageMarkupExtension::class) + ->args([ + service('var_dumper.cloner')->nullOnInvalid(), + service('var_dumper.html_dumper')->nullOnInvalid(), + ]) + ->tag('twig.extension'); + + // Discovered clients + $services->set('httplug.collector.auto_discovered_client', ProfileClient::class) + ->decorate('httplug.auto_discovery.auto_discovered_client') + ->args([ + service('httplug.collector.auto_discovered_client.inner'), + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + $services->set('httplug.collector.auto_discovered_async', ProfileClient::class) + ->decorate('httplug.auto_discovery.auto_discovered_async') + ->args([ + service('httplug.collector.auto_discovered_async.inner'), + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + // ClientFactories + $services->set('httplug.collector.factory.auto', ProfileClientFactory::class) + ->decorate('httplug.factory.auto') + ->args([ + service('httplug.collector.factory.auto.inner'), + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + $services->set('httplug.collector.factory.buzz', ProfileClientFactory::class) + ->decorate('httplug.factory.buzz') + ->args([ + service('httplug.collector.factory.buzz.inner'), + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + $services->set('httplug.collector.factory.curl', ProfileClientFactory::class) + ->decorate('httplug.factory.curl') + ->args([ + service('httplug.collector.factory.curl.inner'), + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + $services->set('httplug.collector.factory.guzzle6', ProfileClientFactory::class) + ->decorate('httplug.factory.guzzle6') + ->args([ + service('httplug.collector.factory.guzzle6.inner'), + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + $services->set('httplug.collector.factory.guzzle7', ProfileClientFactory::class) + ->decorate('httplug.factory.guzzle7') + ->args([ + service('httplug.collector.factory.guzzle7.inner'), + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + $services->set('httplug.collector.factory.react', ProfileClientFactory::class) + ->decorate('httplug.factory.react') + ->args([ + service('httplug.collector.factory.react.inner'), + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + $services->set('httplug.collector.factory.socket', ProfileClientFactory::class) + ->decorate('httplug.factory.socket') + ->args([ + service('httplug.collector.factory.socket.inner'), + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + $services->set(\Http\Client\Common\PluginClientFactory::class, PluginClientFactory::class) + ->args([ + service('httplug.collector.collector'), + service('httplug.collector.formatter'), + service('debug.stopwatch'), + ]); + + $services->set(PluginClientFactoryListener::class) + ->args([ + service(\Http\Client\Common\PluginClientFactory::class), + ]) + ->tag('kernel.event_subscriber'); +}; diff --git a/src/Resources/config/data-collector.xml b/src/Resources/config/data-collector.xml deleted file mode 100644 index c34e41bc..00000000 --- a/src/Resources/config/data-collector.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Resources/config/mock-client.php b/src/Resources/config/mock-client.php new file mode 100644 index 00000000..c8fd11bd --- /dev/null +++ b/src/Resources/config/mock-client.php @@ -0,0 +1,23 @@ +services(); + + $services->set('httplug.client.mock', Client::class) + ->public(); + + $services->alias(Client::class, 'httplug.client.mock') + ->public(); + + $services->set('httplug.factory.mock', MockFactory::class) + ->call('setClient', [ + service('httplug.client.mock'), + ]); +}; diff --git a/src/Resources/config/mock-client.xml b/src/Resources/config/mock-client.xml deleted file mode 100644 index 5a5e2640..00000000 --- a/src/Resources/config/mock-client.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Resources/config/plugins.php b/src/Resources/config/plugins.php new file mode 100644 index 00000000..35614664 --- /dev/null +++ b/src/Resources/config/plugins.php @@ -0,0 +1,124 @@ +services(); + + $services->set('httplug.plugin.cache', CachePlugin::class) + ->args([ + null, + null, + null, + ]) + ->abstract(); + + $services->set('httplug.plugin.content_length', ContentLengthPlugin::class); + + $services->set('httplug.plugin.cookie', CookiePlugin::class) + ->args([null]); + + $services->set('httplug.plugin.decoder', DecoderPlugin::class); + + $services->set('httplug.plugin.error', ErrorPlugin::class); + + $services->set('httplug.plugin.history', HistoryPlugin::class) + ->args([null]); + + $services->set('httplug.plugin.logger', LoggerPlugin::class) + ->args([ + null, + null, + ]) + ->tag('monolog.logger', ['channel' => 'httplug']) + ->abstract(); + + $services->set('httplug.plugin.redirect', RedirectPlugin::class); + + $services->set('httplug.plugin.retry', RetryPlugin::class); + + $services->set('httplug.plugin.stopwatch', StopwatchPlugin::class) + ->args([null]) + ->abstract(); + + $services->set('httplug.plugin.throttle', ThrottlePlugin::class) + ->args([null]) + ->abstract(); + + // client specific plugin definition prototypes + + $services->set('httplug.plugin.add_host', AddHostPlugin::class) + ->args([ + null, + null, + ]) + ->abstract(); + + $services->set('httplug.plugin.add_path', AddPathPlugin::class) + ->args([null]) + ->abstract(); + + $services->set('httplug.plugin.base_uri', BaseUriPlugin::class) + ->args([ + null, + null, + ]) + ->abstract(); + + $services->set('httplug.plugin.content_type', ContentTypePlugin::class) + ->args([null]) + ->abstract(); + + $services->set('httplug.plugin.header_append', HeaderAppendPlugin::class) + ->args([null]) + ->abstract(); + + $services->set('httplug.plugin.header_defaults', HeaderDefaultsPlugin::class) + ->args([null]) + ->abstract(); + + $services->set('httplug.plugin.header_set', HeaderSetPlugin::class) + ->args([null]) + ->abstract(); + + $services->set('httplug.plugin.header_remove', HeaderRemovePlugin::class) + ->args([null]) + ->abstract(); + + $services->set('httplug.plugin.query_defaults', QueryDefaultsPlugin::class) + ->args([null]) + ->abstract(); + + $services->set('httplug.plugin.request_seekable_body', RequestSeekableBodyPlugin::class) + ->args([null]) + ->abstract(); + + $services->set('httplug.plugin.response_seekable_body', ResponseSeekableBodyPlugin::class) + ->args([null]) + ->abstract(); +}; diff --git a/src/Resources/config/plugins.xml b/src/Resources/config/plugins.xml deleted file mode 100644 index 9f9c0ec1..00000000 --- a/src/Resources/config/plugins.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - null - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php new file mode 100644 index 00000000..ed597732 --- /dev/null +++ b/src/Resources/config/services.php @@ -0,0 +1,130 @@ +services(); + + $services->set('httplug.strategy', ConfiguredClientsStrategy::class) + ->args([ + service('httplug.auto_discovery.auto_discovered_client')->nullOnInvalid(), + service('httplug.auto_discovery.auto_discovered_async')->nullOnInvalid(), + ]); + + $services->set('httplug.strategy_listener', ConfiguredClientsStrategyListener::class) + ->tag('kernel.event_subscriber'); + + $services->set('httplug.auto_discovery.auto_discovered_client', ClientInterface::class) + ->factory([Psr18ClientDiscovery::class, 'find']); + + $services->set('httplug.auto_discovery.auto_discovered_async', HttpAsyncClient::class) + ->factory([HttpAsyncClientDiscovery::class, 'find']); + + // Discovery with autowiring support + $services->set('httplug.async_client.default', HttpAsyncClient::class) + ->factory([HttpAsyncClientDiscovery::class, 'find']); + + $services->alias(HttpAsyncClient::class, 'httplug.async_client.default'); + + $services->set('httplug.client.default', ClientInterface::class) + ->factory([Psr18ClientDiscovery::class, 'find']); + + $services->alias(ClientInterface::class, 'httplug.client'); + + // Discovery for PSR-18 + $services->set('httplug.psr18_client.default', ClientInterface::class) + ->factory([Psr18ClientDiscovery::class, 'find']); + + // Discovery for PSR-17 + $services->set('httplug.psr17_request_factory.default', RequestFactoryInterface::class) + ->factory([Psr17FactoryDiscovery::class, 'findRequestFactory']); + + $services->alias(RequestFactoryInterface::class, 'httplug.psr17_request_factory.default') + ->public(); + + $services->set('httplug.psr17_response_factory.default', ResponseFactoryInterface::class) + ->factory([Psr17FactoryDiscovery::class, 'findResponseFactory']); + + $services->alias(ResponseFactoryInterface::class, 'httplug.psr17_response_factory.default') + ->public(); + + $services->set('httplug.psr17_stream_factory.default', StreamFactoryInterface::class) + ->factory([Psr17FactoryDiscovery::class, 'findStreamFactory']); + + $services->alias(StreamFactoryInterface::class, 'httplug.psr17_stream_factory.default') + ->public(); + + $services->set('httplug.psr17_uri_factory.default', UriFactoryInterface::class) + ->factory([Psr17FactoryDiscovery::class, 'findUrlFactory']); + + $services->alias(UriFactoryInterface::class, 'httplug.psr17_uri_factory.default') + ->public(); + + $services->set('httplug.psr17_uploaded_file_factory.default', UploadedFileFactoryInterface::class) + ->factory([Psr17FactoryDiscovery::class, 'findUploadedFileFactory']); + + $services->alias(UploadedFileFactoryInterface::class, 'httplug.psr17_uploaded_file_factory.default') + ->public(); + + $services->set('httplug.psr17_server_request_factory.default', ServerRequestFactoryInterface::class) + ->factory([Psr17FactoryDiscovery::class, 'findServerRequestFactory']); + + $services->alias(ServerRequestFactoryInterface::class, 'httplug.psr17_server_request_factory.default') + ->public(); + + // PluginClientFactory + $services->set(PluginClientFactory::class); + + // ClientFactories + $services->set('httplug.factory.auto', AutoDiscoveryFactory::class); + + $services->set('httplug.factory.buzz', BuzzFactory::class) + ->args([ + service('httplug.psr17_response_factory'), + ]); + + $services->set('httplug.factory.curl', CurlFactory::class) + ->args([ + service('httplug.psr17_response_factory'), + service('httplug.psr17_stream_factory'), + ]); + + $services->set('httplug.factory.guzzle6', Guzzle6Factory::class); + + $services->set('httplug.factory.guzzle7', Guzzle7Factory::class); + + $services->set('httplug.factory.react', ReactFactory::class); + + $services->set('httplug.factory.socket', SocketFactory::class); + + $services->set('httplug.factory.symfony', SymfonyFactory::class) + ->args([ + service('httplug.psr17_response_factory'), + service('httplug.psr17_stream_factory'), + ]); +}; diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml deleted file mode 100644 index c0db9ef5..00000000 --- a/src/Resources/config/services.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Resources/config/vcr-plugin.php b/src/Resources/config/vcr-plugin.php new file mode 100644 index 00000000..49a5b0ac --- /dev/null +++ b/src/Resources/config/vcr-plugin.php @@ -0,0 +1,26 @@ +services(); + + // Recorders + $services->set('httplug.plugin.vcr.recorder.filesystem', 'Http\Client\Plugin\Vcr\Recorder\FilesystemRecorder') + ->args([ + null, + service('filesystem')->nullOnInvalid(), + ]) + ->call('setLogger', [ + service('logger')->nullOnInvalid(), + ]) + ->abstract(); + + $services->set('httplug.plugin.vcr.recorder.in_memory', 'Http\Client\Plugin\Vcr\Recorder\InMemoryRecorder'); + + // Naming strategies + $services->set('httplug.plugin.vcr.naming_strategy.path', 'Http\Client\Plugin\Vcr\NamingStrategy\PathNamingStrategy') + ->abstract(); +}; diff --git a/src/Resources/config/vcr-plugin.xml b/src/Resources/config/vcr-plugin.xml deleted file mode 100644 index 68c8bd69..00000000 --- a/src/Resources/config/vcr-plugin.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - -