瀏覽代碼

+ added post recount function to members maintenance [4423]

Spuds 13 年之前
父節點
當前提交
f02d980afc

+ 9 - 7
Sources/Errors.php

@@ -129,13 +129,15 @@ function fatal_error($error, $log = 'general')
 }
 
 /**
- * A fatal error with a message stored in the language file.
- * This function stops executing and displays an error message by key.
- * It uses the string with the error_message_key key.
- * It logs the error in the forum's default language while displaying the error
- * message in the user's language.
- * @uses Errors language file and applies the $sprintf information if specified.
- * the information is logged if log is specified.
+ * Shows a fatal error with a message stored in the language file.
+ *
+ * This function stops execution and displays an error message by key.
+ *  - uses the string with the error_message_key key.
+ *  - logs the error in the forum's default language while displaying the error
+ *    message in the user's language.
+ *  - uses Errors language file and applies the $sprintf information if specified.
+ *  - the information is logged if log is specified.
+ *
  * @param $error
  * @param $log
  * @param $sprintf

+ 199 - 4
Sources/ManageMaintenance.php

@@ -72,6 +72,7 @@ function ManageMaintenance()
 			'activities' => array(
 				'reattribute' => 'MaintainReattributePosts',
 				'purgeinactive' => 'MaintainPurgeInactiveMembers',
+				'recountposts' => 'MaintainRecountPosts',
 			),
 		),
 		'topics' => array(
@@ -176,6 +177,9 @@ function MaintainMembers()
 		);
 	}
 	$smcFunc['db_free_result']($result);
+	
+	if (isset($_GET['done']) && $_GET['done'] == 'recountposts')
+		$context['maintenance_finished'] = $txt['maintain_recountposts'];
 }
 
 /**
@@ -960,6 +964,7 @@ function OptimizeTables()
  * Recount many forum totals that can be recounted automatically without harm.
  * it requires the admin_forum permission.
  * It shows the maintain_forum admin area.
+ *
  * Totals recounted:
  * - fixes for topics with wrong num_replies.
  * - updates for num_posts and num_topics of all boards.
@@ -977,13 +982,17 @@ function AdminBoardRecount()
 	global $time_start, $smcFunc;
 
 	isAllowedTo('admin_forum');
-
 	checkSession('request');
-	validateToken('admin-maint');
+	
+	// validate the request or the loop
+	if (!isset($_REQUEST['step']))
+		validateToken('admin-maint');
+	else
+		validateToken('admin-boardrecount');
 
 	$context['page_title'] = $txt['not_done_title'];
 	$context['continue_post_data'] = '';
-	$context['continue_countdown'] = '3';
+	$context['continue_countdown'] = 3;
 	$context['sub_template'] = 'not_done';
 
 	// Try for as much time as possible.
@@ -1072,6 +1081,9 @@ function AdminBoardRecount()
 
 			if (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $time_start)) > 3)
 			{
+				createToken('admin-boardrecount');
+				$context['continue_post_data'] = '<input type="hidden" name="' . $context['admin-boardrecount_token_var'] . '" value="' . $context['admin-boardrecount_token'] . '" />';
+
 				$context['continue_get_data'] = '?action=admin;area=maintain;sa=routine;activity=recount;step=0;start=' . $_REQUEST['start'] . ';' . $context['session_var'] . '=' . $context['session_id'];
 				$context['continue_percent'] = round((100 * $_REQUEST['start'] / $max_topics) / $total_steps);
 
@@ -1127,6 +1139,9 @@ function AdminBoardRecount()
 
 			if (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $time_start)) > 3)
 			{
+				createToken('admin-boardrecount');
+				$context['continue_post_data'] = '<input type="hidden" name="' . $context['admin-boardrecount_token_var'] . '" value="' . $context['admin-boardrecount_token'] . '" />';
+
 				$context['continue_get_data'] = '?action=admin;area=maintain;sa=routine;activity=recount;step=1;start=' . $_REQUEST['start'] . ';' . $context['session_var'] . '=' . $context['session_id'];
 				$context['continue_percent'] = round((200 + 100 * $_REQUEST['start'] / $max_topics) / $total_steps);
 
@@ -1180,6 +1195,9 @@ function AdminBoardRecount()
 
 			if (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $time_start)) > 3)
 			{
+				createToken('admin-boardrecount');
+				$context['continue_post_data'] = '<input type="hidden" name="' . $context['admin-boardrecount_token_var'] . '" value="' . $context['admin-boardrecount_token'] . '" />';
+
 				$context['continue_get_data'] = '?action=admin;area=maintain;sa=routine;activity=recount;step=2;start=' . $_REQUEST['start'] . ';' . $context['session_var'] . '=' . $context['session_id'];
 				$context['continue_percent'] = round((300 + 100 * $_REQUEST['start'] / $max_topics) / $total_steps);
 
@@ -1233,6 +1251,9 @@ function AdminBoardRecount()
 
 			if (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $time_start)) > 3)
 			{
+				createToken('admin-boardrecount');
+				$context['continue_post_data'] = '<input type="hidden" name="' . $context['admin-boardrecount_token_var'] . '" value="' . $context['admin-boardrecount_token'] . '" />';
+
 				$context['continue_get_data'] = '?action=admin;area=maintain;sa=routine;activity=recount;step=3;start=' . $_REQUEST['start'] . ';' . $context['session_var'] . '=' . $context['session_id'];
 				$context['continue_percent'] = round((400 + 100 * $_REQUEST['start'] / $max_topics) / $total_steps);
 
@@ -1286,6 +1307,9 @@ function AdminBoardRecount()
 
 			if (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $time_start)) > 3)
 			{
+				createToken('admin-boardrecount');
+				$context['continue_post_data'] = '<input type="hidden" name="' . $context['admin-boardrecount_token_var'] . '" value="' . $context['admin-boardrecount_token'] . '" />';
+
 				$context['continue_get_data'] = '?action=admin;area=maintain;sa=routine;activity=recount;step=4;start=' . $_REQUEST['start'] . ';' . $context['session_var'] . '=' . $context['session_id'];
 				$context['continue_percent'] = round((500 + 100 * $_REQUEST['start'] / $max_topics) / $total_steps);
 
@@ -1332,6 +1356,9 @@ function AdminBoardRecount()
 
 		if (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $time_start)) > 3)
 		{
+			createToken('admin-boardrecount');
+			$context['continue_post_data'] = '<input type="hidden" name="' . $context['admin-boardrecount_token_var'] . '" value="' . $context['admin-boardrecount_token'] . '" />';
+
 			$context['continue_get_data'] = '?action=admin;area=maintain;sa=routine;activity=recount;step=6;start=0;' . $context['session_var'] . '=' . $context['session_id'];
 			$context['continue_percent'] = round(700 / $total_steps);
 
@@ -1375,6 +1402,9 @@ function AdminBoardRecount()
 
 			if (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $time_start)) > 3)
 			{
+				createToken('admin-boardrecount');
+				$context['continue_post_data'] = '<input type="hidden" name="' . $context['admin-boardrecount_token_var'] . '" value="' . $context['admin-boardrecount_token'] . '" />';
+
 				$context['continue_get_data'] = '?action=admin;area=maintain;sa=routine;activity=recount;step=6;start=' . $_REQUEST['start'] . ';' . $context['session_var'] . '=' . $context['session_id'];
 				$context['continue_percent'] = round((700 + 100 * $_REQUEST['start'] / $modSettings['maxMsgID']) / $total_steps);
 
@@ -1660,7 +1690,7 @@ function MaintainMassMoveTopics()
 
 	// Set up to the context.
 	$context['page_title'] = $txt['not_done_title'];
-	$context['continue_countdown'] = '3';
+	$context['continue_countdown'] = 3;
 	$context['continue_post_data'] = '';
 	$context['continue_get_data'] = '';
 	$context['sub_template'] = 'not_done';
@@ -1751,4 +1781,169 @@ function MaintainMassMoveTopics()
 	redirectexit('action=admin;area=maintain;sa=topics;done=massmove');
 }
 
+/**
+ * Recalculate all members post counts
+ * it requires the admin_forum permission.
+ * 
+ * - recounts all posts for members found in the message table
+ * - updates the members post count record in the members talbe
+ * - honors the boards post count flag
+ * - does not count posts in the recyle bin
+ * - zeros post counts for all members with no posts in the message table
+ * - runs as a delayed loop to avoid server overload
+ * - uses the not_done template in Admin.template
+ *
+ * The function redirects back to action=admin;area=maintain;sa=members when complete.
+ * It is accessed via ?action=admin;area=maintain;sa=members;activity=recountposts
+ */
+function MaintainRecountPosts()
+{
+	global $txt, $context, $modSettings, $smcFunc;
+
+	// You have to be allowed in here
+	isAllowedTo('admin_forum');
+	checkSession('request');
+
+	// Set up to the context.
+	$context['page_title'] = $txt['not_done_title'];
+	$context['continue_countdown'] = 3;
+	$context['continue_get_data'] = '';
+	$context['sub_template'] = 'not_done';
+	
+	// init
+	$increment = 200;
+	$_REQUEST['start'] = !isset($_REQUEST['start']) ? 0 : (int) $_REQUEST['start'];
+
+	// Ask for some extra time, on big boards this may take a bit
+	@set_time_limit(600);
+
+	// Only run this query if we don't have the total number of members that have posted
+	if (!isset($_SESSION['total_members']))
+	{
+		validateToken('admin-maint');
+		
+		$request = $smcFunc['db_query']('', '
+			SELECT COUNT(DISTINCT m.id_member)
+			FROM ({db_prefix}messages AS m, {db_prefix}boards AS b)
+			WHERE m.id_member != 0
+				AND b.count_posts = 0
+				AND m.id_board = b.id_board',
+			array(
+			)
+		);
+
+		// save it so we don't do this again for this task
+		list ($_SESSION['total_members']) = $smcFunc['db_fetch_row']($request);
+		$smcFunc['db_free_result']($request);
+	}
+	else
+		validateToken('admin-recountposts');
+
+	// Lets get a group of members and determine their post count (from the boards that have post count enabled of course).
+	$request = $smcFunc['db_query']('', '
+		SELECT /*!40001 SQL_NO_CACHE */ m.id_member, COUNT(m.id_member) AS posts
+		FROM ({db_prefix}messages AS m, {db_prefix}boards AS b)
+		WHERE m.id_member != {int:zero}
+			AND b.count_posts = {int:zero}
+			AND m.id_board = b.id_board ' . (!empty($modSettings['recycle_enable']) ? '
+			AND b.id_board != {int:recycle}' : '') . '
+		GROUP BY m.id_member
+		LIMIT {int:start}, {int:number}',
+		array(
+			'start' => $_REQUEST['start'],
+			'number' => $increment,
+			'recycle' => $modSettings['recycle_board'],
+			'zero' => 0,
+		)
+	);
+	$total_rows = $smcFunc['db_num_rows']($request);
+
+	// Update the post count for this group
+	while ($row = $smcFunc['db_fetch_assoc']($request))
+	{
+		$smcFunc['db_query']('', '
+			UPDATE {db_prefix}members
+			SET posts = {int:posts}
+			WHERE id_member = {int:row}',
+			array(
+				'row' => $row['id_member'],
+				'posts' => $row['posts'],
+			)
+		);
+	}
+	$smcFunc['db_free_result']($request);
+
+	// Continue?
+	if ($total_rows == $increment)
+	{
+		$_REQUEST['start'] += $increment;
+		$context['continue_get_data'] = '?action=admin;area=maintain;sa=members;activity=recountposts;start=' . $_REQUEST['start'] . ';' . $context['session_var'] . '=' . $context['session_id'];
+		$context['continue_percent'] = round(100 * $_REQUEST['start'] / $_SESSION['total_members']);
+		
+		createToken('admin-recountposts');
+		$context['continue_post_data'] = '<input type="hidden" name="' . $context['admin-recountposts_token_var'] . '" value="' . $context['admin-recountposts_token'] . '" />';
+
+		if (function_exists('apache_reset_timeout'))
+			apache_reset_timeout();
+		return;
+	}
+	
+	// final steps ... made more difficult since we don't yet support sub-selects on joins
+	// place all members who have posts in the message table in a temp table
+	$createTemporary = $smcFunc['db_query']('', '
+		CREATE TEMPORARY TABLE {db_prefix}tmp_maint_recountposts (
+			id_member mediumint(8) unsigned NOT NULL default {string:string_zero},
+			PRIMARY KEY (id_member)
+		)
+		SELECT m.id_member 
+		FROM ({db_prefix}messages AS m,{db_prefix}boards AS b)
+		WHERE m.id_member != {int:zero}
+			AND b.count_posts = {int:zero}
+			AND m.id_board = b.id_board ' . (!empty($modSettings['recycle_enable']) ? '
+			AND b.id_board != {int:recycle}' : '') . '
+		GROUP BY m.id_member',
+		array(
+			'zero' => 0,
+			'string_zero' => '0',
+			'db_error_skip' => true,
+		)
+	) !== false;
+
+	if ($createTemporary) 
+	{
+		// outer join the members table on the temporary table finding the members that have a post count but no posts in the message table
+		$request = $smcFunc['db_query']('', '
+			SELECT mem.id_member, mem.posts
+			FROM {db_prefix}members AS mem
+			LEFT OUTER JOIN {db_prefix}tmp_maint_recountposts AS res
+			ON res.id_member = mem.id_member
+			WHERE res.id_member IS null 
+				AND mem.posts != {int:zero}',
+			array(
+				'zero' => 0,
+			)
+		);
+
+		// set the post count to zero for any delinquents we may have found
+		while ($row = $smcFunc['db_fetch_assoc']($request))
+		{
+			$smcFunc['db_query']('', '
+				UPDATE {db_prefix}members
+				SET posts = {int:zero}
+				WHERE id_member = {int:row}',
+				array(
+					'row' => $row['id_member'],
+					'zero' => 0,
+				)
+			);
+		}
+		$smcFunc['db_free_result']($request);
+	}
+	
+	// all done
+	unset($_SESSION['total_members']);
+	$context['maintenance_finished'] = $txt['maintain_recountposts'];
+	redirectexit('action=admin;area=maintain;sa=members;done=recountposts');
+}
+
 ?>

