You are here

function formdazzle_add_form_element_suggestions in Formdazzle! 8

A recursive helper function to add theme suggestions to form elements.

Parameters

Element $element:

string $form_id:

string $tree:

1 call to formdazzle_add_form_element_suggestions()
formdazzle_form_alter in ./formdazzle.module
Implements hook_form_alter().

File

./formdazzle.module, line 25
The module that provides a set of utilities that make form theming easier.

Code

function formdazzle_add_form_element_suggestions(&$element, $form_id, $tree = '') {

  // Get the default info for the #type of form element.
  $defaultInfo = isset($element['#type']) ? Drupal::service('plugin.manager.element_info')
    ->getInfo($element['#type']) : [];

  // Add the default #theme and #theme_wrappers, if needed.
  if (!isset($element['#theme']) && isset($defaultInfo['#theme'])) {
    $element['#theme'] = $defaultInfo['#theme'];
  }

  // #theme can be a string or an array. To ease processing, we ensure it is an
  // array and flatten single-item arrays before we leave this function.
  if (isset($element['#theme']) && !is_array($element['#theme'])) {
    $element['#theme'] = [
      $element['#theme'],
    ];
  }
  if (isset($defaultInfo['#theme_wrappers'])) {
    $element['#theme_wrappers'] = isset($element['#theme_wrappers']) ? array_unique(array_merge($element['#theme_wrappers'], $defaultInfo['#theme_wrappers'])) : $defaultInfo['#theme_wrappers'];
  }

  // Find the form element name.
  $name = isset($element['#name']) ? $element['#name'] : (isset($element['#webform_key']) ? $element['#webform_key'] : $tree);

  // Ensure the name is a proper suggestion string.
  // Based on regex in Drupal\Component\Utility\Html::getId().
  $name = strtolower(strtr($name, [
    ' ' => '_',
    '.' => '_',
    '-' => '_',
    '/' => '_',
    '[' => '_',
    ']' => '',
  ]));
  $name = preg_replace('/[^a-z0-9_]/', '', $name);

  // Use a simplified webform form ID.
  if (isset($element['#entity_type']) && $element['#entity_type'] === 'webform_submission' && isset($element['#webform_id'])) {
    $form_id = 'webform_' . $element['#webform_id'] . '_form';
  }

  // Some Drupal\Core\Render\Element's should have generic suggestions.
  $type = '';
  if (isset($element['#type'])) {
    switch ($element['#type']) {
      case 'actions':
      case 'more_link':
      case 'password_confirm':
        $type = $element['#type'];
        break;
      case 'system_compact_link':
        $type = 'compact_link';
        break;
    }
  }

  // Use the same theme suggestions for each theme hook.
  $suggestion_suffix = ($type ? '__' . $type : '') . '__' . $form_id . ($name ? '__' . $name : '');

  // We want to ensure that all form elements have a generic theme suggestion.
  // Sometimes, form elements already have them. And sometimes, we have figured
  // out ones to add above. If we don't have a generic theme suggestion, add
  // suggestion data so that later hooks can add suggestions to the form.
  $add_data = true;
  if ($name || $type) {
    $add_data = false;
  }
  if ($add_data) {
    $has_good_theme_suggestion = isset($element['#theme']) && (isset($element['#type']) && $element['#theme'][0] === $element['#type'] || strpos($element['#theme'][0], '__'));
    $has_good_theme_wrappers_suggestion = $has_good_theme_suggestion || isset($element['#theme_wrappers']) && strpos($element['#theme_wrappers'][0], '__');
    if ($has_good_theme_suggestion || $has_good_theme_wrappers_suggestion) {
      $add_data = FALSE;
    }
  }

  // We also need to add this data on form_element wrappers to ensure labels
  // get suggestions. @see formdazzle_preprocess_form_element()
  $add_data = $add_data || isset($element['#theme_wrappers']) && in_array('form_element', $element['#theme_wrappers']);
  if ($add_data) {
    $element['#formdazzle'] = [
      'suggestion_suffix' => $suggestion_suffix,
      'form_id' => $form_id,
      'form_element_name' => $name,
    ];
  }

  // Add a theme suggestion to #theme.
  if (isset($element['#theme'])) {

    // If we aren't examining the root form, add #theme suggestions.
    if ($element['#theme'][0] !== $form_id && $element['#theme'][0] !== 'webform_submission_form') {
      foreach ($element['#theme'] as $key => $value) {
        $element['#theme'][$key] .= $suggestion_suffix;
      }
    }

    // Flatten single-item #theme arrays to strings.
    if (count($element['#theme']) == 1) {
      $element['#theme'] = $element['#theme'][0];
    }
  }

  // Add a theme suggestion to #theme_wrappers.
  if (isset($element['#theme_wrappers'])) {
    foreach ($element['#theme_wrappers'] as $key => $value) {
      if ($value !== 'form') {
        $element['#theme_wrappers'][$key] = $value . $suggestion_suffix;
      }
    }
  }

  // Recursively add suggestions to the element's children.
  foreach (Element::children($element) as $key) {
    $child_tree = '';
    if ($tree) {
      $child_tree = $tree . '_' . $key;
    }
    elseif (isset($element[$key]['#tree'])) {
      $child_tree = $key;
    }
    formdazzle_add_form_element_suggestions($element[$key], $form_id, $child_tree);
  }
}