Change record status: 
Project: 
Introduced in branch: 
7.x
Introduced in version: 
7.54
Description: 

In the menu_tree theme implementation, Drupal overwrites the Render API structure with the already rendered HTML for the menu tree very early in the process (in template_preprocess_menu_tree()), making it impossible for themers to access information within or make alterations to that data structure before it is rendered.

With this change, the Render API structure is preserved as a new variable $variables['#tree'] for use in THEMENAME_preprocess_menu_tree(), etc. The original variable, $variables['tree'] (without the pound sign), does not change and is still the variable rendered by the menu_tree theme function.

Example: Add a BEM class to a menu in a block in a specific region

<?php

/**
 * Implements hook_preprocess_HOOK() for theme_menu_tree().
 */
function MYTHEME_preprocess_menu_tree(&$variables) {
  // Create a default class attribute with the original class from theme_menu_tree().
  $variables['#attributes']['class'] = array('menu');

  // If the menu being rendered is being placed as a block into a particular
  // region, add a class to it (for example, to do BEM-style theming).
  if (isset($variables['#tree']['#block']) && $variables['#tree']['#block']->region == 'site_menu') {
    $variables['#attributes']['class'][] = 'menu--horizontal';
  }
}

/**
 * Implements theme_menu_tree().
 */
function MYTHEME_menu_tree($variables) {
  // Drupal's default theme_menu_tree() hardcodes the class attribute. Override
  // and use our dynamic class attribute instead.
  return '<ul ' . drupal_attributes($variables['#attributes']) . '>' . $variables['tree'] . '</ul>';
}
Impacts: 
Module developers
Themers