Diff #4 - trunk/src/Notifications/Notifications.php
9,375 bytes
|
|
January 20, 2025 at 08:20
|
Diff
Index: Notifications.php
--- Notifications.php (nonexistent) +++ Notifications.php (revision 4) @@ -0,0 +1,300 @@ +<?php +declare(strict_types = 1); + +namespace App\Webapp\Notifications; + +use Apex\Svc{App, Container, Emailer, Db, Convert}; +use App\Webapp\Models\EmailNotification; +use Apex\App\Adapters\ArmorAdapter; +use Apex\App\Interfaces{EmailNotificationControllerInterface, UserInterface}; +use Apex\Mercury\Email{EmailMessage, EmailContact, EmailContactCollection}; +use Apex\Armor\Interfaces\ArmorUserInterface; +use App\Users\User; +use App\Webapp\Exceptions\WebappNotificationException; +use App\Users\Exceptions\UserNotExistsException; + +/** + * Notifications + */ +class Notifications +{ + + #[Inject(App::class)] + private App $app; + + #[Inject(Container::class)] + private Container $cntr; + + #[Inject(Db::class)] + private Db $db; + + #[Inject(Convert::class)] + private Convert $convert; + + #[Inject(ArmorAdapter::class)] + private ArmorAdapter $armor_adapter; + + #[Inject(Emailer::class)] + private Emailer $emailer; + + /** + * Process e-mail notifications + */ + public function process(string $class_name, string $uuid = '', array $condition = [], array $data = []):void + { + + // Check class + if (!class_exists($class_name)) { + throw new WebappNotificationException("Notification controller does not exist, $class_name"); + } + + // Load class + $obj = $this->cntr->make($class_name); + if (!$obj instanceof EmailNotificationControllerInterface) { + throw new WebappNotificationException("Notification class does not implement the EmailNotificationControllerInterface, $lcass_name"); + } + + // Go through all notifications + $rows = EmailNotification::where('controller = %s', $class_name); + foreach ($rows as $email) { + + // Check notification + if (!$this->checkCondition($email, $condition)) { + continue; + } + + // Get user + $user = null; + if ($uuid != '' && !$user = User::loadUuid($uuid)) { + throw new UserNotExistsException("No user exists with the uuid, $uuid"); + } + + // Process individual notification + $this->send($obj, $email, $user, $data); + } + + } + + /** + * Check condition + */ + private function checkCondition(EmailNotification $email, array $condition):bool + { + + // Decode condition + $chk = json_decode($email->condition_vars, true); + + // GO through condition vars + $ok=true; + foreach ($condition as $key => $value) { + $chk_value = $chk[$key] ?? ''; + if ($value != $chk_value) { + $ok = false; + break; + } + } + + // Return + return $ok; + } + + /** + * Send notification + */ + public function send(EmailNotificationControllerInterface $obj, EmailNotification $email, ?ArmorUserInterface $user, array $data):void + { + + // Initialize + $uuid = $user === null ? '' : $user->getUuid(); + + // Get sender and recipient + $sender = $this->getSender($obj, $user, $email->sender, $data); + $recipients = $this->getRecipients($obj, $user, $email->recipient, $data); + + // Get merge vars + $merge_vars = $this->getMergeVars($obj, $user, $data); + + // Go through recipients + foreach ($recipients as $recipient) { + + // Format subject and contents + list($tmp_subject, $tmp_contents, $tmp_html_contents) = [$email->subject, $email->text_contents, $email->html_contents]; + foreach ($merge_vars as $key => $value) { + if ($value instanceof \DateTime) { + $value = $this->convert->date($value); + } + $tmp_subject = str_replace("~$key~", (string) $value, $tmp_subject); + $tmp_contents = str_replace("~$key~", (string) $value, $tmp_contents); + $tmp_html_contents = str_replace("~$key~", (string) $value, $tmp_html_contents); + } + + // Create e-mail notification + $msg = $this->cntr->make(EmailMessage::class, [ + 'to_email' => $recipient->getEmail(), + 'to_name' => $recipient->getName() === null ? '' : $recipient->getName(), + 'from_email' => $sender->getEmail(), + 'from_name' => $sender->getName() === null ? '' : $sender->getName(), + 'reply_to' => $this->getReplyTo($obj, $email, $data), + 'cc' => $this->getCc($obj, $email, $data), + 'bcc' => $this->getBcc($obj, $email, $data), + 'subject' => $tmp_subject, + 'text_message' => $tmp_contents, + 'html_message' => $tmp_html_contents + ]); + + // Send e-mail message + $this->emailer->send($msg); + } + + } + + /** + * Get sender + */ + private function getSender(EmailNotificationControllerInterface $obj, ?ArmorUserInterface $user, string $alias, array $data):?EmailContact + { + + // Check for specific user + $sender = null; + if (preg_match("/^\w:\d+$/", $alias)) { + if (!$sender = $this->armor_adapter->getUuid($this->db, $alias)) { + throw new UserNotExistsException("Sender does not exist with uuid, $alias"); + } + + } elseif ($sender == 'user' && $user === null) { + throw new WebappNotificationException("Sender for e-mail notification is set to 'user' but user is null."); + + } elseif ($alias == 'user') { + $sender = $user; + } + + // Get e-mail contact + if ($sender !== null) { + $contact = $this->cntr->make(EmailContact::class, [ + 'email' => $sender->getEmail(), + 'name' => $sender->getFullName() + ]); + + } elseif (!$contact = $obj->getSender($alias, $user, $data)) { + throw new WebappNotificationException("Unable to determine sender for '$alias' with user '" . $user->getUuid() . "'"); + } + + // Return + return $contact; + } + + /** + * Get recipients + */ + private function getRecipients(EmailNotificationControllerInterface $obj, ?ArmorUserInterface $user, string $alias, array $data):?EmailContactCollection + { + + // Initialize + $recipient = null; + $col = $this->cntr->make(EmailContactCollection::class); + + // Check for specific user + if (preg_match("/^\w:\d+$/", $alias)) { + if (!$recipient = $this->armor_adapter->getUuid($this->db, $alias)) { + throw new UserNotExistsException("Sender does not exist with uuid, $alias"); + } + + } elseif ($alias == 'user' && $user === null) { + throw new WebappNotificationException("E-mail notification recipient is set to 'user' but user is null."); + + } elseif ($alias == 'user') { + $recipient = $user; + } + + // Get e-mail contact + if ($recipient !== null) { + $contact = $this->cntr->make(EmailContact::class, [ + 'email' => $recipient->getEmail(), + 'name' => $recipient->getFullName() + ]); + $col[] = $contact; + + } elseif (!$col = $obj->getRecipients($alias, $user, $data)) { + $uuid = $user === null ? 'null' : $user->getUuid(); + throw new WebappNotificationException("Unable to determine recipients for '$alias' with user, $uuid"); + } + + // Return + return $col; + } + + /** + * Get reply to + */ + private function getReplyTo(EmailNotificationControllerInterface $obj, EmailNotification $email, array $data):string + { + + // Check obj + if (null === ($reply_to = $obj->getReplyTo($data))) { + $reply_to = $email->reply_to; + } + + // Return + return $reply_to; + } + + /** + * Get cc + */ + private function getCc(EmailNotificationControllerInterface $obj, EmailNotification $email, array $data):array + { + + // Check obj + if (null === ($cc = $obj->getCc($data))) { + $cc = $email->cc == '' ? [] : [$email->cc]; + } + + // Return + return $cc; + } + + /** + * Get bcc + */ + private function getBcc(EmailNotificationControllerInterface $obj, EmailNotification $email, array $data):array + { + + // Check obj + if (null === ($bcc = $obj->getBcc($data))) { + $bcc = $email->bcc == '' ? [] : [$email->bcc]; + } + + // Return + return $bcc; + } + + /** + * Get merge vars + */ + public function getMergeVars(EmailNotificationControllerInterface $obj, ?UserInterface $user, array $data):array + { + + // Init + $profie = []; + $uuid = ''; + + // Get user profile + if ($user !== null) { + $profile = $user->toDisplayArray(); + $uuid = $user->getUuid(); + } + $profile['domain_name'] = $this->app->config('core.domain_name'); + $profile['site_name'] = $this->app->config('core.site_name'); + $profile['install_url'] = 'https://' . $this->app->config('core.domain_name'); + + // Get vars from controller + if ($vars = $obj->getMergeVars($uuid, $data)) { + $profile = array_merge($profile, $vars); + } + + // Return + return $profile; + } + +} +
Full Code
<?php declare(strict_types = 1);
namespace App\Webapp\Notifications;
use Apex\Svc{App, Container, Emailer, Db, Convert}; use App\Webapp\Models\EmailNotification; use Apex\App\Adapters\ArmorAdapter; use Apex\App\Interfaces{EmailNotificationControllerInterface, UserInterface}; use Apex\Mercury\Email{EmailMessage, EmailContact, EmailContactCollection}; use Apex\Armor\Interfaces\ArmorUserInterface; use App\Users\User; use App\Webapp\Exceptions\WebappNotificationException; use App\Users\Exceptions\UserNotExistsException;
/** * Notifications */ class Notifications {
#[Inject(App::class)]
private App $app;
#[Inject(Container::class)]
private Container $cntr;
#[Inject(Db::class)]
private Db $db;
#[Inject(Convert::class)]
private Convert $convert;
#[Inject(ArmorAdapter::class)]
private ArmorAdapter $armor_adapter;
#[Inject(Emailer::class)]
private Emailer $emailer;
/**
* Process e-mail notifications
*/
public function process(string $class_name, string $uuid = '', array $condition = [], array $data = []):void
{
// Check class
if (!class_exists($class_name)) {
throw new WebappNotificationException("Notification controller does not exist, $class_name");
}
// Load class
$obj = $this->cntr->make($class_name);
if (!$obj instanceof EmailNotificationControllerInterface) {
throw new WebappNotificationException("Notification class does not implement the EmailNotificationControllerInterface, $lcass_name");
}
// Go through all notifications
$rows = EmailNotification::where('controller = %s', $class_name);
foreach ($rows as $email) {
// Check notification
if (!$this->checkCondition($email, $condition)) {
continue;
}
// Get user
$user = null;
if ($uuid != '' && !$user = User::loadUuid($uuid)) {
throw new UserNotExistsException("No user exists with the uuid, $uuid");
}
// Process individual notification
$this->send($obj, $email, $user, $data);
}
}
/**
* Check condition
*/
private function checkCondition(EmailNotification $email, array $condition):bool
{
// Decode condition
$chk = json_decode($email->condition_vars, true);
// GO through condition vars
$ok=true;
foreach ($condition as $key => $value) {
$chk_value = $chk[$key] ?? '';
if ($value != $chk_value) {
$ok = false;
break;
}
}
// Return
return $ok;
}
/**
* Send notification
*/
public function send(EmailNotificationControllerInterface $obj, EmailNotification $email, ?ArmorUserInterface $user, array $data):void
{
// Initialize
$uuid = $user === null ? '' : $user->getUuid();
// Get sender and recipient
$sender = $this->getSender($obj, $user, $email->sender, $data);
$recipients = $this->getRecipients($obj, $user, $email->recipient, $data);
// Get merge vars
$merge_vars = $this->getMergeVars($obj, $user, $data);
// Go through recipients
foreach ($recipients as $recipient) {
// Format subject and contents
list($tmp_subject, $tmp_contents, $tmp_html_contents) = [$email->subject, $email->text_contents, $email->html_contents];
foreach ($merge_vars as $key => $value) {
if ($value instanceof \DateTime) {
$value = $this->convert->date($value);
}
$tmp_subject = str_replace("~$key~", (string) $value, $tmp_subject);
$tmp_contents = str_replace("~$key~", (string) $value, $tmp_contents);
$tmp_html_contents = str_replace("~$key~", (string) $value, $tmp_html_contents);
}
// Create e-mail notification
$msg = $this->cntr->make(EmailMessage::class, [
'to_email' => $recipient->getEmail(),
'to_name' => $recipient->getName() === null ? '' : $recipient->getName(),
'from_email' => $sender->getEmail(),
'from_name' => $sender->getName() === null ? '' : $sender->getName(),
'reply_to' => $this->getReplyTo($obj, $email, $data),
'cc' => $this->getCc($obj, $email, $data),
'bcc' => $this->getBcc($obj, $email, $data),
'subject' => $tmp_subject,
'text_message' => $tmp_contents,
'html_message' => $tmp_html_contents
]);
// Send e-mail message
$this->emailer->send($msg);
}
}
/**
* Get sender
*/
private function getSender(EmailNotificationControllerInterface $obj, ?ArmorUserInterface $user, string $alias, array $data):?EmailContact
{
// Check for specific user
$sender = null;
if (preg_match("/^\w\:\d+$/", $alias)) {
if (!$sender = $this->armor_adapter->getUuid($this->db, $alias)) {
throw new UserNotExistsException("Sender does not exist with uuid, $alias");
}
} elseif ($sender == 'user' && $user === null) {
throw new WebappNotificationException("Sender for e-mail notification is set to 'user' but user is null.");
} elseif ($alias == 'user') {
$sender = $user;
}
// Get e-mail contact
if ($sender !== null) {
$contact = $this->cntr->make(EmailContact::class, [
'email' => $sender->getEmail(),
'name' => $sender->getFullName()
]);
} elseif (!$contact = $obj->getSender($alias, $user, $data)) {
throw new WebappNotificationException("Unable to determine sender for '$alias' with user '" . $user->getUuid() . "'");
}
// Return
return $contact;
}
/**
* Get recipients
*/
private function getRecipients(EmailNotificationControllerInterface $obj, ?ArmorUserInterface $user, string $alias, array $data):?EmailContactCollection
{
// Initialize
$recipient = null;
$col = $this->cntr->make(EmailContactCollection::class);
// Check for specific user
if (preg_match("/^\w\:\d+$/", $alias)) {
if (!$recipient = $this->armor_adapter->getUuid($this->db, $alias)) {
throw new UserNotExistsException("Sender does not exist with uuid, $alias");
}
} elseif ($alias == 'user' && $user === null) {
throw new WebappNotificationException("E-mail notification recipient is set to 'user' but user is null.");
} elseif ($alias == 'user') {
$recipient = $user;
}
// Get e-mail contact
if ($recipient !== null) {
$contact = $this->cntr->make(EmailContact::class, [
'email' => $recipient->getEmail(),
'name' => $recipient->getFullName()
]);
$col[] = $contact;
} elseif (!$col = $obj->getRecipients($alias, $user, $data)) {
$uuid = $user === null ? 'null' : $user->getUuid();
throw new WebappNotificationException("Unable to determine recipients for '$alias' with user, $uuid");
}
// Return
return $col;
}
/**
* Get reply to
*/
private function getReplyTo(EmailNotificationControllerInterface $obj, EmailNotification $email, array $data):string
{
// Check obj
if (null === ($reply_to = $obj->getReplyTo($data))) {
$reply_to = $email->reply_to;
}
// Return
return $reply_to;
}
/**
* Get cc
*/
private function getCc(EmailNotificationControllerInterface $obj, EmailNotification $email, array $data):array
{
// Check obj
if (null === ($cc = $obj->getCc($data))) {
$cc = $email->cc == '' ? [] : [$email->cc];
}
// Return
return $cc;
}
/**
* Get bcc
*/
private function getBcc(EmailNotificationControllerInterface $obj, EmailNotification $email, array $data):array
{
// Check obj
if (null === ($bcc = $obj->getBcc($data))) {
$bcc = $email->bcc == '' ? [] : [$email->bcc];
}
// Return
return $bcc;
}
/**
* Get merge vars
*/
public function getMergeVars(EmailNotificationControllerInterface $obj, ?UserInterface $user, array $data):array
{
// Init
$profie = [];
$uuid = '';
// Get user profile
if ($user !== null) {
$profile = $user->toDisplayArray();
$uuid = $user->getUuid();
}
$profile['domain_name'] = $this->app->config('core.domain_name');
$profile['site_name'] = $this->app->config('core.site_name');
$profile['install_url'] = 'https://' . $this->app->config('core.domain_name');
// Get vars from controller
if ($vars = $obj->getMergeVars($uuid, $data)) {
$profile = array_merge($profile, $vars);
}
// Return
return $profile;
}
}