class MenuParentFormSelector
Default implementation of the menu parent form selector service.
The form selector is a list of all appropriate menu links.
Hierarchy
- class \Drupal\Core\Menu\MenuParentFormSelector implements \Drupal\Core\Menu\MenuParentFormSelectorInterface uses \Drupal\Core\StringTranslation\StringTranslationTrait
 
Expanded class hierarchy of MenuParentFormSelector
1 file declares its use of MenuParentFormSelector
- ViewListBuilderTest.php in core/
modules/ views_ui/ tests/ src/ Unit/ ViewListBuilderTest.php  
1 string reference to 'MenuParentFormSelector'
- core.services.yml in core/
core.services.yml  - core/core.services.yml
 
1 service uses MenuParentFormSelector
File
- 
              core/
lib/ Drupal/ Core/ Menu/ MenuParentFormSelector.php, line 16  
Namespace
Drupal\Core\MenuView source
class MenuParentFormSelector implements MenuParentFormSelectorInterface {
  use StringTranslationTrait;
  
  /**
   * The menu link tree service.
   *
   * @var \Drupal\Core\Menu\MenuLinkTreeInterface
   */
  protected $menuLinkTree;
  
  /**
   * The entity type manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;
  
  /**
   * Constructs a \Drupal\Core\Menu\MenuParentFormSelector.
   *
   * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_link_tree
   *   The menu link tree service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager service.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation service.
   */
  public function __construct(MenuLinkTreeInterface $menu_link_tree, EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation) {
    $this->menuLinkTree = $menu_link_tree;
    $this->entityTypeManager = $entity_type_manager;
    $this->stringTranslation = $string_translation;
  }
  
  /**
   * {@inheritdoc}
   */
  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;
  }
  
  /**
   * {@inheritdoc}
   */
  public function parentSelectElement($menu_parent, $id = '', ?array $menus = NULL) {
    $options_cacheability = new CacheableMetadata();
    $options = $this->getParentSelectOptions($id, $menus, $options_cacheability);
    // If no options were found, there is nothing to select.
    if ($options) {
      $element = [
        '#type' => 'select',
        '#options' => $options,
      ];
      if (!isset($options[$menu_parent])) {
        // The requested menu parent cannot be found in the menu anymore. Try
        // setting it to the top level in the current menu.
        [$menu_name] = explode(':', $menu_parent, 2);
        $menu_parent = $menu_name . ':';
      }
      if (isset($options[$menu_parent])) {
        // Only provide the default value if it is valid among the options.
        $element += [
          '#default_value' => $menu_parent,
        ];
      }
      $options_cacheability->applyTo($element);
      return $element;
    }
    return [];
  }
  
  /**
   * Returns the maximum depth of the possible parents of the menu link.
   *
   * @param string $id
   *   The menu link plugin ID or an empty value for a new link.
   *
   * @return int
   *   The depth related to the depth of the given menu link.
   */
  protected function getParentDepthLimit($id) {
    if ($id) {
      $limit = $this->menuLinkTree
        ->maxDepth() - $this->menuLinkTree
        ->getSubtreeHeight($id);
    }
    else {
      $limit = $this->menuLinkTree
        ->maxDepth() - 1;
    }
    return $limit;
  }
  
  /**
   * Iterates over all items in the tree to prepare the parents select options.
   *
   * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree
   *   The menu tree.
   * @param string $menu_name
   *   The menu name.
   * @param string $indent
   *   The indentation string used for the label.
   * @param array $options
   *   The select options.
   * @param string $exclude
   *   An excluded menu link.
   * @param int $depth_limit
   *   The maximum depth of menu links considered for the select options.
   * @param \Drupal\Core\Cache\CacheableMetadata|null &$cacheability
   *   The object to add cacheability metadata to, if not NULL.
   */
  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) {
        // Don't iterate through any links on this level.
        break;
      }
      // Collect the cacheability metadata of the access result, as well as the
      // link.
      if ($cacheability) {
        $cacheability = $cacheability->merge(CacheableMetadata::createFromObject($element->access))
          ->merge(CacheableMetadata::createFromObject($element->link));
      }
      // Only show accessible links.
      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);
        }
      }
    }
  }
  
  /**
   * Gets a list of menu names for use as options.
   *
   * @param array $menu_names
   *   (optional) Array of menu names to limit the options, or NULL to load all.
   *
   * @return array
   *   Keys are menu names (ids) values are the menu labels.
   */
  protected function getMenuOptions(?array $menu_names = NULL) {
    $menus = $this->entityTypeManager
      ->getStorage('menu')
      ->loadMultiple($menu_names);
    $options = [];
    /** @var \Drupal\system\MenuInterface[] $menus */
    foreach ($menus as $menu) {
      $options[$menu->id()] = $menu->label();
    }
    return $options;
  }
}
Members
| Title Sort descending | Modifiers | Object type | Summary | Overriden Title | Overrides | 
|---|---|---|---|---|---|
| MenuParentFormSelector::$entityTypeManager | protected | property | The entity type manager service. | ||
| MenuParentFormSelector::$menuLinkTree | protected | property | The menu link tree service. | ||
| MenuParentFormSelector::getMenuOptions | protected | function | Gets a list of menu names for use as options. | ||
| MenuParentFormSelector::getParentDepthLimit | protected | function | Returns the maximum depth of the possible parents of the menu link. | ||
| MenuParentFormSelector::getParentSelectOptions | public | function | Gets the options for a select element to choose a menu and parent. | Overrides MenuParentFormSelectorInterface::getParentSelectOptions | |
| MenuParentFormSelector::parentSelectElement | public | function | Gets a form element to choose a menu and parent. | Overrides MenuParentFormSelectorInterface::parentSelectElement | |
| MenuParentFormSelector::parentSelectOptionsTreeWalk | protected | function | Iterates over all items in the tree to prepare the parents select options. | ||
| MenuParentFormSelector::__construct | public | function | Constructs a \Drupal\Core\Menu\MenuParentFormSelector. | ||
| StringTranslationTrait::$stringTranslation | protected | property | The string translation service. | 3 | |
| StringTranslationTrait::formatPlural | protected | function | Formats a string containing a count of items. | ||
| StringTranslationTrait::getNumberOfPlurals | protected | function | Returns the number of plurals supported by a given language. | ||
| StringTranslationTrait::getStringTranslation | protected | function | Gets the string translation service. | ||
| StringTranslationTrait::setStringTranslation | public | function | Sets the string translation service to use. | 2 | |
| StringTranslationTrait::t | protected | function | Translates a string to the current language or to a given language. | 
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.