recurring_events-2.0.x-dev/modules/recurring_events_registration/src/NotificationService.php

modules/recurring_events_registration/src/NotificationService.php
<?php

declare(strict_types=1);

namespace Drupal\recurring_events_registration;

use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Queue\QueueFactory;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Utility\Token;
use Drupal\recurring_events_registration\Entity\RegistrantInterface;

/**
 * Provides a service with helper functions to facilitate notifications.
 */
class NotificationService {

  /**
   * The registrant entity.
   *
   * @var \Drupal\recurring_events_registration\Entity\RegistrantInterface
   */
  protected $entity;

  /**
   * The email key.
   *
   * @var string
   */
  protected $key;

  /**
   * The email subject.
   *
   * @var string
   */
  protected $subject;

  /**
   * The email message.
   *
   * @var string
   */
  protected $message;

  /**
   * The from address.
   *
   * @var string
   */
  protected $from;

  /**
   * The config name.
   *
   * @var string
   */
  protected $configName;

  /**
   * Whether this is a custom or configure email.
   *
   * @var bool
   */
  protected $custom = FALSE;

  public function __construct(
    protected readonly TranslationInterface $translation,
    protected readonly ConfigFactory $configFactory,
    protected readonly LoggerChannelFactoryInterface $loggerFactory,
    protected readonly MessengerInterface $messenger,
    protected readonly Token $token,
    protected readonly ModuleHandlerInterface $moduleHandler,
    protected readonly RegistrationCreationService $creationService,
    protected readonly QueueFactory $queueFactory,
  ) {
    $this->configName = 'recurring_events_registration.registrant.config';
  }

  /**
   * Set the registrant entity.
   *
   * @param \Drupal\recurring_events_registration\Entity\RegistrantInterface $registrant
   *   The registrant entity.
   *
   * @return $this
   *   The NotificationService object.
   */
  public function setEntity(RegistrantInterface $registrant) {
    $this->entity = $registrant;
    return $this;
  }

  /**
   * Set the email key.
   *
   * @param string $key
   *   The email key to use.
   *
   * @return $this
   */
  public function setKey($key) {
    $this->key = $key;
    if ($this->key === 'custom') {
      $this->custom = TRUE;
    }
    return $this;
  }

  /**
   * Set the email subject.
   *
   * @param string $subject
   *   The email subject line.
   *
   * @return $this
   */
  public function setSubject($subject) {
    $this->subject = $subject;
    return $this;
  }

  /**
   * Set the email message.
   *
   * @param string $message
   *   The email message.
   *
   * @return $this
   */
  public function setMessage($message) {
    $this->message = $message;
    return $this;
  }

  /**
   * Set the email from address.
   *
   * @param string $from
   *   The from email address.
   *
   * @return $this
   */
  public function setFrom($from) {
    $this->from = $from;
    return $this;
  }

  /**
   * Set the config name.
   *
   * @param string $name
   *   The name of the config value to use.
   *
   * @return $this
   */
  public function setConfigName($name) {
    $this->configName = $name;
    return $this;
  }

  /**
   * Get the key.
   *
   * @return string|bool
   *   The key, or FALSE if not set.
   */
  public function getKey() {
    if (empty($this->key)) {
      $this->messenger->addError($this->translation->translate('No key defined for @module notifications.', [
        '@module' => 'recurring_events_registration',
      ]));
      $this->loggerFactory->get('recurring_events_registration')->error('No key defined @module notifications. Call @function before proceeding.', [
        '@module' => 'recurring_events_registration',
        '@function' => 'NotificationService::setKey()',
      ]);
      return FALSE;
    }
    return $this->key;
  }

  /**
   * Get the config name.
   *
   * @return string
   *   The name of the config element.
   */
  protected function getConfigName() {
    if (empty($this->configName)) {
      $this->messenger->addError($this->translation->translate('No config name defined for @module notifications.', [
        '@module' => 'recurring_events_registration',
      ]));
      $this->loggerFactory->get('recurring_events_registration')->error('No config name defined for @module notifications. Call @function before proceeding.', [
        '@module' => 'recurring_events_registration',
        '@function' => 'NotificationService::setConfigName()',
      ]);
      return FALSE;
    }
    return $this->configName;
  }

  /**
   * Retrieve config value.
   *
   * @var string $name
   *   The name of the config value to retrieve
   *
   * @return string|bool
   *   Return the config value, or FALSE if not set.
   */
  protected function getConfigValue($name) {
    $value = FALSE;
    $notifications = $this->configFactory->get($this->getConfigName())->get('notifications');
    if (!is_null($notifications[$this->key][$name])) {
      $value = $notifications[$this->key][$name];
    }

    return $value;
  }

  /**
   * Get the from address.
   *
   * @return string
   *   The from address.
   */
  public function getFrom() {
    $key = $this->getKey();
    if ($key) {
      $from = $this->from;
      if (empty($from)) {
        $from = $this->configFactory->get('system.site')->get('mail');
        $this->setFrom($from);
      }

      if (empty($from)) {
        $this->messenger->addError($this->translation->translate('No default from address configured. Please check the system.site mail config.'));
        return '';
      }
      return $from;
    }
    return '';
  }

  /**
   * Check notification is enabled.
   *
   * @return bool
   *   Returns TRUE if enabled, FALSE otherwise.
   */
  public function isEnabled() {
    $key = $this->getKey();
    if ($this->custom) {
      return TRUE;
    }
    if ($key) {
      return (bool) $this->getConfigValue('enabled');
    }
    return FALSE;
  }

