You are here

simple_megamenu.module in Simple Mega Menu 8

Same filename and directory in other branches
  1. 2.0.x simple_megamenu.module

File

simple_megamenu.module
View source
<?php

/**
 * @file
 * Contains simple_megamenu.module.
 */
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\simple_megamenu\Entity\SimpleMegaMenuInterface;

/**
 * Implements hook_help().
 */
function simple_megamenu_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {

    // Main module help for the simple_megamenu module.
    case 'help.page.simple_megamenu':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('Provide a Megamenu entity which can be used on Menu link content to construct a Mega Menu') . '</p>';
      return $output;
    default:
  }
}

/**
 * Implements hook_theme().
 */
function simple_megamenu_theme() {
  $theme = [];
  $theme['simple_mega_menu'] = [
    'render element' => 'elements',
    'file' => 'simple_mega_menu.page.inc',
    'template' => 'simple-mega-menu',
  ];
  $theme['simple_mega_menu_content_add_list'] = [
    'render element' => 'content',
    'variables' => [
      'content' => NULL,
    ],
    'file' => 'simple_mega_menu.page.inc',
  ];
  $theme['menu__simple_megamenu'] = [
    'render element' => 'content',
    'base hook' => 'menu',
  ];
  return $theme;
}

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function simple_megamenu_theme_suggestions_simple_mega_menu(array $variables) {
  $suggestions = [];
  $entity = $variables['elements']['#simple_mega_menu'];
  $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
  $suggestions[] = 'simple_mega_menu__' . $sanitized_view_mode;
  $suggestions[] = 'simple_mega_menu__' . $entity
    ->bundle();
  $suggestions[] = 'simple_mega_menu__' . $entity
    ->bundle() . '__' . $sanitized_view_mode;
  $suggestions[] = 'simple_mega_menu__' . $entity
    ->id();
  $suggestions[] = 'simple_mega_menu__' . $entity
    ->id() . '__' . $sanitized_view_mode;
  return $suggestions;
}

/**
 * Implements hook_preprocess_HOOK().
 */
