Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.67% covered (success)
91.67%
22 / 24
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ContactRepository
91.67% covered (success)
91.67%
22 / 24
33.33% covered (danger)
33.33%
1 / 3
5.01
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 insert
90.91% covered (success)
90.91%
10 / 11
0.00% covered (danger)
0.00%
0 / 1
2.00
 insertPublic
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
2.00
1<?php
2
3declare(strict_types=1);
4
5namespace App\Domain\Contact\Repository;
6
7use App\Domain\Contact\Data\ContactMessageData;
8use PDO;
9use RuntimeException;
10
11use function is_array;
12
13final readonly class ContactRepository
14{
15    public function __construct(private PDO $pdo) {}
16
17    private const string RETURNING = '
18                RETURNING
19                    contact_message_id AS "contactMessageId",
20                    user_id AS "userId",
21                    subject,
22                    message,
23                    status,
24                    created_at::TEXT AS "createdAt",
25                    sender_name AS "senderName",
26                    sender_email AS "senderEmail"';
27
28    public function insert(int $userId, string $subject, string $message): ContactMessageData
29    {
30        $sql = 'INSERT INTO contact_messages (user_id, subject, message)
31                VALUES (:user_id, :subject, :message)' . self::RETURNING;
32
33        $stmt = $this->pdo->prepare($sql);
34        $stmt->bindValue(':user_id', $userId, PDO::PARAM_INT);
35        $stmt->bindValue(':subject', $subject);
36        $stmt->bindValue(':message', $message);
37        $stmt->execute();
38
39        $row = $stmt->fetch(PDO::FETCH_ASSOC);
40        if (!is_array($row)) {
41            throw new RuntimeException('Failed to insert contact_messages row');
42        }
43
44        return ContactMessageData::fromRow($row);
45    }
46
47    /**
48     * Inserts a contact message from an unauthenticated (public) submitter.
49     * user_id is left null; the reply-to identity lives in sender_name/email.
50     * @param string $senderName
51     * @param string $senderEmail
52     * @param string $subject
53     * @param string $message
54     */
55    public function insertPublic(
56        string $senderName,
57        string $senderEmail,
58        string $subject,
59        string $message,
60    ): ContactMessageData {
61        $sql = 'INSERT INTO contact_messages (user_id, sender_name, sender_email, subject, message)
62                VALUES (NULL, :sender_name, :sender_email, :subject, :message)' . self::RETURNING;
63
64        $stmt = $this->pdo->prepare($sql);
65        $stmt->bindValue(':sender_name', $senderName);
66        $stmt->bindValue(':sender_email', $senderEmail);
67        $stmt->bindValue(':subject', $subject);
68        $stmt->bindValue(':message', $message);
69        $stmt->execute();
70
71        $row = $stmt->fetch(PDO::FETCH_ASSOC);
72        if (!is_array($row)) {
73            throw new RuntimeException('Failed to insert public contact_messages row');
74        }
75
76        return ContactMessageData::fromRow($row);
77    }
78}