HebRech GmbH & Co. KG Posted August 31, 2017 Posted August 31, 2017 I have a customized signup form where the user can enter a unique key that will give them to access to certain parts of the site. I intend to implement this through the primary member group as the distinction between the various access levels should be immediately obvious in the forum. In order to achieve this I have added a hook to \IPS\core\modules\front\system\register, extending the _createMember() method. My method looks vaguely like this: public static function _createMember($values, $profileFields) { $member = parent::_createMember($values, $profileFields); $accessData = SomeClass::checkAccessCode($values['access_code']); switch ($accessData->type) { case 'foo': $member->member_group_id = \IPS\Settings::i()->member_group_foo; break; case 'bar': $member->member_group_id = \IPS\Settings::i()->member_group_bar; break; default: $member->member_group_id = \IPS\Settings::i()->member_group_baz; break; } $member->save(); } It actually works... until the "Email activation required" page is loaded. Then the member group is reset to "Member". The stack trace for that save looks like this: /ips4/system/Session/Session.php:210 (IPS\_Member->save) /ips4/system/Session/Session.php:93 (IPS\_Session->init) /ips4/system/Member/Member.php:145 (IPS\_Session::i) /ips4/system/Dispatcher/Front.php:643 (IPS\_Member::loggedIn) /ips4/system/Dispatcher/Front.php:63 (IPS\Dispatcher\_Front::baseCss) /ips4/system/Dispatcher/Dispatcher.php:103 (IPS\Dispatcher\_Front->init) /ips4/index.php:12 (IPS\_Dispatcher::i) From what I can tell the dispatcher asks for the currently logged in member, whoch comes from the session. The session still has the old member object (with member group "Member") and saves that to the database before returning it. Attempts to overwrite the session's member object in my hook have failed, as have attempts to destroy the session in the hook. What are my options for setting the member group during registration without the session undoing my changes?
Adriano Faria Posted August 31, 2017 Posted August 31, 2017 You need to add a new column to store the guest choice and then update new member with the right member group ID after the registration process/validation finishes. That's what I did here:
HebRech GmbH & Co. KG Posted August 31, 2017 Author Posted August 31, 2017 Thanks; that clarifies things a bit. I already store that choice separately. (I removed that code from my example for clarity.) Which hook do I need to use to trigger something immediately after registration?
Adriano Faria Posted August 31, 2017 Posted August 31, 2017 IPS\core\modules\front\system\register::_createMember().
HebRech GmbH & Co. KG Posted August 31, 2017 Author Posted August 31, 2017 44 minutes ago, Adriano Faria said: IPS\core\modules\front\system\register::_createMember(). I already hook that method. The session schenanigans happen later. 43 minutes ago, newbie LAC said: If you make an app I already use a MemberSync extension to set up a few things. As far as I can tell onCreateAccount() runs far too early (as soon as the member is first written to the DB) and onValidate() runs too late – I don't want unvalidated members to be in the default group.
BomAle Posted August 31, 2017 Posted August 31, 2017 /** * Call after completed registration to send email for validation if required or flag for admin validation * * @param bool $noEmailValidationRequired If the user's email is implicitly trusted (for example, provided by a third party), set this to TRUE to bypass email validation * @param bool $doNotDelete If TRUE, the account will not be deleted in the normal cleanup of unvalidated accounts. Used for accounts created in Commerce checkout. * @return void */ public function \IPS\Member::postRegistration( $noEmailValidationRequired=false, $doNotDelete=false ) check also it /** * Member account has been created * * @param $member \IPS\Member New member account * @return void */ public function onCreateAccount( $member ) { if( !$this->_checkStatus() ) { return; } if ( $member->email AND !$member->members_bitoptions['bw_is_spammer'] AND \IPS\Settings::i()->reg_auth_type == 'none') { //member is approved and there are not any auth required } } /** * Member has validated * * @param \IPS\Member $member Member validated * @return void */ public function onValidate( $member ) { if( !$this->_checkStatus() ) { return; } //member is validated do something here }
HebRech GmbH & Co. KG Posted August 31, 2017 Author Posted August 31, 2017 That does sound good... Unfortunately, \IPS\Member::postRegistration() still seems to run before the session overwrites the member. Perhaps my code works correctly and I should rather investigate what causes the session to write obsolete data to the database... Time to hit the source code again.
HebRech GmbH & Co. KG Posted September 1, 2017 Author Posted September 1, 2017 Okay, I finally managed to resolve the problem. Two of them, actually. Basically, I had some problem I can't reconstruct right now. While trying out various things I waved a few dead chickens around. One of those dead chickens involved messing around with how exactly the member groups were set – instead of using the magic member_group_id property I now called set_member_group_id(). I then proceeded to somehow fix the first problem, although by now the member group ID would outwardly change but would never be propagated to the database. The resulting behavior looked exactly as before, although the underlying problem was now a different one. That's why I couldn't get your suggestions to work – the problem was technically solved very early on. After I noticed that set_member_group_id() does not actually do what I thought it does I changed my code back to using the property and it suddenly worked just fine. Perhaps the IPS code documentation could be a bit clearer in situations like this – set_member_group_id() is not there to set the member group ID but is instead a helper method called by the magic property setter defined by the ActiveRecord pattern. While there is a @see reference to ActiveRecord::_set in the doc block the title of "Set group" makes it look like the method can be used to set the group, while it really shouldn't be called directly.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.