diff options
Diffstat (limited to 'phpBB/includes/functions_admin.php')
| -rw-r--r-- | phpBB/includes/functions_admin.php | 734 | 
1 files changed, 306 insertions, 428 deletions
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 722d3c9c67..1c7e68d358 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -1,9 +1,13 @@  <?php  /**  * -* @package acp -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -23,8 +27,6 @@ if (!defined('IN_PHPBB'))  * @param string	$table	constant or fullname of the table  * @param int	$parent_id parent_id of the current set (default = 0)  * @param array	$where	contains strings to compare closer on the where statement (additional) -* -* @author EXreaction  */  function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = array())  { @@ -63,7 +65,7 @@ function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = ar  */  function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $only_acl_post = false, $return_array = false)  { -	global $db, $user, $auth; +	global $db, $auth;  	// This query is identical to the jumpbox one  	$sql = 'SELECT forum_id, forum_name, parent_id, forum_type, forum_flags, forum_options, left_id, right_id @@ -169,7 +171,10 @@ function size_select_options($size_compare)  */  function group_select_options($group_id, $exclude_ids = false, $manage_founder = false)  { -	global $db, $user, $config; +	global $db, $config, $phpbb_container; + +	/** @var \phpbb\group\helper $group_helper */ +	$group_helper = $phpbb_container->get('group_helper');  	$exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE ' . $db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : '';  	$sql_and = (!$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name <> 'REGISTERED_COPPA'" : ''; @@ -187,7 +192,7 @@ function group_select_options($group_id, $exclude_ids = false, $manage_founder =  	while ($row = $db->sql_fetchrow($result))  	{  		$selected = ($row['group_id'] == $group_id) ? ' selected="selected"' : ''; -		$s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . $selected . '>' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; +		$s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . $selected . '>' . $group_helper->get_name($row['group_name']) . '</option>';  	}  	$db->sql_freeresult($result); @@ -311,12 +316,10 @@ function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $incl  * @param bool	$add_log			True if log entry should be added  *  * @return bool						False on error -* -* @author bantu  */  function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perms = true, $add_log = true)  { -	global $db; +	global $db, $user, $phpbb_log;  	// Only one forum id specified  	if (!is_array($dest_forum_ids)) @@ -439,7 +442,7 @@ function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perm  	if ($add_log)  	{ -		add_log('admin', 'LOG_FORUM_COPIED_PERMISSIONS', $src_forum_name, implode(', ', $dest_forum_names)); +		$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_COPIED_PERMISSIONS', false, array($src_forum_name, implode(', ', $dest_forum_names)));  	}  	$db->sql_transaction('commit'); @@ -500,7 +503,7 @@ function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png')  */  function move_topics($topic_ids, $forum_id, $auto_sync = true)  { -	global $db; +	global $db, $phpbb_dispatcher;  	if (empty($topic_ids))  	{ @@ -534,6 +537,27 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true)  	}  	$table_ary = array(TOPICS_TABLE, POSTS_TABLE, LOG_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); + +	/** +	 * Perform additional actions before topics move +	 * +	 * @event core.move_topics_before_query +	 * @var	array	table_ary	Array of tables from which forum_id will be updated for all rows that hold the moved topics +	 * @var	array	topic_ids	Array of the moved topic ids +	 * @var	string	forum_id	The forum id from where the topics are moved +	 * @var	array	forum_ids	Array of the forums where the topics are moving (includes also forum_id) +	 * @var bool	auto_sync	Whether or not to perform auto sync +	 * @since 3.1.5-RC1 +	 */ +	$vars = array( +			'table_ary', +			'topic_ids', +			'forum_id', +			'forum_ids', +			'auto_sync', +	); +	extract($phpbb_dispatcher->trigger_event('core.move_topics_before_query', compact($vars))); +  	foreach ($table_ary as $table)  	{  		$sql = "UPDATE $table @@ -555,7 +579,7 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true)  */  function move_posts($post_ids, $topic_id, $auto_sync = true)  { -	global $db; +	global $db, $phpbb_dispatcher;  	if (!is_array($post_ids))  	{ @@ -589,6 +613,28 @@ function move_posts($post_ids, $topic_id, $auto_sync = true)  		trigger_error('NO_TOPIC');  	} +	/** +	 * Perform additional actions before moving posts +	 * +	 * @event core.move_posts_before +	 * @var	array	post_ids	Array of post ids to move +	 * @var	string	topic_id	The topic id the posts are moved to +	 * @var bool	auto_sync	Whether or not to perform auto sync +	 * @var	array	forum_ids	Array of the forum ids the posts are moved from +	 * @var	array	topic_ids	Array of the topic ids the posts are moved from +	 * @var	array	forum_row	Array with the forum id of the topic the posts are moved to +	 * @since 3.1.7-RC1 +	 */ +	$vars = array( +			'post_ids', +			'topic_id', +			'auto_sync', +			'forum_ids', +			'topic_ids', +			'forum_row', +	); +	extract($phpbb_dispatcher->trigger_event('core.move_posts_before', compact($vars))); +  	$sql = 'UPDATE ' . POSTS_TABLE . '  		SET forum_id = ' . (int) $forum_row['forum_id'] . ", topic_id = $topic_id  		WHERE " . $db->sql_in_set('post_id', $post_ids); @@ -599,6 +645,28 @@ function move_posts($post_ids, $topic_id, $auto_sync = true)  		WHERE " . $db->sql_in_set('post_msg_id', $post_ids);  	$db->sql_query($sql); +	/** +	 * Perform additional actions after moving posts +	 * +	 * @event core.move_posts_after +	 * @var	array	post_ids	Array of the moved post ids +	 * @var	string	topic_id	The topic id the posts are moved to +	 * @var bool	auto_sync	Whether or not to perform auto sync +	 * @var	array	forum_ids	Array of the forum ids the posts are moved from +	 * @var	array	topic_ids	Array of the topic ids the posts are moved from +	 * @var	array	forum_row	Array with the forum id of the topic the posts are moved to +	 * @since 3.1.7-RC1 +	 */ +	$vars = array( +			'post_ids', +			'topic_id', +			'auto_sync', +			'forum_ids', +			'topic_ids', +			'forum_row', +	); +	extract($phpbb_dispatcher->trigger_event('core.move_posts_after', compact($vars))); +  	if ($auto_sync)  	{  		$forum_ids[] = (int) $forum_row['forum_id']; @@ -618,7 +686,7 @@ function move_posts($post_ids, $topic_id, $auto_sync = true)  */  function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_sync = true, $call_delete_posts = true)  { -	global $db, $config, $phpbb_container; +	global $db, $config, $phpbb_container, $phpbb_dispatcher;  	$approved_topics = 0;  	$forum_ids = $topic_ids = array(); @@ -672,6 +740,20 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s  	$table_ary = array(BOOKMARKS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, POLL_VOTES_TABLE, POLL_OPTIONS_TABLE, TOPICS_WATCH_TABLE, TOPICS_TABLE); +	/** +	 * Perform additional actions before topic(s) deletion +	 * +	 * @event core.delete_topics_before_query +	 * @var	array	table_ary	Array of tables from which all rows will be deleted that hold a topic_id occuring in topic_ids +	 * @var	array	topic_ids	Array of topic ids to delete +	 * @since 3.1.4-RC1 +	 */ +	$vars = array( +			'table_ary', +			'topic_ids', +	); +	extract($phpbb_dispatcher->trigger_event('core.delete_topics_before_query', compact($vars))); +  	foreach ($table_ary as $table)  	{  		$sql = "DELETE FROM $table @@ -680,6 +762,18 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s  	}  	unset($table_ary); +	/** +	 * Perform additional actions after topic(s) deletion +	 * +	 * @event core.delete_topics_after_query +	 * @var	array	topic_ids	Array of topic ids that were deleted +	 * @since 3.1.4-RC1 +	 */ +	$vars = array( +			'topic_ids', +	); +	extract($phpbb_dispatcher->trigger_event('core.delete_topics_after_query', compact($vars))); +  	$moved_topic_ids = array();  	// update the other forums @@ -712,15 +806,16 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s  	if ($approved_topics)  	{ -		set_config_count('num_topics', $approved_topics * (-1), true); +		$config->increment('num_topics', $approved_topics * (-1), false);  	} +	/* @var $phpbb_notifications \phpbb\notification\manager */  	$phpbb_notifications = $phpbb_container->get('notification_manager');  	$phpbb_notifications->delete_notifications(array( -		'topic', -		'approve_topic', -		'topic_in_queue', +		'notification.type.topic', +		'notification.type.approve_topic', +		'notification.type.topic_in_queue',  	), $topic_ids);  	return $return; @@ -731,7 +826,39 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s  */  function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true, $post_count_sync = true, $call_delete_topics = true)  { -	global $db, $config, $phpbb_root_path, $phpEx, $auth, $user, $phpbb_container; +	global $db, $config, $phpbb_root_path, $phpEx, $auth, $user, $phpbb_container, $phpbb_dispatcher; + +	// Notifications types to delete +	$delete_notifications_types = array( +		'notification.type.quote', +		'notification.type.approve_post', +		'notification.type.post_in_queue', +		'notification.type.report_post', +	); + +	/** +	* Perform additional actions before post(s) deletion +	* +	* @event core.delete_posts_before +	* @var	string	where_type					Variable containing posts deletion mode +	* @var	mixed	where_ids					Array or comma separated list of posts ids to delete +	* @var	bool	auto_sync					Flag indicating if topics/forums should be synchronized +	* @var	bool	posted_sync					Flag indicating if topics_posted table should be resynchronized +	* @var	bool	post_count_sync				Flag indicating if posts count should be resynchronized +	* @var	bool	call_delete_topics			Flag indicating if topics having no posts should be deleted +	* @var	array	delete_notifications_types	Array with notifications types to delete +	* @since 3.1.0-a4 +	*/ +	$vars = array( +		'where_type', +		'where_ids', +		'auto_sync', +		'posted_sync', +		'post_count_sync', +		'call_delete_topics', +		'delete_notifications_types', +	); +	extract($phpbb_dispatcher->trigger_event('core.delete_posts_before', compact($vars)));  	if ($where_type === 'range')  	{ @@ -808,6 +935,32 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =  	$table_ary = array(POSTS_TABLE, REPORTS_TABLE); +	/** +	* Perform additional actions during post(s) deletion before running the queries +	* +	* @event core.delete_posts_in_transaction_before +	* @var	array	post_ids					Array with deleted posts' ids +	* @var	array	poster_ids					Array with deleted posts' author ids +	* @var	array	topic_ids					Array with deleted posts' topic ids +	* @var	array	forum_ids					Array with deleted posts' forum ids +	* @var	string	where_type					Variable containing posts deletion mode +	* @var	mixed	where_ids					Array or comma separated list of post ids to delete +	* @var	array	delete_notifications_types	Array with notifications types to delete +	* @var	array	table_ary					Array with table names to delete data from +	* @since 3.1.7-RC1 +	*/ +	$vars = array( +		'post_ids', +		'poster_ids', +		'topic_ids', +		'forum_ids', +		'where_type', +		'where_ids', +		'delete_notifications_types', +		'table_ary', +	); +	extract($phpbb_dispatcher->trigger_event('core.delete_posts_in_transaction_before', compact($vars))); +  	foreach ($table_ary as $table)  	{  		$sql = "DELETE FROM $table @@ -863,7 +1016,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =  	}  	$error = false; -	$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); +	$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);  	if ($error)  	{ @@ -872,10 +1025,61 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =  	$search->index_remove($post_ids, $poster_ids, $forum_ids); -	delete_attachments('post', $post_ids, false); +	/** @var \phpbb\attachment\manager $attachment_manager */ +	$attachment_manager = $phpbb_container->get('attachment.manager'); +	$attachment_manager->delete('post', $post_ids, false); +	unset($attachment_manager); + +	/** +	* Perform additional actions during post(s) deletion +	* +	* @event core.delete_posts_in_transaction +	* @var	array	post_ids					Array with deleted posts' ids +	* @var	array	poster_ids					Array with deleted posts' author ids +	* @var	array	topic_ids					Array with deleted posts' topic ids +	* @var	array	forum_ids					Array with deleted posts' forum ids +	* @var	string	where_type					Variable containing posts deletion mode +	* @var	mixed	where_ids					Array or comma separated list of posts ids to delete +	* @var	array	delete_notifications_types	Array with notifications types to delete +	* @since 3.1.0-a4 +	*/ +	$vars = array( +		'post_ids', +		'poster_ids', +		'topic_ids', +		'forum_ids', +		'where_type', +		'where_ids', +		'delete_notifications_types', +	); +	extract($phpbb_dispatcher->trigger_event('core.delete_posts_in_transaction', compact($vars)));  	$db->sql_transaction('commit'); +	/** +	* Perform additional actions after post(s) deletion +	* +	* @event core.delete_posts_after +	* @var	array	post_ids					Array with deleted posts' ids +	* @var	array	poster_ids					Array with deleted posts' author ids +	* @var	array	topic_ids					Array with deleted posts' topic ids +	* @var	array	forum_ids					Array with deleted posts' forum ids +	* @var	string	where_type					Variable containing posts deletion mode +	* @var	mixed	where_ids					Array or comma separated list of posts ids to delete +	* @var	array	delete_notifications_types	Array with notifications types to delete +	* @since 3.1.0-a4 +	*/ +	$vars = array( +		'post_ids', +		'poster_ids', +		'topic_ids', +		'forum_ids', +		'where_type', +		'where_ids', +		'delete_notifications_types', +	); +	extract($phpbb_dispatcher->trigger_event('core.delete_posts_after', compact($vars))); +  	// Resync topics_posted table  	if ($posted_sync)  	{ @@ -891,7 +1095,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =  	if ($approved_posts && $post_count_sync)  	{ -		set_config_count('num_posts', $approved_posts * (-1), true); +		$config->increment('num_posts', $approved_posts * (-1), false);  	}  	// We actually remove topics now to not be inconsistent (the delete_topics function calls this function too) @@ -900,15 +1104,10 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =  		delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false);  	} +	/* @var $phpbb_notifications \phpbb\notification\manager */  	$phpbb_notifications = $phpbb_container->get('notification_manager'); -	$phpbb_notifications->delete_notifications(array( -		'quote', -		'bookmark', -		'post', -		'approve_post', -		'post_in_queue', -	), $post_ids); +	$phpbb_notifications->delete_notifications($delete_notifications_types, $post_ids);  	return sizeof($post_ids);  } @@ -916,225 +1115,21 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =  /**  * Delete Attachments  * +* @deprecated 3.2.0-a1 (To be removed: 3.4.0) +*  * @param string $mode can be: post|message|topic|attach|user  * @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids  * @param bool $resync set this to false if you are deleting posts or topics  */  function delete_attachments($mode, $ids, $resync = true)  { -	global $db, $config; - -	// 0 is as bad as an empty array -	if (empty($ids)) -	{ -		return false; -	} - -	if (is_array($ids)) -	{ -		$ids = array_unique($ids); -		$ids = array_map('intval', $ids); -	} -	else -	{ -		$ids = array((int) $ids); -	} - -	$sql_where = ''; - -	switch ($mode) -	{ -		case 'post': -		case 'message': -			$sql_id = 'post_msg_id'; -			$sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0); -		break; - -		case 'topic': -			$sql_id = 'topic_id'; -		break; - -		case 'user': -			$sql_id = 'poster_id'; -		break; - -		case 'attach': -		default: -			$sql_id = 'attach_id'; -			$mode = 'attach'; -		break; -	} - -	$post_ids = $message_ids = $topic_ids = $physical = array(); - -	// Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled) -	$sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan -			FROM ' . ATTACHMENTS_TABLE . ' -			WHERE ' . $db->sql_in_set($sql_id, $ids); - -	$sql .= $sql_where; - -	$result = $db->sql_query($sql); - -	while ($row = $db->sql_fetchrow($result)) -	{ -		// We only need to store post/message/topic ids if resync is enabled and the file is not orphaned -		if ($resync && !$row['is_orphan']) -		{ -			if (!$row['in_message']) -			{ -				$post_ids[] = $row['post_msg_id']; -				$topic_ids[] = $row['topic_id']; -			} -			else -			{ -				$message_ids[] = $row['post_msg_id']; -			} -		} +	global $phpbb_container; -		$physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']); -	} -	$db->sql_freeresult($result); +	/** @var \phpbb\attachment\manager $attachment_manager */ +	$attachment_manager = $phpbb_container->get('attachment.manager'); +	$num_deleted = $attachment_manager->delete($mode, $ids, $resync); -	// Delete attachments -	$sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' -		WHERE ' . $db->sql_in_set($sql_id, $ids); - -	$sql .= $sql_where; - -	$db->sql_query($sql); -	$num_deleted = $db->sql_affectedrows(); - -	if (!$num_deleted) -	{ -		return 0; -	} - -	// Delete attachments from filesystem -	$space_removed = $files_removed = 0; -	foreach ($physical as $file_ary) -	{ -		if (phpbb_unlink($file_ary['filename'], 'file', true) && !$file_ary['is_orphan']) -		{ -			// Only non-orphaned files count to the file size -			$space_removed += $file_ary['filesize']; -			$files_removed++; -		} - -		if ($file_ary['thumbnail']) -		{ -			phpbb_unlink($file_ary['filename'], 'thumbnail', true); -		} -	} - -	if ($space_removed || $files_removed) -	{ -		set_config_count('upload_dir_size', $space_removed * (-1), true); -		set_config_count('num_files', $files_removed * (-1), true); -	} - -	// If we do not resync, we do not need to adjust any message, post, topic or user entries -	if (!$resync) -	{ -		return $num_deleted; -	} - -	// No more use for the original ids -	unset($ids); - -	// Now, we need to resync posts, messages, topics. We go through every one of them -	$post_ids = array_unique($post_ids); -	$message_ids = array_unique($message_ids); -	$topic_ids = array_unique($topic_ids); - -	// Update post indicators for posts now no longer having attachments -	if (sizeof($post_ids)) -	{ -		// Just check which posts are still having an assigned attachment not orphaned by querying the attachments table -		$sql = 'SELECT post_msg_id -			FROM ' . ATTACHMENTS_TABLE . ' -			WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' -				AND in_message = 0 -				AND is_orphan = 0'; -		$result = $db->sql_query($sql); - -		$remaining_ids = array(); -		while ($row = $db->sql_fetchrow($result)) -		{ -			$remaining_ids[] = $row['post_msg_id']; -		} -		$db->sql_freeresult($result); - -		// Now only unset those ids remaining -		$post_ids = array_diff($post_ids, $remaining_ids); - -		if (sizeof($post_ids)) -		{ -			$sql = 'UPDATE ' . POSTS_TABLE . ' -				SET post_attachment = 0 -				WHERE ' . $db->sql_in_set('post_id', $post_ids); -			$db->sql_query($sql); -		} -	} - -	// Update message table if messages are affected -	if (sizeof($message_ids)) -	{ -		// Just check which messages are still having an assigned attachment not orphaned by querying the attachments table -		$sql = 'SELECT post_msg_id -			FROM ' . ATTACHMENTS_TABLE . ' -			WHERE ' . $db->sql_in_set('post_msg_id', $message_ids) . ' -				AND in_message = 1 -				AND is_orphan = 0'; -		$result = $db->sql_query($sql); - -		$remaining_ids = array(); -		while ($row = $db->sql_fetchrow($result)) -		{ -			$remaining_ids[] = $row['post_msg_id']; -		} -		$db->sql_freeresult($result); - -		// Now only unset those ids remaining -		$message_ids = array_diff($message_ids, $remaining_ids); - -		if (sizeof($message_ids)) -		{ -			$sql = 'UPDATE ' . PRIVMSGS_TABLE . ' -				SET message_attachment = 0 -				WHERE ' . $db->sql_in_set('msg_id', $message_ids); -			$db->sql_query($sql); -		} -	} - -	// Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic -	if (sizeof($topic_ids)) -	{ -		// Just check which topics are still having an assigned attachment not orphaned by querying the attachments table (much less entries expected) -		$sql = 'SELECT topic_id -			FROM ' . ATTACHMENTS_TABLE . ' -			WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' -				AND is_orphan = 0'; -		$result = $db->sql_query($sql); - -		$remaining_ids = array(); -		while ($row = $db->sql_fetchrow($result)) -		{ -			$remaining_ids[] = $row['topic_id']; -		} -		$db->sql_freeresult($result); - -		// Now only unset those ids remaining -		$topic_ids = array_diff($topic_ids, $remaining_ids); - -		if (sizeof($topic_ids)) -		{ -			$sql = 'UPDATE ' . TOPICS_TABLE . ' -				SET topic_attachment = 0 -				WHERE ' . $db->sql_in_set('topic_id', $topic_ids); -			$db->sql_query($sql); -		} -	} +	unset($attachment_manager);  	return $num_deleted;  } @@ -1147,8 +1142,6 @@ function delete_attachments($mode, $ids, $resync = true)  * @param bool		$auto_sync		Will call sync() if this is true  *  * @return array		Array with affected forums -* -* @author bantu  */  function delete_topic_shadows($forum_id, $sql_more = '', $auto_sync = true)  { @@ -1254,27 +1247,19 @@ function update_posted_info(&$topic_ids)  /**  * Delete attached file +* +* @deprecated 3.2.0-a1 (To be removed: 3.4.0)  */  function phpbb_unlink($filename, $mode = 'file', $entry_removed = false)  { -	global $db, $phpbb_root_path, $config; +	global $phpbb_container; -	// Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself. -	$sql = 'SELECT COUNT(attach_id) AS num_entries -		FROM ' . ATTACHMENTS_TABLE . " -		WHERE physical_filename = '" . $db->sql_escape(utf8_basename($filename)) . "'"; -	$result = $db->sql_query($sql); -	$num_entries = (int) $db->sql_fetchfield('num_entries'); -	$db->sql_freeresult($result); +	/** @var \phpbb\attachment\manager $attachment_manager */ +	$attachment_manager = $phpbb_container->get('attachment.manager'); +	$unlink = $attachment_manager->unlink($filename, $mode, $entry_removed); +	unset($attachment_manager); -	// Do not remove file if at least one additional entry with the same name exist. -	if (($entry_removed && $num_entries > 0) || (!$entry_removed && $num_entries > 1)) -	{ -		return false; -	} - -	$filename = ($mode == 'thumbnail') ? 'thumb_' . utf8_basename($filename) : utf8_basename($filename); -	return @unlink($phpbb_root_path . $config['upload_path'] . '/' . $filename); +	return $unlink;  }  /** @@ -1358,7 +1343,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  	{  		case 'topic_moved':  			$db->sql_transaction('begin'); -			switch ($db->sql_layer) +			switch ($db->get_sql_layer())  			{  				case 'mysql4':  				case 'mysqli': @@ -1438,7 +1423,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  				ITEM_DELETED	=> (!empty($topics_softdeleted)) ? ' WHERE ' . $db->sql_in_set('topic_id', $topics_softdeleted) : '',  			); -			foreach ($topic_visiblities as $visibility => $sql_where) +			foreach ($update_ary as $visibility => $sql_where)  			{  				if ($sql_where)  				{ @@ -1727,7 +1712,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  					{  						$forum_data[$forum_id]['topics_approved'] = $row['total_topics'];  					} -					else if ($row['topic_visibility'] == ITEM_UNAPPROVED) +					else if ($row['topic_visibility'] == ITEM_UNAPPROVED || $row['topic_visibility'] == ITEM_REAPPROVE)  					{  						$forum_data[$forum_id]['topics_unapproved'] = $row['total_topics'];  					} @@ -1950,7 +1935,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  					{  						$topic_data[$topic_id]['posts_approved'] = $row['total_posts'];  					} -					else if ($row['post_visibility'] == ITEM_UNAPPROVED) +					else if ($row['post_visibility'] == ITEM_UNAPPROVED || $row['post_visibility'] == ITEM_REAPPROVE)  					{  						$topic_data[$topic_id]['posts_unapproved'] = $row['total_posts'];  					} @@ -1972,7 +1957,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  						$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) +						if ($topic_data[$topic_id]['visibility'] == ITEM_UNAPPROVED || $topic_data[$topic_id]['visibility'] == ITEM_REAPPROVE)  						{  							// Soft delete status is stronger than unapproved.  							$topic_data[$topic_id]['visibility'] = $row['post_visibility']; @@ -2024,7 +2009,6 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  					AND u.user_id = p.poster_id';  			$result = $db->sql_query($sql); -			$post_ids = array();  			while ($row = $db->sql_fetchrow($result))  			{  				$topic_id = intval($row['topic_id']); @@ -2097,7 +2081,6 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  							AND u.user_id = p.poster_id';  					$result = $db->sql_query($sql); -					$post_ids = array();  					while ($row = $db->sql_fetchrow($result))  					{  						$topic_id = (int) $row['topic_id']; @@ -2240,7 +2223,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,  */  function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync = true)  { -	global $db; +	global $db, $phpbb_dispatcher;  	if (!is_array($forum_id))  	{ @@ -2275,6 +2258,26 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync  		$sql_and .= " AND topic_last_view_time < $prune_date";  	} +	if ($prune_mode == 'shadow') +	{ +		$sql_and .= ' AND topic_status = ' . ITEM_MOVED . " AND topic_last_post_time < $prune_date"; +	} + +	/** +	* Use this event to modify the SQL that selects topics to be pruned +	* +	* @event core.prune_sql +	* @var string	forum_id		The forum id +	* @var string	prune_mode		The prune mode +	* @var string	prune_date		The prune date +	* @var int		prune_flags		The prune flags +	* @var bool		auto_sync		Whether or not to perform auto sync +	* @var string	sql_and			SQL text appended to where clause +	* @since 3.1.3-RC1 +	*/ +	$vars = array('forum_id', 'prune_mode', 'prune_date', 'prune_flags', 'auto_sync', 'sql_and'); +	extract($phpbb_dispatcher->trigger_event('core.prune_sql', compact($vars))); +  	$sql = 'SELECT topic_id  		FROM ' . TOPICS_TABLE . '  		WHERE ' . $db->sql_in_set('forum_id', $forum_id) . " @@ -2316,7 +2319,7 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync  */  function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_freq)  { -	global $db; +	global $db, $user, $phpbb_log;  	$sql = 'SELECT forum_name  		FROM ' . FORUMS_TABLE . " @@ -2337,7 +2340,7 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr  			WHERE forum_id = $forum_id";  		$db->sql_query($sql); -		add_log('admin', 'LOG_AUTO_PRUNE', $row['forum_name']); +		$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_AUTO_PRUNE', false, array($row['forum_name']));  	}  	return; @@ -2348,7 +2351,7 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr  * via admin_permissions. Changes of usernames and group names  * must be carried through for the moderators table.  * -* @param \phpbb\db\driver\driver $db Database connection +* @param \phpbb\db\driver\driver_interface $db Database connection  * @param \phpbb\cache\driver\driver_interface Cache driver  * @param \phpbb\auth\auth $auth Authentication object  * @return null @@ -2359,10 +2362,10 @@ function phpbb_cache_moderators($db, $cache, $auth)  	$cache->destroy('sql', MODERATOR_CACHE_TABLE);  	// Clear table -	switch ($db->sql_layer) +	switch ($db->get_sql_layer())  	{  		case 'sqlite': -		case 'firebird': +		case 'sqlite3':  			$db->sql_query('DELETE FROM ' . MODERATOR_CACHE_TABLE);  		break; @@ -2372,7 +2375,7 @@ function phpbb_cache_moderators($db, $cache, $auth)  	}  	// We add moderators who have forum moderator permissions without an explicit ACL_NEVER setting -	$hold_ary = $ug_id_ary = $sql_ary = array(); +	$sql_ary = array();  	// Grab all users having moderative options...  	$hold_ary = $auth->acl_user_raw_data(false, 'm_%', false); @@ -2409,7 +2412,7 @@ function phpbb_cache_moderators($db, $cache, $auth)  				AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1)  				AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . "  				AND ug.user_pending = 0 -				AND o.auth_option " . $db->sql_like_expression('m_' . $db->any_char), +				AND o.auth_option " . $db->sql_like_expression('m_' . $db->get_any_char()),  		);  		$sql = $db->sql_build_query('SELECT', $sql_ary_deny);  		$result = $db->sql_query($sql); @@ -2436,6 +2439,7 @@ function phpbb_cache_moderators($db, $cache, $auth)  			{  				$usernames_ary[$row['user_id']] = $row['username'];  			} +			$db->sql_freeresult($result);  			foreach ($hold_ary as $user_id => $forum_id_ary)  			{ @@ -2525,20 +2529,6 @@ function phpbb_cache_moderators($db, $cache, $auth)  }  /** -* Cache moderators. Called whenever permissions are changed -* via admin_permissions. Changes of usernames and group names -* must be carried through for the moderators table. -* -* @deprecated 3.1 -* @return null -*/ -function cache_moderators() -{ -	global $db, $cache, $auth; -	return phpbb_cache_moderators($db, $cache, $auth); -} - -/**  * View log  *  * @param	string	$mode			The mode defines which log_type is used and from which log the entry is retrieved @@ -2571,7 +2561,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id  /**  * Removes moderators and administrators from foe lists.  * -* @param \phpbb\db\driver\driver $db Database connection +* @param \phpbb\db\driver\driver_interface $db Database connection  * @param \phpbb\auth\auth $auth Authentication object  * @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore  * @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore @@ -2629,11 +2619,11 @@ function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false)  			return;  		} -		switch ($db->sql_layer) +		switch ($db->get_sql_layer())  		{  			case 'mysqli':  			case 'mysql4': -				$sql = 'DELETE ' . (($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '4.1', '>=')) ? 'z.*' : ZEBRA_TABLE) . ' +				$sql = 'DELETE ' . (($db->get_sql_layer() === 'mysqli' || version_compare($db->sql_server_info(true), '4.1', '>=')) ? 'z.*' : ZEBRA_TABLE) . '  					FROM ' . ZEBRA_TABLE . ' z, ' . USER_GROUP_TABLE . ' ug  					WHERE z.zebra_id = ug.user_id  						AND z.foe = 1 @@ -2688,20 +2678,6 @@ function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false)  }  /** -* Removes moderators and administrators from foe lists. -* -* @deprecated 3.1 -* @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore -* @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore -* @return null -*/ -function update_foes($group_id = false, $user_id = false) -{ -	global $db, $auth; -	return phpbb_update_foes($db, $auth, $group_id, $user_id); -} - -/**  * Lists inactive users  */  function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_inactive_time DESC') @@ -2758,6 +2734,7 @@ function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $li  		$users[] = $row;  	} +	$db->sql_freeresult($result);  	return $offset;  } @@ -2800,7 +2777,7 @@ function get_database_size()  	$database_size = false;  	// This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0 -	switch ($db->sql_layer) +	switch ($db->get_sql_layer())  	{  		case 'mysql':  		case 'mysql4': @@ -2816,7 +2793,7 @@ function get_database_size()  				if (preg_match('#(3\.23|[45]\.)#', $version))  				{ -					$db_name = (preg_match('#^(?:3\.23\.(?:[6-9]|[1-9]{2}))|[45]\.#', $version)) ? "`{$db->dbname}`" : $db->dbname; +					$db_name = (preg_match('#^(?:3\.23\.(?:[6-9]|[1-9]{2}))|[45]\.#', $version)) ? "`{$db->get_db_name()}`" : $db->get_db_name();  					$sql = 'SHOW TABLE STATUS  						FROM ' . $db_name; @@ -2845,18 +2822,8 @@ function get_database_size()  			}  		break; -		case 'firebird': -			global $dbname; - -			// if it on the local machine, we can get lucky -			if (file_exists($dbname)) -			{ -				$database_size = filesize($dbname); -			} - -		break; -  		case 'sqlite': +		case 'sqlite3':  			global $dbhost;  			if (file_exists($dbhost)) @@ -2869,8 +2836,24 @@ function get_database_size()  		case 'mssql':  		case 'mssql_odbc':  		case 'mssqlnative': +			$sql = 'SELECT @@VERSION AS mssql_version'; +			$result = $db->sql_query($sql); +			$row = $db->sql_fetchrow($result); +			$db->sql_freeresult($result); +  			$sql = 'SELECT ((SUM(size) * 8.0) * 1024.0) as dbsize  				FROM sysfiles'; + +			if ($row) +			{ +				// Azure stats are stored elsewhere +				if (strpos($row['mssql_version'], 'SQL Azure') !== false) +				{ +					$sql = 'SELECT ((SUM(reserved_page_count) * 8.0) * 1024.0) as dbsize +					FROM sys.dm_db_partition_stats'; +				} +			} +  			$result = $db->sql_query($sql, 7200);  			$database_size = ($row = $db->sql_fetchrow($result)) ? $row['dbsize'] : false;  			$db->sql_freeresult($result); @@ -2886,7 +2869,7 @@ function get_database_size()  			if ($row['proname'] == 'pg_database_size')  			{ -				$database = $db->dbname; +				$database = $db->get_db_name();  				if (strpos($database, '.') !== false)  				{  					list($database, ) = explode('.', $database); @@ -2924,73 +2907,7 @@ function get_database_size()  	return $database_size;  } -/** -* Retrieve contents from remotely stored file -*/ -function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 6) -{ -	global $user; - -	if ($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout)) -	{ -		@fputs($fsock, "GET $directory/$filename HTTP/1.0\r\n"); -		@fputs($fsock, "HOST: $host\r\n"); -		@fputs($fsock, "Connection: close\r\n\r\n"); - -		$timer_stop = time() + $timeout; -		stream_set_timeout($fsock, $timeout); - -		$file_info = ''; -		$get_info = false; - -		while (!@feof($fsock)) -		{ -			if ($get_info) -			{ -				$file_info .= @fread($fsock, 1024); -			} -			else -			{ -				$line = @fgets($fsock, 1024); -				if ($line == "\r\n") -				{ -					$get_info = true; -				} -				else if (stripos($line, '404 not found') !== false) -				{ -					$errstr = $user->lang['FILE_NOT_FOUND'] . ': ' . $filename; -					return false; -				} -			} - -			$stream_meta_data = stream_get_meta_data($fsock); - -			if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop) -			{ -				$errstr = $user->lang['FSOCK_TIMEOUT']; -				return false; -			} -		} -		@fclose($fsock); -	} -	else -	{ -		if ($errstr) -		{ -			$errstr = utf8_convert_message($errstr); -			return false; -		} -		else -		{ -			$errstr = $user->lang['FSOCK_DISABLED']; -			return false; -		} -	} - -	return $file_info; -} - -/** +/*  * Tidy Warnings  * Remove all warnings which have now expired from the database  * The duration of a warning can be defined by the administrator @@ -3033,7 +2950,7 @@ function tidy_warnings()  		$db->sql_transaction('commit');  	} -	set_config('warnings_last_gc', time(), true); +	$config->set('warnings_last_gc', time(), false);  }  /** @@ -3041,7 +2958,7 @@ function tidy_warnings()  */  function tidy_database()  { -	global $db; +	global $config, $db;  	// Here we check permission consistency @@ -3066,7 +2983,7 @@ function tidy_database()  		WHERE ' . $db->sql_in_set('forum_id', $forum_ids, true);  	$db->sql_query($sql); -	set_config('database_last_gc', time(), true); +	$config->set('database_last_gc', time(), false);  }  /** @@ -3100,45 +3017,6 @@ function add_permission_language()  }  /** - * Obtains the latest version information - * - * @param bool $force_update Ignores cached data. Defaults to false. - * @param bool $warn_fail Trigger a warning if obtaining the latest version information fails. Defaults to false. - * @param int $ttl Cache version information for $ttl seconds. Defaults to 86400 (24 hours). - * - * @return string | false Version info on success, false on failure. - */ -function obtain_latest_version_info($force_update = false, $warn_fail = false, $ttl = 86400) -{ -	global $cache; - -	$info = $cache->get('versioncheck'); - -	if ($info === false || $force_update) -	{ -		$errstr = ''; -		$errno = 0; - -		$info = get_remote_file('version.phpbb.com', '/phpbb', -				((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno); - -		if (empty($info)) -		{ -			$cache->destroy('versioncheck'); -			if ($warn_fail) -			{ -				trigger_error($errstr, E_USER_WARNING); -			} -			return false; -		} - -		$cache->put('versioncheck', $info, $ttl); -	} - -	return $info; -} - -/**   * Enables a particular flag in a bitfield column of a given table.   *   * @param string	$table_name		The table to update  | 
