Get the url to view the first unread post in a discussion.

@param discussion_entity $discussion The discussion
@return moodle_url
559900
public function get_discussion_view_first_unread_post_url_from_discussion(discussion_entity $discussion) {
        $viewurl = $this->get_discussion_view_url_from_discussion_id($discussion->get_id());
        $viewurl->set_anchor('unread');

        return $viewurl;
    }
741610
public function get_discussion() {
		if( $this->namespace_id < 0 ) {
			// No discussion page exists
			// Guessing we want to error
			throw new BadEntryError( "get_discussion", "Tried to find the discussion page of a page which could never have one" );
		} else {
			$namespaces = $this->wiki->get_namespaces();
			if( $this->is_discussion() ) {
				return $namespaces[( $this->namespace_id - 1 )] . ":" . $this->title_wo_namespace;
			} else {
				return $namespaces[( $this->namespace_id + 1 )] . ":" . $this->title_wo_namespace;
			}
		}
	}
428751
public function printTopics($forum_id, $sort_by, $start_from)
    {
        $forum_id = Container::get('hooks')
            ->fire('model.forum.print_topics_start', $forum_id, $sort_by, $start_from);

        // Get topic/forum tracking data
        if (!User::get()->is_guest) {
            $tracked_topics = Track::getTrackedTopics();
        }

        // Retrieve a list of topic IDs, LIMIT is (really) expensive so we only fetch the
        // IDs here then later fetch the remaining data
        $result = DB::forTable('topics')
                        ->select('id')
                        ->where('forum_id', $forum_id)
                        ->order_by_desc('sticky')
                        ->order_by_expr($sort_by)
                        ->order_by_desc('id')
                        ->limit(User::get()->disp_topics)
                        ->offset($start_from);
        $result = Container::get('hooks')->fire('model.forum.print_topics_ids_query', $result);
        $result = $result->find_many();

        $forum_data = [];

        // If there are topics in this forum
        if ($result) {
            $topic_ids = [];
            foreach ($result as $cur_topic_id) {
                $topic_ids[] = $cur_topic_id['id'];
            }

            // Fetch list of topics to display on this page
            if (User::get()->is_guest || ForumSettings::get('o_show_dot') == '0') {
                // Without "the dot"
                $result['select'] = [
                    'id',
                    'poster',
                    'subject',
                    'posted',
                    'last_post',
                    'last_post_id',
                    'last_poster',
                    'num_views',
                    'num_replies',
                    'closed',
                    'sticky',
                    'moved_to'
                ];

                $result = DB::forTable('topics')
                            ->select_many($result['select'])
                            ->where_in('id', $topic_ids)
                            ->order_by_desc('sticky')
                            ->order_by_expr($sort_by)
                            ->order_by_desc('id');
            } else {
                // With "the dot"
                $result['select'] = [
                    'has_posted' => 'p.poster_id',
                    't.id',
                    't.subject',
                    't.poster',
                    't.posted',
                    't.last_post',
                    't.last_post_id',
                    't.last_poster',
                    't.num_views',
                    't.num_replies',
                    't.closed',
                    't.sticky',
                    't.moved_to'
                ];

                $result = DB::forTable('topics')
                            ->table_alias('t')
                            ->select_many($result['select'])
//                            ->left_outer_join(DB::prefix().'posts',
// array('t.id', '=', 'p.topic_id'), 'p')
//                            ->left_outer_join(DB::prefix().'posts',
// array('p.poster_id', '=', User::get()->id), null, true)
                    ->left_outer_join(
                        DB::prefix().'posts',
                        '(t.id = p.topic_id AND p.poster_id = '.User::get()->id.')',
                        'p'
                    )
                            ->where_in('t.id', $topic_ids)
                            ->group_by('t.id')
                            ->order_by_desc('sticky')
                            ->order_by_expr($sort_by)
                            ->order_by_desc('id');
            }

            $result = Container::get('hooks')->fireDB('model.forum.print_topics_query', $result);
            $result = $result->find_many();

            $topic_count = 0;
            foreach ($result as $cur_topic) {
                ++$topic_count;
                $status_text = [];
                $cur_topic['item_status'] = ($topic_count % 2 == 0) ? 'roweven' : 'rowodd';
                $cur_topic['icon_type'] = $cur_topic->sticky === '1' ? 'icon icon-sticky' :
                    ($cur_topic->closed === '1' ? 'icon icon-closed' : 'icon');
                $url_subject = Url::slug($cur_topic['subject']);

                if (is_null($cur_topic['moved_to'])) {
                    $cur_topic['last_post_formatted'] = '<a href="'.
                        Router::pathFor('viewPost', ['pid' => $cur_topic['last_post_id']]).'#p'.
                        $cur_topic['last_post_id'].'">'.Utils::timeFormat($cur_topic['last_post']).'</a><br />'.
                        '<span class="byuser">'.__('by').' '.Utils::escape($cur_topic['last_poster']).'</span>';
                } else {
                    $cur_topic['last_post_formatted'] = '- - -';
                }

                if (ForumSettings::get('o_censoring') == '1') { // TODO: correct ?
                    $cur_topic['subject'] = Utils::censor($cur_topic['subject']);
                }

                if ($cur_topic['sticky'] == '1') {
                    $cur_topic['item_status'] .= ' isticky';
                    $status_text[] = '<span class="stickytext">'.__('Sticky').'</span>';
                }

                if ($cur_topic['moved_to'] != 0) {
                    $cur_topic['subject_formatted'] = '<a href="'.
                        Router::pathFor('Topic', ['id' => $cur_topic['moved_to'], 'name' => $url_subject]).'">'.
                        Utils::escape($cur_topic['subject']).'</a> <span class="byuser">'.__('by').' '.
                        Utils::escape($cur_topic['poster']).'</span>';
                    $status_text[] = '<span class="movedtext">'.__('Moved').'</span>';
                    $cur_topic['item_status'] .= ' imoved';
                } elseif ($cur_topic['closed'] == '0') {
                    $cur_topic['subject_formatted'] = '<a href="'.
                        Router::pathFor('Topic', ['id' => $cur_topic['id'], 'name' => $url_subject]).'">'.
                        Utils::escape($cur_topic['subject']).'</a> <span class="byuser">'.__('by').' '.
                        Utils::escape($cur_topic['poster']).'</span>';
                } else {
                    $cur_topic['subject_formatted'] = '<a href="'.
                        Router::pathFor('Topic', ['id' => $cur_topic['id'], 'name' => $url_subject]).'">'.
                        Utils::escape($cur_topic['subject']).'</a> <span class="byuser">'.__('by').' '.
                        Utils::escape($cur_topic['poster']).'</span>';
                    $status_text[] = '<span class="closedtext">'.__('Closed').'</span>';
                    $cur_topic['item_status'] .= ' iclosed';
                }

                if (!User::get()->is_guest && $cur_topic['last_post'] > User::get()->last_visit &&
                    (!isset($tracked_topics['topics'][$cur_topic['id']]) ||
                        $tracked_topics['topics'][$cur_topic['id']] < $cur_topic['last_post']) &&
                    (!isset($tracked_topics['forums'][$forum_id]) ||
                        $tracked_topics['forums'][$forum_id] < $cur_topic['last_post']) &&
                    is_null($cur_topic['moved_to'])) {
                    $cur_topic['item_status'] .= ' inew';
                    $cur_topic['icon_type'] = 'icon icon-new';
                    $cur_topic['subject_formatted'] = '<strong>'.$cur_topic['subject_formatted'].'</strong>';
                    $subject_new_posts = '<span class="newtext">[ <a href="'.
                        Router::pathFor('topicAction', ['id' => $cur_topic['id'], 'action' => 'new']).
                        '" title="'.__('New posts info').'">'.__('New posts').'</a> ]</span>';
                } else {
                    $subject_new_posts = null;
                }

                // Insert the status text before the subject
                $cur_topic['subject_formatted'] = implode(' ', $status_text).' '.$cur_topic['subject_formatted'];

                // Should we display the dot or not? :)
                if (!User::get()->is_guest && ForumSettings::get('o_show_dot') == '1') {
                    if ($cur_topic['has_posted'] == User::get()->id) {
                        $cur_topic['subject_formatted'] = '<strong class="ipost">·&#160;</strong>'.
                            $cur_topic['subject_formatted'];
                        $cur_topic['item_status'] .= ' iposted';
                    }
                }

                $num_pages_topic = ceil(($cur_topic['num_replies'] + 1) / User::get()->disp_posts);

                if ($num_pages_topic > 1) {// FIXME rebuild url
                    $subject_multipage = '<span class="pagestext">[ '.
                        Url::paginate($num_pages_topic, -1, Init::$uri . '/topic/'.$cur_topic['id'].
                            '/'.$url_subject.'/#'). ' ]</span>';
                } else {
                    $subject_multipage = null;
                }

                // Should we show the "New posts" and/or the multipage links?
                if (!empty($subject_new_posts) || !empty($subject_multipage)) {
                    $cur_topic['subject_formatted'] .= !empty($subject_new_posts) ? ' '.$subject_new_posts : '';
                    $cur_topic['subject_formatted'] .= !empty($subject_multipage) ? ' '.$subject_multipage : '';
                }

                $forum_data[] = $cur_topic;
            }
        }

        $forum_data = Container::get('hooks')->fire('model.forum.print_topics', $forum_data);

        return $forum_data;
    }
