Skip to content
Snippets Groups Projects
Commit 20947f90 authored by Camilo Ernesto Escobar Bedoya's avatar Camilo Ernesto Escobar Bedoya
Browse files

Issue #3362297 New Queue Worker to send Email Notifications

parent 64cfad07
No related branches found
No related tags found
1 merge request!73Issue #3362297 Provide new configuration option in the Registrant Settings form to enable/disabled the email notifications queue
...@@ -153,6 +153,7 @@ function recurring_events_reminders_cron() { ...@@ -153,6 +153,7 @@ function recurring_events_reminders_cron() {
$registration_creation_service->setEventInstance($instance); $registration_creation_service->setEventInstance($instance);
$registrants = $registration_creation_service->retrieveRegisteredParties(); $registrants = $registration_creation_service->retrieveRegisteredParties();
if (empty($registrants)) { if (empty($registrants)) {
return; return;
} }
...@@ -161,7 +162,8 @@ function recurring_events_reminders_cron() { ...@@ -161,7 +162,8 @@ function recurring_events_reminders_cron() {
// Send an email to all registrants. // Send an email to all registrants.
foreach ($registrants as $registrant) { foreach ($registrants as $registrant) {
recurring_events_registration_send_notification($key, $registrant); // Add each notification to be sent to the queue.
\Drupal::service('recurring_events_registration.notification_service')->addEmailNotificationToQueue($key, $registrant);
} }
} }
} }
......
...@@ -143,26 +143,44 @@ function template_preprocess_registrant(array &$variables) { ...@@ -143,26 +143,44 @@ function template_preprocess_registrant(array &$variables) {
* Implements hook_mail(). * Implements hook_mail().
*/ */
function recurring_events_registration_mail($key, &$message, $params) { function recurring_events_registration_mail($key, &$message, $params) {
/** @var \Drupal\recurring_events_registration\NotificationService */ if ((empty($params['subject']) || empty($params['body']) || empty($params['from']))
$service = \Drupal::service('recurring_events_registration.notification_service'); && !empty($params['registrant'])
$service->setKey($key)->setEntity($params['registrant']); && $params['registrant'] instanceof Registrant) {
/** @var \Drupal\recurring_events_registration\NotificationService */
$service = \Drupal::service('recurring_events_registration.notification_service');
$service->setKey($key)->setEntity($params['registrant']);
}
if ($service->isEnabled()) {
if (!empty($params['subject'])) {
$service->setSubject($params['subject']);
}
if (!empty($params['body'])) {
$service->setMessage($params['body']);
}
if (!empty($params['from'])) {
$service->setFrom($params['from']);
}
if (!empty($params['from'])) {
$message['from'] = $params['from'];
}
elseif (isset($service)) {
$message['from'] = $service->getFrom(); $message['from'] = $service->getFrom();
}
if (!empty($params['subject'])) {
$message['subject'] = $params['subject'];
}
elseif (isset($service)) {
$message['subject'] = $service->getSubject(); $message['subject'] = $service->getSubject();
}
if (!empty($params['body'])) {
$message['body'][] = $params['body'];
}
elseif (isset($service)) {
$message['body'][] = $service->getMessage(); $message['body'][] = $service->getMessage();
} }
return FALSE;
// echo 'params::' . PHP_EOL;
// print_r($params);
// echo 'message::' . PHP_EOL;
// print_r($message);
// $message['from'] = $params['from'] ?? isset($service) ? $service->getFrom() : '';
// $message['subject'] = $params['subject'] ?? isset($service) ? $service->getSubject() : '';
// $message['body'][] = $params['body'] ?? isset($service) ? $service->getMessage() : '';
} }
/** /**
...@@ -218,7 +236,8 @@ function recurring_events_registration_recurring_events_save_pre_instances_delet ...@@ -218,7 +236,8 @@ function recurring_events_registration_recurring_events_save_pre_instances_delet
// Send an email to all registrants. // Send an email to all registrants.
foreach ($registrants as $registrant) { foreach ($registrants as $registrant) {
recurring_events_registration_send_notification($key, $registrant); // Add each notification to be sent to the queue.
\Drupal::service('recurring_events_registration.notification_service')->addEmailNotificationToQueue($key, $registrant);
$registrant->delete(); $registrant->delete();
} }
} }
...@@ -250,7 +269,8 @@ function recurring_events_registration_entity_update(EntityInterface $entity) { ...@@ -250,7 +269,8 @@ function recurring_events_registration_entity_update(EntityInterface $entity) {
// Send an email to all registrants. // Send an email to all registrants.
foreach ($registrants as $registrant) { foreach ($registrants as $registrant) {
recurring_events_registration_send_notification($key, $registrant); // Add each notification to be sent to the queue.
\Drupal::service('recurring_events_registration.notification_service')->addEmailNotificationToQueue($key, $registrant);
} }
} }
} }
...@@ -274,7 +294,8 @@ function recurring_events_registration_recurring_events_pre_delete_instance(Even ...@@ -274,7 +294,8 @@ function recurring_events_registration_recurring_events_pre_delete_instance(Even
foreach ($registrants as $registrant) { foreach ($registrants as $registrant) {
// Only send email notifications if this event instance is in the future. // Only send email notifications if this event instance is in the future.
if ($registration_creation_service->eventInstanceIsInFuture()) { if ($registration_creation_service->eventInstanceIsInFuture()) {
recurring_events_registration_send_notification($key, $registrant); // Add each notification to be sent to the queue.
\Drupal::service('recurring_events_registration.notification_service')->addEmailNotificationToQueue($key, $registrant);
} }
$registrant->delete(); $registrant->delete();
} }
...@@ -296,7 +317,8 @@ function recurring_events_registration_recurring_events_pre_delete_instances(Eve ...@@ -296,7 +317,8 @@ function recurring_events_registration_recurring_events_pre_delete_instances(Eve
// Send an email to the future registrants. // Send an email to the future registrants.
foreach ($future_registrants as $registrant) { foreach ($future_registrants as $registrant) {
recurring_events_registration_send_notification($key, $registrant); // Add each notification to be sent to the queue.
\Drupal::service('recurring_events_registration.notification_service')->addEmailNotificationToQueue($key, $registrant);
} }
} }
...@@ -317,7 +339,7 @@ function recurring_events_registration_recurring_events_pre_delete_instances(Eve ...@@ -317,7 +339,7 @@ function recurring_events_registration_recurring_events_pre_delete_instances(Eve
* *
* @param string $key * @param string $key
* The mail key used to determine the message and subject. * The mail key used to determine the message and subject.
* @param \Drupal\recurring_events_registration\Entity\RegistrantInterface $registrant * @param \Drupal\recurring_events_registration\Entity\RegistrantInterface|bool $registrant
* The registrant this email relates to. * The registrant this email relates to.
*/ */
function recurring_events_registration_send_notification($key, RegistrantInterface $registrant) { function recurring_events_registration_send_notification($key, RegistrantInterface $registrant) {
......
...@@ -4,7 +4,7 @@ services: ...@@ -4,7 +4,7 @@ services:
arguments: ['@string_translation', '@database', '@logger.factory', '@messenger', '@entity_type.manager', '@module_handler', '@token'] arguments: ['@string_translation', '@database', '@logger.factory', '@messenger', '@entity_type.manager', '@module_handler', '@token']
recurring_events_registration.notification_service: recurring_events_registration.notification_service:
class: Drupal\recurring_events_registration\NotificationService class: Drupal\recurring_events_registration\NotificationService
arguments: ['@string_translation', '@config.factory', '@logger.factory', '@messenger', '@token', '@module_handler', '@recurring_events_registration.creation_service'] arguments: ['@string_translation', '@config.factory', '@logger.factory', '@messenger', '@token', '@module_handler', '@recurring_events_registration.creation_service', '@queue']
recurring_events_registration.access_handler: recurring_events_registration.access_handler:
class: Drupal\recurring_events_registration\AccessHandler class: Drupal\recurring_events_registration\AccessHandler
arguments: ['@string_translation', '@recurring_events_registration.creation_service', '@current_route_match', '@entity_type.manager'] arguments: ['@string_translation', '@recurring_events_registration.creation_service', '@current_route_match', '@entity_type.manager']
...@@ -12,4 +12,4 @@ services: ...@@ -12,4 +12,4 @@ services:
class: Drupal\recurring_events_registration\Routing\RouteSubscriber class: Drupal\recurring_events_registration\Routing\RouteSubscriber
arguments: [ '@config.factory' ] arguments: [ '@config.factory' ]
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
\ No newline at end of file
...@@ -10,6 +10,7 @@ use Drupal\Core\Utility\Token; ...@@ -10,6 +10,7 @@ use Drupal\Core\Utility\Token;
use Drupal\recurring_events_registration\Entity\RegistrantInterface; use Drupal\recurring_events_registration\Entity\RegistrantInterface;
use Drupal\Core\Extension\ModuleHandler; use Drupal\Core\Extension\ModuleHandler;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Queue\QueueFactory;
/** /**
* Provides a service with helper functions to facilitate notifications. * Provides a service with helper functions to facilitate notifications.
...@@ -114,6 +115,13 @@ class NotificationService { ...@@ -114,6 +115,13 @@ class NotificationService {
*/ */
protected $custom = FALSE; protected $custom = FALSE;
/**
* The update fetch queue.
*
* @var \Drupal\Core\Queue\QueueFactory
*/
protected $queueFactory;
/** /**
* Class constructor. * Class constructor.
* *
...@@ -131,8 +139,10 @@ class NotificationService { ...@@ -131,8 +139,10 @@ class NotificationService {
* The module handler service. * The module handler service.
* @param \Drupal\recurring_events_registration\RegistrationCreationService $creation_service * @param \Drupal\recurring_events_registration\RegistrationCreationService $creation_service
* The registration creation service. * The registration creation service.
* @param \Drupal\Core\Queue\QueueFactory $queue_factory
* The queue factory.
*/ */
public function __construct(TranslationInterface $translation, ConfigFactory $config_factory, LoggerChannelFactoryInterface $logger, Messenger $messenger, Token $token, ModuleHandler $module_handler, RegistrationCreationService $creation_service) { public function __construct(TranslationInterface $translation, ConfigFactory $config_factory, LoggerChannelFactoryInterface $logger, Messenger $messenger, Token $token, ModuleHandler $module_handler, RegistrationCreationService $creation_service, QueueFactory $queue_factory) {
$this->translation = $translation; $this->translation = $translation;
$this->configFactory = $config_factory; $this->configFactory = $config_factory;
$this->loggerFactory = $logger->get('recurring_events_registration'); $this->loggerFactory = $logger->get('recurring_events_registration');
...@@ -141,6 +151,7 @@ class NotificationService { ...@@ -141,6 +151,7 @@ class NotificationService {
$this->moduleHandler = $module_handler; $this->moduleHandler = $module_handler;
$this->creationService = $creation_service; $this->creationService = $creation_service;
$this->configName = 'recurring_events_registration.registrant.config'; $this->configName = 'recurring_events_registration.registrant.config';
$this->queueFactory = $queue_factory;
} }
/** /**
...@@ -154,7 +165,8 @@ class NotificationService { ...@@ -154,7 +165,8 @@ class NotificationService {
$container->get('messenger'), $container->get('messenger'),
$container->get('token'), $container->get('token'),
$container->get('module_handler'), $container->get('module_handler'),
$container->get('recurring_events_registration.creation_service') $container->get('recurring_events_registration.creation_service'),
$container->get('queue')
); );
} }
...@@ -246,7 +258,7 @@ class NotificationService { ...@@ -246,7 +258,7 @@ class NotificationService {
* @return string|bool * @return string|bool
* The key, or FALSE if not set. * The key, or FALSE if not set.
*/ */
protected function getKey() { public function getKey() {
if (empty($this->key)) { if (empty($this->key)) {
$this->messenger->addError($this->translation->translate('No key defined for @module notifications.', [ $this->messenger->addError($this->translation->translate('No key defined for @module notifications.', [
'@module' => 'recurring_events_registration', '@module' => 'recurring_events_registration',
...@@ -352,11 +364,7 @@ class NotificationService { ...@@ -352,11 +364,7 @@ class NotificationService {
public function getSubject($parse_tokens = TRUE) { public function getSubject($parse_tokens = TRUE) {
$key = $this->getKey(); $key = $this->getKey();
if ($key) { if ($key) {
$subject = $this->subject; $subject = $this->getConfigValue('subject');
if (empty($subject)) {
$subject = $this->getConfigValue('subject');
$this->setSubject($subject);
}
if (empty($subject)) { if (empty($subject)) {
$this->messenger->addError($this->translation->translate('No default subject configured for @key emails in @config_name.', [ $this->messenger->addError($this->translation->translate('No default subject configured for @key emails in @config_name.', [
...@@ -386,11 +394,7 @@ class NotificationService { ...@@ -386,11 +394,7 @@ class NotificationService {
public function getMessage($parse_tokens = TRUE) { public function getMessage($parse_tokens = TRUE) {
$key = $this->getKey(); $key = $this->getKey();
if ($key) { if ($key) {
$message = $this->message; $message = $this->getConfigValue('body');
if (empty($message)) {
$message = $this->getConfigValue('body');
$this->setMessage($message);
}
if (empty($message)) { if (empty($message)) {
$this->messenger->addError($this->translation->translate('No default body configured for @key emails in @config_name.', [ $this->messenger->addError($this->translation->translate('No default body configured for @key emails in @config_name.', [
...@@ -450,4 +454,57 @@ class NotificationService { ...@@ -450,4 +454,57 @@ class NotificationService {
return $this->creationService->getAvailableTokens($relevant_tokens); 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`. They can get the data from
// `$registrant`. Those `$params` are used later as the
// `$message['params']` in mail hooks.
$this->moduleHandler->alter('recurring_events_registration_message_params_alter', $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);
}
}
} }
<?php
namespace Drupal\recurring_events_registration\Plugin\QueueWorker;
use Drupal\Core\Queue\QueueWorkerBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Mail\MailManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
/**
* Defines 'recurring_events_registration_email_notifications_queue_worker' queue worker.
*
* @QueueWorker(
* id = "recurring_events_registration_email_notifications_queue_worker",
* title = @Translation("Email Notifications Queue Worker"),
* cron = {"time" = 6}
* )
*/
class EmailNotificationsQueueWorker extends QueueWorkerBase implements ContainerFactoryPluginInterface {
/**
* The mail manager.
*
* @var \Drupal\Core\Mail\MailManagerInterface
*/
protected $mailManager;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* Constructs a new LocaleTranslation object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param array $plugin_definition
* @param \Drupal\Core\Mail\MailManagerInterface $mail_manager
* The mail manager.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, MailManagerInterface $mail_manager, LanguageManagerInterface $language_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->mailManager = $mail_manager;
$this->languageManager = $language_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('plugin.manager.mail'),
$container->get('language_manager')
);
}
/**
* {@inheritdoc}
*/
public function processItem($item) {
if (empty($item->key) || empty($item->to) || (empty($item->params['subject']) && empty($item->params['body']))) {
return;
}
// All this worker has to do is to send the email.
// The Subject and Body already have to be included in the `$item`.
$this->mailManager->mail('recurring_events_registration', $item->key, $item->to, $this->languageManager->getDefaultLanguage()->getId(), $item->params);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment