雲客Drupal源碼分析之菜單本地動作MenuLocalActions

菜單本地動作Menu local actions用來爲目標路由提供操作動作,在路由對應頁面中以操作按鈕呈現,比如在呈現某內容列表的路由頁面提供一個添加新內容的按鈕,可參考內容管理頁(/admin/content)的“添加內容”按鈕

本地動作塊:
路由頁面是以本地動作塊來呈現本地動作按鈕的,因此需顯示本地動作的頁面須添加該塊,塊定義如下:
塊管理標籤admin_label:Primary admin actions
塊插件ID:local_actions_block
塊插件類:Drupal\Core\Menu\Plugin\Block\LocalActionsBlock
該塊是一個很簡單的塊(見本系列塊相關主題),主要渲染工作由菜單本地動作插件管理器完成(見下)。

本地動作概述:
系統將動作按鈕視爲插件,一個按鈕對應一個插件定義,一對一關係,如果需要爲某頁面添加動作按鈕,定義插件即可,具體是在模塊根目錄下建立文件:“模塊名.links.action.yml”,其中以根鍵做插件id,其值做插件定義,插件定義有如下鍵名:
route_name:動作按鈕所指頁面的路由名,換句話說即點擊後跳轉到該路由,字符串值,必填項
route_parameters:對應以上路由名的路由參數,數組值,默認爲空數組[],可選
title:動作按鈕文本,字符串值,被系統理解爲可翻譯的,在系統內部被轉化爲翻譯對象TranslatableMarkup,用於按鈕上顯示的文本,並非title屬性值
title_context:可選,標題翻譯上下文,見翻譯系統
appears_on:路由名構成的數組,指示該本地動作將出現在哪些路由頁面中
weight:排序權重,默認爲null
options:按鈕鏈接選項,見本系列URL篇,可在其中指定鏈接屬性,如是否在新窗口打開、屬性值等
id:插件id,系統以yml文件中的定義根鍵自動賦值,最佳實踐推薦根鍵採用路由名,如果多個定義有相同路由名,那麼可以採用後綴加以區分
provider:提供插件定義的模塊名,由系統賦值
deriver:插件派生器的全限定類名,見插件系統
cache_tags:數組值,緩存標籤,默認爲空數組(見默認插件類)
cache_contexts:數組值,緩存上下文,默認爲空數組(見默認插件類)
cache_max_age:緩存最大時間,整數秒,默認爲永久(-1見默認插件類)
class:實例化插件對象的默認實現類,默認爲“Drupal\Core\Menu\LocalActionDefault”,當有特殊需要時可以自定義,在默認安裝中僅兩個定義沒有采用該默認類(但都繼承了該類),插件id和類如下:
block_content_add_action:Drupal\block_content\Plugin\Menu\LocalAction\BlockContentAddLocalAction
entity.menu.add_link_form:Drupal\menu_ui\Plugin\Menu\LocalAction\MenuLinkAdd

菜單本地動作(Menu local actions)插件管理器:
該插件管理器除了收集管理本地動作插件外,還負責爲其構造渲染數組,定義如下:
服務id:plugin.manager.menu.local_action
類:Drupal\Core\Menu\LocalActionManager
插件修改鉤子:menu_local_actions
獲取方法:

$localActionManager =\Drupal::service('plugin.manager.menu.local_action');

使用入口:

$local_actions =$localActionManager->getActionsForRoute($route_name);

這裏$local_actions是可以直接返回呈現的渲染數組,包含該路由擁有的所有本地動作,其格式如下:

$local_actions [$plugin_id] = [
        '#theme' => 'menu_local_action',
        '#link' => [
          'title' => $this->getTitle($plugin),
          'url' => Url::fromRoute($route_name, $route_parameters),
          'localized_options' => $plugin->getOptions($this->routeMatch),
        ],
        '#access' => $access,
        '#weight' => $plugin->getWeight(),
      ];

一個動作按鈕一個子元素,此外還會被附加緩存元數據,在以下預處理函數中會進一步處理:
   template_preprocess_menu_local_action(&$variables)
該函數使鏈接被渲染成按鈕,對應的默認模板爲:
   core/themes/classy/templates/navigation/menu-local-action.html.twig

補充:
1、菜單本地動作被渲染成一個按鈕,但頁面中的按鈕不一定就是本地動作,後者是針對整個路由頁面的全局操作
2、如何查詢目標頁面的路由名呢?你可以下載本系列配套的“yunke_help”模塊,輸入地址即可查詢路由參數,或者依據路徑到可能的模塊下查找路由定義yml文件
3、本地動作是基於路由設置的,是否可以基於url地址呢?答案是不可以,因此本地動作不會指向站外,且系統沒有派發關於頁面本地動作相關的鉤子(插件修改鉤除外),模塊無法干預頁面本地動作塊的生成,但如有需求一定要這些“不可以”變成“可以”怎麼辦呢?在不修改核心的情況下,雲客給出一種解決方案:覆寫菜單本地動作插件管理器服務,自定義一個繼承原插件管理器的類,在自定義類中通過模塊處理器派發修改鉤子,這又一次體現了drupal的強大靈活和oop開發的優越性。

我是雲客,【雲遊天下,做客四方】,聯繫方式見主頁,歡迎轉載,但須註明出處

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章