Skip to content
Snippets Groups Projects
Verified Commit 9334d6f1 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3109970 by znerol, andypost, Prashant.c, daffie, Wim Leers, dww, catch:...

Issue #3109970 by znerol, andypost, Prashant.c, daffie, Wim Leers, dww, catch: Convert uses of $_SESSION in forms and batch
parent 4add05d0
No related branches found
No related tags found
29 merge requests!11131[10.4.x-only-DO-NOT-MERGE]: Issue ##2842525 Ajax attached to Views exposed filter form does not trigger callbacks,!9470[10.3.x-only-DO-NOT-MERGE]: #3331771 Fix file_get_contents(): Passing null to parameter,!8540Issue #3457061: Bootstrap Modal dialog Not closing after 10.3.0 Update,!8528Issue #3456871 by Tim Bozeman: Support NULL services,!8373Issue #3427374 by danflanagan8, Vighneshh: taxonomy_tid ViewsArgumentDefault...,!7526Expose roles in response,!7352Draft: Resolve #3203489 "Set filename as",!3878Removed unused condition head title for views,!3818Issue #2140179: $entity->original gets stale between updates,!3742Issue #3328429: Create item list field formatter for displaying ordered and unordered lists,!3731Claro: role=button on status report items,!3651Issue #3347736: Create new SDC component for Olivero (header-search),!3531Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!3355Issue #3209129: Scrolling problems when adding a block via layout builder,!3154Fixes #2987987 - CSRF token validation broken on routes with optional parameters.,!3133core/modules/system/css/components/hidden.module.css,!2964Issue #2865710 : Dependencies from only one instance of a widget are used in display modes,!2812Issue #3312049: [Followup] Fix Drupal.Commenting.FunctionComment.MissingReturnType returns for NULL,!2794Issue #3100732: Allow specifying `meta` data on JSON:API objects,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2062Issue #3246454: Add weekly granularity to views date sort,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!877Issue #2708101: Default value for link text is not saved,!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493
Pipeline #122218 canceled
Pipeline: drupal

