Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / themes / contrib / bootstrap / src / Plugin / Preprocess / BootstrapDropdown.php
index 28e16629eb57ae273e6f50e92a5bd9b2cddc0f53..8c0a6de217187346bec136c9df659a0c6ea53942 100644 (file)
@@ -1,17 +1,13 @@
 <?php
-/**
- * @file
- * Contains \Drupal\bootstrap\Plugin\Preprocess\BootstrapDropdown.
- */
 
 namespace Drupal\bootstrap\Plugin\Preprocess;
 
-use Drupal\bootstrap\Annotation\BootstrapPreprocess;
 use Drupal\bootstrap\Utility\Element;
 use Drupal\bootstrap\Utility\Unicode;
 use Drupal\bootstrap\Utility\Variables;
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Url;
 
 /**
@@ -35,8 +31,10 @@ class BootstrapDropdown extends PreprocessBase implements PreprocessInterface {
     // Convert the items into a proper item list.
     $variables->items = [
       '#theme' => 'item_list__dropdown',
-      '#alignment' => $variables->alignment,
       '#items' => $variables->items,
+      '#context' => [
+        'alignment' => $variables->alignment,
+      ],
     ];
 
     // Ensure all attributes are proper objects.
@@ -56,11 +54,39 @@ class BootstrapDropdown extends PreprocessBase implements PreprocessInterface {
 
       // Normal dropbutton links are not actually render arrays, convert them.
       foreach ($variables->links as &$element) {
-        if (isset($element['title']) && $element['url']) {
+        // Only process links that have "title".
+        if (!isset($element['title'])) {
+          continue;
+        }
+
+        // If title is an actual render array, just move it up.
+        if (Element::isRenderArray($element['title']) && !isset($element['url'])) {
+          $element = $element['title'];
+        }
+        // Otherwise, convert into an actual "link" render array element.
+        else {
+          if (!isset($element['url'])) {
+            $element['url'] = Url::fromRoute('<none>');
+          }
+
+          $attributes = isset($element['attributes']) ? $element['attributes'] : [];
+          $wrapper_attributes = isset($element['wrapper_attributes']) ? $element['wrapper_attributes'] : [];
+
+          if (isset($element['language']) && $element['language'] instanceof LanguageInterface) {
+            $attributes['hreflang'] = $element['language']->getId();
+            $wrapper_attributes['hreflang'] = $element['language']->getId();
+
+            // Ensure the Url language is set on the object itself.
+            // @todo Possibly a core bug?
+            if (empty($element['url']->getOption('language'))) {
+              $element['url']->setOption('language', $element['language']);
+            }
+          }
+
           // Preserve query parameters (if any)
           if (!empty($element['query'])) {
             $url_query = $element['url']->getOption('query') ?: [];
-            $element['url']->setOption('query', NestedArray::mergeDeep($url_query , $element['query']));
+            $element['url']->setOption('query', NestedArray::mergeDeep($url_query, $element['query']));
           }
 
           // Build render array.
@@ -68,6 +94,9 @@ class BootstrapDropdown extends PreprocessBase implements PreprocessInterface {
             '#type' => 'link',
             '#title' => $element['title'],
             '#url' => $element['url'],
+            '#ajax' => isset($element['ajax']) ? $element['ajax'] : [],
+            '#attributes' => $attributes,
+            '#wrapper_attributes' => $wrapper_attributes,
           ];
         }
       }
@@ -83,26 +112,38 @@ class BootstrapDropdown extends PreprocessBase implements PreprocessInterface {
       foreach ($links->children(TRUE) as $key => $child) {
         $i++;
 
+        // Ensure validation errors are limited.
+        if ($child->getProperty('limit_validation_errors') !== FALSE) {
+          $child->setAttribute('formnovalidate', 'formnovalidate');
+        }
+
         // The first item is always the "primary link".
         if ($i === 0) {
           // Must generate an ID for this child because the toggle will use it.
-          $child->getProperty('id', $child->getAttribute('id', Html::getUniqueId('dropdown-item')));
+          if (!$child->getAttribute('id')) {
+            $child->setAttribute('id', $child->getProperty('id', Html::getUniqueId('dropdown-item')));
+          }
           $primary_action = $child->addClass('hidden');
         }
 
-        // If actually a "link", add it to the items array directly.
-        if ($child->isType('link')) {
-          $items->$key->link = $child->getArrayCopy();
-        }
-        // Otherwise, convert into a proper link.
-        else {
-          // Hide the original element
-          $items->$key->element = $child->addClass('hidden')->getArrayCopy();
+        // Convert into a proper link.
+        if (!$child->isType('link')) {
+          // Retrieve any set HTML identifier for the original element,
+          // generating a new one if necessary. This is needed to ensure events
+          // are bound on the original element (which may be DOM specific).
+          // When the corresponding link below is clicked, it proxies all
+          // events to the "dropdown-target" (the original element).
+          $id = $child->getAttribute('id');
+          if (!$id) {
+            $id = $child->getProperty('id', Html::getUniqueId('dropdown-item'));
+            $child->setAttribute('id', $id);
+          }
 
-          // Retrieve any set HTML identifier for the link, generating a new
-          // one if necessary.
-          $id = $child->getProperty('id', $child->getAttribute('id', Html::getUniqueId('dropdown-item')));
-          $items->$key->link = Element::createStandalone([
+          // Add the original element to the item list, but hide it.
+          $items->{$key . '_original'} = $child->addClass('hidden')->getArrayCopy();
+
+          // Replace the child element with a proper link.
+          $child = Element::createStandalone([
             '#type' => 'link',
             '#title' => $child->getProperty('value', $child->getProperty('title', $child->getProperty('text'))),
             '#url' => Url::fromUserInput('#'),
@@ -111,9 +152,11 @@ class BootstrapDropdown extends PreprocessBase implements PreprocessInterface {
 
           // Also hide the real link if it's the primary action.
           if ($i === 0) {
-            $items->$key->link->addClass('hidden');
+            $child->addClass('hidden');
           }
         }
+
+        $items->$key = $child->getArrayCopy();
       }
 
       // Create a toggle button, extracting relevant info from primary action.