  /**
   * Get the email subject.
   *
   * @param bool $parse_tokens
   *   Whether or not to parse out the tokens.
   *
   * @return string
   *   The email subject line.
   */
  public function getSubject($parse_tokens = TRUE) {
    $key = $this->getKey();
    if ($key) {
      $subject = $this->getConfigValue('subject');

      if (empty($subject)) {
        $this->messenger->addError($this->translation->translate('No default subject configured for @key emails in @config_name.', [
          '@key' => $key,
          '@config_name' => $this->getConfigName(),
        ]));
        return '';
      }

      if ($parse_tokens) {
        return $this->parseTokenizedString($subject);
      }
      return $subject;
    }
    return '';
  }

  /**
   * Get the email message.
   *
   * @param bool $parse_tokens
   *   Whether or not to parse out the tokens.
   *
   * @return string
   *   The email message.
   */
  public function getMessage($parse_tokens = TRUE) {
    $key = $this->getKey();
    if ($key) {
      $message = $this->getConfigValue('body');

      if (empty($message)) {
        $this->messenger->addError($this->translation->translate('No default body configured for @key emails in @config_name.', [
          '@key' => $key,
          '@config_name' => $this->getConfigName(),
        ]));
        return '';
      }

      if ($parse_tokens) {
        return $this->parseTokenizedString($message);
      }
      return $message;
    }
    return '';
  }

  /**
   * Parse a tokenized string.
   *
   * @var string $string
   *   The string to parse.
   *
   * @return string
   *   The parsed string.
   */
  public function parseTokenizedString($string) {
    // #3272196 for some reason the Registrant entity is sometimes null. So here
    // we check first to avoid throwing PHP notices.
    if (empty($this->entity)) {
      return $string;
    }

    $data = [
      'registrant' => $this->entity,
      'eventinstance' => $this->entity ? $this->entity->getEventInstance() : NULL,
      'eventseries' => $this->entity ? $this->entity->getEventSeries() : NULL,
    ];
    // Double token replace to allow for global token replacements containing
    // tokens themselves.
    return $this->token->replace($this->token->replace($string, $data), $data);
  }

  /**
   * Get available tokens form element.
   *
   * @return array
   *   A render array to render on the site.
   */
  public function getAvailableTokens() {
    $relevant_tokens = [
      'eventseries',
      'eventinstance',
      'registrant',
    ];

    return $this->creationService->getAvailableTokens($relevant_tokens);
  }

  /**
   * Adds an email notification to be sent later by the Queue Worker.
   */
  public function addEmailNotificationToQueue($key, RegistrantInterface $registrant) {
    $config = $this->configFactory->get('recurring_events_registration.registrant.config');
    $send_email = $config->get('email_notifications');
    $send_email_key = $config->get('notifications.' . $key . '.enabled');

    // Modify $send_email if necessary.
    if ($registrant instanceof RegistrantInterface) {
      $this->moduleHandler->alter('recurring_events_registration_send_notification', $send_email, $registrant);
    }

    if ($send_email && $send_email_key) {
      // We need to get the parsed email subject and message (after token
      // replacement) to add them to the `$item` that will be queued. We are
      // not adding the `$registrant` to the `$item`, since in the queue worker
      // we cannot rely on operations over the `$registrant` or its parent
      // instance or series, since at that point those entities might have been
      // deleted. There are some operations and notification types that require
      // the `$registrant`to be deleted, for example: the notifications
      // corresponding to the keys 'series_modification_notification' and
      // 'instance_deletion_notification'.
      // @see recurring_events_registration_recurring_events_save_pre_instances_deletion()
      // @see recurring_events_registration_recurring_events_pre_delete_instance()
      $this->setKey($key)->setEntity($registrant);
      $subject = $this->getSubject();
      $message = $this->getMessage();
      $from = $this->getFrom();

      // Create the item to be added to the queue.
      $item = new \stdClass();
      $item->key = $key;
      $item->to = $registrant->email->value;

      $params = [
        'subject' => $subject,
        'body' => $message,
        'from' => $from,
      ];
      // Allow modules to add data to the `$params`. Developers can get data
      // from `$registrant`. Those `$params` can be used later as the
      // `$params` in `hook_mail()` and `$message['params']` in
      // `hook_mail_alter()`.
      // In queued messages, we are not passing the `$registrant` entity as a
      // param (unlike it is being done in non-queued messages
      // `recurring_events_registration_send_notification`), because the entity
      // could no longer exist when the queue worker takes action and sends the
      // email. For example, as mentioned above in another comment, there are
      // some notification types that require the `$registrant` to be deleted
      // as part of the same operation that generates the notification, for
      // example: the notifications corresponding to the keys
      // 'series_modification_notification' and
      // 'instance_deletion_notification'.
      // Therefore, those entities won't be available in the queue worker.
      // It would be unsafe to try to access a registrant for a queued message
      // via `$params['registrant']` in `hook_mail()` or
      // `$message['params']['registrant']` in `hook_mail_alter()`.
      // We encourage developers to make use of the
      // `hook_recurring_events_registration_message_params_alter()` to define
      // any value in the params that could be necessary to perform any logic
      // in the mail hooks (ideally scalar values, custom arrays or custom
      // objects. No loaded entities and no configuration objects, since those
      // could have changed or been deleted by the moment the queue worker is
      // called), those values will be added to the queued item and will be
      // available in the queue worker when it processes the item and in the
      // mail hooks later.
      // @see recurring_events_registration_recurring_events_save_pre_instances_deletion()
      // @see recurring_events_registration_recurring_events_pre_delete_instance
      $this->moduleHandler->alter('recurring_events_registration_message_params', $params, $registrant);
      $item->params = $params;

      // Add the item to the queue.
      $queue = $this->queueFactory->get('recurring_events_registration_email_notifications_queue_worker');
      $queue->createItem($item);
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc