Unverified Commit 5301cfd2 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3518527 by znerol, andypost, smustgrave, catch: Deprecate custom keys in $_SESSION

parent de5530c6
Loading
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -34377,12 +34377,6 @@
	'count' => 1,
	'path' => __DIR__ . '/modules/system/tests/modules/services_defaults_test/src/TestService.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\session_test\\\\Controller\\\\SessionTestController\\:\\:triggerWriteException\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
	'count' => 1,
	'path' => __DIR__ . '/modules/system/tests/modules/session_test/src/Controller/SessionTestController.php',
];
$ignoreErrors[] = [
	'message' => '#^Method Drupal\\\\session_test\\\\EventSubscriber\\\\SessionTestSubscriber\\:\\:onKernelRequestSessionTest\\(\\) has no return type specified\\.$#',
	'identifier' => 'missingType.return',
+11 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
use Drupal\Core\Database\Connection;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

/**
@@ -162,6 +163,16 @@ public function save(): void {
      parent::save();
    }

    $allowedKeys = array_map(
      fn (SessionBagInterface $bag) => $bag->getStorageKey(),
      $this->bags
    );
    $allowedKeys[] = $this->getMetadataBag()->getStorageKey();
    $deprecatedKeys = array_diff(array_keys($_SESSION), $allowedKeys);
    if (count($deprecatedKeys) > 0) {
      @trigger_error(sprintf('Storing values directly in $_SESSION is deprecated in drupal:11.2.0 and will become unsupported in drupal:12.0.0. Use $request->getSession()->set() instead. Affected keys: %s. See https://www.drupal.org/node/3518527', implode(", ", $deprecatedKeys)), E_USER_DEPRECATED);
    }

    $this->startedLazy = FALSE;
  }

+22 −0
Original line number Diff line number Diff line
@@ -179,3 +179,25 @@ session_test.trigger_write_exception:
    no_cache: TRUE
  requirements:
    _access: 'TRUE'

session_test.legacy_get:
  path: '/session-test/legacy-get'
  defaults:
    _title: 'Legacy session value'
    _controller: '\Drupal\session_test\Controller\LegacySessionTestController::get'
  options:
    no_cache: TRUE
  requirements:
    _access: 'TRUE'

session_test.legacy_set:
  path: '/session-test/legacy-set/{test_value}'
  defaults:
    _title: 'Set legacy session value'
    _controller: '\Drupal\session_test\Controller\LegacySessionTestController::set'
  options:
    no_cache: TRUE
    converters:
      test_value: '\s+'
  requirements:
    _access: 'TRUE'
+35 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\session_test\Controller;

use Drupal\Core\Controller\ControllerBase;

/**
 * Controller providing page callbacks for legacy session tests.
 */
class LegacySessionTestController extends ControllerBase {

  /**
   * Prints the stored session value to the screen.
   */
  public function get(): array {
    return empty($_SESSION['legacy_test_value'])
      ? []
      : ['#markup' => $this->t('The current value of the stored session variable is: %val', ['%val' => $_SESSION['legacy_test_value']])];
  }

  /**
   * Stores a value in $_SESSION['legacy_test_value'].
   *
   * @param string $test_value
   *   A session value.
   */
  public function set(string $test_value): array {
    $_SESSION['legacy_test_value'] = $test_value;

    return ['#markup' => $this->t('The current value of the stored session variable has been set to %val', ['%val' => $test_value])];
  }

}
+42 −85
Original line number Diff line number Diff line
@@ -11,20 +11,21 @@
use Symfony\Component\HttpFoundation\Response;

/**
 * Controller providing page callbacks for the action admin interface.
 * Controller providing page callbacks for session tests.
 */
class SessionTestController extends ControllerBase {

  /**
   * Prints the stored session value to the screen.
   *
   * @return string
   *   A notification message.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The incoming request.
   */
  public function get() {
    return empty($_SESSION['session_test_value'])
  public function get(Request $request): array {
    $value = $request->getSession()->get('session_test_value');
    return empty($value)
      ? []
      : ['#markup' => $this->t('The current value of the stored session variable is: %val', ['%val' => $_SESSION['session_test_value']])];
      : ['#markup' => $this->t('The current value of the stored session variable is: %val', ['%val' => $value])];
  }

  /**
@@ -32,11 +33,8 @@ public function get() {
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The incoming request.
   *
   * @return string
   *   A notification message.
   */
  public function getFromSessionObject(Request $request) {
  public function getFromSessionObject(Request $request): array {
    $value = $request->getSession()->get("session_test_key");
    return empty($value)
      ? []
@@ -48,16 +46,13 @@ public function getFromSessionObject(Request $request) {
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The incoming request.
   *
   * @return string
   *   A notification message with session ID.
   */
  public function getId(Request $request) {
    // Set a value in $_SESSION, so that SessionManager::save() will start
  public function getId(Request $request): array {
    // Set a value in session, so that SessionManager::save() will start
    // a session.
    $_SESSION['test'] = 'test';

    $request->getSession()->save();
    $session = $request->getSession();
    $session->set('test', 'test');
    $session->save();

    return ['#markup' => 'session_id:' . session_id() . "\n"];
  }
@@ -67,11 +62,8 @@ public function getId(Request $request) {
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   *
   * @return string
   *   A notification message with session ID.
   */
  public function getIdFromCookie(Request $request) {
  public function getIdFromCookie(Request $request): array {
    return [
      '#markup' => 'session_id:' . $request->cookies->get(session_name()) . "\n",
      '#cache' => ['contexts' => ['cookies:' . session_name()]],
@@ -79,16 +71,15 @@ public function getIdFromCookie(Request $request) {
  }

  /**
   * Stores a value in $_SESSION['session_test_value'].
   * Stores a value in 'session_test_value' session attribute.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   * @param string $test_value
   *   A session value.
   *
   * @return string
   *   A notification message.
   */
  public function set($test_value) {
    $_SESSION['session_test_value'] = $test_value;
  public function set(Request $request, $test_value): array {
    $request->getSession()->set('session_test_value', $test_value);

    return ['#markup' => $this->t('The current value of the stored session variable has been set to %val', ['%val' => $test_value])];
  }
@@ -96,25 +87,21 @@ public function set($test_value) {
  /**
   * Turns off session saving and then tries to save a value anyway.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   * @param string $test_value
   *   A session value.
   *
   * @return string
   *   A notification message.
   */
  public function noSet($test_value) {
  public function noSet(Request $request, $test_value): array {
    \Drupal::service('session_handler.write_safe')->setSessionWritable(FALSE);
    $this->set($test_value);
    $this->set($request, $test_value);
    return ['#markup' => $this->t('session saving was disabled, and then %val was set', ['%val' => $test_value])];
  }

  /**
   * Sets a message to me displayed on the following page.
   *
   * @return string
   *   A notification message.
   */
  public function setMessage() {
  public function setMessage(): Response {
    $this->messenger()->addStatus($this->t('This is a dummy message.'));
    return new Response((string) $this->t('A message was set.'));
    // Do not return anything, so the current request does not result in a
@@ -124,11 +111,8 @@ public function setMessage() {

  /**
   * Sets a message but call drupal_save_session(FALSE).
   *
   * @return string
   *   A notification message.
   */
  public function setMessageButDoNotSave() {
  public function setMessageButDoNotSave(): array {
    \Drupal::service('session_handler.write_safe')->setSessionWritable(FALSE);
    $this->setMessage();
    return ['#markup' => ''];
@@ -136,11 +120,8 @@ public function setMessageButDoNotSave() {

  /**
   * Only available if current user is logged in.
   *
   * @return string
   *   A notification message.
   */
  public function isLoggedIn() {
  public function isLoggedIn(): array {
    return ['#markup' => $this->t('User is logged in.')];
  }

@@ -149,20 +130,13 @@ public function isLoggedIn() {
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The incoming request.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   The response.
   */
  public function traceHandler(Request $request) {
    // Start a session if necessary, set a value and then save and close it.
    $request->getSession()->start();
    if (empty($_SESSION['trace-handler'])) {
      $_SESSION['trace-handler'] = 1;
    }
    else {
      $_SESSION['trace-handler']++;
    }
    $request->getSession()->save();
  public function traceHandler(Request $request): Response {
    // Increment trace-handler counter and save the session.
    $session = $request->getSession();
    $counter = $session->get('trace-handler', 0);
    $session->set('trace-handler', $counter + 1);
    $session->save();

    // Collect traces and return them in JSON format.
    $trace = \Drupal::service('session_test.session_handler_proxy_trace')->getArrayCopy();
@@ -182,15 +156,13 @@ public function traceHandler(Request $request) {
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The incoming request.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   The response.
   *
   * @throws \AssertionError
   */
  public function traceHandlerRewriteUnmodified(Request $request) {
  public function traceHandlerRewriteUnmodified(Request $request): Response {
    // Assert that there is an existing session with stacked handler trace data.
    $session = $request->getSession();
    assert(
      is_int($_SESSION['trace-handler']) && $_SESSION['trace-handler'] > 0,
      is_int($session->get('trace-handler')) && $session->get('trace-handler') > 0,
      'Existing stacked session handler trace not found'
    );

@@ -199,7 +171,7 @@ public function traceHandlerRewriteUnmodified(Request $request) {
      ini_get('session.lazy_write'),
      'session.lazy_write must be enabled to invoke updateTimestamp()'
    );
    $request->getSession()->save();
    $session->save();

    // Collect traces and return them in JSON format.
    $trace = \Drupal::service('session_test.session_handler_proxy_trace')->getArrayCopy();
@@ -212,11 +184,8 @@ public function traceHandlerRewriteUnmodified(Request $request) {
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   A response object containing the session values and the user ID.
   */
  public function getSession(Request $request) {
  public function getSession(Request $request): Response {
    return new JsonResponse(['session' => $request->getSession()->all(), 'user' => $this->currentUser()->id()]);
  }

@@ -227,11 +196,8 @@ public function getSession(Request $request) {
   *   The request object.
   * @param string $test_value
   *   A value to set on the session.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   A response object containing the session values and the user ID.
   */
  public function setSession(Request $request, $test_value) {
  public function setSession(Request $request, $test_value): Response {
    $session = $request->getSession();
    $session->set('test_value', $test_value);
    return new JsonResponse(['session' => $session->all(), 'user' => $this->currentUser()->id()]);
@@ -242,11 +208,8 @@ public function setSession(Request $request, $test_value) {
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   The response object.
   */
  public function setSessionBagFlag(Request $request) {
  public function setSessionBagFlag(Request $request): Response {
    /** @var \Drupal\session_test\Session\TestSessionBag */
    $bag = $request->getSession()->getBag(TestSessionBag::BAG_NAME);
    $bag->setFlag();
@@ -258,11 +221,8 @@ public function setSessionBagFlag(Request $request) {
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   The response object.
   */
  public function clearSessionBagFlag(Request $request) {
  public function clearSessionBagFlag(Request $request): Response {
    /** @var \Drupal\session_test\Session\TestSessionBag */
    $bag = $request->getSession()->getBag(TestSessionBag::BAG_NAME);
    $bag->clearFlag();
@@ -274,11 +234,8 @@ public function clearSessionBagFlag(Request $request) {
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   The response object.
   */
  public function hasSessionBagFlag(Request $request) {
  public function hasSessionBagFlag(Request $request): Response {
    /** @var \Drupal\session_test\Session\TestSessionBag */
    $bag = $request->getSession()->getBag(TestSessionBag::BAG_NAME);
    return new Response(empty($bag->hasFlag())
@@ -293,7 +250,7 @@ public function hasSessionBagFlag(Request $request) {
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   */
  public function triggerWriteException(Request $request) {
  public function triggerWriteException(Request $request): Response {
    $session = $request->getSession();
    $session->set('test_value', 'Ensure session contains some data');

Loading