diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 766931fbd1..74dfb3f4d5 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -6,11 +6,14 @@ */ use Drupal\Component\Utility\Crypt; +use Drupal\Core\Http\InputBag; use Drupal\Core\Logger\RfcLogLevel; use Drupal\Core\Test\TestDatabase; use Drupal\Core\Utility\Error; use Drupal\Core\StringTranslation\TranslatableMarkup; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\InputBag as SymfonyInputBag; /** * Minimum allowed version of PHP for Drupal to be bootstrapped. @@ -130,6 +133,23 @@ // alias once Drupal is running Symfony 5.3 or higher. class_alias('Drupal\Core\Http\KernelEvent', 'Symfony\Component\HttpKernel\Event\KernelEvent', TRUE); +/** + * Set up the Symfony Request factory for forward compatibility with Symfony 5. + * + * @todo Remove this when Symfony 4 is no longer supported. + */ +Request::setFactory( + function ($query, $request, $attributes, $cookies, $files, $server, $content) { + $request = new Request($query, $request, $attributes, $cookies, $files, $server, $content); + foreach (['request', 'query', 'cookies'] as $bag) { + if (!($bag instanceof SymfonyInputBag)) { + $request->$bag = new InputBag($request->$bag->all()); + } + } + return $request; + } +); + /** * Returns and optionally sets the filename for a system resource. * diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index afb2739543..94ab081d8c 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -17,7 +17,6 @@ use Drupal\Core\DependencyInjection\YamlFileLoader; use Drupal\Core\Extension\ExtensionDiscovery; use Drupal\Core\File\MimeType\MimeTypeGuesser; -use Drupal\Core\Http\InputBag; use Drupal\Core\Http\TrustedHostsRequestFactory; use Drupal\Core\Installer\InstallerKernel; use Drupal\Core\Installer\InstallerRedirectTrait; @@ -34,7 +33,6 @@ use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\TerminableInterface; -use Symfony\Component\HttpFoundation\InputBag as SymfonyInputBag; use TYPO3\PharStreamWrapper\Manager as PharStreamWrapperManager; use TYPO3\PharStreamWrapper\Behavior as PharStreamWrapperBehavior; use TYPO3\PharStreamWrapper\PharStreamWrapper; @@ -695,14 +693,6 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = // Ensure sane PHP environment variables. static::bootEnvironment(); - // Replace ParameterBag with InputBag for compatibility with Symfony 5. - // @todo Remove this when Symfony 4 is no longer supported. - foreach (['request', 'query', 'cookies'] as $bag) { - if (!($bag instanceof SymfonyInputBag)) { - $request->$bag = new InputBag($request->$bag->all()); - } - } - try { $this->initializeSettings($request); diff --git a/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php b/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php index f1ddd55a74..7c46418138 100644 --- a/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php +++ b/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php @@ -2,6 +2,7 @@ namespace Drupal\Core\Http; +use Symfony\Component\HttpFoundation\InputBag as SymfonyInputBag; use Symfony\Component\HttpFoundation\Request; /** @@ -61,7 +62,17 @@ public function createRequest(array $query = [], array $request = [], array $att if (empty($server['HTTP_HOST']) || ($server['HTTP_HOST'] === 'localhost' && $this->host !== 'localhost')) { $server['HTTP_HOST'] = $this->host; } - return new Request($query, $request, $attributes, $cookies, $files, $server, $content); + $request = new Request($query, $request, $attributes, $cookies, $files, $server, $content); + + // Replace ParameterBag with InputBag for compatibility with Symfony 5. + // @todo Remove this when Symfony 4 is no longer supported. + foreach (['request', 'query', 'cookies'] as $bag) { + if (!($bag instanceof SymfonyInputBag)) { + $request->$bag = new InputBag($request->$bag->all()); + } + } + + return $request; } } diff --git a/core/modules/system/tests/modules/trusted_hosts_test/src/Controller/TrustedHostsTestController.php b/core/modules/system/tests/modules/trusted_hosts_test/src/Controller/TrustedHostsTestController.php index bb768421f0..78d20d6a4a 100644 --- a/core/modules/system/tests/modules/trusted_hosts_test/src/Controller/TrustedHostsTestController.php +++ b/core/modules/system/tests/modules/trusted_hosts_test/src/Controller/TrustedHostsTestController.php @@ -17,4 +17,12 @@ public function fakeRequestHost() { return ['#markup' => 'Host: ' . $request->getHost()]; } + /** + * Creates a fake request and prints out the class name of the specified bag. + */ + public function bagType($bag) { + $request = Request::create('/'); + return ['#markup' => 'Type: ' . get_class($request->$bag)]; + } + } diff --git a/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.routing.yml b/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.routing.yml index 607710873c..0fe1e2b331 100644 --- a/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.routing.yml +++ b/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.routing.yml @@ -4,3 +4,10 @@ trusted_hosts_test.fake_request: _controller: '\Drupal\trusted_hosts_test\Controller\TrustedHostsTestController::fakeRequestHost' requirements: _access: 'TRUE' + +trusted_hosts_test.bag_type: + path: '/trusted-hosts-test/bag-type/{bag}' + defaults: + _controller: '\Drupal\trusted_hosts_test\Controller\TrustedHostsTestController::bagType' + requirements: + _access: 'TRUE' diff --git a/core/modules/system/tests/src/Functional/System/TrustedHostsTest.php b/core/modules/system/tests/src/Functional/System/TrustedHostsTest.php index db0cb122cf..9cc455ad66 100644 --- a/core/modules/system/tests/src/Functional/System/TrustedHostsTest.php +++ b/core/modules/system/tests/src/Functional/System/TrustedHostsTest.php @@ -111,4 +111,28 @@ public function testShortcut() { $this->assertSession()->linkExists($shortcut->label()); } + /** + * Tests that the request bags have the correct classes. + * + * @todo Remove this when Symfony 4 is no longer supported. + * + * @see \Drupal\Core\Http\TrustedHostsRequestFactory + */ + public function testRequestBags() { + $this->container->get('module_installer')->install(['trusted_hosts_test']); + + $host = $this->container->get('request_stack')->getCurrentRequest()->getHost(); + $settings['settings']['trusted_host_patterns'] = (object) [ + 'value' => ['^' . preg_quote($host) . '$'], + 'required' => TRUE, + ]; + + $this->writeSettings($settings); + + foreach (['request', 'query', 'cookies'] as $bag) { + $this->drupalGet('trusted-hosts-test/bag-type/' . $bag); + $this->assertSession()->pageTextContains('InputBag'); + } + } + } diff --git a/core/tests/Drupal/Tests/Core/Http/InputBagTest.php b/core/tests/Drupal/Tests/Core/Http/InputBagTest.php index 43b24db129..f2120e4afe 100644 --- a/core/tests/Drupal/Tests/Core/Http/InputBagTest.php +++ b/core/tests/Drupal/Tests/Core/Http/InputBagTest.php @@ -4,6 +4,7 @@ use Drupal\Core\Http\InputBag; use Drupal\Tests\UnitTestCase; +use Symfony\Component\HttpFoundation\Request; /** * @coversDefaultClass \Drupal\Core\Http\InputBag @@ -28,4 +29,13 @@ public function testAll() { $input_bag->all('bad'); } + /** + * @coversNothing + * @todo Remove this when Symfony 4 is no longer supported. + */ + public function testRequestFactory() { + $request = Request::create(''); + $this->assertInstanceOf(InputBag::class, $request->query); + } + }