Change User Group Via PHP

I don't think the XenForo Class Proxy works properly when you're loading classes from outside XenForo. I had an issue similar to this when working on something a couple weeks ago. Perhaps @Chris D can chime in on this?

The specific issue I had was with DataWriter classes extending XenForo_DataWriter_User not running when I called XenForo_DataWriter_User from outside of XenForo while using Kotomi.
 
I can't speak on behalf of how the Kotomi bridge works, but generally there should be no problem with XF accessing extended classes.

This is pretty much all you need to instantiate XF and have access to pretty much everything (at the code level, at least):
PHP:
<?php

$startTime = microtime(true);
$fileDir = dirname(__FILE__);

require($fileDir . '/library/XenForo/Autoloader.php');
XenForo_Autoloader::getInstance()->setupAutoloader($fileDir . '/library');

XenForo_Application::initialize($fileDir . '/library', $fileDir);
XenForo_Application::set('page_start_time', $startTime);

$dependencies = new XenForo_Dependencies_Public();
$dependencies->preLoadData();

$visitor = XenForo_Visitor::getInstance();
$user_id = $visitor->getUserId();

$userModel = XenForo_Model::create('XenForo_Model_User');
$userModel->removeUserGroupChange($user_id, 'RANDOM_STRING');
$userModel->addUserGroupChange($user_id, 'RANDOM_STRING', 10);
That should be all you need.
 
I can't speak on behalf of how the Kotomi bridge works, but generally there should be no problem with XF accessing extended classes.

This is pretty much all you need to instantiate XF and have access to pretty much everything (at the code level, at least):
PHP:
<?php

$startTime = microtime(true);
$fileDir = dirname(__FILE__);

require($fileDir . '/library/XenForo/Autoloader.php');
XenForo_Autoloader::getInstance()->setupAutoloader($fileDir . '/library');

XenForo_Application::initialize($fileDir . '/library', $fileDir);
XenForo_Application::set('page_start_time', $startTime);

$dependencies = new XenForo_Dependencies_Public();
$dependencies->preLoadData();

$visitor = XenForo_Visitor::getInstance();
$user_id = $visitor->getUserId();

$userModel = XenForo_Model::create('XenForo_Model_User');
$userModel->removeUserGroupChange($user_id, 'RANDOM_STRING');
$userModel->addUserGroupChange($user_id, 'RANDOM_STRING', 10);
That should be all you need.

Now that I think of it-- I wasn't using Kotomi. I was using the following code:
PHP:
$fileDir = $forumPath;
$startTime = microtime(true);

require($fileDir . '/library/XenForo/Autoloader.php');
XenForo_Autoloader::getInstance()->setupAutoloader($fileDir . '/library');

XenForo_Application::initialize($fileDir . '/library', $fileDir);

XenForo_Session::startPublicSession();

and when I created a DataWriter using XenForo_DataWriter::create('XenForo_DataWriter_User') it did not load any of the classes that extend XenForo_DataWriter_User, so even if I put a die; in _preSave() or _getFields() that never happened, it continued to try to save the user, but missing any custom fields added by add-ons.

I'll try to get more details on this issue when I have some time, but it seems like the XF Class Proxy doesn't actually do anything when it's called from outside of XenForo, which seemed odd.

Jake
 
Is it possible to change the secondary_group_ids with one mysql command like (this works fine in vbulletion for secondary_group; but work not in xenforo):

UPDATE xf_user SET secondary_group_ids= secondary_group_ids+ 23 WHERE NOT (secondary_group_ids & 23);

?
 
I don't know how it has to be done back in 2012, when Chris offered the solution above. But in most recent versions of XenForo the programatic addition (or removal) of a user group to a user account is very easy (assuming we are in a controller):

Code:
$userModel = XenForo_Model::create('XenForo_Model_User');
$userModel->addUserGroupChange($userId, 'any_id_you_like', $groupId);
$userModel->removeUserGroupChange($userId, 'any_id_you_like');

Regarding your comments @Dan Allen :
It won't get better. Modern software is object orientated and follows the MVC model and data writers. It makes it in fact easier to expand the code and the create large applications with a very small bug rate (like XenForo).

External login and registration is also very easy to implement in an add-on. Thanks to MVC and data writers. you should get comfortable with it.
@HWS, Would it be reasonable to adapt what you have provided to use on a bulk update user group assignments? I've been advised there are warranty and support implications, basically, if it gets messed up it cannot be supported by XF and it is strongly discouraged by XF.

I also am wondering if you can comment on an observation I have seen posted and seen myself, which is an apparent lack of working examples that can make understanding the technology easier. In other words, since it is simple and easy to implement external login, where are the several examples available for download and if they are not available that way, why not? It seems common enough to be able to find working examples of all kinds of code, XF modifications not packaged as addons being an exception.
 
Sorry to bump an old thread, but I found a different way to do this, but I noticed one issue, it won't set them to that group again if you remove them from it manually. I believe you have to do removeUserGroupChange with the same key. I'm not sure if this is a better way to do it or not, anyone know?

I don't know how it has to be done back in 2012, when Chris offered the solution above. But in most recent versions of XenForo the programatic addition (or removal) of a user group to a user account is very easy (assuming we are in a controller):

Code:
$userModel = XenForo_Model::create('XenForo_Model_User');
$userModel->addUserGroupChange($userId, 'any_id_you_like', $groupId);
$userModel->removeUserGroupChange($userId, 'any_id_you_like');

The benefit of the user group change system is it does allow changes to be reverted easily. Good use case example is when you create a Moderator or Administrator and specify some additional user groups to place those users into. A user group change is logged with a change key of, e.g. 'moderator', so if that moderator is ever demoted, any user group changes you added will automatically be reverted.

It still is true that using the solution recommended above creates a problem. The problem is that if an administrator uses the ACP to remove someone from a group where they have been added with this method, the user cannot then be re-added to the group, using solution noted above. The fix would be for the ACP to remove the user_group_change record when removing someone from a group. I think that is an oversight in the ACP.

Why aren't user_group_change records created when user_groups are added via the ACP?
 
Last edited:
It still is true that using the solution recommended above creates a problem. The problem is that if an administrator uses the ACP to remove someone from a group where they have been added with this method, the user cannot then be re-added to the group, using solution noted above. The fix would be for the ACP to remove the user_group_change record when removing someone from a group. I think that is an oversight in the ACP.

Why aren't user_group_change records created when user_groups are added via the ACP?

The same problem. How to fix it?

Is my solution correct? removeUserGroupChangeLogByUserId - custom method. Now it's working fine.

Code:
$userModel = XenForo_Model::create('XenForo_Model_User');
    $userModel->removeUserGroupChangeLogByUserId($user_id);
    $userModel->removeUserGroupChange($user_id, '3');
    $userModel->addUserGroupChange($user_id, '4', $usergroup_ids);
 
Last edited:
Top Bottom