Problem/Motivation

In #2542050: Toolbar implementation creates super annoying re-rendering. Toolbar added the following code:


/**
 * Implements hook_preprocess_HOOK() for HTML document templates.
 */
function toolbar_preprocess_html(&$variables) {
  if (!\Drupal::currentUser()->hasPermission('access toolbar')) {
    return;
  }

  $variables['attributes'] = new Attribute($variables['attributes']);
  $variables['attributes']->addClass(['toolbar-tray-open', 'toolbar-horizontal', 'toolbar-fixed', 'toolbar-loading']);
}

Up to this point $variables['attributes'] is an array instead of an object. hook_preprocess_html functions in themes might expect the variable to be an array instead of ArrayAccess object since this change was introduced in 8.4.0.

This also makes theming fragile because depending on whether Toolbar module is enabled or not, the variable will be ArrayAccess object or an array.

Proposed resolution

Use the existing array to add classes rather than converting the array to an Attribute object.

Remaining tasks

  1. Write a patch
  2. Agree on how to handle the BC break
  3. Review
  4. Commit

User interface changes

None.

API changes

'attributes' variable in hook_preprocess_html will be always an array instead of Attribute object.

Data model changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

bojan_dev created an issue. See original summary.

bojan_dev’s picture

idebr’s picture

Status: Active » Needs review
idebr’s picture

Updated the issue summary to expand on the issue at hand.

idebr’s picture

Issue summary: View changes

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

idebr’s picture

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

The patch in #2 solves the fatal error in our custom theme implementing hook_preprocess_html() after updating to Drupal 8.4.0

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

Well now we're in the worst of all worlds because there might code out there assuming this is an attribute :(

@idebr since Attribute implements ArrayAccess it'd be great if this issue detailed what your custom theme is doing in hook_preprocess_html()?

idebr’s picture

Re #8

Well now we're in the worst of all worlds because there might code out there assuming this is an attribute :(

Correct, currently $variables['attributes'] in hook_preprocess_html() may be an array or Attribute depending on where the hook is implemented. Assuming a stock Drupal installation where hooks are called in order of modules, themes and then by alphabet:

  1. For module implementations where the hook starts with an a[...] through toolbar[...], $variables['attributes'] is an array
  2. For module implementations after toolbar and themes, $variables['attributes'] is an Attribute

@idebr since Attribute implements ArrayAccess it'd be great if this issue detailed what your custom theme is doing in hook_preprocess_html()?

The project consists of a multisite installation with a custom theme for the corporate site with a subtheme for its intranet. The intranet theme is stripped from flashy content, since its main focus is to provide textual content.

The following code:

/**
 * Implements hook_preprocess_HOOK().
 */
function intranet_preprocess_html(&$variables) {
  $swoosh_class_index = isset($variables['attributes']['class']) ? array_search('page--with-swoosh-photo', $variables['attributes']['class']) : FALSE;
  if ($swoosh_class_index !== FALSE) {
    unset($variables['attributes']['class'][$swoosh_class_index]);
  }
}

resulted in the following notice:

Warning: array_search() expects parameter 2 to be array, object given in intranet_preprocess_html() (line 95 of themes/custom/intranet/intranet.theme).

idebr’s picture

Status: Needs review » Reviewed & tested by the community

@alexpott Did the additional information help at all? Tentatively updating status back to RTBC, since coding around switching data types makes coding in this area prone to errors.

lauriii’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs release manager review

Thank you @bojan_dev for opening the issue and creating the patch, and thank you @idebr for a clear explanation of the problem. Sorry for both of you that it has taken so long to provide feedback on this issue.

I discussed this issue today with @alexpott. We agreed that there are two possible ways to proceed with this:

  1. Document a known workaround for the bug and make a proper fix in the next major release. If we leave the code as is, themes and modules are prone to errors when enabling or disabling toolbar module. Reason to consider this option is that it wouldn't at least immediately break any sites.
  2. Fix the issue as proposed on this issue by removing the array to Attribute object conversion. This is a BC break which should be documented in a change record. Any modules or themes that assume that the attributes array item type is Attribute are affected. This change could also affect any modules or themes that have worked around this bug already.

According to our Drupal 8 backwards compatibility and internal API policy, preprocess function values can be changed. Given that the policy would allow us to make the code change, and the fact that the bug fix is reverting a relatively recent change, I'm leaning towards suggesting to proceed with the option 2.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

idebr’s picture

Title: Toolbar is messing up attributes in preprocess_html » toolbar_preprocess_html() converts attributes from array to Attribute object

I added a draft change record for #11.2 at https://www.drupal.org/node/3002434

