diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index dd67a2b5416f6c604b6e1062c72926107af8aff5..d778693888f699508fbc44c9cab1b182a668bf5f 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -28,6 +28,8 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\TerminableInterface; @@ -582,6 +584,11 @@ public function preHandle(Request $request) { (bool) Settings::get(RequestSanitizer::SANITIZE_LOG, FALSE) ); + // Ensure that there is a session on every request. + if (!$request->hasSession()) { + $this->initializeEphemeralSession($request); + } + $this->loadLegacyIncludes(); // Load all enabled modules. @@ -1638,4 +1645,23 @@ protected function getInstallProfile() { return $config['profile'] ?? NULL; } + /** + * Initializes a session backed by in-memory store and puts it on the request. + * + * A simple in-memory store is sufficient for command line tools and tests. + * Web requests will be processed by the session middleware where the mock + * session is replaced by a session object backed with persistent storage and + * a real session handler. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request. + * + * @see \Drupal\Core\StackMiddleware\Session::handle() + */ + protected function initializeEphemeralSession(Request $request): void { + $session = new Session(new MockArraySessionStorage()); + $session->start(); + $request->setSession($session); + } + } diff --git a/core/lib/Drupal/Core/StackMiddleware/Session.php b/core/lib/Drupal/Core/StackMiddleware/Session.php index d9da60ac602518ae5a71d66f1d7df673307d0363..94841e1508dde7a62b2ebb85a9a5406b3600f2ff 100644 --- a/core/lib/Drupal/Core/StackMiddleware/Session.php +++ b/core/lib/Drupal/Core/StackMiddleware/Session.php @@ -49,19 +49,42 @@ public function __construct(HttpKernelInterface $http_kernel, $service_name = 's * {@inheritdoc} */ public function handle(Request $request, $type = self::MAIN_REQUEST, $catch = TRUE): Response { + // Initialize and start a session for web requests. Command line tools and + // the parent site in functional tests must continue to use the ephemeral + // session initialized and started in DrupalKernel::preHandle(). if ($type === self::MAIN_REQUEST && PHP_SAPI !== 'cli') { - $session = $this->container->get($this->sessionServiceName); - $session->start(); - $request->setSession($session); + $this->initializePersistentSession($request); } $result = $this->httpKernel->handle($request, $type, $catch); - if ($type === self::MAIN_REQUEST && $request->hasSession()) { + if ($type === self::MAIN_REQUEST && PHP_SAPI !== 'cli' && $request->hasSession()) { $request->getSession()->save(); } return $result; } + /** + * Initializes a session backed by persistent store and puts it on the request. + * + * Sessions for web requests need to be backed by a persistent session store + * and a real session handler (responsible for session cookie management). + * In contrast, a simple in-memory store is sufficient for command line tools + * and tests. Hence, the persistent session should only ever be placed on web + * requests while command line tools and the parent site in functional tests + * must continue to use the ephemeral session initialized in + * DrupalKernel::preHandle(). + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request. + * + * @see \Drupal\Core\DrupalKernel::preHandle() + */ + protected function initializePersistentSession(Request $request): void { + $session = $this->container->get($this->sessionServiceName); + $session->start(); + $request->setSession($session); + } + } diff --git a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php index 2e7083ff86f076e0a42e9a9c215927e19c27b915..737f1ef247e7e7093a496ceb046d43160e765c56 100644 --- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php +++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php @@ -23,6 +23,8 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Yaml\Yaml as SymfonyYaml; use Drupal\Core\Routing\RouteObjectInterface; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -210,10 +212,6 @@ protected function setContainerParameter($name, $value) { protected function rebuildContainer() { // Rebuild the kernel and bring it back to a fully bootstrapped state. $this->container = $this->kernel->rebuildContainer(); - - // Make sure the URL generator has a request object, otherwise calls to - // $this->drupalGet() will fail. - $this->prepareRequestForGenerator(); } /** @@ -254,6 +252,7 @@ protected function resetAll() { */ protected function prepareRequestForGenerator($clean_urls = TRUE, $override_server_vars = []) { $request = Request::createFromGlobals(); + $request->setSession(new Session(new MockArraySessionStorage())); $base_path = $request->getBasePath(); if ($clean_urls) { $request_path = $base_path ? $base_path . '/user' : 'user'; @@ -265,6 +264,7 @@ protected function prepareRequestForGenerator($clean_urls = TRUE, $override_serv $server = array_merge($request->server->all(), $override_server_vars); $request = Request::create($request_path, 'GET', [], [], [], $server); + $request->setSession(new Session(new MockArraySessionStorage())); // Ensure the request time is REQUEST_TIME to ensure that API calls // in the test use the right timestamp. $request->server->set('REQUEST_TIME', REQUEST_TIME); diff --git a/core/modules/book/tests/src/Kernel/BookMultilingualTest.php b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php index fbdfc3d8499a3251ae69250744b2b7329923b413..7c2ead6bc72e295439ca08f2a24fc020ec7cd3d3 100644 --- a/core/modules/book/tests/src/Kernel/BookMultilingualTest.php +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php @@ -14,6 +14,8 @@ use Drupal\Tests\user\Traits\UserCreationTrait; use Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUser; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -271,7 +273,9 @@ public function langcodesProvider() { * is used instead of the content language. */ protected function setCurrentLanguage(string $langcode): void { - \Drupal::requestStack()->push(Request::create("http://$langcode.book.test.domain/")); + $request = Request::create("http://$langcode.book.test.domain/"); + $request->setSession(new Session(new MockArraySessionStorage())); + \Drupal::requestStack()->push($request); $language_manager = $this->container->get('language_manager'); $language_manager->reset(); $current_user = \Drupal::currentUser(); diff --git a/core/modules/comment/tests/src/Kernel/CommentHostnameTest.php b/core/modules/comment/tests/src/Kernel/CommentHostnameTest.php index a056c086de7df3fefed834f477dcd86caefa9e91..7099c6d935363327b4488034e57ea6b9b6cd3ff0 100644 --- a/core/modules/comment/tests/src/Kernel/CommentHostnameTest.php +++ b/core/modules/comment/tests/src/Kernel/CommentHostnameTest.php @@ -6,6 +6,8 @@ use Drupal\comment\Entity\CommentType; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the hostname base field. @@ -29,6 +31,7 @@ class CommentHostnameTest extends KernelTestBase { public function testGetDefaultHostname() { // Create a fake request to be used for testing. $request = Request::create('/', 'GET', [], [], [], ['REMOTE_ADDR' => '203.0.113.1']); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $stack */ $stack = $this->container->get('request_stack'); $stack->push($request); diff --git a/core/modules/language/tests/src/Functional/LanguageNegotiationContentEntityTest.php b/core/modules/language/tests/src/Functional/LanguageNegotiationContentEntityTest.php index d13b923e3b72499751f72fccefd637aca131a60c..d74a1def3940d8c50563c10bc44a0ef8f06239a3 100644 --- a/core/modules/language/tests/src/Functional/LanguageNegotiationContentEntityTest.php +++ b/core/modules/language/tests/src/Functional/LanguageNegotiationContentEntityTest.php @@ -10,6 +10,8 @@ use Drupal\Tests\BrowserTestBase; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -185,6 +187,7 @@ protected function setCurrentRequestForRoute($path, $route_name) { $request = Request::create($path); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, $route_name); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route($path)); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); } diff --git a/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php b/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php index 7a635e1140768bcd58d2c59fa5ba1a9ddca93e9e..46f518b2194af854bcb5d46b69bbf8f0ace9ac5d 100644 --- a/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php +++ b/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php @@ -19,6 +19,8 @@ use Symfony\Component\HttpFoundation\Request; use Drupal\language\LanguageNegotiatorInterface; use Drupal\block\Entity\Block; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the language UI for language switching. @@ -564,6 +566,7 @@ public function testLanguageDomain() { // Test HTTPS via current URL scheme. $request = Request::create('', 'GET', [], [], [], ['HTTPS' => 'on']); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); $italian_url = Url::fromRoute('system.admin', [], ['language' => $languages['it']])->toString(); $correct_link = 'https://' . $link; diff --git a/core/modules/language/tests/src/Kernel/EntityUrlLanguageTest.php b/core/modules/language/tests/src/Kernel/EntityUrlLanguageTest.php index 58ccffc612e74733a035374074b31b583fc42d84..44505aac764d88617d3acc057b3c4bb5ff3dc45f 100644 --- a/core/modules/language/tests/src/Kernel/EntityUrlLanguageTest.php +++ b/core/modules/language/tests/src/Kernel/EntityUrlLanguageTest.php @@ -9,6 +9,8 @@ use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -132,6 +134,7 @@ protected function setCurrentRequestForRoute($path, $route_name) { $request = Request::create($path); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, $route_name); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route($path)); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); } diff --git a/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php b/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php index bc1288972936ef9118ffbc0292813fb208e79852..fd37d6720ea42345400c870e9047f8589b2f6228 100644 --- a/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php +++ b/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php @@ -12,6 +12,8 @@ use Drupal\user\Entity\User; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -62,6 +64,7 @@ public function testOutboundPathAndRouteProcessing() { $request = Request::create('/'); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<front>'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); diff --git a/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php b/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php index 7c72ea90ed2d57d718b68fe176b96e25594fca68..3e10fe98bfcafa3e23ca2c64585e0675aa8c4338 100644 --- a/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php +++ b/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php @@ -16,6 +16,8 @@ use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\Views; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the serializer style plugin. @@ -594,6 +596,7 @@ public function testLivePreview() { // We set up a request so it looks like a request in the live preview. $request = new Request(); $request->query->add([MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = \Drupal::service('request_stack'); $request_stack->push($request); diff --git a/core/modules/syslog/tests/src/Kernel/SyslogTest.php b/core/modules/syslog/tests/src/Kernel/SyslogTest.php index 14137c73efae5fccd67eca5908bccb5e3fed8f32..987f6bef6ec635b5f22640d44cab6d1687aeca4d 100644 --- a/core/modules/syslog/tests/src/Kernel/SyslogTest.php +++ b/core/modules/syslog/tests/src/Kernel/SyslogTest.php @@ -4,6 +4,8 @@ use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Test syslog logger functionality. @@ -30,6 +32,7 @@ public function testSyslogWriting() { $request = Request::create('/page-not-found', 'GET', [], [], [], ['REMOTE_ADDR' => '1.2.3.4']); $request->headers->set('Referer', 'other-site'); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::requestStack()->push($request); $user = $this->getMockBuilder('Drupal\Core\Session\AccountInterface')->getMock(); diff --git a/core/modules/system/tests/src/Functional/Database/SelectPagerDefaultTest.php b/core/modules/system/tests/src/Functional/Database/SelectPagerDefaultTest.php index 41aa5c3a830994e61b1aa48cce236b5809149cdd..67129d429c7c7a1bce764f2f226e0a3d8c7cde45 100644 --- a/core/modules/system/tests/src/Functional/Database/SelectPagerDefaultTest.php +++ b/core/modules/system/tests/src/Functional/Database/SelectPagerDefaultTest.php @@ -6,6 +6,8 @@ use Drupal\Core\Database\Database; use Drupal\Core\Database\Query\PagerSelectExtender; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the pager query select extender. @@ -141,6 +143,7 @@ public function testElementNumbers() { $request->query->replace([ 'page' => '3, 2, 1, 0', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $connection = Database::getConnection(); diff --git a/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php index a335d9648a563ac724b3c196418ddd86814747ab..a09d42b40219e3ae55eb9254ff0a7d97bed5fe24 100644 --- a/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php +++ b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php @@ -11,6 +11,8 @@ use Drupal\user\Entity\User; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; @@ -233,6 +235,7 @@ public function testConfigLevelDepth() { $request = new Request(); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'example3'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $route); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); // \Drupal\Core\Menu\MenuActiveTrail uses the cache collector pattern, which // includes static caching. Since this second scenario simulates a second @@ -300,6 +303,7 @@ public function testConfigExpanded($active_route, $menu_block_level, $expected_i $request = new Request(); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, $active_route); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $route); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); $block_build = $block->build(); diff --git a/core/modules/system/tests/src/Kernel/Theme/TwigIncludeTest.php b/core/modules/system/tests/src/Kernel/Theme/TwigIncludeTest.php index 78298c5044d427e3d0eb4f71c9055c834f94ae98..2abfc8f1708cf7c00a619829f60a8a0812da8a73 100644 --- a/core/modules/system/tests/src/Kernel/Theme/TwigIncludeTest.php +++ b/core/modules/system/tests/src/Kernel/Theme/TwigIncludeTest.php @@ -68,8 +68,10 @@ public function testTemplateInclusion(): void { $twig_config = $this->container->getParameter('twig.config'); $twig_config['allowed_file_extensions'][] = 'sql'; $this->twigConfig = $twig_config; - $this->container->get('kernel')->shutdown(); - $this->container->get('kernel')->boot(); + // @todo This used to call shutdown() and boot(). rebuildContainer() is + // needed until we stop pushing the request twice and only popping it once. + // @see https://www.drupal.org/i/2613044 + $this->container->get('kernel')->rebuildContainer(); /** @var \Drupal\Core\Template\Loader\FilesystemLoader $loader */ $loader = \Drupal::service('twig.loader.filesystem'); $source = $loader->getSourceContext('@__main__\/core/tests/fixtures/files/sql-2.sql'); @@ -80,8 +82,10 @@ public function testTemplateInclusion(): void { $this->assertSame(['css', 'html', 'js', 'svg', 'twig', 'sql'], \Drupal::getContainer()->getParameter('twig.config')['allowed_file_extensions']); unset($twig_config['allowed_file_extensions']); $this->twigConfig = $twig_config; - $this->container->get('kernel')->shutdown(); - $this->container->get('kernel')->boot(); + // @todo This used to call shutdown() and boot(). rebuildContainer() is + // needed until we stop pushing the request twice and only popping it once. + // @see https://www.drupal.org/i/2613044 + $this->container->get('kernel')->rebuildContainer(); $this->assertArrayNotHasKey('allowed_file_extensions', \Drupal::getContainer()->getParameter('twig.config')); /** @var \Drupal\Core\Template\Loader\FilesystemLoader $loader */ $loader = \Drupal::service('twig.loader.filesystem'); @@ -108,8 +112,10 @@ public function testTemplateInclusion(): void { // Allow files with no extension. $twig_config['allowed_file_extensions'] = ['twig', '']; $this->twigConfig = $twig_config; - $this->container->get('kernel')->shutdown(); - $this->container->get('kernel')->boot(); + // @todo This used to call shutdown() and boot(). rebuildContainer() is + // needed until we stop pushing the request twice and only popping it once. + // @see https://www.drupal.org/i/2613044 + $this->container->get('kernel')->rebuildContainer(); /** @var \Drupal\Core\Template\Loader\FilesystemLoader $loader */ $loader = \Drupal::service('twig.loader.filesystem'); $source = $loader->getSourceContext('@__main__\/' . $this->siteDirectory . '/test_file'); diff --git a/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php b/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php index 516e3bd40c3806109a3c06a1569b4d946ecc0b1f..802190359b4c89b089f2702d5c9ce0109cc5403c 100644 --- a/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php +++ b/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php @@ -7,6 +7,8 @@ use Drupal\Component\Utility\Xss; use Drupal\Core\Render\BubbleableMetadata; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests token replacement. @@ -137,6 +139,7 @@ public function testSystemSiteTokenReplacement() { 'SERVER_NAME' => 'http://localhost', ]; $request = Request::create('/subdir/', 'GET', [], [], [], $server); + $request->setSession(new Session(new MockArraySessionStorage())); $request->server->add($server); $request_stack->push($request); $bubbleable_metadata = new BubbleableMetadata(); diff --git a/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php b/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php index 897290b2877861ecf863f53737800ca220cfe822..d41a6dea939cd1a0fa4eb6325e3943231997ebab 100644 --- a/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php +++ b/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php @@ -6,6 +6,8 @@ use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\ViewExecutable; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; trait AssertViewsCacheTagsTrait { @@ -43,6 +45,7 @@ protected function assertViewsCacheTags(ViewExecutable $view, $expected_results_ $request_stack = \Drupal::service('request_stack'); $request = Request::createFromGlobals(); $request->server->set('REQUEST_TIME', REQUEST_TIME); + $request->setSession(new Session(new MockArraySessionStorage())); $view->setRequest($request); $request_stack->push($request); $renderer->renderRoot($build); @@ -123,6 +126,7 @@ protected function assertViewsCacheTagsFromStaticRenderArray(ViewExecutable $vie $request_stack = \Drupal::service('request_stack'); $request = new Request(); $request->server->set('REQUEST_TIME', REQUEST_TIME); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $renderer->renderRoot($build); diff --git a/core/modules/views/tests/src/Kernel/Handler/AreaDisplayLinkTest.php b/core/modules/views/tests/src/Kernel/Handler/AreaDisplayLinkTest.php index e3bbdfa5681350ec5b3a0356a713451494309eba..87a1afea80028905a5707b7e8de5fe8825281a67 100644 --- a/core/modules/views/tests/src/Kernel/Handler/AreaDisplayLinkTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/AreaDisplayLinkTest.php @@ -15,6 +15,8 @@ use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the core views_handler_area_display_link handler. @@ -148,8 +150,7 @@ public function testAreaDisplayLink() { // Assert some special request parameters are filtered from the display // links. - $request_stack = new RequestStack(); - $request_stack->push(Request::create('page_1', 'GET', [ + $request = Request::create('page_1', 'GET', [ 'name' => 'John', 'sort_by' => 'created', 'sort_order' => 'ASC', @@ -166,7 +167,10 @@ public function testAreaDisplayLink() { AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER => 1, FormBuilderInterface::AJAX_FORM_REQUEST => 1, MainContentViewSubscriber::WRAPPER_FORMAT => 1, - ])); + ]); + $request->setSession(new Session(new MockArraySessionStorage())); + $request_stack = new RequestStack(); + $request_stack->push($request); $this->container->set('request_stack', $request_stack); $view->destroy(); $view->setDisplay('page_1'); diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php index e83b425dc42cabee039fa79d966d936c614623e0..f0035f4b1f4e574022d2e1370526f4141c6cd661 100644 --- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php +++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php @@ -11,6 +11,7 @@ use Drupal\Tests\Traits\Core\CronRunTrait; use Drupal\user\Entity\Role; use PHPUnit\Framework\ExpectationFailedException; +use Symfony\Component\HttpFoundation\Request; /** * Tests BrowserTestBase functionality. @@ -521,6 +522,30 @@ public function testHtkey() { $this->assertSession()->statusCodeEquals(403); } + /** + * Tests that a usable session is on the request in test-runner. + */ + public function testSessionOnRequest(): void { + /** @var \Symfony\Component\HttpFoundation\Session\Session $session */ + $session = $this->container->get('request_stack')->getSession(); + + $session->set('some-val', 'do-not-cleanup'); + $this->assertEquals('do-not-cleanup', $session->get('some-val')); + + $session->set('some-other-val', 'do-cleanup'); + $this->assertEquals('do-cleanup', $session->remove('some-other-val')); + } + + /** + * Tests deprecation of modified request stack lacking a session. + * + * @group legacy + */ + public function testDeprecatedSessionMissing(): void { + $this->expectDeprecation('Pushing requests without a session onto the request_stack is deprecated in drupal:10.3.0 and an error will be thrown from drupal:11.0.0. See https://www.drupal.org/node/3337193'); + $this->container->get('request_stack')->push(Request::create('/')); + } + /** * Tests that deprecation headers do not get duplicated. * diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php index 7cd1ae5682cd5016a93c91d5912a1a786dad98f1..52c226c93ea38807acc65e4066f90f43fd40ca70 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php @@ -15,6 +15,8 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Base class for testing the interactive installer. @@ -118,6 +120,7 @@ public function installDrupal() { // server information so that XDebug works. // @see install_begin_request() $request = Request::create($GLOBALS['base_url'] . '/core/install.php', 'GET', [], $_COOKIE, [], $_SERVER); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container = new ContainerBuilder(); $request_stack = new RequestStack(); $request_stack->push($request); diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php index 42ff9e293aa0a46a73b0bdfd86b185d53ab85098..f941802c1434ea989fee92898cc5d5b8cf512d31 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php @@ -13,6 +13,8 @@ use Drupal\taxonomy\Entity\Vocabulary; use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; // cspell:ignore merhaba siema xsiemax @@ -464,6 +466,7 @@ public function testSort() { $request->query->replace([ 'page' => '0,2', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $this->queryResults = $this->storage ->getQuery() @@ -500,6 +503,7 @@ public function testTableSort() { 'sort' => 'asc', 'order' => 'Type', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $header = [ diff --git a/core/tests/Drupal/KernelTests/Core/File/FileUrlGeneratorTest.php b/core/tests/Drupal/KernelTests/Core/File/FileUrlGeneratorTest.php index a4a004c825f765743e78319a092b74def07e7d07..5359ee3fc56aa50611fb336dc2cff013663650d1 100644 --- a/core/tests/Drupal/KernelTests/Core/File/FileUrlGeneratorTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/FileUrlGeneratorTest.php @@ -4,6 +4,8 @@ use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * @coversDefaultClass \Drupal\Core\File\FileUrlGenerator @@ -154,6 +156,7 @@ public function testRelativeFileURL() { // Create a mock Request for transformRelative(). $request = Request::create($GLOBALS['base_url']); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); \Drupal::setContainer($this->container); @@ -183,6 +186,7 @@ public function testGenerateURI($filepath, $expected) { // Create a mock Request for transformRelative(). $request = Request::create($GLOBALS['base_url']); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); \Drupal::setContainer($this->container); @@ -200,6 +204,7 @@ public function testGenerateURIWithSchema() { // Create a mock Request for transformRelative(). $request = Request::create($GLOBALS['base_url']); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); \Drupal::setContainer($this->container); diff --git a/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php b/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php index 57111ee2f442a235dcaf51ecd96ed909cfdcd4fd..c02dad6501a982922a60045599378c82454c8b98 100644 --- a/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php @@ -4,6 +4,8 @@ use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests URL transform to relative. @@ -35,6 +37,7 @@ public function testFileUrlTransformRelative($host, $port, $https, $url, $expect $_SERVER['HTTPS'] = $https; $request = Request::createFromGlobals(); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::requestStack()->push($request); $this->assertSame($expected, \Drupal::service('file_url_generator')->transformRelative($url)); diff --git a/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php b/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php index b2486202890bd8b5da6c86f3aad5857839a3f66a..caa39c1cb722f6cfd499d940f2c87d20a590ba01 100644 --- a/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php +++ b/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php @@ -7,6 +7,8 @@ use Drupal\KernelTests\KernelTestBase; use Drupal\user\Entity\User; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Ensures that form actions can't be tricked into sending to external URLs. @@ -76,6 +78,7 @@ public function testActionUrlBehavior() { $request_stack->pop(); $request_stack->pop(); $request = Request::create($original_request->getSchemeAndHttpHost() . '//example.org'); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $form = \Drupal::formBuilder()->getForm($this); @@ -91,6 +94,7 @@ public function testActionUrlBehavior() { $request_stack = \Drupal::service('request_stack'); $original_request = $request_stack->pop(); $request = Request::create($original_request->getSchemeAndHttpHost() . '/example.org'); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $form = \Drupal::formBuilder()->getForm($this); diff --git a/core/tests/Drupal/KernelTests/Core/Form/FormActionXssTest.php b/core/tests/Drupal/KernelTests/Core/Form/FormActionXssTest.php index fc67b354e94398dd3765a1963118728843423f44..2cf6e10b9091544b167e1adc6e641de51e59fffb 100644 --- a/core/tests/Drupal/KernelTests/Core/Form/FormActionXssTest.php +++ b/core/tests/Drupal/KernelTests/Core/Form/FormActionXssTest.php @@ -7,6 +7,8 @@ use Drupal\KernelTests\KernelTestBase; use Drupal\user\Entity\User; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; // cspell:ignore attribute\'close @@ -77,6 +79,7 @@ public function testFormActionXss() { $request_stack->pop(); $request_stack->pop(); $request = Request::create($original_request->getSchemeAndHttpHost() . '/test/"injected=\'attribute\'close="'); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $form = \Drupal::formBuilder()->getForm($this); diff --git a/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php b/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php index 3624b76e35e7543607433bd20273219e62d94b8c..11faa4aeb4ac0dd6cea30ae590ce7f89062507c1 100644 --- a/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php +++ b/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php @@ -4,6 +4,8 @@ use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * @group Pager @@ -22,6 +24,7 @@ public function testGetUpdatedParameters() { 'other' => 'arbitrary', ]; $request = Request::create('http://example.com', 'GET', $test_parameters); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = $this->container->get('request_stack'); @@ -43,6 +46,7 @@ public function testGetUpdatedParameters() { */ public function testFindPage() { $request = Request::create('http://example.com', 'GET', ['page' => '0,10']); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = $this->container->get('request_stack'); diff --git a/core/tests/Drupal/KernelTests/Core/Pager/RequestPagerTest.php b/core/tests/Drupal/KernelTests/Core/Pager/RequestPagerTest.php index b21f75bc6f0c978c17bb67868ca3a9213e06c845..598f68dbafef80d04fa0b65514f0551c60a16ad6 100644 --- a/core/tests/Drupal/KernelTests/Core/Pager/RequestPagerTest.php +++ b/core/tests/Drupal/KernelTests/Core/Pager/RequestPagerTest.php @@ -4,6 +4,8 @@ use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * @group Pager @@ -17,6 +19,7 @@ class RequestPagerTest extends KernelTestBase { */ public function testFindPage() { $request = Request::create('http://example.com', 'GET', ['page' => '0,10']); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = $this->container->get('request_stack'); @@ -35,6 +38,7 @@ public function testGetQueryParameters() { 'other' => 'arbitrary', ]; $request = Request::create('http://example.com', 'GET', array_merge(['page' => '0,10'], $test_parameters)); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = $this->container->get('request_stack'); diff --git a/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php b/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php index 34a7bdf0006be545f3ceeb4124cd66c2f2f03c31..588fecae8c5be0fb7cac307e33523f3c0f4030f7 100644 --- a/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php +++ b/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php @@ -55,10 +55,12 @@ public function testGetUrlIfValidWithoutAccessCheck() { FALSE, ]; foreach ($methods as $method) { + /** @var \Symfony\Component\HttpFoundation\Request|null $request */ + $request = NULL; if ($method === FALSE) { $request_stack = $this->container->get('request_stack'); while ($request_stack->getCurrentRequest()) { - $request_stack->pop(); + $request = $request_stack->pop(); } $this->container->set('router.request_context', new RequestContext()); } @@ -69,6 +71,12 @@ public function testGetUrlIfValidWithoutAccessCheck() { $this->assertEquals($method, $requestContext->getMethod()); $this->assertInstanceOf(Url::class, $url); $this->assertSame(['entity_test' => $entity->id()], $url->getRouteParameters()); + + if ($method === FALSE) { + // Restore main request. + $request_stack = $this->container->get('request_stack'); + $request_stack->push($request); + } } } diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/RequestPathTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/RequestPathTest.php index 5eb8c624ceb1a166c04ff4098616b73a4b4940fe..8c8bc7942528467d4c5e20f3061e31f9f07143c3 100644 --- a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/RequestPathTest.php +++ b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/RequestPathTest.php @@ -7,6 +7,8 @@ use Drupal\system\Tests\Routing\MockAliasManager; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests system.module's request path condition. @@ -83,6 +85,7 @@ public function testConditions() { $pages = "/my/pass/page\r\n/my/pass/page2\r\n/foo"; $request = Request::create('/my/pass/page2'); + $request->setSession(new Session(new MockArraySessionStorage())); $this->requestStack->push($request); /** @var \Drupal\system\Plugin\Condition\RequestPath $condition */ diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ResponseStatusTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ResponseStatusTest.php index 9f5690a6bf3ae6b5e007c1a8eac4852ca77128de..33c407508e75749ae01d91333d9be92308be73e6 100644 --- a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ResponseStatusTest.php +++ b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ResponseStatusTest.php @@ -9,6 +9,8 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Exception\HttpException; /** @@ -61,6 +63,7 @@ public function testConditions(array $status_codes, bool $negate, int $response_ $request = new Request(); $request->attributes->set('exception', new HttpException($response_code)); } + $request->setSession(new Session(new MockArraySessionStorage())); $this->requestStack->push($request); /** @var \Drupal\system\Plugin\Condition\ResponseStatus $condition */ diff --git a/core/tests/Drupal/KernelTests/Core/Render/Element/TableSortExtenderTest.php b/core/tests/Drupal/KernelTests/Core/Render/Element/TableSortExtenderTest.php index b605b2111d45c1771a262e19208eeb19cff2ce76..c0bd45713a69627dd9190fecdcaef450f3ac24c2 100644 --- a/core/tests/Drupal/KernelTests/Core/Render/Element/TableSortExtenderTest.php +++ b/core/tests/Drupal/KernelTests/Core/Render/Element/TableSortExtenderTest.php @@ -5,6 +5,8 @@ use Drupal\Core\Utility\TableSort; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests table sorting. @@ -31,6 +33,7 @@ public function testTableSortInit() { ]; $request = Request::createFromGlobals(); $request->query->replace([]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $this->assertEquals($expected_ts, $ts, 'Simple table headers sorted correctly.'); @@ -43,6 +46,7 @@ public function testTableSortInit() { // headers are overridable. 'order' => 'bar', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $this->assertEquals($expected_ts, $ts, 'Simple table headers plus non-overriding $_GET parameters sorted correctly.'); @@ -56,6 +60,7 @@ public function testTableSortInit() { // it in the links that it creates. 'alpha' => 'beta', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $expected_ts['sort'] = 'desc'; $expected_ts['query'] = ['alpha' => 'beta']; @@ -83,6 +88,7 @@ public function testTableSortInit() { $request->query->replace([ 'order' => '2', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -101,6 +107,7 @@ public function testTableSortInit() { // exist. 'order' => 'bar', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -121,6 +128,7 @@ public function testTableSortInit() { // it in the links that it creates. 'alpha' => 'beta', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $expected_ts = [ 'name' => '1', @@ -165,6 +173,7 @@ public function testTableSortInit() { $request->query->replace([ 'order' => '1', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -181,6 +190,7 @@ public function testTableSortInit() { $request->query->replace([ 'order' => '2', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -197,6 +207,7 @@ public function testTableSortInit() { $request->query->replace([ 'order' => '3', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -213,6 +224,7 @@ public function testTableSortInit() { $request->query->replace([ 'order' => '4', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -229,6 +241,7 @@ public function testTableSortInit() { $request->query->replace([ 'order' => '5', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ diff --git a/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteNoneTest.php b/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteNoneTest.php index 21e62d9680aff06166951dadb0f03cfcacba1895..7e35066eebab1f321a650472536e48f9b605e6af 100644 --- a/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteNoneTest.php +++ b/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteNoneTest.php @@ -8,6 +8,8 @@ use Drupal\KernelTests\KernelTestBase; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -59,6 +61,7 @@ public function testProcessOutbound() { $request = Request::create('/subdir', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<front>'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -76,6 +79,7 @@ public function testProcessOutbound() { $request = Request::create('/subdir/node/add', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'node.add'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/node/add')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -93,6 +97,7 @@ public function testProcessOutbound() { $request = Request::create('/', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<front>'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -110,6 +115,7 @@ public function testProcessOutbound() { $request = Request::create('/node/add', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'node.add'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/node/add')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); diff --git a/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteProcessorCurrentIntegrationTest.php b/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteProcessorCurrentIntegrationTest.php index 1a99b00171f0be1fe443fc29b1eff70c931a0f16..1c585d8955dab3171cf3ac55cf2779de2a77f710 100644 --- a/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteProcessorCurrentIntegrationTest.php +++ b/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteProcessorCurrentIntegrationTest.php @@ -8,6 +8,8 @@ use Drupal\KernelTests\KernelTestBase; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -60,6 +62,7 @@ public function testProcessOutbound() { $request = Request::create('/subdir/', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<front>'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -75,6 +78,7 @@ public function testProcessOutbound() { $request = Request::create('/subdir/node/add', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'node.add'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/node/add')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -90,6 +94,7 @@ public function testProcessOutbound() { $request = Request::create('/', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<front>'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -105,6 +110,7 @@ public function testProcessOutbound() { $request = Request::create('/node/add', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'node.add'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/node/add')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -119,6 +125,7 @@ public function testProcessOutbound() { 'SERVER_NAME' => 'http://www.example.com', ]; $request = Request::create('/invalid-path', 'GET', [], [], [], $server); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); diff --git a/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationStringTest.php b/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationStringTest.php index 77e37755f3c65cea503d9a921f7d558032a09c9a..b9544e8241278edd136b9192d05017dad81c9d7d 100644 --- a/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationStringTest.php +++ b/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationStringTest.php @@ -58,8 +58,10 @@ protected function rebootAndPrepareSettings() { // Reboot the container so that different services are injected and the new // settings are picked. $kernel = $this->container->get('kernel'); - $kernel->shutdown(); - $kernel->boot(); + // @todo This used to call shutdown() and boot(). rebuildContainer() is + // needed until we stop pushing the request twice and only popping it once. + // @see https://www.drupal.org/i/2613044 + $kernel->rebuildContainer(); $settings = Settings::getAll(); $settings['locale_custom_strings_de'] = ['' => ['Example @number' => 'Example @number translated']]; // Recreate the settings static. diff --git a/core/tests/Drupal/KernelTests/Core/Theme/ImageTest.php b/core/tests/Drupal/KernelTests/Core/Theme/ImageTest.php index 509b6dea77f178f14db0842ef26f50de06db895a..c5b6336e5e8569d7486b27d0af9d4e92c9f57e56 100644 --- a/core/tests/Drupal/KernelTests/Core/Theme/ImageTest.php +++ b/core/tests/Drupal/KernelTests/Core/Theme/ImageTest.php @@ -4,6 +4,8 @@ use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests built-in image theme functions. @@ -43,6 +45,7 @@ protected function setUp(): void { // the Request containing the correct hostname. KernelTestBase doesn't set // it, so push another request onto the stack to ensure it's correct. $request = Request::create('/', 'GET', [], [], [], $_SERVER); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container = \Drupal::service('kernel')->getContainer(); $this->container->get('request_stack')->push($request); diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index 46b4d88018995b039576272e2ce8fb068244cd92..0a07f19c06431aadb581d34de1cb50c653d6134f 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -37,6 +37,7 @@ use Symfony\Component\Routing\Route; use Symfony\Component\VarDumper\VarDumper; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; /** * Base class for functional integration tests. @@ -667,6 +668,19 @@ protected function assertPostConditions(): void { * {@inheritdoc} */ protected function tearDown(): void { + if ($this->container) { + // Clean up mock session started in DrupalKernel::preHandle(). + try { + /** @var \Symfony\Component\HttpFoundation\Session\Session $session */ + $session = $this->container->get('request_stack')->getSession(); + $session->clear(); + $session->save(); + } + catch (SessionNotFoundException) { + @trigger_error('Pushing requests without a session onto the request_stack is deprecated in drupal:10.3.0 and an error will be thrown from drupal:11.0.0. See https://www.drupal.org/node/3337193', E_USER_DEPRECATED); + } + } + // Destroy the testing kernel. if (isset($this->kernel)) { $this->kernel->shutdown(); diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php index 689cf8b953e073e50b867d75b27aeb4502b7ccd4..be83c0a2672fc4118b979dcf78f1a5b7df31d94b 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php +++ b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php @@ -11,6 +11,7 @@ use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\visitor\vfsStreamStructureVisitor; use PHPUnit\Framework\SkippedTestError; +use Symfony\Component\HttpFoundation\Request; /** * @coversDefaultClass \Drupal\KernelTests\KernelTestBase @@ -235,6 +236,34 @@ public function testBootKernel() { $this->assertEquals('public', \Drupal::config('system.file')->get('default_scheme')); } + /** + * Tests that a usable session is on the request. + * + * @covers ::bootKernel + */ + public function testSessionOnRequest(): void { + /** @var \Symfony\Component\HttpFoundation\Session\Session $session */ + $session = $this->container->get('request_stack')->getSession(); + + $session->set('some-val', 'do-not-cleanup'); + $this->assertEquals('do-not-cleanup', $session->get('some-val')); + + $session->set('some-other-val', 'do-cleanup'); + $this->assertEquals('do-cleanup', $session->remove('some-other-val')); + } + + /** + * Tests deprecation of modified request stack lacking a session. + * + * @covers ::tearDown + * + * @group legacy + */ + public function testDeprecatedSessionMissing(): void { + $this->expectDeprecation('Pushing requests without a session onto the request_stack is deprecated in drupal:10.3.0 and an error will be thrown from drupal:11.0.0. See https://www.drupal.org/node/3337193'); + $this->container->get('request_stack')->push(Request::create('/')); + } + /** * Tests the assumption that local time is in 'Australia/Sydney'. */ diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index 38b41f4163d198dd18d1a984ba31eab26f1c1c4f..082292646eefac000238680c92ef3b3215abba70 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -24,6 +24,7 @@ use GuzzleHttp\Cookie\CookieJar; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; use Symfony\Component\VarDumper\VarDumper; /** @@ -446,6 +447,19 @@ protected function cleanupEnvironment() { protected function tearDown(): void { parent::tearDown(); + if ($this->container) { + // Cleanup mock session started in DrupalKernel::preHandle(). + try { + /** @var \Symfony\Component\HttpFoundation\Session\Session $session */ + $session = $this->container->get('request_stack')->getSession(); + $session->clear(); + $session->save(); + } + catch (SessionNotFoundException) { + @trigger_error('Pushing requests without a session onto the request_stack is deprecated in drupal:10.3.0 and an error will be thrown from drupal:11.0.0. See https://www.drupal.org/node/3337193', E_USER_DEPRECATED); + } + } + // Destroy the testing kernel. if (isset($this->kernel)) { $this->cleanupEnvironment();