I need to add a class to form_element_label if it is of type radios or checkboxes. Since D8 this is no longer possible as $variables['element']['#type'] seems not defined in hook_preprocess_form_element_label().

function mytheme_preprocess_form_element_label(&$variables) {
  $element = $variables['element'];

  switch ($element['#type']) {
    case 'radios':
    case 'checkboxes':
      // Add custom label class to element labels.
      $variables['attributes']['class'][] = 'my-label';
      break;
  }
}

Can I add the #type somehow back in my theme or can core add it back, please?

Issue fork drupal-2640088

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

hass created an issue. See original summary.

hass’s picture

Tried adding #type into template_preprocess_form_element() at line 472

$variables['label'] += array_intersect_key($element, array_flip(array('#type', '#id', '#required', '#title', '#title_display')));

, but the added type makes Drupal running out of memory!?? No idea why adding #type makes Drupal running out of memory. It is just one more string.

swentel’s picture

Status: Active » Needs review
StatusFileSize
new595 bytes

Don't get it either why that goes out of memory, but something like in the attached patch works.

hass’s picture

Status: Needs review » Reviewed & tested by the community

I'm fine with this naming, but we need some feedback from core maitainers if this is acceptable. I'm not sure if we need to add an #parents with the original element and leave this extra key out than.

RTBC the patch for now.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

We should have some test coverage of this.

hass’s picture

How should the render array look like? Do you know why we cannot pass #type?

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

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

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

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

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

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

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

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

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

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.

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.

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

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

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

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

quietone’s picture

Status: Needs work » Postponed (maintainer needs more info)
Issue tags: +Bug Smash Initiative

There has been no discussion here for 8 years and much has changed since then. However, since I don't know the theme system I am asking if this is still relevant.

Is this relevant to Drupal 10?

Since we need more information to move forward with this issue, I am setting the status to Postponed (maintainer needs more info). If we don't receive additional information to help with the issue, it may be closed after three months.

Thanks!

bnjmnm’s picture

Status: Postponed (maintainer needs more info) » Active

Although this issue was filed when Force Awakens was #1 at the box office. I confirmed this is still an issue in mid-2024. As the long lifespan of this issue suggests, it's probably not an urgent matter but it would me nice for label preprocess to know the type of element they belong to.

Comment #2 seems like the right place to get this attribute added. If there are still memory issues like the ones reported 8 years ago, perhaps some xdebugging can sniff out the culprit.

As mentioned above, this will of course need some tests. I'm guessing there is an existing test that can get a few lines added so it's not necessary to write a whole new dang test to see if #type is there.

utkarsh_33’s picture

The change that we are making to include '#type' in the keys for array_intersect_key is causing an infinite loop. This is because $element contains a reference to $variables['label'], and modifying $variables['label'] inside the function is triggering the function to be called again, leading to an infinite recursion.
The way i was able to figure that out was because adding

unset($element['#type']);
  $variables['label'] += array_intersect_key($element, array_flip(array('#type', '#id', '#required', '#title', '#title_display')));

code makes it work load the page which was not loading earlier.
Not sure if the solution in this patch is the best solution. If it is i can add the test for the same with the patch applied.

bnjmnm’s picture

his is because $element contains a reference to $variables['label'], and modifying $variables['label'] inside the function is triggering the function to be called again, leading to an infinite recursion.

This was spotted in #2 as well. The next step should be figuring out why adding #type is causing this recursion.

What is it about this additional array property causing this recursive loop? Until we know that, we won't know if the solution in #2 is the right approach. Knowing this might reveal a way to get #type in without the need to rename - it may also reveal an underlying bug or optimization opportunity.

You don't need to fully know the render system to know how this works. The process of investigating these types of bugs is what leads to the fuller understanding. I recommend looking for logic that checks for ['#type'] either being present or not empty. These regexes can help you find those uses:

  • isset\(.*\['#type'\]\)
  • !empty\(.*\['#type'\]\)

. There will still be several results, but you can rule out any uses found inside a module, theme or test since the recursion happens on a minimal install. Look at what the remaining uses do and put breakpoints in places you believe the recursion might be happening. There's a good chance you'll find the cause, but if you don't you can still document which regex-matching areas you checked and what your findings were - that information is still a helpful step forward.

utkarsh_33’s picture

After some debugging and reading about the rendering system i came up with what could be the reason for infinite loop.
- In the Drupal theming system, variables like $variables['label'] are passed to template files for rendering. When you're preparing variables in the
template_preprocess_form_element function, you're essentially preparing data to be used in the template file associated with the form element.
- When you add #type directly to $variables['label'], you're essentially associating the type of the form element with the label of the form element.
- The rendering of form elements in Drupal is a recursive process. When rendering a form element, Drupal may need to render its children or
related elements, which in turn may need to render their children, and so on. If, during this process, Drupal encounters the #type property
associated with a label, it may interpret this as a signal to render another form element, leading to a recursive loop.
- Drupal's rendering system may keep trying to render the label as a form element due to the presence of #type, leading to excessive resource
usage and potentially crashing the system.
So according to what i understood with the above mentioned points i think the approach we are trying to use in #2 may not be the correct way to add type to label.We should keep that as a separate property.

I recommend looking for logic that checks for ['#type'] either being present or not empty. These regexes can help you find those uses:

I was not completely able to get what needs to be done in this so i tried with what i understood and documented my understanding on this.

bnjmnm’s picture

StatusFileSize
new270.75 KB
new467.2 KB
new594.05 KB

If we're running into an infinite recursion issue, I recommend first finding where the recursion is occurring.

We already know that there is an infinite recursion problem when #type is set in the render array.

This is most likely due to a condition that executes code only when #type is present. The two most likely ways PHP would check for the presence of #type are isset($foo['#type']) or !empty($foo['#type'])

We can use a regular expression to find places where these conditions might be set
[^\!]isset\(.*\['#type'\]\) Will look for an "isset" call without a preceding exclamation point, followed by an array path that ends #type. The regex could be even more precise, but just this narrows things down to only 9 places this could be happening.


Most of the results can be ruled out because they are in modules/themes that don't need to be running for this error to occur, they are in tests, or it belongs to a class for a feature that is unrelated to the issue.

Expand the results and you can rule out additional possibilities:

This leaves only 5 possible places, making it pretty easy to check each with an xdebug breakpoint, and see which condition is getting hit infinite times.

If I place the breakpoint in the Renderer.php condition, it appears to loop infinitely when it hits an element with a form_element_label #theme.

Without even having to know that much about the render system, just a little bit of PHP / regex / xdebug we can see the recursion is happening in this block in Renderer.php

 // If the default values for this element have not been loaded yet, populate
    // them.
    if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {
      $elements += $this->elementInfo->getInfo($elements['#type']);
    }

Is this best accomplished by changing the condition, or by changing what this->elementInfo->getInfo($elements['#type']); returns, or something entirely different?

utkarsh_33’s picture

Version: 11.x-dev » 11.0.x-dev

utkarsh_33’s picture

Status: Active » Needs review
smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

Can we update the issue summary to the standard issue template.

Have not reviewed yet.

bnjmnm’s picture

MR has a question about why this particular solution works and evidence that it will not result in other problems. This may require a bit of research, which is a great way to get more familiar with how core works.

This will also need a test to confirm #type is getting passed to the label elements. Forms in general have many tests, to there may be an existing test that you can use this so it's only necessary to add a few lines instead of having to write an entirely new test.

utkarsh_33’s picture

Version: 11.0.x-dev » 11.x-dev

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.