Example #1
0
/**
 * Remove User
 *
 * @param string	$mode		Either 'retain' or 'remove'
 * @param mixed		$user_ids	Either an array of integers or an integer
 * @param bool		$retain_username
 * @return bool
 */
function user_delete($mode, $user_ids, $retain_username = true)
{
    global $cache, $config, $db, $user, $src_dispatcher, $src_container;
    global $src_root_path, $phpEx;
    $db->sql_transaction('begin');
    $user_rows = array();
    if (!is_array($user_ids)) {
        $user_ids = array($user_ids);
    }
    $user_id_sql = $db->sql_in_set('user_id', $user_ids);
    $sql = 'SELECT *
		FROM ' . USERS_TABLE . '
		WHERE ' . $user_id_sql;
    $result = $db->sql_query($sql);
    while ($row = $db->sql_fetchrow($result)) {
        $user_rows[(int) $row['user_id']] = $row;
    }
    $db->sql_freeresult($result);
    if (empty($user_rows)) {
        return false;
    }
    /**
     * Event before a user is deleted
     *
     * @event core.delete_user_before
     * @var	string	mode		Mode of deletion (retain/delete posts)
     * @var	array	user_ids	IDs of the deleted user
     * @var	mixed	retain_username	True if username should be retained
     *				or false if not
     * @since 3.1.0-a1
     */
    $vars = array('mode', 'user_ids', 'retain_username');
    extract($src_dispatcher->trigger_event('core.delete_user_before', compact($vars)));
    // Before we begin, we will remove the reports the user issued.
    $sql = 'SELECT r.post_id, p.topic_id
		FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p
		WHERE ' . $db->sql_in_set('r.user_id', $user_ids) . '
			AND p.post_id = r.post_id';
    $result = $db->sql_query($sql);
    $report_posts = $report_topics = array();
    while ($row = $db->sql_fetchrow($result)) {
        $report_posts[] = $row['post_id'];
        $report_topics[] = $row['topic_id'];
    }
    $db->sql_freeresult($result);
    if (sizeof($report_posts)) {
        $report_posts = array_unique($report_posts);
        $report_topics = array_unique($report_topics);
        // Get a list of topics that still contain reported posts
        $sql = 'SELECT DISTINCT topic_id
			FROM ' . POSTS_TABLE . '
			WHERE ' . $db->sql_in_set('topic_id', $report_topics) . '
				AND post_reported = 1
				AND ' . $db->sql_in_set('post_id', $report_posts, true);
        $result = $db->sql_query($sql);
        $keep_report_topics = array();
        while ($row = $db->sql_fetchrow($result)) {
            $keep_report_topics[] = $row['topic_id'];
        }
        $db->sql_freeresult($result);
        if (sizeof($keep_report_topics)) {
            $report_topics = array_diff($report_topics, $keep_report_topics);
        }
        unset($keep_report_topics);
        // Now set the flags back
        $sql = 'UPDATE ' . POSTS_TABLE . '
			SET post_reported = 0
			WHERE ' . $db->sql_in_set('post_id', $report_posts);
        $db->sql_query($sql);
        if (sizeof($report_topics)) {
            $sql = 'UPDATE ' . TOPICS_TABLE . '
				SET topic_reported = 0
				WHERE ' . $db->sql_in_set('topic_id', $report_topics);
            $db->sql_query($sql);
        }
    }
    // Remove reports
    $db->sql_query('DELETE FROM ' . REPORTS_TABLE . ' WHERE ' . $user_id_sql);
    $num_users_delta = 0;
    // Get auth provider collection in case accounts might need to be unlinked
    $provider_collection = $src_container->get('auth.provider_collection');
    // Some things need to be done in the loop (if the query changes based
    // on which user is currently being deleted)
    $added_guest_posts = 0;
    foreach ($user_rows as $user_id => $user_row) {
        if ($user_row['user_avatar'] && $user_row['user_avatar_type'] == 'avatar.driver.upload') {
            avatar_delete('user', $user_row);
        }
        // Unlink accounts
        foreach ($provider_collection as $provider_name => $auth_provider) {
            $provider_data = $auth_provider->get_auth_link_data($user_id);
            if ($provider_data !== null) {
                $link_data = array('user_id' => $user_id, 'link_method' => 'user_delete');
                // BLOCK_VARS might contain hidden fields necessary for unlinking accounts
                if (isset($provider_data['BLOCK_VARS']) && is_array($provider_data['BLOCK_VARS'])) {
                    foreach ($provider_data['BLOCK_VARS'] as $provider_service) {
                        if (!array_key_exists('HIDDEN_FIELDS', $provider_service)) {
                            $provider_service['HIDDEN_FIELDS'] = array();
                        }
                        $auth_provider->unlink_account(array_merge($link_data, $provider_service['HIDDEN_FIELDS']));
                    }
                } else {
                    $auth_provider->unlink_account($link_data);
                }
            }
        }
        // Decrement number of users if this user is active
        if ($user_row['user_type'] != USER_INACTIVE && $user_row['user_type'] != USER_IGNORE) {
            --$num_users_delta;
        }
        switch ($mode) {
            case 'retain':
                if ($retain_username === false) {
                    $post_username = $user->lang['GUEST'];
                } else {
                    $post_username = $user_row['username'];
                }
                // If the user is inactive and newly registered
                // we assume no posts from the user, and save
                // the queries
                if ($user_row['user_type'] != USER_INACTIVE || $user_row['user_inactive_reason'] != INACTIVE_REGISTER || $user_row['user_posts']) {
                    // When we delete these users and retain the posts, we must assign all the data to the guest user
                    $sql = 'UPDATE ' . FORUMS_TABLE . '
						SET forum_last_poster_id = ' . ANONYMOUS . ", forum_last_poster_name = '" . $db->sql_escape($post_username) . "', forum_last_poster_colour = ''\n\t\t\t\t\t\tWHERE forum_last_poster_id = {$user_id}";
                    $db->sql_query($sql);
                    $sql = 'UPDATE ' . POSTS_TABLE . '
						SET poster_id = ' . ANONYMOUS . ", post_username = '" . $db->sql_escape($post_username) . "'\n\t\t\t\t\t\tWHERE poster_id = {$user_id}";
                    $db->sql_query($sql);
                    $sql = 'UPDATE ' . TOPICS_TABLE . '
						SET topic_poster = ' . ANONYMOUS . ", topic_first_poster_name = '" . $db->sql_escape($post_username) . "', topic_first_poster_colour = ''\n\t\t\t\t\t\tWHERE topic_poster = {$user_id}";
                    $db->sql_query($sql);
                    $sql = 'UPDATE ' . TOPICS_TABLE . '
						SET topic_last_poster_id = ' . ANONYMOUS . ", topic_last_poster_name = '" . $db->sql_escape($post_username) . "', topic_last_poster_colour = ''\n\t\t\t\t\t\tWHERE topic_last_poster_id = {$user_id}";
                    $db->sql_query($sql);
                    // Since we change every post by this author, we need to count this amount towards the anonymous user
                    if ($user_row['user_posts']) {
                        $added_guest_posts += $user_row['user_posts'];
                    }
                }
                break;
            case 'remove':
                // there is nothing variant specific to deleting posts
                break;
        }
    }
    if ($num_users_delta != 0) {
        set_config_count('num_users', $num_users_delta, true);
    }
    // Now do the invariant tasks
    // all queries performed in one call of this function are in a single transaction
    // so this is kosher
    if ($mode == 'retain') {
        // Assign more data to the Anonymous user
        $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
			SET poster_id = ' . ANONYMOUS . '
			WHERE ' . $db->sql_in_set('poster_id', $user_ids);
        $db->sql_query($sql);
        $sql = 'UPDATE ' . USERS_TABLE . '
			SET user_posts = user_posts + ' . $added_guest_posts . '
			WHERE user_id = ' . ANONYMOUS;
        $db->sql_query($sql);
    } else {
        if ($mode == 'remove') {
            if (!function_exists('delete_posts')) {
                include $src_root_path . 'includes/functions_admin.' . $phpEx;
            }
            // Delete posts, attachments, etc.
            // delete_posts can handle any number of IDs in its second argument
            delete_posts('poster_id', $user_ids);
        }
    }
    $table_ary = array(USERS_TABLE, USER_GROUP_TABLE, TOPICS_WATCH_TABLE, FORUMS_WATCH_TABLE, ACL_USERS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, FORUMS_TRACK_TABLE, PROFILE_FIELDS_DATA_TABLE, MODERATOR_CACHE_TABLE, DRAFTS_TABLE, BOOKMARKS_TABLE, SESSIONS_KEYS_TABLE, PRIVMSGS_FOLDER_TABLE, PRIVMSGS_RULES_TABLE);
    // Delete the miscellaneous (non-post) data for the user
    foreach ($table_ary as $table) {
        $sql = "DELETE FROM {$table}\n\t\t\tWHERE " . $user_id_sql;
        $db->sql_query($sql);
    }
    $cache->destroy('sql', MODERATOR_CACHE_TABLE);
    // Change user_id to anonymous for posts edited by this user
    $sql = 'UPDATE ' . POSTS_TABLE . '
		SET post_edit_user = ' . ANONYMOUS . '
		WHERE ' . $db->sql_in_set('post_edit_user', $user_ids);
    $db->sql_query($sql);
    // Change user_id to anonymous for pms edited by this user
    $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
		SET message_edit_user = ' . ANONYMOUS . '
		WHERE ' . $db->sql_in_set('message_edit_user', $user_ids);
    $db->sql_query($sql);
    // Change user_id to anonymous for posts deleted by this user
    $sql = 'UPDATE ' . POSTS_TABLE . '
		SET post_delete_user = ' . ANONYMOUS . '
		WHERE ' . $db->sql_in_set('post_delete_user', $user_ids);
    $db->sql_query($sql);
    // Change user_id to anonymous for topics deleted by this user
    $sql = 'UPDATE ' . TOPICS_TABLE . '
		SET topic_delete_user = ' . ANONYMOUS . '
		WHERE ' . $db->sql_in_set('topic_delete_user', $user_ids);
    $db->sql_query($sql);
    // Delete user log entries about this user
    $sql = 'DELETE FROM ' . LOG_TABLE . '
		WHERE ' . $db->sql_in_set('reportee_id', $user_ids);
    $db->sql_query($sql);
    // Change user_id to anonymous for this users triggered events
    $sql = 'UPDATE ' . LOG_TABLE . '
		SET user_id = ' . ANONYMOUS . '
		WHERE ' . $user_id_sql;
    $db->sql_query($sql);
    // Delete the user_id from the zebra table
    $sql = 'DELETE FROM ' . ZEBRA_TABLE . '
		WHERE ' . $user_id_sql . '
			OR ' . $db->sql_in_set('zebra_id', $user_ids);
    $db->sql_query($sql);
    // Delete the user_id from the banlist
    $sql = 'DELETE FROM ' . BANLIST_TABLE . '
		WHERE ' . $db->sql_in_set('ban_userid', $user_ids);
    $db->sql_query($sql);
    // Delete the user_id from the session table
    $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
		WHERE ' . $db->sql_in_set('session_user_id', $user_ids);
    $db->sql_query($sql);
    // Clean the private messages tables from the user
    if (!function_exists('src_delete_user_pms')) {
        include $src_root_path . 'includes/functions_privmsgs.' . $phpEx;
    }
    src_delete_users_pms($user_ids);
    $src_notifications = $src_container->get('notification_manager');
    $src_notifications->delete_notifications('notification.type.admin_activate_user', $user_ids);
    $db->sql_transaction('commit');
    /**
     * Event after a user is deleted
     *
     * @event core.delete_user_after
     * @var	string	mode		Mode of deletion (retain/delete posts)
     * @var	array	user_ids	IDs of the deleted user
     * @var	mixed	retain_username	True if username should be retained
     *				or false if not
     * @since 3.1.0-a1
     */
    $vars = array('mode', 'user_ids', 'retain_username');
    extract($src_dispatcher->trigger_event('core.delete_user_after', compact($vars)));
    // Reset newest user info if appropriate
    if (in_array($config['newest_user_id'], $user_ids)) {
        update_last_username();
    }
    return false;
}
Example #2
0
/**
* Delete all PM(s) for a given user and delete the ones without references
*
* @param	int		$user_id	ID of the user whose private messages we want to delete
*
* @return	boolean		False if there were no pms found, true otherwise.
*/
function src_delete_user_pms($user_id)
{
    global $db, $user, $src_root_path, $phpEx;
    $user_id = (int) $user_id;
    if (!$user_id) {
        return false;
    }
    return src_delete_users_pms(array($user_id));
}