function simple_megamenu_preprocess_block(&$variables) {

  // Menus are built with #theme 'menu__MENU_NAME' form the the MenuLinkTree
  // class. We need to build menus supported by simple mega menu with the
  // default #theme menu, to be able to add suggestions in the good order.
  if (isset($variables['content']['#menu_name'])) {
    $menu_name = $variables['content']['#menu_name'];

    /** @var \Drupal\simple_megamenu\SimpleMegaMenuHelperInterface $simple_megamenu_helper */
    $simple_megamenu_helper = \Drupal::service('simple_megamenu.helper');
    if ($simple_megamenu_helper
      ->menuIsTargetedByMegaMenuType($menu_name)) {
      $variables['content']['#theme'] = 'menu';
    }
  }
}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function simple_megamenu_theme_suggestions_menu_alter(array &$suggestions, array $variables) {
  if (!isset($variables['menu_name'])) {
    return;
  }
  $menu_name = $variables['menu_name'];
  $menu_name_sanitized = strtr($menu_name, '-', '_');

  /* @var \Drupal\simple_megamenu\SimpleMegaMenuHelperInterface $simple_megamenu_helper */
  $simple_megamenu_helper = \Drupal::service('simple_megamenu.helper');
  if ($simple_mega_menu_types = $simple_megamenu_helper
    ->getMegaMenuTypeWhichTargetMenu($menu_name)) {

    // We add the default suggestion removed in hook_preprocess_block.
    $suggestions[] = 'menu__' . $menu_name_sanitized;

    // And now our own suggestions.
    $suggestions[] = 'menu__simple_megamenu';
    $suggestions[] = 'menu__simple_megamenu__' . $menu_name_sanitized;
    $mega_menu_type_id = implode('_', array_keys($simple_mega_menu_types));
    $suggestions[] = 'menu__simple_megamenu__' . $menu_name_sanitized . '__' . $mega_menu_type_id;
  }
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function simple_megamenu_form_menu_link_content_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  /* @var \Drupal\menu_link_content\Entity\MenuLinkContent $menu_link */
  $menu_link = $form_state
    ->getFormObject()
    ->getEntity();
  $menu_name = $menu_link
    ->getMenuName();
  $menu_link_options = $menu_link->link
    ->first()->options ?: [];

  /* @var \Drupal\simple_megamenu\SimpleMegaMenuHelperInterface $simple_megamenu_helper */
  $simple_megamenu_helper = \Drupal::service('simple_megamenu.helper');
  $allowed_simple_mega_menu_types = $simple_megamenu_helper
    ->getMegaMenuTypeWhichTargetMenu($menu_name);
  $allowed_simple_mega_menu_types = array_keys($allowed_simple_mega_menu_types);
  if ($allowed_simple_mega_menu_types) {

    // The default value.
    $simple_mega_menu = NULL;

    // The default description for the entity reference form.
    $description = t('Select a simple mega menu entity to use on this menu link.');
    $simple_mega_menu_id = isset($menu_link_options['attributes']['data-simple-mega-menu']) ? $menu_link_options['attributes']['data-simple-mega-menu'] : NULL;
    if ($simple_mega_menu_id) {
      $simple_mega_menu = $simple_megamenu_helper
        ->getSimpleMegaMenu($simple_mega_menu_id);
      if ($simple_mega_menu instanceof SimpleMegaMenuInterface) {
        $destination = \Drupal::destination()
          ->getAsArray();
        $edit_path = Url::fromRoute('entity.simple_mega_menu.edit_form', [
          'simple_mega_menu' => $simple_mega_menu
            ->id(),
        ], [
          'query' => $destination,
        ])
          ->toString();
        $description = t('Select a simple mega menu entity to use on this menu link. Edit the entity referenced <a target="_blank" href="@edit_path">here</a>.', [
          '@edit_path' => $edit_path,
        ]);
      }
    }
    $form['simple_mega_menu'] = [
      '#title' => t('Simple Mega Menu'),
      '#description' => $description,
      '#weight' => $form['weight']['#weight'] + 1,
      '#type' => 'entity_autocomplete',
      '#default_value' => $simple_mega_menu,
      '#target_type' => 'simple_mega_menu',
      '#selection_handler' => 'default',
      '#selection_settings' => [
        'target_bundles' => $allowed_simple_mega_menu_types,
      ],
    ];
    $form['actions']['submit']['#submit'][] = 'simple_megamenu_menu_link_content_form_submit';
  }
}

/**
 * Submit function for menu add / edit form.
 */
