============================================================================================================================
Modification Name: Member Groups v3.0

Modification Author: GuldantheWarlock (GuldantheWarlock@xmbgarage.com)

Based on MemberGroups 2.0 by: EvilC (http://www.evilc.com/)

Description:
This modification adds Member Groups to your XMB forum.
Put a group name in a forum's user access list and anyone in the group will be allowed into the forum.
Users may apply to groups or can be added by admins.
Groups can have Group Admins who are regular users that are allowed to edit the user list and description for that group.

Supported Version: XMB 1.9.8 SP3

Updated for 1.9.8 by: WormHole @ XMB Garage

Notes: This modification is released under the GPL. A copy is provided with this software package.

Please backup your files before installing this modification.
Neither XMB Garage nor the author can be held responsible if your board stops functioning properly due to you installing this modification.
============================================================================================================================
=======
Step 1:
=======

Upload the file 'install.php' and 'membergroups.xmb' from the 'Contents' folder to your forum directory and
run install.php by directing your browser to it.

Example: http://www.domain.ext/forum/install.php

NOTE: MAKE SURE YOU DO THIS STEP BEFORE EDITING ANYTHING ELSE, OR YOU MAY RESULT IN ERRORS!

============================================================================================================================
=======
Step 2:
=======
====================
Edit lang/English.lang.php
====================
========================
Add To End Of File Above ?>
========================

// Member Groups Mod Begin
$lang['member_groups'] = 'Member Groups';
$lang['mg_adminlist'] = "Group Admins";
$lang['mg_alreadydenied'] = "You have already applied to join this group and have been denied.<br />Please contact an Administrator if you believe this is an error.";
$lang['mg_alreadyapplied'] = "You have already applied to join this group.<br />Your application is still being reviewed by a group Administrator.";
$lang['mg_alreadyingroup'] = 'You are already a member of this group. There is no need to apply again.';
$lang['mg_applications'] = "Application Status";
$lang['mg_apply'] = "Apply";
$lang['mg_applyapprovedl'] = " has approved your application for Group ";
$lang['mg_applyapproveds'] = "Application approved for Group ";
$lang['mg_applydeniedl'] = " has denied your application for Group ";
$lang['mg_applydenieds'] = "Application denied for Group ";
$lang['mg_approvalsupdated'] = "Approvals updated. Users have been notified via U2U of success / failure";
$lang['mg_approve'] = "Approve";
$lang['mg_approving'] = "Approving members for Group ";
$lang['mg_appliedtogroup'] = "Thank you! Your application will be reviewed by a group Administrator.";
$lang['mg_badurl'] = "Bad URL - Naughty user trying to manually make URL?";
$lang['mg_cancel'] = "Cancel";
$lang['mg_defer'] = "Defer";
$lang['mg_deny'] = "Deny";
$lang['mg_denylist'] = "Deny List";
$lang['mg_docs'] = "Member Groups Documentation";
$lang['mg_editing'] = "Editing Member Groups";
$lang['mg_email_address_for_user'] = "email address for user";
$lang['mg_email_success'] = 'You have successfully sent an email to users of this group. A copy of the email has been sent to your email address.';
$lang['mg_enableapply'] = "Allow users to apply to Group";
$lang['mg_er_grp_bad_char'] = "Bad character in group name. Characters allowed : a-z, A-Z, 0-9, Minus (-) and Underscore (_)";
$lang['mg_er_grp_exist'] = "Error : Group already exists !";
$lang['mg_er_grp_exist2'] = "Error : A username with the same name as this group already exists !";
$lang['mg_er_no_email'] = "Error : You must have a valid email address stored in your profile to send a group email.";
$lang['mg_groupclosed'] = "Sorry! This group is not accepting applications at the moment.";
$lang['mg_er_no_admin_no_email'] = 'Sorry! You must be a member of this group or an admin to send a group message.';
$lang['mg_grpdeleted'] = "Group Deleted.";
$lang['mg_grpdesc'] = "Group Description";
$lang['mg_grpname'] = "Group Name";
$lang['mg_grpupdated'] = "Group added / Updated successfully.";
$lang['mg_minposts'] = "Minimum number of posts before you can apply to a group.";
$lang['mg_msg_not_sent'] = "not found, message not sent.";
$lang['mg_newgrpname'] = "New Group name";
$lang['mg_no_group_admin'] = "Sorry! You are not an admin for any groups. And there are no groups accepting applications to join.";
$lang['mg_no_groups'] = "There are currently no groups. Type a new Group name in the box below and click Submit to create a new Group.";
$lang['mg_noguests'] = "Sorry! Guests are not allowed to view or use Member Groups. Please register or login if you would like to view Member Groups.";
$lang['mg_sent_to_user'] = "sent to Username";
$lang['mg_textgroups'] = "Groups";
$lang['mg_userlist'] = "Group's User list";
$lang['mg_noapprovals'] = "Sorry! There are no applications awaiting approval.";
$lang['mg_norights'] = "You do not have permission to edit this Group.";
$lang['mg_progress'] = "Progress";
$lang['mg_addgroup'] = 'Add Group';
$lang['mg_blankgroup'] = 'Please enter a group name or select a group for deletion!';
$lang['mg_deleteconfirm'] = 'Are you sure you want to delete the selected group(s)?';
$lang['mg_delete'] = 'Del?';
$lang['mg_send_message'] = 'Sending Group Message';
$lang['mg_use_html'] = 'Send message as HTML?';
$lang['mg_massmail_code'] = '$lang["mg_msgprefix"] = "$self[username] as sent the following message to all members of the group \"$group[groupname]\":\n\n";';
$lang['mg_no_applicants'] = 'There are currently no applications to approve.';
$lang['mg_not_enough_posts'] = 'Sorry! You do not have enough posts to join this group.';
$lang['mg_logs'] = 'Member Groups Logs';
$lang['mg_no_logs'] = 'There are no logs to display.';
$lang['mg_no_log_view'] = 'You must be a super administrator to view logs!';
$lang['mg_status_setting'] = 'Allow status to be used in groups/forum userlists?';
$lang['mg_u2u_success'] = 'U2U has successfully been sent to all group members.';
// Member Groups Mod End

============================================================================================================================
=======
Step 3:
=======
==============
Edit File: cp.php
==============
==========
Find Code:
==========

        $onlinetoday_statuson = $onlinetoday_statusoff = '';
        settingHTML('onlinetoday_status', $onlinetoday_statuson, $onlinetoday_statusoff);
        
===============
Add Code Below:
===============

        // Member Groups Mod Begin
        $mgStatusOn = $mgStatusOff = '';
        settingHTML('mg_status', $mgStatusOn, $mgStatusOff);
        // Member Groups Mod End
        
==========
Find Code:
==========

        printsetting1($lang['reportpoststatus'], 'reportpostnew', $reportposton, $reportpostoff);
       
===============
Add Code Below:
===============

        // Member Groups Mod Begin
        printsetting1($lang['mg_status_setting'], 'mgstatusnew', $mgStatusOn, $mgStatusOff);
        // Member Groups Mod End
        
==========
Find Code:
==========

        $onlinetoday_statusnew = formOnOff('onlinetoday_statusnew');
        
===============
Add Code Below:
===============

        // Member Groups Mod Begin
        $mgstatusnew = formOnOff('mgstatusnew');
        // Member Groups Mod End
        
==========
Find Code:
==========

        $db->query("UPDATE ".X_PREFIX."settings SET
        
================
Replace Code With:
================

        $db->query("UPDATE ".X_PREFIX."settings SET
            mg_status='$mgstatusnew',

==========
Find Code:
==========

                $db->query("DELETE FROM ".X_PREFIX."members WHERE uid='$delete'");
                
===============
Add Code Below:
===============

                // Member Groups Mod Begin
                $gquery = $db->query("SELECT mgid, adminlist, userlist, applylist, denylist FROM ".X_PREFIX."membergroups WHERE (userlist REGEXP '(^|(,))( )*$mem[username]( )*((,)|$)') OR (adminlist REGEXP '(^|(,))( )*$mem[username]( )*((,)|$)') OR (applylist REGEXP '(^|(,))( )*$mem[username]( )*((,)|$)') OR (denylist REGEXP '(^|(,))( )*$mem[username]( )*((,)|$)')");
                while($group = $db->fetch_array($gquery)) {
                    $group['userlist']  = array_unique(array_map('trim', explode(',', $group['userlist'])));
                    $group['adminlist'] = array_unique(array_map('trim', explode(',', $group['adminlist'])));
                    $group['applylist'] = array_unique(array_map('trim', explode(',', $group['applylist'])));
                    $group['denylist']  = array_unique(array_map('trim', explode(',', $group['denylist'])));
                    
                    if (($index = array_search($mem['username'], $group['userlist'])) !== false) {
                        unset($group['userlist'][$index]);
                    }
                    natcasesort($group['userlist']);
                    
                    if (($index = array_search($mem['username'], $group['adminlist'])) !== false) {
                        unset($group['adminlist'][$index]);
                    }
                    natcasesort($group['adminlist']);
                    
                    if (($index = array_search($mem['username'], $group['applylist'])) !== false) {
                        unset($group['applylist'][$index]);
                    }
                    natcasesort($group['applylist']);
                    
                    if (($index = array_search($mem['username'], $group['denylist'])) !== false) {
                        unset($group['denylist'][$index]);
                    }
                    natcasesort($group['denylist']);
                    
                    $group['userlist']  = implode(',', $group['userlist']);
                    $group['adminlist'] = implode(',', $group['adminlist']);
                    $group['applylist'] = implode(',', $group['applylist']);
                    $group['denylist']  = implode(',', $group['denylist']);
                    
                    $db->query("UPDATE ".X_PREFIX."membergroups SET userlist='$group[userlist]', adminlist='$group[adminlist]', applylist='$group[applylist]', denylist='$group[denylist]' WHERE mgid='$group[mgid]'");
                }
                $db->free_result($gquery);
                // Member Groups Mod End

============================================================================================================================
=======
Step 4:
=======
=================
Edit File: header.php
=================
==========
Find Code:
==========

    'members',
    
================
Replace Code With:
================

    'membergroups',
    'membergroups_logs',
    'members',

==========
Find Code:
==========

// 'Forum Rules'-link
if ($SETTINGS['bbrules'] == 'on') {
    $links[] = '<img src="'.$imgdir.'/top_bbrules.gif" alt="'.$lang['altrules'].'" border="0" /> <a href="faq.php?page=forumrules"><font class="navtd">'.$lang['textbbrules'].'</font></a>';
}
    
===============
Add Code Below:
===============

// Member Groups-link
    $links[] = '<img src="'.$THEME['imgdir'].'/top_membergroups.gif" alt="'.$lang['member_groups'].'" border="0" /> <a href="membergroups.php"><font class="navtd">'.$lang['member_groups'].'</font></a>';

============================================================================================================================
=======
Step 5:
=======
=======================
Edit File:  include/functions.php
=======================
==========
Find Code:
==========

function privfcheck($private, $userlist) {
    global $self, $xmbuser;

    if (X_SADMIN) {
        return true;
    }

    switch($private) {
        case 4:
            return false;
            break;
        case 3:
            return X_STAFF;
            break;
        case 2:
            return X_ADMIN;
            break;
        case 1:
            if (trim($userlist) == '') {
                return true;
            }

            $user = explode(',', $userlist);
            $xuser = strtolower($xmbuser);
            foreach($user as $usr) {
                $usr = strtolower(trim($usr));
                if ($usr != '' && $xuser == $usr) {
                   return true;
                }
            }
            return false;
            break;
        default:
            return false;
            break;
    }
    return false;
}

================
Replace Code With:
================

function privfcheck($private, $userlist) {
    global $self, $xmbuser, $db, $SETTINGS, $table_membergroups;
    static $groups;

    if ( X_SADMIN ) {
        return true;
    }

    switch($private) {
        case 4: // 4 - No Viewing
            return false;
            break;
        case 3: // 3 - Mods/Admins
            return X_STAFF;
            break;
        case 2: // 2 - Admins
            return X_ADMIN;
            break;
        case 1: // 1 - All users... minus guests.
            if (trim($userlist) == '') {
                return true;
            }

            $user = explode(',', $userlist);
            $xuser = strtolower($xmbuser);
            
            // Member Groups should only be loaded once, so we don't have to query on subsequent calls.
            if (empty($groups)) {
                $query  = $db->query("SELECT groupname, userlist FROM ".X_PREFIX."membergroups");
                while($group = $db->fetch_array($query)) {
	                $name = strtolower($group['groupname']);
                    $groups[$name] = (trim($group['userlist']) != '') ? $group['userlist'] : 'dummy-user';
                }
                $db->free_result($query);
                
                // If there are no groups, throw in a dummy entry to prevent querying in future calls.
                if (empty($groups)) {
                    $groups['dummy-group'] = 'dummy-user';
                }
            }

            foreach ($user as $usr) {
                $usr = strtolower(trim($usr));
                if ( $usr != '' && $xuser == $usr ) {
                   return true;
                }
                
                if ($SETTINGS['mg_status'] == 'on' && strtolower($self['status']) == $usr) {
                    return true;
                } else {
                    if (isset($groups[$usr])) {
                        $userlist = array_unique(array_map('strtolower', array_map('trim', explode(',', $groups[$usr]))));
                        foreach($userlist as $groupuser) {
                            if ($SETTINGS['mg_status'] == 'on' && strtolower($self['status']) == $groupuser) {
                                return true;
                            } else {
                                if ($xuser == $groupuser) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            
            return false;
            break;

        default:
            return false;
            break;
    }
    return false;
}

============================================================================================================================
=======
Step 6:
=======
========================
Edit File: include/admin.inc.php
========================
==========
Find Code:
==========

        global $db, $lang, $self;
        
===============
Add Code Below:
===============

        // Member Groups Mod Begin
        global $table_membergroups, $table_membergroups_logs;
        // Member Groups Mod End
        
==========
Find Code:
==========

        $db->query("UPDATE ".X_PREFIX."whosonline SET username='$userto' WHERE username='$userfrom'");
        
===============
Add Code Below:
===============

        // Member Groups Mod Begin
        $db->query("UPDATE ".X_PREFIX."membergroups_logs SET username='$userto' WHERE username='$userfrom'");
        //Member Groups Mod End

==========
Find Code:
==========

        $query = $db->query("SELECT fid, lastpost FROM ".X_PREFIX."forums WHERE lastpost LIKE '%$userfrom'");
        while($result = $db->fetch_array($query)) {
            list($posttime, $lastauthor, $lastpid) = explode("|", $result['lastpost']);
            if ($lastauthor == $userfrom) {
                $newlastpost = $posttime . '|' . $userto.'|'.$lastpid;
                $db->query("UPDATE ".X_PREFIX."forums SET lastpost='$newlastpost' WHERE fid='".$result['fid']."'");
            }
        }
        $db->free_result($query);
        
===============
Add Code Below:
===============

        // Member Groups Mod Begin
        $query = $db->query("SELECT mgid, adminlist, userlist, applylist, denylist FROM ".X_PREFIX."membergroups WHERE (userlist REGEXP '(^|(,))( )*$userfrom( )*((,)|$)') OR (adminlist REGEXP '(^|(,))( )*$userfrom( )*((,)|$)') OR (applylist REGEXP '(^|(,))( )*$userfrom( )*((,)|$)') OR (denylist REGEXP '(^|(,))( )*$userfrom( )*((,)|$)')");
        while($list = $db->fetch_array($query)) {
            $userlist = explode(',', $list['userlist']);
            $index    = array_search($userfrom, $userlist);
            $userlist[$index] = $userto;
            $userlist = implode(', ', $userlist);
            
            $adminlist = explode(',', $list['adminlist']);
            $index     = array_search($userfrom, $adminlist);
            $adminlist[$index] = $userto;
            $adminlist = implode(', ', $adminlist);
            
            $applylist = explode(',', $list['applylist']);
            $index     = array_search($userfrom, $applylist);
            $applylist[$index] = $userto;
            $applylist = implode(', ', $applylist);
            
            $denylist = explode(',', $list['denylist']);
            $index    = array_search($userfrom, $denylist);
            $denylist[$index] = $userto;
            $denylist = implode(', ', $denylist);
            
            $db->query("UPDATE ".X_PREFIX."membergroups SET userlist='$userlist', adminlist='$adminlist', applylist='$applylist', denylist='$denylist' WHERE mgid='$list[mgid]'");
        }
        $db->free_result($query);
        // Member Groups Mod End
        
==========
Find Code:
==========

    &raquo;&nbsp;<a href="cp2.php?action=modlog"><?php echo $lang['textmodlogs']?></a><br />
    &raquo;&nbsp;<a href="cp2.php?action=cplog"><?php echo $lang['textcplogs']?></a><br />
    &raquo;&nbsp;<a href="tools.php?action=logsdump"><?php echo $lang['textlogsdump']?></a><br />
    
================
Replace Code With:
================

    &raquo;&nbsp;<a href="tools.php?action=logsdump"><?php echo $lang['textlogsdump']?></a><br />
    &raquo;&nbsp;<a href="cp2.php?action=cplog"><?php echo $lang['textcplogs']?></a><br />
    <!-- Member Groups Mod Begin -->
    &raquo;&nbsp;<a href="membergroups.php?action=cplog"><?php echo $lang['mg_logs']?></a><br />
    <!-- Member Groups Mod End -->
    &raquo;&nbsp;<a href="cp2.php?action=modlog"><?php echo $lang['textmodlogs']?></a><br />

============================================================================================================================
=======
Step 7:
=======

Upload 'membergroups.php' from the 'Contents' folder to your forum directory.
Upload 'membergroups.inc.php' from the 'Contents' folder to your forum's 'include' directory.
Upload 'top_membergroups.gif' from the 'Contents' folder to your forum's theme directories.

Optionally, you may also upload the 'mgdocs' folder found in the 'Docs' folder to your forum
directory. This will automatically create a link to the documentation found in the membergroups
footer. This will allow both users and admins to access documentation on how all the features
of the Member Groups work.

============================================================================================================================
Enjoy!