Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oleg/feature/prune users #504

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 25 additions & 2 deletions phpBB/adm/style/acp_prune_users.html
Expand Up @@ -9,7 +9,7 @@ <h1>{L_ACP_PRUNE_USERS}</h1>
<form id="acp_prune" method="post" action="{U_ACTION}"> <form id="acp_prune" method="post" action="{U_ACTION}">


<fieldset> <fieldset>
<legend>{L_ACP_PRUNE_USERS}</legend> <legend>{L_CRITERIA}</legend>
<dl> <dl>
<dt><label for="username">{L_USERNAME}:</label></dt> <dt><label for="username">{L_USERNAME}:</label></dt>
<dd><input type="text" id="username" name="username" /></dd> <dd><input type="text" id="username" name="username" /></dd>
Expand All @@ -18,9 +18,16 @@ <h1>{L_ACP_PRUNE_USERS}</h1>
<dt><label for="email">{L_EMAIL}:</label></dt> <dt><label for="email">{L_EMAIL}:</label></dt>
<dd><input type="text" id="email" name="email" /></dd> <dd><input type="text" id="email" name="email" /></dd>
</dl> </dl>
<dl>
<dt><label for="email">{L_WEBSITE}:</label></dt>
<dd><input type="text" id="website" name="website" /></dd>
</dl>
<dl> <dl>
<dt><label for="joined">{L_JOINED}:</label><br /><span>{L_JOINED_EXPLAIN}</span></dt> <dt><label for="joined">{L_JOINED}:</label><br /><span>{L_JOINED_EXPLAIN}</span></dt>
<dd><select name="joined_select">{S_JOINED_OPTIONS}</select> <input type="text" id="joined" name="joined" /></dd> <dd>
<strong>{L_AFTER}</strong> <input type="text" id="joined_after" name="joined_after" />
<br /> <br /> <strong>{L_BEFORE}</strong> <input type="text" id="joined_before" name="joined_before" />
</dd>
</dl> </dl>
<dl> <dl>
<dt><label for="active">{L_LAST_ACTIVE}:</label><br /><span>{L_LAST_ACTIVE_EXPLAIN}</span></dt> <dt><label for="active">{L_LAST_ACTIVE}:</label><br /><span>{L_LAST_ACTIVE_EXPLAIN}</span></dt>
Expand All @@ -30,11 +37,27 @@ <h1>{L_ACP_PRUNE_USERS}</h1>
<dt><label for="count">{L_POSTS}:</label></dt> <dt><label for="count">{L_POSTS}:</label></dt>
<dd><select name="count_select">{S_COUNT_OPTIONS}</select> <input type="text" id="count" name="count" /></dd> <dd><select name="count_select">{S_COUNT_OPTIONS}</select> <input type="text" id="count" name="count" /></dd>
</dl> </dl>
<dl>
<dt><label for="posts_on_queue">{L_POSTS_ON_QUEUE}:</label></dt>
<dd><select name="queue_select">{S_COUNT_OPTIONS}</select> <input type="text" id="posts_on_queue" name="posts_on_queue" /></select>
</dl>
<dl>
<dt><label for="group_id">{L_GROUP}:</label><br /><span>{L_PRUNE_USERS_GROUP_EXPLAIN}</dt>
<dd><select name="group_id">{S_GROUP_LIST}</select></dd>
</dl>
</fieldset>

