From c62398b372eec4fe7189ac19ccfe6417db0daf81 Mon Sep 17 00:00:00 2001 From: Mark Carver Date: Mon, 17 Apr 2017 03:29:56 -0500 Subject: [PATCH] Issue #2870204 by hass, markcarver: Not properly closing div on bootstrap_image_widget template function --- includes/alter.inc | 45 ++++++++++++++++++++++++++++++++++ includes/process.inc | 5 ++-- templates/image/image-widget.func.php | 8 +----- templates/system/container.func.php | 4 ++- templates/system/form-element.func.php | 20 +++++++++------ 5 files changed, 64 insertions(+), 18 deletions(-) diff --git a/includes/alter.inc b/includes/alter.inc index c4a9677..04e2e4f 100644 --- a/includes/alter.inc +++ b/includes/alter.inc @@ -200,6 +200,51 @@ function _bootstrap_element_info_array_merge($info, $cached) { } /** + * Implements hook_field_widget_form_alter(). + */ +function bootstrap_field_widget_form_alter(&$element, &$form_state, $context) { + $widget_type = isset($context['instance']['widget']['type']) ? $context['instance']['widget']['type'] : NULL; + if ($widget_type === 'image_image') { + foreach (element_children($element) as $child) { + $element[$child]['#process'][] = '_bootstrap_image_field_widget_process'; + } + } +} + +/** + * Implements above #process callback. + */ +function _bootstrap_image_field_widget_process($element, &$form_state, $form) { + // Core explicitly sets #theme_wrappers to an empty array for the upload + // element (perhaps for styling reasons?). Thus, bootstrap_form_element() is + // invoked, preventing any necessary logic from executing. To achieve the + // same goal and keep backwards compatibility, reset the theme wrapper back + // and indicating that the wrapper shouldn't be printed. + $element['upload']['#theme_wrappers'][] = 'form_element__image_widget'; + $element['upload']['#form_element_wrapper'] = FALSE; + + // Unfortunately, core also doesn't set #access on the appropriate elements + // until way too late (ironically, because of #ajax). Instead of calling + // file_managed_file_pre_render(), just mimic the same #access logic, but + // using #default_value instead of #value since the ajax request populates + // #value. + $value = empty($element['#default_value']['fid']); + if (!$value) { + $element['upload']['#access'] = FALSE; + $element['upload_button']['#access'] = FALSE; + } + // If we don't already have a file, there is nothing to remove. + else { + $element['remove_button']['#access'] = FALSE; + } + + // Make the upload file element an input group with a button. + $element['upload']['#input_group_button'] = $value; + + return $element; +} + +/** * Implements hook_form_alter(). */ function bootstrap_form_alter(array &$form, array &$form_state = array(), $form_id = NULL) { diff --git a/includes/process.inc b/includes/process.inc index 3a0e05e..4af8e1b 100644 --- a/includes/process.inc +++ b/includes/process.inc @@ -47,14 +47,13 @@ function bootstrap_form_process($element, &$form_state, &$form) { // Ignore buttons before we find the element in the form. $found_current_element = FALSE; - foreach (element_children($parent) as $child) { + foreach (element_children($parent, TRUE) as $child) { if ($parent[$child] === $element) { $found_current_element = TRUE; continue; } - if ($found_current_element && _bootstrap_is_button($parent[$child])) { - _bootstrap_iconize_button($parent[$child]); + if ($found_current_element && _bootstrap_is_button($parent[$child]) && (!isset($parent[$child]['#access']) || !!$parent[$child]['#access'])) { $element['#field_suffix'] = drupal_render($parent[$child]); break; } diff --git a/templates/image/image-widget.func.php b/templates/image/image-widget.func.php index a2f61ba..73f42c3 100644 --- a/templates/image/image-widget.func.php +++ b/templates/image/image-widget.func.php @@ -30,15 +30,9 @@ function bootstrap_image_widget($variables) { } $output .= '
'; - if ($element['fid']['#value'] != 0) { + if (!empty($element['fid']['#value'])) { $element['filename']['#markup'] = '
' . $element['filename']['#markup'] . ' ' . format_size($element['#file']->filesize) . '
'; } - else { - $element['upload']['#prefix'] = '
'; - $element['upload']['#suffix'] = '
'; - $element['upload_button']['#prefix'] = ''; - $element['upload_button']['#suffix'] = ''; - } $output .= drupal_render_children($element); $output .= '
'; diff --git a/templates/system/container.func.php b/templates/system/container.func.php index 22251f7..ad99929 100644 --- a/templates/system/container.func.php +++ b/templates/system/container.func.php @@ -40,7 +40,9 @@ function bootstrap_container($variables) { $element['#attributes']['class'][] = 'form-wrapper'; // Add Bootstrap "form-group" class. - $element['#attributes']['class'][] = 'form-group'; + if (!isset($element['#form_group']) || !!$element['#form_group']) { + $element['#attributes']['class'][] = 'form-group'; + } } return '' . $element['#children'] . ''; diff --git a/templates/system/form-element.func.php b/templates/system/form-element.func.php index f15b3b6..47e7095 100644 --- a/templates/system/form-element.func.php +++ b/templates/system/form-element.func.php @@ -59,6 +59,8 @@ function bootstrap_form_element(&$variables) { $element = &$variables['element']; $name = !empty($element['#name']) ? $element['#name'] : FALSE; $type = !empty($element['#type']) ? $element['#type'] : FALSE; + $wrapper = isset($element['#form_element_wrapper']) ? !!$element['#form_element_wrapper'] : TRUE; + $form_group = isset($element['#form_group']) ? !!$element['#form_group'] : $wrapper && $type && $type !== 'hidden'; $checkbox = $type && $type === 'checkbox'; $radio = $type && $type === 'radio'; @@ -104,21 +106,25 @@ function bootstrap_form_element(&$variables) { if ($checkbox || $radio) { $wrapper_attributes['class'][] = drupal_html_class($type); } - elseif ($type && $type !== 'hidden') { + elseif ($form_group) { $wrapper_attributes['class'][] = 'form-group'; } // Create a render array for the form element. $build = array( - '#theme_wrappers' => array('container__form_element'), + '#form_group' => $form_group, '#attributes' => $wrapper_attributes, ); - // Render the label for the form element. - $build['label'] = array( - '#markup' => theme('form_element_label', $variables), - '#weight' => $element['#title_display'] === 'before' ? 0 : 2, - ); + if ($wrapper) { + $build['#theme_wrappers'] = array('container__form_element'); + + // Render the label for the form element. + $build['label'] = array( + '#markup' => theme('form_element_label', $variables), + '#weight' => $element['#title_display'] === 'before' ? 0 : 2, + ); + } // Checkboxes and radios render the input element inside the label. If the // element is neither of those, then the input element must be rendered here. -- 2.12.0