插件(Plugins)注册

介绍

插件是通过扩展将新功能添加到CMS的基础。 本文介绍了组件注册。 注册过程允许插件声明其功能,如组件或后端菜单和页面。 插件可以执行的一些示例:

  1. 定义 组件.
  2. 定义 用户权限.
  3. 添加 设置页面, 菜单项, 列表表单.
  4. 创建 数据库表结构和数据.
  5. 修改 核心或其他插件的功能.
  6. 准备classes, 后端控制器, 视图, 资源和其他文件。

目录结构

插件在应用程序目录的/plugins子目录中。 插件目录结构的示例:

  1. plugins/
  2. acme/ <=== Author name
  3. blog/ <=== Plugin name
  4. classes/
  5. components/
  6. controllers/
  7. models/
  8. updates/
  9. ...
  10. Plugin.php <=== 插件注册文件

并非所有插件目录都是必需的。 唯一需要的文件是下面描述的Plugin.php。 如果你的插件只提供一个组件,你的插件目录可能会简单得多,如下所示:

  1. plugins/
  2. acme/ <=== 作者名称
  3. blog/ <=== 扩展名称
  4. components/
  5. Plugin.php <=== 插件注册文件

注意: 如果您正在为Marketplace开发插件,则需要 updates/version.yaml 文件。

插件命名空间(namespaces)

插件名称空间非常重要,特别是如果您要在October市场上发布插件。 当您在Marketplace上注册为作者时,将要求您提供作为所有插件的根命名空间的作者代码。 注册时,您只能指定一次作者代码。 市场提供的默认作者代码由作者姓氏和名字组成,如:JohnSmith。 注册后无法更改代码。 您应该在根命名空间下定义所有插件名称空间,例如\JohnSmith\Blog

注册文件

Plugin.php文件,称为插件注册文件,是一个初始化脚本,用于声明插件的核心功能和信息。 注册文件可以提供以下内容:

  1. 有关插件,其名称和作者的信息。
  2. 扩展CMS的注册方法。

注册脚本应使用插件命名空间。 注册脚本应该定义一个名为Plugin的类,应扩展\System\Classes\PluginBase类。 插件注册类唯一需要的方法是pluginDetails。 插件注册文件的示例:

  1. namespace Acme\Blog;
  2. class Plugin extends \System\Classes\PluginBase
  3. {
  4. public function pluginDetails()
  5. {
  6. return [
  7. 'name' => 'Blog Plugin',
  8. 'description' => 'Provides some really cool blog features.',
  9. 'author' => 'ACME Corporation',
  10. 'icon' => 'icon-leaf'
  11. ];
  12. }
  13. public function registerComponents()
  14. {
  15. return [
  16. 'Acme\Blog\Components\Post' => 'blogPost'
  17. ];
  18. }
  19. }

支持的方法

插件注册类支持以下方法:

方法 描述
pluginDetails() 返回有关插件的信息。
register() 注册方法,在首次注册插件时调用。
boot() 引导方法,在请求路由之前调用。
registerMarkupTags() 注册可在CMS中使用的其他标记标记
registerComponents() 注册此插件的组件
registerNavigation() 注册此插件的后端导航菜单项
registerPermissions() 注册此插件的后端权限
registerSettings() 注册此插件的后端设置链接
registerFormWidgets() 注册此插件的后端表单小部件
registerReportWidgets() 注册此插件的后端报告小部件,包括仪表板小部件。
registerListColumnTypes() 注册此插件提供的自定义列表列类型
registerMailTemplates() 注册此插件提供的邮件视图模板
registerSchedule() 注册定期执行的计划任务

基本插件信息

pluginDetails是插件注册类的必需方法。 它应该返回一个包含以下键的数组:

描述
name 插件名称,必填。
description 插件描述,必需。
author 插件作者姓名,必填。
icon 插件图标的名称。 可以在UI文档中找到可用图标的完整列表。 此字体提供的任何图标名称均有效,例如:icon-glassicon-music
iconSvg 用于代替标准图标的SVG图标,可选。 SVG图标应为矩形,可以支持多种颜色。
homepage 指向作者网站地址的链接,可选。

路由和初始化

插件注册文件可以包含两个方法bootregister。 使用这些方法,您可以执行任何您喜欢的操作,例如注册路径或将处理程序附加到事件。

注册插件时立即调用register方法。 在路由请求之前调用boot方法。 因此,如果您的操作依赖于另一个插件,则应使用引导方法。 例如,在boot方法中,您可以扩展模型:

  1. public function boot()
  2. {
  3. User::extend(function($model) {
  4. $model->hasOne['author'] = ['Acme\Blog\Models\Author'];
  5. });
  6. }

注意: 在更新过程中不会调用bootregister方法来保护系统免受严重错误的影响。要克服此限制,请使用提升权限.

插件还可以提供名为routes.php的文件,其中包含自定义路由逻辑,如路由器服务中所定义。 例如:

  1. Route::group(['prefix' => 'api_acme_blog'], function() {
  2. Route::get('cleanup_posts', function(){ return Posts::cleanUp(); });
  3. });

