code/services/LDAPService.php
public function updateLDAPGroupsForMember(Member $member)
    {
        if (!$this->enabled()) {
            return;
        }
        if (!$member->GUID) {
            throw new ValidationException('Member missing GUID. Cannot update LDAP user');
        }

        $addGroups = [];
        $removeGroups = [];

        $user = $this->getUserByGUID($member->GUID);
        if (empty($user['objectguid'])) {
            throw new ValidationException('LDAP update failure: user missing GUID');
        }

        // If a user belongs to a single group, this comes through as a string.
        // Normalise to a array so it's consistent.
        $existingGroups = !empty($user['memberof']) ? $user['memberof'] : [];
        if ($existingGroups && is_string($existingGroups)) {
            $existingGroups = [$existingGroups];
        }

        foreach ($member->Groups() as $group) {
            if (!$group->GUID) {
                continue;
            }

            // mark this group as something we need to ensure the user belongs to in LDAP.
            $addGroups[] = $group->DN;
        }

        // Which existing LDAP groups are not in the add groups? We'll check these groups to
        // see if the user should be removed from any of them.
        $remainingGroups = array_diff($existingGroups, $addGroups);

        foreach ($remainingGroups as $groupDn) {
            // We only want to be removing groups we have a local Group mapped to. Removing
            // membership for anything else would be bad!
            $group = Group::get()->filter('DN', $groupDn)->first();
            if (!$group || !$group->exists()) {
                continue;
            }

            // this group should be removed from the user's memberof attribute, as it's been removed.
            $removeGroups[] = $groupDn;
        }

        // go through the groups we want the user to be in and ensure they're in them.
        foreach ($addGroups as $groupDn) {
            $this->addLDAPUserToGroup($user['distinguishedname'], $groupDn);
        }

        // go through the groups we _don't_ want the user to be in and ensure they're taken out of them.
        foreach ($removeGroups as $groupDn) {
            $members = $this->getLDAPGroupMembers($groupDn);

            // remove the user from the members data.
            if (in_array($user['distinguishedname'], $members)) {
                foreach ($members as $i => $dn) {
                    if ($dn == $user['distinguishedname']) {
                        unset($members[$i]);
                    }
                }
            }

            try {
                $this->update($groupDn, ['member' => $members]);
            } catch (\Exception $e) {
                throw new ValidationException('LDAP group membership remove failure: '.$e->getMessage());
            }
        }
    }
public function updateLDAPGroupsForMember(Member $member)
    {
        if (!$this->enabled()) {
            return;
        }
        if (!$member->GUID) {
            throw new ValidationException('Member missing GUID. Cannot update LDAP user');
        }

        $addGroups = [];
        $removeGroups = [];

        $user = $this->getUserByGUID($member->GUID);
        if (empty($user['objectguid'])) {
            throw new ValidationException('LDAP update failure: user missing GUID');
        }

        // If a user belongs to a single group, this comes through as a string.
        // Normalise to a array so it's consistent.
        $existingGroups = !empty($user['memberof']) ? $user['memberof'] : [];
        if ($existingGroups && is_string($existingGroups)) {
            $existingGroups = [$existingGroups];
        }

        foreach ($member->Groups() as $group) {
            if (!$group->GUID) {
                continue;
            }

            // mark this group as something we need to ensure the user belongs to in LDAP.
            $addGroups[] = $group->DN;
        }

        // Which existing LDAP groups are not in the add groups? We'll check these groups to
        // see if the user should be removed from any of them.
        $remainingGroups = array_diff($existingGroups, $addGroups);

        foreach ($remainingGroups as $groupDn) {
            // We only want to be removing groups we have a local Group mapped to. Removing
            // membership for anything else would be bad!
            $group = Group::get()->filter('DN', $groupDn)->first();
            if (!$group || !$group->exists()) {
                continue;
            }

            // this group should be removed from the user's memberof attribute, as it's been removed.
            $removeGroups[] = $groupDn;
        }

        // go through the groups we want the user to be in and ensure they're in them.
        foreach ($addGroups as $groupDn) {
            $this->addLDAPUserToGroup($user['distinguishedname'], $groupDn);
        }

        // go through the groups we _don't_ want the user to be in and ensure they're taken out of them.
        foreach ($removeGroups as $groupDn) {
            $members = $this->getLDAPGroupMembers($groupDn);

            // remove the user from the members data.
            if (in_array($user['distinguishedname'], $members)) {
                foreach ($members as $i => $dn) {
                    if ($dn == $user['distinguishedname']) {
                        unset($members[$i]);
                    }
                }
            }

            try {
                $this->update($groupDn, ['member' => $members]);
            } catch (\Exception $e) {
                throw new ValidationException('LDAP group membership remove failure: '.$e->getMessage());
            }
        }
    }
Ensure the user belongs to the correct groups in LDAP from their membership
to local LDAP mapped SilverStripe groups.

This also removes them from LDAP groups if they've been taken out of one.
It will not affect group membership of non-mapped groups, so it will
not touch such internal AD groups like "Domain Users".

@param Member $member