Make the message notify action more flexible and dynamic

Created on 18 April 2025, 10 days ago

Problem/Motivation

The current state of the ECA action is, that it is "locked" to the email notifier.
We have no chance to use or select form other existing notifier plugins in the system, without creating another custom ECA notifier action.

But what if we let the user choose from all system wide notifier plugins as well as a "semi-dynamic" approach with using tokens for the notifier plugin id?

I already made a working poc which I could show off here and open a discussion about the need of this eca action.

<?php

declare(strict_types=1);

namespace Drupal\eca_message_notify \Plugin\Action;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\eca\EcaState;
use Drupal\eca\Plugin\Action\ConfigurableActionBase;
use Drupal\eca\Token\TokenInterface;
use Drupal\message_notify\Exception\MessageNotifyException;
use Drupal\message_notify\MessageNotifier;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\message_notify\Plugin\Notifier\Manager;

/**
 * Provides Send a message by notifier action.
 *
 * @Action(
 *   id = "send_by_notifier",
 *   label = @Translation("Send a message by message notifier"),
 *   type = "message",
 *   category = @Translation("Message")
 * )
 */
class SendByNotifier extends ConfigurableActionBase {

  /**
   * The message notifier.
   *
   * @var \Drupal\message_notify\MessageNotifier
   */

  protected readonly MessageNotifier $notifier;

  /**
   * The notifier manager.
   *
   * @var \Drupal\message_notify\Plugin\Notifier\Manager
   */
  protected readonly Manager $manager;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * The ECA token service.
   *
   * @var \Drupal\eca\Token\TokenInterface
   */
  protected TokenInterface $tokenService;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected AccountProxyInterface $currentUser;

  /**
   * The time interface.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected TimeInterface $time;

  /**
   * The ECA state.
   *
   * @var \Drupal\eca\EcaState
   */
  protected EcaState $state;

  /**
   * The logger channel interface.
   *
   * @var \Drupal\Core\Logger\LoggerChannelInterface
   */
  protected LoggerChannelInterface $logger;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
    $instance = new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager'),
      $container->get('token'),
      $container->get('current_user'),
      $container->get('datetime.time'),
      $container->get('eca.state'),
      $container->get('logger.channel.default')
    );

    $instance->notifier = $container->get('message_notify.sender');
    $instance->manager = $container->get('plugin.message_notify.notifier.manager');

    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration(): array {
    return [
      'notifier' => '',
      'eca_token' => '',
      'message' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
    $form = [];

    $definitions = $this->manager->getDefinitions();
    $options = [];

    foreach ($definitions as $machine_name => $definition) {
      $options[$machine_name] = $definition['label'] ?? $machine_name;
    }

    $form['notifier'] = [
      '#type' => 'select',
      '#title' => $this->t('Notifiers'),
      '#options' => $options,
      '#description' => $this->t('Select a notifier to choose from.'),
      '#default_value' => $this->configuration['notifier'],
      '#required' => TRUE,
      '#eca_token_select_option' => TRUE,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
    $this->configuration['notifier'] = $form_state->getValue('notifier');
    $this->configuration['eca_token'] = $form_state->getValue('eca_token');
    $this->configuration['message'] = $form_state->getValue('message');
  }

  /**
   * {@inheritdoc}
   */
  public function execute() {
    if ($this->configuration['notifier'] == '_eca_token') {
      // Get notifier ID by token.
      $notifier_token = $this->tokenService->getTokenData('send_by_notifier_notifier');
      $notifier_id = $notifier_token->getValue();
    }
    else {
      // Get notifier ID by config form.
      $notifier_id = $this->configuration['notifier'];
    }

    $message_token = $this->configuration['object'];
    $message = $this->tokenService->getTokenData($message_token);

    $options = ['language override' => TRUE];

    /** @var \Drupal\message_notify\Plugin\Notifier\MessageNotifierInterface $notifier */
    $notifier = $this->manager->createInstance($notifier_id, []);

    try {
      $notifier->setMessage($message, $options);
      $notifier->send();
    }
    catch (MessageNotifyException $e) {
      $this->messenger()->addError($this->t('Sending via @channel failed', ['channel' => $notifier_id]));
    }
  }

}

I'd be happy to discuss this :)

Feature request
Status

Active

Version

1.0

Component

Code

Created by

🇩🇪Germany Istari

Live updates comments and jobs are added and updated live.
  • API change

    Changes an existing API or subsystem. Not backportable to earlier major versions, unless absolutely required to fix a critical bug.

Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024