Skip to content
Snippets Groups Projects
Commit b037112e authored by Oliver Davies's avatar Oliver Davies Committed by Jay Friendly
Browse files

Issue #2952860 by opdavies, Jaypan: Emails not being sent when messages are queued

parent f6b92536
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,9 @@ parameters:
private_message.mapper.class: 'Drupal\private_message\Mapper\PrivateMessageMapper'
private_message.service.class: 'Drupal\private_message\Service\PrivateMessageService'
private_message.event_subscriber.class: 'Drupal\private_message\Event\PrivateMessageEventSubscriber'
cache_context.private_message_thread.class: 'Drupal\private_message\Cache\Context\PrivateMessageThreadCacheContext'
private_message.mailer.class: 'Drupal\private_message\Service\PrivateMessageMailer'
private_message.thread_manager.class: 'Drupal\private_message\Service\PrivateMessageThreadManager'
services:
private_message.mapper:
......@@ -22,8 +25,23 @@ services:
- '@datetime.time'
cache_context.private_message_thread:
class: Drupal\private_message\Cache\Context\PrivateMessageThreadCacheContext
class: '%cache_context.private_message_thread.class%'
arguments:
- '@current_route_match'
tags:
- { name: cache.context}
private_message.mailer:
class: '%private_message.mailer.class%'
arguments:
- '@private_message.service'
- '@plugin.manager.mail'
- '@current_user'
- '@user.data'
- '@config.factory'
private_message.thread_manager:
class: '%private_message.thread_manager.class%'
arguments:
- '@private_message.service'
- '@private_message.mailer'
......@@ -18,6 +18,7 @@ use Drupal\private_message\Ajax\PrivateMessageLoadNewMessagesCommand;
use Drupal\private_message\Entity\PrivateMessageThread;
use Drupal\private_message\Entity\PrivateMessageThreadInterface;
use Drupal\private_message\Service\PrivateMessageServiceInterface;
use Drupal\private_message\Service\PrivateMessageThreadManagerInterface;
use Drupal\user\entity\User;
use Drupal\user\UserDataInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -76,6 +77,13 @@ class PrivateMessageForm extends ContentEntityForm {
*/
protected $privateMessageService;
/**
* The private message thread manager service.
*
* @var \Drupal\private_message\Service\PrivateMessageThreadManagerInterface
*/
protected $privateMessageThreadManager;
/**
* Constructs a PrivateMessageForm object.
*
......@@ -93,6 +101,8 @@ class PrivateMessageForm extends ContentEntityForm {
* The configuration factory service.
* @param \Drupal\private_message\Service\PrivateMessageServiceInterface $privateMessageService
* The private message service.
* @param \Drupal\private_message\Service\PrivateMessageThreadManagerInterface $privateMessageThreadManager
* The private message thread manager service.
*/
public function __construct(
EntityManagerInterface $entityManager,
......@@ -101,7 +111,8 @@ class PrivateMessageForm extends ContentEntityForm {
TypedDataManagerInterface $typedDataManager,
UserDataInterface $userData,
ConfigFactoryInterface $configFactory,
PrivateMessageServiceInterface $privateMessageService
PrivateMessageServiceInterface $privateMessageService,
PrivateMessageThreadManagerInterface $privateMessageThreadManager
) {
parent::__construct($entityManager);
......@@ -111,6 +122,7 @@ class PrivateMessageForm extends ContentEntityForm {
$this->userData = $userData;
$this->config = $configFactory->get('private_message.settings');
$this->privateMessageService = $privateMessageService;
$this->privateMessageThreadManager = $privateMessageThreadManager;
}
/**
......@@ -124,7 +136,8 @@ class PrivateMessageForm extends ContentEntityForm {
$container->get('typed_data_manager'),
$container->get('user.data'),
$container->get('config.factory'),
$container->get('private_message.service')
$container->get('private_message.service'),
$container->get('private_message.thread_manager')
);
}
......@@ -279,28 +292,12 @@ class PrivateMessageForm extends ContentEntityForm {
}
}
}
// Get a private message thread containing the given users.
$private_message_thread = $this->privateMessageService->getThreadForMembers($members);
// Add the new message to the thread and save.
$private_message_thread->addMessage($this->entity)->save();
$mailManager = \Drupal::service('plugin.manager.mail');
$params = [
'private_message' => $this->getEntity(),
'private_message_thread' => $private_message_thread,
];
foreach ($members as $member) {
if ($member->id() != $this->currentUser->id()) {
$params['member'] = $member;
$send = $this->userData->get('private_message', $member->id(), 'email_notification');
$send = is_numeric($send) ? (bool) $send : ($this->config->get('enable_email_notifications') && $this->config->get('send_by_default'));
if ($send) {
$mailManager->mail('private_message', 'message_notification', $member->getEmail(), $member->getPreferredLangcode(), $params);
}
}
}
// Save the thread.
$this->privateMessageThreadManager->saveThread($this->entity, $members, [], $private_message_thread);
// Send the user to the private message page. As this thread is the newest,
// it wll be at the top of the list.
......
<?php
namespace Drupal\private_message\Service;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Mail\MailManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\private_message\Entity\PrivateMessageInterface;
use Drupal\private_message\Entity\PrivateMessageThreadInterface;
use Drupal\user\UserDataInterface;
/**
* A service class for sending notification emails for private messages.
*/
class PrivateMessageMailer implements PrivateMessageMailerInterface {
/**
* The private message service.
*
* @var \Drupal\private_message\Service\PrivateMessageServiceInterface
*/
private $privateMessageService;
/**
* The mail manager service.
*
* @var \Drupal\Core\Mail\MailManagerInterface
*/
private $mailManager;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
private $currentUser;
/**
* The user data service.
*
* @var \Drupal\user\UserDataInterface
*/
private $userData;
/**
* The configuration factory service.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
private $config;
/**
* Constructs a new PrivateMessageMailer object.
*
* @param \Drupal\private_message\Service\PrivateMessageServiceInterface $privateMessageService
* The private message service.
* @param \Drupal\Core\Mail\MailManagerInterface $mailManager
* The mail manager service.
* @param \Drupal\Core\Session\AccountProxyInterface $currentUser
* The current user.
* @param \Drupal\user\UserDataInterface $userData
* The user data service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The configuration factory service.
*/
public function __construct(
PrivateMessageServiceInterface $privateMessageService,
MailManagerInterface $mailManager,
AccountProxyInterface $currentUser,
UserDataInterface $userData,
ConfigFactoryInterface $configFactory
) {
$this->privateMessageService = $privateMessageService;
$this->mailManager = $mailManager;
$this->currentUser = $currentUser;
$this->userData = $userData;
$this->config = $configFactory->get('private_message.settings');
}
/**
* {@inheritdoc}
*/
public function send(PrivateMessageInterface $message, PrivateMessageThreadInterface $thread, array $members = []) {
$params = [
'private_message' => $message,
'private_message_thread' => $thread,
];
foreach ($members as $member) {
if ($member->id() != $this->currentUser->id()) {
$params['member'] = $member;
// Should the message be sent?
if ($this->shouldSend($member)) {
$this->mailManager->mail('private_message', 'message_notification', $member->getEmail(), $member->getPreferredLangcode(), $params);
}
}
}
}
/**
* Determines if the message should be sent.
*
* Checks individual user preferences as well as system defaults.
*
* @param \Drupal\Core\Session\AccountInterface $recipient
* The potential recipient.
*
* @return bool
* A boolean indicating whether or not the message should be sent.
*/
private function shouldSend(AccountInterface $recipient) {
$send = (bool) $this->userData->get('private_message', $recipient->id(), 'email_notification');
return is_numeric($send)
? $send
: ($this->config->get('enable_email_notifications') && $this->config->get('send_by_default'));
}
}
<?php
namespace Drupal\private_message\Service;
use Drupal\private_message\Entity\PrivateMessageInterface;
use Drupal\private_message\Entity\PrivateMessageThreadInterface;
/**
* Interface for the Private Message mail service.
*/
interface PrivateMessageMailerInterface {
/**
* Send a private message notification email.
*
* @param \Drupal\private_message\Entity\PrivateMessageInterface $message
* The message.
* @param \Drupal\private_message\Entity\PrivateMessageThreadInterface $thread
* The message thread.
* @param \Drupal\user\UserInterface[] $members
* The message members.
*/
public function send(PrivateMessageInterface $message, PrivateMessageThreadInterface $thread, array $members = []);
}
......@@ -163,15 +163,15 @@ class PrivateMessageService implements PrivateMessageServiceInterface {
/**
* {@inheritdoc}
*/
public function getNewMessages($thread_id, $message_id) {
public function getNewMessages($threadId, $messageId) {
$response = [];
$private_message_thread = $this->pmThreadManager->load($thread_id);
$private_message_thread = $this->pmThreadManager->load($threadId);
if ($private_message_thread && $private_message_thread->isMember($this->currentUser->id())) {
$messages = $private_message_thread->getMessages();
$from_index = FALSE;
foreach ($messages as $index => $message) {
if ($message->id() > $message_id) {
if ($message->id() > $messageId) {
$from_index = $index;
break;
}
......@@ -188,10 +188,10 @@ class PrivateMessageService implements PrivateMessageServiceInterface {
/**
* {@inheritdoc}
*/
public function getPreviousMessages($thread_id, $message_id) {
public function getPreviousMessages($threadId, $messageId) {
$return = [];
$private_message_thread = $this->pmThreadManager->load($thread_id);
$private_message_thread = $this->pmThreadManager->load($threadId);
if ($private_message_thread && $private_message_thread->isMember($this->currentUser->id())) {
$user = $this->userManager->load($this->currentUser->id());
$messages = $private_message_thread->filterUserDeletedMessages($user);
......@@ -199,7 +199,7 @@ class PrivateMessageService implements PrivateMessageServiceInterface {
$settings = $this->configFactory->get('core.entity_view_display.private_message_thread.private_message_thread.default')->get('content.private_messages.settings');
$count = $settings['ajax_previous_load_count'];
foreach ($messages as $index => $message) {
if ($message->id() >= $message_id) {
if ($message->id() >= $messageId) {
$start_index = $index - $count >= 0 ? $index - $count : 0;
$slice_count = $index > $count ? $count : $index;
......
......@@ -25,11 +25,11 @@ interface PrivateMessageServiceInterface {
*
* If no thread exists, one will be created.
*
* @param Drupal\user\UserInterface[] $members
* @param \Drupal\user\UserInterface[] $members
* An array of User objects for whom the private message
* thread should be retrieved.
*
* @return Drupal\private_message\Entity\PrivateMessageThread
* @return \Drupal\private_message\Entity\PrivateMessageThread
* A private message thread that contains all members in the thread.
*/
public function getThreadForMembers(array $members);
......@@ -63,22 +63,22 @@ interface PrivateMessageServiceInterface {
/**
* Retrieve a users private messages created after the given ID.
*
* @param int $thread_id
* @param int $threadId
* The ID of the thread from which messages should be retrieved.
* @param int $message_id
* @param int $messageId
* The ID after which messages should be retrieved.
*
* @return array
* An array containing any new messages that the user has permission to view
*/
public function getNewMessages($thread_id, $message_id);
public function getNewMessages($threadId, $messageId);
/**
* Retrieve old messages for a user that were created before the given ID.
*
* @param int $thread_id
* @param int $threadId
* The ID of the thread from which messages should be retrieved.
* @param int $message_id
* @param int $messageId
* The ID before which messages should be retrieved.
*
* @return array
......@@ -87,7 +87,7 @@ interface PrivateMessageServiceInterface {
* - next_exists: a boolean indicating whether or not any messages appear
* in the thread before the first message returned
*/
public function getPreviousMessages($thread_id, $message_id);
public function getPreviousMessages($threadId, $messageId);
/**
* Get a list of User objects whose account names begin with the given string.
......@@ -167,11 +167,11 @@ interface PrivateMessageServiceInterface {
/**
* Load the thread that a private message belongs to.
*
* @param Drupal\private_message\Entity\PrivateMessageInterface $privateMessage
* @param \Drupal\private_message\Entity\PrivateMessageInterface $privateMessage
* The private message for which the thread it belongs to should be
* returned.
*
* @return Drupal\private_message\Entity\PrivateMessageThread
* @return \Drupal\private_message\Entity\PrivateMessageThread
* The private message thread to which the private message belongs
*/
public function getThreadFromMessage(PrivateMessageInterface $privateMessage);
......
<?php
namespace Drupal\private_message\Service;
use Drupal\Core\Session\AccountInterface;
use Drupal\private_message\Entity\PrivateMessageInterface;
use Drupal\private_message\Entity\PrivateMessageThreadInterface;
/**
* The Private Message generator class.
*
* @package Drupal\private_message\Service
*/
class PrivateMessageThreadManager implements PrivateMessageThreadManagerInterface {
/**
* The private message service.
*
* @var \Drupal\private_message\Service\PrivateMessageServiceInterface
*/
private $privateMessageService;
/**
* The private message mailer service.
*
* @var \Drupal\private_message\Service\PrivateMessageMailerInterface
*/
private $privateMessageMailer;
/**
* The private message.
*
* @var \Drupal\private_message\Entity\PrivateMessageInterface
*/
private $message;
/**
* The message recipients.
*
* @var \Drupal\Core\Session\AccountInterface[]
*/
private $recipients = [];
/**
* An array of members to exclude from notification emails.
*
* @var \Drupal\Core\Session\AccountInterface[]
*/
private $excludeFromMail = [];
/**
* The private message thread.
*
* @var \Drupal\private_message\Entity\PrivateMessageThreadInterface|null
*/
private $thread;
/**
* PrivateMessageThreadManager constructor.
*
* @param \Drupal\private_message\Service\PrivateMessageServiceInterface $private_message_service
* The private message service.
* @param \Drupal\private_message\Service\PrivateMessageMailerInterface $mailer
* The private message mailer service.
*/
public function __construct(
PrivateMessageServiceInterface $private_message_service,
PrivateMessageMailerInterface $mailer
) {
$this->privateMessageService = $private_message_service;
$this->privateMessageMailer = $mailer;
}
/**
* {@inheritdoc}
*/
public function saveThread(PrivateMessageInterface $message, array $recipients = [], array $excludeFromMail = [], PrivateMessageThreadInterface $thread = NULL) {
$this->message = $message;
$this->thread = $thread;
$this->recipients = $recipients;
$this->excludeFromMail = $excludeFromMail;
$this->getThread()
->addMessage()
->sendMail();
}
/**
* If no thread is defined, load one from the thread members.
*
* @return $this
*/
private function getThread() {
if (is_null($this->thread)) {
$this->thread = $this->privateMessageService->getThreadForMembers($this->recipients);
}
return $this;
}
/**
* Add the new message to the thread.
*
* @return $this
*/
private function addMessage() {
$this->thread->addMessage($this->message);
$this->thread->save();
return $this;
}
/**
* Send the notification email.
*
* @return $this
*/
private function sendMail() {
$this->privateMessageMailer->send($this->message, $this->thread, $this->getMailRecipients());
return $this;
}
/**
* The users to receive email notifications.
*
* @return \Drupal\Core\Session\AccountInterface[]
* An array of Account objects of the thread memebers who are to receive
* the email notification.
*/
private function getMailRecipients() {
if (empty($this->excludeFromMail)) {
return $this->recipients;
}
return array_filter($this->recipients, function (AccountInterface $account) {
// If this user is in the excluded list, filter them from the recipients
// list so they do not receive the email.
return !in_array($account, $this->excludeFromMail);
});
}
}
<?php
namespace Drupal\private_message\Service;
use Drupal\private_message\Entity\PrivateMessageInterface;
use Drupal\private_message\Entity\PrivateMessageThreadInterface;
/**
* Handles the generation/update of private messages, threads, and metadata.
*
* @package Drupal\private_message\Service
*/
interface PrivateMessageThreadManagerInterface {
/**
* Saves a private message thread.
*
* A new thread will be created if one does not already exist.
*
* @param \Drupal\private_message\Entity\PrivateMessageInterface $message
* The new message object.
* @param array $recipients
* (optional) An array of message recipients. Defaults to an empty array.
* @param array $excludeFromMail
* (optional) An array of members to exclude from notification emails.
* Defaults to an empty array.
* @param \Drupal\private_message\Entity\PrivateMessageThreadInterface|null $thread
* (optional) The private message thread. If NULL, one will be loaded
* using the recipients array.
*/
public function saveThread(PrivateMessageInterface $message, array $recipients = [], array $excludeFromMail = [], PrivateMessageThreadInterface $thread = NULL);
}
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