diff --git a/amd/build/activityhelp.min.js.map b/amd/build/activityhelp.min.js.map
index 7bae1c7cab..d7235c4241 100644
--- a/amd/build/activityhelp.min.js.map
+++ b/amd/build/activityhelp.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"activityhelp.min.js","sources":["../src/activityhelp.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Show a help string for the amount of activity column in userstats_table.php\n *\n * @module     mod_moodleoverflow/activityhelp\n * @copyright  2023 Tamaro Walter\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\n\nconst Selectors = {\n    actions: {\n        showHelpIcon: '[data-action=\"showhelpicon\"]',\n    },\n};\n\n/**\n * Function that shows the help string.\n */\nexport const init = () => {\n    document.addEventListener('click', event => {\n        if (event.target.closest(Selectors.actions.showHelpIcon)) {\n            event.preventDefault();\n        }\n    });\n};"],"names":["Selectors","showHelpIcon","document","addEventListener","event","target","closest","preventDefault"],"mappings":";;;;;;;;IAyBMA,kBACO,CACLC,aAAc,8CAOF,WAChBC,SAASC,iBAAiB,SAAS,SAAAC,OAC3BA,MAAMC,OAAOC,QAAQN,kBAAkBC,eACvCG,MAAMG"}
\ No newline at end of file
+{"version":3,"file":"activityhelp.min.js","sources":["../src/activityhelp.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Show a help string for the amount of activity column in userstats_table.php\n *\n * @module     mod_moodleoverflow/activityhelp\n * @copyright  2023 Tamaro Walter\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\n\nconst Selectors = {\n    actions: {\n        showHelpIcon: '[data-action=\"showhelpicon\"]',\n    },\n};\n\n/**\n * Function that shows the help icon string.\n */\nexport const init = () => {\n    document.addEventListener('click', event => {\n        if (event.target.closest(Selectors.actions.showHelpIcon)) {\n            event.preventDefault();\n        }\n    });\n};"],"names":["Selectors","showHelpIcon","document","addEventListener","event","target","closest","preventDefault"],"mappings":";;;;;;;;IAyBMA,kBACO,CACLC,aAAc,8CAOF,WAChBC,SAASC,iBAAiB,SAAS,SAAAC,OAC3BA,MAAMC,OAAOC,QAAQN,kBAAkBC,eACvCG,MAAMG"}
\ No newline at end of file
diff --git a/amd/src/activityhelp.js b/amd/src/activityhelp.js
index 601b6ad243..dc4127b6f2 100644
--- a/amd/src/activityhelp.js
+++ b/amd/src/activityhelp.js
@@ -30,7 +30,7 @@ const Selectors = {
 };
 
 /**
- * Function that shows the help string.
+ * Function that shows the help icon string.
  */
 export const init = () => {
     document.addEventListener('click', event => {
diff --git a/amd/src/rating.js b/amd/src/rating.js
index 0f44f3ba77..f1cce7a268 100644
--- a/amd/src/rating.js
+++ b/amd/src/rating.js
@@ -149,7 +149,7 @@ export function init(userid, allowmultiplemarks) {
 
 /**
  * Function to change the String of the post data-action button.
- * Only used if mulitplemarks are allowed.
+ * Only used if multiplemarks are allowed.
  * @param {string} htmlclass the class where the String is being updated
  * @param {string} action    helpful or solved mark
  */
diff --git a/classes/discussion/discussion.php b/classes/discussion/discussion.php
new file mode 100644
index 0000000000..bdc887eeac
--- /dev/null
+++ b/classes/discussion/discussion.php
@@ -0,0 +1,624 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class for working with posts
+ *
+ * @package     mod_moodleoverflow
+ * @copyright   2023 Tamaro Walter
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_moodleoverflow\discussion;
+
+
+// Import namespace from the locallib, needs a check later which namespaces are really needed.
+use mod_moodleoverflow\anonymous;
+
+// Important namespaces.
+use mod_moodleoverflow\readtracking;
+use mod_moodleoverflow\review;
+use mod_moodleoverflow\post\post;
+use mod_moodleoverflow\capabilities;
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/mod/moodleoverflow/locallib.php');
+
+/**
+ * Class that represents a discussion. A discussion administrates the posts and has one parent post, that started the discussion.
+ *
+ * @package     mod_moodleoverflow
+ * @copyright   2023 Tamaro Walter
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ *
+ * Please be careful with functions that delete, add or edit posts and discussions.
+ * Security checks for these functions were done in the post_control class and these functions should only be accessed that way.
+ * Accessing these functions directly without the checks from the post control could lead to serious errors.
+ */
+class discussion {
+
+    /** @var int The discussion ID */
+    private $id;
+
+    /** @var int The course ID where the discussion is located */
+    private $course;
+
+    /** @var int The moodleoverflow ID where the discussion is located*/
+    private $moodleoverflow;
+
+    /** @var string The title of the discussion, the titel of the parent post*/
+    public $name;
+
+    /** @var int The id of the parent/first post*/
+    private $firstpost;
+
+    /** @var int The user ID who started the discussion */
+    private $userid;
+
+    /** @var int Unix-timestamp of modification */
+    public $timemodified;
+
+    /** @var int Unix-timestamp of discussion creation */
+    public $timestart;
+
+    /** @var int the user ID who modified the discussion */
+    public $usermodified;
+
+    // Not Database-related attributes.
+
+    /** @var array an Array of posts that belong to this discussion */
+    public $posts;
+
+    /** @var bool  a variable for checking if this instance has all its posts */
+    public $postsbuild;
+
+    /** @var object The moodleoverflow object where the discussion is located */
+    public $moodleoverflowobject;
+
+    /** @var object The course module object */
+    public $cmobject;
+
+    // Constructors and other builders.
+
+    /**
+     * Constructor to build a new discussion.
+     * @param int   $id                 The Discussion ID.
+     * @param int   $course             The course ID.
+     * @param int   $moodleoverflow     The moodleoverflow ID.
+     * @param char  $name               Discussion Title.
+     * @param int   $firstpost          .
+     * @param int   $userid  The course ID.
+     * @param int   $timemodified   The course ID.
+     * @param int   $timestart   The course ID.
+     * @param int   $usermodified   The course ID.
+     */
+    public function __construct($id, $course, $moodleoverflow, $name, $firstpost,
+                                $userid, $timemodified, $timestart, $usermodified) {
+        $this->id = $id;
+        $this->course = $course;
+        $this->moodleoverflow = $moodleoverflow;
+        $this->name = $name;
+        $this->firstpost = $firstpost;
+        $this->userid = $userid;
+        $this->timemodified = $timemodified;
+        $this->timestart = $timestart;
+        $this->usermodified = $usermodified;
+        $this->posts = [];
+        $this->postsbuild = false;
+    }
+
+    /**
+     * Builds a Discussion from a DB record.
+     *
+     * @param object   $record Data object.
+     * @return object discussion instance
+     */
+    public static function from_record($record) {
+        $id = null;
+        if (object_property_exists($record, 'id') && $record->id) {
+            $id = $record->id;
+        }
+
+        $course = 0;
+        if (object_property_exists($record, 'course') && $record->course) {
+            $course = $record->course;
+        }
+
+        $moodleoverflow = 0;
+        if (object_property_exists($record, 'moodleoverflow') && $record->moodleoverflow) {
+            $moodleoverflow = $record->moodleoverflow;
+        }
+
+        $name = '';
+        if (object_property_exists($record, 'name') && $record->name) {
+            $name = $record->name;
+        }
+
+        $firstpost = 0;
+        if (object_property_exists($record, 'firstpost') && $record->firstpost) {
+            $firstpost = $record->firstpost;
+        }
+
+        $userid = 0;
+        if (object_property_exists($record, 'userid') && $record->userid) {
+            $userid = $record->userid;
+        }
+
+        $timemodified = 0;
+        if (object_property_exists($record, 'timemodified') && $record->timemodified) {
+            $timemodified = $record->timemodified;
+        }
+
+        $timestart = 0;
+        if (object_property_exists($record, 'timestart') && $record->timestart) {
+            $timestart = $record->timestart;
+        }
+
+        $usermodified = 0;
+        if (object_property_exists($record, 'usermodified') && $record->usermodified) {
+            $usermodified = $record->usermodified;
+        }
+
+        $instance = new self($id, $course, $moodleoverflow, $name, $firstpost, $userid, $timemodified, $timestart, $usermodified);
+
+        // Get all the posts so that the instance can work with it.
+        $instance->moodleoverflow_get_discussion_posts();
+
+        return $instance;
+    }
+
+    /**
+     * Function to build a new discussion without specifying the Discussion ID.
+     * @param int   $course             The course ID.
+     * @param int   $moodleoverflow     The moodleoverflow ID.
+     * @param char  $name               Discussion Title.
+     * @param int   $firstpost          .
+     * @param int   $userid  The course ID.
+     * @param int   $timemodified   The course ID.
+     * @param int   $timestart   The course ID.
+     * @param int   $usermodified   The course ID.
+     *
+     * @return object discussion object without id.
+     */
+    public static function construct_without_id($course, $moodleoverflow, $name, $firstpost,
+                                       $userid, $timemodified, $timestart, $usermodified) {
+        $id = null;
+        $instance = new self($id, $course, $moodleoverflow, $name, $firstpost, $userid, $timemodified, $timestart, $usermodified);
+        return $instance;
+    }
+
+    // Discussion Functions.
+
+    /**
+     * Adds a new Discussion with a post.
+     *
+     * @param object $prepost The prepost object from the post_control. Has information about the post and other important stuff.
+     */
+    public function moodleoverflow_add_discussion($prepost) {
+        global $DB;
+
+        // Add the discussion to the Database.
+        $this->id = $DB->insert_record('moodleoverflow_discussions', $this->build_db_object());
+
+        // Create the first/parent post for the new discussion and add it do the DB.
+        $post = post::construct_without_id($this->id, 0, $prepost->userid, $prepost->timenow, $prepost->timenow, $prepost->message,
+                                           $prepost->messageformat, "", 0, $prepost->reviewed, null, $prepost->formattachments);
+        // Add it to the DB and save the id of the first/parent post.
+        $this->firstpost = $post->moodleoverflow_add_new_post();
+
+        // Save the id of the first/parent post in the DB.
+        $DB->set_field('moodleoverflow_discussions', 'firstpost', $this->firstpost, ['id' => $this->id]);
+
+        // Add the parent post to the $posts array.
+        $this->posts[$this->firstpost] = $post;
+        $this->postsbuild = true;
+
+        // Trigger event.
+        $params = [
+            'context' => $prepost->modulecontext,
+            'objectid' => $this->id,
+        ];
+        // TODO: check if the event functions.
+        $event = \mod_moodleoverflow\event\discussion_viewed::create($params);
+        $event->trigger();
+
+        // Return the id of the discussion.
+        return $this->id;
+    }
+
+    /**
+     * Delete a discussion with all of it's posts
+     * @param object $prepost Information about the post from the post_control
+     * @return bool Wether deletion was successful of not
+     */
+    public function moodleoverflow_delete_discussion($prepost) {
+        global $DB;
+        $this->existence_check();
+        $this->posts_check();
+
+        // Delete a discussion with all of it's posts.
+        // In case something does not work we throw the error as it should be known that something went ... terribly wrong.
+        // All DB transactions are rolled back.
+        try {
+            $transaction = $DB->start_delegated_transaction();
+
+            // Delete every post of this discussion.
+            foreach ($this->posts as $post) {
+                $post->moodleoverflow_delete_post(false);
+            }
+
+            // Delete the read-records for the discussion.
+            readtracking::moodleoverflow_delete_read_records(-1, -1, $this->id);
+
+            // Remove the subscriptions for the discussion.
+            $DB->delete_records('moodleoverflow_discuss_subs', ['discussion' => $this->id]);
+
+            // Delete the discussion from the database.
+            $DB->delete_records('moodleoverflow_discussions', ['id' => $this->id]);
+
+            // Trigger the discussion deleted event.
+            $params = [
+                'objectid' => $this->id,
+                'context' => $prepost->modulecontext,
+            ];
+
+            $event = \mod_moodleoverflow\event\discussion_deleted::create($params);
+            $event->trigger();
+
+            // Set the id of this instance to null, so that working with it is not possible anymore.
+            $this->id = null;
+
+            // The discussion has been deleted.
+            $transaction->allow_commit();
+            return true;
+
+        } catch (Exception $e) {
+            $transaction->rollback($e);
+        }
+
+        // Deleting the discussion has failed.
+        return false;
+    }
+
+    /**
+     * Adds a new post to this discussion and the DB.
+     *
+     * @param object $prepost The prepost object from the post_control. Has Information about the post and other important stuff.
+     */
+    public function moodleoverflow_add_post_to_discussion($prepost) {
+        global $DB;
+        $this->existence_check();
+        $this->posts_check();
+
+        // Create the post that will be added to the new discussion.
+        $post = post::construct_without_id($this->id, $prepost->parentid, $prepost->userid, $prepost->timenow, $prepost->timenow,
+                                           $prepost->message, $prepost->messageformat, "", 0, $prepost->reviewed, null,
+                                           $prepost->formattachments);
+        // Add the post to the DB.
+        $postid = $post->moodleoverflow_add_new_post();
+
+        // Add the post to the $posts array and update the timemodified in the DB.
+        $this->posts[$postid] = $post;
+        $this->timemodified = $prepost->timenow;
+        $this->usermodified = $prepost->userid;
+        $DB->update_record('moodleoverflow_discussions', $this->build_db_object());
+
+        // Return the id of the added post.
+        return $postid;
+    }
+
+    /**
+     * Deletes a post that is in this discussion from the DB.
+     * @param object $prepost The prepost object from the post_control. Has Information about the post and other important stuff.
+     * @return bool Wether the deletion was possible
+     * @throws moodle_exception if post is not in this discussion or something failed.
+     */
+    public function moodleoverflow_delete_post_from_discussion($prepost) {
+        $this->existence_check();
+        $this->posts_check();
+
+        // Check if the posts exists in this discussion.
+        $this->post_exists_check($prepost->postid);
+
+        // Access the post and delete it.
+        $post = $this->posts[$prepost->postid];
+        if (!$post->moodleoverflow_delete_post($prepost->deletechildren)) {
+            // Deletion failed.
+            return false;
+        }
+
+        // Check for the new last post of the discussion.
+        $this->moodleoverflow_discussion_adapt_to_last_post();
+
+        // Delete the post from the post array.
+        unset($this->posts[$prepost->postid]);
+
+        return true;
+    }
+
+    /**
+     * Edits the message of a post from this discussion.
+     * @param object $prepost The prepost object from the post_control. Has Information about the post and other important stuff.
+     */
+    public function moodleoverflow_edit_post_from_discussion($prepost) {
+        global $DB;
+        $this->existence_check();
+        $this->posts_check();
+
+        // Check if the posts exists in this discussion.
+        $this->post_exists_check($prepost->postid);
+
+        // Access the post.
+        $post = $this->posts[$prepost->postid];
+
+        // If the post is the firstpost, then update the name of this discussion and the post. If not, only update the post.
+        if ($prepost->postid == array_key_first($this->posts)) {
+            $this->name = $prepost->subject;
+            $this->usermodified = $prepost->userid;
+            $this->timemodified = $prepost->timenow;
+            $DB->update_record('moodleoverflow_discussions', $this->build_db_object());
+        }
+        $post->moodleoverflow_edit_post($prepost->timenow, $prepost->message, $prepost->messageformat, $prepost->formattachments);
+
+        // The post has been edited successfully.
+        return true;
+    }
+
+    /**
+     * This Function checks, what the last added or edited post is. If it changed by a delete function,
+     * the timemodified and the usermodified need to be adapted to the last added or edited post.
+     *
+     * @return bool true if the DB needed to be adapted. false if it didn't change.
+     */
+    public function moodleoverflow_discussion_adapt_to_last_post() {
+        global $DB;
+        $this->existence_check();
+
+        // Find the last reviewed post of the discussion (even if the user has review capability, because it's written to DB).
+        $sql = 'SELECT *
+                FROM {moodleoverflow_posts}
+                WHERE discussion = ' . $this->id .
+                  ' AND reviewed = 1
+                    AND modified = (SELECT MAX(modified) as modified
+                                    FROM {moodleoverflow_posts}
+                                    WHERE discussion = ' . $this->id . ');';
+        $record = $DB->get_record_sql($sql);
+        $lastpost = post::from_record($record);
+
+        // Check if the last post changed. If it changed, then update the DB-record of this discussion.
+        if ($lastpost->modified != $this->timemodified || $lastpost->get_userid() != $this->usermodified) {
+            $this->timemodified = $lastpost->modified;
+            $this->usermodified = $lastpost->get_userid();
+            $DB->update_record('moodleoverflow_discussions', $this->build_db_object());
+
+            // Return that the discussion needed an update.
+            return true;
+        }
+
+        // Return that the discussion didn't need an update.
+        return false;
+    }
+
+    // Getter.
+
+    /**
+     * Getter for the post ID
+     * @return int $this->id    The post ID.
+     */
+    public function get_id() {
+        $this->existence_check();
+        return $this->id;
+    }
+
+    /**
+     * Getter for the courseid
+     * @return int $this->course    The ID of the course where the discussion is located.
+     */
+    public function get_courseid() {
+        $this->existence_check();
+        return $this->course;
+    }
+
+    /**
+     * Getter for the moodleoverflowid
+     * @return int $this->moodleoverflow    The ID of the moodleoverflow where the discussion is located.
+     */
+    public function get_moodleoverflowid() {
+        $this->existence_check();
+        return $this->moodleoverflow;
+    }
+
+    /**
+     * Getter for the firstpostid
+     * @return int $this->firstpost   The ID of the first post.
+     */
+    public function get_firstpostid() {
+        $this->existence_check();
+        return $this->firstpost;
+    }
+
+    /**
+     * Getter for the userid
+     * @return int $this->userid    The ID of the user who wrote the first post.
+     */
+    public function get_userid() {
+        $this->existence_check();
+        return $this->userid;
+    }
+
+    /**
+     * Returns the ratings from this discussion.
+     * @return array of votings
+     */
+    public function moodleoverflow_get_discussion_ratings() {
+        $this->existence_check();
+        $this->posts_check();
+
+        $discussionratings = \mod_moodleoverflow\ratings::moodleoverflow_get_ratings_by_discussion($this->id);
+        return $discussionratings;
+    }
+
+    /**
+     * Get all posts from this Discussion.
+     * The first/parent post is on the first position in the array.
+     *
+     * @return array $posts     Array ob posts objects
+     */
+    public function moodleoverflow_get_discussion_posts() {
+        global $DB;
+        $this->existence_check();
+
+        // Check if the posts array are build yet. If not, build it.
+        if (!$this->postsbuild) {
+            // Get the posts from the DB. Get the parent post first.
+            $firstpostsql = 'SELECT * FROM {moodleoverflow_posts} posts
+                            WHERE discussion = ' . $this->id . ' AND parent = 0;';
+            $otherpostssql = 'SELECT * FROM {moodleoverflow_posts} posts
+                            WHERE discussion = ' . $this->id . ' AND parent != 0;';
+            $firstpostrecord = $DB->get_record_sql($firstpostsql);
+            $otherpostsrecord = $DB->get_records_sql($otherpostssql);
+
+            // Add the first/parent post to the array, then add the other posts.
+            $firstpost = post::from_record($firstpostrecord);
+            $this->posts[$firstpost->get_id()] = $firstpost;
+
+            foreach ($otherpostsrecord as $postrecord) {
+                $post = post::from_record($postrecord);
+                $this->posts[$post->get_id()] = $post;
+            }
+
+            // Now the posts are built.
+            $this->postsbuild = true;
+        }
+
+        // Return the posts array.
+        return $this->posts;
+    }
+
+
+    /**
+     * Returns the moodleoverflowobject
+     *
+     * @return object $moodleoverflowobject
+     */
+    public function get_moodleoverflow() {
+        global $DB;
+        $this->existence_check();
+
+        if (empty($this->moodleoverflowobject)) {
+            $this->moodleoverflowobject = $DB->get_records('moodleoverflow', ['id' => $this->moodleoverflow]);
+        }
+
+        return $this->moodleoverflowobject;
+    }
+
+    /**
+     * Returns the coursemodule
+     *
+     * @return object $cmobject
+     */
+    public function get_coursemodule() {
+        global $DB;
+        $this->existence_check();
+
+        if (empty($this->cmobject)) {
+            if (!$this->cmobject = $DB->get_coursemodule_from_instance('moodleoverflow', $this->get_moodleoverflow()->id,
+                                                                                         $this->get_moodleoverflow()->course)) {
+                throw new \moodle_exception('invalidcoursemodule');
+            }
+        }
+
+        return $this->cmobject;
+    }
+
+    /**
+     * This getter works as an help function in case another file/function needs the db-object of this instance (as the function
+     * is not adapted/refactored to the new way of working with discussion).
+     * @return object
+     */
+    public function get_db_object() {
+        $this->existence_check();
+        return $this->build_db_object();
+    }
+
+    // Helper functions.
+
+    /**
+     * Builds an object from this instance that has only DB-relevant attributes.
+     * As this is an private function, it doesn't need an existence check.
+     * @return object $dbobject
+     */
+    private function build_db_object() {
+        $dbobject = new \stdClass();
+        $dbobject->id = $this->id;
+        $dbobject->course = $this->course;
+        $dbobject->moodleoverflow = $this->moodleoverflow;
+        $dbobject->name = $this->name;
+        $dbobject->firstpost = $this->firstpost;
+        $dbobject->userid = $this->userid;
+        $dbobject->timemodified = $this->timemodified;
+        $dbobject->timestart = $this->timestart;
+        $dbobject->usermodified = $this->usermodified;
+
+        return $dbobject;
+    }
+
+    // Security.
+
+    /**
+     * Makes sure that the instance exists in the database. Every function in this class requires this check
+     * (except the function that adds the discussion to the database)
+     *
+     * @return true
+     * @throws moodle_exception
+     */
+    private function existence_check() {
+        if (empty($this->id) || $this->id == false || $this->id == null) {
+            throw new \moodle_exception('noexistingdiscussion', 'moodleoverflow');
+        }
+        return true;
+    }
+
+    /**
+     * Makes sure that the instance knows all of its posts (That all posts of the db are in the local array).
+     * Not all functions need this check.
+     * @return true
+     * @throws moodle_exception
+     */
+    private function posts_check() {
+        if (!$this->postsbuild) {
+            throw new \moodle_exception('notallpostsavailable', 'moodleoverflow');
+        }
+        return true;
+    }
+
+    /**
+     * Check, if certain posts really exists in this discussion.
+     *
+     * @param int $postid   The ID of the post that is being checked.
+     * @return true
+     * @throws moodle_exception;
+     */
+    private function post_exists_check($postid) {
+        if (!$this->posts[$postid]) {
+            throw new \moodle_exception('postnotpartofdiscussion', 'moodleoverflow');
+        }
+
+        return true;
+    }
+}
diff --git a/classes/output/moodleoverflow_email.php b/classes/output/moodleoverflow_email.php
index 10d57c2797..47f2651b9f 100644
--- a/classes/output/moodleoverflow_email.php
+++ b/classes/output/moodleoverflow_email.php
@@ -188,7 +188,7 @@ protected function export_for_template_text(\mod_moodleoverflow_renderer $render
      *
      * @param \mod_moodleoverflow_renderer $renderer The render to be used for formatting the message and attachments
      *
-     * @return stdClass Data ready for use in a mustache template
+     * @return array Data ready for use in a mustache template
      */
     protected function export_for_template_html(\mod_moodleoverflow_renderer $renderer) {
         return [
diff --git a/classes/post/post.php b/classes/post/post.php
new file mode 100644
index 0000000000..b054a55595
--- /dev/null
+++ b/classes/post/post.php
@@ -0,0 +1,717 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class for working with posts
+ *
+ * @package     mod_moodleoverflow
+ * @copyright   2023 Tamaro Walter
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+namespace mod_moodleoverflow\post;
+
+// Import namespace from the locallib, needs a check later which namespaces are really needed.
+use mod_moodleoverflow\anonymous;
+use mod_moodleoverflow\capabilities;
+use mod_moodleoverflow\review;
+use mod_moodleoverflow\readtracking;
+use mod_moodleoverflow\discussion\discussion;
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/mod/moodleoverflow/locallib.php');
+
+/**
+ * Class that represents a post.
+ *
+ * Please be careful with functions that delete, add or edit posts.
+ * Security checks for these functions were done in the post_control class and these functions should only be accessed that way.
+ * Accessing these functions directly without the checks from the post_control could lead to serious errors.
+ *
+ * Most of the functions in this class are called by moodleoverflow/classes/discussion/discussion.php . The discussion class
+ * manages posts in a moodleoverflow and works like a toplevel class for the post class. If you want to manipulate
+ * (delete, add, edit) posts, please call the functions from the discussion class. To read and obtain information about posts
+ * you are free to choose.
+ *
+ * @package   mod_moodleoverflow
+ * @copyright 2023 Tamaro Walter
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class post {
+
+    // Attributes. The most important attributes are private and can only be changed by internal functions.
+    // Other attributes can be accessed directly.
+
+    /** @var int The post ID */
+    private $id;
+
+    /** @var int The corresponding discussion ID */
+    private $discussion;
+
+    /** @var int The parent post ID */
+    private $parent;
+
+    /** @var int The ID of the User who wrote the post */
+    private $userid;
+
+    /** @var int Creation timestamp */
+    public $created;
+
+    /** @var int Modification timestamp */
+    public $modified;
+
+    /** @var string The message (content) of the post */
+    public $message;
+
+    /** @var int  The message format*/
+    public $messageformat;
+
+    /** @var string Attachment of the post */
+    public $attachment;
+
+    /** @var int Mailed status*/
+    public $mailed;
+
+    /** @var int Review status */
+    public $reviewed;
+
+    /** @var int The time where the post was reviewed*/
+    public $timereviewed;
+
+    // Not database related functions.
+
+    /** @var int This variable is optional, it contains important information for the add_attachment function */
+    public $formattachments;
+
+    /** @var string The subject/title of the Discussion */
+    public $subject;
+
+    /** @var object The discussion where the post is located */
+    public $discussionobject;
+
+    /** @var object The Moodleoverflow where the post is located*/
+    public $moodleoverflowobject;
+
+    /** @var object The course module object */
+    public $cmobject;
+
+    /** @var object The parent post of an answerpost */
+    public $parentpost;
+
+    // Constructors and other builders.
+
+    /**
+     * Constructor to make a new post.
+     * @param int       $id                 The post ID.
+     * @param int       $discussion         The discussion ID.
+     * @param int       $parent             The parent post ID.
+     * @param int       $userid             The user ID that created the post.
+     * @param int       $created            Creation timestamp
+     * @param int       $modified           Modification timestamp
+     * @param string    $message            The message (content) of the post
+     * @param int       $messageformat      The message format
+     * @param char      $attachment         Attachment of the post
+     * @param int       $mailed             Mailed status
+     * @param int       $reviewed           Review status
+     * @param int       $timereviewed       The time where the post was reviewed
+     * @param object    $formattachments    Information about attachments of the post_form
+     */
+    public function __construct($id, $discussion, $parent, $userid, $created, $modified, $message,
+                                $messageformat, $attachment, $mailed, $reviewed, $timereviewed, $formattachments = false) {
+        $this->id = $id;
+        $this->discussion = $discussion;
+        $this->parent = $parent;
+        $this->userid = $userid;
+        $this->created = $created;
+        $this->modified = $modified;
+        $this->message = $message;
+        $this->messageformat = $messageformat;
+        $this->attachment = $attachment;
+        $this->mailed = $mailed;
+        $this->reviewed = $reviewed;
+        $this->timereviewed = $timereviewed;
+        $this->formattachments = $formattachments;
+    }
+
+    /**
+     * Builds a Post from a DB record.
+     * Look up database structure for standard values.
+     * @param object  $record Data object.
+     * @return object post instance
+     */
+    public static function from_record($record) {
+        $id = null;
+        if (object_property_exists($record, 'id') && $record->id) {
+            $id = $record->id;
+        }
+
+        $discussion = 0;
+        if (object_property_exists($record, 'discussion') && $record->discussion) {
+            $discussion = $record->discussion;
+        }
+
+        $parent = 0;
+        if (object_property_exists($record, 'parent') && $record->parent) {
+            $parent = $record->parent;
+        }
+
+        $userid = 0;
+        if (object_property_exists($record, 'userid') && $record->userid) {
+            $userid = $record->userid;
+        }
+
+        $created = 0;
+        if (object_property_exists($record, 'created') && $record->created) {
+            $created = $record->created;
+        }
+
+        $modified = 0;
+        if (object_property_exists($record, 'modified') && $record->modified) {
+            $modified = $record->modified;
+        }
+
+        $message = '';
+        if (object_property_exists($record, 'message') && $record->message) {
+            $message = $record->message;
+        }
+
+        $messageformat = 0;
+        if (object_property_exists($record, 'messageformat') && $record->messageformat) {
+            $messageformat = $record->messageformat;
+        }
+
+        $attachment = '';
+        if (object_property_exists($record, 'attachment') && $record->attachment) {
+            $attachment = $record->attachment;
+        }
+
+        $mailed = 0;
+        if (object_property_exists($record, 'mailed') && $record->mailed) {
+            $mailed = $record->mailed;
+        }
+
+        $reviewed = 1;
+        if (object_property_exists($record, 'reviewed') && $record->reviewed) {
+            $reviewed = $record->reviewed;
+        }
+
+        $timereviewed = null;
+        if (object_property_exists($record, 'timereviewed') && $record->timereviewed) {
+            $timereviewed = $record->timereviewed;
+        }
+
+        return new self($id, $discussion, $parent, $userid, $created, $modified, $message, $messageformat, $attachment, $mailed,
+                        $reviewed, $timereviewed);
+    }
+
+    /**
+     * Function to make a new post without specifying the Post ID.
+     *
+     * @param int       $discussion         The discussion ID.
+     * @param int       $parent             The parent post ID.
+     * @param int       $userid             The user ID that created the post.
+     * @param int       $created            Creation timestamp
+     * @param int       $modified           Modification timestamp
+     * @param string    $message            The message (content) of the post
+     * @param int       $messageformat      The message format
+     * @param char      $attachment         Attachment of the post
+     * @param int       $mailed             Mailed status
+     * @param int       $reviewed           Review status
+     * @param int       $timereviewed       The time where the post was reviewed
+     * @param object    $formattachments    Information about attachments from the post_form
+     *
+     * @return object post object without id
+     */
+    public static function construct_without_id($discussion, $parent, $userid, $created, $modified, $message,
+                                $messageformat, $attachment, $mailed, $reviewed, $timereviewed, $formattachments = false) {
+        $id = null;
+        return new self($id, $discussion, $parent, $userid, $created, $modified, $message, $messageformat, $attachment, $mailed,
+                        $reviewed, $timereviewed, $formattachments);
+    }
+
+    // Post Functions.
+
+    /**
+     * Adds a new post in an existing discussion.
+     * @return bool|int The Id of the post if operation was successful
+     * @throws coding_exception
+     * @throws dml_exception
+     */
+    public function moodleoverflow_add_new_post() {
+        global $USER, $DB;
+
+        // Add post to the database.
+        $this->id = $DB->insert_record('moodleoverflow_posts', $this->build_db_object());
+        $this->moodleoverflow_add_attachment($this, $this->get_moodleoverflow(), $this->get_coursemodule());
+
+        if ($this->reviewed) {
+            // Update the discussion.
+            $DB->set_field('moodleoverflow_discussions', 'timemodified', $this->modified, ['id' => $this->discussion]);
+            $DB->set_field('moodleoverflow_discussions', 'usermodified', $this->userid, ['id' => $this->discussion]);
+        }
+
+        // Mark the created post as read if the user is tracking the discussion.
+        $cantrack = readtracking::moodleoverflow_can_track_moodleoverflows($this->get_moodleoverflow());
+        $istracked = readtracking::moodleoverflow_is_tracked($this->get_moodleoverflow());
+        if ($cantrack && $istracked) {
+            // Please be aware that in future the use of get_db_object() should be replaced with only $this,
+            // as the readtracking class should be refactored with the new way of working with posts.
+            readtracking::moodleoverflow_mark_post_read($this->userid, $this->get_db_object());
+        }
+
+        // Return the id of the created post.
+        return $this->id;
+    }
+
+    /**
+     * Deletes a single moodleoverflow post.
+     *
+     * @param bool  $deletechildren        The child posts
+     *
+     * @return bool Whether the deletion was successful or not
+     */
+    public function moodleoverflow_delete_post($deletechildren) {
+        global $DB, $USER;
+        $this->existence_check();
+
+        // Iterate through all children and delete them.
+        // In case something does not work we throw the error as it should be known that something went ... terribly wrong.
+        // All DB transactions are rolled back.
+        try {
+            $transaction = $DB->start_delegated_transaction();
+
+            // Get the coursemoduleid for later use.
+            $coursemoduleid = $this->get_coursemodule()->id;
+            $childposts = $this->moodleoverflow_get_childposts();
+            if ($deletechildren && $childposts) {
+                foreach ($childposts as $childpost) {
+                    $child = $this->from_record($childpost);
+                    $child->moodleoverflow_delete_post($deletechildren);
+                }
+            }
+
+            // Delete the ratings.
+            $DB->delete_records('moodleoverflow_ratings', ['postid' => $this->id]);
+
+            // Delete the post.
+            if ($DB->delete_records('moodleoverflow_posts', ['id' => $this->id])) {
+                // Delete the read records.
+                readtracking::moodleoverflow_delete_read_records(-1, $this->id);
+
+                // Delete the attachments.
+                $fs = get_file_storage();
+                $context = \context_module::instance($coursemoduleid);
+                $attachments = $fs->get_area_files($context->id, 'mod_moodleoverflow', 'attachment',
+                    $this->id, "filename", true);
+                foreach ($attachments as $attachment) {
+                    // Get file.
+                    $file = $fs->get_file($context->id, 'mod_moodleoverflow', 'attachment', $this->id,
+                        $attachment->get_filepath(), $attachment->get_filename());
+                    // Delete it if it exists.
+                    if ($file) {
+                        $file->delete();
+                    }
+                }
+
+                // Trigger the post deletion event.
+                $params = [
+                    'context' => $context,
+                    'objectid' => $this->id,
+                    'other' => [
+                        'discussionid' => $this->discussion,
+                        'moodleoverflowid' => $this->get_moodleoverflow()->id,
+                    ],
+                ];
+                if ($this->userid !== $USER->id) {
+                    $params['relateduserid'] = $this->userid;
+                }
+                $event = \mod_moodleoverflow\event\post_deleted::create($params);
+                $event->trigger();
+
+                // Set the id of this instance to null, so that working with it is not possible anymore.
+                $this->id = null;
+
+                // The post has been deleted.
+                $transaction->allow_commit();
+                return true;
+            }
+        } catch (Exception $e) {
+            $transaction->rollback($e);
+        }
+
+        // Deleting the post failed.
+        return false;
+    }
+
+    /**
+     * Edits the message from this instance.
+     * @param int       $time               The time the post was modified (given from the discussion class).
+     * @param string    $postmessage        The new message
+     * @param int       $messageformat
+     * @param object    $formattachments    Information about attachments from the post_form
+     *
+     * @return true if the post has been edited successfully
+     */
+    public function moodleoverflow_edit_post($time, $postmessage, $messageformat, $formattachments) {
+        global $DB;
+        $this->existence_check();
+
+        // Update the attributes.
+        $this->modified = $time;
+        $this->message = $postmessage;
+        $this->messageformat = $messageformat;
+        $this->formattachments = $formattachments;
+
+        // Update the record in the database.
+        $DB->update_record('moodleoverflow_posts', $this->build_db_object());
+
+        // Update the attachments. This happens after the DB update call, as this function changes the DB record as well.
+        $this->moodleoverflow_add_attachment();
+
+        // Mark the edited post as read.
+        $this->mark_post_read();
+
+        // The post has been edited successfully.
+        return true;
+    }
+
+    /**
+     * // NOTE: This function replaces the get_post_full() function but is not used until the print and print-related function for
+     * // printing the discussion and a post are adapted to the new post and discussion class.
+     * Gets a post with all info ready for moodleoverflow_print_post.
+     * Most of these joins are just to get the forum id.
+     *
+     * @return mixed array of posts or false
+     */
+    public function moodleoverflow_get_complete_post() {
+        global $DB, $CFG;
+        $this->existence_check();
+
+        if ($CFG->branch >= 311) {
+            $allnames = \core_user\fields::for_name()->get_sql('u', false, '', '', false)->selects;
+        } else {
+            $allnames = implode(', ', fields::get_name_fields());
+        }
+        $sql = "SELECT p.*, d.moodleoverflow, $allnames, u.email, u.picture, u.imagealt
+                FROM {moodleoverflow_posts} p
+                    JOIN {moodleoverflow_discussions} d ON p.discussion = d.id
+                LEFT JOIN {user} u ON p.userid = u.id
+                    WHERE p.id = " . $this->id . " ;";
+
+        $post = $DB->get_records_sql($sql);
+        if ($post->userid == 0) {
+            $post->message = get_string('privacy:anonym_post_message', 'mod_moodleoverflow');
+        }
+        return $post;
+    }
+
+    /**
+     * If successful, this function returns the name of the file
+     *
+     * @return bool
+     */
+    public function moodleoverflow_add_attachment() {
+        global $DB;
+        $this->existence_check();
+
+        if (empty($this->formattachments)) {
+            return true;    // Nothing to do.
+        }
+
+        $context = \context_module::instance($this->get_coursemodule()->id);
+        $info = file_get_draft_area_info($this->formattachments);
+        $present = ($info['filecount'] > 0) ? '1' : '';
+        file_save_draft_area_files($this->formattachments, $context->id, 'mod_moodleoverflow', 'attachment', $this->id,
+                                  \mod_moodleoverflow_post_form::attachment_options($this->get_moodleoverflow()));
+        $DB->set_field('moodleoverflow_posts', 'attachment', $present, ['id' => $this->id]);
+    }
+
+    /**
+     * Returns attachments with information for the template
+     *
+     *
+     * @return array
+     */
+    public function moodleoverflow_get_attachments() {
+        global $CFG, $OUTPUT;
+        $this->existence_check();
+
+        if (empty($this->attachment) || (!$context = \context_module::instance($this->get_coursemodule()->id))) {
+            return [];
+        }
+
+        $attachments = [];
+        $fs = get_file_storage();
+
+        // We retrieve all files according to the time that they were created.  In the case that several files were uploaded
+        // at the sametime (e.g. in the case of drag/drop upload) we revert to using the filename.
+        $files = $fs->get_area_files($context->id, 'mod_moodleoverflow', 'attachment', $this->id, "filename", false);
+        if ($files) {
+            $i = 0;
+            foreach ($files as $file) {
+                $attachments[$i] = [];
+                $attachments[$i]['filename'] = $file->get_filename();
+                $mimetype = $file->get_mimetype();
+                $iconimage = $OUTPUT->pix_icon(file_file_icon($file),
+                    get_mimetype_description($file), 'moodle',
+                    ['class' => 'icon']);
+                $path = moodle_url::make_pluginfile_url($file->get_contextid(), $file->get_component(), $file->get_filearea(),
+                                                         $file->get_itemid(), $file->get_filepath(), $file->get_filename());
+                $attachments[$i]['icon'] = $iconimage;
+                $attachments[$i]['filepath'] = $path;
+
+                if (in_array($mimetype, ['image/gif', 'image/jpeg', 'image/png'])) {
+                    // Image attachments don't get printed as links.
+                    $attachments[$i]['image'] = true;
+                } else {
+                    $attachments[$i]['image'] = false;
+                }
+                $i += 1;
+            }
+        }
+        return $attachments;
+    }
+
+    // Getter.
+
+    /**
+     * Getter for the postid
+     * @return int $this->id    The post ID.
+     */
+    public function get_id() {
+        $this->existence_check();
+        return $this->id;
+    }
+
+    /**
+     * Getter for the discussionid
+     * @return int $this->discussion    The ID of the discussion where the post is located.
+     */
+    public function get_discussionid() {
+        $this->existence_check();
+        return $this->discussion;
+    }
+
+    /**
+     * Getter for the parentid
+     * @return int $this->parent    The ID of the parent post.
+     */
+    public function get_parentid() {
+        $this->existence_check();
+        return $this->parent;
+    }
+
+    /**
+     * Getter for the userid
+     * @return int $this->userid    The ID of the user who wrote the post.
+     */
+    public function get_userid() {
+        $this->existence_check();
+        return $this->userid;
+    }
+
+    /**
+     * Returns the moodleoverflow where the post is located.
+     * @return object $moodleoverflowobject
+     */
+    public function get_moodleoverflow() {
+        global $DB;
+        $this->existence_check();
+
+        if (empty($this->moodleoverflowobject)) {
+            $discussion = $this->get_discussion();
+            $this->moodleoverflowobject = $DB->get_record('moodleoverflow', ['id' => $discussion->get_moodleoverflowid()]);
+        }
+
+        return $this->moodleoverflowobject;
+    }
+
+    /**
+     * Returns the discussion where the post is located.
+     *
+     * @return object $discussionobject.
+     */
+    public function get_discussion() {
+        global $DB;
+        $this->existence_check();
+
+        if (empty($this->discussionobject)) {
+            $record = $DB->get_record('moodleoverflow_discussions', ['id' => $this->discussion]);
+            $this->discussionobject = discussion::from_record($record);
+        }
+        return $this->discussionobject;
+    }
+
+    /**
+     * Returns the coursemodule
+     *
+     * @return object $cmobject
+     */
+    public function get_coursemodule() {
+        $this->existence_check();
+
+        if (empty($this->cmobject)) {
+            $this->cmobject = \get_coursemodule_from_instance('moodleoverflow', $this->get_moodleoverflow()->id);
+        }
+
+        return $this->cmobject;
+    }
+
+    /**
+     * Returns the parent post
+     * @return object|false $post|false
+     */
+    public function moodleoverflow_get_parentpost() {
+        global $DB;
+        $this->existence_check();
+
+        if ($this->parent == 0) {
+            // This post is the parent post.
+            $this->parentpost = false;
+            return false;
+        }
+
+        if (empty($this->parentpost)) {
+            $parentpostrecord = $DB->get_record('moodleoverflow_post', ['id' => $this->parent]);
+            $this->parentpost = $this->from_record($parentpostrecord);
+        }
+        return $this->parentpost;
+    }
+
+    /**
+     * Returns children posts (answers) as DB-records.
+     *
+     * @return array|false children/answer posts.
+     */
+    public function moodleoverflow_get_childposts() {
+        global $DB;
+        $this->existence_check();
+
+        if ($childposts = $DB->get_records('moodleoverflow_posts', ['parent' => $this->id])) {
+            return $childposts;
+        }
+
+        return false;
+    }
+
+    /**
+     * This getter works as an help function in case another file/function needs the db-object of this instance (as the function
+     * is not adapted/refactored to the new way of working with discussion).
+     * @return object
+     */
+    public function get_db_object() {
+        $this->existence_check();
+        return $this->build_db_object();
+    }
+
+    // Helper Functions.
+
+    /**
+     * Calculate the ratings of a post.
+     *
+     * @return object $ratingsobject.
+     */
+    public function moodleoverflow_get_post_ratings() {
+        $this->existence_check();
+
+        $discussionid = $this->get_discussion()->id;
+        $postratings = \mod_moodleoverflow\ratings::moodleoverflow_get_ratings_by_discussion($discussionid, $this->id);
+
+        $ratingsobject = new \stdClass();
+        $ratingsobject->upvotes = $postratings->upvotes;
+        $ratingsobject->downvotes = $postratings->downvotes;
+        $ratingsobject->votesdifference = $postratings->upvotes - $postratings->downvotes;
+        $ratingsobject->markedhelpful = $postratings->ishelpful;
+        $ratingsobject->markedsolution = $postratings->issolved;
+
+        return $ratingsobject;
+    }
+
+    /**
+     * Marks the post as read if the user is tracking the discussion.
+     * Uses function from mod_moodleoverflow\readtracking.
+     */
+    public function mark_post_read() {
+        global $USER;
+        $cantrack = readtracking::moodleoverflow_can_track_moodleoverflows($this->get_moodleoverflow());
+        $istracked = readtracking::moodleoverflow_is_tracked($this->get_moodleoverflow());
+        if ($cantrack && $istracked) {
+            // Please be aware that in future the use of get_db_object() should be replaced with only $this,
+            // as the readtracking class should be refactored with the new way of working with posts.
+            readtracking::moodleoverflow_mark_post_read($USER->id, $this->get_db_object());
+        }
+    }
+
+    /**
+     * Builds an object from this instance that has only DB-relevant attributes.
+     * @return object $dbobject
+     */
+    private function build_db_object() {
+        $dbobject = new \stdClass();
+        $dbobject->id = $this->id;
+        $dbobject->discussion = $this->discussion;
+        $dbobject->parent = $this->parent;
+        $dbobject->userid = $this->userid;
+        $dbobject->created = $this->created;
+        $dbobject->modified = $this->modified;
+        $dbobject->message = $this->message;
+        $dbobject->messageformat = $this->messageformat;
+        $dbobject->attachment = $this->attachment;
+        $dbobject->mailed = $this->mailed;
+        $dbobject->reviewed = $this->reviewed;
+        $dbobject->timereviewed = $this->timereviewed;
+
+        return $dbobject;
+    }
+
+    /*
+     * Count all replies of a post.
+     *
+     * @param bool $onlyreviewed Whether to count only reviewed posts.
+     * @return int Amount of replies
+     */
+    public function moodleoverflow_count_replies($onlyreviewed) {
+        global $DB;
+
+        $conditions = ['parent' => $this->id];
+
+        if ($onlyreviewed) {
+            $conditions['reviewed'] = '1';
+        }
+
+        // Return the amount of replies.
+        return $DB->count_records('moodleoverflow_posts', $conditions);
+    }
+
+    // Security.
+
+    /**
+     * Makes sure that the instance exists in the database. Every function in this class requires this check
+     * (except the function that adds a post to the database)
+     *
+     * @return true
+     * @throws moodle_exception
+     */
+    private function existence_check() {
+        if (empty($this->id) || $this->id == false || $this->id == null) {
+            throw new \moodle_exception('noexistingpost', 'moodleoverflow');
+        }
+        return true;
+    }
+}
diff --git a/classes/post/post_control.php b/classes/post/post_control.php
new file mode 100644
index 0000000000..60f1558966
--- /dev/null
+++ b/classes/post/post_control.php
@@ -0,0 +1,857 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class that is important to interact with posts.
+ *
+ * @package     mod_moodleoverflow
+ * @copyright   2023 Tamaro Walter
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+namespace mod_moodleoverflow\post;
+
+// Import namespace from the locallib, needs a check later which namespaces are really needed.
+use mod_moodleoverflow\anonymous;
+use mod_moodleoverflow\capabilities;
+use mod_moodleoverflow\review;
+
+use mod_moodleoverflow\post\post;
+use mod_moodleoverflow\discussion\discussion;
+use moodle_exception;
+
+defined('MOODLE_INTERNAL') || die();
+global $CFG;
+
+require_once($CFG->dirroot . '/mod/moodleoverflow/locallib.php');
+require_once($CFG->libdir . '/completionlib.php');
+
+/**
+ * This Class controls the manipulation of posts and acts as controller of interactions with the post.php
+ *
+ * This Class has 2 main Tasks:
+ * 1. Before entering the post.php
+ * - Detect the wanted interaction (new discussion, new answer in a discussion, editing or deleting a post)
+ * - make capability and other security/integrity checks (are all given data correct?)
+ * - gather important information that need to be used later.
+ * Note: if a post is being deleted, the post_control deletes it in the first step and the post.php does not call the post_form.php
+ *
+ * Now the post.php calls the post_form, so that the user can enter a message and attachments.
+ *
+ * 2. After calling the post_form:
+ * - collect the information from the post_form
+ * - based on the interaction, call the right function
+ *
+ * @package   mod_moodleoverflow
+ * @copyright 2023 Tamaro Walter
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class post_control {
+
+    /** @var string the Interaction type, the interactions are:
+     * - create (creates a new discussion with a first post)
+     * - reply (replies to a existing post, can be an answer or a comment)
+     * - edit (change the content of an existing post)
+     * - delete (delete a post from a discussion)
+     */
+    private $interaction;
+
+    /** @var object information about the post like the related moodleoverflow, post etc.
+     * Difference between info and prepost: Info has objects, prepost mostly ID's and string like the message of the post.
+     */
+    private $info;
+
+    /** @var object prepost for the classes/post/post_form.php,
+     * this object is more like a prototype of a post and it's not in the database*
+     * Difference between info and prepost. Info has objects, prepost mostly ID's and strings like the message of the post.
+     */
+    private $prepost;
+
+    /**
+     * Constructor
+     */
+    public function __construct() {
+        $this->info = new \stdClass();
+    }
+
+    /**
+     * Detects the interaction and builds the prepost.
+     * @param object $urlparamter parameter from the post.php
+     * @throws moodle_exception if the interaction is not correct.
+     */
+    public function detect_interaction($urlparameter) {
+        $count = 0;
+        $count += $urlparameter->create ? 1 : 0;
+        $count += $urlparameter->reply ? 1 : 0;
+        $count += $urlparameter->edit ? 1 : 0;
+        $count += $urlparameter->delete ? 1 : 0;
+        if ($count !== 1) {
+            throw new \coding_exception('Exactly one parameter should be specified!');
+        }
+
+        if ($urlparameter->create) {
+            $this->interaction = 'create';
+            $this->info->moodleoverflowid = $urlparameter->create;
+            $this->build_prepost_create($this->info->moodleoverflowid);
+
+        } else if ($urlparameter->edit) {
+            $this->interaction = 'edit';
+            $this->info->editpostid = $urlparameter->edit;
+            $this->build_prepost_edit($this->info->editpostid);
+
+        } else if ($urlparameter->reply) {
+            $this->interaction = 'reply';
+            $this->info->replypostid = $urlparameter->reply;
+            $this->build_prepost_reply($this->info->replypostid);
+
+        } else if ($urlparameter->delete) {
+            $this->interaction = 'delete';
+            $this->info->deletepostid = $urlparameter->delete;
+            $this->build_prepost_delete($this->info->deletepostid);
+        } else {
+            throw new moodle_exception('unknownaction');
+        }
+    }
+
+    /**
+     * Controls the execution of an interaction.
+     * @param object $form The results from the post_form.
+     */
+    public function execute_interaction($form) {
+        global $CFG;
+        // Redirect url in case of occurring errors.
+        if (empty($SESSION->fromurl)) {
+            $errordestination = $CFG->wwwroot . '/mod/moodleoverflow/view.php?m=' . $this->prepost->moodleoverflowid;
+        } else {
+            $errordestination = $SESSION->fromurl;
+        }
+
+        // Format the submitted data.
+        $this->prepost->messageformat = $form->message['format'];
+        $this->prepost->formattachments = $form->attachments;
+        $this->prepost->message = $form->message['text'];
+        $this->prepost->messagetrust = trusttext_trusted($this->prepost->modulecontext);
+
+        // Get the current time.
+        $this->prepost->timenow = time();
+
+        // Execute the right function.
+        if ($this->interaction == 'create' && $form->moodleoverflow == $this->prepost->moodleoverflowid) {
+            $this->execute_create($form, $errordestination);
+        } else if ($this->interaction == 'reply' && $form->reply == $this->prepost->parentid) {
+            $this->execute_reply($form, $errordestination);
+        } else if ($this->interaction == 'edit' && $form->edit == $this->prepost->postid) {
+            $this->execute_edit($form, $errordestination);
+        } else {
+            throw new moodle_exception('unexpectedinteractionerror', 'moodleoverflow', $errordestination);
+        }
+    }
+
+    /**
+     * This function is used when a guest enters the post.php.
+     * Parameters will be checked so that the post.php can redirect the user to the right site.
+     * @param int $postid
+     * @param int $moodleoverflowid
+     * @return object $this->information // The gathered information.
+     */
+    public function catch_guest($postid = false, $moodleoverflowid = false) {
+        global $PAGE;
+        if ((!$postid && !$moodleoverflowid) || ($postid && $moodleoverflowid)) {
+            throw new moodle_exception('inaccurateparameter', 'moodleoverflow');
+        }
+        if ($postid) {
+            $this->collect_information($postid, false);
+        } else if ($moodleoverflowid) {
+            $this->collect_information(false, $moodleoverflowid);
+        }
+        $this->info->modulecontext = \context_module::instance($this->info->cm->id);
+
+        // Set the parameters for the page.
+        $PAGE->set_cm($this->info->cm, $this->info->course, $this->info->moodleoverflow);
+        $PAGE->set_context($this->info->modulecontext);
+        $PAGE->set_title($this->info->course->shortname);
+        $PAGE->set_heading($this->info->course->fullname);
+        $PAGE->add_body_class('limitedwidth');
+        return $this->info;
+    }
+
+    // Build functions, that build the prepost object for further use.
+
+    /**
+     * Function to prepare a new discussion in moodleoverflow.
+     *
+     * @param int $moodleoverflowid     The ID of the moodleoverflow where the new discussion post is being created.
+     */
+    private function build_prepost_create($moodleoverflowid) {
+        global $DB, $SESSION, $USER;
+
+        // Get the related moodleoverflow, course coursemodule and the contexts.
+        $this->collect_information(false, $moodleoverflowid);
+
+        // Check if the user can start a new discussion.
+        if (!$this->check_user_can_create_discussion()) {
+
+            // Catch unenrolled user.
+            if (!isguestuser() && !is_enrolled($this->info->coursecontext)) {
+                if (enrol_selfenrol_available($this->info->course->id)) {
+                    $SESSION->wantsurl = qualified_me();
+                    $SESSION->enrolcancel = get_local_referer(false);
+                    redirect(new \moodle_url('/enrol/index.php',  ['id' => $this->info->course->id,
+                                             'returnurl' => '/mod/moodleoverflow/view.php?m=' . $this->info->moodleoverflow->id, ]),
+                                             get_string('youneedtoenrol'));
+                }
+            }
+            // Notify the user, that he can not post a new discussion.
+            throw new moodle_exception('nopostmoodleoverflow', 'moodleoverflow');
+        }
+
+        // Where is the user coming from?
+        $SESSION->fromurl = get_local_referer(false);
+
+        // Prepare the post.
+        $this->assemble_prepost();
+        $this->prepost->postid = null;
+        $this->prepost->discussionid = null;
+        $this->prepost->parentid = 0;
+        $this->prepost->subject = '';
+        $this->prepost->userid = $USER->id;
+        $this->prepost->message = '';
+
+        // Unset where the user is coming from.
+        // Allows to calculate the correct return url later.
+        unset($SESSION->fromdiscussion);
+    }
+
+    /**
+     * Function to prepare a new post that replies to an existing post.
+     *
+     * @param int $replypostid      The ID of the post that is being answered.
+     */
+    private function build_prepost_reply($replypostid) {
+        global $DB, $PAGE, $SESSION, $USER, $CFG;
+
+        // Get the related poost, discussion, moodleoverflow, course, coursemodule and contexts.
+        $this->collect_information($replypostid, false);
+
+        // Ensure the coursemodule is set correctly.
+        $PAGE->set_cm($this->info->cm, $this->info->course, $this->info->moodleoverflow);
+
+        // Prepare a post.
+        $this->assemble_prepost();
+        $this->prepost->postid = null;
+        $this->prepost->parentid = $this->info->relatedpost->get_id();
+        $this->prepost->userid = $USER->id;
+        $this->prepost->message = '';
+
+        // Check whether the user is allowed to post.
+        if (!$this->check_user_can_create_reply()) {
+
+            // Give the user the chance to enroll himself to the course.
+            if (!isguestuser() && !is_enrolled($this->info->coursecontext)) {
+                $SESSION->wantsurl = qualified_me();
+                $SESSION->enrolcancel = get_local_referer(false);
+                redirect(new \moodle_url('/enrol/index.php',
+                    ['id' => $this->info->course->id,
+                     'returnurl' => '/mod/moodleoverflow/view.php?m=' . $this->info->moodleoverflow->id,
+                    ]), get_string('youneedtoenrol'));
+            }
+            // Print the error message.
+            throw new moodle_exception('nopostmoodleoverflow', 'moodleoverflow');
+        }
+        // Make sure the user can post here.
+        if (!$this->info->cm->visible && !has_capability('moodle/course:viewhiddenactivities', $this->info->modulecontext)) {
+            throw new moodle_exception('activityiscurrentlyhidden');
+        }
+
+        // Append 'RE: ' to the discussions subject.
+        $strre = get_string('re', 'moodleoverflow');
+        if (check_php_version('8.0.0')) {
+            if (!(str_starts_with($this->prepost->subject, $strre))) {
+                $this->prepost->subject = $strre . ' ' . $this->prepost->subject;
+            }
+        } else {
+            // TODO: remove this else branch when support for php version 7.4 ends.
+            if (!(substr($this->prepost->subject, 0, strlen($strre)) == $strre)) {
+                $this->prepost->subject = $strre . ' ' . $this->prepost->subject;
+            }
+        }
+
+        // Unset where the user is coming from.
+        // Allows to calculate the correct return url later.
+        unset($SESSION->fromdiscussion);
+    }
+
+    /**
+     * Function to prepare the edit of an user own existing post.
+     *
+     * @param int $editpostid       The ID of the post that is being edited.
+     */
+    private function build_prepost_edit($editpostid) {
+        global $DB, $PAGE, $SESSION, $USER;
+
+        // Get the related post, discussion, moodleoverflow, course, coursemodule and contexts.
+        $this->collect_information($editpostid, false);
+
+        // Set the pages context.
+        $PAGE->set_cm($this->info->cm, $this->info->course, $this->info->moodleoverflow);
+
+        // Check if the post can be edited.
+        $beyondtime = ((time() - $this->info->relatedpost->created) > get_config('moodleoverflow', 'maxeditingtime'));
+
+        // Please be aware that in future the use of get_db_object() should be replaced with $this->info->relatedpost,
+        // as the review class should be refactored with the new way of working with posts.
+        $alreadyreviewed = review::should_post_be_reviewed($this->info->relatedpost->get_db_object(), $this->info->moodleoverflow)
+                           && $this->info->relatedpost->reviewed;
+        if (($beyondtime || $alreadyreviewed) && !has_capability('mod/moodleoverflow:editanypost',
+                                                                 $this->info->modulecontext)) {
+            throw new moodle_exception('maxtimehaspassed', 'moodleoverflow', '',
+                format_time(get_config('moodleoverflow', 'maxeditingtime')));
+        }
+
+        // If the current user is not the one who posted this post.
+        if ($this->info->relatedpost->get_userid() != $USER->id) {
+
+            // Check if the current user has not the capability to edit any post.
+            if (!has_capability('mod/moodleoverflow:editanypost', $this->info->modulecontext)) {
+
+                // Display the error. Capabilities are missing.
+                throw new moodle_exception('cannoteditposts', 'moodleoverflow');
+            }
+        }
+
+        // Load the $post variable.
+        $this->assemble_prepost();
+
+        // Unset where the user is coming from. This allows to calculate the correct return url later.
+        unset($SESSION->fromdiscussion);
+    }
+
+    /**
+     * Function to prepare the deletion of a post.
+     *
+     * @param int $deletepostid     The ID of the post that is being deleted.
+     */
+    private function build_prepost_delete($deletepostid) {
+        global $DB, $USER;
+
+        // Get the related post, discussion, moodleoverflow, course, coursemodule and contexts.
+        $this->collect_information($deletepostid, false);
+
+        // Require a login and retrieve the modulecontext.
+        require_login($this->info->course, false, $this->info->cm);
+
+        // Check some capabilities.
+        $this->check_user_can_delete_post();
+
+        // Count all replies of this post.
+        $this->info->replycount = $this->info->relatedpost->moodleoverflow_count_replies(false);
+        if ($this->info->replycount >= 1) {
+            $this->info->deletetype = 'plural';
+        } else {
+            $this->info->deletetype = 'singular';
+        }
+        // Build the prepost.
+        $this->assemble_prepost();
+        $this->prepost->deletechildren = true;
+    }
+
+    // Execute Functions.
+
+    private function execute_create($form, $errordestination) {
+        global $USER;
+        // Check if the user is allowed to post.
+        $this->check_user_can_create_discussion();
+
+        // Set the post to not reviewed if questions should be reviewed and the user is not a reviewed themselves.
+        if (review::get_review_level($this->info->moodleoverflow) >= review::QUESTIONS &&
+                !capabilities::has(capabilities::REVIEW_POST, $this->info->modulecontext, $USER->id)) {
+            $this->prepost->reviewed = 0;
+        } else {
+            $this->prepost->reviewed = 1;
+        }
+
+        // Get the discussion subject.
+        $this->prepost->subject = $form->subject;
+
+        // Create the discussion object.
+        $discussion = discussion::construct_without_id($this->prepost->courseid, $this->prepost->moodleoverflowid,
+                                                       $this->prepost->subject, 0, $this->prepost->userid,
+                                                       $this->prepost->timenow, $this->prepost->timenow, $this->prepost->userid);
+        if (!$discussion->moodleoverflow_add_discussion($this->prepost)) {
+            throw new moodle_exception('couldnotadd', 'moodleoverflow', $errordestination);
+        }
+
+        // The creation was successful.
+        $redirectmessage = \html_writer::tag('p', get_string("postaddedsuccess", "moodleoverflow"));
+
+        // Trigger the discussion created event.
+        $params = ['context' => $this->info->modulecontext, 'objectid' => $discussion->get_id()];
+        $event = \mod_moodleoverflow\event\discussion_created::create($params);
+        $event->trigger();
+
+        // Subscribe to this thread.
+        // Please be aware that in future the use of get_db_object() should be replaced with only $this->info->discussion,
+        // as the subscription class should be refactored with the new way of working with posts.
+        \mod_moodleoverflow\subscriptions::moodleoverflow_post_subscription($form, $this->info->moodleoverflow,
+                                                                            $discussion->get_db_object(),
+                                                                            $this->info->modulecontext);
+
+        // Define the location to redirect the user after successfully posting.
+        $redirectto = new \moodle_url('/mod/moodleoverflow/view.php', ['m' => $form->moodleoverflow]);
+        redirect(moodleoverflow_go_back_to($redirectto->out()), $redirectmessage, null, \core\output\notification::NOTIFY_SUCCESS);
+    }
+
+    private function execute_reply($form, $errordestination) {
+        // Check if the user has the capability to write a reply.
+        $this->check_user_can_create_reply();
+
+        // Set to not reviewed, if posts should be reviewed, and user is not a reviewer themselves.
+        if (review::get_review_level($this->info->moodleoverflow) == review::EVERYTHING &&
+                !has_capability('mod/moodleoverflow:reviewpost', \context_module::instance($this->info->cm->id))) {
+            $this->prepost->reviewed = 0;
+        } else {
+            $this->prepost->reviewed = 1;
+        }
+
+        // Create the new post.
+        if (!$newpostid = $this->info->discussion->moodleoverflow_add_post_to_discussion($this->prepost)) {
+            throw new moodle_exception('couldnotadd', 'moodleoverflow', $errordestination);
+        }
+
+        // The creation was successful.
+        $redirectmessage = \html_writer::tag('p', get_string("postaddedsuccess", "moodleoverflow"));
+        $redirectmessage .= \html_writer::tag('p', get_string("postaddedtimeleft", "moodleoverflow",
+                                              format_time(get_config('moodleoverflow', 'maxeditingtime'))));
+
+        // Trigger the post created event.
+        $params = ['context' => $this->info->modulecontext, 'objectid' => $newpostid,
+                   'other' => ['discussionid' => $this->prepost->discussionid,
+                               'moodleoverflowid' => $this->prepost->moodleoverflowid,
+                              ],
+                  ];
+        $event = \mod_moodleoverflow\event\post_created::create($params);
+        $event->trigger();
+
+        // Subscribe to this thread.
+        // Please be aware that in future the use of build_db_object() should be replaced with only $this->info->discussion,
+        // as the subscription class should be refactored with the new way of working with posts.
+        \mod_moodleoverflow\subscriptions::moodleoverflow_post_subscription($form, $this->info->moodleoverflow,
+                                                                             $this->info->discussion->get_db_object(),
+                                                                             $this->info->modulecontext);
+
+        // Define the location to redirect the user after successfully posting.
+        $redirectto = new \moodle_url('/mod/moodleoverflow/discussion.php',
+                                      ['d' => $this->prepost->discussionid, 'p' => $newpostid]);
+        redirect(\moodleoverflow_go_back_to($redirectto->out()), $redirectmessage, null, \core\output\notification::NOTIFY_SUCCESS);
+
+    }
+
+    private function execute_edit($form, $errordestination) {
+        global $USER, $DB;
+        // Check if the user has the capability to edit his post.
+        $this->check_user_can_edit_post();
+
+        // If the post that is being edited is the parent post, the subject can be edited too.
+        if ($this->prepost->parentid == 0) {
+            $this->prepost->subject = $form->subject;
+        }
+
+        // Update the post.
+        if (!$this->info->discussion->moodleoverflow_edit_post_from_discussion($this->prepost)) {
+            throw new moodle_exception('couldnotupdate', 'moodleoverflow', $errordestination);
+        }
+
+        // The edit was successful.
+        $redirectmessage = get_string('postupdated', 'moodleoverflow');
+        if ($this->prepost->userid == $USER->id) {
+            $redirectmessage = get_string('postupdated', 'moodleoverflow');
+        } else {
+            if (anonymous::is_post_anonymous($this->info->discussion, $this->info->moodleoverflow, $this->prepost->userid)) {
+                $name = get_string('anonymous', 'moodleoverflow');
+            } else {
+                $realuser = $DB->get_record('user', ['id' => $this->prepost->userid]);
+                $name = fullname($realuser);
+            }
+            $redirectmessage = get_string('editedpostupdated', 'moodleoverflow', $name);
+        }
+
+        // Trigger the post updated event.
+        $params = ['context' => $this->info->modulecontext, 'objectid' => $form->edit,
+                   'other' => ['discussionid' => $this->prepost->discussionid,
+                               'moodleoverflowid' => $this->prepost->moodleoverflowid,
+                              ],
+                   'relateduserid' => $this->prepost->userid == $USER->id ? $this->prepost->userid : null,
+                  ];
+        $event = \mod_moodleoverflow\event\post_updated::create($params);
+        $event->trigger();
+
+        // Define the location to redirect the user after successfully editing.
+        $redirectto = new \moodle_url('/mod/moodleoverflow/discussion.php',
+                                      ['d' => $this->prepost->discussionid, 'p' => $form->edit]);
+        redirect(moodleoverflow_go_back_to($redirectto->out()), $redirectmessage, null, \core\output\notification::NOTIFY_SUCCESS);
+    }
+
+    public function execute_delete() {
+        $this->check_interaction('delete');
+
+        // Check if the user has the capability to delete the post.
+        $timepassed = time() - $this->info->relatedpost->created;
+        $url = new \moodle_url('/mod/moodleoverflow/discussion.php', ['d' => $this->info->discussion->get_id()]);
+        if (($timepassed > get_config('moodleoverflow', 'maxeditingtime')) && !$this->info->deleteanypost) {
+            throw new moodle_exception('cannotdeletepost', 'moodleoverflow', moodleoverflow_go_back_to($url));
+        }
+
+        // A normal user cannot delete his post if there are direct replies.
+        if ($this->info->replycount && !$this->info->deleteanypost) {
+            throw new moodle_exception('cannotdeletereplies', 'moodleoverflow', moodleoverflow_go_back_to($url));
+        }
+
+        // Check if the post is a parent post or not.
+        if ($this->prepost->parentid == 0) {
+            // Save the moodleoverflowid. Then delete the discussion.
+            $moodleoverflowid = $this->info->discussion->get_moodleoverflowid();
+            $this->info->discussion->moodleoverflow_delete_discussion($this->prepost);
+
+            // Redirect the user back to the start page of the moodleoverflow instance.
+            redirect('view.php?m=' . $moodleoverflowid);
+        } else {
+            $this->info->discussion->moodleoverflow_delete_post_from_discussion($this->prepost);
+            $discussionurl = new \moodle_url('/mod/moodleoverflow/discussion.php', ['d' => $this->info->discussion->get_id()]);
+            redirect(moodleoverflow_go_back_to($discussionurl));
+        }
+    }
+
+    // Functions that uses the post.php to build the page.
+
+    /**
+     * Builds a part of confirmation page. The confirmation request box is being build by the post.php.
+     */
+    public function confirm_delete() {
+        $this->check_interaction('delete');
+        global $PAGE;
+        moodleoverflow_set_return();
+        $PAGE->navbar->add(get_string('delete', 'moodleoverflow'));
+        $PAGE->set_title($this->info->course->shortname);
+        $PAGE->set_heading($this->info->course->fullname);
+        $PAGE->add_body_class('limitedwidth');
+    }
+
+    /**
+     *
+     * Builds and returns a post_form object where the users enters/edits the message and attachments of the post.
+     * @param array $pageparams    An object that the post.php created.
+     * @return object a mod_moodleoverflow_post_form object.
+     */
+    public function build_postform($pageparams) {
+        global $USER, $CFG;
+        // Require that the user is logged in properly and enrolled to the course.
+        require_login($this->info->course, false, $this->info->cm);
+
+        // Prepare the attachments.
+        $draftitemid = file_get_submitted_draft_itemid('attachments');
+        file_prepare_draft_area($draftitemid, $this->info->modulecontext->id, 'mod_moodleoverflow', 'attachment',
+                                empty($this->prepost->postid) ? null : $this->prepost->postid,
+                                \mod_moodleoverflow_post_form::attachment_options($this->info->moodleoverflow));
+
+        // If the post is anonymous, attachments should have an anonymous author when editing the attachment.
+        if ($draftitemid && $this->interaction == 'edit' && anonymous::is_post_anonymous($this->info->discussion,
+                $this->info->moodleoverflow, $this->prepost->userid)) {
+            $usercontext = \context_user::instance($USER->id);
+            $anonymousstr = get_string('anonymous', 'moodleoverflow');
+            foreach (get_file_storage()->get_area_files($usercontext->id, 'user', 'draft', $draftitemid) as $file) {
+                $file->set_author($anonymousstr);
+            }
+        }
+
+        // Prepare the form.
+        $edit = $this->interaction == 'edit';
+        $formarray = ['course' => $this->info->course, 'cm' => $this->info->cm, 'coursecontext' => $this->info->coursecontext,
+                      'modulecontext' => $this->info->modulecontext, 'moodleoverflow' => $this->info->moodleoverflow,
+                      'post' => $this->prepost, 'edit' => $edit,
+                    ];
+
+        // Declare the post_form.
+        $mformpost = new \mod_moodleoverflow_post_form('post.php', $formarray, 'post', '', ['id' => 'mformmoodleoverflow']);
+
+        // If the user is not the original author append an extra message to the message. (Happens when interaction = 'edit').
+        if ($USER->id != $this->prepost->userid) {
+            // Create a temporary object.
+            $data = new \stdClass();
+            $data->date = userdate(time());
+            $this->prepost->messageformat = editors_get_preferred_format();
+            if ($this->prepost->messageformat == FORMAT_HTML) {
+                $data->name = \html_writer::tag('a', $CFG->wwwroot . '/user/view.php?id' . $USER->id .
+                                                '&course=' . $this->prepost->courseid . '">' . fullname($USER));
+                $this->prepost->message .= \html_writer::tag('p', \html_writer::tag('span',
+                             get_string('editedby', 'moodleoverflow', $data), ["class" => "edited"]));
+            } else {
+                $data->name = fullname($USER);
+                $this->prepost->message .= "\n\n(" . get_string('editedby', 'moodleoverflow', $data) . ')';
+            }
+            // Delete the temporary object.
+            unset($data);
+        }
+
+        // Define the heading for the form.
+        $formheading = '';
+        if ($this->interaction == 'reply') {
+            $heading = get_string('yourreply', 'moodleoverflow');
+            $formheading = get_string('reply', 'moodleoverflow');
+        } else {
+            $heading = get_string('yournewtopic', 'moodleoverflow');
+        }
+
+        // Set data for the form.
+        $mformpost->set_data([
+             'attachments' => $draftitemid,
+             'general' => $heading,
+             'subject' => $this->prepost->subject,
+             'message' => ['text' => $this->prepost->message,
+                           'format' => editors_get_preferred_format(),
+                           'itemid' => $this->prepost->postid, ],
+             'userid' => $this->prepost->userid,
+             'parent' => $this->prepost->parentid,
+             'discussion' => $this->prepost->discussionid,
+             'course' => $this->prepost->courseid,
+            ]
+            + $pageparams
+        );
+
+        return $mformpost;
+    }
+
+    // Helper functions.
+
+    // Getter.
+
+    /**
+     * Returns the interaction type.
+     * @return string $interaction
+     */
+    public function get_interaction() {
+        return $this->interaction;
+    }
+
+    /**
+     * Returns the gathered important information in the build_prepost_() functions.
+     * @return object $info
+     */
+    public function get_information() {
+        return $this->info;
+    }
+
+    /**
+     * Retuns the prepared post.
+     * @return object $prepost
+     */
+    public function get_prepost() {
+        return $this->prepost;
+    }
+
+    // Functions that build the info and prepost object.
+
+    /**
+     * Builds the information object that is being used in the build prepost functions.
+     * The variables are optional, but one is necessary to build the information object.
+     * @param int $postid
+     * @param int $moodleoverflowid
+     */
+    private function collect_information($postid = false, $moodleoverflowid = false) {
+        if ($postid) {
+            // The related post is the post that is being answered, edited, or deleted.
+            $this->info->relatedpost = $this->check_post_exists($postid);
+            $this->info->discussion = $this->check_discussion_exists($this->info->relatedpost->get_discussionid());
+            $localmoodleoverflowid = $this->info->discussion->get_moodleoverflowid();
+        } else {
+            $localmoodleoverflowid = $moodleoverflowid;
+        }
+        $this->info->moodleoverflow = $this->check_moodleoverflow_exists($localmoodleoverflowid);
+        $this->info->course = $this->check_course_exists($this->info->moodleoverflow->course);
+        $this->info->cm = $this->check_coursemodule_exists($this->info->moodleoverflow->id, $this->info->course->id);
+        $this->info->modulecontext = \context_module::instance($this->info->cm->id);
+        $this->info->coursecontext = \context_course::instance($this->info->course->id);
+    }
+
+    /**
+     * Assembles the prepost object. Helps to reduce code in the build_prepost functions.
+     * Some prepost parameters will be assigned individually by the build_prepost functions.
+     */
+    private function assemble_prepost() {
+        $this->prepost = new \stdClass();
+        $this->prepost->courseid = $this->info->course->id;
+        $this->prepost->moodleoverflowid = $this->info->moodleoverflow->id;
+        $this->prepost->modulecontext = $this->info->modulecontext;
+
+        if ($this->interaction != 'create') {
+            $this->prepost->discussionid = $this->info->discussion->get_id();
+            $this->prepost->subject = $this->info->discussion->name;
+
+            if ($this->interaction != 'reply') {
+                $this->prepost->parentid = $this->info->relatedpost->get_parentid();
+                $this->prepost->postid = $this->info->relatedpost->get_id();
+                $this->prepost->userid = $this->info->relatedpost->get_userid();
+                $this->prepost->message = $this->info->relatedpost->message;
+            }
+        }
+    }
+
+
+    // Interaction check.
+
+    /**
+     * Checks if the interaction is correct
+     * @param string $interaction
+     * @return true if the interaction is correct
+     */
+    private function check_interaction($interaction) {
+        if ($this->interaction != $interaction) {
+            throw new moodle_exception('wronginteraction' , 'moodleoverflow');
+        }
+        return true;
+    }
+
+    // Database checks.
+
+    /**
+     * Checks if the course exists. Returns the $DB->record of the course.
+     * @param int $courseid
+     * @return object $course
+     */
+    private function check_course_exists($courseid) {
+        global $DB;
+        if (!$course = $DB->get_record('course', ['id' => $courseid])) {
+            throw new moodle_exception('invalidcourseid');
+        }
+        return $course;
+    }
+
+    /**
+     * Checks if the coursemodule exists.
+     * @param int $moodleoverflowid
+     * @param int $courseid
+     * @return object $cm
+     */
+    private function check_coursemodule_exists($moodleoverflowid, $courseid) {
+        if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflowid,
+                                                                    $courseid)) {
+            throw new moodle_exception('invalidcoursemodule');
+        }
+        return $cm;
+    }
+
+    /**
+     * Checks if the related moodleoverflow exists.
+     * @param int $moodleoverflowid
+     * @return object $moodleoverflow
+     */
+    private function check_moodleoverflow_exists($moodleoverflowid) {
+        // Get the related moodleoverflow instance.
+        global $DB;
+        if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflowid])) {
+            throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow');
+        }
+        return $moodleoverflow;
+    }
+
+    /**
+     * Checks if the related discussion exists.
+     * @param int $discussionid
+     * @return object $discussion
+     */
+    private function check_discussion_exists($discussionid) {
+        global $DB;
+        if (!$discussionrecord = $DB->get_record('moodleoverflow_discussions', ['id' => $discussionid])) {
+            throw new moodle_exception('invaliddiscussionid', 'moodleoverflow');
+        }
+        return discussion::from_record($discussionrecord);
+    }
+
+    /**
+     * Checks if a post exists.
+     * @param int $postid
+     * @return object $post
+     */
+    private function check_post_exists($postid) {
+        global $DB;
+        if (!$postrecord = $DB->get_record('moodleoverflow_posts', ['id' => $postid])) {
+            throw new moodle_exception('invalidpostid', 'moodleoverflow');
+        }
+        return post::from_record($postrecord);
+    }
+
+    // Capability checks.
+
+    /**
+     * Checks if a user can create a discussion.
+     * @return true
+     * @throws moodle_exception
+     */
+    private function check_user_can_create_discussion() {
+        if (!has_capability('mod/moodleoverflow:startdiscussion', $this->info->modulecontext)) {
+            throw new moodle_exception('cannotcreatediscussion', 'moodleoverflow');
+        }
+        return true;
+    }
+
+    /**
+     * Checks if a user can reply in a discussion.
+     * @return true
+     * @throws moodle_exception
+     */
+    private function check_user_can_create_reply() {
+        if (!has_capability('mod/moodleoverflow:replypost', $this->info->modulecontext, $this->prepost->userid)) {
+            throw new moodle_exception('cannotreply', 'moodleoverflow');
+        }
+        return true;
+    }
+
+    /**
+     * Checks if a user can edit a post.
+     * A user can edit if he can edit any post of if he edits his own post and has the ability to:
+     * start a new discussion or to reply to a post.
+     *
+     * @return true
+     * @throws moodle_exception
+     */
+    private function check_user_can_edit_post() {
+        global $USER;
+        $editanypost = has_capability('mod/moodleoverflow:editanypost', $this->info->modulecontext);
+        $replypost = has_capability('mod/moodleoverflow:replypost', $this->info->modulecontext);
+        $startdiscussion = has_capability('mod/moodleoverflow:startdiscussion', $this->info->modulecontext);
+        $ownpost = ($this->prepost->userid == $USER->id);
+        if (!(($ownpost && ($replypost || $startdiscussion)) || $editanypost)) {
+            throw new moodle_exception('cannotupdatepost', 'moodleoverflow');
+        }
+        return true;
+    }
+
+    /**
+     * Checks if a user can edit a post.
+     * @return true
+     * @throws moodle_exception
+     */
+    private function check_user_can_delete_post() {
+        global $USER;
+        $this->info->deleteownpost = has_capability('mod/moodleoverflow:deleteownpost', $this->info->modulecontext);
+        $this->info->deleteanypost = has_capability('mod/moodleoverflow:deleteanypost', $this->info->modulecontext);
+        if (!(($this->info->relatedpost->get_userid() == $USER->id && $this->info->deleteownpost) || $this->info->deleteanypost)) {
+
+            throw new moodle_exception('cannotdeletepost', 'moodleoverflow');
+        }
+        return true;
+    }
+}
diff --git a/classes/post_form.php b/classes/post_form.php
index caca0de668..97e49d5716 100644
--- a/classes/post_form.php
+++ b/classes/post_form.php
@@ -43,8 +43,9 @@ class mod_moodleoverflow_post_form extends moodleform {
      */
     public function definition() {
 
-        $modform        =& $this->_form;
+        $modform =& $this->_form;
         $post = $this->_customdata['post'];
+        $edit = $this->_customdata['edit'];
         $modcontext = $this->_customdata['modulecontext'];
         $moodleoverflow = $this->_customdata['moodleoverflow'];
 
@@ -70,7 +71,7 @@ public function definition() {
         }
 
         // Submit buttons.
-        if (isset($post->edit)) {
+        if ($edit) {
             $strsubmit = get_string('savechanges');
         } else {
             $strsubmit = get_string('posttomoodleoverflow', 'moodleoverflow');
@@ -142,10 +143,3 @@ public static function attachment_options($moodleoverflow) {
         ];
     }
 }
-
-
-
-
-
-
-
diff --git a/classes/review.php b/classes/review.php
index b7259a37c7..833969f960 100644
--- a/classes/review.php
+++ b/classes/review.php
@@ -132,7 +132,7 @@ public static function get_first_review_post($moodleoverflowid, $afterpostid = n
      */
     public static function should_post_be_reviewed($post, $moodleoverflow): bool {
         $reviewlevel = self::get_review_level($moodleoverflow);
-        if ($post->parent) {
+        if ($post->parent != 0) {
             return $reviewlevel == self::EVERYTHING;
         } else {
             return $reviewlevel >= self::QUESTIONS;
diff --git a/classes/subscriptions.php b/classes/subscriptions.php
index 83af4181d2..2f77e65e31 100644
--- a/classes/subscriptions.php
+++ b/classes/subscriptions.php
@@ -26,6 +26,9 @@
 
 namespace mod_moodleoverflow;
 
+use context_module;
+use stdClass;
+
 /**
  * Moodleoverflow subscription manager.
  *
@@ -356,7 +359,7 @@ public static function subscription_disabled($moodleoverflow) {
      * Checks wheter the specified moodleoverflow can be subscribed to.
      *
      * @param object $moodleoverflow The moodleoverflow ID
-     * @param \context_module $context The module context.
+     * @param context_module $context The module context.
      *
      * @return boolean
      */
@@ -456,7 +459,7 @@ public static function get_unsubscribable_moodleoverflows() {
     /**
      * Get the list of potential subscribers to a moodleoverflow.
      *
-     * @param \context_module $context The moodleoverflow context.
+     * @param context_module $context The moodleoverflow context.
      * @param string          $fields  The list of fields to return for each user.
      * @param string          $sort    Sort order.
      *
@@ -522,7 +525,7 @@ public static function fill_subscription_cache_for_course($courseid, $userid) {
      * Returns a list of user object who are subscribed to this moodleoverflow.
      *
      * @param stdClass        $moodleoverflow     The moodleoverflow record
-     * @param \context_module $context            The moodleoverflow context
+     * @param context_module  $context            The moodleoverflow context
      * @param string          $fields             Requested user fields
      * @param boolean         $includediscussions Whether to take discussion subscriptions into consideration
      *
@@ -641,8 +644,8 @@ public static function reset_moodleoverflow_cache() {
      * Adds user to the subscriber list.
      *
      * @param int             $userid         The user ID
-     * @param \stdClass       $moodleoverflow The moodleoverflow record
-     * @param \context_module $context        The module context
+     * @param stdClass       $moodleoverflow The moodleoverflow record
+     * @param context_module $context        The module context
      * @param bool            $userrequest    Whether the user requested this change themselves.
      *
      * @return bool|int Returns true if the user is already subscribed or the subscription id if successfully subscribed.
@@ -656,7 +659,7 @@ public static function subscribe_user($userid, $moodleoverflow, $context, $userr
         }
 
         // Create a new subscription object.
-        $sub = new \stdClass();
+        $sub = new stdClass();
         $sub->userid = $userid;
         $sub->moodleoverflow = $moodleoverflow->id;
 
@@ -706,8 +709,8 @@ public static function subscribe_user($userid, $moodleoverflow, $context, $userr
      * Removes user from the subscriber list.
      *
      * @param int             $userid         The user ID.
-     * @param \stdClass       $moodleoverflow The moodleoverflow record
-     * @param \context_module $context        The module context
+     * @param stdClass       $moodleoverflow The moodleoverflow record
+     * @param context_module $context        The module context
      * @param boolean         $userrequest    Whether the user requested this change themselves.
      *
      * @return bool Always returns true
@@ -761,9 +764,10 @@ public static function unsubscribe_user($userid, $moodleoverflow, $context, $use
     /**
      * Subscribes the user to the specified discussion.
      *
+     * TODO: Refactor this function to the new way of working with discussion and posts.
      * @param int             $userid     The user ID
-     * @param \stdClass       $discussion The discussion record
-     * @param \context_module $context    The module context
+     * @param stdClass       $discussion The discussion record
+     * @param context_module $context    The module context
      *
      * @return bool Whether a change was made
      */
@@ -807,7 +811,7 @@ public static function subscribe_user_to_discussion($userid, $discussion, $conte
 
             } else {
                 // Else a new record needs to be created.
-                $subscription = new \stdClass();
+                $subscription = new stdClass();
                 $subscription->userid = $userid;
                 $subscription->moodleoverflow = $discussion->moodleoverflow;
                 $subscription->discussion = $discussion->id;
@@ -836,9 +840,9 @@ public static function subscribe_user_to_discussion($userid, $discussion, $conte
     /**
      * Unsubscribes the user from the specified discussion.
      *
-     * @param int             $userid     The user ID
-     * @param \stdClass       $discussion The discussion record
-     * @param \context_module $context    The context module
+     * @param int            $userid     The user ID
+     * @param stdClass       $discussion The discussion record
+     * @param context_module $context    The context module
      *
      * @return bool Whether a change was made
      */
@@ -886,7 +890,7 @@ public static function unsubscribe_user_from_discussion($userid, $discussion, $c
                 // There is no record.
 
                 // Create a new discussion subscription record.
-                $subscription = new \stdClass();
+                $subscription = new stdClass();
                 $subscription->userid = $userid;
                 $subscription->moodleoverflow = $discussion->moodleoverflow;
                 $subscription->discussion = $discussion->id;
@@ -985,10 +989,11 @@ public static function moodleoverflow_get_subscribe_link($moodleoverflow, $conte
     /**
      * Given a new post, subscribes the user to the thread the post was posted in.
      *
+     * TODO: Refactor this function to the new way of working with discussion and posts.
      * @param object $fromform       The submitted form
-     * @param \stdClass       $moodleoverflow The moodleoverflow record
-     * @param \stdClass       $discussion     The discussion record
-     * @param \context_module $modulecontext  The context of the module
+     * @param stdClass       $moodleoverflow The moodleoverflow record
+     * @param stdClass       $discussion     The discussion record
+     * @param context_module $modulecontext  The context of the module
      *
      * @return bool
      */
diff --git a/db/access.php b/db/access.php
index cfa4c6e2fe..1ea6074738 100644
--- a/db/access.php
+++ b/db/access.php
@@ -22,7 +22,7 @@
  * the module version number should be bumped up.
  *
  * The system has four possible values for a capability:
- * CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT, and inherit (not set).
+ * CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT, and inherit (not set].
  *
  * It is important that capability names are unique. The naming convention
  * for capabilities that are specific to modules and blocks is as follows:
diff --git a/db/messages.php b/db/messages.php
index 24a0c7f6a0..ee2af9a367 100644
--- a/db/messages.php
+++ b/db/messages.php
@@ -25,7 +25,6 @@
 defined('MOODLE_INTERNAL') || die();
 
 $messageproviders = [
-
     // Ordinary single moodleoverflow posts.
     'posts' => [],
 ];
diff --git a/db/upgrade.php b/db/upgrade.php
index 8b1595fe16..6c8488b0c9 100644
--- a/db/upgrade.php
+++ b/db/upgrade.php
@@ -264,8 +264,7 @@ function xmldb_moodleoverflow_upgrade($oldversion) {
         $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
         $table->add_key('courseid', XMLDB_KEY_FOREIGN, ['courseid'], 'course', ['id']);
         $table->add_key('forumid', XMLDB_KEY_FOREIGN, ['forumid'], 'moodleoverflow', ['id']);
-        $table->add_key('forumdiscussionid', XMLDB_KEY_FOREIGN,
-                         ['forumdiscussionid'], 'moodleoverflow_discussions', ['id']);
+        $table->add_key('forumdiscussionid', XMLDB_KEY_FOREIGN, ['forumdiscussionid'], 'moodleoverflow_discussions', ['id']);
 
         // Conditionally launch create table for moodleoverflow_mail_info.
         if (!$dbman->table_exists($table)) {
diff --git a/externallib.php b/externallib.php
index 6427bbfcbb..c56375b6ed 100644
--- a/externallib.php
+++ b/externallib.php
@@ -39,6 +39,7 @@
  */
 class mod_moodleoverflow_external extends external_api {
 
+    // TODO: Adapt the functions to the new way of working with posts.
     /**
      * Returns description of method parameters
      * @return external_function_parameters
@@ -54,7 +55,7 @@ public static function record_vote_parameters() {
 
     /**
      * Returns the result of the vote (new rating and reputations).
-     * @return external_multiple_structure
+     * @return external_single_structure
      */
     public static function record_vote_returns() {
         return new external_single_structure(
diff --git a/index.php b/index.php
index 979e43a7f1..33ff3ebe2d 100644
--- a/index.php
+++ b/index.php
@@ -27,6 +27,8 @@
 
 require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
 require_once(dirname(__FILE__) . '/locallib.php');
+
+global $CFG, $USER, $DB, $PAGE, $SESSION, $OUTPUT;
 require_once($CFG->dirroot . '/course/lib.php');
 
 // Fetch submitted parameters.
@@ -57,9 +59,7 @@
 unset($SESSION->fromdiscussion);
 
 // Trigger the course module instace lise viewed evewnt.
-$params = [
-    'context' => context_course::instance($course->id),
-];
+$params = ['context' => context_course::instance($course->id)];
 $event = \mod_moodleoverflow\event\course_module_instance_list_viewed::create($params);
 $event->add_record_snapshot('course', $course);
 $event->trigger();
diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php
index bed611c5b3..11283ba3ae 100644
--- a/lang/en/moodleoverflow.php
+++ b/lang/en/moodleoverflow.php
@@ -124,7 +124,7 @@
 $string['maxmailingtime'] = 'Maximal mailing time';
 $string['configmaxmailingtime'] = 'Posts older than this number of hours will not be mailed to the users. This will help to avoid problems where the cron has not been running for a long time.';
 
-// Strings for the post.php.
+// Strings for the post.php environment.
 $string['invalidmoodleoverflowid'] = 'Forum ID was incorrect';
 $string['invalidparentpostid'] = 'Parent post ID was incorrect';
 $string['notpartofdiscussion'] = 'This post is not part of a discussion!';
@@ -144,11 +144,19 @@
 $string['couldnotupdate'] = 'Could not update your post due to an unknown error';
 $string['editedpostupdated'] = '{$a}\'s post was updated';
 $string['postupdated'] = 'Your post was updated';
-$string['editedby'] = 'Edited by {$a->name} - original submission {$a->date}';
+$string['editedby'] = 'Edited by {$a->name} on {$a->date}';
 $string['cannotdeletepost'] = 'You can\'t delete this post!';
 $string['couldnotdeletereplies'] = 'Sorry, that cannot be deleted as people have already responded to it';
 $string['errorwhiledelete'] = 'An error occurred while deleting record.';
 $string['couldnotdeletereplies'] = 'Sorry, that cannot be deleted as people have already responded to it';
+$string['noexistingpost'] = 'Post does not exists, needs to be created first';
+$string['noexistingdiscussion'] = 'Discussion does not exists, needs to be created first';
+$string['notallpostsavailable'] = 'This Discussion does not have all of its posts, this could lead to errors!';
+$string['missingformattachments'] = 'This functions requires data that was not submitted.';
+$string['unexpectedinteractionerror'] = 'An unexpected error occured, please try again';
+
+// String for the classes/post/post_control.php.
+$string['wronginteraction'] = 'Wrong interaction detected, please choose the right function';
 
 // Strings for the classes/mod_form.php.
 $string['subject'] = 'Subject';
@@ -175,6 +183,7 @@
 $string['notstartuser'] = 'Only the user who started the discussion can mark an answer as helpful.';
 $string['notteacher'] = 'Only course owners can do this.';
 $string['ratingtoold'] = 'Ratings can only be changed within 30 minutes after the first vote. ';
+$string['postnotpartofdiscussion'] = 'Post does not exist in this discussion, please check the parameter';
 
 // Strings for the discussion.php.
 $string['invaliddiscussionid'] = 'Discussion ID was incorrect';
diff --git a/lib.php b/lib.php
index 8a0e2627a0..fabcaa79e2 100644
--- a/lib.php
+++ b/lib.php
@@ -29,6 +29,7 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+// TODO: Adapt functions to the new way of working with posts and discussions (Replace the post/discussion functions).
 use core\context\course;
 
 defined('MOODLE_INTERNAL') || die();
@@ -345,7 +346,7 @@ function moodleoverflow_print_recent_activity($course, $viewfullnames, $timestar
 /**
  * Returns all other caps used in the module.
  *
- * For example, this could be array('moodle/site:accessallgroups') if the
+ * For example, this could be ['moodle/site:accessallgroups'] if the
  * module uses that capability.
  *
  * @return array
diff --git a/locallib.php b/locallib.php
index bd60ab4e0c..ba08224720 100644
--- a/locallib.php
+++ b/locallib.php
@@ -513,8 +513,8 @@ function moodleoverflow_count_discussion_replies($cm) {
 }
 
 /**
+ * TODO: Delete this function when adapting the print-functions to the new post and discussion structure.
  * Check if the user is capable of starting a new discussion.
- *
  * @param object $moodleoverflow
  * @param object $cm
  * @param object $context
@@ -523,7 +523,7 @@ function moodleoverflow_count_discussion_replies($cm) {
  */
 function moodleoverflow_user_can_post_discussion($moodleoverflow, $cm = null, $context = null) {
 
-    // Guests an not-logged-in users can not psot.
+    // Guests an not-logged-in users can not post.
     if (isguestuser() || !isloggedin()) {
         return false;
     }
@@ -643,7 +643,11 @@ function moodleoverflow_get_post_full($postid) {
 
     if ($CFG->branch >= 311) {
         $allnames = \core_user\fields::for_name()->get_sql('u', false, '', '', false)->selects;
+    } else if ($CFG->branch > 309) {
+        $allnames = implode(', ', fields::get_name_fields());
     } else {
+        // TODO: remove this else branch when support for version 3.9 ends and replace the else if branch with 'else' only.
+        // Note that get_all_user_name_fields is a deprecated function and should not be used in newer versions.
         $allnames = get_all_user_name_fields(true, 'u');
     }
     $sql = "SELECT p.*, d.moodleoverflow, $allnames, u.email, u.picture, u.imagealt
@@ -906,6 +910,7 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr
 
 /**
  * Prints a moodleoverflow discussion.
+ * TODO: REFACTOR WITH NEW POST AND DISCUSSION STRUCTURE.
  *
  * @param stdClass $course         The course object
  * @param object   $cm
@@ -915,7 +920,8 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr
  * @param bool     $multiplemarks  The setting of multiplemarks (default: multiplemarks are not allowed)
  */
 function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $multiplemarks = false) {
-    global $USER;
+    global $USER, $DB;
+
     // Check if the current is the starter of the discussion.
     $ownpost = (isloggedin() && ($USER->id == $post->userid));
 
@@ -926,6 +932,7 @@ function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discuss
     $istracked = readtracking::moodleoverflow_is_tracked($moodleoverflow);
 
     // Retrieve all posts of the discussion.
+    // This part is adapted/refactored to the new way of working with posts (use of get_id() function and discussion object).
     $posts = moodleoverflow_get_all_discussion_posts($discussion->id, $istracked, $modulecontext);
     $usermapping = anonymous::get_userid_mapping($moodleoverflow, $discussion->id);
 
@@ -1093,6 +1100,8 @@ function moodleoverflow_get_all_discussion_posts($discussionid, $tracking, $modc
 
 
 /**
+ *
+ * TODO: REFACTOR THIS FUNCTION FOR THE NEW POST STRUCTURE.
  * Prints a moodleoverflow post.
  * @param object $post
  * @param object $discussion
@@ -1120,7 +1129,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co
                                    $footer = '', $highlight = '', $postisread = null,
                                    $dummyifcantsee = true, $istracked = false,
                                    $iscomment = false, $usermapping = [], $level = 0, $multiplemarks = false) {
-    global $USER, $CFG, $OUTPUT, $PAGE;
+    global $USER, $CFG, $OUTPUT, $PAGE, $DB;
 
     // Require the filelib.
     require_once($CFG->libdir . '/filelib.php');
@@ -1545,6 +1554,7 @@ function moodleoverflow_print_posts_nested($course, &$cm, $moodleoverflow, $disc
 }
 
 /**
+ * TODO: Delete this function after adapting the print_post function to the new post structure
  * Returns attachments with information for the template
  *
  * @param object $post
@@ -1626,6 +1636,7 @@ function moodleoverflow_add_attachment($post, $forum, $cm) {
 }
 
 /**
+ * WARNING: this function is only used in the lib.php. For other uses this function is deprecated.
  * Adds a new post in an existing discussion.
  * @param object $post The post object
  * @return bool|int The Id of the post if operation was successful
@@ -1678,87 +1689,6 @@ function moodleoverflow_add_new_post($post) {
     return $post->id;
 }
 
-/**
- * Updates a specific post.
- *
- * Capabilities are not checked, because this is happening in the post.php.
- *
- * @param object $newpost The new post object
- *
- * @return bool Whether the update was successful
- */
-function moodleoverflow_update_post($newpost) {
-    global $DB, $USER;
-
-    // Retrieve not submitted variables.
-    $post = $DB->get_record('moodleoverflow_posts', ['id' => $newpost->id]);
-    $discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $post->discussion]);
-    $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $discussion->moodleoverflow]);
-
-    // Allowed modifiable fields.
-    $modifiablefields = [
-        'message',
-        'messageformat',
-    ];
-
-    // Iteratate through all modifiable fields and update the values.
-    foreach ($modifiablefields as $field) {
-        if (isset($newpost->{$field})) {
-            $post->{$field} = $newpost->{$field};
-        }
-    }
-
-    $post->modified = time();
-    if ($newpost->reviewed ?? $post->reviewed) {
-        // Update the date and the user of the post and the discussion.
-        $discussion->timemodified = $post->modified;
-        $discussion->usermodified = $post->userid;
-    }
-
-    // When editing the starting post of a discussion.
-    if (!$post->parent) {
-        $discussion->name = $newpost->subject;
-    }
-
-    // Update the post and the corresponding discussion.
-    $DB->update_record('moodleoverflow_posts', $post);
-    $DB->update_record('moodleoverflow_discussions', $discussion);
-
-    $cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id);
-    moodleoverflow_add_attachment($newpost, $moodleoverflow, $cm);
-
-    // Mark the edited post as read.
-    $cantrack = readtracking::moodleoverflow_can_track_moodleoverflows($moodleoverflow);
-    $istracked = readtracking::moodleoverflow_is_tracked($moodleoverflow);
-    if ($cantrack && $istracked) {
-        readtracking::moodleoverflow_mark_post_read($USER->id, $post);
-    }
-
-    // The post has been edited successfully.
-    return true;
-}
-
-/**
- * Count all replies of a post.
- *
- * @param object $post The post object
- * @param bool $onlyreviewed Whether to count only reviewed posts.
- *
- * @return int Amount of replies
- */
-function moodleoverflow_count_replies($post, $onlyreviewed) {
-    global $DB;
-
-    $conditions = ['parent' => $post->id];
-
-    if ($onlyreviewed) {
-        $conditions['reviewed'] = '1';
-    }
-
-    // Return the amount of replies.
-    return $DB->count_records('moodleoverflow_posts', $conditions);
-}
-
 /**
  * Deletes a discussion and handles all associated cleanups.
  *
@@ -1887,6 +1817,7 @@ function moodleoverflow_delete_post($post, $deletechildren, $cm, $moodleoverflow
 }
 
 /**
+ * WARNING: this function is only used in the lib.php. For other uses this function is deprecated.
  * Sets the last post for a given discussion.
  *
  * @param int $discussionid The discussion ID
diff --git a/post.php b/post.php
index 303ba6223c..57757b7560 100644
--- a/post.php
+++ b/post.php
@@ -15,49 +15,32 @@
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * The file to manage posts.
+ * The file that is opened in Moodle when the user interacts with posts
  *
  * @package   mod_moodleoverflow
- * @copyright 2017 Kennet Winter <k_wint10@uni-muenster.de>
+ * @copyright 2023 Tamaro Walter
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-// TODO refactor this. For more readability, and to avoid security issues.
-
-// Include config and locallib.
-use mod_moodleoverflow\anonymous;
+use mod_moodleoverflow\post\post_control;
 use mod_moodleoverflow\review;
 
 require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
-global $CFG, $USER, $DB, $PAGE, $SESSION, $OUTPUT;
 require_once(dirname(__FILE__) . '/locallib.php');
+
+global $CFG, $USER, $DB, $PAGE, $SESSION, $OUTPUT;
 require_once($CFG->libdir . '/completionlib.php');
 
-// Declare optional parameters.
+// Declare optional url parameters.
 $moodleoverflow = optional_param('moodleoverflow', 0, PARAM_INT);
 $reply = optional_param('reply', 0, PARAM_INT);
 $edit = optional_param('edit', 0, PARAM_INT);
 $delete = optional_param('delete', 0, PARAM_INT);
 $confirm = optional_param('confirm', 0, PARAM_INT);
 
-$count = 0;
-$count += $moodleoverflow ? 1 : 0;
-$count += $reply ? 1 : 0;
-$count += $edit ? 1 : 0;
-$count += $delete ? 1 : 0;
-
-if ($count !== 1) {
-    throw new coding_exception('Exactly one parameter should be specified!');
-}
-
 // Set the URL that should be used to return to this page.
-$PAGE->set_url('/mod/moodleoverflow/post.php', [
-    'moodleoverflow' => $moodleoverflow,
-    'reply' => $reply,
-    'edit' => $edit,
-    'delete' => $delete,
-    'confirm' => $confirm,
-]);
+$PAGE->set_url('/mod/moodleoverflow/post.php', ['moodleoverflow' => $moodleoverflow, 'reply' => $reply, 'edit' => $edit,
+                                                      'delete' => $delete, 'confirm' => $confirm, ]);
 
 // These params will be passed as hidden variables later in the form.
 $pageparams = ['moodleoverflow' => $moodleoverflow, 'reply' => $reply, 'edit' => $edit];
@@ -65,739 +48,105 @@
 // Get the system context instance.
 $systemcontext = context_system::instance();
 
-// Catch guests.
-if (!isloggedin() || isguestuser()) {
-
-    // The user is starting a new discussion in a moodleoverflow instance.
-    if (!empty($moodleoverflow)) {
-
-        // Check the moodleoverflow instance is valid.
-        if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow])) {
-            throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow');
-        }
-
-        // The user is replying to an existing moodleoverflow discussion.
-    } else if (!empty($reply)) {
+// Create a post_control object to control and lead the process.
+$postcontrol = new post_control();
 
-        // Check if the related post exists.
-        if (!$parent = moodleoverflow_get_post_full($reply)) {
-            throw new moodle_exception('invalidparentpostid', 'moodleoverflow');
-        }
-
-        // Check if the post is part of a valid discussion.
-        if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $parent->discussion])) {
-            throw new moodle_exception('notpartofdiscussion', 'moodleoverflow');
-        }
+// Put all interaction parameters in one object for the post_control.
+$urlparameter = new \stdClass();
+$urlparameter->create = $moodleoverflow;
+$urlparameter->reply = $reply;
+$urlparameter->edit = $edit;
+$urlparameter->delete = $delete;
 
-        // Check if the post is related to a valid moodleoverflow instance.
-        if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $discussion->moodleoverflow])) {
-            throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow');
-        }
-    }
-
-    // Get the related course.
-    if (!$course = $DB->get_record('course', ['id' => $moodleoverflow->course])) {
-        throw new moodle_exception('invalidcourseid');
-    }
-
-    // Get the related coursemodule and its context.
-    if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) {
-        throw new moodle_exception('invalidcoursemodule');
-    }
-
-    // Get the context of the module.
-    $modulecontext = context_module::instance($cm->id);
-
-    // Set parameters for the page.
-    $PAGE->set_cm($cm, $course, $moodleoverflow);
-    $PAGE->set_context($modulecontext);
-    $PAGE->set_title($course->shortname);
-    $PAGE->set_heading($course->fullname);
-
-    // The page should not be large, only pages containing broad tables are usually.
-    $PAGE->add_body_class('limitedwidth');
+// Catch guests.
+if (!isloggedin() || isguestuser()) {
+    // Gather information and set the page right so that user can be redirected to the right site.
+    $information = $postcontrol->catch_guest();
 
     // The guest needs to login.
-    echo $OUTPUT->header();
     $strlogin = get_string('noguestpost', 'forum') . '<br /><br />' . get_string('liketologin');
-    echo $OUTPUT->confirm($strlogin, get_login_url(), $CFG->wwwroot . '/mod/moodleoverflow/view.php?m=' . $moodleoverflow->id);
+    echo $OUTPUT->header();
+    echo $OUTPUT->confirm($strlogin, get_login_url(),
+                          $CFG->wwwroot . '/mod/moodleoverflow/view.php?m= ' . $information->moodleoverflow->id);
     echo $OUTPUT->footer();
     exit;
 }
 
-// First step: A general login is needed to post something.
+// Require a general login to post something.
+// TODO: should course or id really be zero?.
 require_login(0, false);
 
-// First possibility: User is starting a new discussion in a moodleoverflow instance.
-if (!empty($moodleoverflow)) {
-
-    // Check the moodleoverflow instance is valid.
-    if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow])) {
-        throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow');
-    }
-
-    // Get the related course.
-    if (!$course = $DB->get_record('course', ['id' => $moodleoverflow->course])) {
-        throw new moodle_exception('invalidcourseid');
-    }
-
-    // Get the related coursemodule.
-    if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) {
-        throw new moodle_exception('invalidcoursemodule');
-    }
-
-    // Retrieve the contexts.
-    $modulecontext = context_module::instance($cm->id);
-    $coursecontext = context_course::instance($course->id);
-
-    // Check if the user can start a new discussion.
-    if (!moodleoverflow_user_can_post_discussion($moodleoverflow, $cm, $modulecontext)) {
-
-        // Catch unenrolled user.
-        if (!isguestuser() && !is_enrolled($coursecontext)) {
-            if (enrol_selfenrol_available($course->id)) {
-                $SESSION->wantsurl = qualified_me();
-                $SESSION->enrolcancel = get_local_referer(false);
-                redirect(new moodle_url('/enrol/index.php', [
-                    'id' => $course->id,
-                    'returnurl' => '/mod/moodleoverflow/view.php?m=' . $moodleoverflow->id,
-                ]), get_string('youneedtoenrol'));
-            }
-        }
-
-        // Notify the user, that he can not post a new discussion.
-        throw new moodle_exception('nopostmoodleoverflow', 'moodleoverflow');
-    }
-
-    // Where is the user coming from?
-    $SESSION->fromurl = get_local_referer(false);
-
-    // Load all the $post variables.
-    $post = new stdClass();
-    $post->course = $course->id;
-    $post->moodleoverflow = $moodleoverflow->id;
-    $post->discussion = 0;
-    $post->parent = 0;
-    $post->subject = '';
-    $post->userid = $USER->id;
-    $post->message = '';
-
-    // Unset where the user is coming from.
-    // Allows to calculate the correct return url later.
-    unset($SESSION->fromdiscussion);
-
-} else if (!empty($reply)) {
-    // Second possibility: The user is writing a new reply.
-
-    // Check if the post exists.
-    if (!$parent = moodleoverflow_get_post_full($reply)) {
-        throw new moodle_exception('invalidparentpostid', 'moodleoverflow');
-    }
-
-    // Check if the post is part of a discussion.
-    if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $parent->discussion])) {
-        throw new moodle_exception('notpartofdiscussion', 'moodleoverflow');
-    }
-
-    // Check if the discussion is part of a moodleoverflow instance.
-    if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $discussion->moodleoverflow])) {
-        throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow');
-    }
-
-    // Check if the moodleoverflow instance is part of a course.
-    if (!$course = $DB->get_record('course', ['id' => $discussion->course])) {
-        throw new moodle_exception('invalidcourseid');
-    }
-
-    // Retrieve the related coursemodule.
-    if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) {
-        throw new moodle_exception('invalidcoursemodule');
-    }
-
-    // Ensure the coursemodule is set correctly.
-    $PAGE->set_cm($cm, $course, $moodleoverflow);
-
-    // Retrieve the other contexts.
-    $modulecontext = context_module::instance($cm->id);
-    $coursecontext = context_course::instance($course->id);
-
-    // Check whether the user is allowed to post.
-    if (!moodleoverflow_user_can_post($modulecontext, $parent)) {
-
-        // Give the user the chance to enroll himself to the course.
-        if (!isguestuser() && !is_enrolled($coursecontext)) {
-            $SESSION->wantsurl = qualified_me();
-            $SESSION->enrolcancel = get_local_referer(false);
-            redirect(new moodle_url('/enrol/index.php',
-                ['id' => $course->id, 'returnurl' => '/mod/moodleoverflow/view.php?m=' . $moodleoverflow->id]),
-                get_string('youneedtoenrol'));
-        }
-
-        // Print the error message.
-        throw new moodle_exception('nopostmoodleoverflow', 'moodleoverflow');
-    }
-
-    // Make sure the user can post here.
-    if (!$cm->visible && !has_capability('moodle/course:viewhiddenactivities', $modulecontext)) {
-        throw new moodle_exception('activityiscurrentlyhidden');
-    }
-
-    // Load the $post variable.
-    $post = new stdClass();
-    $post->course = $course->id;
-    $post->moodleoverflow = $moodleoverflow->id;
-    $post->discussion = $parent->discussion;
-    $post->parent = $parent->id;
-    $post->subject = $discussion->name;
-    $post->userid = $USER->id;
-    $post->message = '';
-
-    // Append 'RE: ' to the discussions subject.
-    $strre = get_string('re', 'moodleoverflow');
-    if (!(substr($post->subject, 0, strlen($strre)) == $strre)) {
-        $post->subject = $strre . ' ' . $post->subject;
-    }
-
-    // Unset where the user is coming from.
-    // Allows to calculate the correct return url later.
-    unset($SESSION->fromdiscussion);
-
-
-} else if (!empty($edit)) {
-    // Third possibility: The user is editing his own post.
-
-    // Check if the submitted post exists.
-    if (!$post = moodleoverflow_get_post_full($edit)) {
-        throw new moodle_exception('invalidpostid', 'moodleoverflow');
-    }
-
-    // Get the parent post of this post if it is not the starting post of the discussion.
-    if ($post->parent) {
-        if (!$parent = moodleoverflow_get_post_full($post->parent)) {
-            throw new moodle_exception('invalidparentpostid', 'moodleoverflow');
-        }
-    }
-
-    // Check if the post refers to a valid discussion.
-    if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $post->discussion])) {
-        throw new moodle_exception('notpartofdiscussion', 'moodleoverflow');
-    }
-
-    // Check if the post refers to a valid moodleoverflow instance.
-    if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $discussion->moodleoverflow])) {
-        throw new moodle_exception('invalidmoodleoverflowid', 'moodleoverflow');
-    }
-
-    // Check if the post refers to a valid course.
-    if (!$course = $DB->get_record('course', ['id' => $discussion->course])) {
-        throw new moodle_exception('invalidcourseid');
-    }
-
-    // Retrieve the related coursemodule.
-    if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) {
-        throw new moodle_exception('invalidcoursemodule');
-    } else {
-        $modulecontext = context_module::instance($cm->id);
-    }
-
-    // Set the pages context.
-    $PAGE->set_cm($cm, $course, $moodleoverflow);
-
-    // Check if the post can be edited.
-    $beyondtime = ((time() - $post->created) > get_config('moodleoverflow', 'maxeditingtime'));
-    $alreadyreviewed = review::should_post_be_reviewed($post, $moodleoverflow) && $post->reviewed;
-    if (($beyondtime || $alreadyreviewed) && !has_capability('mod/moodleoverflow:editanypost', $modulecontext)) {
-        throw new moodle_exception('maxtimehaspassed', 'moodleoverflow', '',
-            format_time(get_config('moodleoverflow', 'maxeditingtime')));
-    }
-
-
-
-    // If the current user is not the one who posted this post.
-    if ($post->userid <> $USER->id) {
-
-        // Check if the current user has not the capability to edit any post.
-        if (!has_capability('mod/moodleoverflow:editanypost', $modulecontext)) {
-
-            // Display the error. Capabilities are missing.
-            throw new moodle_exception('cannoteditposts', 'moodleoverflow');
-        }
-    }
-
-    // Load the $post variable.
-    $post->edit = $edit;
-    $post->course = $course->id;
-    $post->moodleoverflow = $moodleoverflow->id;
-
-    // Unset where the user is coming from.
-    // Allows to calculate the correct return url later.
-    unset($SESSION->fromdiscussion);
-
-} else if (!empty($delete)) {
-    // Fourth possibility: The user is deleting a post.
-    // Check if the post is existing.
-    if (!$post = moodleoverflow_get_post_full($delete)) {
-        throw new moodle_exception('invalidpostid', 'moodleoverflow');
-    }
-
-    // Get the related discussion.
-    if (!$discussion = $DB->get_record('moodleoverflow_discussions', ['id' => $post->discussion])) {
-        throw new moodle_exception('notpartofdiscussion', 'moodleoverflow');
-    }
-
-    // Get the related moodleoverflow instance.
-    if (!$moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $discussion->moodleoverflow])) {
-        throw new moodle_exception('invalidmoodleoverflowid', 'moodleoveflow');
-    }
-
-    // Get the related coursemodule.
-    if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $moodleoverflow->course)) {
-        throw new moodle_exception('invalidcoursemodule');
-    }
-
-    // Get the related course.
-    if (!$course = $DB->get_record('course', ['id' => $moodleoverflow->course])) {
-        throw new moodle_exception('invalidcourseid');
-    }
-
-    // Require a login and retrieve the modulecontext.
-    require_login($course, false, $cm);
-    $modulecontext = context_module::instance($cm->id);
-
-    // Check some capabilities.
-    $deleteownpost = has_capability('mod/moodleoverflow:deleteownpost', $modulecontext);
-    $deleteanypost = has_capability('mod/moodleoverflow:deleteanypost', $modulecontext);
-    if (!(($post->userid == $USER->id && $deleteownpost) || $deleteanypost)) {
-        throw new moodle_exception('cannotdeletepost', 'moodleoverflow');
-    }
-
-    // Count all replies of this post.
-    $replycount = moodleoverflow_count_replies($post, false);
+// Now the post_control checks which interaction is wanted and builds a prepost.
+$postcontrol->detect_interaction($urlparameter);
 
+// If a post is being deleted, delete it immediately.
+if ($postcontrol->get_interaction() == 'delete') {
     // Has the user confirmed the deletion?
     if (!empty($confirm) && confirm_sesskey()) {
-
-        // Check if the user has the capability to delete the post.
-        $timepassed = time() - $post->created;
-        if (($timepassed > get_config('moodleoverflow', 'maxeditingtime')) && !$deleteanypost) {
-            $url = new moodle_url('/mod/moodleoverflow/discussion.php', ['d' => $post->discussion]);
-            throw new moodle_exception('cannotdeletepost', 'moodleoverflow', moodleoverflow_go_back_to($url));
-        }
-
-        // A normal user cannot delete his post if there are direct replies.
-        if ($replycount && !$deleteanypost) {
-            $url = new moodle_url('/mod/moodleoverflow/discussion.php', ['d' => $post->discussion]);
-            throw new moodle_exception('couldnotdeletereplies', 'moodleoverflow', moodleoverflow_go_back_to($url));
-        } else {
-            // Delete the post.
-
-            // The post is the starting post of a discussion. Delete the topic as well.
-            if (!$post->parent) {
-                moodleoverflow_delete_discussion($discussion, $course, $cm, $moodleoverflow);
-
-                // Trigger the discussion deleted event.
-                $params = [
-                    'objectid' => $discussion->id,
-                    'context' => $modulecontext,
-                ];
-
-                $event = \mod_moodleoverflow\event\discussion_deleted::create($params);
-                $event->trigger();
-
-                // Redirect the user back to start page of the moodleoverflow instance.
-                redirect("view.php?m=$discussion->moodleoverflow");
-                exit;
-
-            } else if (moodleoverflow_delete_post($post, $deleteanypost, $cm, $moodleoverflow)) {
-                // Delete a single post.
-                // Redirect back to the discussion.
-                $discussionurl = new moodle_url('/mod/moodleoverflow/discussion.php', ['d' => $discussion->id]);
-                redirect(moodleoverflow_go_back_to($discussionurl));
-                exit;
-
-            } else {
-                // Something went wrong.
-                throw new moodle_exception('errorwhiledelete', 'moodleoverflow');
-            }
-        }
+        $postcontrol->execute_delete();
     } else {
         // Deletion needs to be confirmed.
-
-        moodleoverflow_set_return();
-        $PAGE->navbar->add(get_string('delete', 'moodleoverflow'));
-        $PAGE->set_title($course->shortname);
-        $PAGE->set_heading($course->fullname);
-
-        // The page should not be large, only pages containing broad tables are usually.
-        $PAGE->add_body_class('limitedwidth');
-
-        // Check if there are replies for the post.
-        if ($replycount) {
-
-            // Check if the user has capabilities to delete more than one post.
-            if (!$deleteanypost) {
-                throw new moodle_exception('couldnotdeletereplies', 'moodleoverflow',
-                    moodleoverflow_go_back_to(new moodle_url('/mod/moodleoverflow/discussion.php',
-                        ['d' => $post->discussion, 'p' . $post->id])));
-            }
-
-            // Request a confirmation to delete the post.
-            echo $OUTPUT->header();
-            echo $OUTPUT->confirm(get_string("deletesureplural", "moodleoverflow", $replycount + 1),
-                "post.php?delete=$delete&confirm=$delete", $CFG->wwwroot . '/mod/moodleoverflow/discussion.php?d=' .
-                $post->discussion . '#p' . $post->id);
-
+        $postcontrol->confirm_delete();
+
+        // Display a confirmation request depending on the number of posts that are being deleted.
+        $information = $postcontrol->get_information();
+        echo $OUTPUT->header();
+        if ($information->deletetype == 'plural') {
+            echo $OUTPUT->confirm(get_string('deletesureplural', 'moodleoverflow', $information->replycount + 1),
+                                  'post.php?delete='.$delete.'&confirm='.$delete,
+                                  $CFG->wwwroot . '/mod/moodleoverflow/discussion.php?d=' . $information->discussion->get_id() .
+                                   '#p' . $information->relatedpost->get_id());
         } else {
-            // Delete a single post.
-
-            // Print a confirmation message.
-            echo $OUTPUT->header();
-            echo $OUTPUT->confirm(get_string("deletesure", "moodleoverflow", $replycount),
+            echo $OUTPUT->confirm(get_string('deletesure', 'moodleoverflow', $information->replycount),
                 "post.php?delete=$delete&confirm=$delete",
-                $CFG->wwwroot . '/mod/moodleoverflow/discussion.php?d=' . $post->discussion . '#p' . $post->id);
+                $CFG->wwwroot . '/mod/moodleoverflow/discussion.php?d=' . $information->discussion->get_id() .
+                 '#p' . $information->relatedpost->get_id());
         }
+        echo $OUTPUT->footer();
     }
-    echo $OUTPUT->footer();
     exit;
-
-} else {
-    // Last posibility: the action is not known.
-
-    throw new moodle_exception('unknownaction');
 }
 
-// Second step: The user must be logged on properly. Must be enrolled to the course as well.
-require_login($course, false, $cm);
+// A post will be created or edited. For that the post_control builds a post_form.
+$mformpost = $postcontrol->build_postform($pageparams);
 
-// Get the contexts.
-$modulecontext = context_module::instance($cm->id);
-$coursecontext = context_course::instance($course->id);
-
-// Get the subject.
-if ($edit) {
-    $subject = $discussion->name;
-} else if ($reply) {
-    $subject = $post->subject;
-} else if ($moodleoverflow) {
-    $subject = $post->subject;
-}
+// The User now entered information in the form. The post.php now needs to process the information and call the right function.
 
-// Get attachments.
-$draftitemid = file_get_submitted_draft_itemid('attachments');
-file_prepare_draft_area($draftitemid,
-    $modulecontext->id,
-    'mod_moodleoverflow',
-    'attachment',
-    empty($post->id) ? null : $post->id,
-    mod_moodleoverflow_post_form::attachment_options($moodleoverflow));
+// Get attributes from the postcontrol.
+$information = $postcontrol->get_information();
+$prepost = $postcontrol->get_prepost();
 
-if ($draftitemid && $edit && anonymous::is_post_anonymous($discussion, $moodleoverflow, $post->userid)
-    && $post->userid != $USER->id) {
-
-    $usercontext = context_user::instance($USER->id);
-    $anonymousstr = get_string('anonymous', 'moodleoverflow');
-    foreach (get_file_storage()->get_area_files($usercontext->id, 'user', 'draft', $draftitemid) as $file) {
-        $file->set_author($anonymousstr);
-    }
-}
-
-// Prepare the form.
-$formarray = [
-    'course' => $course,
-    'cm' => $cm,
-    'coursecontext' => $coursecontext,
-    'modulecontext' => $modulecontext,
-    'moodleoverflow' => $moodleoverflow,
-    'post' => $post,
-    'edit' => $edit,
-];
-$mformpost = new mod_moodleoverflow_post_form('post.php', $formarray, 'post', '', ['id' => 'mformmoodleoverflow']);
-
-// The current user is not the original author.
-// Append the message to the end of the message.
-if ($USER->id != $post->userid) {
-
-    // Create a temporary object.
-    $data = new stdClass();
-    $data->date = userdate($post->modified);
-    $post->messageformat = editors_get_preferred_format();
-
-    // Append the message depending on the messages format.
-    if ($post->messageformat == FORMAT_HTML) {
-        $data->name = '<a href="' . $CFG->wwwroot . '/user/view.php?id' . $USER->id .
-            '&course=' . $post->course . '">' . fullname($USER) . '</a>';
-        $post->message .= '<p><span class="edited">(' . get_string('editedby', 'moodleoverflow', $data) . ')</span></p>';
-    } else {
-        $data->name = fullname($USER);
-        $post->message .= "\n\n(" . get_string('editedby', 'moodleoverflow', $data) . ')';
-    }
-
-    // Delete the temporary object.
-    unset($data);
-}
-
-// Define the heading for the form.
-$formheading = '';
-if (!empty($parent)) {
-    $heading = get_string('yourreply', 'moodleoverflow');
-    $formheading = get_string('reply', 'moodleoverflow');
-} else {
-    $heading = get_string('yournewtopic', 'moodleoverflow');
-}
-
-// Get the original post.
-$postid = empty($post->id) ? null : $post->id;
-$postmessage = empty($post->message) ? null : $post->message;
-
-// Set data for the form.
-// TODO Refactor.
-$param1 = (isset($discussion->id) ? [$discussion->id] : []);
-$param2 = (isset($post->format) ? ['format' => $post->format] : []);
-$param3 = (isset($discussion->timestart) ? ['timestart' => $discussion->timestart] : []);
-$param4 = (isset($discussion->timeend) ? ['timeend' => $discussion->timeend] : []);
-$param5 = (isset($discussion->id) ? ['discussion' => $discussion->id] : []);
-$mformpost->set_data([
-        'attachments' => $draftitemid,
-        'general' => $heading,
-        'subject' => $subject,
-        'message' => [
-            'text' => $postmessage,
-            'format' => editors_get_preferred_format(),
-            'itemid' => $postid,
-        ],
-        'userid' => $post->userid,
-        'parent' => $post->parent,
-        'discussion' => $post->discussion,
-        'course' => $course->id,
-    ] + $pageparams + $param1 + $param2 + $param3 + $param4 + $param5);
-
-// Is it canceled?
+// If the interaction was cancelled, the user needs to be redirected.
 if ($mformpost->is_cancelled()) {
-
-    // Redirect the user back.
-    if (!isset($discussion->id)) {
-        redirect(new moodle_url('/mod/moodleoverflow/view.php', ['m' => $moodleoverflow->id]));
+    if (!isset($prepost->discussionid)) {
+        redirect(new moodle_url('/mod/moodleoverflow/view.php', ['m' => $prepost->moodleoverflowid]));
     } else {
-        redirect(new moodle_url('/mod/moodleoverflow/discussion.php', ['d' => $discussion->id]));
+        redirect(new moodle_url('/mod/moodleoverflow/discussion.php', ['d' => $prepost->discussionid]));
     }
-
-    // Cancel.
-    exit();
+    exit;
 }
 
-// Is it submitted?
+// If the post_form is submitted, the post_control executes the right function.
 if ($fromform = $mformpost->get_data()) {
-
-    // Redirect url in case of occuring errors.
-    if (empty($SESSION->fromurl)) {
-        $errordestination = "$CFG->wwwroot/mod/moodleoverflow/view.php?m=$moodleoverflow->id";
-    } else {
-        $errordestination = $SESSION->fromurl;
-    }
-
-    // Format the submitted data.
-    $fromform->messageformat = $fromform->message['format'];
-    $fromform->message = $fromform->message['text'];
-    $fromform->messagetrust = trusttext_trusted($modulecontext);
-
-    // If we are updating a post.
-    if ($fromform->edit) {
-
-        // Initiate some variables.
-        unset($fromform->groupid);
-        $fromform->id = $fromform->edit;
-        $message = '';
-
-        // The FORUM-Plugin had an bug: https://tracker.moodle.org/browse/MDL-4314
-        // This is a fix for it.
-        if (!$realpost = $DB->get_record('moodleoverflow_posts', ['id' => $fromform->id])) {
-            $realpost = new stdClass();
-            $realpost->userid = -1;
-        }
-
-        // Check the capabilities of the user.
-        // He may proceed if he can edit any post or if he has the startnewdiscussion
-        // capability or the capability to reply and is editing his own post.
-        $editanypost = has_capability('mod/moodleoverflow:editanypost', $modulecontext);
-        $replypost = has_capability('mod/moodleoverflow:replypost', $modulecontext);
-        $startdiscussion = has_capability('mod/moodleoverflow:startdiscussion', $modulecontext);
-        $ownpost = ($realpost->userid == $USER->id);
-        if (!(($ownpost && ($replypost || $startdiscussion)) || $editanypost)) {
-            throw new moodle_exception('cannotupdatepost', 'moodleoverflow');
-        }
-
-        // Update the post or print an error message.
-        $updatepost = $fromform;
-        $updatepost->moodleoverflow = $moodleoverflow->id;
-        if (!moodleoverflow_update_post($updatepost, $mformpost)) {
-            throw new moodle_exception('couldnotupdate', 'moodleoverflow', $errordestination);
-        }
-
-        // Create a success-message.
-        if ($realpost->userid == $USER->id) {
-            $message .= get_string('postupdated', 'moodleoverflow');
-        } else {
-            if (anonymous::is_post_anonymous($discussion, $moodleoverflow, $realpost->userid)) {
-                $name = get_string('anonymous', 'moodleoverflow');
-            } else {
-                $realuser = $DB->get_record('user', ['id' => $realpost->userid]);
-                $name = fullname($realuser);
-            }
-            $message .= get_string('editedpostupdated', 'moodleoverflow', $name);
-        }
-
-        // Create a link to go back to the discussion.
-        $discussionurl = new moodle_url('/mod/moodleoverflow/discussion.php', ['d' => $discussion->id], 'p' . $fromform->id);
-
-        // Set some parameters.
-        $params = [
-            'context' => $modulecontext,
-            'objectid' => $fromform->id,
-            'other' => [
-                'discussionid' => $discussion->id,
-                'moodleoverflowid' => $moodleoverflow->id,
-            ], ];
-
-        // If the editing user is not the original author, add the original author to the params.
-        if ($realpost->userid != $USER->id) {
-            $params['relateduserid'] = $realpost->userid;
-        }
-
-        // Trigger post updated event.
-        $event = \mod_moodleoverflow\event\post_updated::create($params);
-        $event->trigger();
-
-        // Redirect back to the discussion.
-        redirect(moodleoverflow_go_back_to($discussionurl), $message, null, \core\output\notification::NOTIFY_SUCCESS);
-
-        // Cancel.
-        exit;
-
-    } else if ($fromform->discussion) {
-        // Add a new post to an existing discussion.
-
-        // Set some basic variables.
-        unset($fromform->groupid);
-        $message = '';
-        $addpost = $fromform;
-        $addpost->moodleoverflow = $moodleoverflow->id;
-
-        // Create the new post.
-        if ($fromform->id = moodleoverflow_add_new_post($addpost)) {
-
-            // Subscribe to this thread.
-            $discussion = new \stdClass();
-            $discussion->id = $fromform->discussion;
-            $discussion->moodleoverflow = $moodleoverflow->id;
-            \mod_moodleoverflow\subscriptions::moodleoverflow_post_subscription($fromform,
-                $moodleoverflow, $discussion, $modulecontext);
-
-            // Print a success-message.
-            $message .= '<p>' . get_string("postaddedsuccess", "moodleoverflow") . '</p>';
-            $message .= '<p>' . get_string("postaddedtimeleft", "moodleoverflow",
-                    format_time(get_config('moodleoverflow', 'maxeditingtime'))) . '</p>';
-
-            // Set the URL that links back to the discussion.
-            $link = '/mod/moodleoverflow/discussion.php';
-            $discussionurl = new moodle_url($link, ['d' => $discussion->id], 'p' . $fromform->id);
-
-            // Trigger post created event.
-            $params = [
-                'context' => $modulecontext,
-                'objectid' => $fromform->id,
-                'other' => [
-                    'discussionid' => $discussion->id,
-                    'moodleoverflowid' => $moodleoverflow->id,
-                ], ];
-            $event = \mod_moodleoverflow\event\post_created::create($params);
-            $event->trigger();
-            redirect(
-                moodleoverflow_go_back_to($discussionurl),
-                $message,
-                \core\output\notification::NOTIFY_SUCCESS
-            );
-
-            // Print an error if the answer could not be added.
-        } else {
-            throw new moodle_exception('couldnotadd', 'moodleoverflow', $errordestination);
-        }
-
-        // The post has been added.
-        exit;
-
-    } else {
-        // Add a new discussion.
-
-        // The location to redirect the user after successfully posting.
-        $redirectto = new moodle_url('view.php', ['m' => $fromform->moodleoverflow]);
-
-        $discussion = $fromform;
-        $discussion->name = $fromform->subject;
-
-        // Check if the user is allowed to post here.
-        if (!moodleoverflow_user_can_post_discussion($moodleoverflow)) {
-            throw new moodle_exception('cannotcreatediscussion', 'moodleoverflow');
-        }
-
-        // Check if the creation of the new discussion failed.
-        if (!$discussion->id = moodleoverflow_add_discussion($discussion, $modulecontext)) {
-
-            throw new moodle_exception('couldnotadd', 'moodleoverflow', $errordestination);
-
-        } else {    // The creation of the new discussion was successful.
-
-            $params = [
-                'context' => $modulecontext,
-                'objectid' => $discussion->id,
-                'other' => [
-                    'moodleoverflowid' => $moodleoverflow->id,
-                ],
-            ];
-
-            $message = '<p>' . get_string("postaddedsuccess", "moodleoverflow") . '</p>';
-
-            // Trigger the discussion created event.
-            $params = [
-                'context' => $modulecontext,
-                'objectid' => $discussion->id,
-            ];
-            $event = \mod_moodleoverflow\event\discussion_created::create($params);
-            $event->trigger();
-            // Subscribe to this thread.
-            $discussion->moodleoverflow = $moodleoverflow->id;
-            \mod_moodleoverflow\subscriptions::moodleoverflow_post_subscription($fromform,
-                $moodleoverflow, $discussion, $modulecontext);
-        }
-
-        // Redirect back to te discussion.
-        redirect(moodleoverflow_go_back_to($redirectto->out()), $message, null, \core\output\notification::NOTIFY_SUCCESS);
-
-        // Do not continue.
-        exit;
-    }
+    $postcontrol->execute_interaction($fromform);
+    exit;
 }
 
 // If the script gets to this point, nothing has been submitted.
-// We have to display the form.
-// $course and $moodleoverflow are defined.
-// $discussion is only used for replying and editing.
+// The post_form will be displayed.
 
 // Define the message to be displayed above the form.
-$toppost = new stdClass();
-$toppost->subject = get_string("addanewdiscussion", "moodleoverflow");
+$toppost = new \stdClass();
+$toppost->subject = get_string('addanewdiscussion', 'moodleoverflow');
 
 // Initiate the page.
-$PAGE->set_title("$course->shortname: $moodleoverflow->name " . format_string($toppost->subject));
-$PAGE->set_heading($course->fullname);
-
-// The page should not be large, only pages containing broad tables are usually.
+$PAGE->set_title($information->course->shortname . ': ' .
+                 $information->moodleoverflow->name . ' ' .
+                 format_string($toppost->subject));
+$PAGE->set_heading($information->course->fullname);
 $PAGE->add_body_class('limitedwidth');
 
-// Display the header.
+// Display all.
 echo $OUTPUT->header();
-
-// Display the form.
 $mformpost->display();
-
-// Display the footer.
 echo $OUTPUT->footer();
diff --git a/tests/discussion_test.php b/tests/discussion_test.php
new file mode 100644
index 0000000000..0a536ebfcb
--- /dev/null
+++ b/tests/discussion_test.php
@@ -0,0 +1,162 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * PHP Unit Tests for the Discussion class.
+ * @package   mod_moodleoverflow
+ * @copyright 2023 Tamaro Walter
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_moodleoverflow;
+
+use mod_moodleoverflow\post\post;
+use mod_moodleoverflow\discussion\discussion;
+
+/**
+ * Tests if the functions from the discussion class are working correctly.
+ * As the discussion class works as an administrator of the post class, most of the testcases are already realized in the
+ * post_test.php file.
+ * @package   mod_moodleoverflow
+ * @copyright 2023 Tamaro Walter
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @covers \mod_moodleoverflow\discussion\discussion
+ */
+class discussion_test extends \advanced_testcase {
+
+    /** @var \stdClass test course */
+    private $course;
+
+    /** @var \stdClass coursemodule */
+    private $coursemodule;
+
+    /** @var \stdClass modulecontext */
+    private $modulecontext;
+
+    /** @var \stdClass test moodleoverflow */
+    private $moodleoverflow;
+
+    /** @var \stdClass test teacher */
+    private $teacher;
+
+    /** @var discussion a discussion */
+    private $discussion;
+
+    /** @var post the post from the discussion */
+    private $post;
+
+    /** @var \mod_moodleoverflow_generator $generator */
+    private $generator;
+
+    public function setUp(): void {
+        $this->resetAfterTest();
+        $this->helper_course_set_up();
+    }
+
+    public function tearDown(): void {
+        // Clear all caches.
+        subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_discussion_cache();
+    }
+
+    /**
+     * Test, if a discussion is being created correctly
+     */
+    public function test_create_discussion(): void {
+        global $DB;
+
+        // Build a prepost object with important information.
+        $time = time();
+        $prepost = new \stdClass();
+        $prepost->userid = $this->teacher->id;
+        $prepost->timenow = $time;
+        $prepost->message = 'a message';
+        $prepost->messageformat = 1;
+        $prepost->reviewed = 0;
+        $prepost->formattachments = '';
+        $prepost->modulecontext = $this->modulecontext;
+
+        // Build a new discussion object.
+        $discussion = discussion::construct_without_id($this->course->id, $this->moodleoverflow->id, 'Discussion Topic',
+                                           0, $this->teacher->id, $time, $time, $this->teacher->id);
+        $discussionid = $discussion->moodleoverflow_add_discussion($prepost);
+        $posts = $discussion->moodleoverflow_get_discussion_posts();
+        $post = $posts[$discussion->get_firstpostid()];
+
+        // The discussion and the firstpost should be in the DB.
+        $dbdiscussion = $DB->get_record('moodleoverflow_discussions', ['id' => $discussion->get_id()]);
+        $this->assertEquals($dbdiscussion->id, $discussionid);
+        $this->assertEquals('Discussion Topic', $dbdiscussion->name);
+
+        $dbpost = $DB->get_record('moodleoverflow_posts', ['id' => $discussion->get_firstpostid()]);
+        $this->assertEquals($dbpost->id, $post->get_id());
+        $this->assertEquals($dbpost->discussion, $post->get_discussionid());
+        $this->assertEquals($prepost->message, $dbpost->message);
+    }
+
+    /**
+     * Test, if a post and its attachment are deleted successfully.
+     * @covers ::moodleoverflow_delete_post
+     */
+    public function test_delete_discussion(): void {
+        global $DB;
+        // Build the prepost object with necessary information.
+        $prepost = new \stdClass();
+        $prepost->modulecontext = $this->modulecontext;
+
+        // Delete the discussion, but save the IDs first.
+        $discussionid = $this->discussion->get_id();
+        $postid = $this->discussion->get_firstpostid();
+        $this->discussion->moodleoverflow_delete_discussion($prepost);
+
+        // The discussion and the post should not be in the DB anymore.
+        $discussion = count($DB->get_records('moodleoverflow_discussions', ['id' => $discussionid]));
+        $this->assertEquals(0, $discussion);
+
+        $post = count($DB->get_records('moodleoverflow_posts', ['id' => $postid]));
+        $this->assertEquals(0, $post);
+    }
+
+    /**
+     * This function creates:
+     * - a course with a moodleoverflow
+     * - a new discussion with a post. The post has an attachment.
+     */
+    private function helper_course_set_up() {
+        global $DB;
+        // Create a new course with a moodleoverflow forum.
+        $this->course = $this->getDataGenerator()->create_course();
+        $location = ['course' => $this->course->id];
+        $this->moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $location);
+        $this->coursemodule = get_coursemodule_from_instance('moodleoverflow', $this->moodleoverflow->id);
+        $this->modulecontext = \context_module::instance($this->coursemodule->id);
+
+        // Create a teacher.
+        $this->teacher = $this->getDataGenerator()->create_user(['firstname' => 'Tamaro', 'lastname' => 'Walter']);
+        $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, 'student');
+
+        // Create a discussion started from the teacher.
+        $this->generator = $this->getDataGenerator()->get_plugin_generator('mod_moodleoverflow');
+        $discussion = $this->generator->post_to_forum($this->moodleoverflow, $this->teacher);
+
+        // Get the discussion and post object.
+        $discussionrecord = $DB->get_record('moodleoverflow_discussions', ['id' => $discussion[0]->id]);
+        $postrecord = $DB->get_record('moodleoverflow_posts', ['id' => $discussion[1]->id]);
+
+        $this->discussion = discussion::from_record($discussionrecord);
+        $this->post = post::from_record($postrecord);
+    }
+}
diff --git a/tests/post_test.php b/tests/post_test.php
index b29614c879..d2e62d5948 100644
--- a/tests/post_test.php
+++ b/tests/post_test.php
@@ -15,7 +15,7 @@
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * PHP Unit test for post related functions in the locallib.
+ * PHP Unit Tests for the Post class.
  *
  * @package   mod_moodleoverflow
  * @copyright 2023 Tamaro Walter
@@ -23,15 +23,21 @@
  */
 namespace mod_moodleoverflow;
 
+// Use the post class.
+use mod_moodleoverflow\post\post;
+use mod_moodleoverflow\discussion\discussion;
+
 defined('MOODLE_INTERNAL') || die();
 require_once(__DIR__ . '/../locallib.php');
 
 /**
- * PHP Unit test for post related functions in the locallib.
+ *
+ * Tests if the functions from the post class are working correctly.
  *
  * @package   mod_moodleoverflow
  * @copyright 2023 Tamaro Walter
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @covers \mod_moodleoverflow\post\post
  */
 class post_test extends \advanced_testcase {
 
@@ -41,25 +47,24 @@ class post_test extends \advanced_testcase {
     /** @var \stdClass coursemodule */
     private $coursemodule;
 
+    /** @var \stdClass modulecontext */
+    private $modulecontext;
+
     /** @var \stdClass test moodleoverflow */
     private $moodleoverflow;
 
     /** @var \stdClass test teacher */
     private $teacher;
 
-    /** @var \stdClass a discussion */
+    /** @var discussion a discussion */
     private $discussion;
 
-    /** @var \stdClass a post */
+    /** @var post a post */
     private $post;
 
-    /** @var \stdClass an attachment */
-    private $attachment;
-
     /** @var \mod_moodleoverflow_generator $generator */
     private $generator;
 
-
     public function setUp(): void {
         $this->resetAfterTest();
         $this->helper_course_set_up();
@@ -67,46 +72,78 @@ public function setUp(): void {
 
     public function tearDown(): void {
         // Clear all caches.
-        \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache();
-        \mod_moodleoverflow\subscriptions::reset_discussion_cache();
+        subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_discussion_cache();
     }
 
     /**
-     * Test if a post and its attachment are deleted successfully.
-     * @covers ::moodleoverflow_delete_post
+     * Test, if a post is being created correctly
      */
-    public function test_moodleoverflow_delete_post(): void {
+    public function test_create_post(): void {
+        global $DB;
+        // Build a new post object.
+        $time = time();
+        $message = 'a unique message';
+        $post = post::construct_without_id($this->discussion->get_id(), $this->post->get_id(), $this->teacher->id, $time,
+                                           $time, $message, 0, '', 0, 1, null);
+        $post->moodleoverflow_add_new_post();
+
+        // The post should be in the database.
+        $postscount = count($DB->get_records('moodleoverflow_posts', ['id' => $post->get_id()]));
+        $this->assertEquals(1, $postscount);
+    }
+
+    /**
+     * Test, if the message of a post can be edited successfully.
+     */
+    public function test_edit_post(): void {
         global $DB;
 
-        // The attachment should exist.
-        $numberofattachments = count($DB->get_records('files', ['itemid' => $this->post->id]));
-        $this->assertEquals(2, $numberofattachments);
+        // The post and the attachment should exist.
+        $numberofattachments = count($DB->get_records('files', ['itemid' => $this->post->get_id()]));
+        $this->assertEquals(2, $numberofattachments); // One Attachment is saved twice in 'files'.
+        $post = count($DB->get_records('moodleoverflow_posts', ['id' => $this->post->get_id()]));
+        $this->assertEquals(1, $post);
 
-        // Delete the post from the teacher with its attachment.
-        moodleoverflow_delete_post($this->post, false, $this->coursemodule, $this->moodleoverflow);
+        // Gather important parameters.
+        $message = 'a new message';
 
-        // Now try to get the attachment.
-        $numberofattachments = count($DB->get_records('files', ['itemid' => $this->post->id]));
+        $time = time();
 
-        $this->assertEquals(0, $numberofattachments);
+        // Update the post.
+        $this->post->moodleoverflow_edit_post($time, $message, $this->post->messageformat, $this->post->formattachments);
+
+        // The message and modified time should be changed.
+        $post = $DB->get_record('moodleoverflow_posts', ['id' => $this->post->get_id()]);
+        $this->assertEquals($message,  $post->message);
+        $this->assertEquals($time, $post->modified);
     }
 
     /**
-     * Test if a post and its attachment are deleted successfully.
-     * @covers ::moodleoverflow_delete_discussion
+     * Test, if a post and its attachment are deleted successfully.
+     * @covers ::moodleoverflow_delete_post
      */
-    public function test_moodleoverflow_delete_discussion(): void {
+    public function test_moodleoverflow_delete_post(): void {
         global $DB;
 
-        $numberofattachments = count($DB->get_records('files', ['itemid' => $this->post->id, 'filearea' => 'attachment']));
-        $this->assertEquals(2, $numberofattachments);
+        // The post and the attachment should exist.
+        $numberofattachments = count($DB->get_records('files', ['itemid' => $this->post->get_id()]));
+        $this->assertEquals(2, $numberofattachments); // One Attachment is saved twice in 'files'.
+        $post = count($DB->get_records('moodleoverflow_posts', ['id' => $this->post->get_id()]));
+        $this->assertEquals(1, $post);
 
-        // Delete the post from the teacher with its attachment.
-        moodleoverflow_delete_discussion($this->discussion[0], $this->course, $this->coursemodule, $this->moodleoverflow);
+        // Delete the post with its attachment.
+        // Save the post id as it gets unsettled by the post object after being deleted.
+        $postid = $this->post->get_id();
+        $this->post->moodleoverflow_delete_post(true);
 
-        // Now try to get the attachment.
-        $numberofattachments = count($DB->get_records('files', ['itemid' => $this->post->id]));
+        // Now try to get the attachment, it should be deleted from the database.
+        $numberofattachments = count($DB->get_records('files', ['itemid' => $postid]));
         $this->assertEquals(0, $numberofattachments);
+
+        // Try to find the post, it should be deleted.
+        $post = count($DB->get_records('moodleoverflow_posts', ['id' => $postid]));
+        $this->assertEquals(0, $post);
     }
 
     /**
@@ -121,6 +158,7 @@ private function helper_course_set_up() {
         $location = ['course' => $this->course->id];
         $this->moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $location);
         $this->coursemodule = get_coursemodule_from_instance('moodleoverflow', $this->moodleoverflow->id);
+        $this->modulecontext = \context_module::instance($this->coursemodule->id);
 
         // Create a teacher.
         $this->teacher = $this->getDataGenerator()->create_user(['firstname' => 'Tamaro', 'lastname' => 'Walter']);
@@ -128,29 +166,40 @@ private function helper_course_set_up() {
 
         // Create a discussion started from the teacher.
         $this->generator = $this->getDataGenerator()->get_plugin_generator('mod_moodleoverflow');
-        $this->discussion = $this->generator->post_to_forum($this->moodleoverflow, $this->teacher);
-        $this->post = $DB->get_record('moodleoverflow_posts', ['id' => $this->discussion[0]->firstpost], '*');
+        $discussion = $this->generator->post_to_forum($this->moodleoverflow, $this->teacher);
+        $discussionrecord = $DB->get_record('moodleoverflow_discussions', ['id' => $discussion[0]->id]);
+        $this->discussion = discussion::from_record($discussionrecord);
+
+        // Get a temporary post from the DB to add the attachment.
+        $temppost = $DB->get_record('moodleoverflow_posts', ['id' => $this->discussion->get_firstpostid()]);
 
         // Create an attachment by inserting it directly in the database and update the post record.
+        $this->add_new_attachment($temppost, $this->modulecontext, 'world.txt', 'hello world');
 
-        $modulecontext = \context_module::instance($this->coursemodule->id);
+        // Build the real post object now. That is the object that will be tested.
+        $postrecord = $DB->get_record('moodleoverflow_posts', ['id' => $this->discussion->get_firstpostid()]);
+        $this->post = post::from_record($postrecord);
+    }
 
+    /**
+     * @param object $object // The object that will have the attachment
+     * @param $modulecontext
+     * @param string $filename
+     * @param $filecontent
+     * @return void
+     */
+    private function add_new_attachment($object, $modulecontext, $filename, $filecontent) {
+        global $DB;
         $fileinfo = [
-            'contextid' => $modulecontext->id,   // ID of the context.
-            'component' => 'mod_moodleoverflow', // Your component name.
-            'filearea'  => 'attachment',       // Usually = table name.
-            'itemid'    => $this->post->id,              // Usually = ID of row in table.
-            'filepath'  => '/',            // Any path beginning and ending in /.
-            'filename'  => 'NH.jpg',   // Any filename.
+            'contextid' => $modulecontext->id,           // ID of the context.
+            'component' => 'mod_moodleoverflow',               // Your component name.
+            'filearea'  => 'attachment',                       // Usually = table name.
+            'itemid'    => $object->id,                      // Usually = ID of the item (e.g. the post.
+            'filepath'  => '/',                                // Any path beginning and ending in /.
+            'filename'  => $filename,                      // Any filename.
         ];
-
         $fs = get_file_storage();
-
-        // Create a new file containing the text 'hello world'.
-        $fs->create_file_from_string($fileinfo, 'hello world');
-
-        $this->post->attachment = 1;
-        $DB->update_record('moodleoverflow_posts', $this->post);
-
+        $fs->create_file_from_string($fileinfo, $filecontent); // Creates a new file containing the text 'hello world'.
+        $DB->update_record('moodleoverflow_posts', $object);
     }
 }
diff --git a/tests/ratings_test.php b/tests/ratings_test.php
index f0dccc267b..5792913d4e 100644
--- a/tests/ratings_test.php
+++ b/tests/ratings_test.php
@@ -23,6 +23,7 @@
  */
 namespace mod_moodleoverflow;
 use mod_moodleoverflow\ratings;
+use stdClass;
 
 defined('MOODLE_INTERNAL') || die();
 
@@ -38,46 +39,46 @@
  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 class ratings_test extends \advanced_testcase {
-    /** @var \stdClass test course */
+    /** @var stdClass test course */
     private $course;
 
-    /** @var \stdClass coursemodule */
+    /** @var stdClass coursemodule */
     private $coursemodule;
 
-    /** @var \stdClass test moodleoverflow */
+    /** @var stdClass test moodleoverflow */
     private $moodleoverflow;
 
-    /** @var \stdClass test teacher */
+    /** @var stdClass test teacher */
     private $teacher;
 
-    /** @var \stdClass test user */
+    /** @var stdClass test user */
     private $user1;
 
-    /** @var \stdClass another test user */
+    /** @var stdClass another test user */
     private $user2;
 
-    /** @var \stdClass a discussion */
+    /** @var stdClass a discussion */
     private $discussion;
 
-    /** @var \stdClass a post from the teacher*/
+    /** @var stdClass a post from the teacher*/
     private $post;
 
-    /** @var \stdClass answer from user 1 */
+    /** @var stdClass answer from user 1 */
     private $answer1;
 
-    /** @var \stdClass answer from user 1 */
+    /** @var stdClass answer from user 1 */
     private $answer2;
 
-    /** @var \stdClass answer from user 1 */
+    /** @var stdClass answer from user 1 */
     private $answer3;
 
-    /** @var \stdClass answer from user 2 */
+    /** @var stdClass answer from user 2 */
     private $answer4;
 
-    /** @var \stdClass answer from user 2 */
+    /** @var stdClass answer from user 2 */
     private $answer5;
 
-    /** @var \stdClass answer from user 2 */
+    /** @var stdClass answer from user 2 */
     private $answer6;
 
     /** @var \mod_moodleoverflow_generator $generator */
diff --git a/tests/subscriptions_test.php b/tests/subscriptions_test.php
index 2de58cf8b2..9e0061c90c 100644
--- a/tests/subscriptions_test.php
+++ b/tests/subscriptions_test.php
@@ -45,8 +45,8 @@ class subscriptions_test extends advanced_testcase {
      */
     public function setUp(): void {
         // Clear all caches.
-        \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache();
-        \mod_moodleoverflow\subscriptions::reset_discussion_cache();
+        subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_discussion_cache();
     }
 
     /**
@@ -54,8 +54,8 @@ public function setUp(): void {
      */
     public function tearDown(): void {
         // Clear all caches.
-        \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache();
-        \mod_moodleoverflow\subscriptions::reset_discussion_cache();
+        subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_discussion_cache();
     }
 
     /**
@@ -129,34 +129,34 @@ public function test_subscription_modes(): void {
         $this->setUser($user);
 
         // Test the forced subscription.
-        \mod_moodleoverflow\subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_FORCESUBSCRIBE);
+        subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_FORCESUBSCRIBE);
         $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id]);
         $this->assertEquals(MOODLEOVERFLOW_FORCESUBSCRIBE,
-            \mod_moodleoverflow\subscriptions::get_subscription_mode($moodleoverflow));
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_forcesubscribed($moodleoverflow));
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $modulecontext));
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::subscription_disabled($moodleoverflow));
+            subscriptions::get_subscription_mode($moodleoverflow));
+        $this->assertTrue(subscriptions::is_forcesubscribed($moodleoverflow));
+        $this->assertFalse(subscriptions::is_subscribable($moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::subscription_disabled($moodleoverflow));
 
         // Test the disallowed subscription.
-        \mod_moodleoverflow\subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_DISALLOWSUBSCRIBE);
+        subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_DISALLOWSUBSCRIBE);
         $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id]);
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::subscription_disabled($moodleoverflow));
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $modulecontext));
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_forcesubscribed($moodleoverflow));
+        $this->assertTrue(subscriptions::subscription_disabled($moodleoverflow));
+        $this->assertFalse(subscriptions::is_subscribable($moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::is_forcesubscribed($moodleoverflow));
 
         // Test the initial subscription.
-        \mod_moodleoverflow\subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_INITIALSUBSCRIBE);
+        subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_INITIALSUBSCRIBE);
         $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id]);
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $modulecontext));
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::subscription_disabled($moodleoverflow));
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_forcesubscribed($moodleoverflow));
+        $this->assertTrue(subscriptions::is_subscribable($moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::subscription_disabled($moodleoverflow));
+        $this->assertFalse(subscriptions::is_forcesubscribed($moodleoverflow));
 
         // Test the choose subscription.
-        \mod_moodleoverflow\subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_CHOOSESUBSCRIBE);
+        subscriptions::set_subscription_mode($moodleoverflow->id, MOODLEOVERFLOW_CHOOSESUBSCRIBE);
         $moodleoverflow = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id]);
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow, $modulecontext));
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::subscription_disabled($moodleoverflow));
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_forcesubscribed($moodleoverflow));
+        $this->assertTrue(subscriptions::is_subscribable($moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::subscription_disabled($moodleoverflow));
+        $this->assertFalse(subscriptions::is_forcesubscribed($moodleoverflow));
     }
 
     /**
@@ -182,7 +182,7 @@ public function test_unsubscribable_moodleoverflows(): void {
         $this->setUser($user);
 
         // Without any subscriptions, there should be nothing returned.
-        $result = \mod_moodleoverflow\subscriptions::get_unsubscribable_moodleoverflows();
+        $result = subscriptions::get_unsubscribable_moodleoverflows();
         $this->assertEquals(0, count($result));
 
         // Create the moodleoverflows.
@@ -196,15 +196,15 @@ public function test_unsubscribable_moodleoverflows(): void {
         $this->getDataGenerator()->create_module('moodleoverflow', $options);
 
         // At present the user is only subscribed to the initial moodleoverflow.
-        $result = \mod_moodleoverflow\subscriptions::get_unsubscribable_moodleoverflows();
+        $result = subscriptions::get_unsubscribable_moodleoverflows();
         $this->assertEquals(1, count($result));
 
         // Ensure that the user is enrolled in all of the moodleoverflows execpt force subscribe.
-        \mod_moodleoverflow\subscriptions::subscribe_user($user->id, $disallow, $modulecontext);
-        \mod_moodleoverflow\subscriptions::subscribe_user($user->id, $choose, $modulecontext);
+        subscriptions::subscribe_user($user->id, $disallow, $modulecontext);
+        subscriptions::subscribe_user($user->id, $choose, $modulecontext);
 
         // At present the user  is subscribed to all three moodleoverflows.
-        $result = \mod_moodleoverflow\subscriptions::get_unsubscribable_moodleoverflows();
+        $result = subscriptions::get_unsubscribable_moodleoverflows();
         $this->assertEquals(3, count($result));
     }
 
@@ -236,11 +236,11 @@ public function test_moodleoverflow_toggle_as_other(): void {
         $discussion->moodleoverflow = $moodleoverflow->id;
 
         // Check that the user is currently not subscribed to the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow,
             $modulecontext));
 
         // Check that the user is unsubscribed from the discussion too.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow,
             $modulecontext, $discussion->id));
 
         // Check thast we have no records in either on the subscription tables.
@@ -253,7 +253,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
 
         // Subscribing to the moodleoverflow should create a record in the subscription table,
         // but the moodleoverflow discussion subscriptions table.
-        \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
+        subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(1, $count);
@@ -263,7 +263,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
 
         // Unsubscribing should remove the record from the moodleoverflow subscription table.
         // Do not modify the moodleoverflow discussion subscriptions table.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext);
+        subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(0, $count);
@@ -273,7 +273,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
 
         // Enroling the user in the discussion should add one record to the
         // moodleoverflow discussion table without modifying the form subscription.
-        \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(0, $count);
@@ -283,7 +283,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
 
         // Unsubscribing should remove the record from the moodleoverflow subscriptions
         // table and not modify the moodleoverflow discussion subscription table.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
         $options = ['userid' => $author->id, 'discussion' => $discussion->id];
         $count = $DB->count_records('moodleoverflow_discuss_subs', $options);
         $this->assertEquals(0, $count);
@@ -292,7 +292,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
         $this->assertEquals(0, $count);
 
         // Resubscribe to the discussion so that we can check the effect of moodleoverflow-level subscriptions.
-        \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
         $options = ['userid' => $author->id, 'discussion' => $discussion->id];
         $count = $DB->count_records('moodleoverflow_discuss_subs', $options);
         $this->assertEquals(1, $count);
@@ -302,7 +302,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
 
         // Subscribing to the moodleoverflow should have no effect on the moodleoverflow discussion
         // subscription table if the user did not request the change himself.
-        \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
+        subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(1, $count);
@@ -312,7 +312,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
 
         // Unsubbing from the moodleoverflow should have no effect on the moodleoverflow
         // discussion subscription table if the user did not request the change themself.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext);
+        subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(0, $count);
@@ -322,7 +322,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
 
         // Subscribing to the moodleoverflow should remove the per-discussion
         // subscription preference if the user requested the change themself.
-        \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext, true);
+        subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext, true);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(1, $count);
@@ -331,7 +331,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
         $this->assertEquals(0, $count);
 
         // Now unsubscribe from the current discussion whilst being subscribed to the moodleoverflow as a whole.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(1, $count);
@@ -341,7 +341,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
 
         // Unsubscribing from the moodleoverflow should remove the per-discussion
         // subscription preference if the user requested the change himself.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext, true);
+        subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext, true);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(0, $count);
@@ -352,7 +352,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
         $this->assertEquals(0, $count);
 
         // Subscribe to the discussion.
-        \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(0, $count);
@@ -363,7 +363,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
         $this->assertEquals(1, $count);
 
         // Subscribe to the moodleoverflow without removing the discussion preferences.
-        \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
+        subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(1, $count);
@@ -372,7 +372,7 @@ public function test_moodleoverflow_toggle_as_other(): void {
         $this->assertEquals(1, $count);
 
         // Unsubscribe from the discussion should result in a change.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
         $options = ['userid' => $author->id, 'moodleoverflow' => $moodleoverflow->id];
         $count = $DB->count_records('moodleoverflow_subscriptions', $options);
         $this->assertEquals(1, $count);
@@ -397,14 +397,14 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_unsub
         list($author) = $this->helper_create_users($course, 1);
 
         // Check that the user is currently not subscribed to the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow));
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow));
 
         // Post a discussion to the moodleoverflow.
         list($discussion, $post) = $this->helper_post_to_moodleoverflow($moodleoverflow, $author);
         unset($post);
 
         // Check that the user is unsubscribed from the discussion too.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow,
             $moodleoverflow, $discussion));
     }
 
@@ -429,21 +429,21 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_subsc
 
         // Enrol the user in the moodleoverflow.
         // If a subscription was added, we get the record ID.
-        $this->assertIsInt(\mod_moodleoverflow\subscriptions::subscribe_user($author->id,
+        $this->assertIsInt(subscriptions::subscribe_user($author->id,
             $moodleoverflow, $modulecontext));
 
         // If we already have a subscription when subscribing the user, we get a boolean (true).
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext));
 
         // Check that the user is currently subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // Post a discussion to the moodleoverflow.
         list($discussion, $post) = $this->helper_post_to_moodleoverflow($moodleoverflow, $author);
         unset($post);
 
         // Check that the user is subscribed to the discussion too.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion));
     }
 
@@ -467,7 +467,7 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_unsub
         list($author) = $this->helper_create_users($course, 1);
 
         // Check that the user is currently not subscribed to the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow));
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow));
 
         // Post a discussion to the moodleoverflow.
         $discussion = new \stdClass();
@@ -476,18 +476,18 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_unsub
         $discussion->moodleoverflow = $moodleoverflow->id;
 
         // Attempting to unsubscribe from the discussion should not make a change.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id,
+        $this->assertFalse(subscriptions::unsubscribe_user_from_discussion($author->id,
             $discussion, $modulecontext));
 
         // Then subscribe them to the discussion.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id,
+        $this->assertTrue(subscriptions::subscribe_user_to_discussion($author->id,
             $discussion, $modulecontext));
 
         // Check that the user is still unsubscribed from the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow));
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $moodleoverflow));
 
         // But subscribed to the discussion.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
     }
 
@@ -511,10 +511,10 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_subsc
         list($author) = $this->helper_create_users($course, 2);
 
         // Enrol the student in the moodleoverflow.
-        \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
+        subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
 
         // Check that the user is currently subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // Post a discussion to the moodleoverflow.
         $discussion = new \stdClass();
@@ -523,13 +523,13 @@ public function test_moodleoverflow_discussion_subscription_moodleoverflow_subsc
         $discussion->moodleoverflow = $moodleoverflow->id;
 
         // Then unsubscribe them from the discussion.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
 
         // Check that the user is still subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // But unsubscribed from the discussion.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
     }
 
@@ -554,7 +554,7 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         list($author) = $this->helper_create_users($course, 2);
 
         // Enrol the student in the moodleoverflow.
-        \mod_moodleoverflow\subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
+        subscriptions::subscribe_user($author->id, $moodleoverflow, $modulecontext);
 
         // Post a discussion to the moodleoverflow.
         $discussion = new \stdClass();
@@ -563,14 +563,14 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         $discussion->moodleoverflow = $moodleoverflow->id;
 
         // Check that the user is currently subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // Check that the user is initially subscribed to that discussion.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // An attempt to subscribe again should result in a falsey return to indicate that no change was made.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id,
+        $this->assertFalse(subscriptions::subscribe_user_to_discussion($author->id,
             $discussion, $modulecontext));
 
         // And there should be no discussion subscriptions (and one moodleoverflow subscription).
@@ -582,13 +582,13 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         $this->assertEquals(1, $count);
 
         // Then unsubscribe them from the discussion.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
 
         // Check that the user is still subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // An attempt to unsubscribe again should result in a falsey return to indicate that no change was made.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id,
+        $this->assertFalse(subscriptions::unsubscribe_user_from_discussion($author->id,
             $discussion, $modulecontext));
 
         // And there should be a discussion subscriptions (and one moodleoverflow subscription).
@@ -600,7 +600,7 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         $this->assertEquals(1, $count);
 
         // But unsubscribed from the discussion.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // There should be a record in the discussion subscription tracking table.
@@ -614,13 +614,13 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         $this->assertEquals(1, $count);
 
         // Now subscribe the user again to the discussion.
-        \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
 
         // Check that the user is still subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // And is subscribed to the discussion again.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // And one in the moodleoverflow subscription tracking table.
@@ -634,13 +634,13 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         $this->assertEquals(0, $count);
 
         // And unsubscribe again.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
 
         // Check that the user is still subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // But unsubscribed from the discussion.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // And one in the moodleoverflow subscription tracking table.
@@ -654,14 +654,14 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         $this->assertEquals(1, $count);
 
         // And subscribe the user again to the discussion.
-        \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
 
         // Check that the user is still subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // And is subscribed to the discussion again.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // There should be no record in the discussion subscription tracking table.
@@ -675,14 +675,14 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         $this->assertEquals(1, $count);
 
         // And unsubscribe again.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
 
         // But unsubscribed from the discussion.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // Check that the user is still subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // There should be a record in the discussion subscription tracking table.
         $options = ['userid' => $author->id, 'discussion' => $discussion->id];
@@ -695,7 +695,7 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         $this->assertEquals(1, $count);
 
         // Now unsubscribe the user from the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext,
+        $this->assertTrue(subscriptions::unsubscribe_user($author->id, $moodleoverflow, $modulecontext,
             true));
 
         // This removes both the moodleoverflow, and the moodleoverflow records.
@@ -707,7 +707,7 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_subscribed(
         $this->assertEquals(0, $count);
 
         // And should have reset the discussion cache value.
-        $result = \mod_moodleoverflow\subscriptions::fetch_discussion_subscription($moodleoverflow->id, $author->id);
+        $result = subscriptions::fetch_discussion_subscription($moodleoverflow->id, $author->id);
         $this->assertIsArray($result);
         $this->assertFalse(isset($result[$discussion->id]));
     }
@@ -734,7 +734,7 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_unsubscribe
         list($author) = $this->helper_create_users($course, 2);
 
         // Check that the user is currently unsubscribed to the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // Post a discussion to the moodleoverflow.
         $discussion = new \stdClass();
@@ -743,22 +743,22 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_unsubscribe
         $discussion->moodleoverflow = $moodleoverflow->id;
 
         // Check that the user is initially unsubscribed to that discussion.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // Then subscribe them to the discussion.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id,
+        $this->assertTrue(subscriptions::subscribe_user_to_discussion($author->id,
             $discussion, $modulecontext));
 
         // An attempt to subscribe again should result in a falsey return to indicate that no change was made.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id,
+        $this->assertFalse(subscriptions::subscribe_user_to_discussion($author->id,
             $discussion, $modulecontext));
 
         // Check that the user is still unsubscribed from the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // But subscribed to the discussion.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // There should be a record in the discussion subscription tracking table.
@@ -767,13 +767,13 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_unsubscribe
         $this->assertEquals(1, $count);
 
         // Now unsubscribe the user again from the discussion.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
 
         // Check that the user is still unsubscribed from the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // And is unsubscribed from the discussion again.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // There should be no record in the discussion subscription tracking table.
@@ -782,14 +782,14 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_unsubscribe
         $this->assertEquals(0, $count);
 
         // And subscribe the user again to the discussion.
-        \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::subscribe_user_to_discussion($author->id, $discussion, $modulecontext);
 
         // And is subscribed to the discussion again.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertTrue(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // Check that the user is still unsubscribed from the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // There should be a record in the discussion subscription tracking table.
         $options = ['userid' => $author->id, 'discussion' => $discussion->id];
@@ -797,14 +797,14 @@ public function test_moodleoverflow_discussion_toggle_moodleoverflow_unsubscribe
         $this->assertEquals(1, $count);
 
         // And unsubscribe again.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($author->id, $discussion, $modulecontext);
 
         // But unsubscribed from the discussion.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // Check that the user is still unsubscribed from the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::is_subscribed($author->id, $moodleoverflow, $modulecontext));
 
         // There should be no record in the discussion subscription tracking table.
         $options = ['userid' => $author->id, 'discussion' => $discussion->id];
@@ -836,22 +836,22 @@ public function test_fetch_subscribed_users_subscriptions(): void {
         $users = $this->helper_create_users($course, $usercount);
 
         // All users should be subscribed.
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
         $this->assertEquals($usercount, count($subscribers));
 
         // Subscribe the guest user too to the moodleoverflow - they should never be returned by this function.
         $this->getDataGenerator()->enrol_user($CFG->siteguest, $course->id);
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
         $this->assertEquals($usercount, count($subscribers));
 
         // Unsubscribe 2 users.
         $unsubscribedcount = 2;
         for ($i = 0; $i < $unsubscribedcount; $i++) {
-            \mod_moodleoverflow\subscriptions::unsubscribe_user($users[$i]->id, $moodleoverflow, $modulecontext);
+            subscriptions::unsubscribe_user($users[$i]->id, $moodleoverflow, $modulecontext);
         }
 
         // The subscription count should now take into account those users who have been unsubscribed.
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
         $this->assertEquals($usercount - $unsubscribedcount, count($subscribers));
     }
 
@@ -877,7 +877,7 @@ public function test_fetch_subscribed_users_forced(): void {
         $this->helper_create_users($course, $usercount);
 
         // All users should be subscribed.
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
         $this->assertEquals($usercount, count($subscribers));
     }
 
@@ -910,20 +910,20 @@ public function test_fetch_subscribed_users_discussion_subscriptions(): void {
         $discussion->moodleoverflow = $moodleoverflow->id;
 
         // All users should be subscribed.
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
         $this->assertEquals($usercount, count($subscribers));
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
             true);
         $this->assertEquals($usercount, count($subscribers));
 
-        \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($users[0]->id, $discussion, $modulecontext);
+        subscriptions::unsubscribe_user_from_discussion($users[0]->id, $discussion, $modulecontext);
 
         // All users should be subscribed.
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
         $this->assertEquals($usercount, count($subscribers));
 
         // All users should be subscribed.
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
             true);
         $this->assertEquals($usercount, count($subscribers));
 
@@ -936,33 +936,33 @@ public function test_fetch_subscribed_users_discussion_subscriptions(): void {
         $DB->insert_record('moodleoverflow_discuss_subs', $record);
 
         // The discussion count should not have changed.
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
         $this->assertEquals($usercount, count($subscribers));
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
             true);
         $this->assertEquals($usercount, count($subscribers));
 
         // Unsubscribe 2 users.
         $unsubscribedcount = 2;
         for ($i = 0; $i < $unsubscribedcount; $i++) {
-            \mod_moodleoverflow\subscriptions::unsubscribe_user($users[$i]->id, $moodleoverflow, $modulecontext);
+            subscriptions::unsubscribe_user($users[$i]->id, $moodleoverflow, $modulecontext);
         }
 
         // The subscription count should now take into account those users who have been unsubscribed.
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
         $this->assertEquals($usercount - $unsubscribedcount, count($subscribers));
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
             true);
         $this->assertEquals($usercount - $unsubscribedcount, count($subscribers));
 
         // Now subscribe one of those users back to the discussion.
         $subedusers = 1;
         for ($i = 0; $i < $subedusers; $i++) {
-            \mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($users[$i]->id, $discussion, $modulecontext);
+            subscriptions::subscribe_user_to_discussion($users[$i]->id, $discussion, $modulecontext);
         }
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext);
         $this->assertEquals($usercount - $unsubscribedcount, count($subscribers));
-        $subscribers = \mod_moodleoverflow\subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
+        $subscribers = subscriptions::get_subscribed_users($moodleoverflow, $modulecontext, null,
             true);
         $this->assertEquals($usercount - $unsubscribedcount + $subedusers, count($subscribers));
     }
@@ -992,7 +992,7 @@ public function test_force_subscribed_to_moodleoverflow(): void {
         $this->getDataGenerator()->enrol_user($user->id, $course->id, $roleids['student']);
 
         // Check that the user is currently subscribed to the moodleoverflow.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::is_subscribed($user->id, $moodleoverflow, $context));
+        $this->assertTrue(subscriptions::is_subscribed($user->id, $moodleoverflow, $context));
 
         assign_capability('mod/moodleoverflow:allowforcesubscribe', CAP_PROHIBIT, $roleids['student'],
             $context);
@@ -1018,17 +1018,17 @@ public function test_subscription_cache_prefill(): void {
         $users = $this->helper_create_users($course, 20);
 
         // Reset the subscription cache.
-        \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_moodleoverflow_cache();
 
         // Filling the subscription cache should only use a single query, except for Postgres, which delegates actual reading
         // to Cursors, thus tripling the amount of queries. We intend to test the cache, though, so no worries.
-        $this->assertNull(\mod_moodleoverflow\subscriptions::fill_subscription_cache($moodleoverflow->id));
+        $this->assertNull(subscriptions::fill_subscription_cache($moodleoverflow->id));
         $postfillcount = $DB->perf_get_reads();
 
         // Now fetch some subscriptions from that moodleoverflow - these should use
         // the cache and not perform additional queries.
         foreach ($users as $user) {
-            $this->assertTrue(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($moodleoverflow->id, $user->id));
+            $this->assertTrue(subscriptions::fetch_subscription_cache($moodleoverflow->id, $user->id));
         }
         $finalcount = $DB->perf_get_reads();
         $this->assertEquals($finalcount, $postfillcount);
@@ -1053,14 +1053,14 @@ public function test_subscription_cache_fill(): void {
         $users = $this->helper_create_users($course, 20);
 
         // Reset the subscription cache.
-        \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_moodleoverflow_cache();
 
         // Filling the subscription cache should only use a single query.
         $startcount = $DB->perf_get_reads();
 
         // Fetch some subscriptions from that moodleoverflow - these should not use the cache and will perform additional queries.
         foreach ($users as $user) {
-            $this->assertTrue(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($moodleoverflow->id, $user->id));
+            $this->assertTrue(subscriptions::fetch_subscription_cache($moodleoverflow->id, $user->id));
         }
         $finalcount = $DB->perf_get_reads();
         $this->assertEquals(20, $finalcount - $startcount);
@@ -1091,23 +1091,23 @@ public function test_discussion_subscription_cache_fill_for_course(): void {
         $user = reset($users);
 
         // Reset the subscription caches.
-        \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_moodleoverflow_cache();
 
-        $result = \mod_moodleoverflow\subscriptions::fill_subscription_cache_for_course($course->id, $user->id);
+        $result = subscriptions::fill_subscription_cache_for_course($course->id, $user->id);
         $this->assertNull($result);
         $postfillcount = $DB->perf_get_reads();
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($disallowmoodleoverflow->id, $user->id));
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($choosemoodleoverflow->id, $user->id));
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($initialmoodleoverflow->id, $user->id));
+        $this->assertFalse(subscriptions::fetch_subscription_cache($disallowmoodleoverflow->id, $user->id));
+        $this->assertFalse(subscriptions::fetch_subscription_cache($choosemoodleoverflow->id, $user->id));
+        $this->assertTrue(subscriptions::fetch_subscription_cache($initialmoodleoverflow->id, $user->id));
         $finalcount = $DB->perf_get_reads();
         $this->assertEquals(0, $finalcount - $postfillcount);
 
         // Test for all users.
         foreach ($users as $user) {
-            $result = \mod_moodleoverflow\subscriptions::fill_subscription_cache_for_course($course->id, $user->id);
-            $this->assertFalse(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($disallowmoodleoverflow->id, $user->id));
-            $this->assertFalse(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($choosemoodleoverflow->id, $user->id));
-            $this->assertTrue(\mod_moodleoverflow\subscriptions::fetch_subscription_cache($initialmoodleoverflow->id, $user->id));
+            $result = subscriptions::fill_subscription_cache_for_course($course->id, $user->id);
+            $this->assertFalse(subscriptions::fetch_subscription_cache($disallowmoodleoverflow->id, $user->id));
+            $this->assertFalse(subscriptions::fetch_subscription_cache($choosemoodleoverflow->id, $user->id));
+            $this->assertTrue(subscriptions::fetch_subscription_cache($initialmoodleoverflow->id, $user->id));
         }
         $finalcount = $DB->perf_get_reads();
         $reads = $finalcount - $postfillcount;
@@ -1162,24 +1162,24 @@ public function test_discussion_subscription_cache_prefill(): void {
                 if ($usercount % 2) {
                     continue;
                 }
-                \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion, $modulecontext);
+                subscriptions::unsubscribe_user_from_discussion($user->id, $discussion, $modulecontext);
                 $usercount++;
             }
             $moodleoverflowcount++;
         }
 
         // Reset the subscription caches.
-        \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache();
-        \mod_moodleoverflow\subscriptions::reset_discussion_cache();
+        subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_discussion_cache();
 
         // Filling the discussion subscription cache should only use a single query.
-        $this->assertNull(\mod_moodleoverflow\subscriptions::fill_discussion_subscription_cache($moodleoverflow->id));
+        $this->assertNull(subscriptions::fill_discussion_subscription_cache($moodleoverflow->id));
         $postfillcount = $DB->perf_get_reads();
 
         // Now fetch some subscriptions from that moodleoverflow - these should use
         // the cache and not perform additional queries.
         foreach ($users as $user) {
-            $result = \mod_moodleoverflow\subscriptions::fetch_discussion_subscription($moodleoverflow->id, $user->id);
+            $result = subscriptions::fetch_discussion_subscription($moodleoverflow->id, $user->id);
             $this->assertIsArray($result);
         }
         $finalcount = $DB->perf_get_reads();
@@ -1229,22 +1229,22 @@ public function test_discussion_subscription_cache_fill(): void {
                 if ($usercount % 2) {
                     continue;
                 }
-                \mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($user->id, $discussion, $modulecontext);
+                subscriptions::unsubscribe_user_from_discussion($user->id, $discussion, $modulecontext);
                 $usercount++;
             }
             $moodleoverflowcount++;
         }
 
         // Reset the subscription caches.
-        \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache();
-        \mod_moodleoverflow\subscriptions::reset_discussion_cache();
+        subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_discussion_cache();
 
         $startcount = $DB->perf_get_reads();
 
         // Now fetch some subscriptions from that moodleoverflow - these should use
         // the cache and not perform additional queries.
         foreach ($users as $user) {
-            $result = \mod_moodleoverflow\subscriptions::fetch_discussion_subscription($moodleoverflow->id, $user->id);
+            $result = subscriptions::fetch_discussion_subscription($moodleoverflow->id, $user->id);
             $this->assertIsArray($result);
         }
         $finalcount = $DB->perf_get_reads();
@@ -1287,10 +1287,10 @@ public function test_moodleoverflow_subscribe_toggle_as_other_repeat_subscriptio
         $discussion->moodleoverflow = $moodleoverflow->id;
 
         // Confirm that the user is currently not subscribed to the moodleoverflow.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($user->id, $moodleoverflow, $modulecontext));
+        $this->assertFalse(subscriptions::is_subscribed($user->id, $moodleoverflow, $modulecontext));
 
         // Confirm that the user is unsubscribed from the discussion too.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribed($user->id, $moodleoverflow, $modulecontext,
+        $this->assertFalse(subscriptions::is_subscribed($user->id, $moodleoverflow, $modulecontext,
             $discussion->id));
 
         // Confirm that we have no records in either of the subscription tables.
@@ -1305,7 +1305,7 @@ public function test_moodleoverflow_subscribe_toggle_as_other_repeat_subscriptio
 
         // Subscribing to the moodleoverflow should create a record in the subscriptions table,
         // but not the moodleoverflow discussion subscriptions table.
-        \mod_moodleoverflow\subscriptions::subscribe_user($user->id, $moodleoverflow, $modulecontext);
+        subscriptions::subscribe_user($user->id, $moodleoverflow, $modulecontext);
         $this->assertEquals(1, $DB->count_records('moodleoverflow_subscriptions', [
             'userid' => $user->id,
             'moodleoverflow' => $moodleoverflow->id,
@@ -1317,22 +1317,22 @@ public function test_moodleoverflow_subscribe_toggle_as_other_repeat_subscriptio
 
         // Now unsubscribe from the discussion. This should return true.
         $uid = $user->id;
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext));
+        $this->assertTrue(subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext));
 
         // Attempting to unsubscribe again should return false because no change was made.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext));
+        $this->assertFalse(subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext));
 
         // Subscribing to the discussion again should return truthfully as the subscription preference was removed.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext));
+        $this->assertTrue(subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext));
 
         // Attempting to subscribe again should return false because no change was made.
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext));
+        $this->assertFalse(subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext));
 
         // Now unsubscribe from the discussion. This should return true once more.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext));
+        $this->assertTrue(subscriptions::unsubscribe_user_from_discussion($uid, $discussion, $modulecontext));
 
         // And unsubscribing from the moodleoverflow but not as a request from the user should maintain their preference.
-        \mod_moodleoverflow\subscriptions::unsubscribe_user($user->id, $moodleoverflow, $modulecontext);
+        subscriptions::unsubscribe_user($user->id, $moodleoverflow, $modulecontext);
 
         $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', [
             'userid' => $user->id,
@@ -1344,7 +1344,7 @@ public function test_moodleoverflow_subscribe_toggle_as_other_repeat_subscriptio
         ]));
 
         // Subscribing to the discussion should return truthfully because a change was made.
-        $this->assertTrue(\mod_moodleoverflow\subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext));
+        $this->assertTrue(subscriptions::subscribe_user_to_discussion($user->id, $discussion, $modulecontext));
         $this->assertEquals(0, $DB->count_records('moodleoverflow_subscriptions', [
             'userid' => $user->id,
             'moodleoverflow' => $moodleoverflow->id,
@@ -1407,7 +1407,7 @@ public function test_is_subscribable_logged_out($options): void {
         $options['course'] = $course->id;
         $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options);
 
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow,
+        $this->assertFalse(subscriptions::is_subscribable($moodleoverflow,
                 \context_module::instance($moodleoverflow->cmid)));
     }
 
@@ -1432,12 +1432,12 @@ public function test_is_subscribable_is_guest($options): void {
         $options['course'] = $course->id;
         $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options);
 
-        $this->assertFalse(\mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow,
+        $this->assertFalse(subscriptions::is_subscribable($moodleoverflow,
                 \context_module::instance($moodleoverflow->cmid)));
     }
 
     /**
-     * Returns subscription obtions.
+     * Returns subscription options.
      * @return array
      */
     public function is_subscribable_loggedin_provider(): array {
@@ -1483,7 +1483,7 @@ public function test_is_subscribable_loggedin($options, $expect): void {
         $this->getDataGenerator()->enrol_user($user->id, $course->id);
         $this->setUser($user);
 
-        $this->assertEquals($expect, \mod_moodleoverflow\subscriptions::is_subscribable($moodleoverflow,
+        $this->assertEquals($expect, subscriptions::is_subscribable($moodleoverflow,
                 \context_module::instance($moodleoverflow->cmid)));
     }
 }
diff --git a/tests/userstats_test.php b/tests/userstats_test.php
index b6078f1670..bc91c3a136 100644
--- a/tests/userstats_test.php
+++ b/tests/userstats_test.php
@@ -93,8 +93,8 @@ public function setUp(): void {
      */
     public function tearDown(): void {
         // Clear all caches.
-        \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache();
-        \mod_moodleoverflow\subscriptions::reset_discussion_cache();
+        subscriptions::reset_moodleoverflow_cache();
+        subscriptions::reset_discussion_cache();
     }
 
     // Begin of test functions.
@@ -221,7 +221,7 @@ public function test_partial_anonymous(): void {
     }
 
     /**
-     * Test, if userstats are calculated correctly if the moodleoverflow is partially anonymous.
+     * Test, if userstats are calculated correctly if the moodleoverflow is totally anonymous.
      * @covers \userstats_table
      */
     public function test_total_anonymous(): void {
@@ -303,7 +303,7 @@ private function helper_course_set_up() {
      * Makes the existing moodleoverflow anonymous.
      * There are 2 types of anonymous moodleoverflows:
      * anonymous = 1, the topic starter is anonymous
-     * anonymous = 2, all users are anonym
+     * anonymous = 2, all users are anonymous
      *
      * @param int $anonymoussetting
      */
diff --git a/version.php b/version.php
index fe90ba0727..b8fffbb5e6 100644
--- a/version.php
+++ b/version.php
@@ -28,8 +28,8 @@
 defined('MOODLE_INTERNAL') || die();
 
 $plugin->component = 'mod_moodleoverflow';
-$plugin->version = 2023082500;
 $plugin->release = 'v4.2-r4';
+$plugin->version = 2024031200;
 $plugin->requires = 2020061500; // Requires Moodle 3.9+.
 $plugin->maturity = MATURITY_STABLE;
 $plugin->dependencies = [];
diff --git a/view.php b/view.php
index 9fe603d752..d30c6e6544 100644
--- a/view.php
+++ b/view.php
@@ -65,7 +65,6 @@
 // Save the allowmultiplemarks setting.
 $marksetting = $DB->get_record('moodleoverflow', ['id' => $moodleoverflow->id], 'allowmultiplemarks');
 
-
 // Require a login.
 require_login($course, true, $cm);