<commit_before><?php

/**
 * A representation of a forum thread. A forum thread is 1 topic on the forum which
 * has multiple posts underneath it.
 *
 * @package forum
 */

class ForumThread extends DataObject {
	
	static $db = array(
		"Title" => "Varchar(255)",
		"NumViews" => "Int",
		"IsSticky" => "Boolean",
		"IsReadOnly" => "Boolean",
		"IsGlobalSticky" => "Boolean"
	);
	
	static $has_one = array(
		'Forum' => 'Forum',

		// Reference to the most recently added or editing Post.
		'LastPost' => 'Post'
	);
	
	static $has_many = array(
		'Posts' => 'Post'
	);
	
	static $defaults = array(
		'NumViews' => 0,
		'IsSticky' => false,
		'IsReadOnly' => false,
		'IsGlobalSticky' => false
	);
	
	static $indexes = array(
		"SearchFields" => array('type'=>'fulltext', 'name'=>'SearchFields', 'value'=>'Title'),
	);
	
	/**
	 * Check to see if the user can perform editing tasks on this thread. This should
	 * be moderators and admins. For editing posts canCreate() is what referred to since
	 * currently we don't have that fine grain permissions.
	 *
	 * @return bool
	 */
	function canEdit() {
		return (!$this->IsReadOnly && $this->Forum()->canEdit()) ? true : false;
	}
	
	/**
	 * Check if the user can view this thread. Check if they can view the forum since
	 * the permissions on the forum are forum based, not thread based.
	 *
	 * @return bool
	 */
	function canView() {
		return $this->Forum()->canView();
	}
	
	/**
	 * Check to see if the user can create new posts in this thread rather than new threads
	 *
	 * @return bool
	 */
	function canCreate() {
		return (!$this->IsReadOnly && $this->Forum()->canPost()) ? true : false;
	}
	
	/** 
	 * Are Forum Signatures on Member profiles allowed
	 * 
	 * @return bool
	 */
	 function getDisplaySignatures() {
	 	return $this->Forum()->Parent()->DisplaySignatures;
	}
	
	/**
	 * Get the latest post from this thread. Nicer way then using an control
	 * from the template
	 *
	 * @return Post
	 */
	function getLatestPost() {
		if ($post = $this->LastPost()) return $post;
		return $this->updateLastPost();
	}
	
	/**
	 * Return the first post from the thread. Useful to working out the original author
	 *
	 * @return Post
	 */
	function getFirstPost() {
		return DataObject::get_one('Post', "\"ThreadID\" = '$this->ID'", true, "\"ID\" ASC");
	}

	/**
	 * Return the number of posts in this thread. We could use count on 
	 * the dataobject set but that is slower and causes a performance overhead
	 *
	 * @return int
	 */
	function getNumPosts() {
		return (int)DB::query("SELECT count(*) FROM \"Post\" WHERE \"ThreadID\" = $this->ID")->value();
	}
	
	/**
	 * Check if they have visited this thread before. If they haven't increment 
	 * the NumViews value by 1 and set visited to true.
	 */
	function incNumViews() {
		if(Session::get('ForumViewed-' . $this->ID)) return false;

		Session::set('ForumViewed-' . $this->ID, 'true');
		$this->NumViews++;
		$SQL_numViews = Convert::raw2sql($this->NumViews);
		DB::query("UPDATE \"ForumThread\" SET \"NumViews\" = '$SQL_numViews' WHERE \"ID\" = $this->ID");
	}
	
	/**
	 * Link to this forum thread
	 *
	 * @todo Use Title as the URL rather then ID
	 * @return String
	 */
	function Link($action = "show", $showID = true) {
		$baseLink = $this->Forum()->Link();
		$extra = ($showID) ? '/'.$this->ID : '';
		
		return ($action) ? $baseLink . $action . $extra : $baseLink;
	}
	
	/**
	 * Check to see if the user has subscribed to this thread
	 *
	 * @return bool
	 */
	function getHasSubscribed() {
		$member = Member::currentUser();

		return ($member) ? ForumThread_Subscription::already_subscribed($this->ID, $member->ID) : false;
	}
	
	/**
	 * Before deleting the thread remove all the posts
	 */
	function onBeforeDelete() {
		parent::onBeforeDelete(); 

		if($posts = $this->Posts()) {
			foreach($posts as $post) {
				// attachment deletion is handled by the {@link Post::onBeforeDelete}
				$post->delete();
			}
		}
	}

	/**
	 * Update LastPost to the most recent.
	 * @param $post Post		If supplied, this is assumed to be the
	 * 							most recently added or editing Post. If
	 * 							null, we automatically determine the most
	 * 							recent by grabbing the one with the highest
	 * 							ID. This is required in the case of deletion:
	 * 							If the most recent Post is deleted, we need
	 * 							to determine the next most recent.
	 */
	function updateLastPost($post = null) {
		if (!$post) $post = DataObject::get_one('Post', "\"ThreadID\" = '$this->ID'", true, "\"ID\" DESC");
		if ($post && $post->ID != $this->LastPostID) {
			$this->LastPostID = $post->ID;
			$this->write();
		}
	}
}


/**
 * Forum Thread Subscription: Allows members to subscribe to this thread
 * and receive email notifications when these topics are replied to.
 *
 * @package forum
 */
class ForumThread_Subscription extends DataObject {
	<commit_msg>BUGFIX: fixed lastpost method so it actually returns the last post. Previously the lastpost was never returned.<commit_after><?php

/**
 * A representation of a forum thread. A forum thread is 1 topic on the forum which
 * has multiple posts underneath it.
 *
 * @package forum
 */

class ForumThread extends DataObject {
	
