From 3e58b83fe0a9913a33eda1e73e705aacd76075ba Mon Sep 17 00:00:00 2001
From: Kris Booghmans <kris@calibrate.be>
Date: Sat, 15 Feb 2025 14:30:59 +0100
Subject: [PATCH] Add Tools plugin for managing navigation_extra_tools and
 devel links.

---
 assets/js/navigation_extra_version.js       |  34 +++--
 navigation_extra.module                     |   4 -
 src/Plugin/Navigation/Extra/ToolsPlugin.php | 154 ++++++++++++++++++++
 3 files changed, 175 insertions(+), 17 deletions(-)
 create mode 100644 src/Plugin/Navigation/Extra/ToolsPlugin.php

diff --git a/assets/js/navigation_extra_version.js b/assets/js/navigation_extra_version.js
index f94afff..b7beeec 100644
--- a/assets/js/navigation_extra_version.js
+++ b/assets/js/navigation_extra_version.js
@@ -23,21 +23,29 @@
             context,
           ).forEach((logo) => {
             const doc = document.documentElement;
-            const version = doc.querySelector(
-              'a.toolbar-button--icon--navigation-version',
-            );
-            const listItem = version.parentElement;
+            const ulElement = document.createElement('ul');
+            const listItem = doc.querySelector(
+              '.toolbar-button--icon--navigation-version',
+            ).parentElement;
+            const version = listItem.querySelector(`a`);
+
+            // Add the list class.
+            ulElement.classList.add("toolbar-block__list");
 
             // Let the logo link to the version item url.
-            // TODO get this from settings.
-            logo.setAttribute('href', version.getAttribute('href'));
+            logo.setAttribute(
+              'href',
+              version.getAttribute('href'),
+            );
+
+            // 2. Insert the UL before the LI
+            listItem.parentNode.insertBefore(ulElement, listItem);
 
-            // Add the version button after the logo.
-            logo.insertAdjacentElement('afterend', version);
+            // 3. Move the LI into the UL
+            ulElement.appendChild(listItem);
 
-            // Remove version list item from the content menu where it was
-            // placed by the plugin.
-            listItem.remove();
+            // Add the version element (button or a) after the logo.
+            logo.insertAdjacentElement('afterend', ulElement);
 
             // Disable the menu item icon by removing the ::before style.
             version.style.setProperty('--pseudo-before-content', '');
@@ -45,14 +53,14 @@
             // Apply the change to the ::before pseudo-element
             const styleSheet = document.styleSheets[0];
             styleSheet.insertRule(
-              'a.toolbar-button.toolbar-button--icon--navigation-version::before { content: var(--pseudo-before-content); }',
+              '.toolbar-button.toolbar-button--icon--navigation-version::before { content: var(--pseudo-before-content); }',
               styleSheet.cssRules.length,
             );
 
             // Hide the version button if collapsed, otherwise it shrinks
             // the logo.
             styleSheet.insertRule(
-              '[data-admin-toolbar="collapsed"] a.toolbar-button.toolbar-button--icon--navigation-version { display: none; }',
+              '[data-admin-toolbar="collapsed"] .toolbar-button.toolbar-button--icon--navigation-version { display: none; }',
               styleSheet.cssRules.length,
             );
           });
