function fetchPresetPermitOptions($fields)
{
    $permits = array();
    // Add these permit options for actions that involve both a user_id and a group_id
    if (in_array('user_id', $fields) && in_array('group_id', $fields)) {
        // Create permit options for default groups (any user)
        $permits[] = array("name" => "any user and default groups.", "value" => "isDefaultGroup(group_id)");
        // Create permit options for each group (any user)
        $groups = fetchAllGroups();
        foreach ($groups as $group_id => $group) {
            $permits[] = array("name" => "any user and group '{$group['name']}'.", "value" => "isSameGroup(group_id,'{$group['id']}')");
        }
        $permits[] = array("name" => "any user with any group.", "value" => "always()");
        // Only add these permit options for actions that involve a user_id
    } else {
        if (in_array('user_id', $fields)) {
            // Create permit option for 'self'
            $permits[] = array("name" => "themselves only.", "value" => "isLoggedInUser(user_id)");
            // Create permits to perform actions on users in primary groups
            $groups = fetchAllGroups();
            foreach ($groups as $group_id => $group) {
                $permits[] = array("name" => "users whose primary group is '{$group['name']}'.", "value" => "isUserPrimaryGroup(user_id,'{$group['id']}')");
            }
            $permits[] = array("name" => "any user.", "value" => "always()");
            // Add these options for actions that involve a group_id
        } else {
            if (in_array('group_id', $fields)) {
                $groups = fetchAllGroups();
                // TODO: create permit option for the user's primary group only?
                // Create permit options for each group
                foreach ($groups as $group_id => $group) {
                    $permits[] = array("name" => "group '{$group['name']}'.", "value" => "isSameGroup(group_id,'{$group['id']}')");
                }
                $permits[] = array("name" => "any group.", "value" => "always()");
                // Default options
            } else {
                $permits[] = array("name" => "always.", "value" => "always()");
            }
        }
    }
    return $permits;
}
function fetchAllPermits($type)
{
    try {
        global $db_table_prefix;
        $result = array();
        // Build array of groups/users indexed by id
        if ($type == "user") {
            $users = fetchAllUsers();
            foreach ($users as $user) {
                $id = $user['user_id'];
                $result[$id] = array();
                $result[$id]['user_id'] = $id;
                $result[$id]['user_name'] = $user['user_name'];
                $result[$id]['action_permits'] = array();
            }
        } else {
            $groups = fetchAllGroups();
            foreach ($groups as $group) {
                $id = $group['id'];
                $result[$id]['group_id'] = $id;
                $result[$id]['name'] = $group['name'];
                $result[$id]['action_permits'] = array();
            }
        }
        $db = pdoConnect();
        if ($type == "user") {
            $query = "SELECT {$db_table_prefix}user_action_permits.*, user_name FROM  {$db_table_prefix}users, {$db_table_prefix}user_action_permits\n\t\t\tWHERE {$db_table_prefix}users.id = {$db_table_prefix}user_action_permits.user_id ORDER BY user_id, action";
        } else {
            if ($type == "group") {
                $query = "SELECT {$db_table_prefix}group_action_permits.*, name FROM  {$db_table_prefix}groups, {$db_table_prefix}group_action_permits\n\t\t\tWHERE {$db_table_prefix}groups.id = {$db_table_prefix}group_action_permits.group_id ORDER BY group_id, action";
            } else {
                return false;
            }
        }
        $stmt = $db->prepare($query);
        $stmt->execute();
        while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {
            if ($type == "user") {
                $id = $r['user_id'];
            } else {
                $id = $r['group_id'];
            }
            $action_permit_id = $r['id'];
            // Parse out permit string into array of permit functions and parameters
            $permits_arr = explode('&', $r['permits']);
            $permits_by_arg = array();
            foreach ($permits_arr as $permit) {
                $permit_with_params = array();
                preg_match('/(.*?)\\((.*?)\\)/', $permit, $permit_param_str);
                $permit_name = $permit_param_str[1];
                //$permit_with_params['name'] = $permit_name;
                // Extract and map parameters, if any
                if ($permit_param_str[2] and $permit_params = explode(',', $permit_param_str[2])) {
                    $permit_with_params = array();
                    foreach ($permit_params as $param) {
                        $permit_with_params[] = $param;
                    }
                }
                $permits_by_arg[$permit_name] = $permit_with_params;
            }
            $actions = array('action_id' => $action_permit_id, 'action' => $r['action'], 'permits' => $permits_by_arg);
            $result[$id]['action_permits'][$action_permit_id] = $actions;
        }
        // Convert users/groups to numerically indexed array
        $result = array_values($result);
        $stmt = null;
        foreach ($result as $id => $owner) {
            $action_names = array();
            foreach ($owner['action_permits'] as $action_id => $action) {
                $action_names[] = $action['action'];
            }
            //echo var_dump($action_names);
            //echo var_dump($group['action_permits']);
            array_multisort($action_names, SORT_ASC, $owner['action_permits']);
            // Convert action_permits to numerically indexed array
            $result[$id]['action_permits'] = array_values($result[$id]['action_permits']);
        }
        return $result;
    } catch (PDOException $e) {
        addAlert("danger", "Oops, looks like our database encountered an error.");
        error_log("Error in " . $e->getFile() . " on line " . $e->getLine() . ": " . $e->getMessage());
        return false;
    } catch (ErrorException $e) {
        addAlert("danger", "Oops, looks like our server might have goofed.  If you're an admin, please check the PHP error logs.");
        return false;
    }
}
/**
 * Loads all group information.
 * @return array $results contains group information id, name, is_default, can_delete
 */
function loadGroups()
{
    // This block automatically checks this action against the permissions database before running.
    if (!checkActionPermissionSelf(__FUNCTION__, func_get_args())) {
        addAlert("danger", "Sorry, you do not have permission to access this resource.");
        return false;
    }
    // Calls appropriate function in db_functions
    return fetchAllGroups();
}