	static $db = array(
		"Title" => "Varchar(255)",
		"NumViews" => "Int",
		"IsSticky" => "Boolean",
		"IsReadOnly" => "Boolean",
		"IsGlobalSticky" => "Boolean"
	);
	
	static $has_one = array(
		'Forum' => 'Forum',

		// Reference to the most recently added or editing Post.
		'LastPost' => 'Post'
	);
	
	static $has_many = array(
		'Posts' => 'Post'
	);
	
	static $defaults = array(
		'NumViews' => 0,
		'IsSticky' => false,
		'IsReadOnly' => false,
		'IsGlobalSticky' => false
	);
	
	static $indexes = array(
		"SearchFields" => array('type'=>'fulltext', 'name'=>'SearchFields', 'value'=>'Title'),
	);
	
	/**
	 * Check to see if the user can perform editing tasks on this thread. This should
	 * be moderators and admins. For editing posts canCreate() is what referred to since
	 * currently we don't have that fine grain permissions.
	 *
	 * @return bool
	 */
	function canEdit() {
		return (!$this->IsReadOnly && $this->Forum()->canEdit()) ? true : false;
	}
	
	/**
	 * Check if the user can view this thread. Check if they can view the forum since
	 * the permissions on the forum are forum based, not thread based.
	 *
	 * @return bool
	 */
	function canView() {
		return $this->Forum()->canView();
	}
	
	/**
	 * Check to see if the user can create new posts in this thread rather than new threads
	 *
	 * @return bool
	 */
	function canCreate() {
		return (!$this->IsReadOnly && $this->Forum()->canPost()) ? true : false;
	}
	
	/** 
	 * Are Forum Signatures on Member profiles allowed
	 * 
	 * @return bool
	 */
	 function getDisplaySignatures() {
	 	return $this->Forum()->Parent()->DisplaySignatures;
	}
	
	/**
	 * Get the latest post from this thread. Nicer way then using an control
	 * from the template
	 *
	 * @return Post
	 */
	function getLatestPost() {
		if ($post = $this->LastPost()) return $post;
		return $this->updateLastPost();
	}
	
	/**
	 * Return the first post from the thread. Useful to working out the original author
	 *
	 * @return Post
	 */
	function getFirstPost() {
		return DataObject::get_one('Post', "\"ThreadID\" = '$this->ID'", true, "\"ID\" ASC");
	}

	/**
	 * Return the number of posts in this thread. We could use count on 
	 * the dataobject set but that is slower and causes a performance overhead
	 *
	 * @return int
	 */
	function getNumPosts() {
		return (int)DB::query("SELECT count(*) FROM \"Post\" WHERE \"ThreadID\" = $this->ID")->value();
	}
	
	/**
	 * Check if they have visited this thread before. If they haven't increment 
	 * the NumViews value by 1 and set visited to true.
	 */
	function incNumViews() {
		if(Session::get('ForumViewed-' . $this->ID)) return false;

		Session::set('ForumViewed-' . $this->ID, 'true');
		$this->NumViews++;
		$SQL_numViews = Convert::raw2sql($this->NumViews);
		DB::query("UPDATE \"ForumThread\" SET \"NumViews\" = '$SQL_numViews' WHERE \"ID\" = $this->ID");
	}
	
	/**
	 * Link to this forum thread
	 *
	 * @todo Use Title as the URL rather then ID
	 * @return String
	 */
	function Link($action = "show", $showID = true) {
		$baseLink = $this->Forum()->Link();
		$extra = ($showID) ? '/'.$this->ID : '';
		
		return ($action) ? $baseLink . $action . $extra : $baseLink;
	}
	
	/**
	 * Check to see if the user has subscribed to this thread
	 *
	 * @return bool
	 */
	function getHasSubscribed() {
		$member = Member::currentUser();

		return ($member) ? ForumThread_Subscription::already_subscribed($this->ID, $member->ID) : false;
	}
	
	/**
	 * Before deleting the thread remove all the posts
	 */
	function onBeforeDelete() {
		parent::onBeforeDelete(); 

		if($posts = $this->Posts()) {
			foreach($posts as $post) {
				// attachment deletion is handled by the {@link Post::onBeforeDelete}
				$post->delete();
			}
		}
	}

	/**
	 * Update LastPost to the most recent.
	 * @param $post Post		If supplied, this is assumed to be the
	 * 							most recently added or editing Post. If
	 * 							null, we automatically determine the most
	 * 							recent by grabbing the one with the highest
	 * 							ID. This is required in the case of deletion:
	 * 							If the most recent Post is deleted, we need
	 * 							to determine the next most recent.
	 */
	function updateLastPost($post = null) {
		if (!$post) $post = DataObject::get_one('Post', "\"ThreadID\" = '$this->ID'", true, "\"ID\" DESC");
		if ($post && $post->ID != $this->LastPostID) {
			$this->LastPostID = $post->ID;
			$this->write();
		}
		return $post;
	}
}


/**
 * Forum Thread Subscription: Allows members to subscribe to this thread
 * and receive email notifications when these topics are replied to.
 *
 * @package forum
 */
class ForumThread_Subscription extends DataObject {
	
{'fraction_non_alphanumeric': 0.1485440847077988, 'fraction_numerical': 0.0014253716147424149, 'mean_word_length': 3.2104586369481356, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6773392', 'n_tokens_mistral': 3370, 'n_tokens_neox': 2989, 'n_words': 1046}