<fieldset>
<legend>{L_USERNAMES}</legend>
<dl> <dl>
<dt><label for="users">{L_ACP_PRUNE_USERS}:</label><br /><span>{L_SELECT_USERS_EXPLAIN}</span></dt> <dt><label for="users">{L_ACP_PRUNE_USERS}:</label><br /><span>{L_SELECT_USERS_EXPLAIN}</span></dt>
<dd><textarea id="users" name="users" cols="40" rows="5"></textarea></dd> <dd><textarea id="users" name="users" cols="40" rows="5"></textarea></dd>
<dd>[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</dd> <dd>[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</dd>
</dl> </dl>
</fieldset>

<fieldset>
<legend>{L_OPTIONS}</legend>
<dl> <dl>
<dt><label for="deleteposts">{L_DELETE_USER_POSTS}:</label><br /><span>{L_DELETE_USER_POSTS_EXPLAIN}</span></dt> <dt><label for="deleteposts">{L_DELETE_USER_POSTS}:</label><br /><span>{L_DELETE_USER_POSTS_EXPLAIN}</span></dt>
<dd><label><input type="radio" class="radio" name="deleteposts" value="1" /> {L_YES}</label> <dd><label><input type="radio" class="radio" name="deleteposts" value="1" /> {L_YES}</label>
Expand Down
28 changes: 17 additions & 11 deletions phpBB/adm/style/confirm_body_prune.html
Expand Up @@ -2,6 +2,23 @@


<form id="confirm" method="post" action="{S_CONFIRM_ACTION}"> <form id="confirm" method="post" action="{S_CONFIRM_ACTION}">


<fieldset id="userlist">
<h2>{L_PRUNE_USERS_LIST}</h2>
<!-- IF S_DEACTIVATE --><p>{L_PRUNE_USERS_LIST_DEACTIVATE}</p><!-- ELSE --><p>{L_PRUNE_USERS_LIST_DELETE}</p><!-- ENDIF -->

<br />
<!-- BEGIN users -->
&raquo; <input type="checkbox" name="user_ids[]" value="{users.USER_ID}" checked="checked" />
<a href="{users.U_PROFILE}">{users.USERNAME}</a>
<!-- IF users.U_USER_ADMIN --> [<a href="{users.U_USER_ADMIN}">{L_USER_ADMIN}</a>]<!-- ENDIF --><br />
<!-- END users -->
<br />
<span class="small">
<a href="#" onclick="marklist('userlist', 'user_ids', true)">{L_MARK_ALL}</a> &bull;
<a href="#" onclick="marklist('userlist', 'user_ids', false)">{L_UNMARK_ALL}</a>
</span>
</fieldset>

<fieldset> <fieldset>
<h1>{MESSAGE_TITLE}</h1> <h1>{MESSAGE_TITLE}</h1>
<p>{MESSAGE_TEXT}</p> <p>{MESSAGE_TEXT}</p>
Expand All @@ -12,17 +29,6 @@ <h1>{MESSAGE_TITLE}</h1>
<input type="submit" name="confirm" value="{L_YES}" class="button2" />&nbsp; <input type="submit" name="confirm" value="{L_YES}" class="button2" />&nbsp;
<input type="submit" name="cancel" value="{L_NO}" class="button2" /> <input type="submit" name="cancel" value="{L_NO}" class="button2" />
</div> </div>

<h2>{L_PRUNE_USERS_LIST}</h2>
<!-- IF S_DEACTIVATE --><p>{L_PRUNE_USERS_LIST_DEACTIVATE}</p><!-- ELSE --><p>{L_PRUNE_USERS_LIST_DELETE}</p><!-- ENDIF -->

<br />
<!-- BEGIN users -->
&raquo; <a href="{users.U_PROFILE}">{users.USERNAME}</a><!-- IF users.U_USER_ADMIN --> [<a href="{users.U_USER_ADMIN}">{L_USER_ADMIN}</a>]<!-- ENDIF --><br />
<!-- END users -->

<br /><br />

</fieldset> </fieldset>


</form> </form>
Expand Down
5 changes: 1 addition & 4 deletions phpBB/includes/acp/acp_inactive.php
Expand Up @@ -157,10 +157,7 @@ function main($id, $mode)
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
} }


foreach ($mark as $user_id) user_delete('retain', $mark, true);
{
user_delete('retain', $user_id, $user_affected[$user_id]);
}