#122219

    ......@@ -474,11 +474,14 @@ function _batch_finished() {
    }
    }
    // Clean-up the session. Not needed for CLI updates.
    if (isset($_SESSION)) {
    unset($_SESSION['batches'][$batch['id']]);
    if (empty($_SESSION['batches'])) {
    unset($_SESSION['batches']);
    }
    $session = \Drupal::request()->getSession();
    $batches = $session->get('batches', []);
    unset($batches[$batch['id']]);
    if (empty($batches)) {
    $session->remove('batches');
    }
    else {
    $session->set('batches', $batches);
    }
    }
    $_batch = $batch;
    ......@@ -531,7 +534,8 @@ function _batch_finished() {
    // form needs to be rebuilt, save the final $form_state for
    // \Drupal\Core\Form\FormBuilderInterface::buildForm().
    if ($_batch['form_state']->isRebuilding()) {
    $_SESSION['batch_form_state'] = $_batch['form_state'];
    $session = \Drupal::request()->getSession();
    $session->set('batch_form_state', $_batch['form_state']);
    }
    $callback = $_batch['redirect_callback'];
    $_batch['source_url']->mergeOptions(['query' => ['op' => 'finish', 'id' => $_batch['id']]]);
    ......
    ......@@ -612,7 +612,7 @@ function template_preprocess_form_element_label(&$variables) {
    * // The following keys allow for multi-step operations :
    * // 'sandbox' (read / write): An array that can be freely used to
    * // store persistent data between iterations. It is recommended to
    * // use this instead of $_SESSION, which is unsafe if the user
    * // use this instead of the session, which is unsafe if the user
    * // continues browsing in a separate window while the batch is processing.
    * // 'finished' (write): A float number between 0 and 1 informing
    * // the processing engine of the completion level for the operation.
    ......@@ -669,11 +669,12 @@ function template_preprocess_form_element_label(&$variables) {
    * $message = t('Finished with an error.');
    * }
    * \Drupal::messenger()->addMessage($message);
    * // Providing data for the redirected page is done through $_SESSION.
    * // Providing data for the redirected page is done through the session.
    * foreach ($results as $result) {
    * $items[] = t('Loaded node %title.', array('%title' => $result));
    * }
    * $_SESSION['my_batch_results'] = $items;
    * $session = \Drupal::getRequest()->getSession();
    * $session->set('my_batch_results', $items);
    * }
    * @endcode
    */
    ......@@ -718,7 +719,7 @@ function template_preprocess_form_element_label(&$variables) {
    * - finished: Name of an implementation of callback_batch_finished(). This is
    * executed after the batch has completed. This should be used to perform
    * any result massaging that may be needed, and possibly save data in
    * $_SESSION for display after final page redirection.
    * the session for display after final page redirection.
    * - file: Path to the file containing the definitions of the 'operations' and
    * 'finished' functions, for instance if they don't reside in the main
    * .module file. The path should be relative to base_path(), and thus should
    ......@@ -952,7 +953,10 @@ function batch_process($redirect = NULL, Url $url = NULL, $redirect_callback = N
    \Drupal::service(BatchStorageInterface::class)->create($batch);
    // Set the batch number in the session to guarantee that it will stay alive.
    $_SESSION['batches'][$batch['id']] = TRUE;
    $session = \Drupal::request()->getSession();
    $batches = $session->get('batches', []);
    $batches[$batch['id']] = TRUE;
    $session->set('batches', $batches);
    // Redirect for processing.
    $query_options = $error_url->getOption('query');
    ......
    ......@@ -251,11 +251,13 @@ public function buildForm($form_arg, FormStateInterface &$form_state) {
    $form_state->setUserInput($input);
    }
    if (isset($_SESSION['batch_form_state'])) {
    // @todo Remove hasSession() condition in https://www.drupal.org/i/3413153
    if ($request->hasSession() && $request->getSession()->has('batch_form_state')) {
    // We've been redirected here after a batch processing. The form has
    // already been processed, but needs to be rebuilt. See _batch_finished().
    $form_state = $_SESSION['batch_form_state'];
    unset($_SESSION['batch_form_state']);
    $session = $request->getSession();
    $form_state = $session->get('batch_form_state');
    $session->remove('batch_form_state');
    return $this->rebuildForm($form_id, $form_state);
    }
    ......
    ......@@ -431,8 +431,23 @@ protected function assertBigPipePlaceholders(array $expected_big_pipe_placeholde
    * Ensures CSRF tokens can be generated for the current user's session.
    */
    protected function setCsrfTokenSeedInTestEnvironment() {
    // Retrieve the CSRF token from the child site from its serialized session
    // record in the database.
    $session_data = $this->container->get('session_handler.write_safe')->read($this->getSession()->getCookie($this->getSessionName()));
    $csrf_token_seed = unserialize(explode('_sf2_meta|', $session_data)[1])['s'];
    // Ensure that the session is started before accessing a session bag.
    // Otherwise the value stored in the bag is lost when subsequent session
    // access triggers a session start automatically.
    /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */
    $request_stack = $this->container->get('request_stack');
    $session = $request_stack->getSession();
    if (!$session->isStarted()) {
    $session->start();
    }
    // Store the CSRF token in the test runners session metadata bag.
    $this->container->get('session_manager.metadata_bag')->setCsrfTokenSeed($csrf_token_seed);
    }
    ......
    ......@@ -88,9 +88,7 @@ public function getLangcode(Request $request = NULL) {
    if ($request->query->has($param)) {
    return $request->query->get($param);
    }
    // @todo Remove hasSession() from condition in
    // https://www.drupal.org/node/2484991
    if ($request->hasSession() && $request->getSession()->has($param)) {
    if ($request->getSession()->has($param)) {
    return $request->getSession()->get($param);
    }
    }
    ......
    ......@@ -13,7 +13,7 @@
    class SessionTestSubscriber implements EventSubscriberInterface {
    /**
    * Stores whether $_SESSION is empty at the beginning of the request.
    * Stores whether the session is empty at the beginning of the request.
    *
    * @var bool
    */
    ......
    ......@@ -403,7 +403,7 @@ public function assertSessionCookie(bool $sent): void {
    }
    /**
    * Assert whether $_SESSION is empty at the beginning of the request.
    * Assert whether the session is empty at the beginning of the request.
    *
    * @internal
    */
    ......
    ......@@ -4,7 +4,6 @@
    use Drupal\KernelTests\KernelTestBase;
    use Drupal\user\Entity\User;
    use Symfony\Component\HttpFoundation\Session\Session;
    /**
    * Verifies that the password reset behaves as expected with form elements.
    ......@@ -53,14 +52,8 @@ public function testPasswordResetToken() {
    /** @var \Symfony\Component\HttpFoundation\Request $request */
    $request = $this->container->get('request_stack')->getCurrentRequest();
    // @todo: Replace with $request->getSession() as soon as the session is
    // present in KernelTestBase.
    // see: https://www.drupal.org/node/2484991
    $session = new Session();
    $request->setSession($session);
    $token = 'VALID_TOKEN';
    $session->set('pass_reset_1', $token);
    $request->getSession()->set('pass_reset_1', $token);
    // Set token in query string.
    $request->query->set('pass-reset-token', $token);
    ......
    ......@@ -22,6 +22,8 @@
    use Symfony\Component\DependencyInjection\ContainerInterface;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\RequestStack;
    use Symfony\Component\HttpFoundation\Session\Session;
    use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
    /**
    * @coversDefaultClass \Drupal\Core\Form\FormBuilder
    ......@@ -575,6 +577,7 @@ public function testFormCacheDeletionUncached() {
    */
    public function testExceededFileSize() {
    $request = new Request([FormBuilderInterface::AJAX_FORM_REQUEST => TRUE]);
    $request->setSession(new Session(new MockArraySessionStorage()));
    $request_stack = new RequestStack();
    $request_stack->push($request);
    $this->formBuilder = $this->getMockBuilder('\Drupal\Core\Form\FormBuilder')
    ......@@ -598,6 +601,7 @@ public function testExceededFileSize() {
    public function testPostAjaxRequest(): void {
    $request = new Request([FormBuilderInterface::AJAX_FORM_REQUEST => TRUE], ['form_id' => 'different_form_id']);
    $request->setMethod('POST');
    $request->setSession(new Session(new MockArraySessionStorage()));
    $this->requestStack->push($request);
    $form_state = (new FormState())
    ......
    ......@@ -14,6 +14,8 @@
    use Drupal\Tests\UnitTestCase;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\RequestStack;
    use Symfony\Component\HttpFoundation\Session\Session;
    use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
    /**
    * Provides a base class for testing form functionality.
    ......@@ -184,6 +186,7 @@ protected function setUp(): void {
    $this->account = $this->createMock('Drupal\Core\Session\AccountInterface');
    $this->themeManager = $this->createMock('Drupal\Core\Theme\ThemeManagerInterface');
    $this->request = Request::createFromGlobals();
    $this->request->setSession(new Session(new MockArraySessionStorage()));
    $this->eventDispatcher = $this->createMock('Symfony\Contracts\EventDispatcher\EventDispatcherInterface');
    $this->requestStack = new RequestStack();
    $this->requestStack->push($this->request);
    ......
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Finish editing this message first!
    Please register or to comment