From 34935b8eeddc418bf884b166dcd196bb37e8120f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 1 May 2026 12:07:32 +1200 Subject: [PATCH] feat(notifications): add Notification event class Replaces the Mail event with a multi-channel Notification event capable of dispatching to email, console, and webhook recipients in a single payload. Maintains the existing Mail surface (setSubject, setRecipient, setBody, etc.) so existing call sites can be migrated mechanically. --- src/Appwrite/Event/Event.php | 4 +- src/Appwrite/Event/Notification.php | 445 ++++++++++++++++++++++++++++ 2 files changed, 447 insertions(+), 2 deletions(-) create mode 100644 src/Appwrite/Event/Notification.php diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 357442a07c..06af738857 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -18,8 +18,8 @@ class Event public const AUDITS_QUEUE_NAME = 'v1-audits'; public const AUDITS_CLASS_NAME = 'AuditsV1'; - public const MAILS_QUEUE_NAME = 'v1-mails'; - public const MAILS_CLASS_NAME = 'MailsV1'; + public const NOTIFICATIONS_QUEUE_NAME = 'v1-notifications'; + public const NOTIFICATIONS_CLASS_NAME = 'NotificationsV1'; public const FUNCTIONS_QUEUE_NAME = 'v1-functions'; public const FUNCTIONS_CLASS_NAME = 'FunctionsV1'; diff --git a/src/Appwrite/Event/Notification.php b/src/Appwrite/Event/Notification.php new file mode 100644 index 0000000000..fa490f3405 --- /dev/null +++ b/src/Appwrite/Event/Notification.php @@ -0,0 +1,445 @@ + + */ + protected array $recipients = []; + + /** + * @var array + */ + protected array $channels = []; + + protected string $template = ''; + protected array $templateParams = []; + protected string $dedupKey = ''; + + /** + * @var array + */ + protected array $permissions = []; + + public function __construct(protected Publisher $publisher) + { + parent::__construct($publisher); + + $this + ->setQueue(System::getEnv('_APP_NOTIFICATIONS_QUEUE_NAME', Event::NOTIFICATIONS_QUEUE_NAME)) + ->setClass(System::getEnv('_APP_NOTIFICATIONS_CLASS_NAME', Event::NOTIFICATIONS_CLASS_NAME)); + } + + public function setSubject(string $subject): self + { + $this->subject = $subject; + return $this; + } + + public function getSubject(): string + { + return $this->subject; + } + + public function setRecipient(string $recipient): self + { + $this->recipient = $recipient; + return $this; + } + + public function getRecipient(): string + { + return $this->recipient; + } + + public function setBody(string $body): self + { + $this->body = $body; + return $this; + } + + public function getBody(): string + { + return $this->body; + } + + public function setPreview(string $preview): self + { + $this->preview = $preview; + return $this; + } + + public function getPreview(): string + { + return $this->preview; + } + + public function setName(string $name): self + { + $this->name = $name; + return $this; + } + + public function getName(): string + { + return $this->name; + } + + public function setBodyTemplate(string $bodyTemplate): self + { + $this->bodyTemplate = $bodyTemplate; + return $this; + } + + public function getBodyTemplate(): string + { + return $this->bodyTemplate; + } + + public function setSmtpHost(string $host): self + { + $this->smtp['host'] = $host; + return $this; + } + + public function setSmtpPort(int $port): self + { + $this->smtp['port'] = $port; + return $this; + } + + public function setSmtpUsername(string $username): self + { + $this->smtp['username'] = $username; + return $this; + } + + public function setSmtpPassword(string $password): self + { + $this->smtp['password'] = $password; + return $this; + } + + public function setSmtpSecure(string $secure): self + { + $this->smtp['secure'] = $secure; + return $this; + } + + public function setSmtpSenderEmail(string $senderEmail): self + { + $this->smtp['senderEmail'] = $senderEmail; + return $this; + } + + public function setSmtpSenderName(string $senderName): self + { + $this->smtp['senderName'] = $senderName; + return $this; + } + + public function setSmtpReplyToEmail(string $email): self + { + $this->smtp['replyToEmail'] = $email; + return $this; + } + + public function setSmtpReplyToName(string $name): self + { + $this->smtp['replyToName'] = $name; + return $this; + } + + public function getSmtpHost(): string + { + return $this->smtp['host'] ?? ''; + } + + public function getSmtpPort(): int + { + return $this->smtp['port'] ?? 0; + } + + public function getSmtpUsername(): string + { + return $this->smtp['username'] ?? ''; + } + + public function getSmtpPassword(): string + { + return $this->smtp['password'] ?? ''; + } + + public function getSmtpSecure(): string + { + return $this->smtp['secure'] ?? ''; + } + + public function getSmtpSenderEmail(): string + { + return $this->smtp['senderEmail'] ?? ''; + } + + public function getSmtpSenderName(): string + { + return $this->smtp['senderName'] ?? ''; + } + + public function getSmtpReplyToEmail(): string + { + return $this->smtp['replyToEmail'] ?? ''; + } + + public function getSmtpReplyToName(): string + { + return $this->smtp['replyToName'] ?? ''; + } + + public function getVariables(): array + { + return $this->variables; + } + + public function setVariables(array $variables): self + { + $this->variables = $variables; + return $this; + } + + public function appendVariables(array $variables): self + { + $this->variables = \array_merge($this->variables, $variables); + return $this; + } + + public function setAttachment(string $content, string $filename, string $encoding = 'base64', string $type = 'plain/text'): self + { + $this->attachment = [ + 'content' => \base64_encode($content), + 'filename' => $filename, + 'encoding' => $encoding, + 'type' => $type, + ]; + return $this; + } + + public function getAttachment(): array + { + return $this->attachment; + } + + public function resetAttachment(): self + { + $this->attachment = []; + return $this; + } + + public function setSenderEmail(string $email): self + { + $this->customMailOptions['senderEmail'] = $email; + return $this; + } + + public function getSenderEmail(): string + { + return $this->customMailOptions['senderEmail'] ?? ''; + } + + public function setSenderName(string $name): self + { + $this->customMailOptions['senderName'] = $name; + return $this; + } + + public function getSenderName(): string + { + return $this->customMailOptions['senderName'] ?? ''; + } + + public function setReplyToEmail(string $email): self + { + $this->customMailOptions['replyToEmail'] = $email; + return $this; + } + + public function getReplyToEmail(): string + { + return $this->customMailOptions['replyToEmail'] ?? ''; + } + + public function setReplyToName(string $name): self + { + $this->customMailOptions['replyToName'] = $name; + return $this; + } + + public function getReplyToName(): string + { + return $this->customMailOptions['replyToName'] ?? ''; + } + + /** + * @param array $recipients + */ + public function setRecipients(array $recipients): self + { + $this->recipients = $recipients; + return $this; + } + + /** + * @return array + */ + public function getRecipients(): array + { + return $this->recipients; + } + + public function addRecipient(string $address, string $channel = NOTIFICATION_CHANNEL_EMAIL): self + { + $this->recipients[] = ['address' => $address, 'channel' => $channel]; + return $this; + } + + /** + * @param array $channels + */ + public function setChannels(array $channels): self + { + $this->channels = $channels; + return $this; + } + + /** + * @return array + */ + public function getChannels(): array + { + return $this->channels; + } + + public function setTemplate(string $template): self + { + $this->template = $template; + return $this; + } + + public function getTemplate(): string + { + return $this->template; + } + + public function setTemplateParams(array $params): self + { + $this->templateParams = $params; + return $this; + } + + public function getTemplateParams(): array + { + return $this->templateParams; + } + + public function setDedupKey(string $dedupKey): self + { + $this->dedupKey = $dedupKey; + return $this; + } + + public function getDedupKey(): string + { + return $this->dedupKey; + } + + /** + * @param array $permissions + */ + public function setPermissions(array $permissions): self + { + $this->permissions = $permissions; + return $this; + } + + /** + * @return array + */ + public function getPermissions(): array + { + return $this->permissions; + } + + public function reset(): self + { + $this->project = null; + $this->recipient = ''; + $this->name = ''; + $this->subject = ''; + $this->body = ''; + $this->variables = []; + $this->bodyTemplate = ''; + $this->attachment = []; + $this->customMailOptions = []; + $this->recipients = []; + $this->channels = []; + $this->template = ''; + $this->templateParams = []; + $this->dedupKey = ''; + $this->permissions = []; + return $this; + } + + protected function preparePayload(): array + { + $platform = $this->platform; + if (empty($platform)) { + $platform = Config::getParam('platform', []); + } + + $recipients = $this->recipients; + if (empty($recipients) && !empty($this->recipient)) { + $recipients = [[ + 'address' => $this->recipient, + 'channel' => NOTIFICATION_CHANNEL_EMAIL, + ]]; + } + + return [ + 'project' => $this->project, + 'recipient' => $this->recipient, + 'recipients' => $recipients, + 'channels' => $this->channels, + 'template' => $this->template, + 'templateParams' => $this->templateParams, + 'dedupKey' => $this->dedupKey, + 'permissions' => $this->permissions, + 'name' => $this->name, + 'subject' => $this->subject, + 'bodyTemplate' => $this->bodyTemplate, + 'body' => $this->body, + 'preview' => $this->preview, + 'smtp' => $this->smtp, + 'variables' => $this->variables, + 'attachment' => $this->attachment, + 'customMailOptions' => $this->customMailOptions, + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), + 'platform' => $platform, + ]; + } +}