28e16629eb57ae273e6f50e92a5bd9b2cddc0f53
[yaffs-website] / web / themes / contrib / bootstrap / src / Plugin / Preprocess / BootstrapDropdown.php
1 <?php
2 /**
3  * @file
4  * Contains \Drupal\bootstrap\Plugin\Preprocess\BootstrapDropdown.
5  */
6
7 namespace Drupal\bootstrap\Plugin\Preprocess;
8
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;
15 use Drupal\Core\Url;
16
17 /**
18  * Pre-processes variables for the "bootstrap_dropdown" theme hook.
19  *
20  * @ingroup plugins_preprocess
21  *
22  * @BootstrapPreprocess("bootstrap_dropdown")
23  */
24 class BootstrapDropdown extends PreprocessBase implements PreprocessInterface {
25
26   /**
27    * {@inheritdoc}
28    */
29   protected function preprocessVariables(Variables $variables) {
30     $this->preprocessLinks($variables);
31
32     $toggle = Element::create($variables->toggle);
33     $toggle->setProperty('split', $variables->split);
34
35     // Convert the items into a proper item list.
36     $variables->items = [
37       '#theme' => 'item_list__dropdown',
38       '#alignment' => $variables->alignment,
39       '#items' => $variables->items,
40     ];
41
42     // Ensure all attributes are proper objects.
43     $this->preprocessAttributes();
44   }
45
46   /**
47    * Preprocess links in the variables array to convert them from dropbuttons.
48    *
49    * @param \Drupal\bootstrap\Utility\Variables $variables
50    *   A variables object.
51    */
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');
56
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']));
64           }
65
66           // Build render array.
67           $element = [
68             '#type' => 'link',
69             '#title' => $element['title'],
70             '#url' => $element['url'],
71           ];
72         }
73       }
74
75       $items = Element::createStandalone();
76
77       $primary_action = NULL;
78       $links = Element::create($variables->links);
79
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.
82       $i = -1;
83       foreach ($links->children(TRUE) as $key => $child) {
84         $i++;
85
86         // The first item is always the "primary link".
87         if ($i === 0) {
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');
91         }
92
93         // If actually a "link", add it to the items array directly.
94         if ($child->isType('link')) {
95           $items->$key->link = $child->getArrayCopy();
96         }
97         // Otherwise, convert into a proper link.
98         else {
99           // Hide the original element
100           $items->$key->element = $child->addClass('hidden')->getArrayCopy();
101
102           // Retrieve any set HTML identifier for the link, generating a new
103           // one if necessary.
104           $id = $child->getProperty('id', $child->getAttribute('id', Html::getUniqueId('dropdown-item')));
105           $items->$key->link = Element::createStandalone([
106             '#type' => 'link',
107             '#title' => $child->getProperty('value', $child->getProperty('title', $child->getProperty('text'))),
108             '#url' => Url::fromUserInput('#'),
109             '#attributes' => ['data-dropdown-target' => "#$id"],
110           ]);
111
112           // Also hide the real link if it's the primary action.
113           if ($i === 0) {
114             $items->$key->link->addClass('hidden');
115           }
116         }
117       }
118
119       // Create a toggle button, extracting relevant info from primary action.
120       $toggle = Element::createStandalone([
121         '#type' => 'button',
122         '#attributes' => $primary_action->getAttributes()->getArrayCopy(),
123         '#value' => $primary_action->getProperty('value', $primary_action->getProperty('title', $primary_action->getProperty('text'))),
124       ]);
125
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'));
128
129       // Make operations smaller.
130       if ($operations) {
131         $toggle->setButtonSize('btn-xs', FALSE);
132       }
133
134       // Add the toggle render array to the variables.
135       $variables->toggle = $toggle->getArrayCopy();
136
137       // Determine if toggle should be a split button.
138       $variables->split = count($items) > 1;
139
140       // Add the items variable for "bootstrap_dropdown".
141       $variables->items = $items->getArrayCopy();
142
143       // Remove the unnecessary "links" variable now.
144       unset($variables->links);
145     }
146   }
147
148 }