navigation.module

Same filename and directory in other branches
  1. 11.x core/modules/navigation/navigation.module

Primary module hooks for navigation module.

File

core/modules/navigation/navigation.module

View source
<?php


/**
 * @file
 * Primary module hooks for navigation module.
 */

use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\navigation\NavigationContentLinks;
use Drupal\navigation\NavigationRenderer;
use Drupal\navigation\Plugin\SectionStorage\NavigationSectionStorage;
use Drupal\navigation\RenderCallbacks;

/**
 * Implements hook_help().
 */
function navigation_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.navigation':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Navigation module provides a left-aligned, collapsible, vertical sidebar navigation.') . '</p>';
      $output .= '<p>' . t('For more information, see the <a href=":docs">online documentation for the Navigation module</a>.', [
        ':docs' => 'https://www.drupal.org/project/navigation',
      ]) . '</p>';
      return $output;
  }
  $configuration_route = 'layout_builder.navigation.';
  if (!$route_match->getRouteObject()
    ->getOption('_layout_builder') || !str_starts_with($route_name, $configuration_route)) {
    return layout_builder_help($route_name, $route_match);
  }
  if (str_starts_with($route_name, $configuration_route)) {
    $output = '<p>' . t('This layout builder tool allows you to configure the blocks in the navigation toolbar.') . '</p>';
    $output .= '<p>' . t('Forms and links inside the content of the layout builder tool have been disabled.') . '</p>';
    return $output;
  }
}

/**
 * Implements hook_page_top().
 */
function navigation_page_top(array &$page_top) {
  if (!\Drupal::currentUser()->hasPermission('access navigation')) {
    return;
  }
  $navigation_renderer = \Drupal::service('navigation.renderer');
  assert($navigation_renderer instanceof NavigationRenderer);
  $navigation_renderer->removeToolbar($page_top);
  if (\Drupal::routeMatch()->getRouteName() !== 'layout_builder.navigation.view') {
    // Don't render the admin toolbar if in layout edit mode.
    $navigation_renderer->buildNavigation($page_top);
    $navigation_renderer->buildTopBar($page_top);
    return;
  }
  // But if in layout mode, add an empty element to leave space. We need to use
  // an empty .admin-toolbar element because the css uses the adjacent sibling
  // selector. The actual rendering of the navigation blocks/layout occurs in
  // the layout form.
  $page_top['navigation'] = [
    '#type' => 'html_tag',
    '#tag' => 'aside',
    '#attributes' => [
      'class' => 'admin-toolbar',
    ],
  ];
  $navigation_renderer->buildTopBar($page_top);
}

/**
 * Implements hook_module_implements_alter().
 */
function navigation_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'page_top') {
    $group = $implementations['navigation'];
    unset($implementations['navigation']);
    $implementations['navigation'] = $group;
  }
  if ($hook == 'help') {
    // We take over the layout_builder hook_help().
    unset($implementations['layout_builder']);
  }
}

/**
 * Implements hook_theme().
 */
function navigation_theme($existing, $type, $theme, $path) {
  $items['top_bar'] = [
    'variables' => [
      'local_tasks' => [],
    ],
  ];
  $items['top_bar_local_tasks'] = [
    'variables' => [
      'local_tasks' => [],
    ],
  ];
  $items['top_bar_local_task'] = [
    'variables' => [
      'link' => [],
    ],
  ];
  $items['big_pipe_interface_preview__navigation_shortcut_lazy_builder_lazyLinks__Shortcuts'] = [
    'variables' => [
      'callback' => NULL,
      'arguments' => NULL,
      'preview' => NULL,
    ],
    'base hook' => 'big_pipe_interface_preview',
  ];
  $items['block__navigation'] = [
    'render element' => 'elements',
    'base hook' => 'block',
  ];
  $items['navigation_menu'] = [
    'base hook' => 'menu',
    'variables' => [
      'menu_name' => NULL,
      'items' => [],
      'attributes' => [],
    ],
  ];
  $items['menu_region__footer'] = [
    'variables' => [
      'help' => NULL,
      'items' => [],
      'title' => NULL,
      'menu_name' => NULL,
    ],
  ];
  return $items;
}

