diff options
| author | winter | 2025-02-14 17:56:45 +0000 |
|---|---|---|
| committer | winter | 2025-02-14 17:56:58 +0000 |
| commit | 45ac20c7a4d632bbb23aaba50c2d79ac5ebac465 (patch) | |
| tree | eb72692648bdf6c6e78d0334d96342dc79ce728d /Digitigrade/Model | |
| parent | 42e38069e28f84af921b4ea877dc84b4de02c3fe (diff) | |
implement formatted note contents (html and commonmark)
Diffstat (limited to 'Digitigrade/Model')
| -rw-r--r-- | Digitigrade/Model/Note.php | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/Digitigrade/Model/Note.php b/Digitigrade/Model/Note.php index a4df99d..d5d4e69 100644 --- a/Digitigrade/Model/Note.php +++ b/Digitigrade/Model/Note.php @@ -2,6 +2,8 @@ namespace Digitigrade\Model; use Digitigrade\Db; +use Digitigrade\FormattingProvider\CommonMark; +use Digitigrade\FormattingProvider\SanitisedHtml; use Digitigrade\Model\HomeTimelineItem; use Digitigrade\Notification\Notifyable; use Digitigrade\Timeline\TimelineIncludeable; @@ -91,6 +93,7 @@ class Note extends PushableModel implements TimelineIncludeable, Notifyable { $this->saveMentions(); $this->saveAttachments(); $this->saveExtensions(); + $this->saveFormattedContents(); } protected function validate(): bool { @@ -102,7 +105,11 @@ class Note extends PushableModel implements TimelineIncludeable, Notifyable { $pdo = Db::getInstance()->getPdo(); $stmt = $pdo->prepare('SELECT mimetype, body FROM note_formatted_content WHERE note_id = ?'); $stmt->execute([$this->id]); - return $stmt->fetchAll(\PDO::FETCH_ASSOC); + $rows = $stmt->fetchAll(); + return array_combine( + array_map(fn($row) => $row['mimetype'], $rows), + array_map(fn($row) => $row['body'], $rows) + ); } private function findMentions(): array { @@ -126,6 +133,17 @@ class Note extends PushableModel implements TimelineIncludeable, Notifyable { return $items; } + private function saveFormattedContents() { + $pdo = Db::getInstance()->getPdo(); + foreach ($this->formattedContent as $mimetype => $body) { + $stmt = $pdo->prepare( + 'INSERT INTO note_formatted_content(note_id, mimetype, body) VALUES (?, ?, ?)' . + 'ON CONFLICT (note_id, mimetype) DO UPDATE SET body = EXCLUDED.body' + ); + $stmt->execute([$this->id, $mimetype, $body]); + } + } + private function saveMentions() { $pdo = Db::getInstance()->getPdo(); foreach ($this->mentions as $mention) { @@ -230,7 +248,21 @@ class Note extends PushableModel implements TimelineIncludeable, Notifyable { * @return ?string the marked up content */ public function getFormattedContent(string $mimetype): ?string { - return array_filter($this->formattedContent, fn($item) => $item['mimetype'] == $mimetype)[0]['body'] ?? null; + return $this->formattedContent[$mimetype] ?? null; + } + + /** + * Gets the best available formatted content (or plain if there aren't any) + * and converts it to sanitised HTML + * @return string HTML that is hopefully safe to include directly + */ + public function getBestContentAsHtml(): string { + if (isset($this->formattedContent['text/html'])) { + return SanitisedHtml::getInstance()->renderToHtml($this->formattedContent['text/html']); + } elseif (isset($this->formattedContent['text/markdown'])) { + return CommonMark::getInstance()->renderToHtml($this->formattedContent['text/markdown']); + } + return htmlspecialchars($this->plainContent); } public function renderAsHtml() { |
