public static function Dazzler::addSuggestions in Formdazzle! 2.x
Adds theme suggestions to form elements.
Parameters
array $element: The form or form element to give a template suggestion to.
string $form_id: The ID of the form the element belongs to.
string $form_id_suggestion: A suggestion to use based on the form ID.
2 calls to Dazzler::addSuggestions()
- Dazzler::traverse in src/
Dazzler.php - A recursive helper function to traverse all form element children.
- DazzlerTest::testAddSuggestions in tests/
src/ Unit/ DazzlerTest.php - @covers ::addSuggestions
File
- src/
Dazzler.php, line 212
Class
- Dazzler
- A class providing methods to modify Drupal form elements.
Namespace
Drupal\formdazzleCode
public static function addSuggestions(array &$element, $form_id, $form_id_suggestion) {
$needs_theme_suggestion = isset($element['#theme']);
$needs_theme_wrapper_suggestion = isset($element['#theme_wrappers']);
// #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.
$flatten_theme_array = FALSE;
if ($needs_theme_suggestion && !is_array($element['#theme'])) {
$element['#theme'] = [
$element['#theme'],
];
$flatten_theme_array = TRUE;
}
$last_suggestion_key = $needs_theme_suggestion ? array_key_last($element['#theme']) : NULL;
$last_suggestion = !is_null($last_suggestion_key) ? $element['#theme'][$last_suggestion_key] : '';
// Find the form element name.
$name = '';
if (isset($element['#name'])) {
$name = $element['#name'];
}
elseif (isset($element['#webform_key'])) {
$name = $element['#webform_key'];
}
elseif (isset($element['#parents']) && count($element['#parents'])) {
// Based on Drupal\Core\Form\FormBuilder::handleInputElement().
if (isset($element['#type']) && $element['#type'] === 'file') {
$name = 'files_' . $element['#parents'][0];
}
else {
$name = implode('_', $element['#parents']);
}
}
$name_suggestion = '';
if ($name) {
// 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);
$name_suggestion = '__' . $name;
}
// Most Drupal\Core\Render\Element's have generic suggestions, but some
// don't have them when they should.
$type = isset($element['#type']) ? $element['#type'] : '';
$type_suggestion = '';
switch ($type) {
case 'actions':
case 'more_link':
case 'password_confirm':
case 'system_compact_link':
$type_suggestion = '__' . $type;
break;
}
// Don't add name suggestions that are redundant with type suggestions.
if ($type_suggestion && $type_suggestion === $name_suggestion) {
$name_suggestion = '';
}
// Use the same theme suggestions for each theme hook.
$suggestion_suffix = $type_suggestion . '__' . $form_id_suggestion . $name_suggestion;
// We want to ensure that all form elements have a generic theme suggestion.
// But form_element doesn't create a label element until after form_alter
// hooks have run, so we have to add suggestion data so that later hooks can
// add suggestions to the form.
$is_form_element = $needs_theme_wrapper_suggestion && in_array('form_element', $element['#theme_wrappers']);
if ($is_form_element) {
$element['#formdazzle'] = [
'suggestion_suffix' => $suggestion_suffix,
'form_id' => $form_id,
'form_id_suggestion' => $form_id_suggestion,
'form_element_name' => $name,
];
}
// Add theme suggestions to #theme.
// In Drupal\Core\Theme\ThemeManager::render(), if an array of hook
// candidates is passed, use the first exact match. If there are no exact
// matches, the last hook candidate is checked for more generic fallbacks by
// stripping off successive __[suggestion] parts from the end of the string
// until a match is made.
if ($needs_theme_suggestion) {
if ($type === 'form') {
// This is technically a duplicate of an existing suggestion, but Twig
// debugging doesn't show the suggestions unless we add this duplicate.
// @see https://www.drupal.org/project/drupal/issues/2118743
if ($last_suggestion === 'views_exposed_form') {
$element['#theme'][$last_suggestion_key] .= str_replace('__views__', '__', $suggestion_suffix);
}
}
else {
$element['#theme'][$last_suggestion_key] .= $suggestion_suffix;
}
// If we converted a #theme string into an array, convert it back.
if ($flatten_theme_array && count($element['#theme']) === 1) {
$element['#theme'] = $element['#theme'][0];
}
}
// Add theme suggestions to #theme_wrappers.
// In Drupal\Core\Theme\ThemeManager::render(), #theme wrappers is an array
// of theme hooks. The keys of the array are either numeric keys (with the
// theme hook as the value) or strings containing the theme hook (and the
// value is an array of data not important to FormDazzle.) e.g.
// [ 0 => 'theme_hook', 'theme_hook' => ['some' => 'data']].
if ($needs_theme_wrapper_suggestion) {
$add_suggestions_to_keys = FALSE;
foreach ($element['#theme_wrappers'] as $key => $value) {
if (is_string($key)) {
$add_suggestions_to_keys = TRUE;
}
elseif (strpos($value, $suggestion_suffix) === FALSE) {
$element['#theme_wrappers'][$key] = $value . $suggestion_suffix;
}
}
// In order to add suggestions to array keys, we have to rebuild the array
// to ensure that the order of the array isn't disturbed.
if ($add_suggestions_to_keys) {
$theme_wrappers = $element['#theme_wrappers'];
$element['#theme_wrappers'] = [];
foreach ($theme_wrappers as $key => $value) {
if (is_string($key)) {
$element['#theme_wrappers'][$key . $suggestion_suffix] = $value;
}
else {
$element['#theme_wrappers'][] = $value;
}
}
}
}
}