3

I have tried to GET main menu with rest path "/entity/menu/{menu}" but all I get in response JSON is a menu properties as uuid,language,id... without menu structure (links...).

{
  "uuid": "93d5d0a9-a962-4448-af01-c38aa3ebda22"
  "langcode": "en"
  "status": true
  "dependencies": [0]
  "_core": {
    "default_config_hash": "Q2Ra3jfoIVk0f3SjxJX61byRQFVBAbpzYDQOiY-kno8"
  }
  "id": "main"
  "label": "Main navigation"
  "description": "Site section links"
  "locked": true
}

I have also tried to GET menu through block (main menu is also a block) with "/entity/block/{block}" but without luck.

<br />
<b>Fatal error</b>:  Call to a member function access() on null in    <b>C:\Apache\work\test\core\modules\rest\src\Plugin\rest\resource\EntityResource.php</b> on line <b>52</b><br />

Is it possible to GET whole main menu with it's sub-menus in JSON format?

Thanks in advance. Danijel

2 Answers 2

1

There is no such thing. Even if it would work, getting a menu would just give you the menu config entity, there's really nothing useful in there except the label.

You have to write your own rest resource plugin or simply a controller and return the data you need.

0
4

I ended up creating a module that does the basics for getting a menu via rest. I can just put the menus machine name in the URL and it will give me the title, url and weight in JSON format. I uploaded it to github so you can test it out. It is by no means ready for productions web sites. I was just messing around with angular and REST in D8.

Using angular, I would get the menu using the new URL resource after enabling the module and route resource 'entity/restmenu/{menu-name}?_format=hal_json in your case entity/restmenu/main?_format=hal_json

app.controller('MainController', function($scope, $http) {
  $http.defaults.headers.common.Authorization = 'Basic YWRtaW46YWRtaW4=';
  $scope.menuData = $http.get('entity/restmenu/main?_format=hal_json').then(function(response) {
    $scope.menuData = JSON.parse(JSON.parse(response.data));
  });
});

https://github.com/rondog/rest-menu

<?php

/**
 * @file
 * Contains \Drupal\rest_menu\Plugin\rest\resource\rest_menu.
 */

namespace Drupal\rest_menu\Plugin\rest\resource;

use Drupal\Core\Render\HtmlResponse;
use Drupal\Core\Menu;
use Drupal\Core\MenuTreeParameters;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Psr\Log\LoggerInterface;

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "restmenu_resource",
 *   label = @Translation("REST Menu Resource"),
 *   uri_paths = {
 *     "canonical" = "/entity/restmenu/{menu}"
 *   }
 * )
 */
class RESTMenuResource extends ResourceBase {
  /**
   * A current user instance.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * Constructs a Drupal\rest\Plugin\ResourceBase object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param array $serializer_formats
   *   The available serialization formats.
   * @param \Psr\Log\LoggerInterface $logger
   *   A logger instance.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   A current user instance.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    array $serializer_formats,
    LoggerInterface $logger,
    AccountProxyInterface $current_user) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->getParameter('serializer.formats'),
      $container->get('logger.factory')->get('rest'),
      $container->get('current_user')
    );
  }
  /**
   * Responds to GET requests.
   *
   * Returns a list of bundles for specified entity.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
   *   Throws exception expected.
   */
  public function get($entity) {
    $menu_name = $entity;
    $menu_parameters = \Drupal::menuTree()->getCurrentRouteMenuTreeParameters($menu_name);
    $tree = \Drupal::menuTree()->load($menu_name, $menu_parameters);
    $result = array();

    foreach ($tree as $element) {
      $link = $element->link;
      array_push($result, array(
          'title' => $link->getTitle(),
          'url' => $link->getUrlObject()->getInternalPath(),
          'weight' => $link->getWeight()
        )
      );
    }
    return new ResourceResponse(json_encode($result));
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.