diff options
Diffstat (limited to 'phpBB/includes')
34 files changed, 2454 insertions, 1157 deletions
diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 7e8d5d8388..970b033995 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -283,7 +283,7 @@ class acp_forums  				@set_time_limit(0); -				$sql = 'SELECT forum_name, forum_topics_real +				$sql = 'SELECT forum_name, (forum_topics_approved + forum_topics_unapproved + forum_topics_softdeleted) AS total_topics  					FROM ' . FORUMS_TABLE . "  					WHERE forum_id = $forum_id";  				$result = $db->sql_query($sql); @@ -295,7 +295,7 @@ class acp_forums  					trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);  				} -				if ($row['forum_topics_real']) +				if ($row['total_topics'])  				{  					$sql = 'SELECT MIN(topic_id) as min_topic_id, MAX(topic_id) as max_topic_id  						FROM ' . TOPICS_TABLE . ' @@ -314,7 +314,6 @@ class acp_forums  					$end = $start + $batch_size;  					// Sync all topics in batch mode... -					sync('topic_approved', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, false);  					sync('topic', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, true);  					if ($end < $row2['max_topic_id']) @@ -330,15 +329,15 @@ class acp_forums  						$start += $batch_size; -						$url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync&start=$start&topics_done=$topics_done&total={$row['forum_topics_real']}"; +						$url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync&start=$start&topics_done=$topics_done&total={$row['total_topics']}";  						meta_refresh(0, $url);  						$template->assign_vars(array( -							'U_PROGRESS_BAR'		=> $this->u_action . "&action=progress_bar&start=$topics_done&total={$row['forum_topics_real']}", -							'UA_PROGRESS_BAR'		=> addslashes($this->u_action . "&action=progress_bar&start=$topics_done&total={$row['forum_topics_real']}"), +							'U_PROGRESS_BAR'		=> $this->u_action . "&action=progress_bar&start=$topics_done&total={$row['total_topics']}", +							'UA_PROGRESS_BAR'		=> addslashes($this->u_action . "&action=progress_bar&start=$topics_done&total={$row['total_topics']}"),  							'S_CONTINUE_SYNC'		=> true, -							'L_PROGRESS_EXPLAIN'	=> sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $topics_done, $row['forum_topics_real'])) +							'L_PROGRESS_EXPLAIN'	=> sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $topics_done, $row['total_topics']))  						);  						return; @@ -352,7 +351,7 @@ class acp_forums  					'U_PROGRESS_BAR'		=> $this->u_action . '&action=progress_bar',  					'UA_PROGRESS_BAR'		=> addslashes($this->u_action . '&action=progress_bar'),  					'S_CONTINUE_SYNC'		=> true, -					'L_PROGRESS_EXPLAIN'	=> sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], 0, $row['forum_topics_real'])) +					'L_PROGRESS_EXPLAIN'	=> sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], 0, $row['total_topics']))  				);  				return; @@ -857,8 +856,8 @@ class acp_forums  					'FORUM_IMAGE_SRC'	=> ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '',  					'FORUM_NAME'		=> $row['forum_name'],  					'FORUM_DESCRIPTION'	=> generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']), -					'FORUM_TOPICS'		=> $row['forum_topics'], -					'FORUM_POSTS'		=> $row['forum_posts'], +					'FORUM_TOPICS'		=> $row['forum_topics_approved'], +					'FORUM_POSTS'		=> $row['forum_posts_approved'],  					'S_FORUM_LINK'		=> ($forum_type == FORUM_LINK) ? true : false,  					'S_FORUM_POST'		=> ($forum_type == FORUM_POST) ? true : false, @@ -1144,7 +1143,8 @@ class acp_forums  					return array($user->lang['NO_FORUM_ACTION']);  				} -				$forum_data_sql['forum_posts'] = $forum_data_sql['forum_topics'] = $forum_data_sql['forum_topics_real'] = $forum_data_sql['forum_last_post_id'] = $forum_data_sql['forum_last_poster_id'] = $forum_data_sql['forum_last_post_time'] = 0; +				$forum_data_sql['forum_posts_approved'] = $forum_data_sql['forum_posts_unapproved'] = $forum_data_sql['forum_posts_softdeleted'] = $forum_data_sql['forum_topics_approved'] = $forum_data_sql['forum_topics_unapproved'] = $forum_data_sql['forum_topics_softdeleted'] = 0; +				$forum_data_sql['forum_last_post_id'] = $forum_data_sql['forum_last_poster_id'] = $forum_data_sql['forum_last_post_time'] = 0;  				$forum_data_sql['forum_last_poster_name'] = $forum_data_sql['forum_last_poster_colour'] = '';  			}  			else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_LINK) @@ -1264,9 +1264,12 @@ class acp_forums  			else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_POST)  			{  				// Changing a category to a forum? Reset the data (you can't post directly in a cat, you must use a forum) -				$forum_data_sql['forum_posts'] = 0; -				$forum_data_sql['forum_topics'] = 0; -				$forum_data_sql['forum_topics_real'] = 0; +				$forum_data_sql['forum_posts_approved'] = 0; +				$forum_data_sql['forum_posts_unapproved'] = 0; +				$forum_data_sql['forum_posts_softdeleted'] = 0; +				$forum_data_sql['forum_topics_approved'] = 0; +				$forum_data_sql['forum_topics_unapproved'] = 0; +				$forum_data_sql['forum_topics_softdeleted'] = 0;  				$forum_data_sql['forum_last_post_id'] = 0;  				$forum_data_sql['forum_last_post_subject'] = '';  				$forum_data_sql['forum_last_post_time'] = 0; @@ -1793,7 +1796,7 @@ class acp_forums  			FROM ' . POSTS_TABLE . '  			WHERE forum_id = ' . $forum_id . '  				AND post_postcount = 1 -				AND post_approved = 1'; +				AND post_visibility = ' . ITEM_APPROVED;  		$result = $db->sql_query($sql);  		$post_counts = array(); @@ -1931,7 +1934,7 @@ class acp_forums  		// Make sure the overall post/topic count is correct...  		$sql = 'SELECT COUNT(post_id) AS stat  			FROM ' . POSTS_TABLE . ' -			WHERE post_approved = 1'; +			WHERE post_visibility = ' . ITEM_APPROVED;  		$result = $db->sql_query($sql);  		$row = $db->sql_fetchrow($result);  		$db->sql_freeresult($result); @@ -1940,7 +1943,7 @@ class acp_forums  		$sql = 'SELECT COUNT(topic_id) AS stat  			FROM ' . TOPICS_TABLE . ' -			WHERE topic_approved = 1'; +			WHERE topic_visibility = ' . ITEM_APPROVED;  		$result = $db->sql_query($sql);  		$row = $db->sql_fetchrow($result);  		$db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index c44bc1b8a6..64c2b338fd 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -144,14 +144,14 @@ class acp_main  						$sql = 'SELECT COUNT(post_id) AS stat  							FROM ' . POSTS_TABLE . ' -							WHERE post_approved = 1'; +							WHERE post_visibility = ' . ITEM_APPROVED;  						$result = $db->sql_query($sql);  						set_config('num_posts', (int) $db->sql_fetchfield('stat'), true);  						$db->sql_freeresult($result);  						$sql = 'SELECT COUNT(topic_id) AS stat  							FROM ' . TOPICS_TABLE . ' -							WHERE topic_approved = 1'; +							WHERE topic_visibility = ' . ITEM_APPROVED;  						$result = $db->sql_query($sql);  						set_config('num_topics', (int) $db->sql_fetchfield('stat'), true);  						$db->sql_freeresult($result); @@ -232,7 +232,7 @@ class acp_main  							$sql = 'SELECT COUNT(post_id) AS num_posts, poster_id  								FROM ' . POSTS_TABLE . '  								WHERE post_id BETWEEN ' . ($start + 1) . ' AND ' . ($start + $step) . ' -									AND post_postcount = 1 AND post_approved = 1 +									AND post_postcount = 1 AND post_visibility = ' . ITEM_APPROVED . '  								GROUP BY poster_id';  							$result = $db->sql_query($sql); diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index c8542ddbe7..cbfd578d87 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -624,29 +624,31 @@ class acp_users  							$topic_id_ary = $move_topic_ary = $move_post_ary = $new_topic_id_ary = array();  							$forum_id_ary = array($new_forum_id); -							$sql = 'SELECT topic_id, COUNT(post_id) AS total_posts +							$sql = 'SELECT topic_id, post_visibility, COUNT(post_id) AS total_posts  								FROM ' . POSTS_TABLE . "  								WHERE poster_id = $user_id  									AND forum_id <> $new_forum_id -								GROUP BY topic_id"; +								GROUP BY topic_id, post_visibility";  							$result = $db->sql_query($sql);  							while ($row = $db->sql_fetchrow($result))  							{ -								$topic_id_ary[$row['topic_id']] = $row['total_posts']; +								$topic_id_ary[$row['topic_id']][$row['post_visibility']] = $row['total_posts'];  							}  							$db->sql_freeresult($result);  							if (sizeof($topic_id_ary))  							{ -								$sql = 'SELECT topic_id, forum_id, topic_title, topic_replies, topic_replies_real, topic_attachment +								$sql = 'SELECT topic_id, forum_id, topic_title, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, topic_attachment  									FROM ' . TOPICS_TABLE . '  									WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary));  								$result = $db->sql_query($sql);  								while ($row = $db->sql_fetchrow($result))  								{ -									if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']]) +									if ($topic_id_ary[$row['topic_id']][ITEM_APPROVED] == $row['topic_posts_approved'] +									 && $topic_id_ary[$row['topic_id']][ITEM_UNAPPROVED] == $row['topic_posts_unapproved'] +									 && $topic_id_ary[$row['topic_id']][ITEM_DELETED] == $row['topic_posts_softdeleted'])  									{  										$move_topic_ary[] = $row['topic_id'];  									} @@ -679,7 +681,7 @@ class acp_users  										'topic_time'				=> time(),  										'forum_id' 					=> $new_forum_id,  										'icon_id'					=> 0, -										'topic_approved'			=> 1, +										'topic_visibility'			=> ITEM_APPROVED,  										'topic_title' 				=> $post_ary['title'],  										'topic_first_poster_name'	=> $user_row['username'],  										'topic_type'				=> POST_NORMAL, @@ -1036,7 +1038,7 @@ class acp_users  				$sql = 'SELECT COUNT(post_id) as posts_in_queue  					FROM ' . POSTS_TABLE . '  					WHERE poster_id = ' . $user_id . ' -						AND post_approved = 0'; +						AND post_visibility = ' . ITEM_UNAPPROVED;  				$result = $db->sql_query($sql);  				$user_row['posts_in_queue'] = (int) $db->sql_fetchfield('posts_in_queue');  				$db->sql_freeresult($result); diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 96011f4ec5..c1f4c6ac0e 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -87,6 +87,10 @@ define('ITEM_UNLOCKED', 0);  define('ITEM_LOCKED', 1);  define('ITEM_MOVED', 2); +define('ITEM_UNAPPROVED', 0); // => has not yet been approved +define('ITEM_APPROVED', 1); // => has been approved, and has not been soft deleted +define('ITEM_DELETED', 2); // => has been soft deleted +  // Forum Flags  define('FORUM_FLAG_LINK_TRACK', 1);  define('FORUM_FLAG_PRUNE_POLL', 2); diff --git a/phpBB/includes/content_visibility.php b/phpBB/includes/content_visibility.php new file mode 100644 index 0000000000..ac827bd822 --- /dev/null +++ b/phpBB/includes/content_visibility.php @@ -0,0 +1,615 @@ +<?php +/** +* +* @package phpbb +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* phpbb_visibility +* Handle fetching and setting the visibility for topics and posts +* @package phpbb +*/ +class phpbb_content_visibility +{ +	/** +	* Can the current logged-in user soft-delete posts? +	* +	* @param $forum_id		int		Forum ID whose permissions to check +	* @param $poster_id		int		Poster ID of the post in question +	* @param $post_locked	bool	Is the post locked? +	* @return bool +	*/ +	static function can_soft_delete($forum_id, $poster_id, $post_locked) +	{ +		global $auth, $user; + +		if ($auth->acl_get('m_softdelete', $forum_id)) +		{ +			return true; +		} +		else if ($auth->acl_get('f_softdelete', $forum_id) && $poster_id == $user->data['user_id'] && !$post_locked) +		{ +			return true; +		} + +		return false; +	} + +	/** +	* Get the topics post count or the forums post/topic count based on permissions +	* +	* @param $mode			string	One of topic_posts, forum_posts or forum_topics +	* @param $data			array	Array with the topic/forum data to calculate from +	* @param $forum_id		int		The forum id is used for permission checks +	* @return int	Number of posts/topics the user can see in the topic/forum +	*/ +	static public function get_count($mode, $data, $forum_id) +	{ +		global $auth; + +		if (!$auth->acl_get('m_approve', $forum_id)) +		{ +			return (int) $data[$mode . '_approved']; +		} + +		return (int) $data[$mode . '_approved'] + (int) $data[$mode . '_unapproved'] + (int) $data[$mode . '_softdeleted']; +	} + +	/** +	* Create topic/post visibility SQL for a given forum ID +	* +	* Note: Read permissions are not checked. +	* +	* @param $mode			string	Either "topic" or "post" +	* @param $forum_id		int		The forum id is used for permission checks +	* @param $table_alias	string	Table alias to prefix in SQL queries +	* @return string	The appropriate combination SQL logic for topic/post_visibility +	*/ +	static public function get_visibility_sql($mode, $forum_id, $table_alias = '') +	{ +		global $auth; + +		if ($auth->acl_get('m_approve', $forum_id)) +		{ +			return '1 = 1'; +		} + +		return $table_alias . $mode . '_visibility = ' . ITEM_APPROVED; +	} + +	/** +	* Create topic/post visibility SQL for a set of forums +	* +	* Note: Read permissions are not checked. Forums without read permissions +	*		should not be in $forum_ids +	* +	* @param $mode			string	Either "topic" or "post" +	* @param $forum_ids		array	Array of forum ids which the posts/topics are limited to +	* @param $table_alias	string	Table alias to prefix in SQL queries +	* @return string	The appropriate combination SQL logic for topic/post_visibility +	*/ +	static public function get_forums_visibility_sql($mode, $forum_ids = array(), $table_alias = '') +	{ +		global $auth, $db; + +		$where_sql = '('; + +		$approve_forums = array_intersect($forum_ids, array_keys($auth->acl_getf('m_approve', true))); + +		if (sizeof($approve_forums)) +		{ +			// Remove moderator forums from the rest +			$forum_ids = array_diff($forum_ids, $approve_forums); + +			if (!sizeof($forum_ids)) +			{ +				// The user can see all posts/topics in all specified forums +				return $db->sql_in_set($table_alias . 'forum_id', $approve_forums); +			} +			else +			{ +				// Moderator can view all posts/topics in some forums +				$where_sql .= $db->sql_in_set($table_alias . 'forum_id', $approve_forums) . ' OR '; +			} +		} +		else +		{ +			// The user is just a normal user +			return "$table_alias{$mode}_visibility = " . ITEM_APPROVED . ' +				AND ' . $db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true); +		} + +		$where_sql .= "($table_alias{$mode}_visibility = " . ITEM_APPROVED . ' +			AND ' . $db->sql_in_set($table_alias . 'forum_id', $forum_ids) . '))'; + +		return $where_sql; +	} + +	/** +	* Create topic/post visibility SQL for all forums on the board +	* +	* Note: Read permissions are not checked. Forums without read permissions +	*		should be in $exclude_forum_ids +	* +	* @param $mode				string	Either "topic" or "post" +	* @param $exclude_forum_ids	array	Array of forum ids which are excluded +	* @param $table_alias		string	Table alias to prefix in SQL queries +	* @return string	The appropriate combination SQL logic for topic/post_visibility +	*/ +	static public function get_global_visibility_sql($mode, $exclude_forum_ids = array(), $table_alias = '') +	{ +		global $auth, $db; + +		$where_sqls = array(); + +		$approve_forums = array_diff(array_keys($auth->acl_getf('m_approve', true)), $exclude_forum_ids); + +		if (sizeof($exclude_forum_ids)) +		{ +			$where_sqls[] = '(' . $db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true) . " +				AND $table_alias{$mode}_visibility = " . ITEM_APPROVED . ')'; +		} +		else +		{ +			$where_sqls[] = "$table_alias{$mode}_visibility = " . ITEM_APPROVED; +		} + +		if (sizeof($approve_forums)) +		{ +			$where_sqls[] = $db->sql_in_set($table_alias . 'forum_id', $approve_forums); +			return '(' . implode(' OR ', $where_sqls) . ')'; +		} + +		// There is only one element, so we just return that one +		return $where_sqls[0]; +	} + +	/** +	* Change visibility status of one post or all posts of a topic +	* +	* @param $visibility	int		Element of {ITEM_APPROVED, ITEM_DELETED} +	* @param $post_id		mixed	Post ID or array of post IDs to act on, +	*								if it is empty, all posts of topic_id will be modified +	* @param $topic_id		int		Topic where $post_id is found +	* @param $forum_id		int		Forum where $topic_id is found +	* @param $user_id		int		User performing the action +	* @param $time			int		Timestamp when the action is performed +	* @param $reason		string	Reason why the visibilty was changed. +	* @param $is_starter	bool	Is this the first post of the topic changed? +	* @param $is_latest		bool	Is this the last post of the topic changed? +	* @param $limit_visibility	mixed	Limit updating per topic_id to a certain visibility +	* @param $limit_delete_time	mixed	Limit updating per topic_id to a certain deletion time +	* @return array		Changed post data, empty array if an error occured. +	*/ +	static public function set_post_visibility($visibility, $post_id, $topic_id, $forum_id, $user_id, $time, $reason, $is_starter, $is_latest, $limit_visibility = false, $limit_delete_time = false) +	{ +		global $db; + +		if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED))) +		{ +			return array(); +		} + +		if ($post_id) +		{ +			if (is_array($post_id)) +			{ +				$where_sql = $db->sql_in_set('post_id', array_map('intval', $post_id)); +			} +			else +			{ +				$where_sql = 'post_id = ' . (int) $post_id; +			} +			$where_sql .= ' AND topic_id = ' . (int) $topic_id; +		} +		else +		{ +			$where_sql = 'topic_id = ' . (int) $topic_id; + +			// Limit the posts to a certain visibility and deletion time +			// This allows us to only restore posts, that were approved +			// when the topic got soft deleted. So previous soft deleted +			// and unapproved posts are still soft deleted/unapproved +			if ($limit_visibility !== false) +			{ +				$where_sql .= ' AND post_visibility = ' . (int) $limit_visibility; +			} + +			if ($limit_delete_time !== false) +			{ +				$where_sql .= ' AND post_delete_time = ' . (int) $limit_delete_time; +			} +		} + +		$sql = 'SELECT poster_id, post_id, post_postcount, post_visibility +			FROM ' . POSTS_TABLE . ' +			WHERE ' . $where_sql; +		$result = $db->sql_query($sql); + +		$post_ids = $poster_postcounts = $postcounts = $postcount_visibility = array(); +		while ($row = $db->sql_fetchrow($result)) +		{ +			$post_ids[] = (int) $row['post_id']; + +			if ($row['post_visibility'] != $visibility) +			{ +				if ($row['post_postcount'] && !isset($poster_postcounts[(int) $row['poster_id']])) +				{ +					$poster_postcounts[(int) $row['poster_id']] = 1; +				} +				else if ($row['post_postcount']) +				{ +					$poster_postcounts[(int) $row['poster_id']]++; +				} + +				if (!isset($postcount_visibility[$row['post_visibility']])) +				{ +					$postcount_visibility[$row['post_visibility']] = 1; +				} +				else +				{ +					$postcount_visibility[$row['post_visibility']]++; +				} +			} +		} +		$db->sql_freeresult($result); + +		if (empty($post_ids)) +		{ +			return array(); +		} + +		$data = array( +			'post_visibility'		=> (int) $visibility, +			'post_delete_user'		=> (int) $user_id, +			'post_delete_time'		=> ((int) $time) ?: time(), +			'post_delete_reason'	=> truncate_string($reason, 255, 255, false), +		); + +		$sql = 'UPDATE ' . POSTS_TABLE . ' +			SET ' . $db->sql_build_array('UPDATE', $data) . ' +			WHERE ' . $db->sql_in_set('post_id', $post_ids); +		$db->sql_query($sql); + +		// Group the authors by post count, to reduce the number of queries +		foreach ($poster_postcounts as $poster_id => $num_posts) +		{ +			$postcounts[$num_posts][] = $poster_id; +		} + +		// Update users postcounts +		foreach ($postcounts as $num_posts => $poster_ids) +		{ +			if ($visibility == ITEM_DELETED) +			{ +				$sql = 'UPDATE ' . USERS_TABLE . ' +					SET user_posts = 0 +					WHERE ' . $db->sql_in_set('user_id', $poster_ids) . ' +						AND user_posts < ' . $num_posts; +				$db->sql_query($sql); + +				$sql = 'UPDATE ' . USERS_TABLE . ' +					SET user_posts = user_posts - ' . $num_posts . ' +					WHERE ' . $db->sql_in_set('user_id', $poster_ids) . ' +						AND user_posts >= ' . $num_posts; +				$db->sql_query($sql); +			} +			else +			{ +				$sql = 'UPDATE ' . USERS_TABLE . ' +					SET user_posts = user_posts + ' . $num_posts . ' +					WHERE ' . $db->sql_in_set('user_id', $poster_ids); +				$db->sql_query($sql); +			} +		} + +		$update_topic_postcount = true; + +		// Sync the first/last topic information if needed +		if (!$is_starter && $is_latest) +		{ +			// update_post_information can only update the last post info ... +			if ($topic_id) +			{ +				update_post_information('topic', $topic_id, false); +			} +			if ($forum_id) +			{ +				update_post_information('forum', $forum_id, false); +			} +		} +		else if ($is_starter && $topic_id) +		{ +			if (!function_exists('sync')) +			{ +				global $phpEx, $phpbb_root_path; +				include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); +			} + +			// ... so we need to use sync, if the first post is changed. +			// The forum is resynced recursive by sync() itself. +			sync('topic', 'topic_id', $topic_id, true); + +			// sync recalculates the topic replies and forum posts by itself, so we don't do that. +			$update_topic_postcount = false; +		} + +		// Update the topic's reply count and the forum's post count +		if ($update_topic_postcount) +		{ +			$cur_posts = $cur_unapproved_posts = $cur_softdeleted_posts = 0; +			foreach ($postcount_visibility as $post_visibility => $visibility_posts) +			{ +				// We need to substract the posts from the counters ... +				if ($post_visibility == ITEM_APPROVED) +				{ +					$cur_posts += $visibility_posts; +				} +				else if ($post_visibility == ITEM_UNAPPROVED) +				{ +					$cur_unapproved_posts += $visibility_posts; +				} +				else if ($post_visibility == ITEM_DELETED) +				{ +					$cur_softdeleted_posts += $visibility_posts; +				} +			} + +			$sql_ary = array(); +			if ($visibility == ITEM_DELETED) +			{ +				if ($cur_posts) +				{ +					$sql_ary['posts_approved'] = ' - ' . $cur_posts; +				} +				if ($cur_unapproved_posts) +				{ +					$sql_ary['posts_unapproved'] = ' - ' . $cur_unapproved_posts; +				} +				if ($cur_posts + $cur_unapproved_posts) +				{ +					$sql_ary['posts_softdeleted'] = ' + ' . ($cur_posts + $cur_unapproved_posts); +				} +			} +			else +			{ +				if ($cur_unapproved_posts) +				{ +					$sql_ary['posts_unapproved'] = ' - ' . $cur_unapproved_posts; +				} +				if ($cur_softdeleted_posts) +				{ +					$sql_ary['posts_softdeleted'] = ' - ' . $cur_softdeleted_posts; +				} +				if ($cur_softdeleted_posts + $cur_unapproved_posts) +				{ +					$sql_ary['posts_approved'] = ' + ' . ($cur_softdeleted_posts + $cur_unapproved_posts); +				} +			} + +			if (sizeof($sql_ary)) +			{ +				$topic_sql = $forum_sql = array(); + +				foreach ($sql_ary as $field => $value_change) +				{ +					$topic_sql[] = 'topic_' . $field . ' = topic_' . $field . $value_change; +					$forum_sql[] = 'forum_' . $field . ' = forum_' . $field . $value_change; +				} + +				// Update the number for replies and posts +				$sql = 'UPDATE ' . TOPICS_TABLE . ' +					SET ' . implode(', ', $topic_sql) . ' +					WHERE topic_id = ' . (int) $topic_id; +				$db->sql_query($sql); + +				$sql = 'UPDATE ' . FORUMS_TABLE . ' +					SET ' . implode(', ', $forum_sql) . ' +					WHERE forum_id = ' . (int) $forum_id; +				$db->sql_query($sql); +			} +		} + +		return $data; +	} + +	/** +	* Set topic visibility +	* +	* Allows approving (which is akin to undeleting/restore) or soft deleting an entire topic. +	* Calls set_post_visibility as needed. +	* +	* Note: By default, when a soft deleted topic is restored. Only posts that +	*		were approved at the time of soft deleting, are being restored. +	*		Same applies to soft deleting. Only approved posts will be marked +	*		as soft deleted. +	*		If you want to update all posts, use the force option. +	* +	* @param $visibility	int		Element of {ITEM_APPROVED, ITEM_DELETED} +	* @param $topic_id		mixed	Topic ID to act on +	* @param $forum_id		int		Forum where $topic_id is found +	* @param $user_id		int		User performing the action +	* @param $time			int		Timestamp when the action is performed +	* @param $reason		string	Reason why the visibilty was changed. +	* @param $force_update_all	bool	Force to update all posts within the topic +	* @return array		Changed topic data, empty array if an error occured. +	*/ +	static public function set_topic_visibility($visibility, $topic_id, $forum_id, $user_id, $time, $reason, $force_update_all = false) +	{ +		global $db; + +		if (!in_array($visibility, array(ITEM_APPROVED, ITEM_DELETED))) +		{ +			return array(); +		} + +		if (!$force_update_all) +		{ +			$sql = 'SELECT topic_visibility, topic_delete_time +				FROM ' . TOPICS_TABLE . ' +				WHERE topic_id = ' . (int) $topic_id; +			$result = $db->sql_query($sql); +			$original_topic_data = $db->sql_fetchrow($result); +			$db->sql_freeresult($result); + +			if (!$original_topic_data) +			{ +				// The topic does not exist... +				return array(); +			} +		} + +		// Note, we do not set a reason for the posts, just for the topic +		$data = array( +			'topic_visibility'		=> (int) $visibility, +			'topic_delete_user'		=> (int) $user_id, +			'topic_delete_time'		=> ((int) $time) ?: time(), +			'topic_delete_reason'	=> truncate_string($reason, 255, 255, false), +		); + +		$sql = 'UPDATE ' . TOPICS_TABLE . ' +			SET ' . $db->sql_build_array('UPDATE', $data) . ' +			WHERE topic_id = ' . (int) $topic_id; +		$db->sql_query($sql); + +		if (!$db->sql_affectedrows()) +		{ +			return array(); +		} + +		if (!$force_update_all && $original_topic_data['topic_delete_time'] && $original_topic_data['topic_visibility'] == ITEM_DELETED && $visibility == ITEM_APPROVED) +		{ +			// If we're restoring a topic we only restore posts, that were soft deleted through the topic soft deletion. +			self::set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility'], $original_topic_data['topic_delete_time']); +		} +		else if (!$force_update_all && $original_topic_data['topic_visibility'] == ITEM_APPROVED && $visibility == ITEM_DELETED) +		{ +			// If we're soft deleting a topic we only approved posts are soft deleted. +			self::set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true, $original_topic_data['topic_visibility']); +		} +		else +		{ +			self::set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true); +		} + +		return $data; +	} + +	/** +	* Add post to topic and forum statistics +	* +	* @param $data			array	Contains information from the topics table about given topic +	* @param $sql_data		array	Populated with the SQL changes, may be empty at call time +	* @return void +	*/ +	static public function add_post_to_statistic($data, &$sql_data) +	{ +		$sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_approved = topic_posts_approved + 1'; + +		$sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_approved = forum_posts_approved + 1'; + +		if ($data['post_postcount']) +		{ +			$sql_data[USERS_TABLE] = (($sql_data[USERS_TABLE]) ? $sql_data[USERS_TABLE] . ', ' : '') . 'user_posts = user_posts + 1'; +		} + +		set_config_count('num_posts', 1, true); +	} + +	/** +	* Remove post from topic and forum statistics +	* +	* @param $data			array	Contains information from the topics table about given topic +	* @param $sql_data		array	Populated with the SQL changes, may be empty at call time +	* @return void +	*/ +	static public function remove_post_from_statistic($data, &$sql_data) +	{ +		$sql_data[TOPICS_TABLE] = ((!empty($sql_data[TOPICS_TABLE])) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_approved = topic_posts_approved - 1'; +		$sql_data[FORUMS_TABLE] = ((!empty($sql_data[FORUMS_TABLE])) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_approved = forum_posts_approved - 1'; + +		if ($data['post_postcount']) +		{ +			$sql_data[USERS_TABLE] = ((!empty($sql_data[USERS_TABLE])) ? $sql_data[USERS_TABLE] . ', ' : '') . 'user_posts = user_posts - 1'; +		} + +		set_config_count('num_posts', -1, true); +	} + +	/** +	* Remove topic from forum statistics +	* +	* @param $topic_id		int		The topic to act on +	* @param $forum_id		int		Forum where the topic is found +	* @param $topic_row		array	Contains information from the topic, may be empty at call time +	* @param $sql_data		array	Populated with the SQL changes, may be empty at call time +	* @return void +	*/ +	static public function remove_topic_from_statistic($topic_id, $forum_id, &$topic_row, &$sql_data) +	{ +		global $db; + +		// Do we need to grab some topic informations? +		if (!sizeof($topic_row)) +		{ +			$sql = 'SELECT topic_type, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, topic_visibility +				FROM ' . TOPICS_TABLE . ' +				WHERE topic_id = ' . $topic_id; +			$result = $db->sql_query($sql); +			$topic_row = $db->sql_fetchrow($result); +			$db->sql_freeresult($result); +		} + +		// If this is an edited topic or the first post the topic gets completely disapproved later on... +		$sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_topics_approved = forum_topics_approved - 1'; +		$sql_data[FORUMS_TABLE] .= ', forum_posts_approved = forum_posts_approved - ' . $topic_row['topic_posts_approved']; +		$sql_data[FORUMS_TABLE] .= ', forum_posts_unapproved = forum_posts_unapproved - ' . $topic_row['topic_posts_unapproved']; +		$sql_data[FORUMS_TABLE] .= ', forum_posts_softdeleted = forum_posts_softdeleted - ' . $topic_row['topic_posts_softdeleted']; + +		set_config_count('num_topics', -1, true); +		set_config_count('num_posts', $topic_row['topic_posts_approved'] * (-1), true); + +		// Get user post count information +		$sql = 'SELECT poster_id, COUNT(post_id) AS num_posts +			FROM ' . POSTS_TABLE . ' +			WHERE topic_id = ' . $topic_id . ' +				AND post_postcount = 1 +				AND post_visibility = ' . ITEM_APPROVED . ' +			GROUP BY poster_id'; +		$result = $db->sql_query($sql); + +		$postcounts = array(); +		while ($row = $db->sql_fetchrow($result)) +		{ +			$postcounts[(int) $row['num_posts']][] = (int) $row['poster_id']; +		} +		$db->sql_freeresult($result); + +		// Decrement users post count +		foreach ($postcounts as $num_posts => $poster_ids) +		{ +			$sql = 'UPDATE ' . USERS_TABLE . ' +				SET user_posts = 0 +				WHERE user_posts < ' . $num_posts . ' +					AND ' . $db->sql_in_set('user_id', $poster_ids); +			$db->sql_query($sql); + +			$sql = 'UPDATE ' . USERS_TABLE . ' +				SET user_posts = user_posts - ' . $num_posts . ' +				WHERE user_posts >= ' . $num_posts . ' +					AND ' . $db->sql_in_set('user_id', $poster_ids); +			$db->sql_query($sql); +		} +	} +} diff --git a/phpBB/includes/db/migration/data/310/softdelete_p1.php b/phpBB/includes/db/migration/data/310/softdelete_p1.php new file mode 100644 index 0000000000..84f8eebd4a --- /dev/null +++ b/phpBB/includes/db/migration/data/310/softdelete_p1.php @@ -0,0 +1,171 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_softdelete_p1 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return $this->db_tools->sql_column_exists($this->table_prefix . 'posts', 'post_visibility'); +	} + +	static public function depends_on() +	{ +		return array('phpbb_db_migration_data_310_dev'); +	} + +	public function update_schema() +	{ +		return array( +			'add_columns'		=> array( +				$this->table_prefix . 'forums'		=> array( +					'forum_posts_approved'		=> array('UINT', 0), +					'forum_posts_unapproved'	=> array('UINT', 0), +					'forum_posts_softdeleted'	=> array('UINT', 0), +					'forum_topics_approved'		=> array('UINT', 0), +					'forum_topics_unapproved'	=> array('UINT', 0), +					'forum_topics_softdeleted'	=> array('UINT', 0), +				), +				$this->table_prefix . 'posts'		=> array( +					'post_visibility'		=> array('TINT:3', 0), +					'post_delete_time'		=> array('TIMESTAMP', 0), +					'post_delete_reason'	=> array('STEXT_UNI', ''), +					'post_delete_user'		=> array('UINT', 0), +				), +				$this->table_prefix . 'topics'		=> array( +					'topic_visibility'		=> array('TINT:3', 0), +					'topic_delete_time'		=> array('TIMESTAMP', 0), +					'topic_delete_reason'	=> array('STEXT_UNI', ''), +					'topic_delete_user'		=> array('UINT', 0), +					'topic_posts_approved'		=> array('UINT', 0), +					'topic_posts_unapproved'	=> array('UINT', 0), +					'topic_posts_softdeleted'	=> array('UINT', 0), +				), +			), +			'add_index'		=> array( +				$this->table_prefix . 'posts'		=> array( +					'post_visibility'		=> array('post_visibility'), +				), +				$this->table_prefix . 'topics'		=> array( +					'topic_visibility'		=> array('topic_visibility'), +					'forum_vis_last'		=> array('forum_id', 'topic_visibility', 'topic_last_post_id'), +				), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'drop_columns'		=> array( +				$this->table_prefix . 'forums'		=> array( +					'forum_posts_approved', +					'forum_posts_unapproved', +					'forum_posts_softdeleted', +					'forum_topics_approved', +					'forum_topics_unapproved', +					'forum_topics_softdeleted', +				), +				$this->table_prefix . 'posts'		=> array( +					'post_visibility', +					'post_delete_time', +					'post_delete_reason', +					'post_delete_user', +				), +				$this->table_prefix . 'topics'		=> array( +					'topic_visibility', +					'topic_delete_time', +					'topic_delete_reason', +					'topic_delete_user', +					'topic_posts_approved', +					'topic_posts_unapproved', +					'topic_posts_softdeleted', +				), +			), +			'drop_keys'		=> array( +				$this->table_prefix . 'posts'		=> array('post_visibility'), +				$this->table_prefix . 'topics'	=> array('topic_visibility', 'forum_vis_last'), +			), +		); +	} + +	public function update_data() +	{ +		return array( +			array('custom', array(array($this, 'update_post_visibility'))), +			array('custom', array(array($this, 'update_topic_visibility'))), +			array('custom', array(array($this, 'update_topic_forum_counts'))), + +			array('permission.add', array('f_softdelete', false)), +			array('permission.add', array('m_softdelete', false)), +		); +	} + +	public function update_post_visibility() +	{ +		$sql = 'UPDATE ' . $this->table_prefix . 'posts +			SET post_visibility = post_approved'; +		$this->sql_query($sql); +	} + +	public function update_topic_visibility() +	{ +		$sql = 'UPDATE ' . $this->table_prefix . 'topics +			SET topic_visibility = topic_approved'; +		$this->sql_query($sql); +	} + +	public function update_topic_forum_counts() +	{ +		$sql = 'UPDATE ' . $this->table_prefix . 'topics +			SET topic_posts_approved = topic_replies + 1, +				topic_posts_unapproved = topic_replies_real - topic_replies +			WHERE topic_visibility = ' . ITEM_APPROVED; +		$this->sql_query($sql); + +		$sql = 'UPDATE ' . $this->table_prefix . 'topics +			SET topic_posts_approved = 0, +				topic_posts_unapproved = (topic_replies_real - topic_replies) + 1 +			WHERE topic_visibility = ' . ITEM_UNAPPROVED; +		$this->sql_query($sql); + +		$sql = 'SELECT forum_id, topic_visibility, COUNT(topic_id) AS sum_topics, SUM(topic_posts_approved) AS sum_posts_approved, SUM(topic_posts_unapproved) AS sum_posts_unapproved +			FROM ' . $this->table_prefix . 'topics +			GROUP BY forum_id, topic_visibility'; +		$result = $this->db->sql_query($sql); + +		$update_forums = array(); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$forum_id = (int) $row['forum_id']; +			if (!isset($update_forums[$forum_id])) +			{ +				$update_forums[$forum_id] = array( +					'forum_posts_approved'		=> 0, +					'forum_posts_unapproved'	=> 0, +					'forum_topics_approved'		=> 0, +					'forum_topics_unapproved'	=> 0, +				); +			} + +			$update_forums[$forum_id]['forum_posts_approved'] += (int) $row['sum_posts_approved']; +			$update_forums[$forum_id]['forum_posts_unapproved'] += (int) $row['sum_posts_unapproved']; + +			$update_forums[$forum_id][(($row['topic_visibility'] == ITEM_APPROVED) ? 'forum_topics_approved' : 'forum_topics_unapproved')] += (int) $row['sum_topics']; +		} +		$this->db->sql_freeresult($result); + +		foreach ($update_forums as $forum_id => $forum_data) +		{ +			$sql = 'UPDATE ' . FORUMS_TABLE . ' +				SET ' . $this->db->sql_build_array('UPDATE', $forum_data) . ' +				WHERE forum_id = ' . $forum_id; +			$this->sql_query($sql); +		} +	} +} diff --git a/phpBB/includes/db/migration/data/310/softdelete_p2.php b/phpBB/includes/db/migration/data/310/softdelete_p2.php new file mode 100644 index 0000000000..7320a2c2bf --- /dev/null +++ b/phpBB/includes/db/migration/data/310/softdelete_p2.php @@ -0,0 +1,68 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_softdelete_p2 extends phpbb_db_migration +{ +	public function effectively_installed() +	{ +		return !$this->db_tools->sql_column_exists($this->table_prefix . 'posts', 'post_approved'); +	} + +	static public function depends_on() +	{ +		return array( +			'phpbb_db_migration_data_310_dev', +			'phpbb_db_migration_data_310_softdelete_p1', +		); +	} + +	public function update_schema() +	{ +		return array( +			'drop_columns'		=> array( +				$this->table_prefix . 'forums'			=> array('forum_posts', 'forum_topics', 'forum_topics_real'), +				$this->table_prefix . 'posts'			=> array('post_approved'), +				$this->table_prefix . 'topics'			=> array('topic_approved', 'topic_replies', 'topic_replies_real'), +			), +			'drop_keys'		=> array( +				$this->table_prefix . 'posts'			=> array('post_approved'), +				$this->table_prefix . 'topics'			=> array('forum_appr_last'), +			), +		); +	} + +	public function revert_schema() +	{ +		return array( +			'add_columns'		=> array( +				$this->table_prefix . 'forums'			=> array( +					'forum_posts'			=> array('UINT', 0), +					'forum_topics'			=> array('UINT', 0), +					'forum_topics_real'		=> array('UINT', 0), +				), +				$this->table_prefix . 'posts'			=> array( +					'post_approved'			=> array('BOOL', 1), +				), +				$this->table_prefix . 'topics'		=> array( +					'topic_approved'			=> array('BOOL', 1), +					'topic_replies'				=> array('UINT', 0), +					'topic_replies_real'		=> array('UINT', 0), +				), +			), +			'add_index'		=> array( +				$this->table_prefix . 'posts'			=> array( +					'post_approved'		=> array('post_approved'), +				), +				$this->table_prefix . 'topics'		=> array( +					'forum_appr_last'	=> array('forum_id', 'topic_approved', 'topic_last_post_id'), +				), +			), +		); +	} +} diff --git a/phpBB/includes/feed/forum.php b/phpBB/includes/feed/forum.php index 7670fbeaaa..83b836b81d 100644 --- a/phpBB/includes/feed/forum.php +++ b/phpBB/includes/feed/forum.php @@ -90,14 +90,14 @@ class phpbb_feed_forum extends phpbb_feed_post_base  	function get_sql()  	{ -		$m_approve = ($this->auth->acl_get('m_approve', $this->forum_id)) ? true : false; +		$sql_visibility = phpbb_content_visibility::get_visibility_sql('topic', $this->forum_id);  		// Determine topics with recent activity  		$sql = 'SELECT topic_id, topic_last_post_time  			FROM ' . TOPICS_TABLE . '  			WHERE forum_id = ' . $this->forum_id . '  				AND topic_moved_id = 0 -				' . ((!$m_approve) ? 'AND topic_approved = 1' : '') . ' +				' . (($sql_visibility) ? ' AND ' . $sql_visibility : '') . '  			ORDER BY topic_last_post_time DESC';  		$result = $this->db->sql_query_limit($sql, $this->num_items); @@ -116,15 +116,17 @@ class phpbb_feed_forum extends phpbb_feed_post_base  			return false;  		} +		$sql_visibility = phpbb_content_visibility::get_visibility_sql('post', $this->forum_id, 'p.');  +  		$this->sql = array( -			'SELECT'	=>	'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' . +			'SELECT'	=>	'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .  							'u.username, u.user_id',  			'FROM'		=> array(  				POSTS_TABLE		=> 'p',  				USERS_TABLE		=> 'u',  			),  			'WHERE'		=> $this->db->sql_in_set('p.topic_id', $topic_ids) . ' -							' . ((!$m_approve) ? 'AND p.post_approved = 1' : '') . ' +							' . (($sql_visibility) ? ' AND ' . $sql_visibility : '') . '  							AND p.post_time >= ' . $min_post_time . '  							AND p.poster_id = u.user_id',  			'ORDER_BY'	=> 'p.post_time DESC', diff --git a/phpBB/includes/feed/forums.php b/phpBB/includes/feed/forums.php index 72f786aa6a..409097a9f3 100644 --- a/phpBB/includes/feed/forums.php +++ b/phpBB/includes/feed/forums.php @@ -49,7 +49,7 @@ class phpbb_feed_forums extends phpbb_feed_base  		$this->sql = array(  			'SELECT'	=> 'f.forum_id, f.left_id, f.forum_name, f.forum_last_post_time,  							f.forum_desc, f.forum_desc_bitfield, f.forum_desc_uid, f.forum_desc_options, -							f.forum_topics, f.forum_posts', +							f.forum_topics_approved, f.forum_posts_approved',  			'FROM'		=> array(FORUMS_TABLE => 'f'),  			'WHERE'		=> 'f.forum_type = ' . FORUM_POST . '  							AND ' . $this->db->sql_in_set('f.forum_id', $in_fid_ary), @@ -65,8 +65,8 @@ class phpbb_feed_forums extends phpbb_feed_base  		if ($this->config['feed_item_statistics'])  		{ -			$item_row['statistics'] = $this->user->lang('TOTAL_TOPICS', (int) $row['forum_topics']) -				. ' ' . $this->separator_stats . ' ' . $this->user->lang('TOTAL_POSTS_COUNT', (int) $row['forum_posts']); +			$item_row['statistics'] = $this->user->lang('TOTAL_TOPICS', (int) $row['forum_topics_approved']) +				. ' ' . $this->separator_stats . ' ' . $this->user->lang('TOTAL_POSTS_COUNT', (int) $row['forum_posts_approved']);  		}  	}  } diff --git a/phpBB/includes/feed/news.php b/phpBB/includes/feed/news.php index 92cc18a3ab..f2d45b5165 100644 --- a/phpBB/includes/feed/news.php +++ b/phpBB/includes/feed/news.php @@ -72,7 +72,7 @@ class phpbb_feed_news extends phpbb_feed_topic_base  			FROM ' . TOPICS_TABLE . '  			WHERE ' . $this->db->sql_in_set('forum_id', $in_fid_ary) . '  				AND topic_moved_id = 0 -				AND topic_approved = 1 +				AND topic_visibility = ' . ITEM_APPROVED . '  			ORDER BY topic_time DESC';  		$result = $this->db->sql_query_limit($sql, $this->num_items); @@ -90,7 +90,7 @@ class phpbb_feed_news extends phpbb_feed_topic_base  		$this->sql = array(  			'SELECT'	=> 'f.forum_id, f.forum_name, -							t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time, +							t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_views, t.topic_time, t.topic_last_post_time,  							p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',  			'FROM'		=> array(  				TOPICS_TABLE	=> 't', diff --git a/phpBB/includes/feed/overall.php b/phpBB/includes/feed/overall.php index 5fb922f6bb..7e48120b97 100644 --- a/phpBB/includes/feed/overall.php +++ b/phpBB/includes/feed/overall.php @@ -33,17 +33,11 @@ class phpbb_feed_overall extends phpbb_feed_post_base  			return false;  		} -		// m_approve forums -		$fid_m_approve = $this->get_moderator_approve_forums(); -		$sql_m_approve = (!empty($fid_m_approve)) ? 'OR ' . $this->db->sql_in_set('forum_id', $fid_m_approve) : ''; -  		// Determine topics with recent activity  		$sql = 'SELECT topic_id, topic_last_post_time  			FROM ' . TOPICS_TABLE . ' -			WHERE ' . $this->db->sql_in_set('forum_id', $forum_ids) . ' -				AND topic_moved_id = 0 -				AND (topic_approved = 1 -					' . $sql_m_approve . ') +			WHERE topic_moved_id = 0 +				AND ' . phpbb_content_visibility::get_forums_visibility_sql('topic', $forum_ids) . '  			ORDER BY topic_last_post_time DESC';  		$result = $this->db->sql_query_limit($sql, $this->num_items); @@ -62,10 +56,12 @@ class phpbb_feed_overall extends phpbb_feed_post_base  			return false;  		} +		$sql_visibility = phpbb_content_visibility::get_visibility_sql('post', array(), 'p.'); +  		// Get the actual data  		$this->sql = array(  			'SELECT'	=>	'f.forum_id, f.forum_name, ' . -							'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' . +							'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .  							'u.username, u.user_id',  			'FROM'		=> array(  				USERS_TABLE		=> 'u', @@ -78,8 +74,7 @@ class phpbb_feed_overall extends phpbb_feed_post_base  				),  			),  			'WHERE'		=> $this->db->sql_in_set('p.topic_id', $topic_ids) . ' -							AND (p.post_approved = 1 -								' . str_replace('forum_id', 'p.forum_id', $sql_m_approve) . ') +							' . (($sql_visibility) ? ' AND ' . $sql_visibility : '') . '  							AND p.post_time >= ' . $min_post_time . '  							AND u.user_id = p.poster_id',  			'ORDER_BY'	=> 'p.post_time DESC', diff --git a/phpBB/includes/feed/post_base.php b/phpBB/includes/feed/post_base.php index a25ed50263..1f4cb4b5ef 100644 --- a/phpBB/includes/feed/post_base.php +++ b/phpBB/includes/feed/post_base.php @@ -51,7 +51,7 @@ abstract class phpbb_feed_post_base extends phpbb_feed_base  		{  			$item_row['statistics'] = $this->user->lang['POSTED'] . ' ' . $this->user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row)  				. ' ' . $this->separator_stats . ' ' . $this->user->format_date($row[$this->get('published')]) -				. (($this->is_moderator_approve_forum($row['forum_id']) && !$row['post_approved']) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POST_UNAPPROVED'] : ''); +				. (($this->is_moderator_approve_forum($row['forum_id']) && $row['post_visibility'] !== ITEM_APPROVED) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POST_UNAPPROVED'] : '');  		}  	}  } diff --git a/phpBB/includes/feed/topic.php b/phpBB/includes/feed/topic.php index 7d9a344982..42bd291343 100644 --- a/phpBB/includes/feed/topic.php +++ b/phpBB/includes/feed/topic.php @@ -43,7 +43,7 @@ class phpbb_feed_topic extends phpbb_feed_post_base  	function open()  	{ -		$sql = 'SELECT f.forum_options, f.forum_password, t.topic_id, t.forum_id, t.topic_approved, t.topic_title, t.topic_time, t.topic_views, t.topic_replies, t.topic_type +		$sql = 'SELECT f.forum_options, f.forum_password, t.topic_id, t.forum_id, t.topic_visibility, t.topic_title, t.topic_time, t.topic_views, t.topic_replies, t.topic_type  			FROM ' . TOPICS_TABLE . ' t  			LEFT JOIN ' . FORUMS_TABLE . ' f  				ON (f.forum_id = t.forum_id) @@ -93,15 +93,17 @@ class phpbb_feed_topic extends phpbb_feed_post_base  	function get_sql()  	{ +		$sql_visibility = phpbb_content_visibility::get_visibility_sql('post', $this->forum_id, 'p.');  +  		$this->sql = array( -			'SELECT'	=>	'p.post_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' . +			'SELECT'	=>	'p.post_id, p.post_time, p.post_edit_time, p.post_visibility, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .  							'u.username, u.user_id',  			'FROM'		=> array(  				POSTS_TABLE		=> 'p',  				USERS_TABLE		=> 'u',  			),  			'WHERE'		=> 'p.topic_id = ' . $this->topic_id . ' -								' . ($this->forum_id && !$this->auth->acl_get('m_approve', $this->forum_id) ? 'AND p.post_approved = 1' : '') . ' +								' . (($sql_visibility) ? ' AND ' . $sql_visibility : '') . '  								AND p.poster_id = u.user_id',  			'ORDER_BY'	=> 'p.post_time DESC',  		); diff --git a/phpBB/includes/feed/topic_base.php b/phpBB/includes/feed/topic_base.php index e6a47b4c86..a2f5a56f1d 100644 --- a/phpBB/includes/feed/topic_base.php +++ b/phpBB/includes/feed/topic_base.php @@ -51,9 +51,9 @@ abstract class phpbb_feed_topic_base extends phpbb_feed_base  		{  			$item_row['statistics'] = $this->user->lang['POSTED'] . ' ' . $this->user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row)  				. ' ' . $this->separator_stats . ' ' . $this->user->format_date($row[$this->get('published')]) -				. ' ' . $this->separator_stats . ' ' . $this->user->lang['REPLIES'] . ' ' . (($this->is_moderator_approve_forum($row['forum_id'])) ? $row['topic_replies_real'] : $row['topic_replies']) +				. ' ' . $this->separator_stats . ' ' . $this->user->lang['REPLIES'] . ' ' . phpbb_content_visibility::get_count('topic_posts', $row, $row['forum_id']) - 1  				. ' ' . $this->separator_stats . ' ' . $this->user->lang['VIEWS'] . ' ' . $row['topic_views'] -				. (($this->is_moderator_approve_forum($row['forum_id']) && ($row['topic_replies_real'] != $row['topic_replies'])) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POSTS_UNAPPROVED'] : ''); +				. (($this->is_moderator_approve_forum($row['forum_id']) && $row['topic_posts_unapproved']) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POSTS_UNAPPROVED'] : '');  		}  	}  } diff --git a/phpBB/includes/feed/topics.php b/phpBB/includes/feed/topics.php index c8761d7176..31f5177773 100644 --- a/phpBB/includes/feed/topics.php +++ b/phpBB/includes/feed/topics.php @@ -44,7 +44,7 @@ class phpbb_feed_topics extends phpbb_feed_topic_base  			FROM ' . TOPICS_TABLE . '  			WHERE ' . $this->db->sql_in_set('forum_id', $in_fid_ary) . '  				AND topic_moved_id = 0 -				AND topic_approved = 1 +				AND topic_visibility = ' . ITEM_APPROVED . '  			ORDER BY topic_time DESC';  		$result = $this->db->sql_query_limit($sql, $this->num_items); @@ -62,7 +62,7 @@ class phpbb_feed_topics extends phpbb_feed_topic_base  		$this->sql = array(  			'SELECT'	=> 'f.forum_id, f.forum_name, -							t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time, +							t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_views, t.topic_time, t.topic_last_post_time,  							p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',  			'FROM'		=> array(  				TOPICS_TABLE	=> 't', diff --git a/phpBB/includes/feed/topics_active.php b/phpBB/includes/feed/topics_active.php index d1c920c136..249dd1d66a 100644 --- a/phpBB/includes/feed/topics_active.php +++ b/phpBB/includes/feed/topics_active.php @@ -59,7 +59,7 @@ class phpbb_feed_topics_active extends phpbb_feed_topic_base  			FROM ' . TOPICS_TABLE . '  			WHERE ' . $this->db->sql_in_set('forum_id', $in_fid_ary) . '  				AND topic_moved_id = 0 -				AND topic_approved = 1 +				AND topic_visibility = ' . ITEM_APPROVED . '  				' . $last_post_time_sql . '  			ORDER BY topic_last_post_time DESC';  		$result = $this->db->sql_query_limit($sql, $this->num_items); @@ -78,7 +78,7 @@ class phpbb_feed_topics_active extends phpbb_feed_topic_base  		$this->sql = array(  			'SELECT'	=> 'f.forum_id, f.forum_name, -							t.topic_id, t.topic_title, t.topic_replies, t.topic_replies_real, t.topic_views, +							t.topic_id, t.topic_title, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_views,  							t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_post_time,  							p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',  			'FROM'		=> array( diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 6a1b3fd4f8..e884a2f94c 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1999,7 +1999,8 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti  	// Handle update of unapproved topics info.  	// Only update for moderators having m_approve permission for the forum. -	$sql_update_unapproved = ($auth->acl_get('m_approve', $forum_id)) ? '': 'AND t.topic_approved = 1'; +	$sql_update_unapproved = phpbb_content_visibility::get_visibility_sql('topic', $forum_id, 't.'); +	$sql_update_unapproved = ($sql_update_unapproved) ? ' AND ' . $sql_update_unapproved : '';  	// Check the forum for any left unread topics.  	// If there are none, we mark the forum as read. diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 21662eb493..fc29492ac1 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -644,7 +644,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s  		'posts' => ($call_delete_posts) ? delete_posts($where_type, $where_ids, false, true, $post_count_sync, false) : 0,  	); -	$sql = 'SELECT topic_id, forum_id, topic_approved, topic_moved_id +	$sql = 'SELECT topic_id, forum_id, topic_visibility, topic_moved_id  		FROM ' . TOPICS_TABLE . '  		WHERE ' . $where_clause;  	$result = $db->sql_query($sql); @@ -654,7 +654,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s  		$forum_ids[] = $row['forum_id'];  		$topic_ids[] = $row['topic_id']; -		if ($row['topic_approved'] && !$row['topic_moved_id']) +		if ($row['topic_visibility'] == ITEM_APPROVED && !$row['topic_moved_id'])  		{  			$approved_topics++;  		} @@ -775,7 +775,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =  	$approved_posts = 0;  	$post_ids = $topic_ids = $forum_ids = $post_counts = $remove_topics = array(); -	$sql = 'SELECT post_id, poster_id, post_approved, post_postcount, topic_id, forum_id +	$sql = 'SELECT post_id, poster_id, post_visibility, post_postcount, topic_id, forum_id  		FROM ' . POSTS_TABLE . '  		WHERE ' . $where_clause;  	$result = $db->sql_query($sql); @@ -787,12 +787,12 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =  		$topic_ids[] = (int) $row['topic_id'];  		$forum_ids[] = (int) $row['forum_id']; -		if ($row['post_postcount'] && $post_count_sync && $row['post_approved']) +		if ($row['post_postcount'] && $post_count_sync && $row['post_visibility'] == ITEM_APPROVED)  		{  			$post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1;  		} -		if ($row['post_approved']) +		if ($row['post_visibility'] == ITEM_APPROVED)  		{  			$approved_posts++;  		} @@ -889,7 +889,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =  		sync('forum', 'forum_id', $forum_ids, true, true);  	} -	if ($approved_posts) +	if ($approved_posts && $post_count_sync)  	{  		set_config_count('num_posts', $approved_posts * (-1), true);  	} @@ -1292,7 +1292,7 @@ function phpbb_unlink($filename, $mode = 'file', $entry_removed = false)  * - forum				Resync complete forum  * - topic				Resync topics  * - topic_moved			Removes topic shadows that would be in the same forum as the topic they link to -* - topic_approved		Resyncs the topic_approved flag according to the status of the first post +* - topic_visibility	Resyncs the topic_visibility flag according to the status of the first post  * - post_reported		Resyncs the post_reported flag, relying on actual reports  * - topic_reported		Resyncs the topic_reported flag, relying on post_reported flags  * - post_attachement	Same as post_reported, but with attachment flags @@ -1312,7 +1312,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  		$where_ids = ($where_ids) ? array((int) $where_ids) : array();  	} -	if ($mode == 'forum' || $mode == 'topic' || $mode == 'topic_approved' || $mode == 'topic_reported' || $mode == 'post_reported') +	if ($mode == 'forum' || $mode == 'topic' || $mode == 'topic_visibility' || $mode == 'topic_reported' || $mode == 'post_reported')  	{  		if (!$where_type)  		{ @@ -1398,43 +1398,55 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  			$db->sql_transaction('commit');  			break; -		case 'topic_approved': +		case 'topic_visibility':  			$db->sql_transaction('begin'); -			switch ($db->sql_layer) + +			$sql = 'SELECT t.topic_id, p.post_visibility +				FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p +				$where_sql_and p.topic_id = t.topic_id +					AND p.post_visibility = " . ITEM_APPROVED; +			$result = $db->sql_query($sql); + +			$topics_approved = array(); +			while ($row = $db->sql_fetchrow($result))  			{ -				case 'mysql4': -				case 'mysqli': -					$sql = 'UPDATE ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p -						SET t.topic_approved = p.post_approved -						$where_sql_and t.topic_first_post_id = p.post_id"; -					$db->sql_query($sql); -				break; +				$topics_approved[] = (int) $row['topic_id']; +			} +			$db->sql_freeresult($result); -				default: -					$sql = 'SELECT t.topic_id, p.post_approved -						FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p -						$where_sql_and p.post_id = t.topic_first_post_id -							AND p.post_approved <> t.topic_approved"; -					$result = $db->sql_query($sql); +			$sql = 'SELECT t.topic_id, p.post_visibility +				FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p +				$where_sql_and " . $db->sql_in_set('t.topic_id', $topics_approved, true, true) . ' +					AND p.topic_id = t.topic_id +					AND p.post_visibility = ' . ITEM_DELETED; +			$result = $db->sql_query($sql); -					$topic_ids = array(); -					while ($row = $db->sql_fetchrow($result)) -					{ -						$topic_ids[] = $row['topic_id']; -					} -					$db->sql_freeresult($result); +			$topics_softdeleted = array(); +			while ($row = $db->sql_fetchrow($result)) +			{ +				$topics_softdeleted[] = (int) $row['topic_id']; +			} +			$db->sql_freeresult($result); -					if (!sizeof($topic_ids)) -					{ -						return; -					} +			$topics_softdeleted = array_diff($topics_softdeleted, $topics_approved); +			$topics_not_unapproved = array_merge($topics_softdeleted, $topics_approved); + +			$update_ary = array( +				ITEM_UNAPPROVED	=> (!empty($topics_not_unapproved)) ? $where_sql_and . ' ' . $db->sql_in_set('topic_id', $topics_not_unapproved, true) : '', +				ITEM_APPROVED	=> (!empty($topics_approved)) ? ' WHERE ' . $db->sql_in_set('topic_id', $topics_approved) : '', +				ITEM_DELETED	=> (!empty($topics_softdeleted)) ? ' WHERE ' . $db->sql_in_set('topic_id', $topics_softdeleted) : '', +			); +			foreach ($topic_visiblities as $visibility => $sql_where) +			{ +				if ($sql_where) +				{  					$sql = 'UPDATE ' . TOPICS_TABLE . ' -						SET topic_approved = 1 - topic_approved -						WHERE ' . $db->sql_in_set('topic_id', $topic_ids); +						SET topic_visibility = ' . $visibility . ' +						' . $sql_where;  					$db->sql_query($sql); -				break; +				}  			}  			$db->sql_transaction('commit'); @@ -1675,9 +1687,12 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  				$forum_data[$forum_id] = $row;  				if ($sync_extra)  				{ -					$forum_data[$forum_id]['posts'] = 0; -					$forum_data[$forum_id]['topics'] = 0; -					$forum_data[$forum_id]['topics_real'] = 0; +					$forum_data[$forum_id]['posts_approved'] = 0; +					$forum_data[$forum_id]['posts_unapproved'] = 0; +					$forum_data[$forum_id]['posts_softdeleted'] = 0; +					$forum_data[$forum_id]['topics_approved'] = 0; +					$forum_data[$forum_id]['topics_unapproved'] = 0; +					$forum_data[$forum_id]['topics_softdeleted'] = 0;  				}  				$forum_data[$forum_id]['last_post_id'] = 0;  				$forum_data[$forum_id]['last_post_subject'] = ''; @@ -1698,20 +1713,27 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  			// 2: Get topic counts for each forum (optional)  			if ($sync_extra)  			{ -				$sql = 'SELECT forum_id, topic_approved, COUNT(topic_id) AS forum_topics +				$sql = 'SELECT forum_id, topic_visibility, COUNT(topic_id) AS total_topics  					FROM ' . TOPICS_TABLE . '  					WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . ' -					GROUP BY forum_id, topic_approved'; +					GROUP BY forum_id, topic_visibility';  				$result = $db->sql_query($sql);  				while ($row = $db->sql_fetchrow($result))  				{  					$forum_id = (int) $row['forum_id']; -					$forum_data[$forum_id]['topics_real'] += $row['forum_topics']; -					if ($row['topic_approved']) +					if ($row['topic_visibility'] == ITEM_APPROVED)  					{ -						$forum_data[$forum_id]['topics'] = $row['forum_topics']; +						$forum_data[$forum_id]['topics_approved'] = $row['total_topics']; +					} +					else if ($row['topic_visibility'] == ITEM_UNAPPROVED) +					{ +						$forum_data[$forum_id]['topics_unapproved'] = $row['total_topics']; +					} +					else if ($row['topic_visibility'] == ITEM_DELETED) +					{ +						$forum_data[$forum_id]['topics_softdeleted'] = $row['total_topics'];  					}  				}  				$db->sql_freeresult($result); @@ -1722,18 +1744,16 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  			{  				if (sizeof($forum_ids) == 1)  				{ -					$sql = 'SELECT SUM(t.topic_replies + 1) AS forum_posts +					$sql = 'SELECT SUM(t.topic_posts_approved) AS forum_posts_approved, SUM(t.topic_posts_unapproved) AS forum_posts_unapproved, SUM(t.topic_posts_softdeleted) AS forum_posts_softdeleted  						FROM ' . TOPICS_TABLE . ' t  						WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . ' -							AND t.topic_approved = 1  							AND t.topic_status <> ' . ITEM_MOVED;  				}  				else  				{ -					$sql = 'SELECT t.forum_id, SUM(t.topic_replies + 1) AS forum_posts +					$sql = 'SELECT t.forum_id, SUM(t.topic_posts_approved) AS forum_posts_approved, SUM(t.topic_posts_unapproved) AS forum_posts_unapproved, SUM(t.topic_posts_softdeleted) AS forum_posts_softdeleted  						FROM ' . TOPICS_TABLE . ' t  						WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . ' -							AND t.topic_approved = 1  							AND t.topic_status <> ' . ITEM_MOVED . '  						GROUP BY t.forum_id';  				} @@ -1744,7 +1764,9 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  				{  					$forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; -					$forum_data[$forum_id]['posts'] = (int) $row['forum_posts']; +					$forum_data[$forum_id]['posts_approved'] = (int) $row['forum_posts_approved']; +					$forum_data[$forum_id]['posts_unapproved'] = (int) $row['forum_posts_unapproved']; +					$forum_data[$forum_id]['posts_softdeleted'] = (int) $row['forum_posts_softdeleted'];  				}  				$db->sql_freeresult($result);  			} @@ -1755,14 +1777,14 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  				$sql = 'SELECT MAX(t.topic_last_post_id) as last_post_id  					FROM ' . TOPICS_TABLE . ' t  					WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . ' -						AND t.topic_approved = 1'; +						AND t.topic_visibility = ' . ITEM_APPROVED;  			}  			else  			{  				$sql = 'SELECT t.forum_id, MAX(t.topic_last_post_id) as last_post_id  					FROM ' . TOPICS_TABLE . ' t  					WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . ' -						AND t.topic_approved = 1 +						AND t.topic_visibility = ' . ITEM_APPROVED . '  					GROUP BY t.forum_id';  			} @@ -1825,7 +1847,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  			if ($sync_extra)  			{ -				array_push($fieldnames, 'posts', 'topics', 'topics_real'); +				array_push($fieldnames, 'posts_approved', 'posts_unapproved', 'posts_softdeleted', 'topics_approved', 'topics_unapproved', 'topics_softdeleted');  			}  			foreach ($forum_data as $forum_id => $row) @@ -1860,11 +1882,11 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  			break;  		case 'topic': -			$topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array(); +			$topic_data = $post_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array();  			$db->sql_transaction('begin'); -			$sql = 'SELECT t.topic_id, t.forum_id, t.topic_moved_id, t.topic_approved, ' . (($sync_extra) ? 't.topic_attachment, t.topic_reported, ' : '') . 't.topic_poster, t.topic_time, t.topic_replies, t.topic_replies_real, t.topic_first_post_id, t.topic_first_poster_name, t.topic_first_poster_colour, t.topic_last_post_id, t.topic_last_post_subject, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_poster_colour, t.topic_last_post_time +			$sql = 'SELECT t.topic_id, t.forum_id, t.topic_moved_id, t.topic_visibility, ' . (($sync_extra) ? 't.topic_attachment, t.topic_reported, ' : '') . 't.topic_poster, t.topic_time, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_first_post_id, t.topic_first_poster_name, t.topic_first_poster_colour, t.topic_last_post_id, t.topic_last_post_subject, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_poster_colour, t.topic_last_post_time  				FROM ' . TOPICS_TABLE . " t  				$where_sql";  			$result = $db->sql_query($sql); @@ -1879,8 +1901,10 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  				$topic_id = (int) $row['topic_id'];  				$topic_data[$topic_id] = $row; -				$topic_data[$topic_id]['replies_real'] = -1; -				$topic_data[$topic_id]['replies'] = 0; +				$topic_data[$topic_id]['visibility'] = ITEM_UNAPPROVED; +				$topic_data[$topic_id]['posts_approved'] = 0; +				$topic_data[$topic_id]['posts_unapproved'] = 0; +				$topic_data[$topic_id]['posts_softdeleted'] = 0;  				$topic_data[$topic_id]['first_post_id'] = 0;  				$topic_data[$topic_id]['last_post_id'] = 0;  				unset($topic_data[$topic_id]['topic_id']); @@ -1897,11 +1921,11 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  			$db->sql_freeresult($result);  			// Use "t" as table alias because of the $where_sql clause -			// NOTE: 't.post_approved' in the GROUP BY is causing a major slowdown. -			$sql = 'SELECT t.topic_id, t.post_approved, COUNT(t.post_id) AS total_posts, MIN(t.post_id) AS first_post_id, MAX(t.post_id) AS last_post_id +			// NOTE: 't.post_visibility' in the GROUP BY is causing a major slowdown. +			$sql = 'SELECT t.topic_id, t.post_visibility, COUNT(t.post_id) AS total_posts, MIN(t.post_id) AS first_post_id, MAX(t.post_id) AS last_post_id  				FROM ' . POSTS_TABLE . " t  				$where_sql -				GROUP BY t.topic_id, t.post_approved"; +				GROUP BY t.topic_id, t.post_visibility";  			$result = $db->sql_query($sql);  			while ($row = $db->sql_fetchrow($result)) @@ -1922,14 +1946,38 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  					// When we'll be done, only topics with no posts will remain  					unset($delete_topics[$topic_id]); -					$topic_data[$topic_id]['replies_real'] += $row['total_posts']; -					$topic_data[$topic_id]['first_post_id'] = (!$topic_data[$topic_id]['first_post_id']) ? $row['first_post_id'] : min($topic_data[$topic_id]['first_post_id'], $row['first_post_id']); +					if ($row['post_visibility'] == ITEM_APPROVED) +					{ +						$topic_data[$topic_id]['posts_approved'] = $row['total_posts']; +					} +					else if ($row['post_visibility'] == ITEM_UNAPPROVED) +					{ +						$topic_data[$topic_id]['posts_unapproved'] = $row['total_posts']; +					} +					else if ($row['post_visibility'] == ITEM_DELETED) +					{ +						$topic_data[$topic_id]['posts_softdeleted'] = $row['total_posts']; +					} -					if ($row['post_approved'] || !$topic_data[$topic_id]['last_post_id']) +					if ($row['post_visibility'] == ITEM_APPROVED)  					{ -						$topic_data[$topic_id]['replies'] = $row['total_posts'] - 1; +						$topic_data[$topic_id]['visibility'] = ITEM_APPROVED; +						$topic_data[$topic_id]['first_post_id'] = $row['first_post_id'];  						$topic_data[$topic_id]['last_post_id'] = $row['last_post_id'];  					} +					else if ($topic_data[$topic_id]['visibility'] != ITEM_APPROVED) +					{ +						// If there is no approved post, we take the min/max of the other visibilities +						// for the last and first post info, because it is only visible to moderators anyway +						$topic_data[$topic_id]['first_post_id'] = (!empty($topic_data[$topic_id]['first_post_id'])) ? min($topic_data[$topic_id]['first_post_id'], $row['first_post_id']) : $row['first_post_id']; +						$topic_data[$topic_id]['last_post_id'] = max($topic_data[$topic_id]['last_post_id'], $row['last_post_id']); + +						if ($topic_data[$topic_id]['visibility'] == ITEM_UNAPPROVED) +						{ +							// Soft delete status is stronger than unapproved. +							$topic_data[$topic_id]['visibility'] = $row['post_visibility']; +						} +					}  				}  			}  			$db->sql_freeresult($result); @@ -1970,7 +2018,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  				unset($delete_topics, $delete_topic_ids);  			} -			$sql = 'SELECT p.post_id, p.topic_id, p.post_approved, p.poster_id, p.post_subject, p.post_username, p.post_time, u.username, u.user_colour +			$sql = 'SELECT p.post_id, p.topic_id, p.post_visibility, p.poster_id, p.post_subject, p.post_username, p.post_time, u.username, u.user_colour  				FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u  				WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . '  					AND u.user_id = p.poster_id'; @@ -1983,10 +2031,6 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  				if ($row['post_id'] == $topic_data[$topic_id]['first_post_id'])  				{ -					if ($topic_data[$topic_id]['topic_approved'] != $row['post_approved']) -					{ -						$approved_unapproved_ids[] = $topic_id; -					}  					$topic_data[$topic_id]['time'] = $row['post_time'];  					$topic_data[$topic_id]['poster'] = $row['poster_id'];  					$topic_data[$topic_id]['first_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']; @@ -2047,7 +2091,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  				$sync_shadow_topics = array();  				if (sizeof($post_ids))  				{ -					$sql = 'SELECT p.post_id, p.topic_id, p.post_approved, p.poster_id, p.post_subject, p.post_username, p.post_time, u.username, u.user_colour +					$sql = 'SELECT p.post_id, p.topic_id, p.post_visibility, p.poster_id, p.post_subject, p.post_username, p.post_time, u.username, u.user_colour  						FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u  						WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . '  							AND u.user_id = p.poster_id'; @@ -2114,18 +2158,8 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  				unset($sync_shadow_topics, $shadow_topic_data);  			} -			// approved becomes unapproved, and vice-versa -			if (sizeof($approved_unapproved_ids)) -			{ -				$sql = 'UPDATE ' . TOPICS_TABLE . ' -					SET topic_approved = 1 - topic_approved -					WHERE ' . $db->sql_in_set('topic_id', $approved_unapproved_ids); -				$db->sql_query($sql); -			} -			unset($approved_unapproved_ids); -  			// These are fields that will be synchronised -			$fieldnames = array('time', 'replies', 'replies_real', 'poster', 'first_post_id', 'first_poster_name', 'first_poster_colour', 'last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour'); +			$fieldnames = array('time', 'visibility', 'posts_approved', 'posts_unapproved', 'posts_softdeleted', 'poster', 'first_post_id', 'first_poster_name', 'first_poster_colour', 'last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour');  			if ($sync_extra)  			{ diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php index ac791e0d9b..a34a193f60 100644 --- a/phpBB/includes/functions_convert.php +++ b/phpBB/includes/functions_convert.php @@ -1768,7 +1768,7 @@ function sync_post_count($offset, $limit)  	$sql = 'SELECT COUNT(post_id) AS num_posts, poster_id  			FROM ' . POSTS_TABLE . '  			WHERE post_postcount = 1 -				AND post_approved = 1 +				AND post_visibility = ' . ITEM_APPROVED . '  			GROUP BY poster_id  			ORDER BY poster_id';  	$result = $db->sql_query_limit($sql, $limit, $offset); @@ -1941,7 +1941,7 @@ function update_dynamic_config()  	$sql = 'SELECT COUNT(post_id) AS stat  		FROM ' . POSTS_TABLE . ' -		WHERE post_approved = 1'; +		WHERE post_visibility = ' . ITEM_APPROVED;  	$result = $db->sql_query($sql);  	$row = $db->sql_fetchrow($result);  	$db->sql_freeresult($result); @@ -1950,7 +1950,7 @@ function update_dynamic_config()  	$sql = 'SELECT COUNT(topic_id) AS stat  		FROM ' . TOPICS_TABLE . ' -		WHERE topic_approved = 1'; +		WHERE topic_visibility = ' . ITEM_APPROVED;  	$result = $db->sql_query($sql);  	$row = $db->sql_fetchrow($result);  	$db->sql_freeresult($result); diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 9854cd6d70..797ca718d8 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -214,8 +214,9 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod  		}  		// Count the difference of real to public topics, so we can display an information to moderators -		$row['forum_id_unapproved_topics'] = ($auth->acl_get('m_approve', $forum_id) && ($row['forum_topics_real'] != $row['forum_topics'])) ? $forum_id : 0; -		$row['forum_topics'] = ($auth->acl_get('m_approve', $forum_id)) ? $row['forum_topics_real'] : $row['forum_topics']; +		$row['forum_id_unapproved_topics'] = ($auth->acl_get('m_approve', $forum_id) && $row['forum_topics_unapproved']) ? $forum_id : 0; +		$row['forum_posts'] = phpbb_content_visibility::get_count('forum_posts', $row, $forum_id); +		$row['forum_topics'] = phpbb_content_visibility::get_count('forum_topics', $row, $forum_id);  		// Display active topics from this forum?  		if ($show_active && $row['forum_type'] == FORUM_POST && $auth->acl_get('f_read', $forum_id) && ($row['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS)) @@ -815,7 +816,7 @@ function gen_forum_auth_level($mode, $forum_id, $forum_status)  		($auth->acl_get('f_post', $forum_id) && !$locked) ? $user->lang['RULES_POST_CAN'] : $user->lang['RULES_POST_CANNOT'],  		($auth->acl_get('f_reply', $forum_id) && !$locked) ? $user->lang['RULES_REPLY_CAN'] : $user->lang['RULES_REPLY_CANNOT'],  		($user->data['is_registered'] && $auth->acl_gets('f_edit', 'm_edit', $forum_id) && !$locked) ? $user->lang['RULES_EDIT_CAN'] : $user->lang['RULES_EDIT_CANNOT'], -		($user->data['is_registered'] && $auth->acl_gets('f_delete', 'm_delete', $forum_id) && !$locked) ? $user->lang['RULES_DELETE_CAN'] : $user->lang['RULES_DELETE_CANNOT'], +		($user->data['is_registered'] && ($auth->acl_gets('f_delete', 'm_delete', $forum_id) || $auth->acl_gets('f_softdelete', 'm_softdelete', $forum_id)) && !$locked) ? $user->lang['RULES_DELETE_CAN'] : $user->lang['RULES_DELETE_CANNOT'],  	);  	if ($config['allow_attachments']) @@ -1015,73 +1016,63 @@ function display_user_activity(&$userdata)  	$forum_ary = array(); -	// Do not include those forums the user is not having read access to... -	$forum_read_ary = $auth->acl_getf('!f_read'); - -	foreach ($forum_read_ary as $forum_id => $not_allowed) +	$forum_read_ary = $auth->acl_getf('f_read'); +	foreach ($forum_read_ary as $forum_id => $allowed)  	{ -		if ($not_allowed['f_read']) +		if ($allowed['f_read'])  		{  			$forum_ary[] = (int) $forum_id;  		}  	} -	$forum_ary = array_unique($forum_ary); -	$forum_sql = (sizeof($forum_ary)) ? 'AND ' . $db->sql_in_set('forum_id', $forum_ary, true) : ''; - -	$fid_m_approve = $auth->acl_getf('m_approve', true); -	$sql_m_approve = (!empty($fid_m_approve)) ? 'OR ' . $db->sql_in_set('forum_id', array_keys($fid_m_approve)) : ''; - -	// Obtain active forum -	$sql = 'SELECT forum_id, COUNT(post_id) AS num_posts -		FROM ' . POSTS_TABLE . ' -		WHERE poster_id = ' . $userdata['user_id'] . " -			AND post_postcount = 1 -			AND (post_approved = 1 -				$sql_m_approve) -			$forum_sql -		GROUP BY forum_id -		ORDER BY num_posts DESC"; -	$result = $db->sql_query_limit($sql, 1); -	$active_f_row = $db->sql_fetchrow($result); -	$db->sql_freeresult($result); +	$forum_ary = array_diff($forum_ary, $user->get_passworded_forums()); -	if (!empty($active_f_row)) +	$active_f_row = $active_t_row = array(); +	if (!empty($forum_ary))  	{ -		$sql = 'SELECT forum_name -			FROM ' . FORUMS_TABLE . ' -			WHERE forum_id = ' . $active_f_row['forum_id']; -		$result = $db->sql_query($sql, 3600); -		$active_f_row['forum_name'] = (string) $db->sql_fetchfield('forum_name'); +		// Obtain active forum +		$sql = 'SELECT forum_id, COUNT(post_id) AS num_posts +			FROM ' . POSTS_TABLE . ' +			WHERE poster_id = ' . $userdata['user_id'] . ' +				AND post_postcount = 1 +				AND ' . phpbb_content_visibility::get_forums_visibility_sql('post', $forum_ary) . ' +			GROUP BY forum_id +			ORDER BY num_posts DESC'; +		$result = $db->sql_query_limit($sql, 1); +		$active_f_row = $db->sql_fetchrow($result);  		$db->sql_freeresult($result); -	} -	// Obtain active topic -	// We need to exclude passworded forums here so we do not leak the topic title -	$forum_ary_topic = array_unique(array_merge($forum_ary, $user->get_passworded_forums())); -	$forum_sql_topic = (!empty($forum_ary_topic)) ? 'AND ' . $db->sql_in_set('forum_id', $forum_ary_topic, true) : ''; - -	$sql = 'SELECT topic_id, COUNT(post_id) AS num_posts -		FROM ' . POSTS_TABLE . ' -		WHERE poster_id = ' . $userdata['user_id'] . " -			AND post_postcount = 1 -			AND (post_approved = 1 -				$sql_m_approve) -			$forum_sql_topic -		GROUP BY topic_id -		ORDER BY num_posts DESC"; -	$result = $db->sql_query_limit($sql, 1); -	$active_t_row = $db->sql_fetchrow($result); -	$db->sql_freeresult($result); +		if (!empty($active_f_row)) +		{ +			$sql = 'SELECT forum_name +				FROM ' . FORUMS_TABLE . ' +				WHERE forum_id = ' . $active_f_row['forum_id']; +			$result = $db->sql_query($sql, 3600); +			$active_f_row['forum_name'] = (string) $db->sql_fetchfield('forum_name'); +			$db->sql_freeresult($result); +		} -	if (!empty($active_t_row)) -	{ -		$sql = 'SELECT topic_title -			FROM ' . TOPICS_TABLE . ' -			WHERE topic_id = ' . $active_t_row['topic_id']; -		$result = $db->sql_query($sql); -		$active_t_row['topic_title'] = (string) $db->sql_fetchfield('topic_title'); +		// Obtain active topic +		$sql = 'SELECT topic_id, COUNT(post_id) AS num_posts +			FROM ' . POSTS_TABLE . ' +			WHERE poster_id = ' . $userdata['user_id'] . ' +				AND post_postcount = 1 +				AND ' . phpbb_content_visibility::get_forums_visibility_sql('post', $forum_ary) . ' +			GROUP BY topic_id +			ORDER BY num_posts DESC'; +		$result = $db->sql_query_limit($sql, 1); +		$active_t_row = $db->sql_fetchrow($result);  		$db->sql_freeresult($result); + +		if (!empty($active_t_row)) +		{ +			$sql = 'SELECT topic_title +				FROM ' . TOPICS_TABLE . ' +				WHERE topic_id = ' . $active_t_row['topic_id']; +			$result = $db->sql_query($sql); +			$active_t_row['topic_title'] = (string) $db->sql_fetchfield('topic_title'); +			$db->sql_freeresult($result); +		}  	}  	$userdata['active_t_row'] = $active_t_row; diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index b9b518ad32..de88f7cc98 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -176,7 +176,7 @@ function update_post_information($type, $ids, $return_update_sql = false)  	if ($type != 'topic')  	{  		$topic_join = ', ' . TOPICS_TABLE . ' t'; -		$topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_approved = 1'; +		$topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_visibility = ' . ITEM_APPROVED;  	}  	else  	{ @@ -190,7 +190,7 @@ function update_post_information($type, $ids, $return_update_sql = false)  			FROM ' . POSTS_TABLE . " p $topic_join  			WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "  				$topic_condition -				AND p.post_approved = 1"; +				AND p.post_visibility = " . ITEM_APPROVED;  	}  	else  	{ @@ -198,7 +198,7 @@ function update_post_information($type, $ids, $return_update_sql = false)  			FROM ' . POSTS_TABLE . " p $topic_join  			WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . "  				$topic_condition -				AND p.post_approved = 1 +				AND p.post_visibility = " . ITEM_APPROVED . "  			GROUP BY p.{$type}_id";  	}  	$result = $db->sql_query($sql); @@ -988,7 +988,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id  	$sql = 'SELECT p.post_id  		FROM ' . POSTS_TABLE . ' p' . "  		WHERE p.topic_id = $topic_id -			" . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '') . ' +			AND " . phpbb_content_visibility::get_visibility_sql('post', $forum_id, 'p.') . '  			' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . '  			' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . '  		ORDER BY p.post_time '; @@ -1175,14 +1175,14 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id  /**  * Delete Post  */ -function delete_post($forum_id, $topic_id, $post_id, &$data) +function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $softdelete_reason = '')  {  	global $db, $user, $auth;  	global $config, $phpEx, $phpbb_root_path;  	// Specify our post mode  	$post_mode = 'delete'; -	if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && $data['topic_replies_real'] == 0) +	if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1))  	{  		$post_mode = 'delete_topic';  	} @@ -1224,20 +1224,28 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)  		$db->sql_freeresult($result);  	} -	if (!delete_posts('post_id', array($post_id), false, false)) +	// (Soft) delete the post +	if ($is_soft && ($post_mode != 'delete_topic'))  	{ -		// Try to delete topic, we may had an previous error causing inconsistency -		if ($post_mode == 'delete_topic') +		phpbb_content_visibility::set_post_visibility(ITEM_DELETED, $post_id, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason, ($data['topic_first_post_id'] == $post_id), ($data['topic_last_post_id'] == $post_id)); +	} +	else if (!$is_soft) +	{ +		if (!delete_posts('post_id', array($post_id), false, false, false))  		{ -			delete_topics('topic_id', array($topic_id), false); +			// Try to delete topic, we may had an previous error causing inconsistency +			if ($post_mode == 'delete_topic') +			{ +				delete_topics('topic_id', array($topic_id), false); +			} +			trigger_error('ALREADY_DELETED');  		} -		trigger_error('ALREADY_DELETED');  	}  	$db->sql_transaction('commit');  	// Collect the necessary information for updating the tables -	$sql_data[FORUMS_TABLE] = ''; +	$sql_data[FORUMS_TABLE] = $sql_data[TOPICS_TABLE] = '';  	switch ($post_mode)  	{  		case 'delete_topic': @@ -1246,21 +1254,43 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)  			{  				// counting is fun! we only have to do sizeof($forum_ids) number of queries,  				// even if the topic is moved back to where its shadow lives (we count how many times it is in a forum) -				$db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_topics_real = forum_topics_real - ' . $topic_count . ', forum_topics = forum_topics - ' . $topic_count . ' WHERE forum_id = ' . $updated_forum); +				$sql = 'UPDATE ' . FORUMS_TABLE . ' +					SET forum_topics_approved = forum_topics_approved - ' . $topic_count . ' +					WHERE forum_id = ' . $updated_forum; +				$db->sql_query($sql);  				update_post_information('forum', $updated_forum);  			} -			delete_topics('topic_id', array($topic_id), false); +			if ($is_soft) +			{ +				$topic_row = array(); +				phpbb_content_visibility::set_topic_visibility(ITEM_DELETED, $topic_id, $forum_id, $user->data['user_id'], time(), $softdelete_reason); +			} +			else +			{ +				delete_topics('topic_id', array($topic_id), false); -			$sql_data[FORUMS_TABLE] .= 'forum_topics_real = forum_topics_real - 1'; -			$sql_data[FORUMS_TABLE] .= ($data['topic_approved']) ? ', forum_posts = forum_posts - 1, forum_topics = forum_topics - 1' : ''; +				if ($data['topic_visibility'] == ITEM_APPROVED) +				{ +					$sql_data[FORUMS_TABLE] .= 'forum_posts_approved = forum_posts_approved - 1, forum_topics_approved = forum_topics_approved - 1'; +				} +				else if ($data['topic_visibility'] == ITEM_UNAPPROVED) +				{ +					$sql_data[FORUMS_TABLE] .= 'forum_posts_unapproved = forum_posts_unapproved - 1, forum_topics_unapproved = forum_topics_unapproved - 1'; +				} +				else if ($data['topic_visibility'] == ITEM_DELETED) +				{ +					$sql_data[FORUMS_TABLE] .= 'forum_posts_softdeleted = forum_posts_softdeleted - 1, forum_topics_softdeleted = forum_topics_softdeleted - 1'; +				} -			$update_sql = update_post_information('forum', $forum_id, true); -			if (sizeof($update_sql)) -			{ -				$sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; -				$sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); +				$update_sql = update_post_information('forum', $forum_id, true); +				if (sizeof($update_sql)) +				{ +					$sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; +					$sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); +				}  			} +  		break;  		case 'delete_first_post': @@ -1268,73 +1298,101 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)  				FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u  				WHERE p.topic_id = $topic_id  					AND p.poster_id = u.user_id -				ORDER BY p.post_time ASC"; +					AND p.post_visibility = " . ITEM_APPROVED . ' +				ORDER BY p.post_time ASC';  			$result = $db->sql_query_limit($sql, 1);  			$row = $db->sql_fetchrow($result);  			$db->sql_freeresult($result); -			$sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; - -			$sql_data[TOPICS_TABLE] = 'topic_poster = ' . intval($row['poster_id']) . ', topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_colour = '" . $db->sql_escape($row['user_colour']) . "', topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "', topic_time = " . (int) $row['post_time']; - -			// Decrementing topic_replies here is fine because this case only happens if there is more than one post within the topic - basically removing one "reply" -			$sql_data[TOPICS_TABLE] .= ', topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); +			if (!$row) +			{ +				// No approved post, so the first is a not-approved post (unapproved or soft deleted) +				$sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour +					FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u +					WHERE p.topic_id = $topic_id +						AND p.poster_id = u.user_id +					ORDER BY p.post_time ASC"; +				$result = $db->sql_query_limit($sql, 1); +				$row = $db->sql_fetchrow($result); +				$db->sql_freeresult($result); +			}  			$next_post_id = (int) $row['post_id']; + +			$sql_data[TOPICS_TABLE] = $db->sql_build_array('UPDATE', array( +				'topic_poster'				=> (int) $row['poster_id'], +				'topic_first_post_id'		=> (int) $row['post_id'], +				'topic_first_poster_colour'	=> $row['user_colour'], +				'topic_first_poster_name'	=> ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'], +				'topic_time'				=> (int) $row['post_time'], +			));  		break;  		case 'delete_last_post': -			$sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; - -			$update_sql = update_post_information('forum', $forum_id, true); -			if (sizeof($update_sql)) +			if (!$is_soft)  			{ -				$sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; -				$sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); -			} +				// Update last post information when hard deleting. Soft delete already did that by itself. +				$update_sql = update_post_information('forum', $forum_id, true); +				if (sizeof($update_sql)) +				{ +					$sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . implode(', ', $update_sql[$forum_id]); +				} -			$sql_data[TOPICS_TABLE] = 'topic_bumped = 0, topic_bumper = 0, topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); +				$sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_bumped = 0, topic_bumper = 0'; -			$update_sql = update_post_information('topic', $topic_id, true); -			if (sizeof($update_sql)) -			{ -				$sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]); -				$next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]); +				$update_sql = update_post_information('topic', $topic_id, true); +				if (!empty($update_sql)) +				{ +					$sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]); +					$next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]); +				}  			} -			else + +			if (!$next_post_id)  			{  				$sql = 'SELECT MAX(post_id) as last_post_id  					FROM ' . POSTS_TABLE . " -					WHERE topic_id = $topic_id " . -						((!$auth->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : ''); +					WHERE topic_id = $topic_id +						AND " . phpbb_content_visibility::get_visibility_sql('post', $forum_id);  				$result = $db->sql_query($sql); -				$row = $db->sql_fetchrow($result); +				$next_post_id = (int) $db->sql_fetchfield('last_post_id');  				$db->sql_freeresult($result); - -				$next_post_id = (int) $row['last_post_id'];  			}  		break;  		case 'delete':  			$sql = 'SELECT post_id  				FROM ' . POSTS_TABLE . " -				WHERE topic_id = $topic_id " . -					((!$auth->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : '') . ' +				WHERE topic_id = $topic_id +					AND " . phpbb_content_visibility::get_visibility_sql('post', $forum_id) . '  					AND post_time > ' . $data['post_time'] . '  				ORDER BY post_time ASC';  			$result = $db->sql_query_limit($sql, 1); -			$row = $db->sql_fetchrow($result); +			$next_post_id = (int) $db->sql_fetchfield('post_id');  			$db->sql_freeresult($result); - -			$sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; - -			$sql_data[TOPICS_TABLE] = 'topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); -			$next_post_id = (int) $row['post_id'];  		break;  	}  	if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post'))  	{ +		if (!$is_soft) +		{ +			if ($data['post_visibility'] == ITEM_APPROVED) +			{ +				phpbb_content_visibility::remove_post_from_statistic($data, $sql_data); +			} +			else if ($data['post_visibility'] == ITEM_UNAPPROVED) +			{ +				$sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_unapproved = forum_posts_unapproved - 1'; +				$sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_unapproved = topic_posts_unapproved - 1'; +			} +			else if ($data['post_visibility'] == ITEM_DELETED) +			{ +				$sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . 'forum_posts_softdeleted = forum_posts_softdeleted - 1'; +				$sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_posts_softdeleted = topic_posts_softdeleted - 1'; +			} +		} +  		$sql = 'SELECT 1 AS has_attachments  			FROM ' . ATTACHMENTS_TABLE . '  			WHERE topic_id = ' . $topic_id; @@ -1344,18 +1402,16 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)  		if (!$has_attachments)  		{ -			$sql_data[TOPICS_TABLE] .= ', topic_attachment = 0'; +			$sql_data[TOPICS_TABLE] = (($sql_data[TOPICS_TABLE]) ? $sql_data[TOPICS_TABLE] . ', ' : '') . 'topic_attachment = 0';  		}  	} -//	$sql_data[USERS_TABLE] = ($data['post_postcount']) ? 'user_posts = user_posts - 1' : ''; -  	$db->sql_transaction('begin');  	$where_sql = array(  		FORUMS_TABLE	=> "forum_id = $forum_id",  		TOPICS_TABLE	=> "topic_id = $topic_id", -		USERS_TABLE		=> 'user_id = ' . $data['poster_id'] +		USERS_TABLE		=> 'user_id = ' . $data['poster_id'],  	);  	foreach ($sql_data as $table => $update_sql) @@ -1425,7 +1481,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  	}  	else if ($mode == 'edit')  	{ -		$post_mode = ($data['topic_replies_real'] == 0) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit')); +		$post_mode = ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit'));  	}  	// First of all make sure the subject and topic title are having the correct length. @@ -1438,9 +1494,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  	$poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id'];  	// Retrieve some additional information if not present -	if ($mode == 'edit' && (!isset($data['post_approved']) || !isset($data['topic_approved']) || $data['post_approved'] === false || $data['topic_approved'] === false)) +	if ($mode == 'edit' && (!isset($data['post_visibility']) || !isset($data['topic_visibility']) || $data['post_visibility'] === false || $data['topic_visibility'] === false))  	{ -		$sql = 'SELECT p.post_approved, t.topic_type, t.topic_replies, t.topic_replies_real, t.topic_approved +		$sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility  			FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p  			WHERE t.topic_id = p.topic_id  				AND p.post_id = ' . $data['post_id']; @@ -1448,26 +1504,29 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  		$topic_row = $db->sql_fetchrow($result);  		$db->sql_freeresult($result); -		$data['topic_approved'] = $topic_row['topic_approved']; -		$data['post_approved'] = $topic_row['post_approved']; +		$data['topic_visibility'] = $topic_row['topic_visibility']; +		$data['post_visibility'] = $topic_row['post_visibility'];  	} -	// This variable indicates if the user is able to post or put into the queue - it is used later for all code decisions regarding approval -	// The variable name should be $post_approved, because it indicates if the post is approved or not -	$post_approval = 1; +	// This variable indicates if the user is able to post or put into the queue +	$post_visibility = ITEM_APPROVED;  	// Check the permissions for post approval.  	// Moderators must go through post approval like ordinary users.  	if (!$auth->acl_get('f_noapprove', $data['forum_id']))  	{  		// Post not approved, but in queue -		$post_approval = 0; +		$post_visibility = ITEM_UNAPPROVED;  	} -	// Mods are able to force approved/unapproved posts. True means the post is approved, false the post is unapproved +	// MODs/Extensions are able to force any visibility on posts  	if (isset($data['force_approved_state']))  	{ -		$post_approval = ($data['force_approved_state']) ? 1 : 0; +		$post_visibility = (in_array((int) $data['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED))) ? (int) $data['force_approved_state'] : $post_visibility; +	} +	if (isset($data['force_visibility'])) +	{ +		$post_visibility = (in_array((int) $data['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED))) ? (int) $data['force_visibility'] : $post_visibility;  	}  	// Start the transaction here @@ -1484,7 +1543,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  				'icon_id'			=> $data['icon_id'],  				'poster_ip'			=> $user->ip,  				'post_time'			=> $current_time, -				'post_approved'		=> $post_approval, +				'post_visibility'	=> $post_visibility,  				'enable_bbcode'		=> $data['enable_bbcode'],  				'enable_smilies'	=> $data['enable_smilies'],  				'enable_magic_url'	=> $data['enable_urls'], @@ -1550,7 +1609,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  				'forum_id'			=> $data['forum_id'],  				'poster_id'			=> $data['poster_id'],  				'icon_id'			=> $data['icon_id'], -				'post_approved'		=> (!$post_approval) ? 0 : $data['post_approved'], +				// We will change the visibility later +				//'post_visibility'	=> $post_visibility,  				'enable_bbcode'		=> $data['enable_bbcode'],  				'enable_smilies'	=> $data['enable_smilies'],  				'enable_magic_url'	=> $data['enable_urls'], @@ -1571,8 +1631,6 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  		break;  	} - -	$post_approved = $sql_data[POSTS_TABLE]['sql']['post_approved'];  	$topic_row = array();  	// And the topic ladies and gentlemen @@ -1585,7 +1643,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  				'topic_last_view_time'		=> $current_time,  				'forum_id'					=> $data['forum_id'],  				'icon_id'					=> $data['icon_id'], -				'topic_approved'			=> $post_approval, +				'topic_posts_approved'		=> ($post_visibility == ITEM_APPROVED) ? 1 : 0, +				'topic_posts_softdeleted'	=> ($post_visibility == ITEM_DELETED) ? 1 : 0, +				'topic_posts_unapproved'	=> ($post_visibility == ITEM_UNAPPROVED) ? 1 : 0, +				'topic_visibility'			=> $post_visibility, +				'topic_delete_user'			=> ($post_visibility != ITEM_APPROVED) ? (int) $user->data['user_id'] : 0,  				'topic_title'				=> $subject,  				'topic_first_poster_name'	=> (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),  				'topic_first_poster_colour'	=> $user->data['user_colour'], @@ -1617,28 +1679,47 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  				);  			} -			$sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : ''); +			$sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); -			if ($post_approval) +			if ($post_visibility == ITEM_APPROVED) +			{ +				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_approved = forum_topics_approved + 1'; +				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1'; +			} +			else if ($post_visibility == ITEM_UNAPPROVED)  			{ -				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1'; +				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_unapproved = forum_topics_unapproved + 1'; +				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1'; +			} +			else if ($post_visibility == ITEM_DELETED) +			{ +				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_softdeleted = forum_topics_softdeleted + 1'; +				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';  			} -			$sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . (($post_approval) ? ', forum_topics = forum_topics + 1' : '');  		break;  		case 'reply':  			$sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ', -				topic_replies_real = topic_replies_real + 1,  				topic_bumped = 0,  				topic_bumper = 0' . -				(($post_approval) ? ', topic_replies = topic_replies + 1' : '') . +				(($post_visibility == ITEM_APPROVED) ? ', topic_posts_approved = topic_posts_approved + 1' : '') . +				(($post_visibility == ITEM_UNAPPROVED) ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') . +				(($post_visibility == ITEM_DELETED) ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') .  				((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : ''); -			$sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : ''); +			$sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : ''); -			if ($post_approval) +			if ($post_visibility == ITEM_APPROVED)  			{ -				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1'; +				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1'; +			} +			else if ($post_visibility == ITEM_UNAPPROVED) +			{ +				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1'; +			} +			else if ($post_visibility == ITEM_DELETED) +			{ +				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';  			}  		break; @@ -1662,7 +1743,6 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  			$sql_data[TOPICS_TABLE]['sql'] = array(  				'forum_id'					=> $data['forum_id'],  				'icon_id'					=> $data['icon_id'], -				'topic_approved'			=> (!$post_approval) ? 0 : $data['topic_approved'],  				'topic_title'				=> $subject,  				'topic_first_poster_name'	=> $username,  				'topic_type'				=> $topic_type, @@ -1677,56 +1757,6 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  				'topic_attachment'			=> (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0),  			); -			// Correctly set back the topic replies and forum posts... only if the topic was approved before and now gets disapproved -			if (!$post_approval && $data['topic_approved']) -			{ -				// Do we need to grab some topic informations? -				if (!sizeof($topic_row)) -				{ -					$sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved -						FROM ' . TOPICS_TABLE . ' -						WHERE topic_id = ' . $data['topic_id']; -					$result = $db->sql_query($sql); -					$topic_row = $db->sql_fetchrow($result); -					$db->sql_freeresult($result); -				} - -				// If this is the only post remaining we do not need to decrement topic_replies. -				// Also do not decrement if first post - then the topic_replies will not be adjusted if approving the topic again. - -				// If this is an edited topic or the first post the topic gets completely disapproved later on... -				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics = forum_topics - 1'; -				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies'] + 1); - -				set_config_count('num_topics', -1, true); -				set_config_count('num_posts', ($topic_row['topic_replies'] + 1) * (-1), true); - -				// Only decrement this post, since this is the one non-approved now -				if ($auth->acl_get('f_postcount', $data['forum_id'])) -				{ -					$sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1'; -				} -			} - -		break; - -		case 'edit': -		case 'edit_last_post': - -			// Correctly set back the topic replies and forum posts... but only if the post was approved before. -			if (!$post_approval && $data['post_approved']) -			{ -				$sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies = topic_replies - 1, topic_last_view_time = ' . $current_time; -				$sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - 1'; - -				set_config_count('num_posts', -1, true); - -				if ($auth->acl_get('f_postcount', $data['forum_id'])) -				{ -					$sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1'; -				} -			} -  		break;  	} @@ -1751,27 +1781,48 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  		if ($post_mode == 'reply')  		{  			$sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( -				'topic_id' => $data['topic_id']) -			); +				'topic_id' => $data['topic_id'], +			));  		}  		$sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);  		$db->sql_query($sql);  		$data['post_id'] = $db->sql_nextid(); -		if ($post_mode == 'post') +		if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED)  		{  			$sql_data[TOPICS_TABLE]['sql'] = array( -				'topic_first_post_id'		=> $data['post_id'],  				'topic_last_post_id'		=> $data['post_id'],  				'topic_last_post_time'		=> $current_time, -				'topic_last_poster_id'		=> (int) $user->data['user_id'], -				'topic_last_poster_name'	=> (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), +				'topic_last_poster_id'		=> $sql_data[POSTS_TABLE]['sql']['poster_id'], +				'topic_last_poster_name'	=> ($user->data['user_id'] == ANONYMOUS) ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'],  				'topic_last_poster_colour'	=> $user->data['user_colour'],  				'topic_last_post_subject'	=> (string) $subject,  			);  		} +		if ($post_mode == 'post') +		{ +			$sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data['post_id']; +		} + +		// Update total post count and forum information +		if ($post_visibility == ITEM_APPROVED) +		{ +			if ($post_mode == 'post') +			{ +				set_config_count('num_topics', 1, true); +			} +			set_config_count('num_posts', 1, true); + +			$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id']; +			$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'"; +			$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time; +			$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id']; +			$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'"; +			$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'"; +		} +  		unset($sql_data[POSTS_TABLE]['sql']);  	} @@ -1782,6 +1833,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  			SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '  			WHERE topic_id = ' . $data['topic_id'];  		$db->sql_query($sql); + +		unset($sql_data[TOPICS_TABLE]['sql']);  	}  	// Update the posts table @@ -1791,6 +1844,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  			SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '  			WHERE post_id = ' . $data['post_id'];  		$db->sql_query($sql); + +		unset($sql_data[POSTS_TABLE]['sql']);  	}  	// Update Poll Tables @@ -1936,114 +1991,20 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  		}  	} -	// we need to update the last forum information -	// only applicable if the topic is approved -	if ($post_approved || !$data['post_approved']) +	// Fix the post's and topic's visibility and first/last post information, when the post is edited +	if (($post_mode != 'post' && $post_mode != 'reply') && $data['post_visibility'] != $post_visibility)  	{ -		// the last post makes us update the forum table. This can happen if... -		// We make a new topic -		// We reply to a topic -		// We edit the last post in a topic and this post is the latest in the forum (maybe) -		// We edit the only post in the topic -		// We edit the first post in the topic and all the other posts are not approved -		if (($post_mode == 'post' || $post_mode == 'reply') && $post_approved) -		{ -			$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id']; -			$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'"; -			$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time; -			$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id']; -			$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'"; -			$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'"; -		} -		else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies'])) -		{ -			// this does not _necessarily_ mean that we must update the info again, -			// it just means that we might have to -			$sql = 'SELECT forum_last_post_id, forum_last_post_subject -				FROM ' . FORUMS_TABLE . ' -				WHERE forum_id = ' . (int) $data['forum_id']; -			$result = $db->sql_query($sql); -			$row = $db->sql_fetchrow($result); -			$db->sql_freeresult($result); +		// If the post was not approved, it could also be the starter, +		// so we sync the starter after approving/restoring, to ensure that the stats are correct +		// Same applies for the last post +		$is_starter = ($post_mode == 'edit_first_post' || $data['post_visibility'] != ITEM_APPROVED); +		$is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED); -			// this post is the latest post in the forum, better update -			if ($row['forum_last_post_id'] == $data['post_id']) -			{ -				// If post approved and subject changed, or poster is anonymous, we need to update the forum_last* rows -				if ($post_approved && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) -				{ -					// the post's subject changed -					if ($row['forum_last_post_subject'] !== $subject) -					{ -						$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_subject = \'' . $db->sql_escape($subject) . '\''; -					} - -					// Update the user name if poster is anonymous... just in case an admin changed it -					if ($data['poster_id'] == ANONYMOUS) -					{ -						$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'"; -					} -				} -				else if ($data['post_approved'] !== $post_approved) -				{ -					// we need a fresh change of socks, everything has become invalidated -					$sql = 'SELECT MAX(topic_last_post_id) as last_post_id -						FROM ' . TOPICS_TABLE . ' -						WHERE forum_id = ' . (int) $data['forum_id'] . ' -							AND topic_approved = 1'; -					$result = $db->sql_query($sql); -					$row = $db->sql_fetchrow($result); -					$db->sql_freeresult($result); - -					// any posts left in this forum? -					if (!empty($row['last_post_id'])) -					{ -						$sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour -							FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u -							WHERE p.poster_id = u.user_id -								AND p.post_id = ' . (int) $row['last_post_id']; -						$result = $db->sql_query($sql); -						$row = $db->sql_fetchrow($result); -						$db->sql_freeresult($result); - -						// salvation, a post is found! jam it into the forums table -						$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id']; -						$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'"; -						$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time']; -						$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id']; -						$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; -						$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'"; -					} -					else -					{ -						// just our luck, the last topic in the forum has just been turned unapproved... -						$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0'; -						$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''"; -						$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0'; -						$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0'; -						$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''"; -						$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''"; -					} -				} -			} -		} +		phpbb_content_visibility::set_post_visibility($post_visibility, $data['post_id'], $data['topic_id'], $data['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest);  	} - -	// topic sync time! -	// simply, we update if it is a reply or the last post is edited -	if ($post_approved) +	else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies']))  	{ -		// reply requires the whole thing -		if ($post_mode == 'reply') -		{ -			$sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $data['post_id']; -			$sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $user->data['user_id']; -			$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'"; -			$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . (($user->data['user_id'] != ANONYMOUS) ? $db->sql_escape($user->data['user_colour']) : '') . "'"; -			$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'"; -			$sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $current_time; -		} -		else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies'])) +		if ($post_visibility == ITEM_APPROVED || $data['topic_visibility'] == $post_visibility)  		{  			// only the subject can be changed from edit  			$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'"; @@ -2053,57 +2014,44 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  			{  				$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";  			} -		} -	} -	else if (!$data['post_approved'] && ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies']))) -	{ -		// like having the rug pulled from under us -		$sql = 'SELECT MAX(post_id) as last_post_id -			FROM ' . POSTS_TABLE . ' -			WHERE topic_id = ' . (int) $data['topic_id'] . ' -				AND post_approved = 1'; -		$result = $db->sql_query($sql); -		$row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); -		// any posts left in this forum? -		if (!empty($row['last_post_id'])) -		{ -			$sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour -				FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u -				WHERE p.poster_id = u.user_id -					AND p.post_id = ' . (int) $row['last_post_id']; -			$result = $db->sql_query($sql); -			$row = $db->sql_fetchrow($result); -			$db->sql_freeresult($result); - -			// salvation, a post is found! jam it into the topics table -			$sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $row['post_id']; -			$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'"; -			$sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $row['post_time']; -			$sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $row['poster_id']; -			$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; -			$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'"; -		} -	} +			if ($post_visibility == ITEM_APPROVED) +			{ +				// this does not _necessarily_ mean that we must update the info again, +				// it just means that we might have to +				$sql = 'SELECT forum_last_post_id, forum_last_post_subject +					FROM ' . FORUMS_TABLE . ' +					WHERE forum_id = ' . (int) $data['forum_id']; +				$result = $db->sql_query($sql); +				$row = $db->sql_fetchrow($result); +				$db->sql_freeresult($result); -	// Update total post count, do not consider moderated posts/topics -	if ($post_approval) -	{ -		if ($post_mode == 'post') -		{ -			set_config_count('num_topics', 1, true); -			set_config_count('num_posts', 1, true); -		} +				// this post is the latest post in the forum, better update +				if ($row['forum_last_post_id'] == $data['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) +				{ +					// the post's subject changed +					if ($row['forum_last_post_subject'] !== $subject) +					{ +						$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'"; +					} -		if ($post_mode == 'reply') -		{ -			set_config_count('num_posts', 1, true); +					// Update the user name if poster is anonymous... just in case a moderator changed it +					if ($data['poster_id'] == ANONYMOUS) +					{ +						$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'"; +					} +				} +			}  		}  	}  	// Update forum stats -	$where_sql = array(POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id); +	$where_sql = array( +		POSTS_TABLE		=> 'post_id = ' . $data['post_id'], +		TOPICS_TABLE	=> 'topic_id = ' . $data['topic_id'], +		FORUMS_TABLE	=> 'forum_id = ' . $data['forum_id'], +		USERS_TABLE		=> 'user_id = ' . $poster_id +	);  	foreach ($sql_data as $table => $update_ary)  	{ @@ -2226,7 +2174,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  	$phpbb_notifications = $phpbb_container->get('notification_manager'); -	if ($post_approval) +	if ($post_visibility == ITEM_APPROVED)  	{  		switch ($mode)  		{ @@ -2259,7 +2207,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  			break;  		}  	} -	else +	else if ($post_visibility == ITEM_UNAPPROVED)  	{  		switch ($mode)  		{ @@ -2276,6 +2224,32 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  			case 'edit_first_post':  			case 'edit':  			case 'edit_last_post': +				// @todo: Check whether these notification deletions are correct +				$phpbb_notifications->delete_notifications('topic', $data['topic_id']); + +				$phpbb_notifications->delete_notifications(array( +					'quote', +					'bookmark', +					'post', +				), $data['post_id']); +			break; +		} +	} +	else if ($post_visibility == ITEM_DELETED) +	{ +		switch ($mode) +		{ +			case 'post': +			case 'reply': +			case 'quote': +				// Nothing to do here +			break; + +			case 'edit_topic': +			case 'edit_first_post': +			case 'edit': +			case 'edit_last_post': +				// @todo: Check whether these notification deletions are correct  				$phpbb_notifications->delete_notifications('topic', $data['topic_id']);  				$phpbb_notifications->delete_notifications(array( @@ -2289,7 +2263,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u  	$params = $add_anchor = ''; -	if ($post_approval) +	if ($post_visibility == ITEM_APPROVED)  	{  		$params .= '&t=' . $data['topic_id']; diff --git a/phpBB/includes/mcp/info/mcp_queue.php b/phpBB/includes/mcp/info/mcp_queue.php index 7ad79f9781..68cac5abd2 100644 --- a/phpBB/includes/mcp/info/mcp_queue.php +++ b/phpBB/includes/mcp/info/mcp_queue.php @@ -21,6 +21,8 @@ class mcp_queue_info  			'modes'		=> array(  				'unapproved_topics'	=> array('title' => 'MCP_QUEUE_UNAPPROVED_TOPICS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')),  				'unapproved_posts'	=> array('title' => 'MCP_QUEUE_UNAPPROVED_POSTS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), +				'deleted_topics'	=> array('title' => 'MCP_QUEUE_DELETED_TOPICS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), +				'deleted_posts'		=> array('title' => 'MCP_QUEUE_DELETED_POSTS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')),  				'approve_details'	=> array('title' => 'MCP_QUEUE_APPROVE_DETAILS', 'auth' => 'acl_m_approve,$id || (!$id && aclf_m_approve)', 'cat' => array('MCP_QUEUE')),  			),  		); diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index 0fad9e2a22..a7302ce912 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -98,7 +98,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)  	$sort_by_sql = $sort_order_sql = array();  	mcp_sorting('viewforum', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id); -	$forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total; +	$forum_topics = ($total == -1) ? $forum_info['forum_topics_approved'] : $total;  	$limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : '';  	$base_url = $url . "&i=$id&action=$action&mode=$mode&sd=$sort_dir&sk=$sort_key&st=$sort_days" . (($merge_select) ? $selected_ids : ''); @@ -116,6 +116,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)  		'S_CAN_REPORT'			=> $auth->acl_get('m_report', $forum_id),  		'S_CAN_DELETE'			=> $auth->acl_get('m_delete', $forum_id), +		'S_CAN_RESTORE'			=> $auth->acl_get('m_approve', $forum_id),  		'S_CAN_MERGE'			=> $auth->acl_get('m_merge', $forum_id),  		'S_CAN_MOVE'			=> $auth->acl_get('m_move', $forum_id),  		'S_CAN_FORK'			=> $auth->acl_get('m_', $forum_id), @@ -154,7 +155,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)  	$sql = 'SELECT t.topic_id  		FROM ' . TOPICS_TABLE . ' t  		WHERE t.forum_id = ' . $forum_id . ' -			' . (($auth->acl_get('m_approve', $forum_id)) ? '' : 'AND t.topic_approved = 1') . " +			AND ' . phpbb_content_visibility::get_visibility_sql('topic', $forum_id, 't.') . "  			$limit_time_sql  		ORDER BY t.topic_type DESC, $sort_order_sql";  	$result = $db->sql_query_limit($sql, $topics_per_page, $start); @@ -203,7 +204,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)  		$row = &$topic_rows[$topic_id]; -		$replies = ($auth->acl_get('m_approve', $forum_id)) ? $row['topic_replies_real'] : $row['topic_replies']; +		$replies = phpbb_content_visibility::get_count('topic_posts', $row, $forum_id) - 1;  		if ($row['topic_status'] == ITEM_MOVED)  		{ @@ -220,9 +221,11 @@ function mcp_forum_view($id, $mode, $action, $forum_info)  		$topic_title = censor_text($row['topic_title']); -		$topic_unapproved = (!$row['topic_approved'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; -		$posts_unapproved = ($row['topic_approved'] && $row['topic_replies'] < $row['topic_replies_real'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; +		$topic_unapproved = ($row['topic_visibility'] == ITEM_UNAPPROVED  && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; +		$posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; +		$topic_deleted = $row['topic_visibility'] == ITEM_DELETED;  		$u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&i=queue&mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&t=' . $row['topic_id'] : ''; +		$u_mcp_queue = (!$u_mcp_queue && $topic_deleted) ? $url . '&i=queue&mode=deleted_topics&t=' . $topic_id : $u_mcp_queue;  		$topic_row = array(  			'ATTACH_ICON_IMG'		=> ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', @@ -232,6 +235,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)  			'TOPIC_ICON_IMG_WIDTH'	=> (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '',  			'TOPIC_ICON_IMG_HEIGHT'	=> (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '',  			'UNAPPROVED_IMG'		=> ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', +			'DELETED_IMG'			=> ($topic_deleted) ? $user->img('icon_topic_deleted', 'POSTS_DELETED') : '',  			'TOPIC_AUTHOR'				=> get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),  			'TOPIC_AUTHOR_COLOUR'		=> get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), @@ -245,7 +249,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)  			'TOPIC_TYPE'		=> $topic_type,  			'TOPIC_TITLE'		=> $topic_title, -			'REPLIES'			=> ($auth->acl_get('m_approve', $row['forum_id'])) ? $row['topic_replies_real'] : $row['topic_replies'], +			'REPLIES'			=> phpbb_content_visibility::get_count('topic_posts', $row, $row['forum_id']) - 1,  			'LAST_POST_TIME'	=> $user->format_date($row['topic_last_post_time']),  			'FIRST_POST_TIME'	=> $user->format_date($row['topic_time']),  			'LAST_POST_SUBJECT'	=> $row['topic_last_post_subject'], @@ -254,6 +258,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)  			'S_TOPIC_REPORTED'		=> (!empty($row['topic_reported']) && empty($row['topic_moved_id']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false,  			'S_TOPIC_UNAPPROVED'	=> $topic_unapproved,  			'S_POSTS_UNAPPROVED'	=> $posts_unapproved, +			'S_TOPIC_DELETED'		=> $topic_deleted,  			'S_UNREAD_TOPIC'		=> $unread_topic,  		); diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php index ba4b15895a..44cab5d910 100644 --- a/phpBB/includes/mcp/mcp_front.php +++ b/phpBB/includes/mcp/mcp_front.php @@ -39,7 +39,7 @@ function mcp_front_view($id, $mode, $action)  			$sql = 'SELECT COUNT(post_id) AS total  				FROM ' . POSTS_TABLE . '  				WHERE ' . $db->sql_in_set('forum_id', $forum_list) . ' -					AND post_approved = 0'; +					AND post_visibility = ' . ITEM_UNAPPROVED;  			$result = $db->sql_query($sql);  			$total = (int) $db->sql_fetchfield('total');  			$db->sql_freeresult($result); @@ -60,7 +60,7 @@ function mcp_front_view($id, $mode, $action)  				$sql = 'SELECT post_id  					FROM ' . POSTS_TABLE . '  					WHERE ' . $db->sql_in_set('forum_id', $forum_list) . ' -						AND post_approved = 0 +						AND post_visibility = ' . ITEM_UNAPPROVED . '  					ORDER BY post_time DESC';  				$result = $db->sql_query_limit($sql, 5); diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index c28b466bcf..c044e5c871 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -33,7 +33,7 @@ class mcp_main  	function main($id, $mode)  	{  		global $auth, $db, $user, $template, $action; -		global $config, $phpbb_root_path, $phpEx; +		global $config, $phpbb_root_path, $phpEx, $request;  		$quickmod = ($mode == 'quickmod') ? true : false; @@ -108,27 +108,48 @@ class mcp_main  			case 'delete_topic':  				$user->add_lang('viewtopic'); -				$topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); +				// f parameter is not reliable for permission usage, however we just use it to decide +				// which permission we will check later on. So if it is manipulated, we will still catch it later on. +				$forum_id = $request->variable('f', 0); +				$topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); +				$soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false;  				if (!sizeof($topic_ids))  				{  					trigger_error('NO_TOPIC_SELECTED');  				} -				mcp_delete_topic($topic_ids); +				mcp_delete_topic($topic_ids, $soft_delete, ($soft_delete) ? $request->variable('delete_reason', '', true) : '');  			break;  			case 'delete_post':  				$user->add_lang('posting'); -				$post_ids = (!$quickmod) ? request_var('post_id_list', array(0)) : array(request_var('p', 0)); +				// f parameter is not reliable for permission usage, however we just use it to decide +				// which permission we will check later on. So if it is manipulated, we will still catch it later on. +				$forum_id = $request->variable('f', 0); +				$post_ids = (!$quickmod) ? $request->variable('post_id_list', array(0)) : array($request->variable('p', 0)); +				$soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false;  				if (!sizeof($post_ids))  				{  					trigger_error('NO_POST_SELECTED');  				} -				mcp_delete_post($post_ids); +				mcp_delete_post($post_ids, $soft_delete, ($soft_delete) ? $request->variable('delete_reason', '', true) : ''); +			break; + +			case 'restore_topic': +				$user->add_lang('posting'); + +				$topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); + +				if (!sizeof($topic_ids)) +				{ +					trigger_error('NO_TOPIC_SELECTED'); +				} + +				mcp_restore_topic($topic_ids);  			break;  		} @@ -455,59 +476,31 @@ function mcp_move_topic($topic_ids)  		$forum_sync_data[$forum_id] = current($topic_data);  		$forum_sync_data[$to_forum_id] = $forum_data; -		// Real topics added to target forum -		$topics_moved = sizeof($topic_data); - -		// Approved topics added to target forum -		$topics_authed_moved = 0; - -		// Posts (topic replies + topic post if approved) added to target forum -		$topic_posts_added = 0; - -		// Posts (topic replies + topic post if approved and not global announcement) removed from source forum -		$topic_posts_removed = 0; - -		// Real topics removed from source forum (all topics without global announcements) -		$topics_removed = 0; - -		// Approved topics removed from source forum (except global announcements) -		$topics_authed_removed = 0; +		$topics_moved = $topics_moved_unapproved = $topics_moved_softdeleted = 0; +		$posts_moved = $posts_moved_unapproved = $posts_moved_softdeleted = 0;  		foreach ($topic_data as $topic_id => $topic_info)  		{ -			if ($topic_info['topic_approved']) +			if ($topic_info['topic_visibility'] == ITEM_APPROVED)  			{ -				$topics_authed_moved++; -				$topic_posts_added++; +				$topics_moved++;  			} - -			$topic_posts_added += $topic_info['topic_replies']; - -			$topics_removed++; -			$topic_posts_removed += $topic_info['topic_replies']; - -			if ($topic_info['topic_approved']) +			elseif ($topic_info['topic_visibility'] == ITEM_UNAPPROVED)  			{ -				$topics_authed_removed++; -				$topic_posts_removed++; +				$topics_moved_unapproved++; +			} +			elseif ($topic_info['topic_visibility'] == ITEM_DELETED) +			{ +				$topics_moved_softdeleted++;  			} -		} - -		$db->sql_transaction('begin'); - -		$sync_sql = array(); - -		if ($topic_posts_added) -		{ -			$sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . $topic_posts_added; -		} -		if ($topics_authed_moved) -		{ -			$sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . (int) $topics_authed_moved; +			$posts_moved += $topic_info['topic_posts_approved']; +			$posts_moved_unapproved += $topic_info['topic_posts_unapproved']; +			$posts_moved_softdeleted += $topic_info['topic_posts_softdeleted'];  		} +		$topics_moved = sizeof($topic_data); -		$sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . (int) $topics_moved; +		$db->sql_transaction('begin');  		// Move topics, but do not resync yet  		move_topics($topic_ids, $to_forum_id, false); @@ -528,21 +521,22 @@ function mcp_move_topic($topic_ids)  			add_log('mod', $to_forum_id, $topic_id, 'LOG_MOVE', $row['forum_name'], $forum_data['forum_name']);  			// Leave a redirection if required and only if the topic is visible to users -			if ($leave_shadow && $row['topic_approved'] && $row['topic_type'] != POST_GLOBAL) +			if ($leave_shadow && $row['topic_visibility'] == ITEM_APPROVED && $row['topic_type'] != POST_GLOBAL)  			{  				$shadow = array(  					'forum_id'				=>	(int) $row['forum_id'],  					'icon_id'				=>	(int) $row['icon_id'],  					'topic_attachment'		=>	(int) $row['topic_attachment'], -					'topic_approved'		=>	1, // a shadow topic is always approved +					'topic_visibility'		=>	ITEM_APPROVED, // a shadow topic is always approved  					'topic_reported'		=>	0, // a shadow topic is never reported  					'topic_title'			=>	(string) $row['topic_title'],  					'topic_poster'			=>	(int) $row['topic_poster'],  					'topic_time'			=>	(int) $row['topic_time'],  					'topic_time_limit'		=>	(int) $row['topic_time_limit'],  					'topic_views'			=>	(int) $row['topic_views'], -					'topic_replies'			=>	(int) $row['topic_replies'], -					'topic_replies_real'	=>	(int) $row['topic_replies_real'], +					'topic_posts_approved'	=>	(int) $row['topic_posts_approved'], +					'topic_posts_unapproved'=>	(int) $row['topic_posts_unapproved'], +					'topic_posts_softdeleted'=>	(int) $row['topic_posts_softdeleted'],  					'topic_status'			=>	ITEM_MOVED,  					'topic_type'			=>	POST_NORMAL,  					'topic_first_post_id'	=>	(int) $row['topic_first_post_id'], @@ -568,25 +562,45 @@ function mcp_move_topic($topic_ids)  				$db->sql_query('INSERT INTO ' . TOPICS_TABLE . $db->sql_build_array('INSERT', $shadow));  				// Shadow topics only count on new "topics" and not posts... a shadow topic alone has 0 posts -				$topics_removed--; -				$topics_authed_removed--; +				$shadow_topics++;  			}  		}  		unset($topic_data); -		if ($topic_posts_removed) +		$sync_sql = array(); +		if ($posts_moved)  		{ -			$sync_sql[$forum_id][] = 'forum_posts = forum_posts - ' . $topic_posts_removed; +			$sync_sql[$to_forum_id][] = 'forum_posts_approved = forum_posts_approved + ' . (int) $posts_moved; +			$sync_sql[$forum_id][] = 'forum_posts_approved = forum_posts_approved - ' . (int) $posts_moved;  		} - -		if ($topics_removed) +		if ($posts_moved_unapproved) +		{ +			$sync_sql[$to_forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved + ' . (int) $posts_moved_unapproved; +			$sync_sql[$forum_id][] = 'forum_posts_unapproved = forum_posts_unapproved - ' . (int) $posts_moved_unapproved; +		} +		if ($posts_moved_softdeleted)  		{ -			$sync_sql[$forum_id][]	= 'forum_topics_real = forum_topics_real - ' . (int) $topics_removed; +			$sync_sql[$to_forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted + ' . (int) $posts_moved_softdeleted; +			$sync_sql[$forum_id][] = 'forum_posts_softdeleted = forum_posts_softdeleted - ' . (int) $posts_moved_softdeleted;  		} -		if ($topics_authed_removed) +		if ($topics_moved)  		{ -			$sync_sql[$forum_id][]	= 'forum_topics = forum_topics - ' . (int) $topics_authed_removed; +			$sync_sql[$to_forum_id][] = 'forum_topics_approved = forum_topics_approved + ' . (int) $topics_moved; +			if ($topics_moved - $shadow_topics > 0) +			{ +				$sync_sql[$forum_id][] = 'forum_topics_approved = forum_topics_approved - ' . (int) ($topics_moved - $shadow_topics); +			} +		} +		if ($topics_moved_unapproved) +		{ +			$sync_sql[$to_forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved + ' . (int) $topics_moved_unapproved; +			$sync_sql[$forum_id][] = 'forum_topics_unapproved = forum_topics_unapproved - ' . (int) $topics_moved_unapproved; +		} +		if ($topics_moved_softdeleted) +		{ +			$sync_sql[$to_forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted + ' . (int) $topics_moved_softdeleted; +			$sync_sql[$forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted - ' . (int) $topics_moved_softdeleted;  		}  		$success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS'; @@ -636,25 +650,97 @@ function mcp_move_topic($topic_ids)  }  /** +* Restore Topics +*/ +function mcp_restore_topic($topic_ids) +{ +	global $auth, $user, $db, $phpEx, $phpbb_root_path, $request; + +	if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_approve'))) +	{ +		return; +	} + +	$redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); +	$forum_id = $request->variable('f', 0); + +	$s_hidden_fields = build_hidden_fields(array( +		'topic_id_list'	=> $topic_ids, +		'f'				=> $forum_id, +		'action'		=> 'restore_topic', +		'redirect'		=> $redirect, +	)); +	$success_msg = ''; + +	if (confirm_box(true)) +	{ +		$success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_RESTORED_SUCCESS' : 'TOPICS_RESTORED_SUCCESS'; + +		$data = get_topic_data($topic_ids); + +		foreach ($data as $topic_id => $row) +		{ +			$return = phpbb_content_visibility::set_topic_visibility(ITEM_APPROVED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), ''); +			if (!empty($return)) +			{ +				add_log('mod', $row['forum_id'], $topic_id, 'LOG_RESTORE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']); +			} +		} +	} +	else +	{ +		confirm_box(false, (sizeof($topic_ids) == 1) ? 'RESTORE_TOPIC' : 'RESTORE_TOPICS', $s_hidden_fields); +	} + +	$topic_id = $request->variable('t', 0); +	if (!$request->is_set('quickmod', phpbb_request_interface::REQUEST)) +	{ +		$redirect = $request->variable('redirect', "index.$phpEx"); +		$redirect = reapply_sid($redirect); +		$redirect_message = 'PAGE'; +	} +	else if ($topic_id) +	{ +		$redirect = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id); +		$redirect_message = 'TOPIC'; +	} +	else +	{ +		$redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); +		$redirect_message = 'FORUM'; +	} + +	if (!$success_msg) +	{ +		redirect($redirect); +	} +	else +	{ +		meta_refresh(3, $redirect); +		trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_' . $redirect_message], '<a href="' . $redirect . '">', '</a>')); +	} +} + +/**  * Delete Topics  */ -function mcp_delete_topic($topic_ids) +function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_topic')  { -	global $auth, $user, $db, $phpEx, $phpbb_root_path; +	global $auth, $user, $db, $phpEx, $phpbb_root_path, $request;  	if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_delete')))  	{  		return;  	} -	$redirect = request_var('redirect', build_url(array('action', 'quickmod'))); -	$forum_id = request_var('f', 0); +	$redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); +	$forum_id = $request->variable('f', 0); -	$s_hidden_fields = build_hidden_fields(array( +	$s_hidden_fields = array(  		'topic_id_list'	=> $topic_ids,  		'f'				=> $forum_id, -		'action'		=> 'delete_topic', -		'redirect'		=> $redirect) +		'action'		=> $action, +		'redirect'		=> $redirect,  	);  	$success_msg = ''; @@ -672,23 +758,80 @@ function mcp_delete_topic($topic_ids)  			}  			else  			{ -				add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']); +				// Only soft delete non-shadow topics +				if ($is_soft) +				{ +					$return = phpbb_content_visibility::set_topic_visibility(ITEM_DELETED, $topic_id, $row['forum_id'], $user->data['user_id'], time(), $soft_delete_reason); +					if (!empty($return)) +					{ +						add_log('mod', $row['forum_id'], $topic_id, 'LOG_SOFTDELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']); +					} +				} +				else +				{ +					add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']); +				}  			}  		} -		$return = delete_topics('topic_id', $topic_ids); +		if (!$is_soft) +		{ +			$return = delete_topics('topic_id', $topic_ids); +		}  	}  	else  	{ -		confirm_box(false, (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS', $s_hidden_fields); +		global $template; + +		$user->add_lang('posting'); + +		$only_softdeleted = false; +		if ($auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id)) +		{ +			// If there are only soft deleted topics, we display a message why the option is not available +			$sql = 'SELECT topic_id +				FROM ' . TOPICS_TABLE . ' +				WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' +					AND topic_visibility <> ' . ITEM_DELETED; +			$result = $db->sql_query_limit($sql, 1); +			$only_softdeleted = !$db->sql_fetchfield('topic_id'); +			$db->sql_freeresult($result); +		} + +		$template->assign_vars(array( +			'S_SOFTDELETED'			=> $only_softdeleted, +			'S_TOPIC_MODE'			=> true, +			'S_ALLOWED_DELETE'		=> $auth->acl_get('m_delete', $forum_id), +			'S_ALLOWED_SOFTDELETE'	=> $auth->acl_get('m_softdelete', $forum_id), +			'S_DELETE_REASON'		=> $auth->acl_get('m_softdelete', $forum_id), +		)); + +		$l_confirm = (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS'; +		if ($only_softdeleted) +		{ +			$l_confirm .= '_PERMANENTLY'; +			$s_hidden_fields['delete_permanent'] = '1'; +		} +		else if (!$auth->acl_get('m_softdelete', $forum_id)) +		{ +			$s_hidden_fields['delete_permanent'] = '1'; +		} + +		confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');  	} -	if (!isset($_REQUEST['quickmod'])) +	$topic_id = $request->variable('t', 0); +	if (!$request->is_set('quickmod', phpbb_request_interface::REQUEST))  	{ -		$redirect = request_var('redirect', "index.$phpEx"); +		$redirect = $request->variable('redirect', "index.$phpEx");  		$redirect = reapply_sid($redirect);  		$redirect_message = 'PAGE';  	} +	else if ($is_soft && $topic_id) +	{ +		$redirect = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id); +		$redirect_message = 'TOPIC'; +	}  	else  	{  		$redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); @@ -709,27 +852,92 @@ function mcp_delete_topic($topic_ids)  /**  * Delete Posts  */ -function mcp_delete_post($post_ids) +function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', $action = 'delete_post')  { -	global $auth, $user, $db, $phpEx, $phpbb_root_path; +	global $auth, $user, $db, $phpEx, $phpbb_root_path, $request; -	if (!check_ids($post_ids, POSTS_TABLE, 'post_id', array('m_delete'))) +	if (!check_ids($post_ids, POSTS_TABLE, 'post_id', array('m_softdelete')))  	{  		return;  	} -	$redirect = request_var('redirect', build_url(array('action', 'quickmod'))); -	$forum_id = request_var('f', 0); +	$redirect = $request->variable('redirect', build_url(array('action', 'quickmod'))); +	$forum_id = $request->variable('f', 0); -	$s_hidden_fields = build_hidden_fields(array( +	$s_hidden_fields = array(  		'post_id_list'	=> $post_ids,  		'f'				=> $forum_id, -		'action'		=> 'delete_post', -		'redirect'		=> $redirect) +		'action'		=> $action, +		'redirect'		=> $redirect,  	);  	$success_msg = ''; -	if (confirm_box(true)) +	if (confirm_box(true) && $is_soft) +	{ +		$post_info = get_post_data($post_ids); + +		$topic_info = $approve_log = array(); + +		// Group the posts by topic_id +		foreach ($post_info as $post_id => $post_data) +		{ +			if ($post_data['post_visibility'] != ITEM_APPROVED) +			{ +				continue; +			} +			$topic_id = (int) $post_data['topic_id']; + +			$topic_info[$topic_id]['posts'][] = (int) $post_id; +			$topic_info[$topic_id]['forum_id'] = (int) $post_data['forum_id']; + +			if ($post_id == $post_data['topic_first_post_id']) +			{ +				$topic_info[$topic_id]['first_post'] = true; +			} + +			if ($post_id == $post_data['topic_last_post_id']) +			{ +				$topic_info[$topic_id]['last_post'] = true; +			} + +			$approve_log[] = array( +				'forum_id'		=> $post_data['forum_id'], +				'topic_id'		=> $post_data['topic_id'], +				'post_subject'	=> $post_data['post_subject'], +				'poster_id'		=> $post_data['poster_id'], +				'post_username'	=> $post_data['post_username'], +				'username'		=> $post_data['username'], +			); +		} + +		foreach ($topic_info as $topic_id => $topic_data) +		{ +			phpbb_content_visibility::set_post_visibility(ITEM_DELETED, $topic_data['posts'], $topic_id, $topic_data['forum_id'], $user->data['user_id'], time(), $soft_delete_reason, isset($topic_data['first_post']), isset($topic_data['last_post'])); +		} +		$affected_topics = sizeof($topic_info); +		// None of the topics is really deleted, so a redirect won't hurt much. +		$deleted_topics = 0; + +		$success_msg = (sizeof($post_info) == 1) ? 'POST_DELETED_SUCCESS' : 'POSTS_DELETED_SUCCESS'; + +		foreach ($approve_log as $row) +		{ +			$post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username']; +			add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_SOFTDELETE_POST', $row['post_subject'], $post_username); +		} + +		$topic_id = $request->variable('t', 0); + +		// Return links +		$return_link = array(); +		if ($affected_topics == 1 && $topic_id) +		{ +			$return_link[] = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id") . '">', '</a>'); +		} +		$return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>'); + +	} +	else if (confirm_box(true))  	{  		if (!function_exists('delete_posts'))  		{ @@ -772,7 +980,7 @@ function mcp_delete_post($post_ids)  		$deleted_topics = ($row = $db->sql_fetchrow($result)) ? ($affected_topics - $row['topics_left']) : $affected_topics;  		$db->sql_freeresult($result); -		$topic_id = request_var('t', 0); +		$topic_id = $request->variable('t', 0);  		// Return links  		$return_link = array(); @@ -810,10 +1018,45 @@ function mcp_delete_post($post_ids)  	}  	else  	{ -		confirm_box(false, (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS', $s_hidden_fields); +		global $template; + +		$user->add_lang('posting'); + +		$only_softdeleted = false; +		if ($auth->acl_get('m_delete', $forum_id) && $auth->acl_get('m_softdelete', $forum_id)) +		{ +			// If there are only soft deleted posts, we display a message why the option is not available +			$sql = 'SELECT post_id +				FROM ' . POSTS_TABLE . ' +				WHERE ' . $db->sql_in_set('post_id', $post_ids) . ' +					AND post_visibility <> ' . ITEM_DELETED; +			$result = $db->sql_query_limit($sql, 1); +			$only_softdeleted = !$db->sql_fetchfield('post_id'); +			$db->sql_freeresult($result); +		} + +		$template->assign_vars(array( +			'S_SOFTDELETED'			=> $only_softdeleted, +			'S_ALLOWED_DELETE'		=> $auth->acl_get('m_delete', $forum_id), +			'S_ALLOWED_SOFTDELETE'	=> $auth->acl_get('m_softdelete', $forum_id), +			'S_DELETE_REASON'		=> $auth->acl_get('m_softdelete', $forum_id), +		)); + +		$l_confirm = (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS'; +		if ($only_softdeleted) +		{ +			$l_confirm .= '_PERMANENTLY'; +			$s_hidden_fields['delete_permanent'] = '1'; +		} +		else if (!$auth->acl_get('m_softdelete', $forum_id)) +		{ +			$s_hidden_fields['delete_permanent'] = '1'; +		} + +		confirm_box(false, $l_confirm, build_hidden_fields($s_hidden_fields), 'confirm_delete_body.html');  	} -	$redirect = request_var('redirect', "index.$phpEx"); +	$redirect = $request->variable('redirect', "index.$phpEx");  	$redirect = reapply_sid($redirect);  	if (!$success_msg) @@ -932,13 +1175,14 @@ function mcp_fork_topic($topic_ids)  				'forum_id'					=> (int) $to_forum_id,  				'icon_id'					=> (int) $topic_row['icon_id'],  				'topic_attachment'			=> (int) $topic_row['topic_attachment'], -				'topic_approved'			=> 1, +				'topic_visibility'			=> ITEM_APPROVED,  				'topic_reported'			=> 0,  				'topic_title'				=> (string) $topic_row['topic_title'],  				'topic_poster'				=> (int) $topic_row['topic_poster'],  				'topic_time'				=> (int) $topic_row['topic_time'], -				'topic_replies'				=> (int) $topic_row['topic_replies_real'], -				'topic_replies_real'		=> (int) $topic_row['topic_replies_real'], +				'topic_posts_approved'		=> (int) $topic_row['topic_posts_approved'], +				'topic_posts_unapproved'	=> (int) $topic_row['topic_posts_unapproved'], +				'topic_posts_softdeleted'	=> (int) $topic_row['topic_posts_softdeleted'],  				'topic_status'				=> (int) $topic_row['topic_status'],  				'topic_type'				=> (int) $topic_row['topic_type'],  				'topic_first_poster_name'	=> (string) $topic_row['topic_first_poster_name'], @@ -1009,7 +1253,7 @@ function mcp_fork_topic($topic_ids)  					'icon_id'			=> (int) $row['icon_id'],  					'poster_ip'			=> (string) $row['poster_ip'],  					'post_time'			=> (int) $row['post_time'], -					'post_approved'		=> 1, +					'post_visibility'	=> ITEM_APPROVED,  					'post_reported'		=> 0,  					'enable_bbcode'		=> (int) $row['enable_bbcode'],  					'enable_smilies'	=> (int) $row['enable_smilies'], @@ -1125,23 +1369,15 @@ function mcp_fork_topic($topic_ids)  		}  		// Sync new topics, parent forums and board stats -		sync('topic', 'topic_id', $new_topic_id_list); - -		$sync_sql = array(); - -		$sync_sql[$to_forum_id][]	= 'forum_posts = forum_posts + ' . $total_posts; -		$sync_sql[$to_forum_id][]	= 'forum_topics = forum_topics + ' . sizeof($new_topic_id_list); -		$sync_sql[$to_forum_id][]	= 'forum_topics_real = forum_topics_real + ' . sizeof($new_topic_id_list); - -		foreach ($sync_sql as $forum_id_key => $array) -		{ -			$sql = 'UPDATE ' . FORUMS_TABLE . ' -				SET ' . implode(', ', $array) . ' -				WHERE forum_id = ' . $forum_id_key; -			$db->sql_query($sql); -		} +		$sql = 'UPDATE ' . FORUMS_TABLE . ' +			SET forum_posts_approved = forum_posts_approved + ' . $total_posts . ', +				forum_topics_approved = forum_topics_approved + ' . sizeof($new_topic_id_list) . ' +			WHERE forum_id = ' . $to_forum_id; +		$db->sql_query($sql); +		sync('topic', 'topic_id', $new_topic_id_list);  		sync('forum', 'forum_id', $to_forum_id); +  		set_config_count('num_topics', sizeof($new_topic_id_list), true);  		set_config_count('num_posts', $total_posts, true); diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 520c964228..734fa96a78 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -174,6 +174,33 @@ function mcp_post_details($id, $mode, $action)  		}  	} +	// Deleting information +	if ($post_info['post_visibility'] == ITEM_DELETED && $post_info['post_delete_user']) +	{ +		// User having deleted the post also being the post author? +		if (!$post_info['post_delete_user'] || $post_info['post_delete_user'] == $post_info['poster_id']) +		{ +			$display_username = get_username_string('full', $post_info['poster_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']); +		} +		else +		{ +			$sql = 'SELECT user_id, username, user_colour +				FROM ' . USERS_TABLE . ' +				WHERE user_id = ' . (int) $post_info['post_delete_user']; +			$result = $db->sql_query($sql); +			$user_delete_row = $db->sql_fetchrow($result); +			$db->sql_freeresult($result); +			$display_username = get_username_string('full', $post_info['post_delete_user'], $user_delete_row['username'], $user_delete_row['user_colour']); +		} + +		$user->add_lang('viewtopic'); +		$l_deleted_by = $user->lang('DELETED_INFORMATION', $display_username, $user->format_date($post_info['post_delete_time'], false, true)); +	} +	else +	{ +		$l_deleted_by = ''; +	} +  	$template->assign_vars(array(  		'U_MCP_ACTION'			=> "$url&i=main&quickmod=1&mode=post_details", // Use this for mode paramaters  		'U_POST_ACTION'			=> "$url&i=$id&mode=post_details", // Use this for action parameters @@ -185,10 +212,13 @@ function mcp_post_details($id, $mode, $action)  		'S_CAN_DELETE_POST'		=> $auth->acl_get('m_delete', $post_info['forum_id']),  		'S_POST_REPORTED'		=> ($post_info['post_reported']) ? true : false, -		'S_POST_UNAPPROVED'		=> (!$post_info['post_approved']) ? true : false, +		'S_POST_UNAPPROVED'		=> ($post_info['post_visibility'] == ITEM_UNAPPROVED) ? true : false, +		'S_POST_DELETED'		=> ($post_info['post_visibility'] == ITEM_DELETED) ? true : false,  		'S_POST_LOCKED'			=> ($post_info['post_edit_locked']) ? true : false,  		'S_USER_NOTES'			=> true,  		'S_CLEAR_ALLOWED'		=> ($auth->acl_get('a_clearlogs')) ? true : false, +		'DELETED_MESSAGE'		=> $l_deleted_by, +		'DELETE_REASON'			=> $post_info['post_delete_reason'],  		'U_EDIT'				=> ($auth->acl_get('m_edit', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=edit&f={$post_info['forum_id']}&p={$post_info['post_id']}") : '',  		'U_FIND_USERNAME'		=> append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=mcp_chgposter&field=username&select_single=true'), @@ -205,6 +235,7 @@ function mcp_post_details($id, $mode, $action)  		'RETURN_FORUM'			=> sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f={$post_info['forum_id']}&start={$start}") . '">', '</a>'),  		'REPORTED_IMG'			=> $user->img('icon_topic_reported', $user->lang['POST_REPORTED']),  		'UNAPPROVED_IMG'		=> $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']), +		'DELETED_IMG'			=> $user->img('icon_topic_deleted', $user->lang['POST_DELETED']),  		'EDIT_IMG'				=> $user->img('icon_post_edit', $user->lang['EDIT_POST']),  		'SEARCH_IMG'			=> $user->img('icon_user_search', $user->lang['SEARCH']), @@ -415,7 +446,7 @@ function change_poster(&$post_info, $userdata)  	}  	// Adjust post counts... only if the post is approved (else, it was not added the users post count anyway) -	if ($post_info['post_postcount'] && $post_info['post_approved']) +	if ($post_info['post_postcount'] && $post_info['post_visibility'] == ITEM_APPROVED)  	{  		$sql = 'UPDATE ' . USERS_TABLE . '  			SET user_posts = user_posts - 1 diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index 24afa1f210..29c0375e6c 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -25,14 +25,14 @@ class mcp_queue  	var $p_master;  	var $u_action; -	function mcp_queue(&$p_master) +	public function mcp_queue(&$p_master)  	{  		$this->p_master = &$p_master;  	} -	function main($id, $mode) +	public function main($id, $mode)  	{ -		global $auth, $db, $user, $template, $cache; +		global $auth, $db, $user, $template, $cache, $request;  		global $config, $phpbb_root_path, $phpEx, $action, $phpbb_container;  		include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); @@ -45,25 +45,96 @@ class mcp_queue  		switch ($action)  		{  			case 'approve': -			case 'disapprove': +			case 'restore':  				include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); -				$post_id_list = request_var('post_id_list', array(0)); +				$post_id_list = $request->variable('post_id_list', array(0)); +				$topic_id_list = $request->variable('topic_id_list', array(0)); -				if (!sizeof($post_id_list)) +				if (!empty($post_id_list)) +				{ +					self::approve_posts($action, $post_id_list, 'queue', $mode); +				} +				else if (!empty($topic_id_list)) +				{ +					self::approve_topics($action, $topic_id_list, 'queue', $mode); +				} +				else  				{  					trigger_error('NO_POST_SELECTED');  				} +			break; + +			case 'delete': +				$post_id_list = $request->variable('post_id_list', array(0)); +				$topic_id_list = $request->variable('topic_id_list', array(0)); -				if ($action == 'approve') +				if (!empty($post_id_list)) +				{ +					if (!function_exists('mcp_delete_post')) +					{ +						global $phpbb_root_path, $phpEx; +						include($phpbb_root_path . 'includes/mcp/mcp_main.' . $phpEx); +					} +					mcp_delete_post($post_id_list, false, '', $action); +				} +				else if (!empty($topic_id_list))  				{ -					approve_post($post_id_list, 'queue', $mode); +					if (!function_exists('mcp_delete_topic')) +					{ +						global $phpbb_root_path, $phpEx; +						include($phpbb_root_path . 'includes/mcp/mcp_main.' . $phpEx); +					} +					mcp_delete_topic($topic_id_list, false, '', $action);  				}  				else  				{ -					disapprove_post($post_id_list, 'queue', $mode); +					trigger_error('NO_POST_SELECTED');  				} +			break; +			case 'disapprove': +				$post_id_list = $request->variable('post_id_list', array(0)); +				$topic_id_list = $request->variable('topic_id_list', array(0)); + +				if (!empty($topic_id_list) && $mode == 'deleted_topics') +				{ +					if (!function_exists('mcp_delete_topics')) +					{ +						global $phpbb_root_path, $phpEx; +						include($phpbb_root_path . 'includes/mcp/mcp_main.' . $phpEx); +					} +					mcp_delete_topic($topic_id_list, false, '', 'disapprove'); +					return; +				} + +				include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + +				if (!empty($topic_id_list)) +				{ +					$post_visibility = ($mode == 'deleted_topics') ? ITEM_DELETED : ITEM_UNAPPROVED; +					$sql = 'SELECT post_id +						FROM ' . POSTS_TABLE . ' +						WHERE post_visibility = ' . $post_visibility . ' +							AND ' . $db->sql_in_set('topic_id', $topic_id_list); +					$result = $db->sql_query($sql); + +					$post_id_list = array(); +					while ($row = $db->sql_fetchrow($result)) +					{ +						$post_id_list[] = (int) $row['post_id']; +					} +					$db->sql_freeresult($result); +				} + +				if (!empty($post_id_list)) +				{ +					self::disapprove_posts($post_id_list, 'queue', $mode); +				} +				else +				{ +					trigger_error('NO_POST_SELECTED'); +				}  			break;  		} @@ -181,6 +252,33 @@ class mcp_queue  					}  				} +				// Deleting information +				if ($post_info['post_visibility'] == ITEM_DELETED && $post_info['post_delete_user']) +				{ +					// User having deleted the post also being the post author? +					if (!$post_info['post_delete_user'] || $post_info['post_delete_user'] == $post_info['poster_id']) +					{ +						$display_username = get_username_string('full', $post_info['poster_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']); +					} +					else +					{ +						$sql = 'SELECT u.user_id, u.username, u.user_colour +							FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u +							WHERE p.post_id =  ' . $post_info['post_id'] . ' +								AND p.post_delete_user = u.user_id'; +						$result = $db->sql_query($sql); +						$post_delete_userinfo = $db->sql_fetchrow($result); +						$db->sql_freeresult($result); +						$display_username = get_username_string('full', $post_info['post_delete_user'], $post_delete_userinfo['username'], $post_delete_userinfo['user_colour']); +					} + +					$l_deleted_by = $user->lang('DELETED_INFORMATION', $display_username, $user->format_date($post_info['post_delete_time'], false, true)); +				} +				else +				{ +					$l_deleted_by = ''; +				} +  				$post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']);  				$topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']); @@ -189,9 +287,12 @@ class mcp_queue  					'U_APPROVE_ACTION'		=> append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&p=$post_id&f=$forum_id"),  					'S_CAN_VIEWIP'			=> $auth->acl_get('m_info', $post_info['forum_id']),  					'S_POST_REPORTED'		=> $post_info['post_reported'], -					'S_POST_UNAPPROVED'		=> !$post_info['post_approved'], +					'S_POST_UNAPPROVED'		=> ($post_info['post_visibility'] == ITEM_UNAPPROVED),  					'S_POST_LOCKED'			=> $post_info['post_edit_locked'],  					'S_USER_NOTES'			=> true, +					'S_POST_DELETED'		=> ($post_info['post_visibility'] == ITEM_DELETED), +					'DELETED_MESSAGE'		=> $l_deleted_by, +					'DELETE_REASON'			=> $post_info['post_delete_reason'],  					'U_EDIT'				=> ($auth->acl_get('m_edit', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=edit&f={$post_info['forum_id']}&p={$post_info['post_id']}") : '',  					'U_MCP_APPROVE'			=> append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), @@ -203,6 +304,7 @@ class mcp_queue  					'MINI_POST_IMG'			=> ($post_unread) ? $user->img('icon_post_target_unread', 'UNREAD_POST') : $user->img('icon_post_target', 'POST'), +  					'RETURN_QUEUE'			=> sprintf($user->lang['RETURN_QUEUE'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue' . (($topic_id) ? '&mode=unapproved_topics' : '&mode=unapproved_posts')) . "&start=$start\">", '</a>'),  					'RETURN_POST'			=> sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>'),  					'RETURN_TOPIC_SIMPLE'	=> sprintf($user->lang['RETURN_TOPIC_SIMPLE'], '<a href="' . $topic_url . '">', '</a>'), @@ -230,9 +332,16 @@ class mcp_queue  			case 'unapproved_topics':  			case 'unapproved_posts': +			case 'deleted_topics': +			case 'deleted_posts': +				$m_perm = 'm_approve'; +				$is_topics = ($mode == 'unapproved_topics' || $mode == 'deleted_topics') ? true : false; +				$is_restore = ($mode == 'deleted_posts' || $mode == 'deleted_topics') ? true : false; +				$visibility_const = (!$is_restore) ? ITEM_UNAPPROVED : ITEM_DELETED; +  				$user->add_lang(array('viewtopic', 'viewforum')); -				$topic_id = request_var('t', 0); +				$topic_id = $request->variable('t', 0);  				$forum_info = array();  				if ($topic_id) @@ -248,7 +357,7 @@ class mcp_queue  					$forum_id = $topic_info['forum_id'];  				} -				$forum_list_approve = get_forum_list('m_approve', false, true); +				$forum_list_approve = get_forum_list($m_perm, false, true);  				$forum_list_read = array_flip(get_forum_list('f_read', true, true)); // Flipped so we can isset() the forum IDs  				// Remove forums we cannot read @@ -274,16 +383,16 @@ class mcp_queue  						trigger_error('NOT_MODERATOR');  					} -					$sql = 'SELECT SUM(forum_topics) as sum_forum_topics +					$sql = 'SELECT SUM(forum_topics_approved) as sum_forum_topics  						FROM ' . FORUMS_TABLE . '  						WHERE ' . $db->sql_in_set('forum_id', $forum_list);  					$result = $db->sql_query($sql); -					$forum_info['forum_topics'] = (int) $db->sql_fetchfield('sum_forum_topics'); +					$forum_info['forum_topics_approved'] = (int) $db->sql_fetchfield('sum_forum_topics');  					$db->sql_freeresult($result);  				}  				else  				{ -					$forum_info = get_forum_data(array($forum_id), 'm_approve'); +					$forum_info = get_forum_data(array($forum_id), $m_perm);  					if (!sizeof($forum_info))  					{ @@ -305,21 +414,22 @@ class mcp_queue  				$sort_by_sql = $sort_order_sql = array();  				mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); -				$forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total; +				$forum_topics = ($total == -1) ? $forum_info['forum_topics_approved'] : $total;  				$limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : '';  				$forum_names = array(); -				if ($mode == 'unapproved_posts') +				if (!$is_topics)  				{  					$sql = 'SELECT p.post_id  						FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t' . (($sort_order_sql[0] == 'u') ? ', ' . USERS_TABLE . ' u' : '') . '  						WHERE ' . $db->sql_in_set('p.forum_id', $forum_list) . ' -							AND p.post_approved = 0 +							AND p.post_visibility = ' . $visibility_const . '  							' . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.poster_id' : '') . '  							' . (($topic_id) ? 'AND p.topic_id = ' . $topic_id : '') . "  							AND t.topic_id = p.topic_id -							AND t.topic_first_post_id <> p.post_id +							AND (t.topic_visibility <> p.post_visibility +								OR t.topic_delete_user = 0)  							$limit_time_sql  						ORDER BY $sort_order_sql";  					$result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); @@ -365,9 +475,10 @@ class mcp_queue  				else  				{  					$sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, t.topic_title AS post_subject, t.topic_time AS post_time, t.topic_poster AS poster_id, t.topic_first_post_id AS post_id, t.topic_attachment AS post_attachment, t.topic_first_poster_name AS username, t.topic_first_poster_colour AS user_colour -						FROM ' . TOPICS_TABLE . " t -						WHERE " . $db->sql_in_set('forum_id', $forum_list) . " -							AND topic_approved = 0 +						FROM ' . TOPICS_TABLE . ' t +						WHERE ' . $db->sql_in_set('forum_id', $forum_list) . ' +							AND topic_visibility = ' . $visibility_const . " +							AND topic_delete_user <> 0  							$limit_time_sql  						ORDER BY $sort_order_sql";  					$result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); @@ -401,7 +512,7 @@ class mcp_queue  				{  					if (empty($row['post_username']))  					{ -						$row['post_username'] = $user->lang['GUEST']; +						$row['post_username'] = $row['username'] ?: $user->lang['GUEST'];  					}  					$template->assign_block_vars('postrow', array( @@ -416,6 +527,7 @@ class mcp_queue  						'U_POST_AUTHOR'			=> get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']),  						'POST_ID'		=> $row['post_id'], +						'TOPIC_ID'		=> $row['topic_id'],  						'FORUM_NAME'	=> $forum_names[$row['forum_id']],  						'POST_SUBJECT'	=> ($row['post_subject'] != '') ? $row['post_subject'] : $user->lang['NO_SUBJECT'],  						'TOPIC_TITLE'	=> $row['topic_title'], @@ -430,581 +542,688 @@ class mcp_queue  				// Now display the page  				$template->assign_vars(array( -					'L_DISPLAY_ITEMS'		=> ($mode == 'unapproved_posts') ? $user->lang['DISPLAY_POSTS'] : $user->lang['DISPLAY_TOPICS'], -					'L_EXPLAIN'				=> ($mode == 'unapproved_posts') ? $user->lang['MCP_QUEUE_UNAPPROVED_POSTS_EXPLAIN'] : $user->lang['MCP_QUEUE_UNAPPROVED_TOPICS_EXPLAIN'], -					'L_TITLE'				=> ($mode == 'unapproved_posts') ? $user->lang['MCP_QUEUE_UNAPPROVED_POSTS'] : $user->lang['MCP_QUEUE_UNAPPROVED_TOPICS'], +					'L_DISPLAY_ITEMS'		=> (!$is_topics) ? $user->lang['DISPLAY_POSTS'] : $user->lang['DISPLAY_TOPICS'], +					'L_EXPLAIN'				=> $user->lang['MCP_QUEUE_' . strtoupper($mode) . '_EXPLAIN'], +					'L_TITLE'				=> $user->lang['MCP_QUEUE_' . strtoupper($mode)],  					'L_ONLY_TOPIC'			=> ($topic_id) ? sprintf($user->lang['ONLY_TOPIC'], $topic_info['topic_title']) : '',  					'S_FORUM_OPTIONS'		=> $forum_options,  					'S_MCP_ACTION'			=> build_url(array('t', 'f', 'sd', 'st', 'sk')), -					'S_TOPICS'				=> ($mode == 'unapproved_posts') ? false : true, +					'S_TOPICS'				=> $is_topics, +					'S_RESTORE'				=> $is_restore,  					'PAGE_NUMBER'			=> phpbb_on_page($template, $user, $base_url, $total, $config['topics_per_page'], $start),  					'TOPIC_ID'				=> $topic_id, -					'TOTAL'					=> $user->lang((($mode == 'unapproved_posts') ? 'VIEW_TOPIC_POSTS' : 'VIEW_FORUM_TOPICS'), (int) $total), +					'TOTAL'					=> $user->lang(((!$is_topics) ? 'VIEW_TOPIC_POSTS' : 'VIEW_FORUM_TOPICS'), (int) $total),  				));  				$this->tpl_name = 'mcp_queue';  			break;  		}  	} -} - -/** -* Approve Post/Topic -*/ -function approve_post($post_id_list, $id, $mode) -{ -	global $db, $template, $user, $config; -	global $phpEx, $phpbb_root_path; -	global $request, $phpbb_container; -	if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) +	/** +	* Approve/Restore posts +	* +	* @param $action		string	Action we perform on the posts ('approve' or 'restore') +	* @param $post_id_list	array	IDs of the posts to approve/restore +	* @param $id			mixed	Category of the current active module +	* @param $mode			string	Active module +	* @return null +	*/ +	static public function approve_posts($action, $post_id_list, $id, $mode)  	{ -		trigger_error('NOT_AUTHORISED'); -	} +		global $db, $template, $user, $config, $request, $phpbb_container; +		global $phpEx, $phpbb_root_path; -	$redirect = request_var('redirect', build_url(array('quickmod'))); -	$success_msg = ''; +		if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) +		{ +			trigger_error('NOT_AUTHORISED'); +		} -	$s_hidden_fields = build_hidden_fields(array( -		'i'				=> $id, -		'mode'			=> $mode, -		'post_id_list'	=> $post_id_list, -		'action'		=> 'approve', -		'redirect'		=> $redirect) -	); +		$redirect = $request->variable('redirect', build_url(array('quickmod'))); +		$success_msg = $post_url = ''; +		$approve_log = array(); -	$post_info = get_post_data($post_id_list, 'm_approve'); +		$s_hidden_fields = build_hidden_fields(array( +			'i'				=> $id, +			'mode'			=> $mode, +			'post_id_list'	=> $post_id_list, +			'action'		=> $action, +			'redirect'		=> $redirect, +		)); -	if (confirm_box(true)) -	{ -		$notify_poster = (isset($_REQUEST['notify_poster'])) ? true : false; +		$post_info = get_post_data($post_id_list, 'm_approve'); -		// If Topic -> total_topics = total_topics+1, total_posts = total_posts+1, forum_topics = forum_topics+1, forum_posts = forum_posts+1 -		// If Post -> total_posts = total_posts+1, forum_posts = forum_posts+1, topic_replies = topic_replies+1 +		if (confirm_box(true)) +		{ +			$notify_poster = ($action == 'approve' && isset($_REQUEST['notify_poster'])); -		$total_topics = $total_posts = 0; -		$topic_approve_sql = $post_approve_sql = $topic_id_list = $forum_id_list = $approve_log = array(); -		$user_posts_sql = $post_approved_list = array(); +			$topic_info = array(); -		foreach ($post_info as $post_id => $post_data) -		{ -			if ($post_data['post_approved']) +			// Group the posts by topic_id +			foreach ($post_info as $post_id => $post_data)  			{ -				$post_approved_list[] = $post_id; -				continue; -			} +				if ($post_data['post_visibility'] == ITEM_APPROVED) +				{ +					continue; +				} +				$topic_id = (int) $post_data['topic_id']; -			$topic_id_list[$post_data['topic_id']] = 1; -			$forum_id_list[$post_data['forum_id']] = 1; +				$topic_info[$topic_id]['posts'][] = (int) $post_id; +				$topic_info[$topic_id]['forum_id'] = (int) $post_data['forum_id']; -			// User post update (we do not care about topic or post, since user posts are strictly connected to posts) -			// But we care about forums where post counts get not increased. ;) -			if ($post_data['post_postcount']) -			{ -				$user_posts_sql[$post_data['poster_id']] = (empty($user_posts_sql[$post_data['poster_id']])) ? 1 : $user_posts_sql[$post_data['poster_id']] + 1; -			} +				// Refresh the first post, if the time or id is older then the current one +				if ($post_id <= $post_data['topic_first_post_id'] || $post_data['post_time'] <= $post_data['topic_time']) +				{ +					$topic_info[$topic_id]['first_post'] = true; +				} -			// Topic or Post. ;) -			if ($post_data['topic_first_post_id'] == $post_id) -			{ -				$total_topics++; -				$topic_approve_sql[] = $post_data['topic_id']; +				// Refresh the last post, if the time or id is newer then the current one +				if ($post_id >= $post_data['topic_last_post_id'] || $post_data['post_time'] >= $post_data['topic_last_post_time']) +				{ +					$topic_info[$topic_id]['last_post'] = true; +				} + +				$post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f={$post_data['forum_id']}&t={$post_data['topic_id']}&p={$post_data['post_id']}") . '#p' . $post_data['post_id'];  				$approve_log[] = array( -					'type'			=> 'topic', -					'post_subject'	=> $post_data['post_subject'],  					'forum_id'		=> $post_data['forum_id'],  					'topic_id'		=> $post_data['topic_id'], +					'post_subject'	=> $post_data['post_subject'],  				);  			} -			else + +			foreach ($topic_info as $topic_id => $topic_data)  			{ -				$approve_log[] = array( -					'type'			=> 'post', -					'post_subject'	=> $post_data['post_subject'], -					'forum_id'		=> $post_data['forum_id'], -					'topic_id'		=> $post_data['topic_id'], -				); +				phpbb_content_visibility::set_post_visibility(ITEM_APPROVED, $topic_data['posts'], $topic_id, $topic_data['forum_id'], $user->data['user_id'], time(), '', isset($topic_data['first_post']), isset($topic_data['last_post']));  			} -			$total_posts++; +			if (sizeof($post_info) >= 1) +			{ +				$success_msg = (sizeof($post_info) == 1) ? 'POST_' . strtoupper($action) . 'D_SUCCESS' : 'POSTS_' . strtoupper($action) . 'D_SUCCESS'; +			} -			// Increment by topic_replies if we approve a topic... -			// This works because we do not adjust the topic_replies when re-approving a topic after an edit. -			if ($post_data['topic_first_post_id'] == $post_id && $post_data['topic_replies']) +			foreach ($approve_log as $log_data)  			{ -				$total_posts += $post_data['topic_replies']; +				add_log('mod', $log_data['forum_id'], $log_data['topic_id'], 'LOG_POST_' . strtoupper($action) . 'D', $log_data['post_subject']);  			} -			$post_approve_sql[] = $post_id; -		} +			// Only send out the mails, when the posts are being approved +			if ($action == 'approve') +			{ +				$phpbb_notifications = $phpbb_container->get('notification_manager'); -		$post_id_list = array_values(array_diff($post_id_list, $post_approved_list)); -		for ($i = 0, $size = sizeof($post_approved_list); $i < $size; $i++) -		{ -			unset($post_info[$post_approved_list[$i]]); -		} +				// Handle notifications +				foreach ($post_info as $post_id => $post_data) +				{ +					$phpbb_notifications->delete_notifications('post_in_queue', $post_id); -		if (sizeof($topic_approve_sql)) -		{ -			$sql = 'UPDATE ' . TOPICS_TABLE . ' -				SET topic_approved = 1 -				WHERE ' . $db->sql_in_set('topic_id', $topic_approve_sql); -			$db->sql_query($sql); -		} +					$phpbb_notifications->add_notifications(array( +						'quote', +						'bookmark', +						'post', +					), $post_data); + +					$phpbb_notifications->mark_notifications_read(array( +						'quote', +						'bookmark', +						'post', +					), $post_data['post_id'], $user->data['user_id']); + +					// Notify Poster? +					if ($notify_poster) +					{ +						if ($post_data['poster_id'] == ANONYMOUS) +						{ +							continue; +						} -		if (sizeof($post_approve_sql)) +						$phpbb_notifications->add_notifications('approve_post', $post_data); +					} +				} +			} +		} +		else  		{ -			$sql = 'UPDATE ' . POSTS_TABLE . ' -				SET post_approved = 1 -				WHERE ' . $db->sql_in_set('post_id', $post_approve_sql); -			$db->sql_query($sql); +			$show_notify = false; + +			if ($action == 'approve' && ($config['email_enable'] || $config['jab_enable'])) +			{ +				foreach ($post_info as $post_data) +				{ +					if ($post_data['poster_id'] == ANONYMOUS) +					{ +						continue; +					} +					else +					{ +						$show_notify = true; +						break; +					} +				} +			} + +			$template->assign_vars(array( +				'S_NOTIFY_POSTER'			=> $show_notify, +				'S_' . strtoupper($action)	=> true, +			)); + +			confirm_box(false, strtoupper($action) . '_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html');  		} -		unset($topic_approve_sql, $post_approve_sql); +		$redirect = $request->variable('redirect', "index.$phpEx"); +		$redirect = reapply_sid($redirect); -		foreach ($approve_log as $log_data) +		if (!$success_msg)  		{ -			add_log('mod', $log_data['forum_id'], $log_data['topic_id'], ($log_data['type'] == 'topic') ? 'LOG_TOPIC_APPROVED' : 'LOG_POST_APPROVED', $log_data['post_subject']); +			redirect($redirect);  		} - -		if (sizeof($user_posts_sql)) +		else  		{ -			// Try to minimize the query count by merging users with the same post count additions -			$user_posts_update = array(); +			meta_refresh(3, $redirect); -			foreach ($user_posts_sql as $user_id => $user_posts) +			// If approving one post, also give links back to post... +			$add_message = ''; +			if (sizeof($post_info) == 1 && $post_url)  			{ -				$user_posts_update[$user_posts][] = $user_id; +				$add_message = '<br /><br />' . sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>');  			} -			foreach ($user_posts_update as $user_posts => $user_id_ary) +			$message = $user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>') . $add_message; + +			if ($request->is_ajax())  			{ -				$sql = 'UPDATE ' . USERS_TABLE . ' -					SET user_posts = user_posts + ' . $user_posts . ' -					WHERE ' . $db->sql_in_set('user_id', $user_id_ary); -				$db->sql_query($sql); +				$json_response = new phpbb_json_response; +				$json_response->send(array( +					'MESSAGE_TITLE'		=> $user->lang['INFORMATION'], +					'MESSAGE_TEXT'		=> $message, +					'REFRESH_DATA'		=> null, +					'visible'			=> true, +				));  			} -		} -		if ($total_topics) -		{ -			set_config_count('num_topics', $total_topics, true); +			trigger_error($message);  		} +	} -		if ($total_posts) +	/** +	* Approve/Restore topics +	* +	* @param $action		string	Action we perform on the posts ('approve' or 'restore') +	* @param $topic_id_list	array	IDs of the topics to approve/restore +	* @param $id			mixed	Category of the current active module +	* @param $mode			string	Active module +	* @return null +	*/ +	static public function approve_topics($action, $topic_id_list, $id, $mode) +	{ +		global $db, $template, $user, $config; +		global $phpEx, $phpbb_root_path, $request; + +		if (!check_ids($topic_id_list, TOPICS_TABLE, 'topic_id', array('m_approve')))  		{ -			set_config_count('num_posts', $total_posts, true); +			trigger_error('NOT_AUTHORISED');  		} -		sync('topic', 'topic_id', array_keys($topic_id_list), true); -		sync('forum', 'forum_id', array_keys($forum_id_list), true, true); -		unset($topic_id_list, $forum_id_list); +		$redirect = $request->variable('redirect', build_url(array('quickmod'))); +		$success_msg = $topic_url = ''; +		$approve_log = array(); -		// Send out normal user notifications -		$email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']); +		$s_hidden_fields = build_hidden_fields(array( +			'i'				=> $id, +			'mode'			=> $mode, +			'topic_id_list'	=> $topic_id_list, +			'action'		=> $action, +			'redirect'		=> $redirect, +		)); -		$phpbb_notifications = $phpbb_container->get('notification_manager'); +		$topic_info = get_topic_data($topic_id_list, 'm_approve'); -		// Handle notifications -		foreach ($post_info as $post_id => $post_data) +		if (confirm_box(true))  		{ -			if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) +			$notify_poster = ($action == 'approve' && isset($_REQUEST['notify_poster'])) ? true : false; + +			foreach ($topic_info as $topic_id => $topic_data)  			{ -				$phpbb_notifications->delete_notifications('topic_in_queue', $post_data['topic_id']); +				phpbb_content_visibility::set_topic_visibility(ITEM_APPROVED, $topic_id, $topic_data['forum_id'], $user->data['user_id'], time(), ''); -				$phpbb_notifications->add_notifications(array( -					'quote', -					'topic', -				), $post_data); +				$topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f={$topic_data['forum_id']}&t={$topic_id}"); -				$phpbb_notifications->mark_notifications_read('quote', $post_data['post_id'], $user->data['user_id']); -				$phpbb_notifications->mark_notifications_read('topic', $post_data['topic_id'], $user->data['user_id']); +				$approve_log[] = array( +					'forum_id'		=> $topic_data['forum_id'], +					'topic_id'		=> $topic_data['topic_id'], +					'topic_title'	=> $topic_data['topic_title'], +				); +			} -				if ($notify_poster) -				{ -					$phpbb_notifications->add_notifications('approve_topic', $post_data); -				} +			if (sizeof($topic_info) >= 1) +			{ +				$success_msg = (sizeof($topic_info) == 1) ? 'TOPIC_' . strtoupper($action) . 'D_SUCCESS' : 'TOPICS_' . strtoupper($action) . 'D_SUCCESS';  			} -			else + +			foreach ($approve_log as $log_data)  			{ -				$phpbb_notifications->delete_notifications('post_in_queue', $post_id); +				add_log('mod', $log_data['forum_id'], $log_data['topic_id'], 'LOG_TOPIC_' . strtoupper($action) . 'D', $log_data['topic_title']); +			} -				$phpbb_notifications->add_notifications(array( -					'quote', -					'bookmark', -					'post', -				), $post_data); -				 -				$phpbb_notifications->mark_notifications_read(array( -					'quote', -					'bookmark', -					'post', -				),$post_data['post_id'], $user->data['user_id']); +			// Only send out the mails, when the posts are being approved +			if ($action == 'approve') +			{ +				// Handle notifications +				$phpbb_notifications = $phpbb_container->get('notification_manager'); -				if ($notify_poster) +				foreach ($topic_info as $topic_id => $topic_data)  				{ -					$phpbb_notifications->add_notifications('approve_post', $post_data); -				} -			} -		} +					$phpbb_notifications->delete_notifications('topic_in_queue', $post_data['topic_id']); +					$phpbb_notifications->add_notifications(array( +						'quote', +						'topic', +					), $post_data); -		if (sizeof($post_id_list) == 1) -		{ -			$post_data = $post_info[$post_id_list[0]]; -			$post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f={$post_data['forum_id']}&t={$post_data['topic_id']}&p={$post_data['post_id']}") . '#p' . $post_data['post_id']; -		} -		unset($post_info); +					$phpbb_notifications->mark_notifications_read('quote', $post_data['post_id'], $user->data['user_id']); +					$phpbb_notifications->mark_notifications_read('topic', $post_data['topic_id'], $user->data['user_id']); -		if ($total_topics) -		{ -			$success_msg = ($total_topics == 1) ? 'TOPIC_APPROVED_SUCCESS' : 'TOPICS_APPROVED_SUCCESS'; +					if ($notify_poster) +					{ +						$phpbb_notifications->add_notifications('approve_topic', $post_data); +					} +				} +			}  		}  		else  		{ -			$success_msg = (sizeof($post_id_list) + sizeof($post_approved_list) == 1) ? 'POST_APPROVED_SUCCESS' : 'POSTS_APPROVED_SUCCESS'; -		} -	} -	else -	{ -		$show_notify = false; +			$show_notify = false; -		if ($config['email_enable'] || $config['jab_enable']) -		{ -			foreach ($post_info as $post_data) +			if ($action == 'approve' && ($config['email_enable'] || $config['jab_enable']))  			{ -				if ($post_data['poster_id'] == ANONYMOUS) +				foreach ($topic_info as $topic_data)  				{ -					continue; -				} -				else -				{ -					$show_notify = true; -					break; +					if ($topic_data['topic_poster'] == ANONYMOUS) +					{ +						continue; +					} +					else +					{ +						$show_notify = true; +						break; +					}  				}  			} -		} -		$template->assign_vars(array( -			'S_NOTIFY_POSTER'	=> $show_notify, -			'S_APPROVE'			=> true) -		); - -		confirm_box(false, 'APPROVE_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html'); -	} - -	$redirect = request_var('redirect', "index.$phpEx"); -	$redirect = reapply_sid($redirect); - -	if (!$success_msg) -	{ -		redirect($redirect); -	} -	else -	{ -		meta_refresh(3, $redirect); +			$template->assign_vars(array( +				'S_NOTIFY_POSTER'			=> $show_notify, +				'S_' . strtoupper($action)	=> true, +			)); -		// If approving one post, also give links back to post... -		$add_message = ''; -		if (sizeof($post_id_list) == 1 && !empty($post_url)) -		{ -			$add_message = '<br /><br />' . sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>'); +			confirm_box(false, strtoupper($action) . '_TOPIC' . ((sizeof($topic_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html');  		} -		$message = $user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>') . $add_message; +		$redirect = $request->variable('redirect', "index.$phpEx"); +		$redirect = reapply_sid($redirect); -		if ($request->is_ajax()) +		if (!$success_msg)  		{ -			$json_response = new phpbb_json_response; -			$json_response->send(array( -				'MESSAGE_TITLE'		=> $user->lang['INFORMATION'], -				'MESSAGE_TEXT'		=> $message, -				'REFRESH_DATA'		=> null, -				'approved'				=> true -			)); +			redirect($redirect);  		} +		else +		{ +			meta_refresh(3, $redirect); -		trigger_error($message); -	} -} +			// If approving one topic, also give links back to topic... +			$add_message = ''; +			if (sizeof($topic_info) == 1 && $topic_url) +			{ +				$add_message = '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $topic_url . '">', '</a>'); +			} -/** -* Disapprove Post/Topic -*/ -function disapprove_post($post_id_list, $id, $mode) -{ -	global $db, $template, $user, $config; -	global $phpEx, $phpbb_root_path; -	global $request, $phpbb_container; +			$message = $user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>') . $add_message; -	if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) -	{ -		trigger_error('NOT_AUTHORISED'); +			if ($request->is_ajax()) +			{ +				$json_response = new phpbb_json_response; +				$json_response->send(array( +					'MESSAGE_TITLE'		=> $user->lang['INFORMATION'], +					'MESSAGE_TEXT'		=> $message, +					'REFRESH_DATA'		=> null, +					'visible'			=> true, +				)); +			} + +			trigger_error($message); +		}  	} -	$redirect = request_var('redirect', build_url(array('t', 'mode', 'quickmod')) . "&mode=$mode"); -	$reason = utf8_normalize_nfc(request_var('reason', '', true)); -	$reason_id = request_var('reason_id', 0); -	$success_msg = $additional_msg = ''; +	/** +	* Disapprove Post +	* +	* @param $post_id_list	array	IDs of the posts to disapprove/delete +	* @param $id			mixed	Category of the current active module +	* @param $mode			string	Active module +	* @return null +	*/ +	static public function disapprove_posts($post_id_list, $id, $mode) +	{ +		global $db, $template, $user, $config, $phpbb_container; +		global $phpEx, $phpbb_root_path, $request; -	$s_hidden_fields = build_hidden_fields(array( -		'i'				=> $id, -		'mode'			=> $mode, -		'post_id_list'	=> $post_id_list, -		'action'		=> 'disapprove', -		'redirect'		=> $redirect) -	); +		if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) +		{ +			trigger_error('NOT_AUTHORISED'); +		} -	$notify_poster = (isset($_REQUEST['notify_poster'])) ? true : false; -	$disapprove_reason = ''; +		$redirect = $request->variable('redirect', build_url(array('t', 'mode', 'quickmod')) . "&mode=$mode"); +		$reason = $request->variable('reason', '', true); +		$reason_id = $request->variable('reason_id', 0); +		$success_msg = $additional_msg = ''; + +		$s_hidden_fields = build_hidden_fields(array( +			'i'				=> $id, +			'mode'			=> $mode, +			'post_id_list'	=> $post_id_list, +			'action'		=> 'disapprove', +			'redirect'		=> $redirect) +		); -	if ($reason_id) -	{ -		$sql = 'SELECT reason_title, reason_description -			FROM ' . REPORTS_REASONS_TABLE . " -			WHERE reason_id = $reason_id"; -		$result = $db->sql_query($sql); -		$row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		if (!$row || (!$reason && strtolower($row['reason_title']) == 'other')) -		{ -			$additional_msg = $user->lang['NO_REASON_DISAPPROVAL']; +		$notify_poster = $request->is_set('notify_poster'); +		$disapprove_reason = ''; -			$request->overwrite('confirm', null, phpbb_request_interface::POST); -			$request->overwrite('confirm_key', null, phpbb_request_interface::POST); -			$request->overwrite('confirm_key', null, phpbb_request_interface::REQUEST); -		} -		else +		if ($reason_id)  		{ -			// If the reason is defined within the language file, we will use the localized version, else just use the database entry... -			$disapprove_reason = (strtolower($row['reason_title']) != 'other') ? ((isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])] : $row['reason_description']) : ''; -			$disapprove_reason .= ($reason) ? "\n\n" . $reason : ''; - -			if (isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) +			$sql = 'SELECT reason_title, reason_description +				FROM ' . REPORTS_REASONS_TABLE . " +				WHERE reason_id = $reason_id"; +			$result = $db->sql_query($sql); +			$row = $db->sql_fetchrow($result); +			$db->sql_freeresult($result); + +			if (!$row || (!$reason && strtolower($row['reason_title']) == 'other'))  			{ -				$disapprove_reason_lang = strtoupper($row['reason_title']); +				$additional_msg = $user->lang['NO_REASON_DISAPPROVAL']; + +				$request->overwrite('confirm', null, phpbb_request_interface::POST); +				$request->overwrite('confirm_key', null, phpbb_request_interface::POST); +				$request->overwrite('confirm_key', null, phpbb_request_interface::REQUEST);  			} +			else +			{ +				// If the reason is defined within the language file, we will use the localized version, else just use the database entry... +				$disapprove_reason = (strtolower($row['reason_title']) != 'other') ? ((isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])] : $row['reason_description']) : ''; +				$disapprove_reason .= ($reason) ? "\n\n" . $reason : ''; -			$email_disapprove_reason = $disapprove_reason; +				if (isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) +				{ +					$disapprove_reason_lang = strtoupper($row['reason_title']); +				} +			}  		} -	} -	$post_info = get_post_data($post_id_list, 'm_approve'); +		$post_info = get_post_data($post_id_list, 'm_approve'); -	if (confirm_box(true)) -	{ -		$disapprove_log = $disapprove_log_topics = $disapprove_log_posts = array(); -		$topic_replies_real = $post_disapprove_list = array(); - -		// Build a list of posts to be unapproved and get the related topics real replies count +		$is_disapproving = false;  		foreach ($post_info as $post_id => $post_data)  		{ -			$post_disapprove_list[$post_id] = $post_data['topic_id']; -			if (!isset($topic_replies_real[$post_data['topic_id']])) +			if ($post_data['post_visibility'] == ITEM_DELETED)  			{ -				$topic_replies_real[$post_data['topic_id']] = $post_data['topic_replies_real']; +				continue;  			} + +			$is_disapproving = true;  		} -		// Now we build the log array -		foreach ($post_disapprove_list as $post_id => $topic_id) +		if (confirm_box(true))  		{ -			// If the count of disapproved posts for the topic is greater -			// than topic's real replies count, the whole topic is disapproved/deleted -			if (sizeof(array_keys($post_disapprove_list, $topic_id)) > $topic_replies_real[$topic_id]) +			$disapprove_log = $disapprove_log_topics = $disapprove_log_posts = array(); +			$topic_posts_unapproved = $post_disapprove_list = $topic_information = array(); + +			// Build a list of posts to be disapproved and get the related topics real replies count +			foreach ($post_info as $post_id => $post_data)  			{ -				// Don't write the log more than once for every topic -				if (!isset($disapprove_log_topics[$topic_id])) +				$post_disapprove_list[$post_id] = $post_data['topic_id']; +				if (!isset($topic_posts_unapproved[$post_data['topic_id']]))  				{ -					// Build disapproved topics log -					$disapprove_log_topics[$topic_id] = array( -						'type'			=> 'topic', -						'post_subject'	=> $post_info[$post_id]['topic_title'], -						'forum_id'		=> $post_info[$post_id]['forum_id'], -						'topic_id'		=> 0, // useless to log a topic id, as it will be deleted -					); +					$topic_information[$post_data['topic_id']] = $post_data; +					$topic_posts_unapproved[$post_data['topic_id']] = 0;  				} +				$topic_posts_unapproved[$post_data['topic_id']]++;  			} -			else + +			// Now we build the log array +			foreach ($post_disapprove_list as $post_id => $topic_id)  			{ -				// Build disapproved posts log -				$disapprove_log_posts[] = array( -					'type'			=> 'post', -					'post_subject'	=> $post_info[$post_id]['post_subject'], -					'forum_id'		=> $post_info[$post_id]['forum_id'], -					'topic_id'		=> $post_info[$post_id]['topic_id'], -				); +				// If the count of disapproved posts for the topic is equal +				// to the number of unapproved posts in the topic, and there are no different +				// posts, we disapprove the hole topic +				if ($topic_information[$topic_id]['topic_posts_approved'] == 0 && +					$topic_information[$topic_id]['topic_posts_softdeleted'] == 0 && +					$topic_information[$topic_id]['topic_posts_unapproved'] == $topic_posts_unapproved[$topic_id]) +				{ +					// Don't write the log more than once for every topic +					if (!isset($disapprove_log_topics[$topic_id])) +					{ +						// Build disapproved topics log +						$disapprove_log_topics[$topic_id] = array( +							'type'			=> 'topic', +							'post_subject'	=> $post_info[$post_id]['topic_title'], +							'forum_id'		=> $post_info[$post_id]['forum_id'], +							'topic_id'		=> 0, // useless to log a topic id, as it will be deleted +							'post_username'	=> ($post_info[$post_id]['poster_id'] == ANONYMOUS && !empty($post_info[$post_id]['post_username'])) ? $post_info[$post_id]['post_username'] : $post_info[$post_id]['username'], +						); +					} +				} +				else +				{ +					// Build disapproved posts log +					$disapprove_log_posts[] = array( +						'type'			=> 'post', +						'post_subject'	=> $post_info[$post_id]['post_subject'], +						'forum_id'		=> $post_info[$post_id]['forum_id'], +						'topic_id'		=> $post_info[$post_id]['topic_id'], +						'post_username'	=> ($post_info[$post_id]['poster_id'] == ANONYMOUS && !empty($post_info[$post_id]['post_username'])) ? $post_info[$post_id]['post_username'] : $post_info[$post_id]['username'], +					); +				}  			} -		} -		// Get disapproved posts/topics counts separately -		$num_disapproved_topics = sizeof($disapprove_log_topics); -		$num_disapproved_posts = sizeof($disapprove_log_posts); +			// Get disapproved posts/topics counts separately +			$num_disapproved_topics = sizeof($disapprove_log_topics); +			$num_disapproved_posts = sizeof($disapprove_log_posts); -		// Build the whole log -		$disapprove_log = array_merge($disapprove_log_topics, $disapprove_log_posts); +			// Build the whole log +			$disapprove_log = array_merge($disapprove_log_topics, $disapprove_log_posts); -		// Unset unneeded arrays -		unset($post_data, $disapprove_log_topics, $disapprove_log_posts); +			// Unset unneeded arrays +			unset($post_data, $disapprove_log_topics, $disapprove_log_posts); -		// Let's do the job - delete disapproved posts -		if (sizeof($post_disapprove_list)) -		{ -			if (!function_exists('delete_posts')) +			// Let's do the job - delete disapproved posts +			if (sizeof($post_disapprove_list))  			{ -				include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); -			} +				if (!function_exists('delete_posts')) +				{ +					include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); +				} -			// We do not check for permissions here, because the moderator allowed approval/disapproval should be allowed to delete the disapproved posts -			// Note: function delete_posts triggers related forums/topics sync, -			// so we don't need to call update_post_information later and to adjust real topic replies or forum topics count manually -			delete_posts('post_id', array_keys($post_disapprove_list)); +				// We do not check for permissions here, because the moderator allowed approval/disapproval should be allowed to delete the disapproved posts +				// Note: function delete_posts triggers related forums/topics sync, +				// so we don't need to call update_post_information later and to adjust real topic replies or forum topics count manually +				delete_posts('post_id', array_keys($post_disapprove_list)); -			foreach ($disapprove_log as $log_data) -			{ -				add_log('mod', $log_data['forum_id'], $log_data['topic_id'], ($log_data['type'] == 'topic') ? 'LOG_TOPIC_DISAPPROVED' : 'LOG_POST_DISAPPROVED', $log_data['post_subject'], $disapprove_reason); +				foreach ($disapprove_log as $log_data) +				{ +					if ($is_disapproving) +					{ +						$l_log_message = ($log_data['type'] == 'topic') ? 'LOG_TOPIC_DISAPPROVED' : 'LOG_POST_DISAPPROVED'; +						add_log('mod', $log_data['forum_id'], $log_data['topic_id'], $l_log_message, $log_data['post_subject'], $disapprove_reason); +					} +					else +					{ +						$l_log_message = ($log_data['type'] == 'topic') ? 'LOG_DELETE_TOPIC' : 'LOG_DELETE_POST'; +						add_log('mod', $log_data['forum_id'], $log_data['topic_id'], $l_log_message, $log_data['post_subject'], $log_data['post_username']); +					} +				}  			} -		} -		$phpbb_notifications = $phpbb_container->get('notification_manager'); +			$phpbb_notifications = $phpbb_container->get('notification_manager'); -		foreach ($post_info as $post_id => $post_data) -		{ -			if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) -			{ -				$phpbb_notifications->delete_notifications('topic_in_queue', $post_data['topic_id']); -			} -			else -			{ -				$phpbb_notifications->delete_notifications('post_in_queue', $post_id); -			} -		} - -		// Notify Poster? -		if ($notify_poster) -		{  			$lang_reasons = array(); -			// Handle notifications  			foreach ($post_info as $post_id => $post_data)  			{ -				$post_data['disapprove_reason'] = ''; -				if (isset($disapprove_reason_lang)) +				$disapprove_all_posts_in_topic = $topic_information[$topic_id]['topic_posts_approved'] == 0 && +					$topic_information[$topic_id]['topic_posts_softdeleted'] == 0 && +					$topic_information[$topic_id]['topic_posts_unapproved'] == $topic_posts_unapproved[$topic_id]; + +				$phpbb_notifications->delete_notifications('post_in_queue', $post_id); + +				// Do we disapprove the whole topic? Remove potential notifications +				if ($disapprove_all_posts_in_topic) +				{ +					$phpbb_notifications->delete_notifications('topic_in_queue', $post_data['topic_id']); +				} + +				// Notify Poster? +				if ($notify_poster)  				{ -					// Okay we need to get the reason from the posters language -					if (!isset($lang_reasons[$post_data['user_lang']])) +					if ($post_data['poster_id'] == ANONYMOUS)  					{ -						// Assign the current users translation as the default, this is not ideal but getting the board default adds another layer of complexity. -						$lang_reasons[$post_data['user_lang']] = $user->lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; +						continue; +					} -						// Only load up the language pack if the language is different to the current one -						if ($post_data['user_lang'] != $user->lang_name && file_exists($phpbb_root_path . '/language/' . $post_data['user_lang'] . '/mcp.' . $phpEx)) +					$post_data['disapprove_reason'] = ''; +					if (isset($disapprove_reason_lang)) +					{ +						// Okay we need to get the reason from the posters language +						if (!isset($lang_reasons[$post_data['user_lang']]))  						{ -							// Load up the language pack -							$lang = array(); -							@include($phpbb_root_path . '/language/' . basename($post_data['user_lang']) . '/mcp.' . $phpEx); +							// Assign the current users translation as the default, this is not ideal but getting the board default adds another layer of complexity. +							$lang_reasons[$post_data['user_lang']] = $user->lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; -							// If we find the reason in this language pack use it -							if (isset($lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang])) +							// Only load up the language pack if the language is different to the current one +							if ($post_data['user_lang'] != $user->lang_name && file_exists($phpbb_root_path . '/language/' . $post_data['user_lang'] . '/mcp.' . $phpEx))  							{ -								$lang_reasons[$post_data['user_lang']] = $lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; -							} +								// Load up the language pack +								$lang = array(); +								@include($phpbb_root_path . '/language/' . basename($post_data['user_lang']) . '/mcp.' . $phpEx); -							unset($lang); // Free memory +								// If we find the reason in this language pack use it +								if (isset($lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang])) +								{ +									$lang_reasons[$post_data['user_lang']] = $lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; +								} + +								unset($lang); // Free memory +							}  						} + +						$post_data['disapprove_reason'] = $lang_reasons[$post_data['user_lang']]; +						$post_data['disapprove_reason'] .= ($reason) ? "\n\n" . $reason : '';  					} -					$post_data['disapprove_reason'] = $lang_reasons[$post_data['user_lang']]; -					$post_data['disapprove_reason'] .= ($reason) ? "\n\n" . $reason : ''; -				} -				if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) -				{ -					if ($notify_poster) +					if ($disapprove_all_posts_in_topic && $topic_information[$topic_id]['topic_posts_unapproved'] == 1)  					{ +						// If there is only 1 post when disapproving the topic, +						// we send the user a "disapprove topic" notification...  						$phpbb_notifications->add_notifications('disapprove_topic', $post_data);  					} -				} -				else -				{ -					if ($notify_poster) +					else  					{ +						// ... otherwise there are multiple unapproved posts and +						// all of them are disapproved as posts.  						$phpbb_notifications->add_notifications('disapprove_post', $post_data);  					}  				}  			} -			unset($lang_reasons); -		} -		unset($post_info, $disapprove_reason, $email_disapprove_reason, $disapprove_reason_lang); +			unset($lang_reasons, $post_info, $disapprove_reason, $disapprove_reason_lang); -		if ($num_disapproved_topics) -		{ -			$success_msg = ($num_disapproved_topics == 1) ? 'TOPIC_DISAPPROVED_SUCCESS' : 'TOPICS_DISAPPROVED_SUCCESS'; + +			if ($num_disapproved_topics) +			{ +				$success_msg = ($num_disapproved_topics == 1) ? 'TOPIC' : 'TOPICS'; +			} +			else +			{ +				$success_msg = ($num_disapproved_posts == 1) ? 'POST' : 'POSTS'; +			} + +			if ($is_disapproving) +			{ +				$success_msg .= '_DISAPPROVED_SUCCESS'; +			} +			else +			{ +				$success_msg .= '_DELETED_SUCCESS'; +			}  		}  		else  		{ -			$success_msg = ($num_disapproved_posts == 1) ? 'POST_DISAPPROVED_SUCCESS' : 'POSTS_DISAPPROVED_SUCCESS'; -		} -	} -	else -	{ -		include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx); +			include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx); -		display_reasons($reason_id); +			$show_notify = false; -		$show_notify = false; +			foreach ($post_info as $post_data) +			{ +				if ($post_data['poster_id'] == ANONYMOUS) +				{ +					continue; +				} +				else +				{ +					$show_notify = true; +					break; +				} +			} -		foreach ($post_info as $post_data) -		{ -			if ($post_data['poster_id'] == ANONYMOUS) +			$l_confirm_msg = 'DISAPPROVE_POST'; +			$confirm_template = 'mcp_approve.html'; +			if ($is_disapproving)  			{ -				continue; +				display_reasons($reason_id);  			}  			else  			{ -				$show_notify = true; -				break; +				$user->add_lang('posting'); + +				$l_confirm_msg = 'DELETE_POST_PERMANENTLY'; +				$confirm_template = 'confirm_delete_body.html';  			} -		} +			$l_confirm_msg .= ((sizeof($post_id_list) == 1) ? '' : 'S'); -		$template->assign_vars(array( -			'S_NOTIFY_POSTER'	=> $show_notify, -			'S_APPROVE'			=> false, -			'REASON'			=> $reason, -			'ADDITIONAL_MSG'	=> $additional_msg) -		); +			$template->assign_vars(array( +				'S_NOTIFY_POSTER'	=> $show_notify, +				'S_APPROVE'			=> false, +				'REASON'			=> ($is_disapproving) ? $reason : '', +				'ADDITIONAL_MSG'	=> $additional_msg, +			)); -		confirm_box(false, 'DISAPPROVE_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html'); -	} +			confirm_box(false, $l_confirm_msg, $s_hidden_fields, $confirm_template); +		} -	$redirect = request_var('redirect', "index.$phpEx"); -	$redirect = reapply_sid($redirect); +		$redirect = $request->variable('redirect', "index.$phpEx"); +		$redirect = reapply_sid($redirect); -	if (!$success_msg) -	{ -		redirect($redirect); -	} -	else -	{ -		$message = $user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>'); - -		if ($request->is_ajax()) +		if (!$success_msg)  		{ -			$json_response = new phpbb_json_response; -			$json_response->send(array( -				'MESSAGE_TITLE'		=> $user->lang['INFORMATION'], -				'MESSAGE_TEXT'		=> $message, -				'REFRESH_DATA'		=> null, -				'approved'				=> false -			)); +			redirect($redirect);  		} +		else +		{ +			$message = $user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>'); -		meta_refresh(3, $redirect); -		trigger_error($message); +			if ($request->is_ajax()) +			{ +				$json_response = new phpbb_json_response; +				$json_response->send(array( +					'MESSAGE_TITLE'		=> $user->lang['INFORMATION'], +					'MESSAGE_TEXT'		=> $message, +					'REFRESH_DATA'		=> null, +					'visible'			=> false, +				)); +			} + +			meta_refresh(3, $redirect); +			trigger_error($message); +		}  	}  } diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 0a600d7057..72400ce623 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -187,7 +187,7 @@ class mcp_reports  					'S_CLOSE_ACTION'		=> append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id),  					'S_CAN_VIEWIP'			=> $auth->acl_get('m_info', $post_info['forum_id']),  					'S_POST_REPORTED'		=> $post_info['post_reported'], -					'S_POST_UNAPPROVED'		=> !$post_info['post_approved'], +					'S_POST_UNAPPROVED'		=> ($post_info['post_visibility'] == POST_UNAPPROVED),  					'S_POST_LOCKED'			=> $post_info['post_edit_locked'],  					'S_USER_NOTES'			=> true, @@ -292,11 +292,11 @@ class mcp_reports  					$global_id = $forum_list[0]; -					$sql = 'SELECT SUM(forum_topics) as sum_forum_topics +					$sql = 'SELECT SUM(forum_topics_approved) as sum_forum_topics  						FROM ' . FORUMS_TABLE . '  						WHERE ' . $db->sql_in_set('forum_id', $forum_list);  					$result = $db->sql_query($sql); -					$forum_info['forum_topics'] = (int) $db->sql_fetchfield('sum_forum_topics'); +					$forum_info['forum_topics_approved'] = (int) $db->sql_fetchfield('sum_forum_topics');  					$db->sql_freeresult($result);  				}  				else @@ -328,7 +328,7 @@ class mcp_reports  				$sort_by_sql = $sort_order_sql = array();  				mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); -				$forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total; +				$forum_topics = ($total == -1) ? $forum_info['forum_topics_approved'] : $total;  				$limit_time_sql = ($sort_days) ? 'AND r.report_time >= ' . (time() - ($sort_days * 86400)) : '';  				if ($mode == 'reports') diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index e3dd5a6b57..1d2030edb1 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -84,8 +84,8 @@ function mcp_topic_view($id, $mode, $action)  		$subject = $topic_info['topic_title'];  	} -	// Approve posts? -	if ($action == 'approve' && $auth->acl_get('m_approve', $topic_info['forum_id'])) +	// Restore or pprove posts? +	if (($action == 'restore' || $action == 'approve') && $auth->acl_get('m_approve', $topic_info['forum_id']))  	{  		include($phpbb_root_path . 'includes/mcp/mcp_queue.' . $phpEx);  		include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); @@ -98,7 +98,7 @@ function mcp_topic_view($id, $mode, $action)  		if (!$sort)  		{ -			approve_post($post_id_list, $id, $mode); +			mcp_queue::approve_posts($action, $post_id_list, $id, $mode);  		}  	} @@ -115,14 +115,7 @@ function mcp_topic_view($id, $mode, $action)  	if ($total == -1)  	{ -		if ($auth->acl_get('m_approve', $topic_info['forum_id'])) -		{ -			$total = $topic_info['topic_replies_real'] + 1; -		} -		else -		{ -			$total = $topic_info['topic_replies'] + 1; -		} +		$total = phpbb_content_visibility::get_count('topic_posts', $topic_info, $topic_info['forum_id']);  	}  	$posts_per_page = max(0, request_var('posts_per_page', intval($config['posts_per_page']))); @@ -145,8 +138,8 @@ function mcp_topic_view($id, $mode, $action)  	$sql = 'SELECT u.username, u.username_clean, u.user_colour, p.*  		FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u  		WHERE ' . (($action == 'reports') ? 'p.post_reported = 1 AND ' : '') . ' -			p.topic_id = ' . $topic_id . ' ' . -			((!$auth->acl_get('m_approve', $topic_info['forum_id'])) ? ' AND p.post_approved = 1 ' : '') . ' +			p.topic_id = ' . $topic_id . ' +			AND ' .	phpbb_content_visibility::get_visibility_sql('post', $topic_info['forum_id'], 'p.') . '  			AND p.poster_id = u.user_id ' .  			$limit_time_sql . '  		ORDER BY ' . $sort_order_sql; @@ -182,7 +175,7 @@ function mcp_topic_view($id, $mode, $action)  		$topic_tracking_info = get_complete_topic_tracking($topic_info['forum_id'], $topic_id);  	} -	$has_unapproved_posts = false; +	$has_unapproved_posts = $has_deleted_posts = false;  	// Grab extensions  	$extensions = $attachments = array(); @@ -227,11 +220,16 @@ function mcp_topic_view($id, $mode, $action)  			parse_attachments($topic_info['forum_id'], $message, $attachments[$row['post_id']], $update_count);  		} -		if (!$row['post_approved']) +		if ($row['post_visibility'] == ITEM_UNAPPROVED)  		{  			$has_unapproved_posts = true;  		} +		if ($row['post_visibility'] == ITEM_DELETED) +		{ +			$has_deleted_posts = true; +		} +  		$post_unread = (isset($topic_tracking_info[$topic_id]) && $row['post_time'] > $topic_tracking_info[$topic_id]) ? true : false;  		$template->assign_block_vars('postrow', array( @@ -249,7 +247,8 @@ function mcp_topic_view($id, $mode, $action)  			'MINI_POST_IMG'			=> ($post_unread) ? $user->img('icon_post_target_unread', 'UNREAD_POST') : $user->img('icon_post_target', 'POST'),  			'S_POST_REPORTED'	=> ($row['post_reported'] && $auth->acl_get('m_report', $topic_info['forum_id'])), -			'S_POST_UNAPPROVED'	=> (!$row['post_approved'] && $auth->acl_get('m_approve', $topic_info['forum_id'])), +			'S_POST_UNAPPROVED'	=> ($row['post_visibility'] == ITEM_UNAPPROVED && $auth->acl_get('m_approve', $topic_info['forum_id'])), +			'S_POST_DELETED'	=> ($row['post_visibility'] == ITEM_DELETED && $auth->acl_get('m_approve', $topic_info['forum_id'])),  			'S_CHECKED'			=> (($submitted_id_list && !in_array(intval($row['post_id']), $submitted_id_list)) || in_array(intval($row['post_id']), $checked_ids)) ? true : false,  			'S_HAS_ATTACHMENTS'	=> (!empty($attachments[$row['post_id']])) ? true : false, @@ -325,6 +324,7 @@ function mcp_topic_view($id, $mode, $action)  		'REPORTED_IMG'		=> $user->img('icon_topic_reported', 'POST_REPORTED'),  		'UNAPPROVED_IMG'	=> $user->img('icon_topic_unapproved', 'POST_UNAPPROVED'), +		'DELETED_IMG'		=> $user->img('icon_topic_deleted', 'POST_DELETED_RESTORE'),  		'INFO_IMG'			=> $user->img('icon_post_info', 'VIEW_INFO'),  		'S_MCP_ACTION'		=> "$url&i=$id&mode=$mode&action=$action&start=$start", @@ -333,6 +333,7 @@ function mcp_topic_view($id, $mode, $action)  		'S_CAN_MERGE'		=> ($auth->acl_get('m_merge', $topic_info['forum_id'])) ? true : false,  		'S_CAN_DELETE'		=> ($auth->acl_get('m_delete', $topic_info['forum_id'])) ? true : false,  		'S_CAN_APPROVE'		=> ($has_unapproved_posts && $auth->acl_get('m_approve', $topic_info['forum_id'])) ? true : false, +		'S_CAN_RESTORE'		=> ($has_deleted_posts && $auth->acl_get('m_approve', $topic_info['forum_id'])) ? true : false,  		'S_CAN_LOCK'		=> ($auth->acl_get('m_lock', $topic_info['forum_id'])) ? true : false,  		'S_CAN_REPORT'		=> ($auth->acl_get('m_report', $topic_info['forum_id'])) ? true : false,  		'S_CAN_SYNC'		=> $auth->acl_get('m_', $topic_info['forum_id']), @@ -448,7 +449,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)  			if ($sort_order_sql[0] == 'u')  			{ -				$sql = 'SELECT p.post_id, p.forum_id, p.post_approved +				$sql = 'SELECT p.post_id, p.forum_id, p.post_visibility  					FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u  					WHERE p.topic_id = $topic_id  						AND p.poster_id = u.user_id @@ -457,7 +458,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)  			}  			else  			{ -				$sql = 'SELECT p.post_id, p.forum_id, p.post_approved +				$sql = 'SELECT p.post_id, p.forum_id, p.post_visibility  					FROM ' . POSTS_TABLE . " p  					WHERE p.topic_id = $topic_id  						$limit_time_sql @@ -470,7 +471,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)  			while ($row = $db->sql_fetchrow($result))  			{  				// If split from selected post (split_beyond), we split the unapproved items too. -				if (!$row['post_approved'] && !$auth->acl_get('m_approve', $row['forum_id'])) +				if ($row['post_visibility'] == ITEM_UNAPPROVED && !$auth->acl_get('m_approve', $row['forum_id']))  				{  //					continue;  				} @@ -497,10 +498,10 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)  		$icon_id = request_var('icon', 0);  		$sql_ary = array( -			'forum_id'		=> $to_forum_id, -			'topic_title'	=> $subject, -			'icon_id'		=> $icon_id, -			'topic_approved'=> 1 +			'forum_id'			=> $to_forum_id, +			'topic_title'		=> $subject, +			'icon_id'			=> $icon_id, +			'topic_visibility'	=> 1  		);  		$sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php index aa493c3281..2dd95a9680 100644 --- a/phpBB/includes/search/fulltext_mysql.php +++ b/phpBB/includes/search/fulltext_mysql.php @@ -351,7 +351,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base  	* @param	string		$sort_dir			is either a or d representing ASC and DESC  	* @param	string		$sort_days			specifies the maximum amount of days a post may be old  	* @param	array		$ex_fid_ary			specifies an array of forum ids which should not be searched -	* @param	array		$m_approve_fid_ary	specifies an array of forum ids in which the searcher is allowed to view unapproved posts +	* @param	string		$post_visibility	specifies which types of posts the user can view in which forums  	* @param	int			$topic_id			is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched  	* @param	array		$author_ary			an array of author ids if the author should be ignored during the search the array is empty  	* @param	string		$author_name		specifies the author match, when ANONYMOUS is also a search-match @@ -360,7 +360,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base  	* @param	int			$per_page			number of ids each page is supposed to contain  	* @return	boolean|int						total number of results  	*/ -	public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) +	public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)  	{  		// No keywords? No posts  		if (!$this->search_query) @@ -378,7 +378,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base  			$sort_key,  			$topic_id,  			implode(',', $ex_fid_ary), -			implode(',', $m_approve_fid_ary), +			$post_visibility,  			implode(',', $author_ary)  		))); @@ -445,19 +445,6 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base  			break;  		} -		if (!sizeof($m_approve_fid_ary)) -		{ -			$m_approve_fid_sql = ' AND p.post_approved = 1'; -		} -		else if ($m_approve_fid_ary === array(-1)) -		{ -			$m_approve_fid_sql = ''; -		} -		else -		{ -			$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; -		} -  		$sql_select			= (!$result_count) ? 'SQL_CALC_FOUND_ROWS ' : '';  		$sql_select			= ($type == 'posts') ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id';  		$sql_from			= ($join_topic) ? TOPICS_TABLE . ' t, ' : ''; @@ -480,7 +467,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base  		$sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : '';  		$sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : '';  		$sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; -		$sql_where_options .= $m_approve_fid_sql; +		$sql_where_options .= ' AND ' . $post_visibility;  		$sql_where_options .= $sql_author;  		$sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';  		$sql_where_options .= $sql_match_where; @@ -546,7 +533,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base  	* @param	string		$sort_dir			is either a or d representing ASC and DESC  	* @param	string		$sort_days			specifies the maximum amount of days a post may be old  	* @param	array		$ex_fid_ary			specifies an array of forum ids which should not be searched -	* @param	array		$m_approve_fid_ary	specifies an array of forum ids in which the searcher is allowed to view unapproved posts +	* @param	string		$post_visibility	specifies which types of posts the user can view in which forums  	* @param	int			$topic_id			is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched  	* @param	array		$author_ary			an array of author ids  	* @param	string		$author_name		specifies the author match, when ANONYMOUS is also a search-match @@ -574,7 +561,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base  			$sort_key,  			$topic_id,  			implode(',', $ex_fid_ary), -			implode(',', $m_approve_fid_ary), +			$post_visibility,  			implode(',', $author_ary),  			$author_name,  		))); @@ -629,18 +616,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base  			break;  		} -		if (!sizeof($m_approve_fid_ary)) -		{ -			$m_approve_fid_sql = ' AND p.post_approved = 1'; -		} -		else if ($m_approve_fid_ary == array(-1)) -		{ -			$m_approve_fid_sql = ''; -		} -		else -		{ -			$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; -		} +		$m_approve_fid_sql = ' AND ' . $post_visibility;  		// If the cache was completely empty count the results  		$calc_results = ($result_count) ? '' : 'SQL_CALC_FOUND_ROWS '; diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php index b9c784ea67..730c3a6c2d 100644 --- a/phpBB/includes/search/fulltext_native.php +++ b/phpBB/includes/search/fulltext_native.php @@ -507,7 +507,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  	* @param	string		$sort_dir			is either a or d representing ASC and DESC  	* @param	string		$sort_days			specifies the maximum amount of days a post may be old  	* @param	array		$ex_fid_ary			specifies an array of forum ids which should not be searched -	* @param	array		$m_approve_fid_ary	specifies an array of forum ids in which the searcher is allowed to view unapproved posts +	* @param	string		$post_visibility	specifies which types of posts the user can view in which forums  	* @param	int			$topic_id			is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched  	* @param	array		$author_ary			an array of author ids if the author should be ignored during the search the array is empty  	* @param	string		$author_name		specifies the author match, when ANONYMOUS is also a search-match @@ -516,7 +516,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  	* @param	int			$per_page			number of ids each page is supposed to contain  	* @return	boolean|int						total number of results  	*/ -	public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) +	public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)  	{  		// No keywords? No posts.  		if (empty($this->search_query)) @@ -544,7 +544,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  			$sort_key,  			$topic_id,  			implode(',', $ex_fid_ary), -			implode(',', $m_approve_fid_ary), +			$post_visibility,  			implode(',', $author_ary),  			$author_name,  		))); @@ -721,14 +721,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  			$sql_where[] = '(' . implode(' OR ', $is_null_joins) . ')';  		} -		if (!sizeof($m_approve_fid_ary)) -		{ -			$sql_where[] = 'p.post_approved = 1'; -		} -		else if ($m_approve_fid_ary !== array(-1)) -		{ -			$sql_where[] = '(p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; -		} +		$sql_where[] = $post_visibility;  		if ($topic_id)  		{ @@ -911,7 +904,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  	* @param	string		$sort_dir			is either a or d representing ASC and DESC  	* @param	string		$sort_days			specifies the maximum amount of days a post may be old  	* @param	array		$ex_fid_ary			specifies an array of forum ids which should not be searched -	* @param	array		$m_approve_fid_ary	specifies an array of forum ids in which the searcher is allowed to view unapproved posts +	* @param	string		$post_visibility	specifies which types of posts the user can view in which forums  	* @param	int			$topic_id			is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched  	* @param	array		$author_ary			an array of author ids  	* @param	string		$author_name		specifies the author match, when ANONYMOUS is also a search-match @@ -920,7 +913,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  	* @param	int			$per_page			number of ids each page is supposed to contain  	* @return	boolean|int						total number of results  	*/ -	public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) +	public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)  	{  		// No author? No posts  		if (!sizeof($author_ary)) @@ -939,7 +932,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  			$sort_key,  			$topic_id,  			implode(',', $ex_fid_ary), -			implode(',', $m_approve_fid_ary), +			$post_visibility,  			implode(',', $author_ary),  			$author_name,  		))); @@ -967,6 +960,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  		$sql_time		= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';  		$sql_topic_id	= ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';  		$sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : ''; +		$post_visibility = ($post_visibility) ? ' AND ' . $post_visibility : '';  		// Build sql strings for sorting  		$sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); @@ -989,19 +983,6 @@ class phpbb_search_fulltext_native extends phpbb_search_base  			break;  		} -		if (!sizeof($m_approve_fid_ary)) -		{ -			$m_approve_fid_sql = ' AND p.post_approved = 1'; -		} -		else if ($m_approve_fid_ary == array(-1)) -		{ -			$m_approve_fid_sql = ''; -		} -		else -		{ -			$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; -		} -  		$select = ($type == 'posts') ? 'p.post_id' : 't.topic_id';  		$is_mysql = false; @@ -1024,7 +1005,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  							WHERE $sql_author  								$sql_topic_id  								$sql_firstpost -								$m_approve_fid_sql +								$post_visibility  								$sql_fora  								$sql_time";  					} @@ -1044,7 +1025,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  							WHERE $sql_author  								$sql_topic_id  								$sql_firstpost -								$m_approve_fid_sql +								$post_visibility  								$sql_fora  								AND t.topic_id = p.topic_id  								$sql_time" . (($this->db->sql_layer == 'sqlite') ? ')' : ''); @@ -1070,7 +1051,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  				WHERE $sql_author  					$sql_topic_id  					$sql_firstpost -					$m_approve_fid_sql +					$post_visibility  					$sql_fora  					$sql_sort_join  					$sql_time @@ -1084,7 +1065,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base  				WHERE $sql_author  					$sql_topic_id  					$sql_firstpost -					$m_approve_fid_sql +					$post_visibility  					$sql_fora  					AND t.topic_id = p.topic_id  					$sql_sort_join diff --git a/phpBB/includes/search/fulltext_postgres.php b/phpBB/includes/search/fulltext_postgres.php index 496a29f5a3..16369c3d95 100644 --- a/phpBB/includes/search/fulltext_postgres.php +++ b/phpBB/includes/search/fulltext_postgres.php @@ -334,7 +334,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base  	* @param	string		$sort_dir			is either a or d representing ASC and DESC  	* @param	string		$sort_days			specifies the maximum amount of days a post may be old  	* @param	array		$ex_fid_ary			specifies an array of forum ids which should not be searched -	* @param	array		$m_approve_fid_ary	specifies an array of forum ids in which the searcher is allowed to view unapproved posts +	* @param	string		$post_visibility	specifies which types of posts the user can view in which forums  	* @param	int			$topic_id			is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched  	* @param	array		$author_ary			an array of author ids if the author should be ignored during the search the array is empty  	* @param	string		$author_name		specifies the author match, when ANONYMOUS is also a search-match @@ -343,7 +343,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base  	* @param	int			$per_page			number of ids each page is supposed to contain  	* @return	boolean|int						total number of results  	*/ -	public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) +	public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)  	{  		// No keywords? No posts  		if (!$this->search_query) @@ -367,7 +367,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base  			$sort_key,  			$topic_id,  			implode(',', $ex_fid_ary), -			implode(',', $m_approve_fid_ary), +			$post_visibility,  			implode(',', $author_ary)  		))); @@ -434,19 +434,6 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base  			break;  		} -		if (!sizeof($m_approve_fid_ary)) -		{ -			$m_approve_fid_sql = ' AND p.post_approved = 1'; -		} -		else if ($m_approve_fid_ary === array(-1)) -		{ -			$m_approve_fid_sql = ''; -		} -		else -		{ -			$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; -		} -  		$sql_select			= ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id';  		$sql_from			= ($join_topic) ? TOPICS_TABLE . ' t, ' : '';  		$field				= ($type == 'posts') ? 'post_id' : 'topic_id'; @@ -470,7 +457,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base  		$sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : '';  		$sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : '';  		$sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; -		$sql_where_options .= $m_approve_fid_sql; +		$sql_where_options .= ' AND ' . $post_visibility;  		$sql_where_options .= $sql_author;  		$sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';  		$sql_where_options .= $sql_match_where; @@ -550,7 +537,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base  	* @param	string		$sort_dir			is either a or d representing ASC and DESC  	* @param	string		$sort_days			specifies the maximum amount of days a post may be old  	* @param	array		$ex_fid_ary			specifies an array of forum ids which should not be searched -	* @param	array		$m_approve_fid_ary	specifies an array of forum ids in which the searcher is allowed to view unapproved posts +	* @param	string		$post_visibility	specifies which types of posts the user can view in which forums  	* @param	int			$topic_id			is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched  	* @param	array		$author_ary			an array of author ids  	* @param	string		$author_name		specifies the author match, when ANONYMOUS is also a search-match @@ -559,7 +546,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base  	* @param	int			$per_page			number of ids each page is supposed to contain  	* @return	boolean|int						total number of results  	*/ -	public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) +	public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)  	{  		// No author? No posts  		if (!sizeof($author_ary)) @@ -578,7 +565,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base  			$sort_key,  			$topic_id,  			implode(',', $ex_fid_ary), -			implode(',', $m_approve_fid_ary), +			$post_visibility,  			implode(',', $author_ary),  			$author_name,  		))); @@ -633,18 +620,7 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base  			break;  		} -		if (!sizeof($m_approve_fid_ary)) -		{ -			$m_approve_fid_sql = ' AND p.post_approved = 1'; -		} -		else if ($m_approve_fid_ary == array(-1)) -		{ -			$m_approve_fid_sql = ''; -		} -		else -		{ -			$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $this->db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; -		} +		$m_approve_fid_sql = ' AND ' . $post_visibility;  		// Build the query for really selecting the post_ids  		if ($type == 'posts') diff --git a/phpBB/includes/search/fulltext_sphinx.php b/phpBB/includes/search/fulltext_sphinx.php index 889324bbda..2f7b236c78 100644 --- a/phpBB/includes/search/fulltext_sphinx.php +++ b/phpBB/includes/search/fulltext_sphinx.php @@ -274,6 +274,7 @@ class phpbb_search_fulltext_sphinx  						p.forum_id,  						p.topic_id,  						p.poster_id, +						p.post_visibility,  						CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,  						p.post_time,  						p.post_subject, @@ -291,6 +292,7 @@ class phpbb_search_fulltext_sphinx  				array('sql_attr_uint',				'forum_id'),  				array('sql_attr_uint',				'topic_id'),  				array('sql_attr_uint',				'poster_id'), +				array('sql_attr_uint',				'post_visibility'),  				array('sql_attr_bool',				'topic_first_post'),  				array('sql_attr_bool',				'deleted'),  				array('sql_attr_timestamp'	,		'post_time'), @@ -306,6 +308,7 @@ class phpbb_search_fulltext_sphinx  						p.forum_id,  						p.topic_id,  						p.poster_id, +						p.post_visibility,  						CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,  						p.post_time,  						p.post_subject, @@ -445,7 +448,7 @@ class phpbb_search_fulltext_sphinx  	* @param	string		$sort_dir			is either a or d representing ASC and DESC  	* @param	string		$sort_days			specifies the maximum amount of days a post may be old  	* @param	array		$ex_fid_ary			specifies an array of forum ids which should not be searched -	* @param	array		$m_approve_fid_ary	specifies an array of forum ids in which the searcher is allowed to view unapproved posts +	* @param	string		$post_visibility	specifies which types of posts the user can view in which forums  	* @param	int			$topic_id			is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched  	* @param	array		$author_ary			an array of author ids if the author should be ignored during the search the array is empty  	* @param	string		$author_name		specifies the author match, when ANONYMOUS is also a search-match @@ -454,7 +457,7 @@ class phpbb_search_fulltext_sphinx  	* @param	int			$per_page			number of ids each page is supposed to contain  	* @return	boolean|int						total number of results  	*/ -	public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) +	public function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page)  	{  		// No keywords? No posts.  		if (!strlen($this->search_query) && !sizeof($author_ary)) @@ -569,6 +572,11 @@ class phpbb_search_fulltext_sphinx  			$this->sphinx->SetFilter('poster_id', $author_ary);  		} +		// As this is not simply possible at the moment, we limit the result to approved posts. +		// This will make it impossible for moderators to search unapproved and softdeleted posts, +		// but at least it will also cause the same for normal users. +		$this->sphinx->SetFilter('post_visibility', array(ITEM_APPROVED)); +  		if (sizeof($ex_fid_ary))  		{  			// All forums that a user is allowed to access @@ -663,7 +671,7 @@ class phpbb_search_fulltext_sphinx  	* @param	string		$sort_dir			is either a or d representing ASC and DESC  	* @param	string		$sort_days			specifies the maximum amount of days a post may be old  	* @param	array		$ex_fid_ary			specifies an array of forum ids which should not be searched -	* @param	array		$m_approve_fid_ary	specifies an array of forum ids in which the searcher is allowed to view unapproved posts +	* @param	string		$post_visibility	specifies which types of posts the user can view in which forums  	* @param	int			$topic_id			is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched  	* @param	array		$author_ary			an array of author ids  	* @param	string		$author_name		specifies the author match, when ANONYMOUS is also a search-match @@ -672,14 +680,14 @@ class phpbb_search_fulltext_sphinx  	* @param	int			$per_page			number of ids each page is supposed to contain  	* @return	boolean|int						total number of results  	*/ -	public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page) +	public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)  	{  		$this->search_query = '';  		$this->sphinx->SetMatchMode(SPH_MATCH_FULLSCAN);  		$fields = ($firstpost_only) ? 'firstpost' : 'all';  		$terms = 'all'; -		return $this->keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, $id_ary, $start, $per_page); +		return $this->keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, $id_ary, $start, $per_page);  	}  	/** diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index 94fd59433b..7aa06464b7 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -778,7 +778,7 @@ class ucp_main  			$unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false;  			// Replies -			$replies = ($auth->acl_get('m_approve', $forum_id)) ? $row['topic_replies_real'] : $row['topic_replies']; +			$replies = phpbb_content_visibility::get_count('topic_posts', $row, $forum_id) - 1;  			if ($row['topic_status'] == ITEM_MOVED && !empty($row['topic_moved_id']))  			{  | 
