pdo->prepare( 'SELECT * FROM todo_items WHERE list_id = :list ORDER BY position ASC, id ASC' ); $stmt->execute(['list' => $listId]); return array_map($this->cast(...), $stmt->fetchAll()); } /** * @return TodoItemRow|null */ public function findInList(int $id, int $listId): ?array { $stmt = $this->pdo->prepare('SELECT * FROM todo_items WHERE id = :id AND list_id = :list'); $stmt->execute(['id' => $id, 'list' => $listId]); $row = $stmt->fetch(); return $row === false ? null : $this->cast($row); } /** * @return TodoItemRow */ public function create(int $listId, string $text, bool $complete, ?int $position): array { $position ??= $this->nextPosition($listId); $stmt = $this->pdo->prepare( 'INSERT INTO todo_items (list_id, text, complete, position) VALUES (:list, :text, :complete, :position)' ); $stmt->execute([ 'list' => $listId, 'text' => $text, 'complete' => $complete ? 1 : 0, 'position' => $position, ]); /** @var TodoItemRow $item */ $item = $this->findInList((int) $this->pdo->lastInsertId(), $listId); return $item; } /** * @param array{text?: string, complete?: bool, position?: int} $fields * @return TodoItemRow */ public function update(int $id, int $listId, array $fields): array { $sets = ['updated_at = ' . "strftime('%Y-%m-%dT%H:%M:%SZ', 'now')"]; $params = ['id' => $id]; if (array_key_exists('text', $fields)) { $sets[] = 'text = :text'; $params['text'] = $fields['text']; } if (array_key_exists('complete', $fields)) { $sets[] = 'complete = :complete'; $params['complete'] = $fields['complete'] ? 1 : 0; } if (array_key_exists('position', $fields)) { $sets[] = 'position = :position'; $params['position'] = $fields['position']; } $stmt = $this->pdo->prepare('UPDATE todo_items SET ' . implode(', ', $sets) . ' WHERE id = :id'); $stmt->execute($params); /** @var TodoItemRow $item */ $item = $this->findInList($id, $listId); return $item; } public function delete(int $id): void { $this->pdo->prepare('DELETE FROM todo_items WHERE id = :id')->execute(['id' => $id]); } private function nextPosition(int $listId): int { $stmt = $this->pdo->prepare( 'SELECT COALESCE(MAX(position), -1) + 1 FROM todo_items WHERE list_id = :list' ); $stmt->execute(['list' => $listId]); return (int) $stmt->fetchColumn(); } /** * @param array $row * @return TodoItemRow */ private function cast(array $row): array { $row['id'] = (int) $row['id']; $row['list_id'] = (int) $row['list_id']; $row['complete'] = (bool) $row['complete']; $row['position'] = (int) $row['position']; /** @var TodoItemRow $row */ return $row; } }