diff --git a/core/lib/Drupal/Core/Ajax/AjaxResponseAttachmentsProcessor.php b/core/lib/Drupal/Core/Ajax/AjaxResponseAttachmentsProcessor.php index a96e0e14dcf..d7a72b430fb 100644 --- a/core/lib/Drupal/Core/Ajax/AjaxResponseAttachmentsProcessor.php +++ b/core/lib/Drupal/Core/Ajax/AjaxResponseAttachmentsProcessor.php @@ -132,7 +132,7 @@ class AjaxResponseAttachmentsProcessor implements AttachmentsResponseProcessorIn * An array of commands ready to be returned as JSON. */ protected function buildAttachmentsCommands(AjaxResponse $response, Request $request) { - $ajax_page_state = $request->request->all('ajax_page_state'); + $ajax_page_state = $request->get('ajax_page_state'); // Aggregate CSS/JS if necessary, but only during normal site operation. $optimize_css = !defined('MAINTENANCE_MODE') && $this->config->get('css.preprocess'); diff --git a/core/lib/Drupal/Core/Render/Element/RenderElement.php b/core/lib/Drupal/Core/Render/Element/RenderElement.php index 627b041e048..5e1cc95e749 100644 --- a/core/lib/Drupal/Core/Render/Element/RenderElement.php +++ b/core/lib/Drupal/Core/Render/Element/RenderElement.php @@ -244,6 +244,7 @@ abstract class RenderElement extends PluginBase implements ElementInterface { * - #ajax['event'] * - #ajax['prevent'] * - #ajax['url'] + * - #ajax['type'] * - #ajax['callback'] * - #ajax['options'] * - #ajax['wrapper'] @@ -340,6 +341,7 @@ abstract class RenderElement extends PluginBase implements ElementInterface { // to be substantially different for a JavaScript triggered submission. $settings += [ 'url' => NULL, + 'type' => 'POST', 'options' => ['query' => []], 'dialogType' => 'ajax', ]; diff --git a/core/lib/Drupal/Core/Theme/AjaxBasePageNegotiator.php b/core/lib/Drupal/Core/Theme/AjaxBasePageNegotiator.php index f4eec9b7a1a..ff50dc3eb06 100644 --- a/core/lib/Drupal/Core/Theme/AjaxBasePageNegotiator.php +++ b/core/lib/Drupal/Core/Theme/AjaxBasePageNegotiator.php @@ -65,7 +65,7 @@ class AjaxBasePageNegotiator implements ThemeNegotiatorInterface { * {@inheritdoc} */ public function applies(RouteMatchInterface $route_match) { - $ajax_page_state = $this->requestStack->getCurrentRequest()->request->all('ajax_page_state'); + $ajax_page_state = $this->requestStack->getCurrentRequest()->get('ajax_page_state'); return !empty($ajax_page_state['theme']) && isset($ajax_page_state['theme_token']); } @@ -73,7 +73,7 @@ class AjaxBasePageNegotiator implements ThemeNegotiatorInterface { * {@inheritdoc} */ public function determineActiveTheme(RouteMatchInterface $route_match) { - $ajax_page_state = $this->requestStack->getCurrentRequest()->request->all('ajax_page_state'); + $ajax_page_state = $this->requestStack->getCurrentRequest()->get('ajax_page_state'); $theme = $ajax_page_state['theme']; $token = $ajax_page_state['theme_token']; diff --git a/core/misc/ajax.js b/core/misc/ajax.js index ec18625bf65..32d8cf08ac4 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -325,6 +325,13 @@ elementSettings.url = href; elementSettings.event = 'click'; } + const type = $linkElement.data('ajax-type'); + /** + * In case of setting custom ajax type for link we rewrite ajax.type. + */ + if (type) { + elementSettings.type = type; + } Drupal.ajax(elementSettings); }); }; @@ -391,6 +398,7 @@ */ Drupal.Ajax = function (base, element, elementSettings) { const defaults = { + type: 'POST', event: element ? 'mousedown' : null, keypress: true, selector: base ? `#${base}` : null, @@ -591,7 +599,7 @@ }, dataType: 'json', jsonp: false, - type: 'POST', + type: ajax.type, }; if (elementSettings.dialog) { diff --git a/core/modules/big_pipe/src/Render/BigPipe.php b/core/modules/big_pipe/src/Render/BigPipe.php index 0461890b714..75adfebe3a8 100644 --- a/core/modules/big_pipe/src/Render/BigPipe.php +++ b/core/modules/big_pipe/src/Render/BigPipe.php @@ -465,7 +465,7 @@ class BigPipe { // - the HTML to load the CSS can be rendered. // - the HTML to load the JS (at the top) can be rendered. $fake_request = $this->requestStack->getMainRequest()->duplicate(); - $fake_request->request->set('ajax_page_state', ['libraries' => implode(',', $cumulative_assets->getAlreadyLoadedLibraries())]); + $fake_request->query->set('ajax_page_state', ['libraries' => implode(',', $cumulative_assets->getAlreadyLoadedLibraries())]); try { $html_response = $this->filterEmbeddedResponse($fake_request, $html_response); } @@ -575,7 +575,7 @@ class BigPipe { // - the attachments associated with the response are finalized, which // allows us to track the total set of asset libraries sent in the // initial HTML response plus all embedded AJAX responses sent so far. - $fake_request->request->set('ajax_page_state', ['libraries' => implode(',', $cumulative_assets->getAlreadyLoadedLibraries())] + $cumulative_assets->getSettings()['ajaxPageState']); + $fake_request->query->set('ajax_page_state', ['libraries' => implode(',', $cumulative_assets->getAlreadyLoadedLibraries())] + $cumulative_assets->getSettings()['ajaxPageState']); try { $ajax_response = $this->filterEmbeddedResponse($fake_request, $ajax_response); } diff --git a/core/modules/views/js/ajax_view.js b/core/modules/views/js/ajax_view.js index bae75722339..6e30c173680 100644 --- a/core/modules/views/js/ajax_view.js +++ b/core/modules/views/js/ajax_view.js @@ -90,6 +90,7 @@ this.element_settings = { url: ajaxPath + queryString, submit: settings, + type: 'GET', setClick: true, event: 'click', selector, @@ -127,6 +128,7 @@ const selfSettings = $.extend({}, this.element_settings, { event: 'RefreshView', base: this.selector, + type: 'GET', element: this.$view.get(0), }); this.refreshViewAjax = Drupal.ajax(selfSettings); @@ -201,6 +203,7 @@ submit: viewData, base: false, element: link, + type: 'GET', }); this.pagerAjax = Drupal.ajax(selfSettings); }; diff --git a/core/modules/views/src/Controller/ViewAjaxController.php b/core/modules/views/src/Controller/ViewAjaxController.php index 1b0188982e5..67caeb62b9c 100644 --- a/core/modules/views/src/Controller/ViewAjaxController.php +++ b/core/modules/views/src/Controller/ViewAjaxController.php @@ -12,8 +12,6 @@ use Drupal\Core\EventSubscriber\AjaxResponseSubscriber; use Drupal\Core\EventSubscriber\MainContentViewSubscriber; use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Path\CurrentPathStack; -use Drupal\Core\Render\BubbleableMetadata; -use Drupal\Core\Render\RenderContext; use Drupal\Core\Render\RendererInterface; use Drupal\Core\Routing\RedirectDestinationInterface; use Drupal\Core\Ajax\ScrollTopCommand; @@ -112,10 +110,10 @@ class ViewAjaxController implements ContainerInjectionInterface { * Thrown when the view was not found. */ public function ajaxView(Request $request) { - $name = $request->request->get('view_name'); - $display_id = $request->request->get('view_display_id'); + $name = $request->get('view_name'); + $display_id = $request->get('view_display_id'); if (isset($name) && isset($display_id)) { - $args = $request->request->get('view_args', ''); + $args = $request->get('view_args', ''); $args = $args !== '' ? explode('/', Html::decodeEntities($args)) : []; // Arguments can be empty, make sure they are passed on as NULL so that @@ -124,10 +122,10 @@ class ViewAjaxController implements ContainerInjectionInterface { return ($arg == '' ? NULL : $arg); }, $args); - $path = $request->request->get('view_path'); - $dom_id = $request->request->get('view_dom_id'); + $path = $request->get('view_path'); + $dom_id = $request->get('view_dom_id'); $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL; - $pager_element = $request->request->get('pager_element'); + $pager_element = $request->get('pager_element'); $pager_element = isset($pager_element) ? intval($pager_element) : NULL; $response = new ViewAjaxResponse(); @@ -164,10 +162,9 @@ class ViewAjaxController implements ContainerInjectionInterface { $this->currentPath->setPath('/' . ltrim($path, '/'), $request); } - // Add all POST data, because AJAX is always a post and many things, + // Add all POST data, because AJAX is sometimes a POST and many things, // such as tablesorts, exposed filters and paging assume GET. $request_all = $request->request->all(); - unset($request_all['ajax_page_state']); $query_all = $request->query->all(); $request->query->replace($request_all + $query_all); @@ -190,16 +187,7 @@ class ViewAjaxController implements ContainerInjectionInterface { // Reuse the same DOM id so it matches that in drupalSettings. $view->dom_id = $dom_id; - $context = new RenderContext(); - $preview = $this->renderer->executeInRenderContext($context, function () use ($view, $display_id, $args) { - return $view->preview($display_id, $args); - }); - if (!$context->isEmpty()) { - $bubbleable_metadata = $context->pop(); - BubbleableMetadata::createFromRenderArray($preview) - ->merge($bubbleable_metadata) - ->applyTo($preview); - } + $preview = $view->preview($display_id, $args); $response->addCommand(new ReplaceCommand(".js-view-dom-id-$dom_id", $preview)); $response->addCommand(new PrependCommand(".js-view-dom-id-$dom_id", ['#type' => 'status_messages'])); diff --git a/core/modules/views/src/Form/ViewsForm.php b/core/modules/views/src/Form/ViewsForm.php index 766e366d134..8b274fe2c05 100644 --- a/core/modules/views/src/Form/ViewsForm.php +++ b/core/modules/views/src/Form/ViewsForm.php @@ -157,7 +157,7 @@ class ViewsForm implements FormInterface, ContainerInjectionInterface { $form = []; $query = $this->requestStack->getCurrentRequest()->query->all(); - $query = UrlHelper::filterQueryParameters($query, [], ''); + $query = UrlHelper::filterQueryParameters($query, ['_wrapper_format'], ''); $options = ['query' => $query]; $form['#action'] = $view->hasUrl() ? $view->getUrl()->setOptions($options)->toString() : Url::fromRoute('')->setOptions($options)->toString(); diff --git a/core/modules/views/tests/src/FunctionalJavascript/PaginationAJAXTest.php b/core/modules/views/tests/src/FunctionalJavascript/PaginationAJAXTest.php index 00454912af1..d4a73743320 100644 --- a/core/modules/views/tests/src/FunctionalJavascript/PaginationAJAXTest.php +++ b/core/modules/views/tests/src/FunctionalJavascript/PaginationAJAXTest.php @@ -98,8 +98,6 @@ class PaginationAJAXTest extends WebDriverTestBase { $this->assertCount(5, $rows); $this->assertStringContainsString('Node 6 content', $rows[0]->getHtml()); $link = $page->findLink('Go to page 3'); - // Test that no unwanted parameters are added to the URL. - $this->assertEquals('?status=All&type=All&langcode=All&items_per_page=5&order=changed&sort=asc&page=2', $link->getAttribute('href')); $this->assertNoDuplicateAssetsOnPage(); $this->clickLink('Go to page 3'); diff --git a/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php b/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php index af6f8a135e9..d6b881851a3 100644 --- a/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php +++ b/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php @@ -182,18 +182,18 @@ class ViewAjaxControllerTest extends UnitTestCase { */ public function testAjaxView() { $request = new Request(); - $request->request->set('view_name', 'test_view'); - $request->request->set('view_display_id', 'page_1'); - $request->request->set('view_path', '/test-page'); - $request->request->set('_wrapper_format', 'ajax'); - $request->request->set('ajax_page_state', 'drupal.settings[]'); - $request->request->set('type', 'article'); + $request->query->set('view_name', 'test_view'); + $request->query->set('view_display_id', 'page_1'); + $request->query->set('view_path', '/test-page'); + $request->query->set('_wrapper_format', 'ajax'); + $request->query->set('ajax_page_state', 'drupal.settings[]'); + $request->query->set('type', 'article'); [$view, $executable] = $this->setupValidMocks(); $this->redirectDestination->expects($this->atLeastOnce()) ->method('set') - ->with('/test-page?type=article'); + ->with('/test-page?ajax_page_state=drupal.settings%5B%5D&type=article'); $this->currentPath->expects($this->once()) ->method('setPath') ->with('/test-page', $request); @@ -211,18 +211,18 @@ class ViewAjaxControllerTest extends UnitTestCase { */ public function testAjaxViewViewPathNoSlash() { $request = new Request(); - $request->request->set('view_name', 'test_view'); - $request->request->set('view_display_id', 'page_1'); - $request->request->set('view_path', 'test-page'); - $request->request->set('_wrapper_format', 'ajax'); - $request->request->set('ajax_page_state', 'drupal.settings[]'); - $request->request->set('type', 'article'); + $request->query->set('view_name', 'test_view'); + $request->query->set('view_display_id', 'page_1'); + $request->query->set('view_path', 'test-page'); + $request->query->set('_wrapper_format', 'ajax'); + $request->query->set('ajax_page_state', 'drupal.settings[]'); + $request->query->set('type', 'article'); [$view, $executable] = $this->setupValidMocks(); $this->redirectDestination->expects($this->atLeastOnce()) ->method('set') - ->with('test-page?type=article'); + ->with('test-page?ajax_page_state=drupal.settings%5B%5D&type=article'); $this->currentPath->expects($this->once()) ->method('setPath') ->with('/test-page'); diff --git a/core/tests/Drupal/Tests/Core/Theme/AjaxBasePageNegotiatorTest.php b/core/tests/Drupal/Tests/Core/Theme/AjaxBasePageNegotiatorTest.php index 9c19f9ea68f..be5985da8a7 100644 --- a/core/tests/Drupal/Tests/Core/Theme/AjaxBasePageNegotiatorTest.php +++ b/core/tests/Drupal/Tests/Core/Theme/AjaxBasePageNegotiatorTest.php @@ -55,8 +55,10 @@ class AjaxBasePageNegotiatorTest extends UnitTestCase { * @dataProvider providerTestApplies */ public function testApplies($request_data, $expected) { - $request = new Request([], $request_data); - $request->request = new InputBag($request->request->all()); + $request = new Request(); + foreach ($request_data as $key => $data) { + $request->query->set($key, $data); + } $route_match = RouteMatch::createFromRequest($request); $this->requestStack->push($request); @@ -80,8 +82,8 @@ class AjaxBasePageNegotiatorTest extends UnitTestCase { $theme = 'claro'; $theme_token = 'valid_theme_token'; - $request = new Request([], ['ajax_page_state' => ['theme' => $theme, 'theme_token' => $theme_token]]); - $request->request = new InputBag($request->request->all()); + $request = new Request(); + $request->query->set('ajax_page_state', ['theme' => $theme, 'theme_token' => $theme_token]); $this->requestStack->push($request); $route_match = RouteMatch::createFromRequest($request); @@ -97,8 +99,8 @@ class AjaxBasePageNegotiatorTest extends UnitTestCase { public function testDetermineActiveThemeInvalidToken() { $theme = 'claro'; $theme_token = 'invalid_theme_token'; - - $request = new Request([], ['ajax_page_state' => ['theme' => $theme, 'theme_token' => $theme_token]]); + $request = new Request(); + $request->query->set('ajax_page_state', ['theme' => $theme, 'theme_token' => $theme_token]); $request->request = new InputBag($request->request->all()); $this->requestStack->push($request); $route_match = RouteMatch::createFromRequest($request); @@ -118,7 +120,8 @@ class AjaxBasePageNegotiatorTest extends UnitTestCase { // theme token. See system_js_settings_alter(). $theme_token = ''; - $request = new Request([], ['ajax_page_state' => ['theme' => $theme, 'theme_token' => $theme_token]]); + $request = new Request([]); + $request->query->set('ajax_page_state', ['theme' => $theme, 'theme_token' => $theme_token]); $request->request = new InputBag($request->request->all()); $this->requestStack->push($request); $route_match = RouteMatch::createFromRequest($request);