From 7ae9670d22e55ef67d9a6ca822cef64df90c721d Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Wed, 19 Sep 2018 14:04:28 +0100 Subject: [PATCH] Issue #2860341 by heddn, juampynr, seanB, RumyanaRuseva, ephod, stephsem23: PrivateTempStore->getOwner Attempts to access possibly unset Request Session --- .../Core/TempStore/PrivateTempStore.php | 30 +++++++++++++++- .../AnonymousPrivateTempStoreTest.php | 34 +++++++++++++------ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/core/lib/Drupal/Core/TempStore/PrivateTempStore.php b/core/lib/Drupal/Core/TempStore/PrivateTempStore.php index 67d6e32d6cd6..ea7ec3fc3725 100644 --- a/core/lib/Drupal/Core/TempStore/PrivateTempStore.php +++ b/core/lib/Drupal/Core/TempStore/PrivateTempStore.php @@ -123,6 +123,7 @@ class PrivateTempStore { if ($this->currentUser->isAnonymous()) { // @todo when https://www.drupal.org/node/2865991 is resolved, use force // start session API rather than setting an arbitrary value directly. + $this->startSession(); $this->requestStack ->getCurrentRequest() ->getSession() @@ -219,7 +220,34 @@ class PrivateTempStore { * The owner. */ protected function getOwner() { - return $this->currentUser->id() ?: $this->requestStack->getCurrentRequest()->getSession()->getId(); + $owner = $this->currentUser->id(); + if ($this->currentUser->isAnonymous()) { + $this->startSession(); + $owner = $this->requestStack->getCurrentRequest()->getSession()->getId(); + } + return $owner; + } + + /** + * Start session because it is required for a private temp store. + * + * Ensures that an anonymous user has a session created for them, as + * otherwise subsequent page loads will not be able to retrieve their + * tempstore data. + * + * @todo when https://www.drupal.org/node/2865991 is resolved, use force + * start session API. + */ + protected function startSession() { + $has_session = $this->requestStack + ->getCurrentRequest() + ->hasSession(); + if (!$has_session) { + /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ + $session = \Drupal::service('session'); + $this->requestStack->getCurrentRequest()->setSession($session); + $session->start(); + } } } diff --git a/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php b/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php index 7b1faa86cce1..77d229aee467 100644 --- a/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php +++ b/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php @@ -19,6 +19,13 @@ class AnonymousPrivateTempStoreTest extends KernelTestBase { */ public static $modules = ['system']; + /** + * The private temp store. + * + * @var \Drupal\Core\TempStore\PrivateTempStore + */ + protected $tempStore; + /** * {@inheritdoc} */ @@ -29,30 +36,35 @@ class AnonymousPrivateTempStoreTest extends KernelTestBase { // full Drupal environment. $this->installSchema('system', ['key_value_expire']); - $session = $this->container->get('session'); $request = Request::create('/'); - $request->setSession($session); - $stack = $this->container->get('request_stack'); $stack->pop(); $stack->push($request); + $this->tempStore = $this->container->get('tempstore.private')->get('anonymous_private_temp_store'); + } + + /** + * Tests anonymous can get without a previous set. + */ + public function testAnonymousCanUsePrivateTempStoreGet() { + $actual = $this->tempStore->get('foo'); + $this->assertNull($actual); } /** * Tests anonymous can use the PrivateTempStore. */ - public function testAnonymousCanUsePrivateTempStore() { - $temp_store = $this->container->get('tempstore.private')->get('anonymous_private_temp_store'); - $temp_store->set('foo', 'bar'); - $metadata1 = $temp_store->getMetadata('foo'); + public function testAnonymousCanUsePrivateTempStoreSet() { + $this->tempStore->set('foo', 'bar'); + $metadata1 = $this->tempStore->getMetadata('foo'); - $this->assertEquals('bar', $temp_store->get('foo')); + $this->assertEquals('bar', $this->tempStore->get('foo')); $this->assertNotEmpty($metadata1->owner); - $temp_store->set('foo', 'bar2'); - $metadata2 = $temp_store->getMetadata('foo'); - $this->assertEquals('bar2', $temp_store->get('foo')); + $this->tempStore->set('foo', 'bar2'); + $metadata2 = $this->tempStore->getMetadata('foo'); + $this->assertEquals('bar2', $this->tempStore->get('foo')); $this->assertNotEmpty($metadata2->owner); $this->assertEquals($metadata2->owner, $metadata1->owner); }