add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected)); add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected));
} }
Expand Down
142 changes: 111 additions & 31 deletions phpBB/includes/acp/acp_prune.php
Expand Up @@ -243,6 +243,7 @@ function prune_users($id, $mode)
if (confirm_box(true)) if (confirm_box(true))
{ {
$user_ids = $usernames = array(); $user_ids = $usernames = array();

$this->get_prune_users($user_ids, $usernames); $this->get_prune_users($user_ids, $usernames);


if (sizeof($user_ids)) if (sizeof($user_ids))
Expand All @@ -256,19 +257,13 @@ function prune_users($id, $mode)
{ {
if ($deleteposts) if ($deleteposts)
{ {
foreach ($user_ids as $user_id) user_delete('remove', $user_ids);
{
user_delete('remove', $user_id);
}


$l_log = 'LOG_PRUNE_USER_DEL_DEL'; $l_log = 'LOG_PRUNE_USER_DEL_DEL';
} }
else else
{ {
foreach ($user_ids as $user_id) user_delete('retain', $user_ids, true);
{
user_delete('retain', $user_id, $usernames[$user_id]);
}


$l_log = 'LOG_PRUNE_USER_DEL_ANON'; $l_log = 'LOG_PRUNE_USER_DEL_ANON';
} }
Expand Down Expand Up @@ -300,6 +295,7 @@ function prune_users($id, $mode)
{ {
$template->assign_block_vars('users', array( $template->assign_block_vars('users', array(
'USERNAME' => $usernames[$user_id], 'USERNAME' => $usernames[$user_id],
'USER_ID' => $user_id,
'U_PROFILE' => append_sid($phpbb_root_path . 'memberlist.' . $phpEx, 'mode=viewprofile&amp;u=' . $user_id), 'U_PROFILE' => append_sid($phpbb_root_path . 'memberlist.' . $phpEx, 'mode=viewprofile&amp;u=' . $user_id),
'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&amp;mode=overview&amp;u=' . $user_id, true, $user->session_id) : '', 'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&amp;mode=overview&amp;u=' . $user_id, true, $user->session_id) : '',
)); ));
Expand All @@ -315,8 +311,8 @@ function prune_users($id, $mode)
'mode' => $mode, 'mode' => $mode,
'prune' => 1, 'prune' => 1,


'users' => utf8_normalize_nfc(request_var('users', '', true)), 'users' => request_var('users', '', true),
'username' => utf8_normalize_nfc(request_var('username', '', true)), 'username' => request_var('username', '', true),
'email' => request_var('email', ''), 'email' => request_var('email', ''),
'joined_select' => request_var('joined_select', ''), 'joined_select' => request_var('joined_select', ''),
'joined' => request_var('joined', ''), 'joined' => request_var('joined', ''),
Expand All @@ -341,22 +337,27 @@ function prune_users($id, $mode)
} }


$find_time = array('lt' => $user->lang['BEFORE'], 'gt' => $user->lang['AFTER']); $find_time = array('lt' => $user->lang['BEFORE'], 'gt' => $user->lang['AFTER']);
$s_find_join_time = '';
foreach ($find_time as $key => $value)
{
$s_find_join_time .= '<option value="' . $key . '">' . $value . '</option>';
}

$s_find_active_time = ''; $s_find_active_time = '';
foreach ($find_time as $key => $value) foreach ($find_time as $key => $value)
{ {
$s_find_active_time .= '<option value="' . $key . '">' . $value . '</option>'; $s_find_active_time .= '<option value="' . $key . '">' . $value . '</option>';
} }


$s_group_list = '<option value="0" selected="selected">' . $user->lang['SELECT_OPTION'] . '</option>';
$sql = 'SELECT group_id, group_name FROM ' . GROUPS_TABLE . '
WHERE group_type <> ' . GROUP_SPECIAL . '
ORDER BY group_name ASC';
$result = $db->sql_query($sql);

while ($row = $db->sql_fetchrow($result))
{
$s_group_list .= '<option value="' . $row['group_id'] . '">' . $row['group_name'] . '</select>';
}

$template->assign_vars(array( $template->assign_vars(array(
'U_ACTION' => $this->u_action, 'U_ACTION' => $this->u_action,
'S_JOINED_OPTIONS' => $s_find_join_time,
'S_ACTIVE_OPTIONS' => $s_find_active_time, 'S_ACTIVE_OPTIONS' => $s_find_active_time,
'S_GROUP_LIST' => $s_group_list,
'S_COUNT_OPTIONS' => $s_find_count, 'S_COUNT_OPTIONS' => $s_find_count,
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=acp_prune&amp;field=users'), 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=acp_prune&amp;field=users'),
)); ));
Expand All @@ -369,42 +370,78 @@ function get_prune_users(&$user_ids, &$usernames)
{ {
global $user, $db; global $user, $db;


$users = utf8_normalize_nfc(request_var('users', '', true)); $users_by_name = request_var('users', '', true);

$users_by_id = request_var('user_ids', array(0));
if ($users)
if ($users_by_name)
{ {
$users = explode("\n", $users); $users = explode("\n", $users_by_name);
$where_sql = ' AND ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', $users)); $where_sql = ' AND ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', $users));
} }
else if (!empty($users_by_id))
{
$user_ids = $users_by_id;
user_get_id_name($user_ids, $usernames);

$where_sql = ' AND ' . $db->sql_in_set('user_id', $user_ids);
}
else else
{ {
$username = utf8_normalize_nfc(request_var('username', '', true)); $username = request_var('username', '', true);
$email = request_var('email', ''); $email = request_var('email', '');
$website = request_var('website', '');


$joined_select = request_var('joined_select', 'lt');
$active_select = request_var('active_select', 'lt'); $active_select = request_var('active_select', 'lt');
$count_select = request_var('count_select', 'eq'); $count_select = request_var('count_select', 'eq');
$joined = request_var('joined', ''); $queue_select = request_var('queue_select', 'gt');
$joined_before = request_var('joined_before', '');
$joined_after = request_var('joined_after', '');
$active = request_var('active', ''); $active = request_var('active', '');


$count = request_var('count', 0);
$posts_on_queue = request_var('posts_on_queue', 0);

$active = ($active) ? explode('-', $active) : array(); $active = ($active) ? explode('-', $active) : array();
$joined = ($joined) ? explode('-', $joined) : array(); $joined_before = ($joined_before) ? explode('-', $joined_before) : array();
$joined_after = ($joined_after) ? explode('-', $joined_after) : array();


if ((sizeof($active) && sizeof($active) != 3) || (sizeof($joined) && sizeof($joined) != 3)) // calculate the conditions required by the join time criteria
$joined_sql = '';
if (!empty($joined_before) && !empty($joined_after))
{ {
trigger_error($user->lang['WRONG_ACTIVE_JOINED_DATE'] . adm_back_link($this->u_action), E_USER_WARNING); // if the two entered dates are equal, we need to adjust
// so that our time range is a full day instead of 1 second
if ($joined_after == $joined_before)
{
$joined_after[2] += 1; //$joined_after[2]++;
}

$joined_sql = ' AND user_regdate BETWEEN ' . gmmktime(0, 0, 0, (int) $joined_after[1], (int) $joined_after[2], (int) $joined_after[0]) . ' AND ' . gmmktime(0, 0, 0, (int) $joined_before[1], (int) $joined_before[2], (int) $joined_before[0]);
} }
else if (empty($joined_before) && !empty($joined_after))
{
$joined_sql = ' AND user_regdate > ' . gmmktime(0, 0, 0, (int) $joined_after[1], (int) $joined_after[2], (int) $joined_after[0]);
}
else if (empty($joined_after) && !empty($joined_before))
{
$joined_sql = ' AND user_regdate < ' . gmmktime(0, 0, 0, (int) $joined_before[1], (int) $joined_before[2], (int) $joined_before[3]);
}
// implicit else when both arrays are empty do nothing


$count = request_var('count', ''); if ((sizeof($active) && sizeof($active) != 3) || (sizeof($joined_before) && sizeof($joined_before) != 3) || (sizeof($joined_after) && sizeof($joined_after) != 3))
{
trigger_error($user->lang['WRONG_ACTIVE_JOINED_DATE'] . adm_back_link($this->u_action), E_USER_WARNING);
}


$key_match = array('lt' => '<', 'gt' => '>', 'eq' => '='); $key_match = array('lt' => '<', 'gt' => '>', 'eq' => '=');
$sort_by_types = array('username', 'user_email', 'user_posts', 'user_regdate', 'user_lastvisit'); $sort_by_types = array('username', 'user_email', 'user_posts', 'user_regdate', 'user_lastvisit');


$where_sql = ''; $where_sql = '';
$where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->any_char, utf8_clean_string($username))) : ''; $where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->any_char, utf8_clean_string($username))) : '';
$where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->any_char, $email)) . ' ' : ''; $where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->any_char, $email)) . ' ' : '';
$where_sql .= (sizeof($joined)) ? " AND user_regdate " . $key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]) : ''; $where_sql .= ($website) ? ' AND user_website ' . $db->sql_like_expression(str_replace('*', $db->any_char, $website)) . ' ' : '';
$where_sql .= ($count !== '') ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : ''; $where_sql .= $joined_sql;
$where_sql .= ($count) ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : '';