1092646
protected function getDefaultAttributes($discussion)
    {
        if (! ($discussion instanceof Discussion)) {
            throw new InvalidArgumentException(
                get_class($this).' can only serialize instances of '.Discussion::class
            );
        }

        return [
            'title' => $discussion->title,
            'slug'  => $discussion->slug,
        ];
    }
620283
public function GetCount($DiscussionID) {
      $this->FireEvent('BeforeGetCount');
      
      if (!empty($this->_Where)) {
         return FALSE;
      }
      
      return $this->SQL->Select('CommentID', 'count', 'CountComments')
         ->From('Comment')
         ->Where('DiscussionID', $DiscussionID)
         ->Get()
         ->FirstRow()
         ->CountComments;
   }
598410
public function GetNew($DiscussionID, $LastCommentID = 0) {
      $this->SetData('Discussion', $this->DiscussionModel->GetID($DiscussionID), TRUE);
      
      // Check permissions.
      $this->Permission('Vanilla.Discussions.View', TRUE, 'Category', $this->Discussion->PermissionCategoryID);
      $this->SetData('CategoryID', $this->CategoryID = $this->Discussion->CategoryID, TRUE);
      
      // Get the comments.
      $Comments = $this->CommentModel->GetNew($DiscussionID, $LastCommentID)->Result();
      $this->SetData('Comments', $Comments, TRUE);
      
      // Set the data.
      if(count($Comments) > 0) {
         $LastComment = $Comments[count($Comments) - 1];
         // Mark the comment read.
         $this->SetData('Offset', $this->Discussion->CountComments, TRUE);
         $this->CommentModel->SetWatch($this->Discussion, $this->Discussion->CountComments, $this->Discussion->CountComments, $this->Discussion->CountComments);
         
         $LastCommentID = $this->Json('LastCommentID');
         if(is_null($LastCommentID) || $LastComment->CommentID > $LastCommentID) {
            $this->Json('LastCommentID', $LastComment->CommentID);
         }
      } else {
         $this->SetData('Offset', $this->CommentModel->GetOffset($LastCommentID), TRUE);
      }
      
      $this->View = 'comments';
      $this->Render();
   }
