Change User Group Using PHP

Dan Allen

Active member
CONTEXT
Our site has subsystems besides Xenforo. When people signup for our site, they signup using our proprietary security system that controls access to all the subsystems, including Xenforo. That system adds people to XenForo, using an outdated addon called XenForoSDK. It does not add people to different user groups. It just adds them and people are put into a default group using group promotions.

We need to be able to add people to various forum user groups when they signup for our site. The group assignments vary by which products they buy. Access to our forums is part of what they are paying for. Currently, we have a person login to the Xenforo Admin Control Panel, search for the new users based on data printed out by our security system, then check the little boxes to put them into a forum user group. It's impractical.

REQUIREMENT
The requirement is to have a program that runs as part of our proprietary site signup that puts people into the right forum groups based on what they have bought.

To test a process for automating this task, I created a file called addUserScottyJakes_to_Group_38.php. The file is in the xenforo directory with the same ownership and permissions as index.php and admin.php. This is 100% of the file's contents:

Code:
<?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();
$name = 'Scotty Jakes';
$userModel = XenForo_Model::create('XenForo_Model_User');
$user = $userModel->getUserByName($name);
$user_id=$user->getUserId();
$userModel = XenForo_Model::create('XenForo_Model_User');
$userModel->removeUserGroupChange($user_id, 'RANDOM_STRING');
$userModel->addUserGroupChange($user_id, 'RANDOM_STRING', 38);

When I ran the program, it did not add Scotty Jakes to user group 38. When I ran the program, I simulated operating conditions by deleting all the cookies for our domain from my browser. Then I registered Scotty Jakes through our site's signup process. Then I ran addUserScottyJakes_to_Group_38.php

How can I make this work?

Thank you.
 
$user_id=$user->getUserId(); Wont work because $user is an array, rather than an object.

Try

PHP:
$user_id = $user['user_id'];
 
@Chris D Tangent question, how does XenForo recognize @Chris D vs. @Chris Don't forget to pickup the milk? I guess the space after the D serves as a delimiter to the interpreter that handles rich text input?

The main comment I wanted to make is that answer you provided is perfect. Thank you.
 
The following function takes a message and runs it through a filtering process then a complex regular expression to ascertain which users are tagged in that message:

XenForo_Model_UserTagging::getTaggedUsersInMessage();

It's probably harder to explain in words than it is to read the code (but it's not the simplest code in the world, either!).

Glad that worked for you.
 
You said it all enough right there, thank you.

Chris, I have another follow up that is more serious.

I am going make a statement. XenForo is serious excellent software, with a globally significant install base, right?

Your company needs to hire a technical writer to make for you an introduction for people who dig into the code.

This is what I needed to be told, a year ago.
Here is a paragraph that would have saved me months.
"Dan, make a file with php as the file extention. Put it in the xf root directory. Put this code in it. That set of code lets you retrieve and update user information, such as adding user groups, changing their profile. In that example you can see it add a group, changing one of their preferences. Make another file with this code instead. You can see it is almost the same as the other, but this instantiates forum and post classes instead of user classes. This third file has the 20 most commonly used object and methods, that will give you a start. Including logging into Xenforo, so if you have another application you log into XF with this code in that application and use these objects to do anything XF does, except you can do it from inside another application that makes calls into our library. We figure this is way better than a restful api and just as easy to learn, so why bother with a restful API?

Oh and very important Dan, you do not have to be logged in to use these programs."
It makes your company come across as fly by night that you don't have any serious documentation. Your software is so excellent, you have a great rep anyway, but this lack of documentation is I dunno,. The fact that you help the way you shows you want to support people doing this kind of thing. The cost for an introduction would be almost nothing it would make big impact. I have seen plenty of smart programmers on this forum lost the same way I was lost.

What do I mean lost? I could not figure what to do with any of the sample code people provided, until I made a guess after reading your post that said, "that is pretty much all you need" Meanwhile, while I could not figure that out that I needed to a file with your sample code in it, I figured out a way to move people among user groups by SQL manipulation and then running the user cache update through admin. That was a lot more complicated than this. So why was I not getting this. I program object oriented code every day, so that is not the issue

I don't think I ever have worked so hard, for so long to get an answer that is so simple.

SSL certificate installation is the closest 2nd, but this is lot simpler than getting SSL.

These are the instructions I needed:
"Dan, make a file with php as the file extention. Put it in the xf root directory. Put this code in it. That set of code lets you retrieve and update user information, such as adding user groups, changing their profile. In that example you can see it add a group, changing one of their preferences. Make another file with this code instead. You can see it is almost the same as the other, but this instantiates forum and post classes instead of user classes. This third file has the 20 most commonly used object and methods, that will give you a start. Including logging into Xenforo, so if you have another application you log into XF with this code in that application and use these objects to do anything XF does, except you can do it from inside another application that makes calls into our library. We figure this is way better than a restful api and just as easy to learn, so why bother with a restful API?

I think that paragraph six months ago would have got me more than everything I got in those six until yesterday. When the lightbulb came on for me, I was just guessing what to do. You wrote "that should be pretty much all you need" to somebody else. I looked at that and thought,"well, it sounds like he is saying means I can make a file and put that code in there I will have everything I need. For all knew, that code needed to be embedded within some other code to get it to go. More often than not, that is how code is presented.
 
