Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 73
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
TaskComment
0.00% covered (danger)
0.00%
0 / 73
0.00% covered (danger)
0.00%
0 / 6
342
0.00% covered (danger)
0.00%
0 / 1
 save
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
42
 getForTaskAndDate
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
12
 getForTask
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
 delete
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 fromArray
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 toArray
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace BuyerKiosk\Workbook;
4
5use \PDO;
6use \PDOException;
7
8/**
9 * TaskComment - Model for task comments
10 *
11 * Manages comments on tasks for specific dates, allowing employees to
12 * add notes and context to daily task execution.
13 */
14class TaskComment
15{
16    /**
17     * @var int|null Comment ID
18     */
19    public $id;
20
21    /**
22     * @var int Task ID
23     */
24    public $taskId;
25
26    /**
27     * @var string Date this comment relates to (Y-m-d format)
28     */
29    public $date;
30
31    /**
32     * @var int Employee ID who created the comment
33     */
34    public $employeeId;
35
36    /**
37     * @var string Comment text
38     */
39    public $comment;
40
41    /**
42     * @var string Created timestamp
43     */
44    public $createdAt;
45
46    /**
47     * Save task comment (insert)
48     *
49     * @param PDO $db Database connection
50     * @return int The ID of the created comment
51     * @throws \Exception If required fields are missing or insert fails
52     */
53    public function save(PDO $db): int
54    {
55        if (!isset($this->taskId) || !isset($this->date) || !isset($this->employeeId) || !isset($this->comment)) {
56            throw new \Exception('taskId, date, employeeId, and comment are required');
57        }
58
59        try {
60            $stmt = $db->prepare("
61                INSERT INTO workbook_task_comments
62                (taskId, date, employeeId, comment)
63                VALUES
64                (:taskId, :date, :employeeId, :comment)
65            ");
66
67            $stmt->execute([
68                ':taskId' => $this->taskId,
69                ':date' => $this->date,
70                ':employeeId' => $this->employeeId,
71                ':comment' => $this->comment
72            ]);
73
74            $this->id = (int) $db->lastInsertId();
75            return $this->id;
76        } catch (PDOException $e) {
77            error_log("TaskComment::save error: " . $e->getMessage());
78            throw new \Exception('Failed to save task comment: ' . $e->getMessage());
79        }
80    }
81
82    /**
83     * Get all comments for a specific task and date
84     *
85     * Includes employee first and last name via JOIN
86     *
87     * @param PDO $db Database connection
88     * @param int $taskId Task ID
89     * @param string $date Date (Y-m-d format)
90     * @return array Array of TaskComment objects with employee names
91     */
92    public static function getForTaskAndDate(PDO $db, int $taskId, string $date): array
93    {
94        try {
95            $stmt = $db->prepare("
96                SELECT dtc.*, e.employeeFirstName, e.employeeLastName
97                FROM workbook_task_comments dtc
98                INNER JOIN employees e ON dtc.employeeId = e.employeeID
99                WHERE dtc.taskId = :taskId AND dtc.date = :date
100                ORDER BY dtc.createdAt ASC
101            ");
102            $stmt->execute([
103                ':taskId' => $taskId,
104                ':date' => $date
105            ]);
106
107            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
108            $comments = [];
109
110            foreach ($rows as $row) {
111                $comment = self::fromArray($row);
112                // Add employee name for convenience
113                $comment->employeeFirstName = $row['employeeFirstName'];
114                $comment->employeeLastName = $row['employeeLastName'];
115                $comments[] = $comment;
116            }
117
118            return $comments;
119        } catch (PDOException $e) {
120            error_log("TaskComment::getForTaskAndDate error: " . $e->getMessage());
121            return [];
122        }
123    }
124
125    /**
126     * Get all comments for a specific task (across all dates)
127     *
128     * Includes employee first and last name via JOIN
129     *
130     * @param PDO $db Database connection
131     * @param int $taskId Task ID
132     * @param int $limit Optional limit on number of comments to return
133     * @return array Array of TaskComment objects with employee names
134     */
135    public static function getForTask(PDO $db, int $taskId, int $limit = 100): array
136    {
137        try {
138            $stmt = $db->prepare("
139                SELECT dtc.*, e.employeeFirstName, e.employeeLastName
140                FROM workbook_task_comments dtc
141                INNER JOIN employees e ON dtc.employeeId = e.employeeID
142                WHERE dtc.taskId = :taskId
143                ORDER BY dtc.date DESC, dtc.createdAt DESC
144                LIMIT :limit
145            ");
146            $stmt->bindValue(':taskId', $taskId, PDO::PARAM_INT);
147            $stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
148            $stmt->execute();
149
150            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
151            $comments = [];
152
153            foreach ($rows as $row) {
154                $comment = self::fromArray($row);
155                // Add employee name for convenience
156                $comment->employeeFirstName = $row['employeeFirstName'];
157                $comment->employeeLastName = $row['employeeLastName'];
158                $comments[] = $comment;
159            }
160
161            return $comments;
162        } catch (PDOException $e) {
163            error_log("TaskComment::getForTask error: " . $e->getMessage());
164            return [];
165        }
166    }
167
168    /**
169     * Delete a task comment
170     *
171     * @param PDO $db Database connection
172     * @return bool True if successful
173     */
174    public function delete(PDO $db): bool
175    {
176        if (!isset($this->id)) {
177            error_log("TaskComment::delete error: id is required");
178            return false;
179        }
180
181        try {
182            $stmt = $db->prepare("
183                DELETE FROM workbook_task_comments
184                WHERE id = :id
185            ");
186
187            return $stmt->execute([':id' => $this->id]);
188        } catch (PDOException $e) {
189            error_log("TaskComment::delete error: " . $e->getMessage());
190            return false;
191        }
192    }
193
194    /**
195     * Create a TaskComment object from an array
196     *
197     * @param array $data Associative array of task comment data
198     * @return self
199     */
200    public static function fromArray(array $data): self
201    {
202        $comment = new self();
203        $comment->id = isset($data['id']) ? (int) $data['id'] : null;
204        $comment->taskId = (int) $data['taskId'];
205        $comment->date = $data['date'];
206        $comment->employeeId = (int) $data['employeeId'];
207        $comment->comment = $data['comment'];
208        $comment->createdAt = $data['createdAt'] ?? null;
209
210        return $comment;
211    }
212
213    /**
214     * Convert TaskComment to array
215     *
216     * @return array Associative array representation
217     */
218    public function toArray(): array
219    {
220        return [
221            'id' => $this->id,
222            'taskId' => $this->taskId,
223            'date' => $this->date,
224            'employeeId' => $this->employeeId,
225            'comment' => $this->comment,
226            'createdAt' => $this->createdAt
227        ];
228    }
229}