View source
<?php
namespace Drupal\Core\Menu;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\DependencyInjection\DeprecatedServicePropertyTrait;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
class MenuParentFormSelector implements MenuParentFormSelectorInterface {
use StringTranslationTrait;
use DeprecatedServicePropertyTrait;
protected $deprecatedProperties = [
'entityManager' => 'entity.manager',
];
protected $menuLinkTree;
protected $entityTypeManager;
public function __construct(MenuLinkTreeInterface $menu_link_tree, EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation) {
$this->menuLinkTree = $menu_link_tree;
if ($entity_type_manager instanceof EntityManagerInterface) {
@trigger_error('Passing the entity.manager service to MenuParentFormSelector::__construct() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Pass the new dependencies instead. See https://www.drupal.org/node/2549139.', E_USER_DEPRECATED);
$this->entityTypeManager = \Drupal::entityTypeManager();
}
else {
$this->entityTypeManager = $entity_type_manager;
}
$this->stringTranslation = $string_translation;
}
public function getParentSelectOptions($id = '', array $menus = NULL, CacheableMetadata &$cacheability = NULL) {
if (!isset($menus)) {
$menus = $this
->getMenuOptions();
}
$options = [];
$depth_limit = $this
->getParentDepthLimit($id);
foreach ($menus as $menu_name => $menu_title) {
$options[$menu_name . ':'] = '<' . $menu_title . '>';
$parameters = new MenuTreeParameters();
$parameters
->setMaxDepth($depth_limit);
$tree = $this->menuLinkTree
->load($menu_name, $parameters);
$manipulators = [
[
'callable' => 'menu.default_tree_manipulators:checkNodeAccess',
],
[
'callable' => 'menu.default_tree_manipulators:checkAccess',
],
[
'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
],
];
$tree = $this->menuLinkTree
->transform($tree, $manipulators);
$this
->parentSelectOptionsTreeWalk($tree, $menu_name, '--', $options, $id, $depth_limit, $cacheability);
}
return $options;
}
public function parentSelectElement($menu_parent, $id = '', array $menus = NULL) {
$options_cacheability = new CacheableMetadata();
$options = $this
->getParentSelectOptions($id, $menus, $options_cacheability);
if ($options) {
$element = [
'#type' => 'select',
'#options' => $options,
];
if (!isset($options[$menu_parent])) {
list($menu_name, $parent) = explode(':', $menu_parent, 2);
$menu_parent = $menu_name . ':';
}
if (isset($options[$menu_parent])) {
$element += [
'#default_value' => $menu_parent,
];
}
$options_cacheability
->applyTo($element);
return $element;
}
return [];
}
protected function getParentDepthLimit($id) {
if ($id) {
$limit = $this->menuLinkTree
->maxDepth() - $this->menuLinkTree
->getSubtreeHeight($id);
}
else {
$limit = $this->menuLinkTree
->maxDepth() - 1;
}
return $limit;
}
protected function parentSelectOptionsTreeWalk(array $tree, $menu_name, $indent, array &$options, $exclude, $depth_limit, CacheableMetadata &$cacheability = NULL) {
foreach ($tree as $element) {
if ($element->depth > $depth_limit) {
break;
}
if ($cacheability) {
$cacheability = $cacheability
->merge(CacheableMetadata::createFromObject($element->access))
->merge(CacheableMetadata::createFromObject($element->link));
}
if (!$element->access
->isAllowed()) {
continue;
}
$link = $element->link;
if ($link
->getPluginId() != $exclude) {
$title = $indent . ' ' . Unicode::truncate($link
->getTitle(), 30, TRUE, FALSE);
if (!$link
->isEnabled()) {
$title .= ' (' . $this
->t('disabled') . ')';
}
$options[$menu_name . ':' . $link
->getPluginId()] = $title;
if (!empty($element->subtree)) {
$this
->parentSelectOptionsTreeWalk($element->subtree, $menu_name, $indent . '--', $options, $exclude, $depth_limit, $cacheability);
}
}
}
}
protected function getMenuOptions(array $menu_names = NULL) {
$menus = $this->entityTypeManager
->getStorage('menu')
->loadMultiple($menu_names);
$options = [];
foreach ($menus as $menu) {
$options[$menu
->id()] = $menu
->label();
}
return $options;
}
}