That was a long comment, I be as brief as possible going forward.

What commands can put in that program I have now to add a user?

I am looking at the Visitor class, but not seeing ADD USER or anything like that.
 
Noted.

Fact is, it's patently obvious to anyone that spends any time with the software or the forum that we're certainly not a "fly by night" operation and the fact is that many people have different ways of learning. Only some of them learn by reading the kind of documentation you're talking about. Only some learn by doing things like reading the code. Some learn by a combination of both. The fact that some people can competently develop for XenForo without the documentation demonstrates that it's not essential, but at the same time we have seen feedback to suggest it would be useful so it will certainly be something we consider for the future.

I am looking at the Visitor class, but not seeing ADD USER or anything like that.
Generally whenever you're creating stuff in XenForo, or updating, you should use the DataWriter system. Simplest example which demonstrates creating a user can be seen in the XenForo_ControllerAdmin_User class under the actionSave() function.

This is the function that runs when you're on the Create User page in the Admin CP and you click on the "Save Changes" button. Clicking Save Changes on that page calls the actionSave() method and takes the input from the Create User page and creates a user with it. It's also responsible for updating a user via the user edit page, but there should be conditionals in that code which make it clear the different code paths required for updating an existing user vs creating a new one.
 
Thank your answer on both items.

I want correct something I wrote wrong. Xenforo is flat out the best software I have had an opportunity to work with and I am old and been working with software most of my life. Everything about Xenforo is first class. Maybe the documentation is not something you emphasize and I can only assume that is part of the reason for your success.

My poor statement on that matter might have obscured the main point I was trying convey. I think this point might be important, because the information available to me indicates a substantial fraction of Xenforo installation are adversely affected, and that a relatively small mitigation action would make a significant contribution to making those installation better. I also think this problem is hard to spot, especially for people who are not affected by it and surrounded by people unaffected by it. The vector of this problem passes through a significant number of developers, but not all developers. I doubt this problem is a reliable indicator of a developer's competence or intelligence.

I think the problem relates to understanding a certain tiny fraction of information needed to develop with Xenforo software. I think it would be possible to create a hugely favorable result with comparatively tiny effort, by focusing on the tiny body of knowledge I am referring to. It would be like providing a cyrypto key to make a large dataset readable. Without the key, there is little hope for understanding the data. With the key, the data is in plain text. The reason some people obtain the key to understanding Xenforo software coding more easily than others occasionally is the result of high intelligence. Some people get the key because they happen to have come into the software field by a path that has this orientation built in. The rest of us are baffled until we get the key. Once we get the key, you wouldn't know we are from the pool of those who are baffled upon first contact. I think providing the key to the baffled would help a lot of people.

In my previous note, I stated how I think I could have been given the key. Basically, I needed a practical and simple example of how to make program that instantiates one of the main XF classes and does something simple with it, bypassing the security routines built into XF application. Without that practical, simple example, I was lost. With that example, I am not lost. Maybe I am unique or representative of only of outliers. Maybe, half the developers assigned to work with this software are the boat I have been in. Comments in these forums indicates to me that the baffled-upon-first-contact is a lot more frequent than "oh I just get it and understand this easily from the first time I see it."

I hope this is more valuable than my previous effort on this topic. Thank you for your valuable time

Simplest example which demonstrates creating a user can be seen in the XenForo_ControllerAdmin_User class under the actionSave() function.
Ok, here is what am going to do with that. I am going make a stand-alone program based on the code in the XenForo_ControllerAdmin_User class under the actionSave() function. I think what people need is stand-alone example with a reference to how it was created by using the code in the in the application That puts a program into a person's hands that they can run off the bat and then edit, using the Xenforo app as a reference library showing how to do everything. Who needs more documentation than that?

Until I had an example like that, I was dead in the water. I think everything I have been trying to say is that simple.

The "key" is the simple example that someone can run without doing anything except copying the file onto their sever then just run it via their browser by hitting its url.

.
 
I could not figure how to get the actionSave in XenForo_ControllerAdmin_User to work without being logged in. Since the goal is for the process to run during signup to our site, it has to be able to do the job without logging the browser in as an administrator.

So, what I did was copy actionSave into the user model, naming it saveMember.

I copied the form that comes up in admin for creating a user into my external app. The app fills in the form, not people, then the app posts the form to this script:

Code:
<?php 
$startTime = microtime(true);
define('XF_ROOT', $basePath);  
define('TIMENOW', time());
define('SESSION_BYPASS', true); 
require_once(XF_ROOT . '/library/XenForo/Autoloader.php');
XenForo_Autoloader::getInstance()->setupAutoloader(XF_ROOT . 'library');
XenForo_Application::initialize(XF_ROOT . 'library', XF_ROOT);
XenForo_Application::set('page_start_time', $startTime);
$dependencies = new XenForo_Dependencies_Admin();
$dependencies->preLoadData();
$userModel = XenForo_Model::create('XenForo_Model_User');
$new_memberArr=$userModel->saveNewUser();

I am changing the post to something that outsiders cannot touch or submit, either database records or an array in the php session, or both.

I am sure this is not the best way to do this. So I am more than interested in suggestions.
 
Top Bottom