4 * Contains \Drupal\bootstrap\Plugin\Preprocess\BootstrapDropdown.
7 namespace Drupal\bootstrap\Plugin\Preprocess;
9 use Drupal\bootstrap\Annotation\BootstrapPreprocess;
10 use Drupal\bootstrap\Utility\Element;
11 use Drupal\bootstrap\Utility\Unicode;
12 use Drupal\bootstrap\Utility\Variables;
13 use Drupal\Component\Utility\Html;
14 use Drupal\Component\Utility\NestedArray;
18 * Pre-processes variables for the "bootstrap_dropdown" theme hook.
20 * @ingroup plugins_preprocess
22 * @BootstrapPreprocess("bootstrap_dropdown")
24 class BootstrapDropdown extends PreprocessBase implements PreprocessInterface {
29 protected function preprocessVariables(Variables $variables) {
30 $this->preprocessLinks($variables);
32 $toggle = Element::create($variables->toggle);
33 $toggle->setProperty('split', $variables->split);
35 // Convert the items into a proper item list.
37 '#theme' => 'item_list__dropdown',
38 '#alignment' => $variables->alignment,
39 '#items' => $variables->items,
42 // Ensure all attributes are proper objects.
43 $this->preprocessAttributes();
47 * Preprocess links in the variables array to convert them from dropbuttons.
49 * @param \Drupal\bootstrap\Utility\Variables $variables
52 protected function preprocessLinks(Variables $variables) {
53 // Convert "dropbutton" theme suggestion variables.
54 if (Unicode::strpos($variables->theme_hook_original, 'links__dropbutton') !== FALSE && !empty($variables->links)) {
55 $operations = !!Unicode::strpos($variables->theme_hook_original, 'operations');
57 // Normal dropbutton links are not actually render arrays, convert them.
58 foreach ($variables->links as &$element) {
59 if (isset($element['title']) && $element['url']) {
60 // Preserve query parameters (if any)
61 if (!empty($element['query'])) {
62 $url_query = $element['url']->getOption('query') ?: [];
63 $element['url']->setOption('query', NestedArray::mergeDeep($url_query , $element['query']));
66 // Build render array.
69 '#title' => $element['title'],
70 '#url' => $element['url'],
75 $items = Element::createStandalone();
77 $primary_action = NULL;
78 $links = Element::create($variables->links);
80 // Iterate over all provided "links". The array may be associative, so
81 // this cannot rely on the key to be numeric, it must be tracked manually.
83 foreach ($links->children(TRUE) as $key => $child) {
86 // The first item is always the "primary link".
88 // Must generate an ID for this child because the toggle will use it.
89 $child->getProperty('id', $child->getAttribute('id', Html::getUniqueId('dropdown-item')));
90 $primary_action = $child->addClass('hidden');
93 // If actually a "link", add it to the items array directly.
94 if ($child->isType('link')) {
95 $items->$key->link = $child->getArrayCopy();
97 // Otherwise, convert into a proper link.
99 // Hide the original element
100 $items->$key->element = $child->addClass('hidden')->getArrayCopy();
102 // Retrieve any set HTML identifier for the link, generating a new
104 $id = $child->getProperty('id', $child->getAttribute('id', Html::getUniqueId('dropdown-item')));
105 $items->$key->link = Element::createStandalone([
107 '#title' => $child->getProperty('value', $child->getProperty('title', $child->getProperty('text'))),
108 '#url' => Url::fromUserInput('#'),
109 '#attributes' => ['data-dropdown-target' => "#$id"],
112 // Also hide the real link if it's the primary action.
114 $items->$key->link->addClass('hidden');
119 // Create a toggle button, extracting relevant info from primary action.
120 $toggle = Element::createStandalone([
122 '#attributes' => $primary_action->getAttributes()->getArrayCopy(),
123 '#value' => $primary_action->getProperty('value', $primary_action->getProperty('title', $primary_action->getProperty('text'))),
126 // Remove the "hidden" class that was added to the primary action.
127 $toggle->removeClass('hidden')->removeAttribute('id')->setAttribute('data-dropdown-target', '#' . $primary_action->getAttribute('id'));
129 // Make operations smaller.
131 $toggle->setButtonSize('btn-xs', FALSE);
134 // Add the toggle render array to the variables.
135 $variables->toggle = $toggle->getArrayCopy();
137 // Determine if toggle should be a split button.
138 $variables->split = count($items) > 1;
140 // Add the items variable for "bootstrap_dropdown".
141 $variables->items = $items->getArrayCopy();
143 // Remove the unnecessary "links" variable now.
144 unset($variables->links);