4 * Contains \Drupal\bootstrap\Plugin\Preprocess\BootstrapPanel.
7 namespace Drupal\bootstrap\Plugin\Preprocess;
9 use Drupal\bootstrap\Annotation\BootstrapPreprocess;
10 use Drupal\bootstrap\Utility\Element;
11 use Drupal\bootstrap\Utility\Variables;
12 use Drupal\Component\Render\MarkupInterface;
13 use Drupal\Component\Utility\Html;
16 * Pre-processes variables for the "bootstrap_panel" theme hook.
18 * @ingroup plugins_preprocess
20 * @BootstrapPreprocess("bootstrap_panel")
22 class BootstrapPanel extends PreprocessBase implements PreprocessInterface {
27 protected function preprocessElement(Element $element, Variables $variables) {
28 // Assign the ID, if not already set.
29 $element->map(['id']);
31 // Add necessary classes.
32 $element->addClass(['form-item', 'js-form-item', 'form-wrapper', 'js-form-wrapper']);
35 $properties = ['field_prefix', 'body', 'children'];
37 // Only add the #value property if it's a "details" or "fieldset" element
38 // type. Some form elements may use "CompositeFormElementTrait" which
39 // will inadvertently and eventually become preprocessed here and #value
40 // may actually be the element's value instead of a renderable element.
41 if ($element->isType(['details', 'fieldset'])) {
42 $properties[] = 'value';
45 // Add the "#field_suffix" property.
46 $properties[] = 'field_suffix';
48 // Merge all possible content from the element into a single render array.
49 foreach ($properties as $property) {
50 $body[$property] = Element::create($element->getProperty($property, []))->getArray();
52 $variables['body'] = array_filter($body);
55 'attributes' => 'attributes',
56 'body_attributes' => 'body_attributes',
57 'content_attributes' => 'body_attributes',
58 'description' => 'description',
59 'description_attributes' => 'description_attributes',
60 'description_display' => 'description_display',
63 'required' => 'required',
64 'panel_type' => 'panel_type',
66 'title_attributes' => 'heading_attributes',
69 // Handle specific "details" elements.
70 if ($element->isType('details')) {
71 // Details are always collapsible per the HTML5 spec.
72 // @see https://www.drupal.org/node/1852020
73 $variables['collapsible'] = TRUE;
75 // Determine the collapsed state.
76 $variables['collapsed'] = !$element->getProperty('open', TRUE);
78 // Remove the unnecessary details attribute.
79 $element->removeAttribute('open');
81 // Handle specific "fieldset" elements.
82 elseif ($element->isType('fieldset')) {
83 // Override variables to mimic the default "fieldset" element info.
84 // They will be mapped below if they exist on the element.
85 unset($variables['collapsible'], $variables['collapsed']);
86 $map['collapsed'] = 'collapsed';
87 $map['collapsible'] = 'collapsible';
90 // Map the element properties to the variables array.
91 $variables->map($map);
97 protected function preprocessVariables(Variables $variables) {
98 // Retrieve the ID, generating one if needed.
99 $id = $variables->getAttribute('id', Html::getUniqueId($variables->offsetGet('id', 'bootstrap-panel')));
100 unset($variables['id']);
102 // Handle collapsible state.
103 if ($variables['heading'] && $variables['collapsible']) {
104 // Retrieve the body ID attribute.
105 if ($body_id = $variables->getAttribute('id', "$id--content", 'body_attributes')) {
106 // Ensure the target is set.
107 if ($variables['target'] = $variables->offsetGet('target', "#$body_id")) {
108 // Set additional necessary attributes to the heading.
109 $variables->setAttributes([
110 'aria-controls' => preg_replace('/^#/', '', $variables['target']),
111 'aria-expanded' => !$variables['collapsed'] ? 'true' : 'false',
112 'aria-pressed' => !$variables['collapsed'] ? 'true' : 'false',
113 'data-toggle' => 'collapse',
115 ], 'heading_attributes');
120 // Ensure we render HTML from heading.
121 $heading = $variables->offsetGet('heading');
122 if ($heading && (is_string($heading) || ($heading instanceof MarkupInterface))) {
123 $variables->offsetSet('heading', ['#markup' => $heading]);
126 // Ensure there is a valid panel state.
127 if (!$variables->offsetGet('panel_type')) {
128 $variables->offsetSet('panel_type', 'default');
131 // Convert the description variable.
132 $this->preprocessDescription();
134 // Ensure all attributes are proper objects.
135 $this->preprocessAttributes();