function simple_megamenu_menu_link_content_form_submit($form, FormStateInterface $form_state) {
  $menu_link = $form_state
    ->getFormObject()
    ->getEntity();
  $menu_link_options = $menu_link->link
    ->first()->options;
  if ($form_state
    ->getValue('simple_mega_menu')) {
    $data_simple_mega_menu = [
      'attributes' => [
        'data-simple-mega-menu' => $form_state
          ->getValue('simple_mega_menu'),
      ],
    ];
    $menu_link->link
      ->first()->options = array_merge_recursive($menu_link_options, $data_simple_mega_menu);
  }
  else {
    if (isset($menu_link_options['attributes']['data-simple-mega-menu'])) {
      unset($menu_link_options['attributes']['data-simple-mega-menu']);
    }
    $menu_link->link
      ->first()->options = $menu_link_options;
  }
  $menu_link
    ->save();
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * For routing menu link item added by modules, we need to alter the form
 * differently than the menu link content form. The menu link item is here
 * a Plugin.
 */
function simple_megamenu_form_menu_link_edit_alter(&$form, FormStateInterface $form_state, $form_id) {

  // Currently we can't save options on Menu link plugin because
  // \Drupal\Core\Menu\MenuLinkDefault doesn't allow to override options (see
  // $overrideAllowed variables).
  // And \Drupal\Core\Menu\StaticMenuLinkOverrides::saveOverride too.
  // Once https://www.drupal.org/node/2656534 was in, we could save the Plugin
  // options definition.
  // @see https://www.drupal.org/node/2656534
  return;

  // phpcs:disable
  $build_info = $form_state
    ->getBuildInfo();

  /** @var \Drupal\Core\Menu\MenuLinkDefault $menu_link_default */
  $menu_link_default = $build_info['args'][0];
  $menu_link_options = $menu_link_default
    ->getOptions();
  $menu_name = $menu_link_default
    ->getMenuName();

  /* @var \Drupal\simple_megamenu\SimpleMegaMenuHelperInterface $simple_megamenu_helper */
  $simple_megamenu_helper = \Drupal::service('simple_megamenu.helper');
  $allowed_simple_mega_menu_types = $simple_megamenu_helper
    ->getMegaMenuTypeWhichTargetMenu($menu_name);
  $allowed_simple_mega_menu_types = array_keys($allowed_simple_mega_menu_types);
  if ($allowed_simple_mega_menu_types) {

    // The default value.
    $simple_mega_menu = NULL;

    // The default description for the entity reference form.
    $description = t('Select a simple mega menu entity to use on this menu link.');
    $simple_mega_menu_id = isset($menu_link_options['attributes']['data-simple-mega-menu']) ? $menu_link_options['attributes']['data-simple-mega-menu'] : NULL;
    if ($simple_mega_menu_id) {
      $simple_mega_menu = $simple_megamenu_helper
        ->getSimpleMegaMenu($simple_mega_menu_id);
      if ($simple_mega_menu instanceof SimpleMegaMenuInterface) {
        $destination = \Drupal::destination()
          ->getAsArray();
        $edit_path = Url::fromRoute('entity.simple_mega_menu.edit_form', [
          'simple_mega_menu' => $simple_mega_menu
            ->id(),
        ], [
          'query' => $destination,
        ])
          ->toString();
        $description = t('Select a simple mega menu entity to use on this menu link. Edit the entity referenced <a target="_blank" href="@edit_path">here</a>.', [
          '@edit_path' => $edit_path,
        ]);
      }
    }
    $form['simple_mega_menu'] = [
      '#title' => t('Simple Mega Menu'),
      '#description' => $description,
      '#type' => 'entity_autocomplete',
      '#default_value' => $simple_mega_menu,
      '#target_type' => 'simple_mega_menu',
      '#selection_handler' => 'default',
      '#selection_settings' => [
        'target_bundles' => $allowed_simple_mega_menu_types,
      ],
    ];
    $form['#submit'][] = 'simple_megamenu_menu_link_default_form_submit';
  }

  // phpcs:enable
}

/**
 * Submit function for menu add / edit form.
 */
function simple_megamenu_menu_link_default_form_submit($form, FormStateInterface $form_state) {
  $build_info = $form_state
    ->getBuildInfo();

  /* @var \Drupal\Core\Menu\MenuLinkDefault $menu_link_default */
  $menu_link_default = $build_info['args'][0];

  /* @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
  $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
  $menu_link_options = $menu_link_default
    ->getOptions();
  if ($form_state
    ->getValue('simple_mega_menu')) {
    $data_simple_mega_menu = [
      'attributes' => [
        'data-simple-mega-menu' => $form_state
          ->getValue('simple_mega_menu'),
      ],
    ];
    $options = array_merge($menu_link_options, $data_simple_mega_menu);
    $menu_link_manager
      ->updateDefinition($menu_link_default
      ->getPluginId(), [
      'options' => $options,
    ]);
  }
  else {
    if (isset($menu_link_options['attributes']['data-simple-mega-menu'])) {
      unset($menu_link_options['attributes']['data-simple-mega-menu']);
      if (empty($menu_link_options['attributes'])) {
        unset($menu_link_options['attributes']);
      }
    }
    $menu_link_manager
      ->updateDefinition($menu_link_default
      ->getPluginId(), [
      'options' => $menu_link_options,
    ]);
  }
}