idebr’s picture

lauriii’s picture

Issue summary: View changes

I updated the issue summary with more information.

Sadly I still cannot think of a way to fix this without any disruption. However, In my opinion, we cannot leave the code as it is. The fact that Toolbar module changes the type of the 'attribute' variable into Attribute object makes theming fragile because some themes might incorrectly expect the variable to be Attribute object, which it isn't consistently since it depends on whether Toolbar module is enabled or not. Some themes might have already built code that relies on 'attributes' being Attribute object, but in fact, that code is broken at the moment since it creates dependency on Toolbar module being enabled.

Hopefully, in future, we will run some type checks for variables: #3016948: Type check theme variables, but in the meanwhile, we just have to be more careful to not introduce this kind of changes.

markhalliwell’s picture

Given the Drupal Core frontend BC policy, I think option #11.2 is sufficient. Any decent theme should be prepared to handle either an array or Attribute object; that's what the Drupal Bootstrap base theme does.

The CR is a little muddy though...

For a consistent developer experience, the 'attributes' variable in html.html.twig is now consistently an array.

This seems to imply that the Twig template variable would suddenly become an array. This isn't true as ThemeManager::render ensures that 'attributes', 'title_attributes', 'content_attributes' all become Attribute objects prior to Twig template rendering.

lauriii’s picture

Thank you for the review @markcarver! I agree that the change record could use some more clarity, so I went ahead and updated it. Feel free to take another look at that.

markhalliwell’s picture

FileSize
1.18 KB

CR looks good to me.

Was planning on marking this as RTBC, but it seems there still needs to be a release manager review?

Also, seems a bit unnecessary to have this be an array + foreach loop; they can just be simple additions... here's a new patch (no interdiff, patch is extremely tiny).

lauriii’s picture

+1 on the new patch.

Lendude’s picture

Status: Needs review » Reviewed & tested by the community

Looks we have a concession here that #11.2 is the way to go (I agree too), lets see if a release manager agrees :)

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 18: 2917653-18.patch, failed testing. View results

markhalliwell’s picture

Status: Needs work » Reviewed & tested by the community

Seems like a random test failure.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 18: 2917653-18.patch, failed testing. View results

markhalliwell’s picture

Status: Needs work » Reviewed & tested by the community

Another random test failure...

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 18: 2917653-18.patch, failed testing. View results

idebr’s picture

Status: Needs work » Reviewed & tested by the community

Testbot:
15 Feb 2019 at 13:19 CET: PHP 7 & MySQL 5.5 Build Successful

dww’s picture

Sadly, the testbot got all kinds of confused yesterday. I've had to re-upload patches to a number of issues to unstick weirdness. Agreed #18 is RTBC. Here it is again. This should get the testbot to stop marking this needs work.

  • catch committed c5b88d8 on 8.7.x
    Issue #2917653 by markcarver, bojan_dev, dww, idebr, lauriii:...
catch’s picture

Version: 8.6.x-dev » 8.7.x-dev
Status: Reviewed & tested by the community » Fixed

Agreed on changing this back, at the moment it depends when your hook is fired and whether toolbar is enabled, so could affect any new site seemingly at random. With the patch applied, we have consistent behaviour that won't affect new sites and would only affect a subsection of existing sites that have adapted to the bug since 8.4...

Committed c5b88d8 and pushed to 8.7.x. Thanks!

dww’s picture

Version: 8.7.x-dev » 8.6.x-dev
Status: Fixed » Reviewed & tested by the community
Issue tags: +Needs change record updates

We can haz backport? ;) Maybe too disruptive in a patch release. But I don't see any explicit mention that this had to wait for a minor release, and @lauriii participated here multiple times. I would have assumed they would have said so if this wasn't backportable. ;) The issue lived on the 8.6.x branch for quite a while, and that's what we were testing against.

Thoughts?

Thanks,
-Derek

p.s. CR needs updates to clarify the version(s) where this is fixed, and to be published.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 27: 2917653-27.18-again.patch, failed testing. View results

dww’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
801 bytes

Sad, sad confused bot. :/ Here's #18/#27 yet again. A raw git diff this time, without the commit metadata.

lauriii’s picture

Version: 8.6.x-dev » 8.7.x-dev
Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs release manager review, -Needs change record updates

I think this bug fix is too risky to be included in a patch release since some modules and themes built after 8.4.0 might have to be updated. I updated the CR and published it!

dww’s picture

Okay, sounds good. Thanks for being explicit (and fixing/publishing the CR!).

Cheers,
-Derek

Status: Fixed » Closed (fixed)

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