314 lines
12 KiB
PHP
314 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* @defgroup user_form User Forms
|
|
*/
|
|
|
|
/**
|
|
* @file classes/user/form/RegistrationForm.php
|
|
*
|
|
* Copyright (c) 2014-2021 Simon Fraser University
|
|
* Copyright (c) 2003-2021 John Willinsky
|
|
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
|
*
|
|
* @class RegistrationForm
|
|
*
|
|
* @ingroup user_form
|
|
*
|
|
* @brief Form for user registration.
|
|
*/
|
|
|
|
namespace PKP\user\form;
|
|
|
|
use APP\core\Application;
|
|
use APP\facades\Repo;
|
|
use APP\notification\form\NotificationSettingsForm;
|
|
use APP\template\TemplateManager;
|
|
use PKP\config\Config;
|
|
use PKP\core\Core;
|
|
use PKP\db\DAORegistry;
|
|
use PKP\facades\Locale;
|
|
use PKP\form\Form;
|
|
use PKP\security\Role;
|
|
use PKP\security\Validation;
|
|
use PKP\session\SessionManager;
|
|
use PKP\site\Site;
|
|
use PKP\user\InterestManager;
|
|
use PKP\user\User;
|
|
|
|
class RegistrationForm extends Form
|
|
{
|
|
/** @var User The user object being created (available to hooks during registrationform::execute hook) */
|
|
public $user;
|
|
|
|
/** @var bool user is already registered with another context */
|
|
public $existingUser;
|
|
|
|
/** @var bool whether or not captcha is enabled for this form */
|
|
public $captchaEnabled;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param Site $site
|
|
*/
|
|
public function __construct($site)
|
|
{
|
|
parent::__construct('frontend/pages/userRegister.tpl');
|
|
|
|
// Validation checks for this form
|
|
$form = $this;
|
|
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'username', 'required', 'user.register.form.usernameExists', [Repo::user(), 'getByUsername'], [true], true));
|
|
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'username', 'required', 'user.profile.form.usernameRequired'));
|
|
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'password', 'required', 'user.profile.form.passwordRequired'));
|
|
$this->addCheck(new \PKP\form\validation\FormValidatorUsername($this, 'username', 'required', 'user.register.form.usernameAlphaNumeric'));
|
|
$this->addCheck(new \PKP\form\validation\FormValidatorLength($this, 'password', 'required', 'user.register.form.passwordLengthRestriction', '>=', $site->getMinPasswordLength()));
|
|
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'password', 'required', 'user.register.form.passwordsDoNotMatch', fn ($password) => $password == $form->getData('password2')));
|
|
|
|
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'givenName', 'required', 'user.profile.form.givenNameRequired'));
|
|
|
|
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'country', 'required', 'user.profile.form.countryRequired'));
|
|
|
|
// Email checks
|
|
$this->addCheck(new \PKP\form\validation\FormValidatorEmail($this, 'email', 'required', 'user.profile.form.emailRequired'));
|
|
$this->addCheck(new \PKP\form\validation\FormValidatorCustom($this, 'email', 'required', 'user.register.form.emailExists', [Repo::user(), 'getByEmail'], [true], true));
|
|
|
|
$this->captchaEnabled = Config::getVar('captcha', 'captcha_on_register') && Config::getVar('captcha', 'recaptcha');
|
|
if ($this->captchaEnabled) {
|
|
$request = Application::get()->getRequest();
|
|
$this->addCheck(new \PKP\form\validation\FormValidatorReCaptcha($this, $request->getRemoteAddr(), 'common.captcha.error.invalid-input-response', $request->getServerHost()));
|
|
}
|
|
|
|
$context = Application::get()->getRequest()->getContext();
|
|
if ($context && $context->getData('privacyStatement')) {
|
|
$this->addCheck(new \PKP\form\validation\FormValidator($this, 'privacyConsent', 'required', 'user.profile.form.privacyConsentRequired'));
|
|
}
|
|
|
|
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
|
|
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
|
|
}
|
|
|
|
/**
|
|
* @copydoc Form::fetch()
|
|
*
|
|
* @param null|mixed $template
|
|
*/
|
|
public function fetch($request, $template = null, $display = false)
|
|
{
|
|
$templateMgr = TemplateManager::getManager($request);
|
|
$site = $request->getSite();
|
|
|
|
if ($this->captchaEnabled) {
|
|
$templateMgr->assign('recaptchaPublicKey', Config::getVar('captcha', 'recaptcha_public_key'));
|
|
}
|
|
|
|
$countries = [];
|
|
foreach (Locale::getCountries() as $country) {
|
|
$countries[$country->getAlpha2()] = $country->getLocalName();
|
|
}
|
|
asort($countries);
|
|
$templateMgr->assign('countries', $countries);
|
|
|
|
$userFormHelper = new UserFormHelper();
|
|
$userFormHelper->assignRoleContent($templateMgr, $request);
|
|
|
|
$templateMgr->assign([
|
|
'source' => $request->getUserVar('source'),
|
|
'minPasswordLength' => $site->getMinPasswordLength(),
|
|
'enableSiteWidePrivacyStatement' => Config::getVar('general', 'sitewide_privacy_statement'),
|
|
'siteWidePrivacyStatement' => $site->getData('privacyStatement'),
|
|
]);
|
|
|
|
return parent::fetch($request, $template, $display);
|
|
}
|
|
|
|
/**
|
|
* @copydoc Form::initData()
|
|
*/
|
|
public function initData()
|
|
{
|
|
$this->_data = [
|
|
'locales' => [],
|
|
'userGroupIds' => [],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Assign form data to user-submitted data.
|
|
*/
|
|
public function readInputData()
|
|
{
|
|
parent::readInputData();
|
|
|
|
$this->readUserVars([
|
|
'username',
|
|
'password',
|
|
'password2',
|
|
'givenName',
|
|
'familyName',
|
|
'affiliation',
|
|
'email',
|
|
'country',
|
|
'interests',
|
|
'emailConsent',
|
|
'privacyConsent',
|
|
'readerGroup',
|
|
'reviewerGroup',
|
|
]);
|
|
|
|
if ($this->captchaEnabled) {
|
|
$this->readUserVars([
|
|
'g-recaptcha-response',
|
|
]);
|
|
}
|
|
|
|
// Collect the specified user group IDs into a single piece of data
|
|
$this->setData('userGroupIds', array_merge(
|
|
array_keys((array) $this->getData('readerGroup')),
|
|
array_keys((array) $this->getData('reviewerGroup'))
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @copydoc Form::validate()
|
|
*/
|
|
public function validate($callHooks = true)
|
|
{
|
|
$request = Application::get()->getRequest();
|
|
|
|
// Ensure the consent checkbox has been completed for the site and any user
|
|
// group sign-ups if we're in the site-wide registration form
|
|
if (!$request->getContext()) {
|
|
if ($request->getSite()->getData('privacyStatement')) {
|
|
$privacyConsent = $this->getData('privacyConsent');
|
|
if (!is_array($privacyConsent) || !array_key_exists(Application::CONTEXT_ID_NONE, $privacyConsent)) {
|
|
$this->addError('privacyConsent[' . Application::CONTEXT_ID_NONE . ']', __('user.register.form.missingSiteConsent'));
|
|
}
|
|
}
|
|
|
|
if (!Config::getVar('general', 'sitewide_privacy_statement')) {
|
|
$contextIds = [];
|
|
foreach ($this->getData('userGroupIds') as $userGroupId) {
|
|
$userGroup = Repo::userGroup()->get($userGroupId);
|
|
$contextIds[] = $userGroup->getContextId();
|
|
}
|
|
|
|
$contextIds = array_unique($contextIds);
|
|
if (!empty($contextIds)) {
|
|
$contextDao = Application::getContextDao();
|
|
$privacyConsent = (array) $this->getData('privacyConsent');
|
|
foreach ($contextIds as $contextId) {
|
|
$context = $contextDao->getById($contextId);
|
|
if ($context->getData('privacyStatement') && !array_key_exists($contextId, $privacyConsent)) {
|
|
$this->addError('privacyConsent[' . $contextId . ']', __('user.register.form.missingContextConsent'));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return parent::validate($callHooks);
|
|
}
|
|
|
|
/**
|
|
* Register a new user.
|
|
*
|
|
* @return int|null User ID, or false on failure
|
|
*/
|
|
public function execute(...$functionArgs)
|
|
{
|
|
$requireValidation = Config::getVar('email', 'require_validation');
|
|
|
|
// New user
|
|
$this->user = $user = Repo::user()->newDataObject();
|
|
|
|
$user->setUsername($this->getData('username'));
|
|
|
|
// The multilingual user data (givenName, familyName and affiliation) will be saved
|
|
// in the current UI locale and copied in the site's primary locale too
|
|
$request = Application::get()->getRequest();
|
|
$site = $request->getSite();
|
|
$sitePrimaryLocale = $site->getPrimaryLocale();
|
|
$currentLocale = Locale::getLocale();
|
|
|
|
// Set the base user fields (name, etc.)
|
|
$user->setGivenName($this->getData('givenName'), $currentLocale);
|
|
$user->setFamilyName($this->getData('familyName'), $currentLocale);
|
|
$user->setEmail($this->getData('email'));
|
|
$user->setCountry($this->getData('country'));
|
|
$user->setAffiliation($this->getData('affiliation'), $currentLocale);
|
|
|
|
if ($sitePrimaryLocale != $currentLocale) {
|
|
$user->setGivenName($this->getData('givenName'), $sitePrimaryLocale);
|
|
$user->setFamilyName($this->getData('familyName'), $sitePrimaryLocale);
|
|
$user->setAffiliation($this->getData('affiliation'), $sitePrimaryLocale);
|
|
}
|
|
|
|
$user->setDateRegistered(Core::getCurrentDate());
|
|
$user->setInlineHelp(1); // default new users to having inline help visible.
|
|
$user->setPassword(Validation::encryptCredentials($this->getData('username'), $this->getData('password')));
|
|
|
|
if ($requireValidation) {
|
|
// The account should be created in a disabled
|
|
// state.
|
|
$user->setDisabled(true);
|
|
$user->setDisabledReason(__('user.login.accountNotValidated', ['email' => $this->getData('email')]));
|
|
}
|
|
|
|
parent::execute(...$functionArgs);
|
|
|
|
Repo::user()->add($user);
|
|
$userId = $user->getId();
|
|
if (!$userId) {
|
|
return false;
|
|
}
|
|
|
|
// Associate the new user with the existing session
|
|
$sessionManager = SessionManager::getManager();
|
|
$session = $sessionManager->getUserSession();
|
|
$session->setSessionVar('username', $user->getUsername());
|
|
|
|
// Save the selected roles or assign the Reader role if none selected
|
|
if ($request->getContext() && !$this->getData('reviewerGroup')) {
|
|
$defaultReaderGroup = Repo::userGroup()->getByRoleIds([Role::ROLE_ID_READER], $request->getContext()->getId(), true)->first();
|
|
if ($defaultReaderGroup) {
|
|
Repo::userGroup()->assignUserToGroup($user->getId(), $defaultReaderGroup->getId(), $request->getContext()->getId());
|
|
}
|
|
} else {
|
|
$userFormHelper = new UserFormHelper();
|
|
$userFormHelper->saveRoleContent($this, $user);
|
|
}
|
|
|
|
// Save the email notification preference
|
|
if ($request->getContext() && !$this->getData('emailConsent')) {
|
|
// Get the public notification types
|
|
$notificationSettingsForm = new NotificationSettingsForm();
|
|
$notificationCategories = $notificationSettingsForm->getNotificationSettingCategories($request->getContext());
|
|
foreach ($notificationCategories as $notificationCategory) {
|
|
if ($notificationCategory['categoryKey'] === 'notification.type.public') {
|
|
$publicNotifications = $notificationCategory['settings'];
|
|
}
|
|
}
|
|
if (isset($publicNotifications)) {
|
|
$notificationSubscriptionSettingsDao = DAORegistry::getDAO('NotificationSubscriptionSettingsDAO'); /** @var NotificationSubscriptionSettingsDAO $notificationSubscriptionSettingsDao */
|
|
$notificationSubscriptionSettingsDao->updateNotificationSubscriptionSettings(
|
|
'blocked_emailed_notification',
|
|
$publicNotifications,
|
|
$user->getId(),
|
|
$request->getContext()->getId()
|
|
);
|
|
}
|
|
}
|
|
|
|
// Insert the user interests
|
|
$interestManager = new InterestManager();
|
|
$interestManager->setInterestsForUser($user, $this->getData('interests'));
|
|
|
|
return $userId;
|
|
}
|
|
}
|
|
|
|
if (!PKP_STRICT_MODE) {
|
|
class_alias('\PKP\user\form\RegistrationForm', '\RegistrationForm');
|
|
}
|