655684
public function get_url() {
        if ($this->other['forumtype'] == 'single') {
            // Single discussion forums are an exception. We show
            // the forum itself since it only has one discussion
            // thread.
            $url = new \moodle_url('/mod/forum/view.php', array('f' => $this->other['forumid']));
        } else {
            $url = new \moodle_url('/mod/forum/discuss.php', array('d' => $this->other['discussionid']));
        }
        $url->set_anchor('p'.$this->objectid);
        return $url;
    }
344219
public function can_post_in_discussion(stdClass $user, discussion_entity $discussion) : bool {
        $forum = $this->get_forum();
        $forumrecord = $this->get_forum_record();
        $discussionrecord = $this->get_discussion_record($discussion);
        $context = $this->get_context();
        $coursemodule = $forum->get_course_module_record();
        $course = $forum->get_course_record();

        return forum_user_can_post($forumrecord, $discussionrecord, $user, $coursemodule, $course, $context);
    }
395000
public function update_discussion(discussion_entity $discussion) : ?discussion_entity {
        $discussionrecord = $this->get_legacy_factory()->to_legacy_object($discussion);
        if ($this->get_db()->update_record('forum_discussions', $discussionrecord)) {
            $records = $this->transform_db_records_to_entities([$discussionrecord]);

            return count($records) ? array_shift($records) : null;
        }

        return null;
    }
