From a19117466df0032976cad5b2f2a975d128004dd6 Mon Sep 17 00:00:00 2001 From: Alexander Skvortsov Date: Sun, 23 Aug 2020 20:27:17 -0400 Subject: [PATCH] Start post types page --- docs/extend/post-types.md | 67 +++++++++++++++++++- docs/images/extend/post-types/post-type.png | Bin 0 -> 14648 bytes 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 docs/images/extend/post-types/post-type.png diff --git a/docs/extend/post-types.md b/docs/extend/post-types.md index 2126282d8..1a4d6747a 100644 --- a/docs/extend/post-types.md +++ b/docs/extend/post-types.md @@ -1 +1,66 @@ -# Post Types \ No newline at end of file +# Custom Post Types + +In addition to regular "comment posts", Flarum uses the post system to display meta information about discussions, such as when discussions are renamed, or are moved from one tag to the other. The only post type available by default is the "Discussion Renamed" event post. + +![Discussion Renamed Event Post](../images/extend/post-types/post-type.png) + +To create a custom event post type, you must register it in both the backend and the frontend. + +## Backend + +Just like regular comment posts, custom post types are stored in, and retrieved from, the database. This means that we will need: + +- A database representation of the custom post type +- An Eloquent model to represent the custom post type. +- Logic (perhaps tied to an event handler or command bus handler) to create and save an instance of this model. + +### How It Works + +By default, event posts are stored in the `posts` database table, alongside regular comment posts. This means that event posts will naturally be included alongside data retrieved from the list posts API endpoint. However, since the content of event posts isn't a block of formatted text, but rather some other data used to represent an event, we use the `content` column to store a serialized version of that data. + +For instance, when a discussion is renamed, we want to store the old title and the new title, so that we can display: + +`USERNAME changed the title to NEW_NAME`, or `USERNAME changed the title from OLD_NAME to NEW_NAME` + +::: tip Think Ahead! +When trying to decide what to save and what not to save in the database, keep in mind that you won't be able to go back in time, and get more than you saved. If you might want to display it later, it might be worth saving it now. +::: + +If we look at the relevant code in the `Flarum\Post\DiscussionRenamedPost`, we see exactly this: + +```php +public static function reply($discussionId, $userId, $oldTitle, $newTitle) +{ + $post = new static; + + $post->content = static::buildContent($oldTitle, $newTitle); + $post->created_at = Carbon::now(); + $post->discussion_id = $discussionId; + $post->user_id = $userId; + + return $post; +} + +/** + * Build the content attribute. + * + * @param string $oldTitle The old title of the discussion. + * @param string $newTitle The new title of the discussion. + * @return array + */ +protected static function buildContent($oldTitle, $newTitle) +{ + return [$oldTitle, $newTitle]; +} +``` + +::: tip Use Existing Fields +Notice that in the example above, we don't save the username in content, but it's still shown in the screenshot. How is this possible? + +Since the 'posts' table has a User ID column, we can use that to link event posts with the users that triggered them. Furthermore, using a foreign key relationship here helps us tie the change to the user more closely. +::: + + +## Create Your Own + +Coming Soon! diff --git a/docs/images/extend/post-types/post-type.png b/docs/images/extend/post-types/post-type.png new file mode 100644 index 0000000000000000000000000000000000000000..2b548b03eebdde8c18729a84efb3621ca619c862 GIT binary patch literal 14648 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 literal 0 HcmV?d00001