/**
 * Implements hook_menu_links_discovered_alter().
 */
function navigation_menu_links_discovered_alter(&$links) {
  $navigation_links = \Drupal::classResolver(NavigationContentLinks::class);
  assert($navigation_links instanceof NavigationContentLinks);
  $navigation_links->addMenuLinks($links);
  $navigation_links->removeAdminContentLink($links);
  $navigation_links->removeHelpLink($links);
}

/**
 * Implements hook_block_build_BASE_BLOCK_ID_alter().
 */
function navigation_block_build_local_tasks_block_alter(array &$build, BlockPluginInterface $block) {
  $navigation_renderer = \Drupal::service('navigation.renderer');
  assert($navigation_renderer instanceof NavigationRenderer);
  $navigation_renderer->removeLocalTasks($build, $block);
}

/**
 * Implements hook_plugin_filter_TYPE__CONSUMER_alter().
 *
 * Curate the blocks available in the Layout Builder "Add Block" UI.
 */
function navigation_plugin_filter_block__layout_builder_alter(array &$definitions, array $extra) {
  if (($extra['section_storage'] ?? NULL) instanceof NavigationSectionStorage) {
    // Remove all blocks other than the ones we support.
    $navigation_safe = [
      'navigation_user',
      'navigation_shortcuts',
      'navigation_menu',
    ];
    $definitions = array_filter($definitions, static function (array $definition, string $plugin_id) use ($navigation_safe) : bool {
      [
        $base_plugin_id,
      ] = explode(PluginBase::DERIVATIVE_SEPARATOR, $plugin_id);
      return in_array($base_plugin_id, $navigation_safe, TRUE);
    }, ARRAY_FILTER_USE_BOTH);
  }
}

/**
 * Implements hook_plugin_filter_TYPE__CONSUMER_alter().
 */
function navigation_plugin_filter_layout__layout_builder_alter(array &$definitions, array $extra) {
  if (($extra['section_storage'] ?? NULL) instanceof NavigationSectionStorage) {
    // We don't allow adding a new section.
    $definitions = [];
  }
}

/**
 * Implements hook_block_alter().
 */
function navigation_block_alter(&$definitions) : void {
  $hidden = [
    'navigation_user',
    'navigation_shortcuts',
    'navigation_menu',
  ];
  foreach ($hidden as $block_id) {
    if (isset($definitions[$block_id])) {
      $definitions[$block_id]['_block_ui_hidden'] = TRUE;
    }
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function template_preprocess_navigation(array &$variables) : void {
  $variables['hide_logo'] = $variables['content']['#hide_logo'] ?? TRUE;
}

/**
 * Implements hook_element_info_alter().
 */
function navigation_element_info_alter(array &$info) {
  if (array_key_exists('layout_builder', $info)) {
    $info['layout_builder']['#pre_render'][] = [
      RenderCallbacks::class,
      'alterLayoutBuilder',
    ];
  }
}

Functions

Title Deprecated Summary
navigation_block_alter Implements hook_block_alter().
navigation_block_build_local_tasks_block_alter Implements hook_block_build_BASE_BLOCK_ID_alter().
navigation_element_info_alter Implements hook_element_info_alter().
navigation_help Implements hook_help().
navigation_menu_links_discovered_alter Implements hook_menu_links_discovered_alter().
navigation_module_implements_alter Implements hook_module_implements_alter().
navigation_page_top Implements hook_page_top().
navigation_plugin_filter_block__layout_builder_alter Implements hook_plugin_filter_TYPE__CONSUMER_alter().
navigation_plugin_filter_layout__layout_builder_alter Implements hook_plugin_filter_TYPE__CONSUMER_alter().
navigation_theme Implements hook_theme().
template_preprocess_navigation Implements hook_preprocess_HOOK().

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.