Even though you can disable individual menu items and whole hierarchies through the "Enabled toggle", JSON:API Menu Items will only show enabled menu items in the JSON:API. That means that the enabled field in the JSON:API output will always be set to true.

The reason for this behaviour is the following line https://git.drupalcode.org/project/jsonapi_menu_items/-/blob/1.2.x/src/R... which ensures that only enabled menu items will be shown.

But there is value in letting the frontend choose how to handle enabled and disabled menus. At least I'd hope to have this configurable.

Comments

dgsiegel created an issue.

topplestack’s picture

Second this. We have a situation where the menu only appears if a page is in the menu, but want the link to several pages to not appear in the menu so that the user arrives at the page via a separate navigation method.

mglaman’s picture

Are there concerns disabled items being exposed could be considered a security issue around information disclosure?

Menus are config entities; maybe we can add a third_party_settings, which adds a checkbox that says "Provide disabled menu links over the API" as an opt-in for this. How does that sound?

1000.grad.digital’s picture

i use this solution!

Core Patch:
(drupal/core/lib/Drupal/Core/Menu/MenuTreeParameters.php)

--- MenuTreeParameters.php.BAK	2025-02-10 21:55:07.477305842 +0100
+++ MenuTreeParameters.php	2025-02-10 21:58:06.924300799 +0100
@@ -178,7 +178,9 @@
    * @return $this
    */
   public function onlyEnabledLinks() {
-    $this->addCondition('enabled', 1);
+    if (!isset($this->conditions['enabled'])) {
+      $this->addCondition('enabled', 1);
+    }
     return $this;
   }

Filter Parameter:

&filter[conditions][enabled][value][]=0&filter[conditions][enabled][value][]=1&filter[conditions][enabled][operator]=IN
alexpott’s picture

This approach could be taken by the module without needing a core patch. We could move the $parameters->onlyEnabledLinks(); to before the if ($request->query->has('filter')) {. And then if you add a condition on enabled it will respect that instead.

Thinking about security. I think we're okay in terms access to links as this will still be checked so we're not giving out access if the user does not have access to link. I guess the one consideration is that maybe people have used the enabled flag as a proxy for access when it's something they can not control. I think this use-case is highly likely and therefore I think potentially we should go the other way here and prevent a user from adding enabled to the list of filter conditions and clearly document that this route only returns enabled links.

guardiola86’s picture

I had to do something like this to hide menu elements that are disabled:

use Drupal\jsonapi\Routing\Routes;
use Drupal\Core\Entity\Query\QueryInterface;

/**
 * Implements hook_entity_query_ENTITY_TYPE_alter() for menu_link_content.
 */
function hook_entity_query_menu_link_content_alter(QueryInterface $query) {
  if (\Drupal::hasRequest()) {
    $request = \Drupal::request();
    if (Routes::isJsonApiRequest($request->attributes->all())) {
      $query->condition('enabled', 1);
    }
  }
}