Elgg  Version 5.1
DelayedEmailService.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Email;
4 
6 use Elgg\Email;
11 use Elgg\Invoker;
15 
23 
24  use Loggable;
25 
26  protected const NOTIFICATIONS_BATCH_SIZE = 500;
27 
31  protected $queue_table;
32 
36  protected $email;
37 
41  protected $views;
42 
46  protected $translator;
47 
51  protected $invoker;
52 
63  $this->queue_table = $queue_table;
64  $this->email = $email;
65  $this->views = $views;
66  $this->translator = $translator;
67  $this->invoker = $invoker;
68  }
69 
78  $recipient = $notification->getRecipient();
79 
80  $delivery_interval = $recipient->delayed_email_interval ?: 'daily';
81 
82  try {
83  return $this->queue_table->queueEmail($recipient->guid, $delivery_interval, $notification);
84  } catch (DatabaseException $e) {
85  $this->getLogger()->error($e);
86  }
87 
88  return false;
89  }
90 
99  public function processQueuedNotifications(string $delivery_interval, int $timestamp): int {
100  // processing could take a while
101  set_time_limit(0);
102 
103  return ($this->invoker->call(ELGG_IGNORE_ACCESS, function() use ($delivery_interval, $timestamp) {
104  $count = 0;
105 
106  // process one recipient
107  $processRecipient = function(int $recipient_guid, array $notifications, int $max_id) use ($delivery_interval, $timestamp) {
108  try {
109  $this->processRecipientNotifications($recipient_guid, $notifications, $delivery_interval);
110  } catch (\Throwable $t) {
111  $this->getLogger()->error($t);
112  }
113 
114  // cleanup the queue for this recipient
115  return $this->queue_table->deleteRecipientRows($recipient_guid, $delivery_interval, $timestamp, $max_id);
116  };
117 
118  // get the next recipient to process
119  $recipient_guid = $this->queue_table->getNextRecipientGUID($delivery_interval, $timestamp);
120  while ($recipient_guid > 0) {
121  // get a notification batch to process for this recipient
122  $rows = $this->queue_table->getRecipientRows($recipient_guid, $delivery_interval, $timestamp, self::NOTIFICATIONS_BATCH_SIZE);
123  while (!empty($rows)) {
124  $notifications = [];
125  $max_id = 0;
126  foreach ($rows as $row) {
127  $max_id = max($max_id, $row->id);
128 
129  $notification = $row->getNotification();
130  if (!$notification instanceof Notification) {
131  continue;
132  }
133 
134  $notifications[] = $notification;
135  }
136 
137  // send all notifications in this batch
138  $count += $processRecipient($recipient_guid, $notifications, $max_id);
139 
140  // get next batch
141  $rows = $this->queue_table->getRecipientRows($recipient_guid, $delivery_interval, $timestamp, static::NOTIFICATIONS_BATCH_SIZE);
142  }
143 
144  // get next recipient to process
145  $recipient_guid = $this->queue_table->getNextRecipientGUID($delivery_interval, $timestamp);
146  }
147 
148  return $count;
149  }));
150  }
151 
161  protected function processRecipientNotifications(int $recipient_guid, array $notifications, string $delivery_interval): bool {
162  $recipient = get_entity($recipient_guid);
163  if (!$recipient instanceof \ElggEntity || !isset($recipient->email)) {
164  return false;
165  }
166 
167  $view_vars = [
168  'recipient' => $recipient,
169  'notifications' => $notifications,
170  'delivery_interval' => $delivery_interval,
171  ];
172 
173  $body = $this->views->renderView('email/delayed_email/plaintext', $view_vars);
174  if (empty($body)) {
175  return true;
176  }
177 
178  $html_body = $this->views->renderView('email/delayed_email/html', $view_vars);
179 
181  'to' => $recipient,
182  'subject' => $this->translator->translate("notifications:delayed_email:subject:{$delivery_interval}", [], (string) $recipient->language),
183  'body' => $body,
184  'params' => [
185  'html_body' => $html_body,
186  ],
187  ]);
188 
189  return $this->email->send($email);
190  }
191 }
getRecipient()
Get the recipient entity.
$notifications
Definition: html.php:12
processQueuedNotifications(string $delivery_interval, int $timestamp)
Send out notifications for the given delivery_interval.
$rows
Definition: redis.php:25
static factory(array $options=[])
Create an email instance form an array of options.
Definition: Email.php:80
Notification container.
$timestamp
Definition: date.php:34
__construct(DelayedEmailQueueTable $queue_table, EmailService $email, ViewsService $views, Translator $translator, Invoker $invoker)
Create a new service.
trait Loggable
Enables adding a logger.
Definition: Loggable.php:14
const ELGG_IGNORE_ACCESS
elgg_call() flags
Definition: constants.php:130
enqueueNotification(Notification $notification)
Queue a notification for delayed email delivery.
get_entity(int $guid)
Loads and returns an entity object from a guid.
Definition: entities.php:67
$notification
Definition: body.php:13
$site email
Definition: settings.php:16
A generic parent class for database exceptions.
Views service.
$count
Definition: ban.php:24
processRecipientNotifications(int $recipient_guid, array $notifications, string $delivery_interval)
Send out the combined email notification for a given recipient.
Interfaces with the database to perform operations on the delayed_email_queue table.
getLogger()
Returns logger.
Definition: Loggable.php:37
$recipient_guid
Definition: mute.php:7
Email service.
$recipient
Definition: mute.php:8
Handle storing and processing delayed emails.
Invocation service.
Definition: Invoker.php:10