+ 15 - 0
Themes/default/ManageMaintenance.template.php

@@ -350,6 +350,21 @@ function template_maintain_members()
 			</div>
 			<span class="botslice"><span></span></span>
 		</div>
+		<div class="cat_bar">
+			<h3 class="catbg">', $txt['maintain_recountposts'], '</h3>
+		</div>
+		<div class="windowbg">
+			<span class="topslice"><span></span></span>
+			<div class="content">
+				<form action="', $scripturl, '?action=admin;area=maintain;sa=members;activity=recountposts" method="post" accept-charset="', $context['character_set'], '" id="membersForm">
+					<p>', $txt['maintain_recountposts_info'], '</p>
+					<span><input type="submit" value="', $txt['maintain_run_now'], '" class="button_submit" /></span>
+					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
+					<input type="hidden" name="', $context['admin-maint_token_var'], '" value="', $context['admin-maint_token'], '" />
+				</form>
+			</div>
+			<span class="botslice"><span></span></span>
+		</div>		
 	</div>
 	<br class="clear" />
 

+ 3 - 0
Themes/default/languages/ManageMaintenance.english.php

@@ -211,4 +211,7 @@ $txt['reattribute_confirm_username'] = 'a username';
 $txt['reattribute_confirm_email'] = 'an email address';
 $txt['reattribute_cannot_find_member'] = 'Could not find member to attribute posts to.';
 
+$txt['maintain_recountposts'] = 'Recount User Posts';
+$txt['maintain_recountposts_info'] = 'Run this maintenance task to update your users total post count.  It will recount all (countable) posts made by each user and then update their profile post count totals';
+
 ?>