diff options
Diffstat (limited to 'lib/posts.php')
-rw-r--r-- | lib/posts.php | 306 |
1 files changed, 218 insertions, 88 deletions
diff --git a/lib/posts.php b/lib/posts.php index 1537749..8ffb92b 100644 --- a/lib/posts.php +++ b/lib/posts.php @@ -1,9 +1,202 @@ <?php +class Post extends model { + + const DB_TABLE = 'posts'; + + public int $id; + public string $title; + public string $md; + public string $html; + public string $tocHtml; + public string $text; + public int $ts; + public int $updateTs; + public bool $visible; + public bool $toc; + public string $shortName; + + function edit(array $fields) { + $cur_ts = time(); + if (!$this->visible && $fields['visible']) + $fields['ts'] = $cur_ts; + + $fields['update_ts'] = $cur_ts; + + if ($fields['md'] != $this->md) { + $fields['html'] = markup::markdownToHtml($fields['md']); + $fields['text'] = markup::htmlToText($fields['html']); + } + + if ((isset($fields['toc']) && $fields['toc']) || $this->toc) { + $fields['toc_html'] = markup::toc($fields['md']); + } + + parent::edit($fields); + $this->updateImagePreviews(); + } + + function updateHtml() { + $html = markup::markdownToHtml($this->md); + $this->html = $html; + + DB()->query("UPDATE posts SET html=? WHERE id=?", $html, $this->id); + } + + function updateText() { + $html = markup::markdownToHtml($this->md); + $text = markup::htmlToText($html); + $this->text = $text; + + DB()->query("UPDATE posts SET text=? WHERE id=?", $text, $this->id); + } + + function getDescriptionPreview(int $len): string { + if (mb_strlen($this->text) >= $len) + return mb_substr($this->text, 0, $len-3).'...'; + return $this->text; + } + + function getFirstImage(): ?Upload { + if (!preg_match('/\{image:([\w]{8})/', $this->md, $match)) + return null; + return uploads::getUploadByRandomId($match[1]); + } + + function getUrl(): string { + return $this->shortName != '' ? "/{$this->shortName}/" : "/{$this->id}/"; + } + + function getDate(): string { + return date('j M', $this->ts); + } + + function getYear(): int { + return (int)date('Y', $this->ts); + } + + function getFullDate(): string { + return date('j F Y', $this->ts); + } + + function getUpdateDate(): string { + return date('j M', $this->updateTs); + } + + function getFullUpdateDate(): string { + return date('j F Y', $this->updateTs); + } + + function getHtml(bool $is_retina, string $theme): string { + $html = $this->html; + $html = markup::htmlImagesFix($html, $is_retina, $theme); + return $html; + } + + function getToc(): ?string { + return $this->toc ? $this->tocHtml : null; + } + + function isUpdated(): bool { + return $this->updateTs && $this->updateTs != $this->ts; + } + + /** + * @return Tag[] + */ + function getTags(): array { + $db = DB(); + $q = $db->query("SELECT tags.* FROM posts_tags + LEFT JOIN tags ON tags.id=posts_tags.tag_id + WHERE posts_tags.post_id=? + ORDER BY posts_tags.tag_id", $this->id); + return array_map('Tag::create_instance', $db->fetchAll($q)); + } + + /** + * @return int[] + */ + function getTagIds(): array { + $ids = []; + $db = DB(); + $q = $db->query("SELECT tag_id FROM posts_tags WHERE post_id=? ORDER BY tag_id", $this->id); + while ($row = $db->fetch($q)) { + $ids[] = (int)$row['tag_id']; + } + return $ids; + } + + function setTagIds(array $new_tag_ids) { + $cur_tag_ids = $this->getTagIds(); + $add_tag_ids = array_diff($new_tag_ids, $cur_tag_ids); + $rm_tag_ids = array_diff($cur_tag_ids, $new_tag_ids); + + $db = DB(); + if (!empty($add_tag_ids)) { + $rows = []; + foreach ($add_tag_ids as $id) + $rows[] = ['post_id' => $this->id, 'tag_id' => $id]; + $db->multipleInsert('posts_tags', $rows); + } + + if (!empty($rm_tag_ids)) + $db->query("DELETE FROM posts_tags WHERE post_id=? AND tag_id IN(".implode(',', $rm_tag_ids).")", $this->id); + + $upd_tag_ids = array_merge($new_tag_ids, $rm_tag_ids); + $upd_tag_ids = array_unique($upd_tag_ids); + foreach ($upd_tag_ids as $id) + tags::recountTagPosts($id); + } + + /** + * @param bool $update Whether to overwrite preview if already exists + * @return int + * @throws Exception + */ + function updateImagePreviews(bool $update = false): int { + $images = []; + if (!preg_match_all('/\{image:([\w]{8}),(.*?)}/', $this->md, $matches)) + return 0; + + for ($i = 0; $i < count($matches[0]); $i++) { + $id = $matches[1][$i]; + $w = $h = null; + $opts = explode(',', $matches[2][$i]); + foreach ($opts as $opt) { + if (str_contains($opt, '=')) { + list($k, $v) = explode('=', $opt); + if ($k == 'w') + $w = (int)$v; + else if ($k == 'h') + $h = (int)$v; + } + } + $images[$id][] = [$w, $h]; + } + + if (empty($images)) + return 0; + + $images_affected = 0; + $uploads = uploads::getUploadsByRandomId(array_keys($images), true); + foreach ($uploads as $u) { + foreach ($images[$u->randomId] as $s) { + list($w, $h) = $s; + list($w, $h) = $u->getImagePreviewSize($w, $h); + if ($u->createImagePreview($w, $h, $update, $u->imageMayHaveAlphaChannel())) + $images_affected++; + } + } + + return $images_affected; + } + +} + class posts { - public static function getPostsCount(bool $include_hidden = false): int { - $db = getDb(); + static function getCount(bool $include_hidden = false): int { + $db = DB(); $sql = "SELECT COUNT(*) FROM posts"; if (!$include_hidden) { $sql .= " WHERE visible=1"; @@ -11,14 +204,14 @@ class posts { return (int)$db->result($db->query($sql)); } - public static function getPostsCountByTagId(int $tag_id, bool $include_hidden = false): int { - $db = getDb(); + static function getCountByTagId(int $tag_id, bool $include_hidden = false): int { + $db = DB(); if ($include_hidden) { $sql = "SELECT COUNT(*) FROM posts_tags WHERE tag_id=?"; } else { $sql = "SELECT COUNT(*) FROM posts_tags - LEFT JOIN posts ON posts.id=posts_tags.post_id - WHERE posts_tags.tag_id=? AND posts.visible=1"; + LEFT JOIN posts ON posts.id=posts_tags.post_id + WHERE posts_tags.tag_id=? AND posts.visible=1"; } return (int)$db->result($db->query($sql, $tag_id)); } @@ -26,8 +219,8 @@ class posts { /** * @return Post[] */ - public static function getPosts(int $offset = 0, int $count = -1, bool $include_hidden = false): array { - $db = getDb(); + static function getList(int $offset = 0, int $count = -1, bool $include_hidden = false): array { + $db = DB(); $sql = "SELECT * FROM posts"; if (!$include_hidden) $sql .= " WHERE visible=1"; @@ -41,11 +234,11 @@ class posts { /** * @return Post[] */ - public static function getPostsByTagId(int $tag_id, bool $include_hidden = false): array { - $db = getDb(); + static function getPostsByTagId(int $tag_id, bool $include_hidden = false): array { + $db = DB(); $sql = "SELECT posts.* FROM posts_tags - LEFT JOIN posts ON posts.id=posts_tags.post_id - WHERE posts_tags.tag_id=?"; + LEFT JOIN posts ON posts.id=posts_tags.post_id + WHERE posts_tags.tag_id=?"; if (!$include_hidden) $sql .= " AND posts.visible=1"; $sql .= " ORDER BY posts.ts DESC"; @@ -53,8 +246,8 @@ class posts { return array_map('Post::create_instance', $db->fetchAll($q)); } - public static function add(array $data = []): int|bool { - $db = getDb(); + static function add(array $data = []): int|bool { + $db = DB(); $html = \markup::markdownToHtml($data['md']); $text = \markup::htmlToText($html); @@ -70,64 +263,41 @@ class posts { $id = $db->insertId(); - $post = posts::get($id); + $post = self::get($id); $post->updateImagePreviews(); return $id; } - public static function delete(Post $post): void { + static function delete(Post $post): void { $tags = $post->getTags(); - $db = getDb(); + $db = DB(); $db->query("DELETE FROM posts WHERE id=?", $post->id); $db->query("DELETE FROM posts_tags WHERE post_id=?", $post->id); foreach ($tags as $tag) - self::recountPostsWithTag($tag->id); + tags::recountTagPosts($tag->id); } - public static function getTagIds(array $tags): array { - $found_tags = []; - $map = []; - - $db = getDb(); - $q = $db->query("SELECT id, tag FROM tags - WHERE tag IN ('".implode("','", array_map(function($tag) use ($db) { return $db->escape($tag); }, $tags))."')"); - while ($row = $db->fetch($q)) { - $found_tags[] = $row['tag']; - $map[$row['tag']] = (int)$row['id']; - } - - $notfound_tags = array_diff($tags, $found_tags); - if (!empty($notfound_tags)) { - foreach ($notfound_tags as $tag) { - $db->insert('tags', ['tag' => $tag]); - $map[$tag] = $db->insertId(); - } - } - - return $map; - } - - public static function get(int $id): ?Post { - $db = getDb(); + static function get(int $id): ?Post { + $db = DB(); $q = $db->query("SELECT * FROM posts WHERE id=?", $id); return $db->numRows($q) ? new Post($db->fetch($q)) : null; } - public static function getPostByName(string $short_name): ?Post { - $db = getDb(); + static function getByName(string $short_name): ?Post { + $db = DB(); $q = $db->query("SELECT * FROM posts WHERE short_name=?", $short_name); return $db->numRows($q) ? new Post($db->fetch($q)) : null; } - public static function getPostsById(array $ids, bool $flat = false): array { + static function getPostsById(array $ids, bool $flat = false): array { if (empty($ids)) { return []; } - $db = getDb(); + $db = DB(); $posts = array_fill_keys($ids, null); $q = $db->query("SELECT * FROM posts WHERE id IN(".implode(',', $ids).")"); @@ -148,44 +318,4 @@ class posts { return $posts; } - public static function getAllTags(bool $include_hidden = false): array { - $db = getDb(); - $field = $include_hidden ? 'posts_count' : 'visible_posts_count'; - $q = $db->query("SELECT * FROM tags WHERE $field > 0 ORDER BY $field DESC, tag"); - return array_map('Tag::create_instance', $db->fetchAll($q)); - } - - public static function getTag(string $tag): ?Tag { - $db = getDb(); - $q = $db->query("SELECT * FROM tags WHERE tag=?", $tag); - return $db->numRows($q) ? new Tag($db->fetch($q)) : null; - } - - /** - * @param int $tag_id - */ - public static function recountPostsWithTag($tag_id) { - $db = getDb(); - $count = $db->result($db->query("SELECT COUNT(*) FROM posts_tags WHERE tag_id=?", $tag_id)); - $vis_count = $db->result($db->query("SELECT COUNT(*) FROM posts_tags - LEFT JOIN posts ON posts.id=posts_tags.post_id - WHERE posts_tags.tag_id=? AND posts.visible=1", $tag_id)); - $db->query("UPDATE tags SET posts_count=?, visible_posts_count=? WHERE id=?", - $count, $vis_count, $tag_id); - } - - public static function splitStringToTags(string $tags): array { - $tags = trim($tags); - if ($tags == '') { - return []; - } - - $tags = preg_split('/,\s+/', $tags); - $tags = array_filter($tags, function($tag) { return trim($tag) != ''; }); - $tags = array_map('trim', $tags); - $tags = array_map('mb_strtolower', $tags); - - return $tags; - } - -} +}
\ No newline at end of file |