94. 系统管理工具栏toolbar

系统管理工具栏toolbar是指用户登录后页面顶部的黑色条区域,后简称工具栏,里面列出了系统最重要的一些链接,默认有:管理、快捷方式、用户等,点击这些链接后会展开显示对应的子链接。注意这里并没有将工具栏里面的链接称为菜单,在drupal中菜单有明确的定义(请见本系列后续的菜单系统介绍),默认情况下工具栏用到了菜单,但她本身不是菜单,先明确这一点以便于理解一些概念。

 

 

工具栏由两部分构成:

tab:工具栏里面的链接,可以通过附加类属性的方式追加显示图标

tray:这是可选的,代表点击tab中的链接后展开显示的对应区域(tab的托盘),里面可以放置子链接或其它内容;如果省略tray,那么点击tab后将直接打开其链接,否则点击事件被拦截并展开tray显示。

模块可以向工具栏中添加tab和其对应的tray

 

添加工具栏:

整个管理工具栏是通过钩子“page_top”添加的,该钩子在HTML渲染器的以下方法中派发:

\Drupal\Core\Render\MainContent\HtmlRenderer::buildPageTopAndBottom

运行时机在块系统运行后,她向#typehtml的渲染数组添加子元素page_top,工具栏就位于该子元素中(html渲染数组默认有三个子元素page_top pagepage_bottom),工具栏由核心模块toolbar添加,钩子函数如下:

function toolbar_page_top(array &$page_top) {
  $page_top['toolbar'] = [
    '#type' => 'toolbar',
    '#access' => \Drupal::currentUser()->hasPermission('access toolbar'),
    '#cache' => [
      'keys' => ['toolbar'],
      'contexts' => ['user.permissions'],
    ],
  ];
}

 

由该钩子可见,工具栏并不是依据用户是否登录来判断显示的,只要具备'access toolbar'权限即显示。

 

添加工具栏链接:

从上面的钩子可知道管理工具栏由toolbar元素类型的渲染数组产生,所有工作被封装到该元素类型中,该元素类型类如下:

\Drupal\toolbar\Element\Toolbar

在其中将派发toolbar钩子及其修改钩子来构建工具栏,如果模块需向工具栏添加链接可以实现该钩子,这里假设模块名为yunke,添加菜单的钩子示例如下:

function yunke_toolbar()
{
    $items['yunke'] = [
        '#type'   => 'toolbar_item',
        'tab'     => [
            '#type'       => 'link',
            '#title'      => "云客",
            '#url'        => \Drupal\Core\Url::fromRoute('<front>'),
            '#attributes' => [
                'title' => "工具栏顶级链接",
                'class' => ['toolbar-icon'], //如需图标,则在此处补充具体的图标类
            ],
        ],
        '#weight' => 10000, //菜单排序 越大越靠后
    ];

    // tab如不需要托盘区域,那么在此处直接返回$items即可,不需要以下内容,
    //此时tab链接为以上'#url'指定的地址,以下构建tray托盘区域
    $items['yunke']['tray'] = [
        '#heading' => '托盘区域', //一个隐藏的内容,用于辅助视障设备
    ];
    //列出以下子链接,注意以下将采用links主题钩子,因此不是以属性方式传递
    $links = [
        'index'     => [
            'title' => "链接一",
            'url'   => \Drupal\Core\Url::fromRoute('<front>'),
        ],
        'info'      => [
            'title' => "链接二",
            'url'   => \Drupal\Core\Url::fromRoute('<front>'),
        ],
        'resources' => [
            'title' => "链接三",
            'url'   => \Drupal\Core\Url::fromRoute('<front>'),
        ],
    ];
    $items['yunke']['tray']['group1']=[
        '#theme' => 'links__toolbar_yunke', //默认将采用links主题钩子
        '#links' => $links,
        '#attributes' => [
            'class' => ['toolbar-menu'],
        ],
    ];
    $items['yunke']['tray']['group2']=[ //可以根据需要给菜单分组
        '#type' => 'link',
        '#title' => '子菜单组',
        '#url' => \Drupal\Core\Url::fromRoute('<front>'),
    ];
//还可以在$items['yunke']['tray']中追加任意需要显示的内容
    return $items;

}

 

以上列子yunke模块只添加了一个tab,如需多个只需在$items中添加多个子元素即可

 

调整工具栏:

模块可以实现toolbar修改钩子来调整工具栏,如排序、删除其他模块的工具栏设置等等,这里以排序做一个演示,假设模块名为yunke

function yunke_toolbar_alter(&$items)
{
    $items['administration']['#weight']=999;
}

这将使“管理”链接排到“用户”后面,这里需要注意:如果你想通过该钩子去调整其他模块提供的工具栏元素,还需要视情况而定,在使用了延迟构建#lazy_builder或渲染前处理器#pre_render时,有些链接可能尚未产生,通常这种情况下需要用到对应模块自己派发的修改钩子,比如这里你并不能调整管理菜单的内容,而需要通过菜单系统来调整。

 

删除整个工具栏:

添加整个工具栏是在钩子“page_top”中,那么删除她也可以实现该钩子,这里介绍一种方法,假设模块名为“yunke_help”,如下:

function yunke_help_page_top(array &$page_top)
{
    $route_name = \Drupal::routeMatch()->getRouteName();
    if ($route_name != "yunke_help.index") {
        return;
    }
    if (isset($page_top["#pre_render"]) && is_array($page_top["#pre_render"])) {
        $page_top["#pre_render"][] = "delete_toolbar";
    } else {
        $page_top["#pre_render"] = ["delete_toolbar"];
    }
}
function delete_toolbar($e)
{
    unset($e['toolbar']);
    return $e;
}

以上方法用到了#pre_render,你可能会想到为什么不在page_top钩子中直接unset变量$page_top['toolbar'],这是因为我们无法保证各模块钩子的执行顺序,执行时可能还未产生,且系统也没有派发对应的page_top修改钩子。

我们来看一看如下的toolbar修改钩子是否能实现删除功能:

function yunke_toolbar_alter(&$items)
{
    $items['#access']=false;
}

这是不行的,因为该钩子在工具栏渲染数组的#pre_render中运行,此时权限检查已经执行过了。但如果改为以下逻辑将可以实现删除:

function yunke_toolbar_alter(&$items)
{
    $items = [];
    $items['#cache'] = []; //禁用工具栏渲染数组缓存
}

该方法虽然能够实现删除,但不如以上采用#pre_render的方法优雅,且浪费性能。

 

系统管理菜单:

工具栏中的管理链接是真正的菜单,内容由菜单系统提供,工具栏tabtoolbar模块在toolbar_toolbar()钩子中添加,关于该内容请阅读本系列菜单主题。

 

本书共115小节:

评论 (写第一个评论)