// First handle pruning of users who never logged in, last active date is 0000-00-00 // First handle pruning of users who never logged in, last active date is 0000-00-00
if (sizeof($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0) if (sizeof($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0)
Expand Down Expand Up @@ -447,7 +484,6 @@ function get_prune_users(&$user_ids, &$usernames)
$where_sql"; $where_sql";
$result = $db->sql_query($sql); $result = $db->sql_query($sql);


$where_sql = '';
$user_ids = $usernames = array(); $user_ids = $usernames = array();


while ($row = $db->sql_fetchrow($result)) while ($row = $db->sql_fetchrow($result))
Expand All @@ -460,5 +496,49 @@ function get_prune_users(&$user_ids, &$usernames)
} }
} }
$db->sql_freeresult($result); $db->sql_freeresult($result);

if ($group_id)
{
$sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . '
WHERE group_id = ' . (int) $group_id . '
AND user_pending = 0
AND ' . $db->sql_in_set('user_id', $user_ids, false, true);
$result = $db->sql_query($sql);

// we're performing an intersection operation, so all the relevant users
// come from this most recent query (which was limited to the results of the
// previous query)
$user_ids = $usernames = array();
while ($row = $db->sql_fetchrow($result))
{
$user_ids[] = $row['poster_id'];
}

// only get usernames if they are needed (not part of some later query)
if (!$posts_on_queue)
{
// this is an additional query aginst the users table
user_get_id_name($user_ids, $usernames);
}
}

if ($posts_on_queue)
{
$sql = 'SELECT poster_id, COUNT(post_id) AS queue_posts FROM ' . POSTS_TABLE . '
WHERE ' . $db->sql_in_set('poster_id', $user_ids, false, true) .
' GROUP BY poster_id
HAVING queue_posts ' . $key_match[$queue_select] . ' ' . $posts_on_queue;
$result = $db->sql_query($result);

// same intersection logic as the above group ID portion
$user_ids = $usernames = array();
while ($row = $db->sql_fetchrow($result))
{
$user_ids[] = $row['poster_id'];
}

// do an additional query to get the correct set of usernames
user_get_id_name($user_ids, $usernames);
}
} }
} }