improvements-2.x-dev/modules/improvements_menu/improvements_menu.link_advanced_settings.inc
modules/improvements_menu/improvements_menu.link_advanced_settings.inc
<?php use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Menu\MenuLinkInterface; use Drupal\Core\Render\Element\Checkboxes; use Drupal\Core\Url; use Drupal\druhels\DrupalHelper; use Drupal\menu_link_content\Form\MenuLinkContentForm; use Drupal\menu_link_content\MenuLinkContentInterface; use Drupal\menu_ui\Form\MenuLinkEditForm; use Drupal\menu_ui\MenuForm; use Drupal\system\Entity\Menu; use Drupal\system\MenuInterface; /** * Add advanced settings to menu link form. */ function improvements_menu_link_advanced_settings_form_alter(array &$form, FormStateInterface $form_state): void { $form_object = $form_state->getFormObject(); if ($form_object instanceof MenuLinkContentForm) { $menu_link = $form_object->getEntity(); /** @var MenuLinkContentInterface $menu_link */ } elseif ($form_object instanceof MenuLinkEditForm) { $menu_link = $form_state->getBuildInfo()['args'][0]; /** @var MenuLinkInterface $menu_link */ } else { return; } $menu_link_advanced_options = improvements_menu_get_menu_link_advanced_options($menu_link); $form['advanced'] = [ '#type' => 'details', '#title' => t('Advanced settings'), '#weight' => 20, ]; $form['advanced'] += \Drupal::moduleHandler()->invokeAll('menu_link_third_party_settings_form', [$menu_link, $menu_link_advanced_options]); $form_state->set('menu_link', $menu_link); // Content menu link if ($menu_link instanceof MenuLinkContentInterface) { $form['actions']['submit']['#submit'][] = 'improvements_menu_link_form_advanced_settings_submit'; } // Module menu link else { $form['#submit'][] = 'improvements_menu_link_form_advanced_settings_submit'; } } /** * Return menu link advanced options. */ function improvements_menu_get_menu_link_advanced_options(MenuLinkContentInterface|MenuLinkInterface $menu_link, array $menu_links_advanced_options = NULL): array { if ($menu_links_advanced_options === NULL) { $menu = Menu::load($menu_link->getMenuName()); /** @var MenuInterface $menu */ $menu_links_advanced_options = $menu->getThirdPartySetting('improvements', 'links_options', []); } $menu_link_options_key = str_replace('.', '_', $menu_link->getPluginId()); return $menu_links_advanced_options[$menu_link_options_key] ?? []; } /** * Implements hook_menu_link_third_party_settings_form(). * * @see improvements_menu_link_advanced_settings_form_alter() */ function improvements_menu_menu_link_third_party_settings_form($menu_link, array $menu_link_advanced_options): array { $form['open_in_dialog'] = [ '#type' => 'checkbox', '#title' => t('Open in dialog'), '#default_value' => $menu_link_advanced_options['open_in_dialog'] ?? FALSE, ]; $form['hide_href'] = [ '#type' => 'checkbox', '#title' => t('Hide href attribute'), '#default_value' => $menu_link_advanced_options['hide_href'] ?? FALSE, '#states' => [ 'visible' => [ ':input[name="open_in_dialog"]' => [ 'checked' => TRUE, ], ], ], ]; $form['target_blank'] = [ '#type' => 'checkbox', '#title' => t('Open in new tab'), '#default_value' => $menu_link_advanced_options['target_blank'] ?? FALSE, ]; $form['item_class'] = [ '#type' => 'textfield', '#title' => t('Item class'), '#default_value' => $menu_link_advanced_options['item_class'] ?? '', ]; $form['link_class'] = [ '#type' => 'textfield', '#title' => t('Link class'), '#default_value' => $menu_link_advanced_options['link_class'] ?? '', ]; $language_filter_options = []; foreach (\Drupal::languageManager()->getLanguages() as $language) { $language_filter_options[$language->getId()] = $language->getName(); } $form['language_filter'] = [ '#type' => 'checkboxes', '#title' => t('Language'), '#description' => t('Show menu item only for checked langauges'), '#options' => $language_filter_options, '#default_value' => $menu_link_advanced_options['language_filter'] ?? [], ]; return $form; } /** * Menu link form submit callback. */ function improvements_menu_link_form_advanced_settings_submit(array &$form, FormStateInterface $form_state): void { // Save advanced options $menu_link = $form_state->get('menu_link'); /** @var MenuLinkContentInterface|MenuLinkInterface $menu_link */ $menu_link_advanced_options = \Drupal::moduleHandler()->invokeAll('menu_link_third_party_settings_form_submit', [$menu_link, $form_state]); improvements_menu_save_menu_link_advanced_options($menu_link, $menu_link_advanced_options); } /** * Implements hook_menu_link_third_party_settings_form_submit(). * * @see improvements_menu_link_form_advanced_settings_submit() */ function improvements_menu_link_third_party_settings_form_submit($menu_link, FormStateInterface $form_state): array { $menu_link_advanced_options = []; if ($form_state->getValue('open_in_dialog')) { $menu_link_advanced_options['open_in_dialog'] = TRUE; } if ($form_state->getValue('hide_href')) { $menu_link_advanced_options['hide_href'] = TRUE; } if ($form_state->getValue('target_blank')) { $menu_link_advanced_options['target_blank'] = TRUE; } if ($item_class = $form_state->getValue('item_class')) { $menu_link_advanced_options['item_class'] = $item_class; } if ($link_class = $form_state->getValue('link_class')) { $menu_link_advanced_options['link_class'] = $link_class; } if ($language_filter = $form_state->getValue('language_filter')) { $menu_link_advanced_options['language_filter'] = Checkboxes::getCheckedCheckboxes($language_filter); } return $menu_link_advanced_options; } /** * Save menu links advanced options. * * @param MenuLinkContentInterface|MenuLinkInterface $menu_link * @param array|null $menu_link_advanced_options */ function improvements_menu_save_menu_link_advanced_options($menu_link, array $menu_link_advanced_options = []): void { $menu = Menu::load($menu_link->getMenuName()); /** @var MenuInterface $menu */ $menu_link_id = $menu_link->getPluginId(); $menu_link_key = str_replace('.', '_', $menu_link_id); $menu_links_advanced_options = $menu->getThirdPartySetting('improvements', 'links_options', []); if ($menu_link_advanced_options) { $menu_links_advanced_options[$menu_link_key] = $menu_link_advanced_options; } elseif (isset($menu_links_advanced_options[$menu_link_key])) { unset($menu_links_advanced_options[$menu_link_key]); } $menu->setThirdPartySetting('improvements', 'links_options', $menu_links_advanced_options); $menu->save(); } /** * Implements hook_ENTITY_TYPE_delete(): menu_link_content. */ function improvements_menu_link_content_delete(MenuLinkContentInterface $menu_link): void { improvements_menu_save_menu_link_advanced_options($menu_link); } /** * Preprocess menu item. * * @see improvements_preprocess_menu_items() */ function improvements_menu_link_advanced_settings_preprocess_menu_item(array &$menu_item, array &$menu_vars, array $menu_links_advanced_options): void { $menu_link = $menu_item['original_link']; /** @var MenuLinkContentInterface|MenuLinkInterface $menu_link */ $menu_link_advanced_options = improvements_menu_get_menu_link_advanced_options($menu_link, $menu_links_advanced_options); $menu_item_url = $menu_item['url']; /** @var Url $menu_item_url */ $menu_link_attributes = []; if (!$menu_link_advanced_options) { return; } // Option "Language" if (!empty($menu_link_advanced_options['language_filter'])) { if (!in_array(DrupalHelper::getCurrentLangcode(), $menu_link_advanced_options['language_filter'], TRUE)) { $menu_item['access'] = FALSE; return; } } // Option "Open in dialog" if (!empty($menu_link_advanced_options['open_in_dialog'])) { $menu_link_attributes['class'][] = 'use-ajax'; $menu_link_attributes['data-dialog-type'] = 'modal'; $menu_vars['#attached']['library'][] = 'core/drupal.ajax'; } // Option "Hide href attribute" if (!empty($menu_link_advanced_options['hide_href'])) { $menu_link_attributes['data-ajax-url'] = $menu_item_url->toString(); // Replace url $new_menu_item_url = Url::fromUri('internal:#<none>'); $new_menu_item_url->setOption('attributes', $menu_item_url->getOption('attributes')); $menu_item['url'] = $new_menu_item_url; $menu_item_url = $menu_item['url']; } // Option "Target blank" if (!empty($menu_link_advanced_options['target_blank'])) { $menu_link_attributes['target'] = '_blank'; } // Option "Item class" if (!empty($menu_link_advanced_options['item_class'])) { $menu_item['attributes']->addClass($menu_link_advanced_options['item_class']); } // Option "Link class" if (!empty($menu_link_advanced_options['link_class'])) { $menu_link_attributes['class'][] = $menu_link_advanced_options['link_class']; } // Merge url attributes if ($menu_link_attributes) { $menu_item_url->mergeOptions(['attributes' => $menu_link_attributes]); } $menu_item['advanced_options'] = $menu_link_advanced_options; } /** * Implements hook_form_FORM_ID_alter(): menu_edit_form. * * @see improvements_form_menu_edit_form_alter() */ function improvements_menu_link_advanced_form_menu_edit_form_alter(array &$form, FormStateInterface $form_state): void { $form['#entity_builders'][] = 'improvements_menu_link_advanced_menu_edit_form_entity_builder'; } /** * Menu form #entity_builders callback. * * @see improvements_menu_link_advanced_form_menu_edit_form_alter() */ function improvements_menu_link_advanced_menu_edit_form_entity_builder(string $entity_type, MenuInterface $menu, array &$form, FormStateInterface $form_state): void { // Fix bug when other modules remove all third_party_settings data if ($form_state->hasValue('third_party_settings')) { $menu_form_object = $form_state->getFormObject(); /** @var MenuForm $menu_form_object */ $old_menu = $menu_form_object->getEntity(); /** @var MenuInterface $old_menu */ $menu_improvements_module_third_party_settings = $old_menu->getThirdPartySettings('improvements'); foreach ($menu_improvements_module_third_party_settings as $setting_name => $setting_value) { $menu->setThirdPartySetting('improvements', $setting_name, $setting_value); } } }