Skip to content

Commit eedda81

Browse files
committed
[FrameworkBundle] Integrate PsrHttpMessageBridge
1 parent 61023a7 commit eedda81

File tree

12 files changed

+202
-2
lines changed

12 files changed

+202
-2
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use Doctrine\DBAL\Connection;
1616
use Psr\Log\LogLevel;
1717
use Seld\JsonLint\JsonParser;
18+
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
19+
use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
1820
use Symfony\Bundle\FullStack;
1921
use Symfony\Component\Asset\Package;
2022
use Symfony\Component\AssetMapper\AssetMapper;
@@ -192,6 +194,7 @@ public function getConfigTreeBuilder(): TreeBuilder
192194
$this->addHtmlSanitizerSection($rootNode, $enableIfStandalone);
193195
$this->addWebhookSection($rootNode, $enableIfStandalone);
194196
$this->addRemoteEventSection($rootNode, $enableIfStandalone);
197+
$this->addPsrHttpMessageBridgeSection($rootNode, $willBeAvailable);
195198

196199
return $treeBuilder;
197200
}
@@ -2582,4 +2585,24 @@ private function addHtmlSanitizerSection(ArrayNodeDefinition $rootNode, callable
25822585
->end()
25832586
;
25842587
}
2588+
2589+
private function addPsrHttpMessageBridgeSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable): void
2590+
{
2591+
$enableMode = 'canBeEnabled';
2592+
if (!class_exists(FullStack::class)
2593+
&& $willBeAvailable('symfony/psr-http-message-bridge', HttpFoundationFactoryInterface::class)
2594+
&& 0 === (new \ReflectionClass(PsrHttpFactory::class))->getConstructor()->getNumberOfRequiredParameters()
2595+
) {
2596+
$enableMode = 'canBeDisabled';
2597+
}
2598+
2599+
$rootNode
2600+
->children()
2601+
->arrayNode('psr_http_message_bridge')
2602+
->info('PSR HTTP message bridge configuration')
2603+
->{$enableMode}()
2604+
->end()
2605+
->end()
2606+
;
2607+
}
25852608
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
use Psr\Http\Client\ClientInterface;
2626
use Psr\Log\LoggerAwareInterface;
2727
use Symfony\Bridge\Monolog\Processor\DebugProcessor;
28+
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
29+
use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
2830
use Symfony\Bridge\Twig\Extension\CsrfExtension;
2931
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
3032
use Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface;
@@ -576,6 +578,17 @@ public function load(array $configs, ContainerBuilder $container)
576578
$this->registerHtmlSanitizerConfiguration($config['html_sanitizer'], $container, $loader);
577579
}
578580

581+
if ($this->readConfigEnabled('psr_http_message_bridge', $container, $config['psr_http_message_bridge'])) {
582+
if (!interface_exists(HttpFoundationFactoryInterface::class)) {
583+
throw new LogicException('PSR HTTP Message support cannot be enabled as the bridge is not installed. Try running "composer require symfony/psr-http-message-bridge".');
584+
}
585+
if ((new \ReflectionClass(PsrHttpFactory::class))->getConstructor()->getNumberOfRequiredParameters() > 0) {
586+
throw new LogicException('PSR HTTP Message support cannot be enabled for version 2 or earlier. Please update symfony/psr-http-message-bridge to 6.4 or wire all services manually.');
587+
}
588+
589+
$loader->load('psr_http_message_bridge.php');
590+
}
591+
579592
$this->addAnnotatedClassesToCompile([
580593
'**\\Controller\\',
581594
'**\\Entity\\',
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
13+
14+
use Psr\Http\Message\ResponseFactoryInterface;
15+
use Psr\Http\Message\ServerRequestFactoryInterface;
16+
use Psr\Http\Message\StreamFactoryInterface;
17+
use Psr\Http\Message\UploadedFileFactoryInterface;
18+
use Symfony\Bridge\PsrHttpMessage\ArgumentValueResolver\PsrServerRequestResolver;
19+
use Symfony\Bridge\PsrHttpMessage\EventListener\PsrResponseListener;
20+
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
21+
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
22+
use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
23+
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
24+
25+
return static function (ContainerConfigurator $container) {
26+
$container->services()
27+
->set('psr_http_message_bridge.http_foundation_factory', HttpFoundationFactory::class)
28+
->alias(HttpFoundationFactoryInterface::class, 'psr_http_message_bridge.http_foundation_factory')
29+
30+
->set('psr_http_message_bridge.psr_http_factory', PsrHttpFactory::class)
31+
->args([
32+
service(ServerRequestFactoryInterface::class)->nullOnInvalid(),
33+
service(StreamFactoryInterface::class)->nullOnInvalid(),
34+
service(UploadedFileFactoryInterface::class)->nullOnInvalid(),
35+
service(ResponseFactoryInterface::class)->nullOnInvalid(),
36+
])
37+
->alias(HttpMessageFactoryInterface::class, 'psr_http_message_bridge.psr_http_factory')
38+
39+
->set('psr_http_message_bridge.psr_server_request_resolver', PsrServerRequestResolver::class)
40+
->args([service('psr_http_message_bridge.psr_http_factory')])
41+
->tag('controller.argument_value_resolver', ['priority' => -100])
42+
43+
->set('psr_http_message_bridge.psr_response_listener', PsrResponseListener::class)
44+
->args([
45+
service('psr_http_message_bridge.http_foundation_factory'),
46+
])
47+
->tag('kernel.event_subscriber')
48+
;
49+
};

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Doctrine\DBAL\Connection;
1515
use PHPUnit\Framework\TestCase;
16+
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
1617
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Configuration;
1718
use Symfony\Bundle\FullStack;
1819
use Symfony\Component\Cache\Adapter\DoctrineAdapter;
@@ -46,7 +47,7 @@ public function testDefaultConfig()
4647
$this->assertEquals(self::getBundleDefaultConfig(), $config);
4748
}
4849

49-
public function getTestValidSessionName()
50+
public function getTestValidSessionName(): array
5051
{
5152
return [
5253
[null],
@@ -526,7 +527,7 @@ public function testEnabledLockNeedsResources()
526527
]);
527528
}
528529

