menu_ui.module
Same filename in other branches
File
-
core/
modules/ menu_ui/ menu_ui.module
View source
<?php
/**
* @file
*/
use Drupal\Core\Form\FormStateInterface;
use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\node\NodeTypeInterface;
use Drupal\node\NodeInterface;
/**
* Helper function to create or update a menu link for a node.
*
* @param \Drupal\node\NodeInterface $node
* Node entity.
* @param array $values
* Values for the menu link.
*/
function _menu_ui_node_save(NodeInterface $node, array $values) {
/** @var \Drupal\menu_link_content\MenuLinkContentInterface $entity */
if (!empty($values['entity_id'])) {
$entity = MenuLinkContent::load($values['entity_id']);
if ($entity->isTranslatable() && $node->isTranslatable()) {
if (!$entity->hasTranslation($node->language()
->getId())) {
$entity = $entity->addTranslation($node->language()
->getId(), $entity->toArray());
}
else {
$entity = $entity->getTranslation($node->language()
->getId());
}
}
else {
// Ensure the entity matches the node language.
$entity = $entity->getUntranslated();
$entity->set($entity->getEntityType()
->getKey('langcode'), $node->language()
->getId());
}
}
else {
// Create a new menu_link_content entity.
$entity = MenuLinkContent::create([
'link' => [
'uri' => 'entity:node/' . $node->id(),
],
'langcode' => $node->language()
->getId(),
]);
$entity->enabled->value = 1;
}
$entity->title->value = trim($values['title']);
$entity->description->value = trim($values['description']);
$entity->menu_name->value = $values['menu_name'];
$entity->parent->value = $values['parent'];
$entity->weight->value = $values['weight'] ?? 0;
$entity->isDefaultRevision($node->isDefaultRevision());
$entity->save();
}
/**
* Returns the definition for a menu link for the given node.
*
* @param \Drupal\node\NodeInterface $node
* The node entity.
*
* @return array
* An array that contains default values for the menu link form.
*/
function menu_ui_get_menu_link_defaults(NodeInterface $node) {
// Prepare the definition for the edit form.
/** @var \Drupal\node\NodeTypeInterface $node_type */
$node_type = $node->type->entity;
$menu_name = strtok($node_type->getThirdPartySetting('menu_ui', 'parent', 'main:'), ':');
$defaults = FALSE;
if ($node->id()) {
$id = FALSE;
// Give priority to the default menu
$type_menus = $node_type->getThirdPartySetting('menu_ui', 'available_menus', [
'main',
]);
if (in_array($menu_name, $type_menus)) {
$query = \Drupal::entityQuery('menu_link_content')->accessCheck(TRUE)
->condition('link.uri', 'entity:node/' . $node->id())
->condition('menu_name', $menu_name)
->sort('id', 'ASC')
->range(0, 1);
$result = $query->execute();
$id = !empty($result) ? reset($result) : FALSE;
}
// Check all allowed menus if a link does not exist in the default menu.
if (!$id && !empty($type_menus)) {
$query = \Drupal::entityQuery('menu_link_content')->accessCheck(TRUE)
->condition('link.uri', 'entity:node/' . $node->id())
->condition('menu_name', array_values($type_menus), 'IN')
->sort('id', 'ASC')
->range(0, 1);
$result = $query->execute();
$id = !empty($result) ? reset($result) : FALSE;
}
if ($id) {
$menu_link = MenuLinkContent::load($id);
$menu_link = \Drupal::service('entity.repository')->getTranslationFromContext($menu_link);
$defaults = [
'entity_id' => $menu_link->id(),
'id' => $menu_link->getPluginId(),
'title' => $menu_link->getTitle(),
'title_max_length' => $menu_link->getFieldDefinitions()['title']
->getSetting('max_length'),
'description' => $menu_link->getDescription(),
'description_max_length' => $menu_link->getFieldDefinitions()['description']
->getSetting('max_length'),
'menu_name' => $menu_link->getMenuName(),
'parent' => $menu_link->getParentId(),
'weight' => $menu_link->getWeight(),
];
}
}
if (!$defaults) {
// Get the default max_length of a menu link title from the base field
// definition.
$field_definitions = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions('menu_link_content');
$max_length = $field_definitions['title']->getSetting('max_length');
$description_max_length = $field_definitions['description']->getSetting('max_length');
$defaults = [
'entity_id' => 0,
'id' => '',
'title' => '',
'title_max_length' => $max_length,
'description' => '',
'description_max_length' => $description_max_length,
'menu_name' => $menu_name,
'parent' => '',
'weight' => 0,
];
}
return $defaults;
}
/**
* Entity form builder to add the menu information to the node.
*/
function menu_ui_node_builder($entity_type, NodeInterface $entity, &$form, FormStateInterface $form_state) {
$entity->menu = $form_state->getValue('menu');
}
/**
* Form submission handler for menu item field on the node form.
*
* @see menu_ui_form_node_form_alter()
*/
function menu_ui_form_node_form_submit($form, FormStateInterface $form_state) {
$node = $form_state->getFormObject()
->getEntity();
if (!$form_state->isValueEmpty('menu')) {
$values = $form_state->getValue('menu');
if (empty($values['enabled'])) {
if ($values['entity_id']) {
$entity = MenuLinkContent::load($values['entity_id']);
$entity->delete();
}
}
else {
// In case the menu title was left empty, fall back to the node title.
if (empty(trim($values['title']))) {
$values['title'] = $node->label();
}
// Decompose the selected menu parent option into 'menu_name' and 'parent',
// if the form used the default parent selection widget.
if (!empty($values['menu_parent'])) {
[
$menu_name,
$parent,
] = explode(':', $values['menu_parent'], 2);
$values['menu_name'] = $menu_name;
$values['parent'] = $parent;
}
_menu_ui_node_save($node, $values);
}
}
}
/**
* Validate handler for forms with menu options.
*
* @see menu_ui_form_node_type_form_alter()
*/
function menu_ui_form_node_type_form_validate(&$form, FormStateInterface $form_state) {
$available_menus = array_filter($form_state->getValue('menu_options'));
// If there is at least one menu allowed, the selected item should be in
// one of them.
if (count($available_menus)) {
$menu_item_id_parts = explode(':', $form_state->getValue('menu_parent'));
if (!in_array($menu_item_id_parts[0], $available_menus)) {
$form_state->setErrorByName('menu_parent', t('The selected menu link is not under one of the selected menus.'));
}
}
else {
$form_state->setValue('menu_parent', '');
}
}
/**
* Entity builder for the node type form with menu options.
*
* @see menu_ui_form_node_type_form_alter()
*/
function menu_ui_form_node_type_form_builder($entity_type, NodeTypeInterface $type, &$form, FormStateInterface $form_state) {
$type->setThirdPartySetting('menu_ui', 'available_menus', array_values(array_filter($form_state->getValue('menu_options'))));
$type->setThirdPartySetting('menu_ui', 'parent', $form_state->getValue('menu_parent'));
}
/**
* Implements hook_preprocess_HOOK() for block templates.
*/
function menu_ui_preprocess_block(&$variables) : void {
if ($variables['configuration']['provider'] == 'menu_ui') {
$variables['attributes']['role'] = 'navigation';
}
}
Functions
Title | Deprecated | Summary |
---|---|---|
menu_ui_form_node_form_submit | Form submission handler for menu item field on the node form. | |
menu_ui_form_node_type_form_builder | Entity builder for the node type form with menu options. | |
menu_ui_form_node_type_form_validate | Validate handler for forms with menu options. | |
menu_ui_get_menu_link_defaults | Returns the definition for a menu link for the given node. | |
menu_ui_node_builder | Entity form builder to add the menu information to the node. | |
menu_ui_preprocess_block | Implements hook_preprocess_HOOK() for block templates. | |
_menu_ui_node_save | Helper function to create or update a menu link for a node. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.