diff --git a/core/core.services.yml b/core/core.services.yml index f91e5976f3..4c4e49bc0b 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1150,6 +1150,10 @@ services: tags: - { name: event_subscriber } arguments: ['@resolver_manager.entity'] + ajax.ajax_page_state_listener: + class: Drupal\Core\Ajax\AjaxPageStateSubscriber + tags: + - { name: 'event_subscriber' } ajax_response.subscriber: class: Drupal\Core\EventSubscriber\AjaxResponseSubscriber arguments: ['@ajax_response.attachments_processor'] diff --git a/core/lib/Drupal/Core/Ajax/AjaxPageStateSubscriber.php b/core/lib/Drupal/Core/Ajax/AjaxPageStateSubscriber.php new file mode 100644 index 0000000000..4d24246980 --- /dev/null +++ b/core/lib/Drupal/Core/Ajax/AjaxPageStateSubscriber.php @@ -0,0 +1,44 @@ +getRequest(); + if ($request->request->has('ajax_page_state')) { + $ajax_page_state = $request->request->get('ajax_page_state'); + $ajax_page_state = json_decode(UrlHelper::uncompressQueryParameter($ajax_page_state), TRUE); + $request->request->set('ajax_page_state', $ajax_page_state); + } + if ($request->query->has('ajax_page_state')) { + $ajax_page_state = $request->query->get('ajax_page_state'); + $ajax_page_state = json_decode(UrlHelper::uncompressQueryParameter($ajax_page_state), TRUE); + $request->query->set('ajax_page_state', $ajax_page_state); + $request->request->set('ajax_page_state', $ajax_page_state); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents(): array { + $events[KernelEvents::REQUEST][] = ['onRequest']; + return $events; + } + +} diff --git a/core/lib/Drupal/Core/Asset/AssetResolver.php b/core/lib/Drupal/Core/Asset/AssetResolver.php index 42b51c39d8..0eaf6e8dee 100644 --- a/core/lib/Drupal/Core/Asset/AssetResolver.php +++ b/core/lib/Drupal/Core/Asset/AssetResolver.php @@ -4,6 +4,7 @@ use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\NestedArray; +use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Language\LanguageManagerInterface; @@ -325,6 +326,11 @@ public function getJsAssets(AttachedAssetsInterface $assets, $optimize, Language // Update the $assets object accordingly, so that it reflects the final // settings. $assets->setSettings($settings); + // Convert ajaxPageState to a compressed string from an array, since it is + // used by ajax.js to pass to AJAX requests as a query parameter. + if (isset($settings['ajaxPageState'])) { + $settings['ajaxPageState'] = UrlHelper::compressQueryParameter(json_encode($settings['ajaxPageState'])); + } $settings_as_inline_javascript = [ 'type' => 'setting', 'group' => JS_SETTING, diff --git a/core/misc/ajax.js b/core/misc/ajax.js index 32d8cf08ac..b56b471923 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -824,13 +824,11 @@ // Allow Drupal to return new JavaScript and CSS files to load without // returning the ones already loaded. + // @see \Drupal\Core\Ajax\AjaxPageStateSubscriber // @see \Drupal\Core\Theme\AjaxBasePageNegotiator // @see \Drupal\Core\Asset\LibraryDependencyResolverInterface::getMinimalRepresentativeSubset() // @see system_js_settings_alter() - const pageState = drupalSettings.ajaxPageState; - options.data['ajax_page_state[theme]'] = pageState.theme; - options.data['ajax_page_state[theme_token]'] = pageState.theme_token; - options.data['ajax_page_state[libraries]'] = pageState.libraries; + options.data.ajax_page_state = drupalSettings.ajaxPageState; }; /** diff --git a/core/modules/big_pipe/tests/src/Functional/BigPipeTest.php b/core/modules/big_pipe/tests/src/Functional/BigPipeTest.php index 246cd47a64..09c612a7a4 100644 --- a/core/modules/big_pipe/tests/src/Functional/BigPipeTest.php +++ b/core/modules/big_pipe/tests/src/Functional/BigPipeTest.php @@ -184,7 +184,7 @@ public function testBigPipe() { // Verifying BigPipe assets are present. $this->assertNotEmpty($this->getDrupalSettings()); - $this->assertContains('big_pipe/big_pipe', explode(',', $this->getDrupalSettings()['ajaxPageState']['libraries']), 'BigPipe asset library is present.'); + $this->assertContains('big_pipe/big_pipe', explode(',', $this->getDrupalSettingsUncompressed()['ajaxPageState']['libraries']), 'BigPipe asset library is present.'); // Verify that the two expected exceptions are logged as errors. $this->assertEquals($log_count + 2, (int) $connection->select('watchdog')->countQuery()->execute()->fetchField(), 'Two new watchdog entries.'); diff --git a/core/modules/comment/tests/src/Functional/CommentCSSTest.php b/core/modules/comment/tests/src/Functional/CommentCSSTest.php index 5ad9c93248..1b3169e2d1 100644 --- a/core/modules/comment/tests/src/Functional/CommentCSSTest.php +++ b/core/modules/comment/tests/src/Functional/CommentCSSTest.php @@ -89,7 +89,7 @@ public function testCommentClasses() { } // Request the node with the comment. $this->drupalGet('node/' . $node->id()); - $settings = $this->getDrupalSettings(); + $settings = $this->getDrupalSettingsUncompressed(); // Verify the data-history-node-id attribute, which is necessary for the // by-viewer class and the "new" indicator, see below. diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index 4bb41d8f71..8f1404cb55 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -8,6 +8,7 @@ use Behat\Mink\Selector\SelectorsHandler; use Behat\Mink\Session; use Drupal\Component\Serialization\Json; +use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Database\Database; use Drupal\Core\Test\FunctionalTestSetupTrait; use Drupal\Core\Test\TestSetupTrait; @@ -624,6 +625,21 @@ protected function getDrupalSettings() { return []; } + /** + * Gets the value of drupalSettings with ajaxPageState uncompressed. + * + * @return array + * The Drupal settings array, with the ajaxPageState key uncompressed. + */ + protected function getDrupalSettingsUncompressed() { + $settings = $this->getDrupalSettings(); + if (isset($settings['ajaxPageState'])) { + $settings['ajaxPageState'] = json_decode(UrlHelper::uncompressQueryParameter($settings['ajaxPageState']), 1); + } + return $settings; + } + + /** * Retrieves the current calling line in the class under test. *