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);
}
}
}
