冬季 / wn-notify-plugin
Winter CMS 通知插件
Requires
- php: >=7.2
- composer/installers: ~1.0
README
插件目前处于Beta状态,请谨慎使用。
支持通过多种不同渠道发送通知,包括邮件、短信和Slack。
通过导航到 设置 > 通知规则 在后端区域管理通知。
通知工作流
当通知触发时,它使用以下工作流
- 插件使用
registerNotificationRules
注册相关操作、条件和事件 - 使用
Notifier::bindEvent
将通知类绑定到系统事件 - 触发系统事件
Event::fire
- 捕获事件的参数以及任何全局上下文参数
- 将命令推送到队列以处理通知
Queue::push
- 命令找到所有通知规则,并触发它们
- 检查通知条件,只有在满足条件时才继续
- 触发通知操作
以下是一个插件注册通知规则的示例。 groups
定义将创建用于更好地组织事件的容器。 presets
定义指定系统定义的通知规则。
public function registerNotificationRules() { return [ 'events' => [ \Winter\User\NotifyRules\UserActivatedEvent::class, ], 'actions' => [ \Winter\User\NotifyRules\SaveToDatabaseAction::class, ], 'conditions' => [ \Winter\User\NotifyRules\UserAttributeCondition::class ], 'groups' => [ 'user' => [ 'label' => 'User', 'icon' => 'icon-user' ], ], 'presets' => '$/winter/user/config/notify_presets.yaml', ]; }
以下是一个触发通知的示例。系统事件 winter.user.activate
绑定到 UserActivatedEvent
类。
// Bind to a system event \Winter\Notify\Classes\Notifier::bindEvents([ 'winter.user.activate' => \Winter\User\NotifyRules\UserActivatedEvent::class ]); // Fire the system event Event::fire('winter.user.activate', [$this]);
以下是一个注册上下文参数的示例,这些参数对所有通知都是全局可用的。
\Winter\Notify\Classes\Notifier::instance()->registerCallback(function($manager) { $manager->registerGlobalParams([ 'user' => Auth::getUser() ]); });
以下是一个事件预置的示例
# =================================== # Event Presets # =================================== welcome_email: name: Send welcome email to user event: Winter\User\NotifyRules\UserRegisteredEvent items: - action: Winter\Notify\NotifyRules\SendMailTemplateAction mail_template: winter.user::mail.welcome send_to_mode: user conditions: - condition: Winter\Notify\NotifyRules\ExecutionContextCondition subcondition: environment operator: is value: dev condition_text: Application environment <span class="operator">is</span> dev
创建事件类
事件类负责准备传递给条件和操作的参数。静态方法 makeParamsFromEvent
将系统事件提供的参数转换为参数。
class UserActivatedEvent extends \Winter\Notify\Classes\EventBase { /** * @var array Local conditions supported by this event. */ public $conditions = [ \Winter\User\NotifyRules\UserAttributeCondition::class ]; /** * Returns information about this event, including name and description. */ public function eventDetails() { return [ 'name' => 'Activated', 'description' => 'A user is activated', 'group' => 'user' ]; } /** * Defines the usable parameters provided by this class. */ public function defineParams() { return [ 'name' => [ 'title' => 'Name', 'label' => 'Name of the user', ], // ... ]; } public static function makeParamsFromEvent(array $args, $eventName = null) { return [ 'user' => array_get($args, 0) ]; } }
创建动作类
动作类定义通知的最终步骤并执行通知。一些示例可能是发送电子邮件或写入数据库。
class SendMailTemplateAction extends \Winter\Notify\Classes\ActionBase { /** * Returns information about this event, including name and description. */ public function actionDetails() { return [ 'name' => 'Compose a mail message', 'description' => 'Send a message to a recipient', 'icon' => 'icon-envelope' ]; } /** * Field configuration for the action. */ public function defineFormFields() { return 'fields.yaml'; } public function getText() { $template = $this->host->template_name; return 'Send a message using '.$template; } /** * Triggers this action. * @param array $params * @return void */ public function triggerAction($params) { $email = 'test@email.tld'; $template = $this->host->template_name; Mail::sendTo($email, $template, $params); } }
使用表单字段定义文件在动作建立时提供表单字段。这些值可以通过主机模型通过 $this->host
属性从条件中访问。
# =================================== # Field Definitions # =================================== fields: template_name: label: Template name type: text
动作可以选择不提供表单字段,只需从 defineFormFields
方法返回false即可。
public function defineFormFields() { return false; }
创建条件类
条件类应指定它在用户界面中应如何显示,提供名称、标题和摘要文本。它还必须声明一个 isTrue
方法来评估条件是否为真。
class MyCondition extends \Winter\Notify\Classes\ConditionBase { /** * Return either ConditionBase::TYPE_ANY or ConditionBase::TYPE_LOCAL */ public function getConditionType() { // If the condition should appear for all events return ConditionBase::TYPE_ANY; // If the condition should appear only for some events return ConditionBase::TYPE_LOCAL; } /** * Field configuration for the condition. */ public function defineFormFields() { return 'fields.yaml'; } public function getName() { return 'My condition is checked'; } public function getTitle() { return 'My condition'; } public function getText() { $value = $this->host->mycondition; return 'My condition <span class="operator">is</span> '.$value; } /** * Checks whether the condition is TRUE for specified parameters * @param array $params * @return bool */ public function isTrue(&$params) { return true; } }
在条件建立时使用表单字段定义文件提供表单字段。这些值可以通过主机模型通过 $this->host
属性从条件中访问。
# =================================== # Field Definitions # =================================== fields: mycondition: label: My condition type: dropdown options: true: True false: False
模型属性条件类
模型属性条件是为将条件应用于模型属性集而专门设计的。
class UserAttributeCondition extends \Winter\Notify\Classes\ModelAttributesConditionBase { protected $modelClass = \Winter\User\Models\User::class; public function getGroupingTitle() { return 'User attribute'; } public function getTitle() { return 'User attribute'; } /** * Checks whether the condition is TRUE for specified parameters * @param array $params Specifies a list of parameters as an associative array. * @return bool */ public function isTrue(&$params) { $hostObj = $this->host; $attribute = $hostObj->subcondition; if (!$user = array_get($params, 'user')) { throw new ApplicationException('Error evaluating the user attribute condition: the user object is not found in the condition parameters.'); } return parent::evalIsTrue($user); } }
使用属性定义文件指定应包含在条件中的属性。
# =================================== # Condition Attribute Definitions # =================================== attributes: name: label: Name email: label: Email address country: label: Country type: relation relation: model: Winter\Location\Models\Country label: Name nameFrom: name keyFrom: id
数据库保存动作
数据库中有一个专用表用于存储事件及其参数。该表通过 Winter\Notify\Models\Notification
模型访问,并可以从您的模型中作为关系引用。在此示例中,MyProject
模型包含其自己的通知通道,称为 notifications
。
class MyProject extends Model { // ... public $morphMany = [ 'my_notifications' => [ \Winter\Notify\Models\Notification::class, 'name' => 'notifiable' ] ]; }
该通道应与 Winter\Notify\NotifyRules\SaveDatabaseAction
进行注册,以便在选择操作时显示为相关对象。
SaveDatabaseAction::extend(function ($action) { $action->addTableDefinition([ 'label' => 'Project activity', 'class' => MyProject::class, 'relation' => 'my_notifications', 'param' => 'project' ]); });
标签显示为相关对象,类引用模型类,关系指关系名称。 参数定义了参数名称,传递给触发事件。
因此,本质上,如果您将 project
传递给事件参数,或者如果 project
是全局参数,则会创建一个带有存储在 data
属性中的参数的通知模型。相当于以下代码:
$myproject->my_notifications()->create([ // ... 'data' => $params ]);
动态添加事件条件
可以将事件扩展以包括新的本地条件。只需将条件类添加到事件的 $conditions
数组属性中即可。
UserActivatedEvent::extend(function($event) { $event->conditions[] = \Winter\UserPlus\NotifyRules\UserLocationAttributeCondition::class; });