冬季/wn-notify-plugin

Winter CMS 通知插件

资助包维护!
wintercms
Open Collective

安装数: 2,602

依赖关系: 2

建议者: 0

安全性: 0

星标: 3

关注者: 5

分支: 4

公开问题: 0

类型:winter-plugin

v2.0.0 2021-04-22 15:44 UTC

This package is auto-updated.

Last update: 2024-09-08 18:41:17 UTC


README

插件目前处于Beta状态,请谨慎使用。

支持通过多种不同渠道发送通知,包括邮件、短信和Slack。

通过导航到 设置 > 通知规则 在后端区域管理通知。

通知工作流

当通知触发时,它使用以下工作流

  1. 插件使用 registerNotificationRules 注册相关操作、条件和事件
  2. 使用 Notifier::bindEvent 将通知类绑定到系统事件
  3. 触发系统事件 Event::fire
  4. 捕获事件的参数以及任何全局上下文参数
  5. 将命令推送到队列以处理通知 Queue::push
  6. 命令找到所有通知规则,并触发它们
  7. 检查通知条件,只有在满足条件时才继续
  8. 触发通知操作

以下是一个插件注册通知规则的示例。 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;
});