diff --git a/navigation_extra.module b/navigation_extra.module
index 5899458..baa9a6a 100644
--- a/navigation_extra.module
+++ b/navigation_extra.module
@@ -59,8 +59,6 @@ function navigation_extra_plugin_filter_block__layout_builder_alter(array &$defi
     // Keep track of what blocks we consider safe for navigation.
     $navigation_safe = [
       'navigation_extra_local_tasks',
-      'navigation_extra_version',
-      'navigation_extra_content',
     ];
 
     $safe_definitions = array_filter($definitions, static function (array $definition, string $plugin_id) use ($navigation_safe): bool {
@@ -84,8 +82,6 @@ function navigation_extra_block_alter(&$definitions): void {
 
   $hidden = [
     'navigation_extra_local_tasks',
-    'navigation_extra_version',
-    'navigation_extra_content',
   ];
 
   foreach ($hidden as $block_id) {
diff --git a/src/Plugin/Navigation/Extra/ToolsPlugin.php b/src/Plugin/Navigation/Extra/ToolsPlugin.php
new file mode 100644
index 0000000..a4371cf
--- /dev/null
+++ b/src/Plugin/Navigation/Extra/ToolsPlugin.php
@@ -0,0 +1,154 @@
+<?php
+
+namespace Drupal\navigation_extra\Plugin\Navigation\Extra;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\navigation_extra\NavigationExtraPluginBase;
+
+/**
+ * Manages development and administration tool links.
+ *
+ * @NavigationExtraPlugin(
+ *   id = "tools",
+ *   name = @Translation("Tools"),
+ *   description = @Translation("Manages development and administration tool links."),
+ * )
+ */
+class ToolsPlugin extends NavigationExtraPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigForm(array &$form, FormStateInterface $form_state): array {
+    $elements = parent::buildConfigForm($form, $form_state);
+
+    // Weight doesn't matter for common settings.
+    $elements['weight']['#type'] = 'hidden';
+    $elements['weight']['#value'] = 0;
+
+    // If navigation_extra_tools is installed add some options to move it under
+    // version.
+    if ($this->moduleHandler->moduleExists('navigation_extra_tools')) {
+      $elements['navigation_extra_tools'] = [
+        '#type' => 'details',
+        '#title' => $this->t('Navigation extra tools'),
+      ];
+
+      $elements['navigation_extra_tools']['position'] = [
+        '#type' => 'select',
+        '#options' => [
+          ''  => $this->t('Tools menu (default)'),
+          'navigation_extra_version' => $this->t('Version menu'),
+        ],
+        '#title' => $this->t('Position'),
+        '#description' => $this->t('Place the tools links under a different menu item.'),
+        '#default_value' => $this->config->get("plugins.tools.navigation_extra_tools.position") ?? '',
+      ];
+
+      $elements['navigation_extra_tools']['group'] = [
+        '#type' => 'checkbox',
+        '#title' => $this->t('Group under Tools'),
+        '#description' => $this->t('Keep all links under a Tools item when placing under Version menu.'),
+        '#default_value' => $this->config->get('plugins.tools.navigation_extra_tools.group') ?? 0,
+      ];
+
+    }
+
+    if ($this->moduleHandler->moduleExists('devel')) {
+      $elements['devel'] = [
+        '#type' => 'details',
+        '#title' => $this->t('Devel'),
+      ];
+
+      $elements['devel']['position'] = [
+        '#type' => 'select',
+        '#options' => [
+          ''  => $this->t('Devel menu (default)'),
+          'navigation_extra_version' => $this->t('Version menu'),
+        ],
+        '#title' => $this->t('Position'),
+        '#description' => $this->t('Place the devel links under a different menu item.'),
+        '#default_value' => $this->config->get("plugins.tools.devel.position") ?? '',
+      ];
+
+      $elements['devel']['group'] = [
+        '#type' => 'checkbox',
+        '#title' => $this->t('Group under Development'),
+        '#description' => $this->t('Keep all links under a Development item when placing under Version menu.'),
+        '#default_value' => $this->config->get('plugins.tools.devel.group') ?? 0,
+      ];
+
+    }
+
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function alterDiscoveredMenuLinks(array &$links): void {
+
+    if ($this->moduleHandler->moduleExists('navigation_extra_tools')) {
+      $position = $this->config->get('plugins.tools.navigation_extra_tools.position') ?? '';
+      $group = $this->config->get('plugins.tools.navigation_extra_tools.group') ?? 0;
+
+      if ($position == 'navigation_extra_version' && $this->config->get('plugins.version.enabled')) {
+
+        if ($group) {
+          // Just change the parent of the main item.
+          $links['navigation_extra_tools.help']['parent'] = 'navigation.version';
+        }
+        else {
+          // Move all items to the new parent and remove the original.
+          foreach ($links as $id => &$link) {
+            if (str_contains($id, 'navigation_extra_tools')) {
+              if ($link['parent'] == 'navigation_extra_tools.help') {
+                $link['parent'] = 'navigation.version';
+              }
+            }
+          }
+
+          $this->removeLink('navigation_extra_tools.help', $links);
+        }
+      }
+    }
+
+    if ($this->moduleHandler->moduleExists('devel')) {
+      $position = $this->config->get('plugins.tools.devel.position') ?? '';
+      $group = $this->config->get('plugins.tools.devel.group') ?? 0;
+
+      if ($position == 'navigation_extra_version' && $this->config->get('plugins.version.enabled')) {
+
+        if ($group) {
+          $this->addLink('navigation.tools.development', [
+            'route_name' => 'devel.admin_settings',
+            'title' => $this->t('Development'),
+            'weight' => $this->config->get("plugins.tools.weight") ?? 0,
+            'parent' => 'navigation.version',
+            'options' => [
+              'attributes' => [
+                'class' => [
+                  'navigation-extra--tools',
+                  'navigation-extra--tools-development',
+                ],
+              ],
+            ],
+          ] + ($links['navigation.tools.development'] ?? []), $links);
+        }
+
+        // Move all items to the new parent.
+        foreach ($links as $id => &$link) {
+          if (str_starts_with($id, 'devel')) {
+            if ('devel' == ($link['menu_name'] ?? '') ) {
+              $link['menu_name'] = 'content';
+              $link['parent'] = $group ? 'navigation.tools.development' : 'navigation.version';
+            }
+          }
+        }
+
+
+      }
+    }
+  }
+
+}
-- 
GitLab