529-
protected static function getBundleDefaultConfig()
530+
protected static function getBundleDefaultConfig(): array
530531
{
531532
return [
532533
'http_method_override' => false,
@@ -784,6 +785,9 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor
784785
'remote-event' => [
785786
'enabled' => false,
786787
],
788+
'psr_http_message_bridge' => [
789+
'enabled' => !class_exists(FullStack::class) && 0 === (new \ReflectionClass(PsrHttpFactory::class))->getConstructor()->getNumberOfRequiredParameters(),
790+
],
787791
];
788792
}
789793
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller;
13+
14+
use Psr\Http\Message\ResponseFactoryInterface;
15+
use Psr\Http\Message\ResponseInterface;
16+
use Psr\Http\Message\ServerRequestInterface;
17+
use Psr\Http\Message\StreamFactoryInterface;
18+
19+
final class PsrHttpMessageController
20+
{
21+
public function __construct(
22+
private readonly ResponseFactoryInterface&StreamFactoryInterface $factory,
23+
) {
24+
}
25+
26+
public function __invoke(ServerRequestInterface $request): ResponseInterface
27+
{
28+
$responsePayload = json_encode([
29+
'message' => sprintf('Hello %s!', $request->getQueryParams()['name'] ?? 'World'),
30+
], \JSON_THROW_ON_ERROR);
31+
32+
return $this->factory->createResponse()
33+
->withHeader('Content-Type', 'application/json')
34+
->withBody($this->factory->createStream($responsePayload))
35+
;
36+
}
37+
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ http_client_call:
6565
path: /http_client_call
6666
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\HttpClientController::index }
6767

68+
psr_http_message_bridge:
69+
path: /psr_http
70+
controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\PsrHttpMessageController
71+
6872
uid:
6973
resource: "../../Controller/UidController.php"
7074
type: "attribute"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
13+
14+
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
15+
16+
class PsrHttpMessageBridgeTest extends AbstractWebTestCase
17+
{
18+
public function testBridgeIntegration()
19+
{
20+
if ((new \ReflectionClass(PsrHttpFactory::class))->getConstructor()->getNumberOfRequiredParameters() > 0) {
21+
$this->expectException(\LogicException::class);
22+
$this->expectExceptionMessage('PSR HTTP Message support cannot be enabled for version 2 or earlier. Please update symfony/psr-http-message-bridge to 6.4 or wire all services manually.');
23+
}
24+
25+
$client = $this->createClient(['test_case' => 'PsrHttpMessageBridge', 'root_config' => 'config.yml', 'debug' => true]);
26+
$client->request('GET', '/psr_http?name=Symfony');
27+
28+
$this->assertResponseIsSuccessful();
29+
$this->assertResponseHeaderSame('content-type', 'application/json');
30+
$this->assertJsonStringEqualsJsonString('{"message":"Hello Symfony!"}', $client->getResponse()->getContent());
31+
}
32+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
13+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
14+
15+
return [
16+
new FrameworkBundle(),
17+
new TestBundle(),
18+
];
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
imports:
2+
- { resource: ../config/default.yml }
3+
- { resource: services.yml }
4+
5+
framework:
6+
http_method_override: false
7+
profiler: ~
8+
psr_http_message_bridge:
9+
enabled: true
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_emailtest_bundle:
2+
resource: '@TestBundle/Resources/config/routing.yml'

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy