diff --git a/asset-bundles.json b/asset-bundles.json index bf94419..012655d 100644 --- a/asset-bundles.json +++ b/asset-bundles.json @@ -44,6 +44,13 @@ "onCollision": "merge" } } + }, + "js/pages/register": { + "scripts": [ + "vendor/speakingurl/speakingurl.min.js", + "userfrosting/js/uf-captcha.js", + "uf-tweaks/js/pages/register.js" + ] } } } diff --git a/assets/uf-tweaks/js/pages/register.js b/assets/uf-tweaks/js/pages/register.js new file mode 100644 index 0000000..af0cb7f --- /dev/null +++ b/assets/uf-tweaks/js/pages/register.js @@ -0,0 +1,96 @@ +/** + * Page-specific Javascript file. Should generally be included as a separate asset bundle in your page template. + * example: {{ assets.js('js/pages/sign-in-or-register') | raw }} + * + * This script depends on validation rules specified in pages/partials/page.js.twig. + * + * Target page: account/register + */ +$(document).ready(function() { + // TOS modal + $(this).find('.js-show-tos').click(function(e) { + e.preventDefault(); + + $("body").ufModal({ + sourceUrl: site.uri.public + "/modals/account/tos", + msgTarget: $("#alerts-page") + }); + }); + + // Auto-generate username when name is filled in + var autoGenerate = true; + $("#register").find('input[name=first_name], input[name=last_name]').on('input change', function() { + if (!autoGenerate) { + return; + } + + var form = $("#register"); + + var firstName = form.find('input[name=first_name]').val().trim(); + var lastName = form.find('input[name=last_name]').val().trim(); + + if (!firstName && !lastName) { + return; + } + + var userName = getSlug(firstName + ' ' + lastName, { + separator: '.' + }); + // Set slug + form.find('input[name=user_name]').val(userName); + }); + + // Autovalidate username field on a delay + var timer; + $("#register").find('input[name=first_name], input[name=last_name], input[name=user_name]').on('input change', function() { + clearTimeout(timer); // Clear the timer so we don't end up with dupes. + timer = setTimeout(function() { // assign timer a new timeout + $("#register").find('input[name=user_name]').valid(); + }, 500); + }); + + // Enable/disable username suggestions in registration page + $("#register").find('#input-register-username-suggest').on('click', function(e) { + e.preventDefault(); + var form = $("#register"); + $.getJSON(site.uri.public + '/account/suggest-username') + .done(function (data) { + // Set suggestion + form.find('input[name=user_name]').val(data.user_name); + }); + }); + + // Turn off autogenerate when someone enters stuff manually in user_name + $("#register").find('input[name=user_name]').on('input', function() { + autoGenerate = false; + }); + + // Add remote rule for checking usernames on the fly + var registrationValidators = $.extend( + true, // deep extend + page.validators.register, + { + rules: { + user_name: { + remote: { + url: site.uri.public + '/account/check-username', + dataType: 'text' + } + } + } + } + ); + + // Handles form submission + $("#register").ufForm({ + validator: registrationValidators, + msgTarget: $("#alerts-page"), + keyupDelay: 500 + }).on("submitSuccess.ufForm", function() { + // Reload to clear form and show alerts + window.location.reload(); + }).on("submitError.ufForm", function() { + // Reload captcha + $("#captcha").captcha(); + }); +}); diff --git a/src/Controller/AccountController.php b/src/Controller/AccountController.php index 23330a1..7c8f574 100644 --- a/src/Controller/AccountController.php +++ b/src/Controller/AccountController.php @@ -108,4 +108,80 @@ class AccountController extends UFAccountController ], ]); } + + /** + * Render the account registration page for UserFrosting. + * + * This allows new (non-authenticated) users to create a new account for themselves on your website (if enabled). + * By definition, this is a "public page" (does not require authentication). + * + * AuthGuard: false + * checkEnvironment + * Route: /account/register + * Route Name: register + * Request type: GET + * + * @param Request $request + * @param Response $response + * @param array $args + * + * @throws NotFoundException If site registration is disabled + */ + public function pageRegister(Request $request, Response $response, $args) + { + /** @var \UserFrosting\Support\Repository\Repository $config */ + $config = $this->ci->config; + + if (!$config['site.registration.enabled']) { + throw new NotFoundException(); + } + + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + $authenticator = $this->ci->authenticator; + + // Redirect if user is already logged in + if ($authenticator->check()) { + $redirect = $this->ci->get('redirect.onAlreadyLoggedIn'); + + return $redirect($request, $response, $args); + } + + // Load validation rules + $schema = new RequestSchema('schema://requests/register.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); + $schema->set('passwordc.validators.length.min', $config['site.password.length.min']); + $schema->set('passwordc.validators.length.max', $config['site.password.length.max']); + $validatorRegister = new JqueryValidationAdapter($schema, $this->ci->translator); + + // Get locale information + $currentLocale = $this->ci->translator->getLocale()->getIdentifier(); + + // Get a list of all locales + $locales = $this->ci->locale->getAvailableOptions(); + + // Hide the locale field if there is only 1 locale available + $fields = [ + 'hidden' => [], + 'disabled' => [], + ]; + if (count($locales) <= 1) { + $fields['hidden'][] = 'locale'; + } + + return $this->ci->view->render($response, 'pages/register.html.twig', [ + 'page' => [ + 'validators' => [ + 'register' => $validatorRegister->rules('json', false), + ], + ], + 'form' => [ + 'fields' => $fields, + ], + 'locales' => [ + 'available' => $locales, + 'current' => $currentLocale, + ], + ]); + } } diff --git a/templates/forms/inputs/register-captcha.html.twig b/templates/forms/inputs/register-captcha.html.twig new file mode 100644 index 0000000..9d8cab5 --- /dev/null +++ b/templates/forms/inputs/register-captcha.html.twig @@ -0,0 +1,17 @@ +{% block input_user_locale %} +{% if site.registration.captcha %} + {% if col_width %}
{{translate("LOCALE.ACCOUNT")}}.
+{{translate('REGISTER')}}
+ + {% include "forms/register.html.twig" %} +