依赖关系定义

插件可以通过在插件注册文件中定义$require属性来依赖其他插件,该属性应该包含一系列被认为是需求的插件名称。 依赖于Acme.User插件的插件可以通过以下方式声明此要求:

  1. namespace Acme\Blog;
  2. class Plugin extends \System\Classes\PluginBase
  3. {
  4. /**
  5. * @var array Plugin dependencies
  6. */
  7. public $require = ['Acme.User'];
  8. [...]
  9. }

依赖关系定义将影响插件的运行方式和更新过程如何应用更新。 安装过程将尝试自动安装任何依赖项,但是如果在系统中检测到插件而没有任何依赖项,则会禁用它以防止系统错误。

依赖关系定义可能很复杂,但应注意防止循环引用。 应始终指向依赖图,并将循环依赖视为设计错误。

继承Twig

可以使用插件注册类的registerMarkupTags方法在CMS中注册自定义Twig过滤器和函数。 下一个示例注册两个Twig过滤器和两个函数。

  1. public function registerMarkupTags()
  2. {
  3. return [
  4. 'filters' => [
  5. // A global function, i.e str_plural()
  6. 'plural' => 'str_plural',
  7. // A local method, i.e $this->makeTextAllCaps()
  8. 'uppercase' => [$this, 'makeTextAllCaps']
  9. ],
  10. 'functions' => [
  11. // A static method call, i.e Form::open()
  12. 'form_open' => ['October\Rain\Html\Form', 'open'],
  13. // Using an inline closure
  14. 'helloWorld' => function() { return 'Hello World!'; }
  15. ]
  16. ];
  17. }
  18. public function makeTextAllCaps($text)
  19. {
  20. return strtoupper($text);
  21. }

导航菜单

插件可以通过覆盖插件注册类.的registerNavigation方法来扩展后端导航菜单。 本节介绍如何将菜单项添加到后端导航区域。 注册带有两个子菜单项的顶级导航菜单项的示例:

  1. public function registerNavigation()
  2. {
  3. return [
  4. 'blog' => [
  5. 'label' => 'Blog',
  6. 'url' => Backend::url('acme/blog/posts'),
  7. 'icon' => 'icon-pencil',
  8. 'permissions' => ['acme.blog.*'],
  9. 'order' => 500,
  10. 'sideMenu' => [
  11. 'posts' => [
  12. 'label' => 'Posts',
  13. 'icon' => 'icon-copy',
  14. 'url' => Backend::url('acme/blog/posts'),
  15. 'permissions' => ['acme.blog.access_posts']
  16. ],
  17. 'categories' => [
  18. 'label' => 'Categories',
  19. 'icon' => 'icon-copy',
  20. 'url' => Backend::url('acme/blog/categories'),
  21. 'permissions' => ['acme.blog.access_categories']
  22. ]
  23. ]
  24. ]
  25. ];
  26. }

注册后端导航时,可以使用本地化字符串作为“label”值。 后端导航也可以通过permissions值控制,并对应于定义的后端用户权限。 后端导航在整个导航菜单项上显示的顺序由“order”值控制。 数字越大意味着该项目将在菜单项的顺序中稍后出现,而较低的数字意味着它将在较早时出现。

要使子菜单项可见,您可以使用BackendMenu::setContext方法在后端控制器中设置导航上下文 。 这将使父菜单项处于活动状态,并在侧边菜单中显示子项。

注册中间件(middleware)

要注册自定义中间件,您可以在引导方法中使用以下调用来扩展您希望添加中间件的Controller类。

  1. public function boot()
  2. {
  3. \Cms\Classes\CmsController::extend(function($controller) {
  4. $controller->middleware('Path\To\Custom\Middleware');
  5. });
  6. }

或者,您可以通过以下方式将其直接推送到内核中。

  1. public function boot()
  2. {
  3. // Add a new middleware to beginning of the stack.
  4. $this->app['Illuminate\Contracts\Http\Kernel']
  5. ->prependMiddleware('Path\To\Custom\Middleware');
  6. // Add a new middleware to end of the stack.
  7. $this->app['Illuminate\Contracts\Http\Kernel']
  8. ->pushMiddleware('Path\To\Custom\Middleware');
  9. }

提升权限

默认情况下,插件仅限于访问系统的某些区域。 这是为了防止可能将管理员锁定在后端的严重错误。 在没有提升权限的情况下访问这些区域时,插件的bootregister 初始化方法 将不会触发。

请求 描述
/combine 资源组合器生成器URL
/backend/system/updates 网站更新上下文
/backend/system/install 安装路径
/backend/backend/auth 后端认证路径(登录,注销)
october:up 运行所有挂起的迁移的CLI命令
october:update 用于触发更新过程的CLI命令

定义$elevated属性以授予插件的提升权限。

  1. /**
  2. * @var bool Plugin requires elevated permissions.
  3. */
  4. public $elevated = true;