Problem/Motivation

Without spending all of the time to find out historically why this was done, or to think through all implications of this change, I believe that AjaxBasePageNegotiator is too restrictive.

It's stated intent is to prevent CSS from loading from two different themes on an Ajax request.
However, in order to do that, the route must declare _theme: ajax_base_page in its route options.
And if there are multiple modals in a row, each route must declare this.

However, the route author should not need to know in advance that the route would be used in a modal, it should Just Work™.

Proposed resolution

Remove the explicit check for _theme: ajax_base_page and instead use the check for ajax_page_state.

Remaining tasks

Needs manual testing:
Verify that Quick Edit still works fine, both when using Seven as the admin theme and Bartik as the default theme, and when Bartik is the default and admin theme.

User interface changes

N/A

API changes

Possibly?

Data model changes

N/A

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tim.plunkett created an issue. See original summary.

tim.plunkett’s picture

Status: Active » Needs review
FileSize
1.35 KB
dawehner’s picture

I agree, it doesn't really make sense.
Should this issue remove the other instances of it in core?

tim.plunkett’s picture

I don't see why not.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs tests

NIce, it returned green. I guess we still have tests for the general feature. I guess we need a change record for that?

tim.plunkett’s picture

Status: Reviewed & tested by the community » Needs work

I'm a little worried about this change.
I uploaded this change to a test issue, and it passed:

