death-notifier/src/main/php/com/fwdekker/deathnotifier/mailer/EmailQueue.php

118 lines
3.6 KiB
PHP

<?php
namespace com\fwdekker\deathnotifier\mailer;
use com\fwdekker\deathnotifier\Database;
use PDO;
/**
* A queue of {@see Email Emails}, stored in a {@see Database}.
*/
class EmailQueue
{
/**
* @var Database the database to store the queue in
*/
private readonly Database $database;
/**
* Constructs a new `EmailQueue`.
*
* @param Database $database the database to store the queue in
*/
public function __construct(Database $database)
{
$this->database = $database;
}
/**
* Populates the {@see Database} with the necessary structures for an `EmailQueue`.
*
* @return void
*/
public function install(): void
{
$conn = $this->database->conn;
$conn->exec("CREATE TABLE email_tasks(type_key TEXT NOT NULL,
recipient TEXT NOT NULL,
subject TEXT NOT NULL,
body TEXT NOT NULL,
PRIMARY KEY (type_key, recipient));");
}
/**
* Executes {@see $lambda} within a single database transaction.
*
* @param callable(): void $lambda the function to execute within a transaction
* @return void
* @see Database::transaction()
*/
public function transaction(callable $lambda): void
{
$this->database->transaction($lambda);
}
/**
* Returns all queued emails.
*
* @return array<array{"type_key": string, "recipient": string, "subject": string, "body": string}> all queued
* emails
*/
public function get_queue(): array
{
$stmt = $this->database->conn->prepare("SELECT type_key, recipient, subject, body FROM email_tasks;");
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Adds {@see Email Emails} to the queue.
*
* {@see emails} are added to the database, with the primary keys determined by {@see Email::$type_key} and
* {@see Email::$recipient}. If an {@see Email} with this key is already in the queue, it is replaced with
* {@see $emails}.
*
* @param array<Email> $emails the emails to queue
* @return void
*/
public function enqueue(array $emails): void
{
$stmt = $this->database->conn->prepare("INSERT OR REPLACE INTO email_tasks (type_key, recipient, subject, body)
VALUES (:type_key, :recipient, :subject, :body);");
$stmt->bindParam(":recipient", $recipient);
$stmt->bindParam(":type_key", $type_key);
$stmt->bindParam(":subject", $subject);
$stmt->bindParam(":body", $body);
foreach ($emails as $email) {
$recipient = $email->recipient;
$type_key = $email->type_key;
$subject = $email->get_subject();
$body = $email->get_body();
$stmt->execute();
}
}
/**
* Removes mails from the queue.
*
* @param array<array{"type_key": string, "recipient": string}> $emails the emails to remove from the queue
* @return void
*/
public function unqueue(array $emails): void
{
$stmt = $this->database->conn->prepare("DELETE FROM email_tasks
WHERE type_key=:type_key AND recipient=:recipient;");
$stmt->bindParam(":type_key", $type_key);
$stmt->bindParam(":recipient", $recipient);
foreach ($emails as ["type_key" => $type_key, "recipient" => $recipient])
$stmt->execute();
}
}