1

I have 2 front end registration forms. One for normal users and one for admins. In each form I have a hidden input with a group value like so:

<input type="hidden" name="group" value="ypo">

In craft I have allow public registration checked and verify user address unchecked

Then I have a module that does two things: One, it assigns new registrations to the correct group based on the hidden field and that part works like a charm, but I'll still post it here just in case:

Event::on(
        Elements::class,
        Elements::EVENT_AFTER_SAVE_ELEMENT,
        function(ElementEvent $event){
          // Check it's a front end request
          if (Craft::$app->request->getIsSiteRequest()) {
            if($event->element instanceof \craft\elements\User){
              $user = $event->element;
              if($event->isNew) {
                  $formName = Craft::$app->getRequest()->post('group');
                  if($formName==='ypo')
                  {
                    Craft::$app->getUsers()->assignUserToGroups($event->element->id, [1]);
                    logMessage('Assigning Member - id: '.$event->element->id);
                  }
                  if($formName==='yp')
                  {
                    Craft::$app->getUsers()->assignUserToGroups($event->element->id, [2]);
                    logMessage('Assigning Website User - id: '.$event->element->id);
                    $users =  Craft::$app->getUsers();
                    if($users->sendActivationEmail($user)) {
                      logMessage('Activation Email Sent');
                    }
                  }
              }
            }
          }
        }
      );

Two, it blocks new users from being activated like that:

Event::on(
          Users::class,
          Users::EVENT_BEFORE_ACTIVATE_USER,
          function (UserEvent $event) {
              if (Craft::$app->request->getIsSiteRequest()) {
                // Only trigger when request comes from the specified form
                $formName = Craft::$app->getRequest()->post('group');
                if($formName==='ypo' || $formName==="yp") {
                  logMessage('Activation Withold');
                  $event->isValid = false;

                }
              }
          }
      );

I based this code on Brandon's answer to [a very similar question][1] and it works, in a sense it sets the status to pending, but...

[1]: How can I set new user accounts to pending status in a Craft 3 module? but added the safeguard that the code will only be triggered when the accompanying hidden form fields are present.

The problem

The problem is that whenever I want to activate the account,by emailing the activation code (manually or by my script), I get an error:

Return value of craft\web\twig\variables\UserSession::getRememberedUsername() must be of the type string, null returned

EDIT: error was due to having 'autoLoginAfterAccountActivation' => true in settings. Switching that off got rid of the error, but the activation still doesn't work.

What's even more weird is when I use the activation code from the admin panel, I'm then redirected to set your new password page instead of activation.

My log doesn't show that my script has been triggered, so it shouldn't prevent activation from link or email. Any help would be appreciated.


I did a lot of testing, If I remove EVENT_BEFORE_ACTIVATE_USER code and register a user, and then put it back in and send email, activation works. This means that setting craft\events\UserEvent::$isValid to false is permanent and can no longer be activated. Any idea why?

1

So, for the part preventing the activation, don't use:

if (Craft::$app->request->getIsSiteRequest())

Just do:

Event::on(
    Users::class,
    Users::EVENT_BEFORE_ACTIVATE_USER,
    function(Event $event){
        $formName = Craft::$app->getRequest()->post('group');
        if ($formName==='ypo' || $formName==="yp") {
           $event->isValid = false;
        }
    }
);

For the other part:

Event::on(
Elements::class,
Elements::EVENT_AFTER_SAVE_ELEMENT,
    function(Event $event){
        // Check it's a front end request
        if (Craft::$app->request->getIsSiteRequest()) {
            if($event->element instanceof \craft\elements\User) {
                $user = $event->element;
                if($event->isNew) {
                    $user->unverifiedEmail = $user->email;
                    Craft::$app->getElements()->saveElement($user, false);
                    $formName = Craft::$app->getRequest()->post('group');

                    if($formName==='ypo') {
                        Craft::$app->getUsers()->assignUserToGroups($user->id, [1]);
                    }
                    if($formName==='yp') {
                        Craft::$app->getUsers()->assignUserToGroups($user->id, [2]);
                        $emailSent = Craft::$app->getUsers()->sendActivationEmail($user);    
                    }
                }
            }
        }
    }
);

Because you don't enforce email verification in control panel/user settings, you are skipping populating the unverifiedEmail field for the new user which is done here and that was part of the issue too :)

  • ahh the unverifiedEmail field, that did it. – Lukigi Mar 4 at 11:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.