690844
public function get_unsubscribeforumlink() {
        if (!\mod_forum\subscriptions::is_subscribable($this->forum)) {
            return null;
        }
        $link = new \moodle_url(
            '/mod/forum/subscribe.php', array(
                'id' => $this->forum->id,
            )
        );

        return $link->out(false);
    }
490999
public function get_view_post_url_from_post(post_entity $post) : moodle_url {
        return $this->get_view_post_url_from_post_id($post->get_discussion_id(), $post->get_id());
    }
1127557
public function get_forum_view_url_from_forum(forum_entity $forum, ?int $pageno = null,
            ?int $sortorder = null) : moodle_url {

        return $this->get_forum_view_url_from_course_module_id($forum->get_course_module_record()->id, $pageno, $sortorder);
    }
441912
protected static function get_discussion_area(\stdClass $discussion) : Array {
        $pathparts = [];
        if (!empty($discussion->groupname)) {
            $pathparts[] = get_string('groups');
            $pathparts[] = $discussion->groupname;
        }

        $parts = [
            $discussion->id,
            $discussion->name,
        ];

        $discussionname = implode('-', $parts);

        $pathparts[] = get_string('discussions', 'mod_forum');
        $pathparts[] = $discussionname;

        return $pathparts;
    }
1141510
public function get_discussion_from_stdclass(stdClass $record) : discussion_entity {
        return new discussion_entity(
            $record->id,
            $record->course,
            $record->forum,
            $record->name,
            $record->firstpost,
            $record->userid,
            $record->groupid,
            $record->assessed,
            $record->timemodified,
            $record->usermodified,
            $record->timestart,
            $record->timeend,
            $record->pinned,
            $record->timelocked
        );
    }
1133491
public function get_doc_url(\core_search\document $doc) {
        // The post is already in static cache, we fetch it in self::search_access.
        $post = $this->get_post($doc->get('itemid'));
        return new \moodle_url('/mod/forum/discuss.php', array('d' => $post->discussion));
    }
682571
public function must_post_before_viewing_discussion(stdClass $user, discussion_entity $discussion) : bool {
        $forum = $this->get_forum();

        if ($forum->get_type() === 'qanda') {
            // If it's a Q and A forum then the user must either have the capability to view without
            // posting or the user must have posted before they can view the discussion.
            return !has_capability('mod/forum:viewqandawithoutposting', $this->get_context(), $user) &&
                !forum_user_has_posted($forum->get_id(), $discussion->get_id(), $user->id);
        } else {
            // No other forum types require posting before viewing.
            return false;
        }
    }
721125
public function GetBookmarkUsers($DiscussionID) {
      return $this->SQL
         ->Select('UserID')
         ->From('UserDiscussion')
         ->Where('DiscussionID', $DiscussionID)
         ->Where('Bookmarked', '1')
         ->Get();
   }