diff --git a/core/lib/Drupal/Core/Theme/AjaxBasePageNegotiator.php b/core/lib/Drupal/Core/Theme/AjaxBasePageNegotiator.php
index 261cedf..59b4f53 100644
--- a/core/lib/Drupal/Core/Theme/AjaxBasePageNegotiator.php
+++ b/core/lib/Drupal/Core/Theme/AjaxBasePageNegotiator.php
@@ -67,10 +67,7 @@ public function __construct(CsrfTokenGenerator $token_generator, ConfigFactoryIn
    * {@inheritdoc}
    */
   public function applies(RouteMatchInterface $route_match) {
-    // Check whether the route was configured to use the base page theme.
-    return ($route = $route_match->getRouteObject())
-      && $route->hasOption('_theme')
-      && $route->getOption('_theme') == 'ajax_base_page';
+    return FALSE;
   }
 
   /**

To me that indicates that we have NO test coverage for this functionality.

Wim Leers’s picture

However, the route author should not need to know in advance that the route would be used in a modal, it should Just Work™.

This is an excellent, excellent point.

I think this is really just a remnant from D7 and before. We now have the ability to render anything in a modal. Which means it'd be even wrong to set _theme: ajax_base_page in those cases!

To me that indicates that we have NO test coverage for this functionality.

I'm not surprised, our test coverage for AJAX/dialog/modal is poor. :( Because it stems from D7 and before.

pwolanin’s picture

What would some minimal test coverage look like here? Obviously the JS testing isn't in place enough I don't think to actually test the ajax?

tim.plunkett’s picture

Here's a unit test.

This needs some manual testing from someone not me:

Verify that Quick Edit still works fine, both when using Seven as the admin theme and Bartik as the default theme, and when Bartik is the default and admin theme.

tim.plunkett’s picture

Status: Needs work » Needs review
davidhernandez’s picture

I tried quick edit with multiple themes set on the front end and back end. I didn't notice any difference in functionality.

The last submitted patch, 9: 2745953-ajax-9-FAIL.patch, failed testing.

dawehner’s picture

Did some manual testing , and well, as you see, the right theme is used.


Obviously the JS testing isn't in place enough I don't think to actually test the ajax?

This statement is obviously wrong ;)

Note: The interdiff and the fail patch are identical.

The last submitted patch, 13: 2745953-FAIL.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 13: 2745953-13.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
3.63 KB
3.63 KB
13.04 KB

Missing @group. Note, the interdiff is still relative to #9

The last submitted patch, 16: 2745953-FAIL.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 16: 2745953-15.patch, failed testing.

Wim Leers’s picture

  1. +++ b/core/modules/system/tests/modules/ajax_test/src/Controller/AjaxTestController.php
    @@ -6,6 +6,7 @@
    +use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
    

    This is not used anywhere.

  2. +++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxThemeTest.php
    @@ -0,0 +1,45 @@
    + * Ensures that ajax themes are rendered in the frontend theme.
    

    Tests that AJAX responses use the current theme.

  3. +++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxThemeTest.php
    @@ -0,0 +1,45 @@
    +  ¶
    

    Whitespace nit.

dawehner’s picture

Status: Needs work » Needs review
FileSize
3.09 KB
3.85 KB
13.26 KB

Thank you wim!

Do you sometimes have these moments when you really question how it could have passed locally?

The last submitted patch, 20: 2745953-FAIL.patch, failed testing.

pwolanin’s picture

+++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxThemeTest.php
@@ -0,0 +1,55 @@
+    file_put_contents('/tmp/foo.png', $this->getSession()->getScreenshot());
+    file_put_contents('/tmp/foo.html', $this->getSession()->getPage()->getHtml());

This is leftover debug code?

dawehner’s picture

Sure, totally.

Wim Leers’s picture

Do you sometimes have these moments when you really question how it could have passed locally?

Too often!

+++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxThemeTest.php
@@ -27,19 +28,28 @@ public function testAjaxWithAdminRoute() {
+    $this->assertJsCondition($condition, 10000);

10 seconds?!

dawehner’s picture

10 seconds?!

Yeah not sure about this value. I just copied it from \Drupal\Tests\views\FunctionalJavascript\ExposedFilterAJAXTest::waitForAjaxToFinish. Note: this is also just a timeout when the actual functionality doesn't work.

tim.plunkett’s picture

Opened #2747863: Move \Drupal\Tests\views\FunctionalJavascript\ExposedFilterAJAXTest::waitForAjaxToFinish to \Drupal\FunctionalJavascriptTests\JavascriptTestBase about moving that helper method to the base class. Then we'll have one place to decide on whether 10 seconds is too much.

dawehner’s picture

Sure, there we go.

dawehner’s picture

FileSize
801 bytes

Here is the interdiff

tim.plunkett’s picture

The changes since #9, my patch, look great!
Can someone provide a final review?

dawehner’s picture

I'm RTBC for everything beside the test. If someone else gives a +1 for the test I'm super happy.

Wim Leers’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Theme/AjaxBasePageNegotiator.php
    @@ -67,17 +65,15 @@ public function __construct(CsrfTokenGenerator $token_generator, ConfigFactoryIn
    -    if (($ajax_page_state = $this->requestStack->getCurrentRequest()->request->get('ajax_page_state'))  && !empty($ajax_page_state['theme']) && !empty($ajax_page_state['theme_token'])) {
    +    if ($ajax_page_state = $this->requestStack->getCurrentRequest()->request->get('ajax_page_state')) {
    

    Hm… we remove those two conditions because the applies() check already tests them for us.

    But that makes the code read strangely now: it looks as if we don't care if the 'theme' and 'theme_token' array keys exist.

    I think this can be much simplified: remove the condition altogether. And just do

    $ajax_page_state = …
    $theme = …
    $theme_token = …
    

    … because the applies() check already ensures this is only called if all those things exist.

    This may seem a nit, but IMO makes the code more maintainable long-term.

  2. +++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxThemeTest.php
    @@ -0,0 +1,53 @@
    +    // First visit the site directly via the URL. This should render it in the
    +    // admin theme.
    ...
    +    // Now
    

    Second comment is incomplete.

When those things are addressed, I agree with RTBC.

tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
2.51 KB
14.23 KB

Agreed!

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you tim!

Wim Leers’s picture

+++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxThemeTest.php
@@ -32,7 +32,7 @@ public function testAjaxWithAdminRoute() {
+    // Now click the modal, which should use also use the admin theme.

"use also use" :)

Can be fixed on commit.

RTBC++

tim.plunkett’s picture

Just fixing the nits now to streamline it for the committers :)

Wim Leers’s picture

Nice, even more nits fixed than I noticed :P

dawehner’s picture

@tim.plunkett++
Yeah I better setup storm to yell at me.

tim.plunkett’s picture

This is ready, but I think either catch or alexpott should be the one to commit it.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: -Needs framework manager review +Needs change record

The change looks good and I can't see any security issues that would be brought about by this change and it is great to have the additional test coverage. I think we should have a change record for this change and also search existing ones that might need an update + docs.

alexpott’s picture

Issue tags: +8.2.0 release notes

Fox example https://www.drupal.org/node/2122201 will need an update for 8.2.x

tim.plunkett’s picture

Status: Needs work » Needs review
Issue tags: -Needs change record

Wrote https://www.drupal.org/node/2752989, that handbook page in #40 is the only one I could find. I will update those docs once this is committed.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

@tim.plunkett: CR looks great, but IMO you can already make the changes to https://www.drupal.org/node/2122201. We need those docs to work for both D8.0/8.1 and >=8.2. So we need to mention both. What I've been doing is <sup>Since 8.2.0</sup> for version-specific things. For example: https://www.drupal.org/node/2617470/revisions/view/9118520/9372512 for https://www.drupal.org/developing/api/8/ckeditor.

No other CRs talk about this, at least not according to https://www.drupal.org/list-changes/drupal/published?keywords_descriptio..., so #39 is addressed.

tim.plunkett’s picture

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed c2b2864 and pushed to 8.2.x. Thanks!

  • alexpott committed c2b2864 on 8.2.x
    Issue #2745953 by dawehner, tim.plunkett, Wim Leers:...
Wim Leers’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

xjm’s picture

Issue tags: -8.2.0 release notes

This didn't really seem to fit in the release notes, but feel free to retag if I've missed some importance. A CR seems sufficient.