Example #1
0
    /**
     * Display the registration form.
     *
     * Parameters passed via GET:
     * --------------------------
     * None.
     *
     * Parameters passed via POST:
     * ---------------------------
     * See the definition of {@link Users_Controller_FormData_RegistrationForm}.
     *
     * Parameters passed via SESSION:
     * ------------------------------
     * None.
     *
     * Parameters passed via SERVER:
     * ------------------------------
     * string HTTP_USER_AGENT The browser user agent string, for comparison with illegal user agent strings.
     *
     * @return string The rendered template.
     */
    public function register()
    {
        // Should not be here if logged in.
        $this->redirectIf(UserUtil::isLoggedIn(), ModUtil::url($this->name, 'user', 'main'));

        // check permisisons
        if (!SecurityUtil::checkPermission($this->name .'::', '::', ACCESS_READ)) {
            throw new Zikula_Exception_Forbidden();
        }

        // Check if registration is enabled
        if (!$this->getVar(Users_Constant::MODVAR_REGISTRATION_ENABLED, Users_Constant::DEFAULT_REGISTRATION_ENABLED)) {
            return $this->view->fetch('users_user_registration_disabled.tpl');
        }

        // Initialize state for the state machine later on.
        $state = 'error';

        if ($this->request->isGet()) {
            // An HTTP GET, meaning either we are reentering the function from an external authenticator,
            // or we are entering the function for the very first time.
            $reentrantTokenReceived = $this->request->query->get('reentranttoken', false);
            if ($reentrantTokenReceived) {
                // We got here by reentering from an external authenticator. Grab the data we stored in session variables.
                $sessionVars = $this->request->getSession()->get('Users_Controller_User_register', false, 'Zikula_Users');
                if ($sessionVars) {
                    $reentrantToken = isset($sessionVars['reentranttoken']) ? $sessionVars['reentranttoken'] : false;
                    $authenticationInfo = isset($sessionVars['authentication_info']) ? $sessionVars['authentication_info'] : array();
                    $selectedAuthenticationMethod = isset($sessionVars['authentication_method']) ? $sessionVars['authentication_method'] : array();

                    if ($reentrantToken != $reentrantTokenReceived) {
                        throw new Zikula_Exception_Forbidden();
                    }
                } else {
                    throw new Zikula_Exception_Fatal($this->__('An internal error occurred. Failed to retrieve stored registration state.'));
                }

                $state = 'authenticate';
            } else {
                // We are entering this function for the very first time.
                $selectedAuthenticationMethod = array();
                $authenticationInfo = array();

                $state = 'start';
            }
        } elseif ($this->request->isPost()) {
            // An HTTP POST, so a form was submitted in order to get into the function. There are three possibilities.
            // It could be that the user selected an authentication method, and we need to switch to that method.
            // It could be that the user supplied authentication info to send to an authentication method, and we need to do that.
            // It could be that the user submitted the actual registration form.

            $this->checkCsrfToken();

            if ($this->request->request->get('authentication_method_selector', false)) {
                // The user selected an authentication method, so we need to switch to it.
                $selectedAuthenticationMethod = $this->request->request->get('authentication_method', false);
                $authenticationInfo = array();

                $state = 'authentication_method_selector';
            } elseif ($this->request->request->get('registration_authentication_info', false)) {
                // The user submitted authentication information that needs to be processed by the authentication module.
                $authenticationInfo           = $this->request->request->get('authentication_info', array());
                $selectedAuthenticationMethod = $this->request->request->get('authentication_method', array());

                $reentrantToken = substr(SecurityUtil::generateCsrfToken(), 0, 10);

                $state = 'authenticate';
            } elseif ($this->request->request->get('registration_info', false)) {
                // The user submitted the acutal registration form, so we need to validate the entries and register him.
                $formData = new Users_Controller_FormData_RegistrationForm('users_register', $this->serviceManager);
                $formData->setFromRequestCollection($this->request->request);
                $selectedAuthenticationMethod = json_decode($this->request->request->get('authentication_method_ser', false), true);
                $authenticationInfo = json_decode($this->request->request->get('authentication_info_ser', false), true);

                $state = 'validate';
            }
        } else {
            // Neither a POST nor a GET, so a fatal error.
            throw new Zikula_Exception_Forbidden();
        }

        // The state machine that handles the processing of the data from the initialization above.
        while ($state != 'stop') {
            switch ($state) {
                case 'start':
                    // Initial starting point for registration - a GET request without a reentrant token
                    // Check for illegal user agents trying to register.
                    $userAgent = $this->request->server->get('HTTP_USER_AGENT', '');
                    $illegalUserAgents = $this->getVar(Users_Constant::MODVAR_REGISTRATION_ILLEGAL_AGENTS, '');
                    // Convert the comma-separated list into a regexp pattern.
                    $pattern = array('/^(\s*,\s*)+/D', '/\b(\s*,\s*)+\b/D', '/(\s*,\s*)+$/D');
                    $replace = array('', '|', '');
                    $illegalUserAgents = preg_replace($pattern, $replace, preg_quote($illegalUserAgents, '/'));
                    // Check for emptiness here, in case there were just spaces and commas in the original string.
                    if (!empty($illegalUserAgents) && preg_match("/^({$illegalUserAgents})/iD", $userAgent)) {
                        throw new Zikula_Exception_Forbidden($this->__('Sorry! The user agent you are using (the browser or other software you are using to access this site) is banned from the registration process.'));
                    }

                    // Notify that we are beginning a registration session.
                    $event = new Zikula_Event('module.users.ui.registration.started');
                    $this->eventManager->notify($event);

                    // Get a list of authentication methods available for registration
                    // NOTE: The Users module methods should NOT appear on this list!
                    $authenticationMethodList = new Users_Helper_AuthenticationMethodList($this, array(), Zikula_Api_AbstractAuthentication::FILTER_REGISTRATION_ENABLED);

                    if ($authenticationMethodList->countEnabledForRegistration() <= 0) {
                        // There are no (non-Users module) methods available for registration, so just default to Users.
                        // Note that the method name is 'uname' here no matter what loginviaoption says. This is on purpose.
                        $selectedAuthenticationMethod = array(
                            'modname' => 'Users',
                            'method'  => 'uname',
                        );

                        $state = 'display_registration';
                    } else {
                        // There are other authentication modules with methods that are enabled for registration. Display
                        // the choices to the user.
                        $state = 'display_method_selector';
                    }
                    break;

                case 'display_registration':
                    // An authentication method has been selected (or defaulted), or there were errors with the last
                    // submission of the registration form.
                    // Display the registration form to the user.
                    if (!isset($formData)) {
                        $formData = new Users_Controller_FormData_RegistrationForm('users_register', $this->serviceManager);
                    }

                    $state = 'stop';

                    $arguments = array(
                        'authentication_method' => $selectedAuthenticationMethod,
                        'authentication_info'   => $authenticationInfo,
                        'registration_info'     => isset($registrationInfo) ? $registrationInfo : array(),
                        'errorFields'           => isset($errorFields) ? $errorFields : array(),
                        'errorMessages'         => isset($errorMessages) ? $errorMessages : array(),
                    );

                    return $this->view->assign_by_ref('formData', $formData)
                            ->assign($arguments)
                            ->fetch('users_user_register.tpl');
                    break;

                case 'display_method_selector':
                    // An authentication method to use with the user's registration has not been selected.
                    // Present the choices to the user.
                    $authenticationMethodList = new Users_Helper_AuthenticationMethodList($this, array(), Zikula_Api_AbstractAuthentication::FILTER_REGISTRATION_ENABLED);

                    // TODO - The order and availability should be set by configuration
                    $authenticationMethodDisplayOrder = array();
                    foreach ($authenticationMethodList as $am) {
                        if ($am->isEnabledForAuthentication()) {
                            $authenticationMethodDisplayOrder[] = array(
                                'modname'   => $am->modname,
                                'method'    => $am->method,
                            );
                        }
                    }

                    $usersAuthenticationMethod = array(
                        'modname' => 'Users',
                        'method'  => 'uname',
                    );

                    $state = 'stop';

                    $arguments = array(
                        'authentication_info'                   => isset($authenticationInfo) ? $authenticationInfo : array(),
                        'selected_authentication_method'        => $selectedAuthenticationMethod,
                        'users_authentication_method'           => $usersAuthenticationMethod,
                        'authentication_method_display_order'   => $authenticationMethodDisplayOrder,
                    );

                    return $this->view->assign($arguments)
                            ->fetch('users_user_registration_method.tpl');
                    break;

                case 'authentication_method_selector':
                    // One of the authentication method selectors on the registration methods page was clicked.
                    if (!$selectedAuthenticationMethod || !is_array($selectedAuthenticationMethod) || empty($selectedAuthenticationMethod)
                            || !isset($selectedAuthenticationMethod['modname']) || !is_string($selectedAuthenticationMethod['modname']) || empty($selectedAuthenticationMethod['modname'])
                            || !isset($selectedAuthenticationMethod['method']) || !is_string($selectedAuthenticationMethod['method']) || empty($selectedAuthenticationMethod['method'])
                            ) {
                        throw new Zikula_Exception_Fatal($this->__('An invalid authentication method was selected.'));
                    }

                    if ($selectedAuthenticationMethod['modname'] == $this->name) {
                        $state = 'display_registration';
                    } else {
                        $state = 'display_method_selector';
                    }
                    break;

                case 'authenticate':
                    // The user provided and submitted the authentication information form on the registration methods page in order
                    // to authenticate his credentials with the authentication method in order to proceed to the main registration page,
                    // OR the user is reentering the registration process after exiting to the external authentication service to
                    // authenticate his credentials.

                    // Save the submitted information in case the authentication method is external and reentrant.
                    // We're using sessions here, even though anonymous sessions might be turned off for anonymous users.
                    // If the user is trying to regiuster, then he's going to get a session if he's successful and logs in,
                    // so using sessions on the anonymous user just before registration should be ok.
                    SessionUtil::requireSession();
                    $sessionVars = array(
                        'authentication_info'   => $authenticationInfo,
                        'authentication_method' => $selectedAuthenticationMethod,
                        'reentranttoken'        => $reentrantToken,
                    );
                    $this->request->getSession()->set('Users_Controller_User_register', $sessionVars, 'Zikula_Users');

                    // The authentication method selected might be reentrant (it might send the user out to an external web site
                    // for authentication, and then send us back to finish the job). We need to tell the external system to where
                    // we would like to return.
                    $reentrantUrl = ModUtil::url($this->name, 'user', 'register', array('reentranttoken' => $reentrantToken), null, null, true, true);

                    // The chosen authentication method might be reentrant, and this is the point were the user might be directed
                    // outside the Zikula system for external authentication.
                    $arguments = array(
                        'authentication_info'   => $authenticationInfo,
                        'authentication_method' => $selectedAuthenticationMethod,
                        'reentrant_url'         => $reentrantUrl,
                    );
                    $checkPasswordResult = ModUtil::apiFunc($selectedAuthenticationMethod['modname'], 'authentication', 'checkPasswordForRegistration', $arguments, 'Zikula_Api_AbstractAuthentication');

                    // If we have gotten to this point in the same call to registrationMethod(), then the authentication method was not external
                    // and reentrant, so we should not need the session variable any more. If it is external and reentrant, and the
                    // user was required to exit the Zikula system for authentication on the external system, then we will not get
                    // to this point until the reentrant callback (at which point the variable should, again, not be needed
                    // anymore).
                    $this->request->getSession()->del('Users_Controller_User_register', 'Zikula_Users');

                    // Did we get a good user? If so, then we can proceed to hook-like event and hook validation.
                    if (isset($checkPasswordResult) && $checkPasswordResult && is_array($checkPasswordResult)) {
                        if (isset($checkPasswordResult['authentication_info'])) {
                            $arguments['authentication_info'] = $checkPasswordResult['authentication_info'];
                        }
                        $uid = ModUtil::apiFunc($selectedAuthenticationMethod['modname'], 'authentication', 'getUidForAuthenticationInfo', $arguments, 'Zikula_Api_AbstractAuthentication');

                        if ($uid === false) {
                            if (isset($checkPasswordResult['authentication_info'])) {
                                $authenticationInfo = $checkPasswordResult['authentication_info'];
                            }

                            $formData = new Users_Controller_FormData_RegistrationForm('users_register', $this->serviceManager);

                            $registrationInfo = (isset($checkPasswordResult['registration_info']) && is_array($checkPasswordResult['registration_info'])) ? $checkPasswordResult['registration_info'] : array();
                            if (!empty($registrationInfo)) {
                                if (isset($registrationInfo['nickname']) && !empty($registrationInfo['nickname'])) {
                                    $formData->setField('uname', $registrationInfo['nickname']);
                                }
                                if (isset($registrationInfo['email']) && !empty($registrationInfo['email'])) {
                                    $formData->setField('email', $registrationInfo['email']);
                                }
                            }

                            $state = 'display_registration';
                        } else {
                            $this->registerError($this->__('The credentials you provided are already associated with an existing user account or registration request.'));
                            $state = 'display_method_selector';
                        }
                    } else {
                        if (!$this->request->getSession()->hasMessages(Zikula_Session::MESSAGE_ERROR)) {
                            $this->registerError($this->__('We were unable to confirm your credentials with the selected service.'));
                        }
                        $state = 'display_method_selector';
                    }
                    break;

                case 'validate':
                    // The user filled in and submitted the main registration form and it needs to be validated.
                    // Get the form data
                    $formData->getField('uname')->setData(mb_strtolower($formData->getField('uname')->getData()));
                    $formData->getField('email')->setData(mb_strtolower($formData->getField('email')->getData()));

                    // Set up the parameters for a call to Users_Api_Registration#getRegistrationErrors()
                    $antispamAnswer = $formData->getFieldData('antispamanswer');
                    $reginfo = $formData->toUserArray();
                    $arguments = array(
                        'checkmode'         => 'new',
                        'reginfo'           => $reginfo,
                        'passagain'         => $formData->getFieldData('passagain'),
                        'emailagain'        => $formData->getFieldData('emailagain'),
                        'antispamanswer'    => isset($antispamAnswer) ? $antispamAnswer : '',
                    );

                    if ($formData->isValid()) {
                        $errorFields = ModUtil::apiFunc($this->name, 'registration', 'getRegistrationErrors', $arguments);
                    } else {
                        $errorFields = $formData->getErrorMessages();
                    }

                    // Validate the hook-like event.
                    $event = new Zikula_Event('module.users.ui.validate_edit.new_registration', $reginfo, array(), new Zikula_Hook_ValidationProviders());
                    $validators = $this->eventManager->notify($event)->getData();

                    // Validate the hook
                    $hook = new Zikula_ValidationHook('users.ui_hooks.registration.validate_edit', $validators);
                    $this->notifyHooks($hook);
                    $validators = $hook->getValidators();

                    if (empty($errorFields) && !$validators->hasErrors()) {
                        // No errors, move on to registration.
                        $state = 'register';
                    } else {
                        // There were errors with the entries on the registration form. Redisplay it.
                        $state = 'display_registration';
                    }
                    break;

                case 'register':
                    // The registration validated, so do the actual registration.
                    $canLogIn = false;
                    $redirectUrl = '';

                    $registeredObj = ModUtil::apiFunc($this->name, 'registration', 'registerNewUser', array(
                        'reginfo'           => $reginfo,
                        'usernotification'  => true,
                        'adminnotification' => true
                    ));

                    if (isset($registeredObj) && $registeredObj) {
                        // The main registration completed successfully.
                        if ($selectedAuthenticationMethod['modname'] != $this->name) {
                            // The selected authentication module is NOT the Users module, so make sure the user is registered
                            // with the authentication module (associate the Users module record uid with the login information).
                            $arguments = array(
                                'authentication_method' => $selectedAuthenticationMethod,
                                'authentication_info'   => $authenticationInfo,
                                'uid'                   => $registeredObj['uid'],
                            );
                            $authenticationRegistered = ModUtil::apiFunc($selectedAuthenticationMethod['modname'], 'authentication', 'register', $arguments, 'Zikula_Api_AbstractAuthentication');
                            if (!$authenticationRegistered) {
                                $this->registerError($this->__('There was a problem associating your log-in information with your account. Please contact the site administrator.'));
                            }
                        } elseif ($this->getVar(Users_Constant::MODVAR_LOGIN_METHOD, Users_Constant::LOGIN_METHOD_UNAME) == Users_Constant::LOGIN_METHOD_EMAIL) {
                            // The authentication method IS the Users module, prepare for auto-login.
                            // The log-in user ID is the user's e-mail address.
                            $authenticationInfo = array(
                                'login_id' => $registeredObj['email'],
                                // Need the unhashed password here for auto-login
                                'pass'     => $reginfo['pass'],
                            );
                        } else {
                            // The authentication method IS the Users module, prepare for auto-login.
                            // The log-in user ID is the user's user name.
                            $authenticationInfo = array(
                                'login_id' => $registeredObj['uname'],
                                // Need the unhashed password here for auto-login
                                'pass'     => $reginfo['pass'],
                            );
                        }

                        // Allow hook-like events to process the registration...
                        $event = new Zikula_Event('module.users.ui.process_edit.new_registration', $registeredObj);
                        $this->eventManager->notify($event);

                        // ...and hooks to process the registration.
                        $hook = new Zikula_ProcessHook('users.ui_hooks.registration.process_edit', $registeredObj['uid']);
                        $this->notifyHooks($hook);

                        // If there were errors after the main registration, then make sure they can be displayed.
                        // TODO - Would this even happen?
                        if (!empty($registeredObj['regErrors'])) {
                            $this->view->assign('regErrors', $registeredObj['regErrors']);
                        }

                        // Register the appropriate status or error to be displayed to the user, depending on the account's
                        // activated status, whether registrations are moderated, whether e-mail addresses need to be verified,
                        // and other sundry conditions.
                        if ($registeredObj['activated'] == Users_Constant::ACTIVATED_PENDING_REG) {
                            // The account is saved and is pending either moderator approval, e-mail verification, or both.
                            $moderation = $this->getVar(Users_Constant::MODVAR_REGISTRATION_APPROVAL_REQUIRED, Users_Constant::DEFAULT_REGISTRATION_APPROVAL_REQUIRED);
                            $moderationOrder = $this->getVar(Users_Constant::MODVAR_REGISTRATION_APPROVAL_SEQUENCE, Users_Constant::DEFAULT_REGISTRATION_APPROVAL_SEQUENCE);
                            $verifyEmail = $this->getVar(Users_Constant::MODVAR_REGISTRATION_VERIFICATION_MODE, Users_Constant::DEFAULT_REGISTRATION_VERIFICATION_MODE);

                            if (!empty($registeredObj['regErrors'])) {
                                // There were errors. This message takes precedence.
                                $this->registerError($this->__('Your registration request has been saved, however the problems listed below were detected during the registration process. Please contact the site administrator regarding the status of your request.'));
                            } elseif ($moderation && ($verifyEmail != Users_Constant::VERIFY_NO)) {
                                // Pending both moderator approval, and e-mail verification. Set the appropriate message
                                // based on the order of approval/verification set.
                                if ($moderationOrder == Users_Constant::APPROVAL_AFTER) {
                                    // Verification then approval.
                                    $this->registerStatus($this->__('Done! Your registration request has been saved. Remember that your e-mail address must be verified and your request must be approved before you will be able to log in. Please check your e-mail for an e-mail address verification message. Your account will not be approved until after the verification process is completed.'));
                                } elseif ($moderationOrder == Users_Constant::APPROVAL_BEFORE) {
                                    // Approval then verification.
                                    $this->registerStatus($this->__('Done! Your registration request has been saved. Remember that your request must be approved and your e-mail address must be verified before you will be able to log in. Please check your e-mail periodically for a message from us. You will receive a message after we have reviewed your request.'));
                                } else {
                                    // Approval and verification in any order.
                                    $this->registerStatus($this->__('Done! Your registration request has been saved. Remember that your e-mail address must be verified and your request must be approved before you will be able to log in. Please check your e-mail for an e-mail address verification message.'));
                                }
                            } elseif ($moderation) {
                                // Pending moderator approval only.
                                $this->registerStatus($this->__('Done! Your registration request has been saved. Remember that your request must be approved before you will be able to log in. Please check your e-mail periodically for a message from us. You will receive a message after we have reviewed your request.'));
                            } elseif ($verifyEmail != Users_Constant::VERIFY_NO) {
                                // Pending e-mail address verification only.
                                $this->registerStatus($this->__('Done! Your registration request has been saved. Remember that your e-mail address must be verified before you will be able to log in. Please check your e-mail for an e-mail address verification message.'));
                            } else {
                                // Some unknown state! Should never get here, but just in case...
                                $this->registerError($this->__('Your registration request has been saved, however your current registration status could not be determined. Please contact the site administrator regarding the status of your request.'));
                            }
                        } elseif ($registeredObj['activated'] == Users_Constant::ACTIVATED_ACTIVE) {
                            // The account is saved, and is active (no moderator approval, no e-mail verification, and the user can log in now).
                            if (!empty($registeredObj['regErrors'])) {
                                // Errors. This message takes precedence.
                                $this->registerError($this->__('Your account has been created and you may now log in, however the problems listed below were detected during the registration process. Please contact the site administrator for more information.'));
                            } elseif ($this->getVar(Users_Constant::MODVAR_REGISTRATION_AUTO_LOGIN, Users_Constant::DEFAULT_REGISTRATION_AUTO_LOGIN)) {
                                // No errors and auto-login is turned on. A simple post-log-in message.
                                $this->registerStatus($this->__('Done! Your account has been created.'));
                            } else {
                                // No errors, and no auto-login. A simple message telling the user he may log in.
                                $this->registerStatus($this->__('Done! Your account has been created and you may now log in.'));
                            }
                            $canLogIn = true;
                        } else {
                            // Shouldn't really get here out of the registration process, but cover all the bases.
                            $this->registerError($this->__('Your registration request has been saved, however the problems listed below were detected during the registration process. Please contact the site administrator regarding the status of your request.'));
                            $registeredObj['regErrors'] = $this->__('Your account status will not permit you to log in at this time. Please contact the site administrator for more information.');
                        }

                        // Notify that we are completing a registration session.
                        $arguments = array(
                            'redirecturl' => $redirectUrl,
                        );
                        $event = new Zikula_Event('module.users.ui.registration.succeeded', $registeredObj, $arguments);
                        $event = $this->eventManager->notify($event);
                        $redirectUrl = $event->hasArg('redirecturl') ? $event->getArg('redirecturl') : $redirectUrl;

                        // Set up the next state to follow this one, along with any data needed.
                        if ($canLogIn && $this->getVar(Users_Constant::MODVAR_REGISTRATION_AUTO_LOGIN, Users_Constant::DEFAULT_REGISTRATION_AUTO_LOGIN)) {
                            // Next is auto-login. Make sure redirectUrl has a value so we know where to send the user.
                            if (empty($redirectUrl)) {
                                $redirectUrl = System::getHomepageUrl();
                            }
                            $state = 'auto_login';
                        } elseif (!empty($redirectUrl)) {
                            // No auto-login, but a redirect URL, so send the user there next.
                            $state = 'redirect';
                        } elseif (!$registeredObj || !empty($registeredObj['regErrors']) || !$canLogIn) {
                            // Either some sort of error, or the user cannot yet log in. Send him to a page to display
                            // the current status message or error message.
                            $state = 'display_status';
                        } else {
                            // No auto-login, no redirect URL, no errors, and the user can log in at this point.
                            // Send him to the login screen.
                            $redirectUrl = ModUtil::url($this->name, 'user', 'login');
                            $state = 'redirect';
                        }
                    } else {
                        // The main registration process failed.
                        $this->registerError($this->__('Error! Could not create the new user account or registration application. Please check with a site administrator before re-registering.'));

                        // Notify that we are completing a registration session.
                        $arguments = array(
                            'redirecturl' => $redirectUrl,
                        );
                        $event = new Zikula_Event('module.users.ui.registration.failed', null, $arguments);
                        $event = $this->eventManager->notify($event);
                        $redirectUrl = $event->hasArg('redirecturl') ? $event->getArg('redirecturl') : $redirectUrl;

                        // Set the next state to folllow this one.
                        if (!empty($redirectUrl)) {
                            // A redirect URL, so send the user there.
                            $state = 'redirect';
                        } else {
                            // No redirect, so send the user to a page to show the current error message.
                            $state = 'display_status';
                        }
                    }
                    break;

                case 'display_status':
                    // At the end of the registration process with no where else to go.
                    // Show the user the current status message(s) or error message(s).
                    $state = 'stop';

                    return $this->view->fetch('users_user_displaystatusmsg.tpl');
                    break;

                case 'redirect':
                    // At the end of the registration process with a redirect URL. Send the user there.
                    $state = 'stop';
                    $this->redirect($redirectUrl);
                    break;

                case 'auto_login':
                    // At the end of the registration process that was successful with the user in a state where
                    // he can log in, and auto-login enabled. Log the user in, sending him to the page specified.
                    $state = 'stop';
                    $arguments = array(
                        'authentication_method' => $selectedAuthenticationMethod,
                        'authentication_info'   => $authenticationInfo,
                        'rememberme'            => false,
                        'returnpage'            => $redirectUrl,
                    );

                    return ModUtil::func($this->name, 'user', 'login', $arguments);
                    break;

                default:
                    // An unknown processing state.
                    $state = 'stop';
                    break;
            }
        }

        // If we got here then we exited the above state machine with a 'stop', but there was no return statement
        // in the terminal state. We don't know what to do.
        throw new Zikula_Exception_Fatal($this->__('The registration process has entered an unknown state.'));
    }