' . t('About') . ''; $output .= '

' . t('The Navigation module provides a left-aligned, collapsible, vertical sidebar navigation.') . '

'; $output .= '

' . t('For more information, see the online documentation for the Navigation module.', [ ':docs' => 'https://www.drupal.org/project/navigation', ]) . '

'; 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 = '

' . t('This layout builder tool allows you to configure the blocks in the navigation toolbar.') . '

'; $output .= '

' . t('Forms and links inside the content of the layout builder tool have been disabled.') . '

'; return $output; } } /** * Implements hook_page_top(). */ function navigation_page_top(array &$page_top) { $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['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']; } }