From 2eb5a432d2229788ce2fdb09f36c6f4bebdea813 Mon Sep 17 00:00:00 2001 From: Laria Carolin Chabowski Date: Fri, 7 Feb 2020 09:44:59 +0100 Subject: Initial commit --- src/Models/Note.php | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/Models/Note.php (limited to 'src/Models/Note.php') diff --git a/src/Models/Note.php b/src/Models/Note.php new file mode 100644 index 0000000..901f5aa --- /dev/null +++ b/src/Models/Note.php @@ -0,0 +1,250 @@ +id = uniqid("", true); + } + + /** + * @param SQLite3 $db + * @param DbQuery $query + * @return self[] + */ + private static function fromQuery(SQLite3 $db, DbQuery $query): array + { + $out = []; + + foreach ($query->fetchRowsAssoc($db) as $row) { + $note = new self(); + + $note->savedToDb = true; + $note->id = $row["id"]; + $note->content = $row["content"]; + $note->trash = (bool)(int)$row["trash"]; + + $out[$row["id"]] = $note; + } + + if (!empty($out)) { + $q = (new DbQuery("SELECT tag, note_id FROM tags WHERE note_id IN (" . DbQuery::valueListPlaceholders($out) . ")")) + ->bindMultiText(array_keys($out)); + + foreach ($q->fetchRows($db) as [$tag, $id]) { + $out[$id]->tags[] = $tag; + } + } + + return $out; + } + + /** + * @param SQLite3 $db + * @param array $ids + * @return self[] indexes by id + */ + public static function byIds(SQLite3 $db, array $ids): array + { + if (empty($ids)) + return []; + + $query = (new DbQuery(" + SELECT note.id, content.content, note.trash + FROM notes note + INNER JOIN note_contents content + ON content.rowid = note.content_row + WHERE id IN (" . DbQuery::valueListPlaceholders($ids) . ") + "))->bindMultiText($ids); + + return self::fromQuery($db, $query); + } + + public static function byId(SQLite3 $db, string $id): ?self + { + return self::byIds($db, [$id])[$id] ?? null; + } + + /** + * @return string + */ + public function getId(): string + { + return $this->id; + } + + /** + * @return string + */ + public function getContent(): string + { + return $this->content; + } + + /** + * @param string $content + * @return Note + */ + public function setContent(string $content): Note + { + $this->content = $content; + return $this; + } + + /** + * @return array + */ + public function getTags(): array + { + return $this->tags; + } + + /** + * @param array $tags + * @return Note + */ + public function setTags(array $tags): Note + { + $tags = array_map("trim", $tags); + $tags = array_filter($tags); + $tags = array_unique($tags); + + $this->tags = $tags; + return $this; + } + + /** + * @return bool + */ + public function isTrash(): bool + { + return $this->trash; + } + + /** + * @param bool $trash + * @return Note + */ + public function setTrash(bool $trash): Note + { + $this->trash = $trash; + return $this; + } + + private function deleteContent(SQLite3 $db) + { + (new DbQuery("DELETE FROM note_contents WHERE rowid IN (SELECT content_row FROM notes WHERE id = ?)")) + ->bind(1, BoundVal::ofText($this->id)) + ->exec($db); + } + + private function deleteTags(SQLite3 $db) + { + (new DbQuery("DELETE FROM tags WHERE note_id = ?")) + ->bind(1, BoundVal::ofText($this->id)) + ->exec($db); + } + + public function save(SQLite3 $db) + { + if ($this->savedToDb) + $this->update($db); + else + $this->insert($db); + } + + private function insert(SQLite3 $db) + { + $db->exec("BEGIN"); + + $this->deleteContent($db); + + DbQuery::insertKV($db, "note_contents", ["content" => BoundVal::ofText($this->content)]); + $rowid = (new DbQuery("SELECT last_insert_rowid()"))->fetchRow($db)[0]; + + DbQuery::insertKV($db, "notes", [ + "id" => BoundVal::ofText($this->id), + "content_row" => BoundVal::ofInt($rowid), + "trash" => BoundVal::ofInt($this->trash ? 0 : 1), + ]); + + $this->writeTags($db); + + $db->exec("COMMIT"); + } + + private function update(SQLite3 $db) + { + $db->exec("BEGIN"); + + $this->deleteTags($db); + + (new DbQuery(" + UPDATE note_contents + SET content = :content + WHERE rowid = ( + SELECT content_row + FROM notes + WHERE id = :id + ) + ")) + ->bind("content", BoundVal::ofText($this->content)) + ->bind("id", BoundVal::ofText($this->id)) + ->exec($db); + + $this->writeTags($db); + + (new DbQuery(" + UPDATE notes + SET changed_at = CURRENT_TIMESTAMP, + trash = :trash + WHERE id = :id + ")) + ->bind("id", BoundVal::ofText($this->id)) + ->bind("trash", BoundVal::ofInt($this->trash ? 0 : 1)) + ->exec($db); + + $db->exec("COMMIT"); + } + + /** + * @param SQLite3 $db + */ + private function writeTags(SQLite3 $db): void + { + $this->deleteTags($db); + DbQuery::insert($db, + "tags", + ["note_id", "tag"], + array_map(fn($t) => [BoundVal::ofText($this->id), BoundVal::ofText($t)], $this->tags) + ); + } + + public function delete(SQLite3 $db): void + { + $this->deleteTags($db); + $this->deleteContent($db); + (new DbQuery("DELETE FROM notes WHERE id = ?")) + ->bind(1, BoundVal::ofText($this->id)) + ->exec($db); + $this->savedToDb = false; + } +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf