MyBB Community Forums

Full Version: Tutorial - Exclude an usergroup from being pruned in user pruning.
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
So I think that this won't be implemented in 1.6.x series and 1.8 final version would take too much time for something important like this.

The current user pruning options/settings has very limited options which doesn't allow us to exclude certain usergroups from being pruned, for example if you have a premium/paid usergroup on your forum and you selected a criteria to prune users with 0 posts, then, if anyone from the premium group has made no posts (i.e. zero posts), then, unfortunately, he will be pruned too. Refer to this thread of mine for more info or if you have any doubts.

So, to avoid all these, we are going to make a CORE edit to the pruning task file. The user pruning task file is located in:

./inc/tasks/userpruning.php

Open it and find a line something like this:

if($usergroup['canmodcp'] == 1 || $usergroup['cancp'] == 1 || $usergroup['issupermod'] == 1 || $usergroup['isbannedgroup'] == 1)

Now, replace above line of code with:

if($usergroup['canmodcp'] == 1 || $usergroup['cancp'] == 1 || $usergroup['issupermod'] == 1 || $usergroup['isbannedgroup'] == 1 || in_array($usergroup['gid'],array('8')))

In above new code, by default, I have added one usergroup, namely usergroup #8 from being pruned/deleted. You can disallow pruning of users of multiple usergroup in the below fashion, for example:

if($usergroup['canmodcp'] == 1 || $usergroup['cancp'] == 1 || $usergroup['issupermod'] == 1 || $usergroup['isbannedgroup'] == 1 || in_array($usergroup['gid'],array('8','10','11')))

So the above code will save users of usergroup #8, 10 and 11, for example, from being pruned.

This can be used until we have an official new feature for this.

Note, this is tested on localhost by me for multiple times and it worked as it should. This tutorial is provided 'as is' without any guarantees. Backup your database before trying anything.

Thank you.
this only works on primary usergroup. It does not help with additional usergroups. So if you want to prune registered users with no posts, but have someone in as special additional group that you want to keep, then they will still get pruned.
A quick glance to the task file tells me that it doesn't even considers additionalgroups for deleting users. For example, if you want to delete users from usergroup "9" and exclude users from group "4", it wouldn't delete user X if X has usergroup "7" as primary group and gid "9" as an additional group.

You will need more that those edits to make it work unfortunately.

Right, what about you changing:
	// Are we pruning by posts?
	if($mybb->settings['enableprunebyposts'] == 1)
	{
		$in_usergroups = array();
		$users = array();
		
		$usergroups = $cache->read("usergroups");
		foreach($usergroups as $gid => $usergroup)
		{
			// Exclude admin, moderators, super moderators, banned
			if($usergroup['canmodcp'] == 1 || $usergroup['cancp'] == 1 || $usergroup['issupermod'] == 1 || $usergroup['isbannedgroup'] == 1)
			{
				continue;
			}
			$in_usergroups[] = $gid;
		}
		
		// If we're not pruning unactivated users, then remove them from the criteria
		if($mybb->settings['pruneunactived'] == 0)
		{
			$key = array_search('5', $in_usergroups);
			unset($in_usergroups[$key]);
		}
		
		$regdate = TIME_NOW-(intval($mybb->settings['dayspruneregistered'])*24*60*60);
		$query = $db->simple_select("users", "uid", "regdate <= ".intval($regdate)." AND postnum <= ".intval($mybb->settings['prunepostcount'])." AND usergroup IN(".$db->escape_string(implode(',', $in_usergroups)).")");
		while($user = $db->fetch_array($query))
		{
			$users[$user['uid']] = $user['uid'];
		}
	}

With this:
	define('GROUPS_TO_DELETE', '2,5,7');
	define('GROUPS_TO_IGNORE', '3,4,6');

	switch($db->type)
	{
		case 'pgsql':
		case 'sqlite3':
		case 'sqlite2':
			$sql = "','||additionalgroups||','";
			break;
		default:
			$sql = "CONCAT(',',additionalgroups,',')";
			break;
	}
	
	// Are we pruning by posts?
	if($mybb->settings['enableprunebyposts'] == 1)
	{
		$in_usergroups = array();
		$users = array();
		
		$usergroups = $cache->read("usergroups");
		foreach($usergroups as $gid => $usergroup)
		{
			// Exclude admin, moderators, super moderators, banned
			if($usergroup['canmodcp'] == 1 || $usergroup['cancp'] == 1 || $usergroup['issupermod'] == 1 || $usergroup['isbannedgroup'] == 1 || !in_array($gid, explode(',', GROUPS_TO_DELETE)) || in_array($gid, explode(',', GROUPS_TO_IGNORE))
			{
				continue;
			}
			$in_usergroups[] = $gid;
		}
		
		// If we're not pruning unactivated users, then remove them from the criteria
		if($mybb->settings['pruneunactived'] == 0)
		{
			$key = array_search('5', $in_usergroups);
			unset($in_usergroups[$key]);
		}
		$regdate = TIME_NOW-(intval($mybb->settings['dayspruneregistered'])*24*60*60);
		$where = "regdate<='{$regdate}'";
		if(($postcount = intval($mybb->settings['prunepostcount'])) > 0)
		{
			$where .= " AND postnum<='{$postcount}'";
		}
		$where .= " AND (usergroup IN({$db->escape_string(implode(',', $in_usergroups))})";
		$groups = explode(',', GROUPS_TO_DELETE);
		foreach((array)$groups as $group)
		{
			$where .= " OR {$sql} LIKE '%,{$group},%'";
		}
		$where .= ")";
		$ignore = explode(',', GROUPS_TO_IGNORE);
		foreach((array)$ignore as $igroup)
		{
			$where .= " AND {$sql} NOT LIKE '%,{$igroup},%'";
		}
		$query = $db->simple_select("users", "uid, usergroup, additionalgroups", $where);
		while($user = $db->fetch_array($query))
		{
			$users[$user['uid']] = $user['uid'];
		}
	}

The user pruning system really needs some improving, I would like to see a hook there too as right now I can't see a way to know when a user is deleted unless I create my own task to do the check.
Yep, the one I provided is only for primary groups. I've had and have no time currently, I'll take one more quick look on providing edits for additional groups, as well. And yeah, the pruning system needs vast improvement.