class NavigationHooks

Hook implementations for navigation.

Hierarchy

Expanded class hierarchy of NavigationHooks

File

core/modules/navigation/src/Hook/NavigationHooks.php, line 17

Namespace

Drupal\navigation\Hook
View source
class NavigationHooks {
    
    /**
     * Implements hook_help().
     */
    public function 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 \Drupal::moduleHandler()->invoke('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().
     */
    public function pageTop(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_theme().
     */
    public function theme($existing, $type, $theme, $path) : array {
        $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,
                'title' => NULL,
                'items' => [],
                'attributes' => [],
            ],
        ];
        $items['menu_region__footer'] = [
            'variables' => [
                'items' => [],
                'title' => NULL,
                'menu_name' => NULL,
            ],
        ];
        return $items;
    }
    
    /**
     * Implements hook_menu_links_discovered_alter().
     */
    public function menuLinksDiscoveredAlter(&$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().
     */
    public function blockBuildLocalTasksBlockAlter(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.
     */
    public function pluginFilterBlockLayoutBuilderAlter(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().
     */
    public function pluginFilterLayoutLayoutBuilderAlter(array &$definitions, array $extra) {
        if (($extra['section_storage'] ?? NULL) instanceof NavigationSectionStorage) {
            // We don't allow adding a new section.
            $definitions = [];
        }
    }
    
    /**
     * Implements hook_block_alter().
     */
    public function blockAlter(&$definitions) : void {
        $hidden = [
            'navigation_user',
            'navigation_shortcuts',
            'navigation_menu',
            'navigation_link',
        ];
        foreach ($hidden as $block_id) {
            if (isset($definitions[$block_id])) {
                $definitions[$block_id]['_block_ui_hidden'] = TRUE;
            }
        }
    }
    
    /**
     * Implements hook_element_info_alter().
     */
    public function elementInfoAlter(array &$info) {
        if (array_key_exists('layout_builder', $info)) {
            $info['layout_builder']['#pre_render'][] = [
                RenderCallbacks::class,
                'alterLayoutBuilder',
            ];
        }
    }

}

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