[SOLVED] CBSubs undoes group-add actions

9 years 9 months ago - 9 years 9 months ago #247155 by wlc11
Hi folks,

I'm writing a CB plugin to set multiple user groups during signup, and I've just discovered that CB or CBSubs seems to be unsetting the groups after me.

After many hours of troubleshooting my queries and being sure they were right, I threw in a die() right after adding the users to the groups, and sure enough, User Manager shows them in those groups (but of course, not activated).

The plans under CB Subs are set to Access -> User Group -> No change of usergroup

The logic required for our use case does not make the User Group chooser fully effective (we need to set the user to multiple groups, and choose one of them dynamically).

What is the cleanest workaround to prevent inserts to #__user_usergroups_map from being undone?

Additional info:
Joomla 3.3.1 (temporarily behind because we're near deployment on this project)
CB 1.9.1

We're using the onCPayUserStateChange event.

I have authorization to send Joomlapolis staff the project code if necessary.

Please Log in to join the conversation.

9 years 9 months ago - 9 years 9 months ago #247156 by wlc11
Replied by wlc11 on topic Merged with above
Merged with above

Please Log in to join the conversation.

9 years 9 months ago #247195 by krileon
Replied by krileon on topic Merged with above
Use CB Auto Actions and its Usergroups action then act on the after registration trigger. If you want it to depend on CBSubs you can use the below trigger and conditionals. There's no need to write a custom plugin to add usergroups.

Plan Active
Triggers: onCPayUserStateChange
User: Automatic
Access: Everybody
Conditional 1: [var3] Equal To PLAN_ID_HERE
Conditional 2: [var2] Equal To A

Plan Expired
Triggers: onCPayUserStateChange
User: Automatic
Access: Everybody
Conditional 1: [var3] Equal To PLAN_ID_HERE
Conditional 2: [var2] Equal To X

As long as CBSubs is set to not change usergroups it won't touch them at all. What you're probably experiencing, depending on how your plugin works, is user store override. Meaning you're storing the user, but then the user is being stored by CB which is where your usergroups would be lost. The above CBSubs triggers or the after registration trigger should both work ok.


Kyle (Krileon)
Community Builder Team Member
Before posting on forums: Read FAQ thoroughly + Read our Documentation + Search the forums
CB links: Documentation - Localization - CB Quickstart - CB Paid Subscriptions - Add-Ons - Forge
--
If you are a Professional, Developer, or CB Paid Subscriptions subscriber and have a support issue please always post in your respective support forums for best results!
--
If I've missed your support post with a delay of 3 days or greater and are a Professional, Developer, or CBSubs subscriber please send me a private message with your thread and will reply when possible!
--
Please note I am available Monday - Friday from 8:00 AM CST to 4:00 PM CST. I am away on weekends (Saturday and Sunday) and if I've missed your post on or before a weekend after business hours please wait for the next following business day (Monday) and will get to your issue as soon as possible, thank you.
--
My role here is to provide guidance and assistance. I cannot provide custom code for each custom requirement. Please do not inquire me about custom development.

Please Log in to join the conversation.

9 years 9 months ago - 9 years 9 months ago #247201 by wlc11
Replied by wlc11 on topic Merged with above
The determination of which group to set can _only_ be determined by custom logic. It involves processes outside of CB and custom creation of user groups and viewlists. E.g. we are conditionally creating the group, and doing a few affiliate-related actions as well. The plugin is necessary.

As to "user store override" -- I am directly writing to the #__user_usergroup_map table during signup, associating $user->id (from the $user object passed to the event). There are no other CB-related objects involved unless they somehow override JFactory::getDbo() in order to accomplish it.

In short, I'm sorry, but this is not a solution. The code we've spent a month of development on is finished except for this problem.


PS: Also to clarify, we are allowing CB to complete the registration without interference (you had supposed we were manually storing the user; no, we're just manually storing #__user_usergroup_map entries after CB creates the user).


PPS: And to make things as super-clear as possible, the relevant part of our plugin in a nutshell:

onCPayUserStateChange:
- determine the event (using a copy-paste of the if/elseif block from page 3 of the CBSubs_devkit_integrations_API_doc pdf)
- if we have an event, switch on it:
-- case pendingfirst or activation we grab outside data from mysql to update & act on
--- these cases do not break
-- next are cases renewal and autorenewal
--- if the event was activation, add the user to two different groups (one for Paid status, another for a group chosen/created by the user who invited them)
--- else check if the user is in the Payment Expired group; if so, remove them from it, add them to the Paid group, and set them to an arbitrary number of other groups based on their memberships prior to expiration (stored in a table outside CB)
--- (these cases do break)

I include this information to help you see, as efficiently as possible, that we really need a solution closer to what was explicitly requested - whether it's a different event I could use for these actions (with the same data about the event, after whatever's happening here), or a patch, (or a setting we're missing). We just need "No change of user group" to apply to everything except our code.

Please Log in to join the conversation.

9 years 9 months ago - 9 years 9 months ago #247265 by krileon
Replied by krileon on topic Merged with above

As to "user store override" -- I am directly writing to the #__user_usergroup_map table during signup, associating $user->id (from the $user object passed to the event). There are no other CB-related objects involved unless they somehow override JFactory::getDbo() in order to accomplish it.

Don't write directly to the database. It's not going to update the user object in memory. The users session data also won't have the usergroups. To add usergroups you need to use APIs. The below for example is how CB Auto Actions does it.

$session	=	JFactory::getSession();
$jUser		=	$session->get( 'user' );

$user->gids	=	$groups;

$user->store();

if ( $jUser->id == $user->id ) {
	JAccess::clearStatics();

	$session->set( 'user', new JUser( $user->id ) );
}

The above assumes $user is the CB user object, which ideally would be the object sent by the CB trigger being acted on (e.g. after registration or cbsubs user state change). If the user being updated is the actual user then it can update their session data with the new usergroups. If you want to add groups to the existing groups you'd just merge gids with your groups array. Same usage can be used to remove groups as well by removing them from the gids array. You can also use strictly Joomla user object API if you want, but just be sure you update $user->gids with the new groups array.

It all depends on the storage order though. CBSubs doesn't replace usergroups on Joomla 1.6 and newer. It only adds them if they are specified in the plan being activated. So if the new usergroups are in the user object then they should never be lost no matter the situation.


Kyle (Krileon)
Community Builder Team Member
Before posting on forums: Read FAQ thoroughly + Read our Documentation + Search the forums
CB links: Documentation - Localization - CB Quickstart - CB Paid Subscriptions - Add-Ons - Forge
--
If you are a Professional, Developer, or CB Paid Subscriptions subscriber and have a support issue please always post in your respective support forums for best results!
--
If I've missed your support post with a delay of 3 days or greater and are a Professional, Developer, or CBSubs subscriber please send me a private message with your thread and will reply when possible!
--
Please note I am available Monday - Friday from 8:00 AM CST to 4:00 PM CST. I am away on weekends (Saturday and Sunday) and if I've missed your post on or before a weekend after business hours please wait for the next following business day (Monday) and will get to your issue as soon as possible, thank you.
--
My role here is to provide guidance and assistance. I cannot provide custom code for each custom requirement. Please do not inquire me about custom development.

Please Log in to join the conversation.

9 years 9 months ago - 9 years 9 months ago #247288 by wlc11
Replied by wlc11 on topic Merged with above
We will implement this advice trapping for whether the user in question, is the user in the session -- however it raises the question about activations/deactivations peformed via other means (expiration, admin action). In other words we need it to work in all cases of activation/deactivation.

I'll adapt my two functions for setting/unsetting groups so that they use your method when the logged-in user_id is equal to the CB user->id being passed to the event, and my method otherwise (edit: done, see below) -- however I anticipate possible problems on this (i.e., if CB's objects need me to avoid direct table writes, but the present session is not applicable to the user who is subject to the status change, what do I do?)

Will update this message once I see what happens.

EDIT: The user in the session object has no id at this phase. Here is what I get when I print_r on JFactory::getSession()->get('user')
jUser = JUser Object
(
    [isRoot:protected] => 1
    [id] => 0
    [name] => 
    [username] => 
    [email] => 
    [password] => $2y$10$qRt0/eUAgGtEB9rxDqEt3O5xfLQ8lKp18CEImOyu0TSP3ub1CxRUy
    [password_clear] => foobar
    [block] => 
    [sendEmail] => 0
    [registerDate] => 2014-07-30 21:38:29
    [lastvisitDate] => 
    [activation] => 
    [params] => 
    [groups] => Array
        (
            [0] => 1
        )

    [guest] => 1
    [lastResetTime] => 
    [resetCount] => 
    [requireReset] => 
    [_params:protected] => Joomla\\Registry\\Registry Object
        (
            [data:protected] => stdClass Object
                (
                )

        )

    [_authGroups:protected] => Array
        (
            [0] => 1
        )

    [_authLevels:protected] => Array
        (
            [0] => 1
            [1] => 1
            [2] => 3
            [3] => 6
        )

    [_authActions:protected] => 
    [_errorMsg:protected] => 
    [_errors:protected] => Array
        (
        )

    [aid] => 0
)

Please Log in to join the conversation.

Moderators: beatnantkrileon
Time to create page: 0.632 seconds

Facebook Twitter LinkedIn