View source
<?php
namespace Drupal\rest_menu_items\Plugin\rest\resource;
use Drupal\Core\Cache\CacheableResponseInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Menu\MenuLinkInterface;
use Drupal\path_alias\AliasManagerInterface;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Psr\Log\LoggerInterface;
class RestMenuItemsResource extends ResourceBase {
protected $aliasManager;
protected $configFactory;
protected $entityTypeManager;
protected $menuItems = [];
protected $maxDepth = 0;
protected $minDepth = 1;
public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, AliasManagerInterface $alias_manager, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entityTypeManager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
$this->aliasManager = $alias_manager;
$this->configFactory = $config_factory;
$this->entityTypeManager = $entityTypeManager;
}
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('path_alias.manager'), $container
->get('config.factory'), $container
->get('entity_type.manager'));
}
public function get($menu_name = NULL) {
if ($menu_name) {
$this
->setup();
$parameters = new MenuTreeParameters();
$parameters
->onlyEnabledLinks();
if (!empty($this->maxDepth)) {
$parameters
->setMaxDepth($this->maxDepth);
}
if (!empty($this->minDepth)) {
$parameters
->setMinDepth($this->minDepth);
}
$menu_tree = \Drupal::menuTree();
$tree = $menu_tree
->load($menu_name, $parameters);
if (empty($tree)) {
$response = new ResourceResponse($tree);
if ($response instanceof CacheableResponseInterface) {
$response
->addCacheableDependency(new RestMenuItemsCacheableDependency($menu_name, $this->minDepth, $this->maxDepth));
}
return $response;
}
$manipulators = [
[
'callable' => 'menu.default_tree_manipulators:checkAccess',
],
[
'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
],
];
$tree = $menu_tree
->transform($tree, $manipulators);
$menu = $menu_tree
->build($tree);
if (empty($menu['#items'])) {
return new ResourceResponse([]);
}
$this
->getMenuItems($menu['#items'], $this->menuItems);
$response = new ResourceResponse(array_values($this->menuItems));
if ($response instanceof CacheableResponseInterface) {
$response
->addCacheableDependency(new RestMenuItemsCacheableDependency($menu_name, $this->minDepth, $this->maxDepth));
}
return $response;
}
throw new HttpException($this
->t("Menu name was not provided"));
}
protected function getMenuItems(array $tree, array &$items = []) {
$config = $this->configFactory
->get('rest_menu_items.config');
$outputValues = $config
->get('output_values');
foreach ($tree as $item_value) {
$org_link = $item_value['original_link'];
$url = $item_value['url'];
$newValue = [];
foreach ($outputValues as $valueKey) {
if (!empty($valueKey)) {
$this
->getElementValue($newValue, $valueKey, $org_link, $url);
}
}
if (!empty($item_value['below'])) {
$newValue['below'] = [];
$this
->getMenuItems($item_value['below'], $newValue['below']);
}
$items[] = $newValue;
}
}
private function setup() {
$request = \Drupal::request();
$max = $request
->get('max_depth');
if (!empty($max)) {
$this->maxDepth = $max;
}
$min = $request
->get('min_depth');
if (!empty($min)) {
$this->minDepth = $min;
}
}
protected function getElementValue(array &$returnArray, $key, MenuLinkInterface $link, Url $url) {
$config = $this->configFactory
->get('rest_menu_items.config');
$external = $url
->isExternal();
$routed = $url
->isRouted();
$existing = TRUE;
$value = NULL;
$itemsToRemoveWhenNoLink = [
'uri',
'alias',
'absolute',
'relative',
];
if (!$external && $routed && $url
->getRouteName() === '<nolink>' && in_array($key, $itemsToRemoveWhenNoLink)) {
return;
}
if ($external || !$routed) {
$uri = $url
->getUri();
}
else {
try {
$uri = $url
->getInternalPath();
} catch (\UnexpectedValueException $e) {
$uri = $relative = Url::fromUri($url
->getUri())
->toString();
$existing = FALSE;
}
}
switch ($key) {
case 'key':
$value = $link
->getDerivativeId();
if (empty($value)) {
$value = $link
->getBaseId();
}
break;
case 'title':
$value = $link
->getTitle();
break;
case 'description':
$value = $link
->getDescription();
break;
case 'uri':
$value = $uri;
break;
case 'alias':
if ($routed) {
$value = ltrim($this->aliasManager
->getAliasByPath("/{$uri}"), '/');
}
break;
case 'external':
$value = $external;
break;
case 'absolute':
$base_url = $config
->get('base_url');
if ($external) {
$value = $uri;
}
elseif (!$routed) {
if (empty($base_url)) {
$url
->setAbsolute();
}
$value = $url
->toString(TRUE)
->getGeneratedUrl();
if (!empty($base_url)) {
$value = $base_url . $value;
}
}
else {
$options = [];
if (empty($base_url)) {
$options = [
'absolute' => TRUE,
];
}
$value = Url::fromUri('internal:/' . $uri, $options)
->toString(TRUE)
->getGeneratedUrl();
if (!empty($base_url)) {
$value = $base_url . $value;
}
}
break;
case 'relative':
if (!$external) {
$value = Url::fromUri('internal:/' . $uri, [
'absolute' => FALSE,
])
->toString(TRUE)
->getGeneratedUrl();
}
if (!$routed) {
$url
->setAbsolute(FALSE);
$value = $url
->toString(TRUE)
->getGeneratedUrl();
}
if (!$existing) {
$value = Url::fromUri($url
->getUri())
->toString();
}
break;
case 'existing':
$value = $existing;
break;
case 'weight':
$value = $link
->getWeight();
break;
case 'expanded':
$value = $link
->isExpanded();
break;
case 'enabled':
$value = $link
->isEnabled();
break;
case 'uuid':
if (!$external && $routed) {
$params = Url::fromUri('internal:/' . $uri)
->getRouteParameters();
$entity_type = key($params);
if (!empty($entity_type) && $this->entityTypeManager
->hasDefinition($entity_type)) {
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($params[$entity_type]);
$value = $entity
->uuid();
}
}
break;
case 'options':
$value = $link
->getOptions();
break;
}
$addFragmentElements = [
'alias',
'absolute',
'relative',
];
if (!empty($config
->get('add_fragment')) && in_array($key, $addFragmentElements)) {
$this
->addFragment($value, $link);
}
$returnArray[$key] = $value;
}
private function addFragment(&$value, $link) {
$options = $link
->getOptions();
if (!empty($options) && isset($options['fragment'])) {
$value .= '#' . $options['fragment'];
}
}
}